mob.c 116 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343
  1. // $Id: mob.c,v 1.7 2004/09/25 05:32:18 MouseJstr Exp $
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdarg.h>
  5. #include <string.h>
  6. #include "timer.h"
  7. #include "socket.h"
  8. #include "db.h"
  9. #include "nullpo.h"
  10. #include "malloc.h"
  11. #include "map.h"
  12. #include "clif.h"
  13. #include "intif.h"
  14. #include "pc.h"
  15. #include "mob.h"
  16. #include "guild.h"
  17. #include "itemdb.h"
  18. #include "skill.h"
  19. #include "battle.h"
  20. #include "party.h"
  21. #include "npc.h"
  22. #include "log.h"
  23. #ifdef MEMWATCH
  24. #include "memwatch.h"
  25. #endif
  26. #define MIN_MOBTHINKTIME 100
  27. #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute)
  28. #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute)
  29. struct mob_db mob_db[2001];
  30. /*==========================================
  31. * Local prototype declaration (only required thing)
  32. *------------------------------------------
  33. */
  34. static int distance(int,int,int,int);
  35. static int mob_makedummymobdb(int);
  36. static int mob_timer(int,unsigned int,int,int);
  37. int mobskill_use(struct mob_data *md,unsigned int tick,int event);
  38. int mobskill_deltimer(struct mob_data *md );
  39. int mob_skillid2skillidx(int class,int skillid);
  40. int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx);
  41. static int mob_unlocktarget(struct mob_data *md,int tick);
  42. /*==========================================
  43. * Mob is searched with a name.
  44. *------------------------------------------
  45. */
  46. int mobdb_searchname(const char *str)
  47. {
  48. int i;
  49. for(i=0;i<sizeof(mob_db)/sizeof(mob_db[0]);i++){
  50. if( strcmpi(mob_db[i].name,str)==0 || strcmp(mob_db[i].jname,str)==0 ||
  51. memcmp(mob_db[i].name,str,24)==0 || memcmp(mob_db[i].jname,str,24)==0)
  52. return i;
  53. }
  54. return 0;
  55. }
  56. /*==========================================
  57. * Id Mob is checked.
  58. *------------------------------------------
  59. */
  60. int mobdb_checkid(const int id)
  61. {
  62. if (id <= 0 || id >= (sizeof(mob_db) / sizeof(mob_db[0])) || mob_db[id].name[0] == '\0')
  63. return 0;
  64. return id;
  65. }
  66. /*==========================================
  67. * The minimum data set for MOB spawning
  68. *------------------------------------------
  69. */
  70. int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
  71. {
  72. nullpo_retr(0, md);
  73. md->bl.prev=NULL;
  74. md->bl.next=NULL;
  75. if(strcmp(mobname,"--en--")==0)
  76. memcpy(md->name,mob_db[class].name,24);
  77. else if(strcmp(mobname,"--ja--")==0)
  78. memcpy(md->name,mob_db[class].jname,24);
  79. else
  80. memcpy(md->name,mobname,24);
  81. md->n = 0;
  82. md->base_class = md->class = class;
  83. md->bl.id= npc_get_new_npc_id();
  84. memset(&md->state,0,sizeof(md->state));
  85. md->timer = -1;
  86. md->target_id=0;
  87. md->attacked_id=0;
  88. md->speed=mob_db[class].speed;
  89. return 0;
  90. }
  91. /*==========================================
  92. * The MOB appearance for one time (for scripts)
  93. *------------------------------------------
  94. */
  95. int mob_once_spawn(struct map_session_data *sd,char *mapname,
  96. int x,int y,const char *mobname,int class,int amount,const char *event)
  97. {
  98. struct mob_data *md=NULL;
  99. int m,count,lv=255,r=class;
  100. if( sd )
  101. lv=sd->status.base_level;
  102. if( sd && strcmp(mapname,"this")==0)
  103. m=sd->bl.m;
  104. else
  105. m=map_mapname2mapid(mapname);
  106. if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // 値が異常なら召喚を止める
  107. return 0;
  108. if(class<0){ // ランダムに召喚
  109. int i=0;
  110. int j=-class-1;
  111. int k;
  112. if(j>=0 && j<MAX_RANDOMMONSTER){
  113. do{
  114. class=rand()%1000+1001;
  115. k=rand()%1000000;
  116. }while((mob_db[class].max_hp <= 0 || mob_db[class].summonper[j] <= k ||
  117. (lv<mob_db[class].lv && battle_config.random_monster_checklv)) && (i++) < 2000);
  118. if(i>=2000){
  119. class=mob_db[0].summonper[j];
  120. }
  121. }else{
  122. return 0;
  123. }
  124. // if(battle_config.etc_log)
  125. // printf("mobclass=%d try=%d\n",class,i);
  126. }
  127. if(sd){
  128. if(x<=0) x=sd->bl.x;
  129. if(y<=0) y=sd->bl.y;
  130. }else if(x<=0 || y<=0){
  131. printf("mob_once_spawn: ??\n");
  132. }
  133. for(count=0;count<amount;count++){
  134. md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
  135. memset(md, '\0', sizeof *md);
  136. if(class>4000) { // large/tiny mobs [Valaris]
  137. md->size=2;
  138. class-=4000;
  139. }
  140. else if(class>2000) {
  141. md->size=1;
  142. class-=2000;
  143. }
  144. if(mob_db[class].mode&0x02)
  145. md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  146. else
  147. md->lootitem=NULL;
  148. mob_spawn_dataset(md,mobname,class);
  149. md->bl.m=m;
  150. md->bl.x=x;
  151. md->bl.y=y;
  152. if(r<0&&battle_config.dead_branch_active) md->mode=0x1+0x4+0x80; //移動してアクティブで反撃する
  153. md->m =m;
  154. md->x0=x;
  155. md->y0=y;
  156. md->xs=0;
  157. md->ys=0;
  158. md->spawndelay1=-1; // 一度のみフラグ
  159. md->spawndelay2=-1; // 一度のみフラグ
  160. memcpy(md->npc_event,event,sizeof(md->npc_event));
  161. md->bl.type=BL_MOB;
  162. map_addiddb(&md->bl);
  163. mob_spawn(md->bl.id);
  164. if(class==1288) { // emperium hp based on defense level [Valaris]
  165. struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
  166. if(gc) {
  167. mob_db[class].max_hp+=2000*gc->defense;
  168. md->hp=mob_db[class].max_hp;
  169. }
  170. } // end addition [Valaris]
  171. }
  172. return (amount>0)?md->bl.id:0;
  173. }
  174. /*==========================================
  175. * The MOB appearance for one time (& area specification for scripts)
  176. *------------------------------------------
  177. */
  178. int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
  179. int x0,int y0,int x1,int y1,
  180. const char *mobname,int class,int amount,const char *event)
  181. {
  182. int x,y,i,c,max,lx=-1,ly=-1,id=0;
  183. int m;
  184. if(strcmp(mapname,"this")==0)
  185. m=sd->bl.m;
  186. else
  187. m=map_mapname2mapid(mapname);
  188. max=(y1-y0+1)*(x1-x0+1)*3;
  189. if(max>1000)max=1000;
  190. if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // A summon is stopped if a value is unusual
  191. return 0;
  192. for(i=0;i<amount;i++){
  193. int j=0;
  194. do{
  195. x=rand()%(x1-x0+1)+x0;
  196. y=rand()%(y1-y0+1)+y0;
  197. }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
  198. if(j>=max){
  199. if(lx>=0){ // 検索に失敗したので以前に沸いた場所を使う
  200. x=lx;
  201. y=ly;
  202. }else
  203. return 0; // 最初に沸く場所の検索を失敗したのでやめる
  204. }
  205. id=mob_once_spawn(sd,mapname,x,y,mobname,class,1,event);
  206. lx=x;
  207. ly=y;
  208. }
  209. return id;
  210. }
  211. /*==========================================
  212. * Summoning Guardians [Valaris]
  213. *------------------------------------------
  214. */
  215. int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
  216. int x,int y,const char *mobname,int class,int amount,const char *event,int guardian)
  217. {
  218. struct mob_data *md=NULL;
  219. int m,count=1,lv=255;
  220. if( sd )
  221. lv=sd->status.base_level;
  222. if( sd && strcmp(mapname,"this")==0)
  223. m=sd->bl.m;
  224. else
  225. m=map_mapname2mapid(mapname);
  226. if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000) // 値が異常なら召喚を止める
  227. return 0;
  228. if(class<0)
  229. return 0;
  230. if(sd){
  231. if(x<=0) x=sd->bl.x;
  232. if(y<=0) y=sd->bl.y;
  233. }
  234. else if(x<=0 || y<=0)
  235. printf("mob_spawn_guardian: ??\n");
  236. for(count=0;count<amount;count++){
  237. struct guild_castle *gc;
  238. md=calloc(sizeof(struct mob_data), 1);
  239. if(md==NULL){
  240. printf("mob_spawn_guardian: out of memory !\n");
  241. exit(1);
  242. }
  243. memset(md, '\0', sizeof *md);
  244. mob_spawn_dataset(md,mobname,class);
  245. md->bl.m=m;
  246. md->bl.x=x;
  247. md->bl.y=y;
  248. md->m =m;
  249. md->x0=x;
  250. md->y0=y;
  251. md->xs=0;
  252. md->ys=0;
  253. md->spawndelay1=-1; // Only once is a flag.
  254. md->spawndelay2=-1; // Only once is a flag.
  255. memcpy(md->npc_event,event,sizeof(md->npc_event));
  256. md->bl.type=BL_MOB;
  257. map_addiddb(&md->bl);
  258. mob_spawn(md->bl.id);
  259. gc=guild_mapname2gc(map[md->bl.m].name);
  260. if(gc) {
  261. mob_db[class].max_hp+=2000*gc->defense;
  262. if(guardian==0) { md->hp=gc->Ghp0; gc->GID0=md->bl.id; }
  263. if(guardian==1) { md->hp=gc->Ghp1; gc->GID1=md->bl.id; }
  264. if(guardian==2) { md->hp=gc->Ghp2; gc->GID2=md->bl.id; }
  265. if(guardian==3) { md->hp=gc->Ghp3; gc->GID3=md->bl.id; }
  266. if(guardian==4) { md->hp=gc->Ghp4; gc->GID4=md->bl.id; }
  267. if(guardian==5) { md->hp=gc->Ghp5; gc->GID5=md->bl.id; }
  268. if(guardian==6) { md->hp=gc->Ghp6; gc->GID6=md->bl.id; }
  269. if(guardian==7) { md->hp=gc->Ghp7; gc->GID7=md->bl.id; }
  270. }
  271. }
  272. return (amount>0)?md->bl.id:0;
  273. }
  274. /*==========================================
  275. * The disregard ID is added to mob.
  276. *------------------------------------------
  277. */
  278. int mob_exclusion_add(struct mob_data *md,int type,int id)
  279. {
  280. nullpo_retr(0, md);
  281. if(type==1)
  282. md->exclusion_src=id;
  283. if(type==2)
  284. md->exclusion_party=id;
  285. if(type==3)
  286. md->exclusion_guild=id;
  287. return 0;
  288. }
  289. /*==========================================
  290. * The disregard ID of mob is checked. (TAGE?)
  291. *------------------------------------------
  292. */
  293. int mob_exclusion_check(struct mob_data *md,struct map_session_data *sd)
  294. {
  295. nullpo_retr(0, sd);
  296. nullpo_retr(0, md);
  297. if(sd->bl.type==BL_PC){
  298. if(md->exclusion_src && md->exclusion_src==sd->bl.id)
  299. return 1;
  300. if(md->exclusion_party && md->exclusion_party==sd->status.party_id)
  301. return 2;
  302. if(md->exclusion_guild && md->exclusion_guild==sd->status.guild_id)
  303. return 3;
  304. }
  305. return 0;
  306. }
  307. /*==========================================
  308. * Appearance income of mob
  309. *------------------------------------------
  310. */
  311. int mob_get_viewclass(int class)
  312. {
  313. return mob_db[class].view_class;
  314. }
  315. int mob_get_sex(int class)
  316. {
  317. return mob_db[class].sex;
  318. }
  319. short mob_get_hair(int class)
  320. {
  321. return mob_db[class].hair;
  322. }
  323. short mob_get_hair_color(int class)
  324. {
  325. return mob_db[class].hair_color;
  326. }
  327. short mob_get_weapon(int class)
  328. {
  329. return mob_db[class].weapon;
  330. }
  331. short mob_get_shield(int class)
  332. {
  333. return mob_db[class].shield;
  334. }
  335. short mob_get_head_top(int class)
  336. {
  337. return mob_db[class].head_top;
  338. }
  339. short mob_get_head_mid(int class)
  340. {
  341. return mob_db[class].head_mid;
  342. }
  343. short mob_get_head_buttom(int class)
  344. {
  345. return mob_db[class].head_buttom;
  346. }
  347. short mob_get_clothes_color(int class) // Add for player monster dye - Valaris
  348. {
  349. return mob_db[class].clothes_color; // End
  350. }
  351. int mob_get_equip(int class) // mob equip [Valaris]
  352. {
  353. return mob_db[class].equip;
  354. }
  355. /*==========================================
  356. * Is MOB in the state in which the present movement is possible or not?
  357. *------------------------------------------
  358. */
  359. int mob_can_move(struct mob_data *md)
  360. {
  361. nullpo_retr(0, md);
  362. if(md->canmove_tick > gettick() || (md->opt1 > 0 && md->opt1 != 6) || md->option&2)
  363. return 0;
  364. // アンクル中で動けないとか
  365. if( md->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
  366. md->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
  367. md->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
  368. md->sc_data[SC_SPIDERWEB].timer != -1 //スパイダーウェッブ
  369. )
  370. return 0;
  371. return 1;
  372. }
  373. /*==========================================
  374. * Time calculation concerning one step next to mob
  375. *------------------------------------------
  376. */
  377. static int calc_next_walk_step(struct mob_data *md)
  378. {
  379. nullpo_retr(0, md);
  380. if(md->walkpath.path_pos>=md->walkpath.path_len)
  381. return -1;
  382. if(md->walkpath.path[md->walkpath.path_pos]&1)
  383. return battle_get_speed(&md->bl)*14/10;
  384. return battle_get_speed(&md->bl);
  385. }
  386. static int mob_walktoxy_sub(struct mob_data *md);
  387. /*==========================================
  388. * Mob Walk processing
  389. *------------------------------------------
  390. */
  391. static int mob_walk(struct mob_data *md,unsigned int tick,int data)
  392. {
  393. int moveblock;
  394. int i,ctype;
  395. static int dirx[8]={0,-1,-1,-1,0,1,1,1};
  396. static int diry[8]={1,1,0,-1,-1,-1,0,1};
  397. int x,y,dx,dy;
  398. nullpo_retr(0, md);
  399. md->state.state=MS_IDLE;
  400. if(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_pos!=data)
  401. return 0;
  402. md->walkpath.path_half ^= 1;
  403. if(md->walkpath.path_half==0){
  404. md->walkpath.path_pos++;
  405. if(md->state.change_walk_target){
  406. mob_walktoxy_sub(md);
  407. return 0;
  408. }
  409. }
  410. else {
  411. if(md->walkpath.path[md->walkpath.path_pos]>=8)
  412. return 1;
  413. x = md->bl.x;
  414. y = md->bl.y;
  415. ctype = map_getcell(md->bl.m,x,y);
  416. if(ctype == 1 || ctype == 5) {
  417. mob_stop_walking(md,1);
  418. return 0;
  419. }
  420. md->dir=md->walkpath.path[md->walkpath.path_pos];
  421. dx = dirx[md->dir];
  422. dy = diry[md->dir];
  423. ctype = map_getcell(md->bl.m,x+dx,y+dy);
  424. if(ctype == 1 || ctype == 5) {
  425. mob_walktoxy_sub(md);
  426. return 0;
  427. }
  428. moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE);
  429. md->state.state=MS_WALK;
  430. map_foreachinmovearea(clif_moboutsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,md);
  431. x += dx;
  432. y += dy;
  433. if(md->min_chase>13)
  434. md->min_chase--;
  435. if(moveblock) map_delblock(&md->bl);
  436. md->bl.x = x;
  437. md->bl.y = y;
  438. if(moveblock) map_addblock(&md->bl);
  439. map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md);
  440. md->state.state=MS_IDLE;
  441. if(md->option&4)
  442. skill_check_cloaking(&md->bl);
  443. skill_unit_move(&md->bl,tick,1); // スキルユニットの検査
  444. }
  445. if((i=calc_next_walk_step(md))>0){
  446. i = i>>1;
  447. if(i < 1 && md->walkpath.path_half == 0)
  448. i = 1;
  449. md->timer=add_timer(tick+i,mob_timer,md->bl.id,md->walkpath.path_pos);
  450. md->state.state=MS_WALK;
  451. if(md->walkpath.path_pos>=md->walkpath.path_len)
  452. clif_fixmobpos(md); // とまったときに位置の再送信
  453. }
  454. return 0;
  455. }
  456. /*==========================================
  457. * Attack processing of mob
  458. *------------------------------------------
  459. */
  460. static int mob_attack(struct mob_data *md,unsigned int tick,int data)
  461. {
  462. struct block_list *tbl=NULL;
  463. struct map_session_data *tsd=NULL;
  464. struct mob_data *tmd=NULL;
  465. int mode,race,range;
  466. nullpo_retr(0, md);
  467. md->min_chase=13;
  468. md->state.state=MS_IDLE;
  469. md->state.skillstate=MSS_IDLE;
  470. if( md->skilltimer!=-1 ) // スキル使用中
  471. return 0;
  472. if(md->opt1>0 || md->option&2)
  473. return 0;
  474. if(md->sc_data[SC_AUTOCOUNTER].timer != -1)
  475. return 0;
  476. if(md->sc_data[SC_BLADESTOP].timer != -1)
  477. return 0;
  478. if((tbl=map_id2bl(md->target_id))==NULL){
  479. md->target_id=0;
  480. md->state.targettype = NONE_ATTACKABLE;
  481. return 0;
  482. }
  483. if(tbl->type==BL_PC)
  484. tsd=(struct map_session_data *)tbl;
  485. else if(tbl->type==BL_MOB)
  486. tmd=(struct mob_data *)tbl;
  487. else
  488. return 0;
  489. if(tsd){
  490. if( pc_isdead(tsd) || tsd->invincible_timer != -1 || pc_isinvisible(tsd) || md->bl.m != tbl->m || tbl->prev == NULL || distance(md->bl.x,md->bl.y,tbl->x,tbl->y)>=13 ){
  491. md->target_id=0;
  492. md->state.targettype = NONE_ATTACKABLE;
  493. return 0;
  494. }
  495. }
  496. if(tmd){
  497. if(md->bl.m != tbl->m || tbl->prev == NULL || distance(md->bl.x,md->bl.y,tbl->x,tbl->y)>=13){
  498. md->target_id=0;
  499. md->state.targettype = NONE_ATTACKABLE;
  500. return 0;
  501. }
  502. }
  503. if(!md->mode)
  504. mode=mob_db[md->class].mode;
  505. else
  506. mode=md->mode;
  507. race=mob_db[md->class].race;
  508. if(!(mode&0x80)){
  509. md->target_id=0;
  510. md->state.targettype = NONE_ATTACKABLE;
  511. return 0;
  512. }
  513. if(tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
  514. ((pc_ishiding(tsd) || tsd->state.gangsterparadise) && !((race == 4 || race == 6) && !tsd->perfect_hiding) ) ) ) {
  515. md->target_id=0;
  516. md->state.targettype = NONE_ATTACKABLE;
  517. return 0;
  518. }
  519. range = mob_db[md->class].range;
  520. if(mode&1)
  521. range++;
  522. if(distance(md->bl.x,md->bl.y,tbl->x,tbl->y) > range)
  523. return 0;
  524. if(battle_config.monster_attack_direction_change)
  525. md->dir=map_calc_dir(&md->bl, tbl->x,tbl->y ); // 向き設定
  526. //clif_fixmobpos(md);
  527. md->state.skillstate=MSS_ATTACK;
  528. if( mobskill_use(md,tick,-2) ) // スキル使用
  529. return 0;
  530. md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,0);
  531. if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
  532. skill_status_change_end(&md->bl,SC_CLOAKING,-1);
  533. md->attackabletime = tick + battle_get_adelay(&md->bl);
  534. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  535. md->state.state=MS_ATTACK;
  536. return 0;
  537. }
  538. /*==========================================
  539. * The attack of PC which is attacking id is stopped.
  540. * The callback function of clif_foreachclient
  541. *------------------------------------------
  542. */
  543. int mob_stopattacked(struct map_session_data *sd,va_list ap)
  544. {
  545. int id;
  546. nullpo_retr(0, sd);
  547. nullpo_retr(0, ap);
  548. id=va_arg(ap,int);
  549. if(sd->attacktarget==id)
  550. pc_stopattack(sd);
  551. return 0;
  552. }
  553. /*==========================================
  554. * The timer in which the mob's states changes
  555. *------------------------------------------
  556. */
  557. int mob_changestate(struct mob_data *md,int state,int type)
  558. {
  559. unsigned int tick;
  560. int i;
  561. nullpo_retr(0, md);
  562. if(md->timer != -1)
  563. delete_timer(md->timer,mob_timer);
  564. md->timer=-1;
  565. md->state.state=state;
  566. switch(state){
  567. case MS_WALK:
  568. if((i=calc_next_walk_step(md))>0){
  569. i = i>>2;
  570. md->timer=add_timer(gettick()+i,mob_timer,md->bl.id,0);
  571. }
  572. else
  573. md->state.state=MS_IDLE;
  574. break;
  575. case MS_ATTACK:
  576. tick = gettick();
  577. i=DIFF_TICK(md->attackabletime,tick);
  578. if(i>0 && i<2000)
  579. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  580. else if(type) {
  581. md->attackabletime = tick + battle_get_amotion(&md->bl);
  582. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  583. }
  584. else {
  585. md->attackabletime = tick + 1;
  586. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  587. }
  588. break;
  589. case MS_DELAY:
  590. md->timer=add_timer(gettick()+type,mob_timer,md->bl.id,0);
  591. break;
  592. case MS_DEAD:
  593. skill_castcancel(&md->bl,0);
  594. // mobskill_deltimer(md);
  595. md->state.skillstate=MSS_DEAD;
  596. md->last_deadtime=gettick();
  597. // Since it died, all aggressors' attack to this mob is stopped.
  598. clif_foreachclient(mob_stopattacked,md->bl.id);
  599. skill_unit_out_all(&md->bl,gettick(),1);
  600. skill_status_change_clear(&md->bl,2); // ステータス異常を解除する
  601. skill_clear_unitgroup(&md->bl); // 全てのスキルユニットグループを削除する
  602. skill_cleartimerskill(&md->bl);
  603. if(md->deletetimer!=-1)
  604. delete_timer(md->deletetimer,mob_timer_delete);
  605. md->deletetimer=-1;
  606. md->hp=md->target_id=md->attacked_id=0;
  607. md->state.targettype = NONE_ATTACKABLE;
  608. break;
  609. }
  610. return 0;
  611. }
  612. /*==========================================
  613. * timer processing of mob (timer function)
  614. * It branches to a walk and an attack.
  615. *------------------------------------------
  616. */
  617. static int mob_timer(int tid,unsigned int tick,int id,int data)
  618. {
  619. struct mob_data *md;
  620. struct block_list *bl;
  621. if( (bl=map_id2bl(id)) == NULL ){ //攻撃してきた敵がもういないのは正常のようだ
  622. return 1;
  623. }
  624. if(!bl || !bl->type || bl->type!=BL_MOB)
  625. return 1;
  626. nullpo_retr(1, md=(struct mob_data*)bl);
  627. if(!md->bl.type || md->bl.type!=BL_MOB)
  628. return 1;
  629. if(md->timer != tid){
  630. if(battle_config.error_log)
  631. printf("mob_timer %d != %d\n",md->timer,tid);
  632. return 0;
  633. }
  634. md->timer=-1;
  635. if(md->bl.prev == NULL || md->state.state == MS_DEAD)
  636. return 1;
  637. map_freeblock_lock();
  638. switch(md->state.state){
  639. case MS_WALK:
  640. mob_walk(md,tick,data);
  641. break;
  642. case MS_ATTACK:
  643. mob_attack(md,tick,data);
  644. break;
  645. case MS_DELAY:
  646. mob_changestate(md,MS_IDLE,0);
  647. break;
  648. default:
  649. if(battle_config.error_log)
  650. printf("mob_timer : %d ?\n",md->state.state);
  651. break;
  652. }
  653. map_freeblock_unlock();
  654. return 0;
  655. }
  656. /*==========================================
  657. *
  658. *------------------------------------------
  659. */
  660. static int mob_walktoxy_sub(struct mob_data *md)
  661. {
  662. struct walkpath_data wpd;
  663. nullpo_retr(0, md);
  664. if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy))
  665. return 1;
  666. memcpy(&md->walkpath,&wpd,sizeof(wpd));
  667. md->state.change_walk_target=0;
  668. mob_changestate(md,MS_WALK,0);
  669. clif_movemob(md);
  670. return 0;
  671. }
  672. /*==========================================
  673. * mob move start
  674. *------------------------------------------
  675. */
  676. int mob_walktoxy(struct mob_data *md,int x,int y,int easy)
  677. {
  678. struct walkpath_data wpd;
  679. nullpo_retr(0, md);
  680. if(md->state.state == MS_WALK && path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,x,y,easy) )
  681. return 1;
  682. md->state.walk_easy = easy;
  683. md->to_x=x;
  684. md->to_y=y;
  685. if(md->state.state == MS_WALK)
  686. md->state.change_walk_target=1;
  687. else
  688. return mob_walktoxy_sub(md);
  689. return 0;
  690. }
  691. /*==========================================
  692. * mob spawn with delay (timer function)
  693. *------------------------------------------
  694. */
  695. static int mob_delayspawn(int tid,unsigned int tick,int m,int n)
  696. {
  697. mob_spawn(m);
  698. return 0;
  699. }
  700. /*==========================================
  701. * spawn timing calculation
  702. *------------------------------------------
  703. */
  704. int mob_setdelayspawn(int id)
  705. {
  706. unsigned int spawntime,spawntime1,spawntime2,spawntime3;
  707. struct mob_data *md;
  708. struct block_list *bl;
  709. if((bl=map_id2bl(id)) == NULL)
  710. return -1;
  711. if(!bl || !bl->type || bl->type!=BL_MOB)
  712. return -1;
  713. nullpo_retr(-1, md=(struct mob_data*)bl);
  714. if(!md || md->bl.type!=BL_MOB)
  715. return -1;
  716. // Processing of MOB which is not revitalized
  717. if(md->spawndelay1==-1 && md->spawndelay2==-1 && md->n==0){
  718. map_deliddb(&md->bl);
  719. if(md->lootitem) {
  720. map_freeblock(md->lootitem);
  721. md->lootitem=NULL;
  722. }
  723. map_freeblock(md); // Instead of [ of free ]
  724. return 0;
  725. }
  726. spawntime1=md->last_spawntime+md->spawndelay1;
  727. spawntime2=md->last_deadtime+md->spawndelay2;
  728. spawntime3=gettick()+5000;
  729. // spawntime = max(spawntime1,spawntime2,spawntime3);
  730. if(DIFF_TICK(spawntime1,spawntime2)>0)
  731. spawntime=spawntime1;
  732. else
  733. spawntime=spawntime2;
  734. if(DIFF_TICK(spawntime3,spawntime)>0)
  735. spawntime=spawntime3;
  736. add_timer(spawntime,mob_delayspawn,id,0);
  737. return 0;
  738. }
  739. /*==========================================
  740. * Mob spawning. Initialization is also variously here.
  741. *------------------------------------------
  742. */
  743. int mob_spawn(int id)
  744. {
  745. int x=0,y=0,i=0,c;
  746. unsigned int tick = gettick();
  747. struct mob_data *md;
  748. struct block_list *bl;
  749. nullpo_retr(-1, bl=map_id2bl(id));
  750. if(!bl || !bl->type || bl->type!=BL_MOB)
  751. return -1;
  752. nullpo_retr(-1, md=(struct mob_data*)bl);
  753. if(!md || !md->bl.type || md->bl.type!=BL_MOB)
  754. return -1;
  755. md->last_spawntime=tick;
  756. if( md->bl.prev!=NULL ){
  757. // clif_clearchar_area(&md->bl,3);
  758. skill_unit_out_all(&md->bl,gettick(),1);
  759. map_delblock(&md->bl);
  760. }
  761. else
  762. md->class = md->base_class;
  763. md->bl.m =md->m;
  764. do {
  765. if(md->x0==0 && md->y0==0){
  766. x=rand()%(map[md->bl.m].xs-2)+1;
  767. y=rand()%(map[md->bl.m].ys-2)+1;
  768. } else {
  769. x=md->x0+rand()%(md->xs+1)-md->xs/2;
  770. y=md->y0+rand()%(md->ys+1)-md->ys/2;
  771. }
  772. i++;
  773. } while(((c=map_getcell(md->bl.m,x,y))==1 || c==5) && i<50);
  774. if(i>=50){
  775. // if(battle_config.error_log==1)
  776. // printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
  777. add_timer(tick+5000,mob_delayspawn,id,0);
  778. return 1;
  779. }
  780. md->to_x=md->bl.x=x;
  781. md->to_y=md->bl.y=y;
  782. md->dir=0;
  783. map_addblock(&md->bl);
  784. memset(&md->state,0,sizeof(md->state));
  785. md->attacked_id = 0;
  786. md->target_id = 0;
  787. md->move_fail_count = 0;
  788. if(!md->speed)
  789. md->speed = mob_db[md->class].speed;
  790. md->def_ele = mob_db[md->class].element;
  791. if(!md->level) // [Valaris]
  792. md->level=mob_db[md->class].lv;
  793. md->master_id=0;
  794. md->master_dist=0;
  795. md->state.state = MS_IDLE;
  796. md->state.skillstate = MSS_IDLE;
  797. md->timer = -1;
  798. md->last_thinktime = tick;
  799. md->next_walktime = tick+rand()%50+5000;
  800. md->attackabletime = tick;
  801. md->canmove_tick = tick;
  802. md->guild_id = 0;
  803. if (md->class >= 1285 && md->class <= 1288) {
  804. struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
  805. if(gc)
  806. md->guild_id = gc->guild_id;
  807. }
  808. md->sg_count=0;
  809. md->deletetimer=-1;
  810. md->skilltimer=-1;
  811. for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
  812. md->skilldelay[i] = c;
  813. md->skillid=0;
  814. md->skilllv=0;
  815. memset(md->dmglog,0,sizeof(md->dmglog));
  816. if(md->lootitem)
  817. memset(md->lootitem,0,sizeof(md->lootitem));
  818. md->lootitem_count = 0;
  819. for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++)
  820. md->skilltimerskill[i].timer = -1;
  821. for(i=0;i<MAX_STATUSCHANGE;i++) {
  822. md->sc_data[i].timer=-1;
  823. md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 = md->sc_data[i].val4 =0;
  824. }
  825. md->sc_count=0;
  826. md->opt1=md->opt2=md->opt3=md->option=0;
  827. memset(md->skillunit,0,sizeof(md->skillunit));
  828. memset(md->skillunittick,0,sizeof(md->skillunittick));
  829. md->hp = battle_get_max_hp(&md->bl);
  830. if(md->hp<=0){
  831. mob_makedummymobdb(md->class);
  832. md->hp = battle_get_max_hp(&md->bl);
  833. }
  834. clif_spawnmob(md);
  835. return 0;
  836. }
  837. /*==========================================
  838. * Distance calculation between two points
  839. *------------------------------------------
  840. */
  841. static int distance(int x0,int y0,int x1,int y1)
  842. {
  843. int dx,dy;
  844. dx=abs(x0-x1);
  845. dy=abs(y0-y1);
  846. return dx>dy ? dx : dy;
  847. }
  848. /*==========================================
  849. * The stop of MOB's attack
  850. *------------------------------------------
  851. */
  852. int mob_stopattack(struct mob_data *md)
  853. {
  854. md->target_id=0;
  855. md->state.targettype = NONE_ATTACKABLE;
  856. md->attacked_id=0;
  857. return 0;
  858. }
  859. /*==========================================
  860. * The stop of MOB's walking
  861. *------------------------------------------
  862. */
  863. int mob_stop_walking(struct mob_data *md,int type)
  864. {
  865. nullpo_retr(0, md);
  866. if(md->state.state == MS_WALK || md->state.state == MS_IDLE) {
  867. int dx=0,dy=0;
  868. md->walkpath.path_len=0;
  869. if(type&4){
  870. dx=md->to_x-md->bl.x;
  871. if(dx<0)
  872. dx=-1;
  873. else if(dx>0)
  874. dx=1;
  875. dy=md->to_y-md->bl.y;
  876. if(dy<0)
  877. dy=-1;
  878. else if(dy>0)
  879. dy=1;
  880. }
  881. md->to_x=md->bl.x+dx;
  882. md->to_y=md->bl.y+dy;
  883. if(dx!=0 || dy!=0){
  884. mob_walktoxy_sub(md);
  885. return 0;
  886. }
  887. mob_changestate(md,MS_IDLE,0);
  888. }
  889. if(type&0x01)
  890. clif_fixmobpos(md);
  891. if(type&0x02) {
  892. int delay=battle_get_dmotion(&md->bl);
  893. unsigned int tick = gettick();
  894. if(md->canmove_tick < tick)
  895. md->canmove_tick = tick + delay;
  896. }
  897. return 0;
  898. }
  899. /*==========================================
  900. * Reachability to a Specification ID existence place
  901. *------------------------------------------
  902. */
  903. int mob_can_reach(struct mob_data *md,struct block_list *bl,int range)
  904. {
  905. int dx,dy;
  906. struct walkpath_data wpd;
  907. int i;
  908. nullpo_retr(0, md);
  909. nullpo_retr(0, bl);
  910. dx=abs(bl->x - md->bl.x);
  911. dy=abs(bl->y - md->bl.y);
  912. //=========== guildcastle guardian no search start===========
  913. //when players are the guild castle member not attack them !
  914. if(md->class >= 1285 && md->class <= 1287){
  915. struct map_session_data *sd;
  916. struct guild *g=NULL;
  917. struct guild_castle *gc=guild_mapname2gc(map[bl->m].name);
  918. if(gc && agit_flag==0) // Guardians will not attack during non-woe time [Valaris]
  919. return 0; // end addition [Valaris]
  920. if(bl && bl->type == BL_PC){
  921. nullpo_retr(0, sd=(struct map_session_data *)bl);
  922. if(!gc)
  923. return 0;
  924. if(gc && sd && sd->status.guild_id) {
  925. g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
  926. if(g && g->guild_id == gc->guild_id)
  927. return 0;
  928. if(g && gc && guild_isallied(g,gc))
  929. return 0;
  930. }
  931. }
  932. }
  933. //========== guildcastle guardian no search eof==============
  934. if(bl && bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris]
  935. struct map_session_data *sd;
  936. if((sd=(struct map_session_data *)bl) != NULL && pc_isGM(sd) >= battle_config.monsters_ignore_gm)
  937. return 0;
  938. }
  939. if( md->bl.m != bl->m) // 違うャbプ
  940. return 0;
  941. if( range>0 && range < ((dx>dy)?dx:dy) ) // 遠すぎる
  942. return 0;
  943. if( md->bl.x==bl->x && md->bl.y==bl->y ) // 同じマス
  944. return 1;
  945. // Obstacle judging
  946. wpd.path_len=0;
  947. wpd.path_pos=0;
  948. wpd.path_half=0;
  949. if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x,bl->y,0)!=-1)
  950. return 1;
  951. if(bl->type!=BL_PC && bl->type!=BL_MOB)
  952. return 0;
  953. // It judges whether it can adjoin or not.
  954. dx=(dx>0)?1:((dx<0)?-1:0);
  955. dy=(dy>0)?1:((dy<0)?-1:0);
  956. if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-dx,bl->y-dy,0)!=-1)
  957. return 1;
  958. for(i=0;i<9;i++){
  959. if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-1+i/3,bl->y-1+i%3,0)!=-1)
  960. return 1;
  961. }
  962. return 0;
  963. }
  964. /*==========================================
  965. * Determination for an attack of a monster
  966. *------------------------------------------
  967. */
  968. int mob_target(struct mob_data *md,struct block_list *bl,int dist)
  969. {
  970. struct map_session_data *sd;
  971. struct status_change *sc_data;
  972. short *option;
  973. int mode,race;
  974. nullpo_retr(0, md);
  975. nullpo_retr(0, bl);
  976. sc_data = battle_get_sc_data(bl);
  977. option = battle_get_option(bl);
  978. race=mob_db[md->class].race;
  979. if(!md->mode)
  980. mode=mob_db[md->class].mode;
  981. else
  982. mode=md->mode;
  983. if(!(mode&0x80)) {
  984. md->target_id = 0;
  985. return 0;
  986. }
  987. // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
  988. if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && ( !(mode&0x04) || rand()%100>25) )
  989. return 0;
  990. if(mode&0x20 || // Coercion is exerted if it is MVPMOB.
  991. (sc_data && sc_data[SC_TRICKDEAD].timer == -1 && sc_data[SC_BASILICA].timer == -1 &&
  992. ( (option && !(*option&0x06) ) || race==4 || race==6) ) ) {
  993. if(bl->type == BL_PC) {
  994. nullpo_retr(0, sd = (struct map_session_data *)bl);
  995. if(sd->invincible_timer != -1 || pc_isinvisible(sd))
  996. return 0;
  997. if(!(mode&0x20) && race!=4 && race!=6 && sd->state.gangsterparadise)
  998. return 0;
  999. }
  1000. md->target_id=bl->id; // Since there was no disturbance, it locks on to target.
  1001. if(bl->type == BL_PC || bl->type == BL_MOB)
  1002. md->state.targettype = ATTACKABLE;
  1003. else
  1004. md->state.targettype = NONE_ATTACKABLE;
  1005. md->min_chase=dist+13;
  1006. if(md->min_chase>26)
  1007. md->min_chase=26;
  1008. }
  1009. return 0;
  1010. }
  1011. /*==========================================
  1012. * The ?? routine of an active monster
  1013. *------------------------------------------
  1014. */
  1015. static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
  1016. {
  1017. struct map_session_data *tsd=NULL;
  1018. struct mob_data *smd,*tmd=NULL;
  1019. int mode,race,dist,*pcc;
  1020. nullpo_retr(0, bl);
  1021. nullpo_retr(0, ap);
  1022. nullpo_retr(0, smd=va_arg(ap,struct mob_data *));
  1023. nullpo_retr(0, pcc=va_arg(ap,int *));
  1024. if(bl->type==BL_PC)
  1025. tsd=(struct map_session_data *)bl;
  1026. else if(bl->type==BL_MOB)
  1027. tmd=(struct mob_data *)bl;
  1028. else
  1029. return 0;
  1030. //敵味方判定
  1031. if(battle_check_target(&smd->bl,bl,BCT_ENEMY)==0)
  1032. return 0;
  1033. if(!smd->mode)
  1034. mode=mob_db[smd->class].mode;
  1035. else
  1036. mode=smd->mode;
  1037. // アクティブでターゲット射程内にいるなら、ロックする
  1038. if( mode&0x04 ){
  1039. race=mob_db[smd->class].race;
  1040. //対象がPCの場合
  1041. if(tsd &&
  1042. !pc_isdead(tsd) &&
  1043. tsd->bl.m == smd->bl.m &&
  1044. tsd->invincible_timer == -1 &&
  1045. !pc_isinvisible(tsd) &&
  1046. (dist=distance(smd->bl.x,smd->bl.y,tsd->bl.x,tsd->bl.y))<9
  1047. )
  1048. {
  1049. if(mode&0x20 ||
  1050. (tsd->sc_data[SC_TRICKDEAD].timer == -1 && tsd->sc_data[SC_BASILICA].timer == -1 &&
  1051. ((!pc_ishiding(tsd) && !tsd->state.gangsterparadise) || ((race == 4 || race == 6) && !tsd->perfect_hiding) ))){ // 妨害がないか判定
  1052. if( mob_can_reach(smd,bl,12) && // 到達可能性判定
  1053. rand()%1000<1000/(++(*pcc)) ){ // 範囲内PCで等確率にする
  1054. smd->target_id=tsd->bl.id;
  1055. smd->state.targettype = ATTACKABLE;
  1056. smd->min_chase=13;
  1057. }
  1058. }
  1059. }
  1060. //対象がMobの場合
  1061. else if(tmd &&
  1062. tmd->bl.m == smd->bl.m &&
  1063. (dist=distance(smd->bl.x,smd->bl.y,tmd->bl.x,tmd->bl.y))<9
  1064. )
  1065. {
  1066. if( mob_can_reach(smd,bl,12) && // 到達可能性判定
  1067. rand()%1000<1000/(++(*pcc)) ){ // 範囲内で等確率にする
  1068. smd->target_id=bl->id;
  1069. smd->state.targettype = ATTACKABLE;
  1070. smd->min_chase=13;
  1071. }
  1072. }
  1073. }
  1074. return 0;
  1075. }
  1076. /*==========================================
  1077. * loot monster item search
  1078. *------------------------------------------
  1079. */
  1080. static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
  1081. {
  1082. struct mob_data* md;
  1083. int mode,dist,*itc;
  1084. nullpo_retr(0, bl);
  1085. nullpo_retr(0, ap);
  1086. nullpo_retr(0, md=va_arg(ap,struct mob_data *));
  1087. nullpo_retr(0, itc=va_arg(ap,int *));
  1088. if(!md->mode)
  1089. mode=mob_db[md->class].mode;
  1090. else
  1091. mode=md->mode;
  1092. if( !md->target_id && mode&0x02){
  1093. if(!md->lootitem || (battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) )
  1094. return 0;
  1095. if(bl->m == md->bl.m && (dist=distance(md->bl.x,md->bl.y,bl->x,bl->y))<9){
  1096. if( mob_can_reach(md,bl,12) && // Reachability judging
  1097. rand()%1000<1000/(++(*itc)) ){ // It is made a probability, such as within the limits PC.
  1098. md->target_id=bl->id;
  1099. md->state.targettype = NONE_ATTACKABLE;
  1100. md->min_chase=13;
  1101. }
  1102. }
  1103. }
  1104. return 0;
  1105. }
  1106. /*==========================================
  1107. * The ?? routine of a link monster
  1108. *------------------------------------------
  1109. */
  1110. static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
  1111. {
  1112. struct mob_data *tmd;
  1113. struct mob_data* md;
  1114. struct block_list *target;
  1115. nullpo_retr(0, bl);
  1116. nullpo_retr(0, ap);
  1117. nullpo_retr(0, tmd=(struct mob_data *)bl);
  1118. nullpo_retr(0, md=va_arg(ap,struct mob_data *));
  1119. nullpo_retr(0, target=va_arg(ap,struct block_list *));
  1120. // same family free in a range at a link monster -- it will be made to lock if MOB is
  1121. /* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){
  1122. if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
  1123. if( mob_can_reach(tmd,target,12) ){ // Reachability judging
  1124. tmd->target_id=md->target_id;
  1125. tmd->state.targettype = ATTACKABLE;
  1126. tmd->min_chase=13;
  1127. }
  1128. }
  1129. }*/
  1130. if( md->attacked_id > 0 && mob_db[md->class].mode&0x08){
  1131. if( tmd->class==md->class && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
  1132. if( mob_can_reach(tmd,target,12) ){ // Reachability judging
  1133. tmd->target_id=md->attacked_id;
  1134. tmd->state.targettype = ATTACKABLE;
  1135. tmd->min_chase=13;
  1136. }
  1137. }
  1138. }
  1139. return 0;
  1140. }
  1141. /*==========================================
  1142. * Processing of slave monsters
  1143. *------------------------------------------
  1144. */
  1145. static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
  1146. {
  1147. struct mob_data *mmd=NULL;
  1148. struct block_list *bl;
  1149. int mode,race,old_dist;
  1150. nullpo_retr(0, md);
  1151. if((bl=map_id2bl(md->master_id)) != NULL )
  1152. mmd=(struct mob_data *)bl;
  1153. mode=mob_db[md->class].mode;
  1154. // It is not main monster/leader.
  1155. if(!mmd || mmd->bl.type!=BL_MOB || mmd->bl.id!=md->master_id)
  1156. return 0;
  1157. // Since it is in the map on which the master is not, teleport is carried out and it pursues.
  1158. if( mmd->bl.m != md->bl.m ){
  1159. mob_warp(md,mmd->bl.m,mmd->bl.x,mmd->bl.y,3);
  1160. md->state.master_check = 1;
  1161. return 0;
  1162. }
  1163. // Distance with between slave and master is measured.
  1164. old_dist=md->master_dist;
  1165. md->master_dist=distance(md->bl.x,md->bl.y,mmd->bl.x,mmd->bl.y);
  1166. // Since the master was in near immediately before, teleport is carried out and it pursues.
  1167. if( old_dist<10 && md->master_dist>18){
  1168. mob_warp(md,-1,mmd->bl.x,mmd->bl.y,3);
  1169. md->state.master_check = 1;
  1170. return 0;
  1171. }
  1172. // Although there is the master, since it is somewhat far, it approaches.
  1173. if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
  1174. (md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0) && md->master_dist<15){
  1175. int i=0,dx,dy,ret;
  1176. if(md->master_dist>4) {
  1177. do {
  1178. if(i<=5){
  1179. dx=mmd->bl.x - md->bl.x;
  1180. dy=mmd->bl.y - md->bl.y;
  1181. if(dx<0) dx+=(rand()%( (dx<-3)?3:-dx )+1);
  1182. else if(dx>0) dx-=(rand()%( (dx>3)?3:dx )+1);
  1183. if(dy<0) dy+=(rand()%( (dy<-3)?3:-dy )+1);
  1184. else if(dy>0) dy-=(rand()%( (dy>3)?3:dy )+1);
  1185. }else{
  1186. dx=mmd->bl.x - md->bl.x + rand()%7 - 3;
  1187. dy=mmd->bl.y - md->bl.y + rand()%7 - 3;
  1188. }
  1189. ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
  1190. i++;
  1191. } while(ret && i<10);
  1192. }
  1193. else {
  1194. do {
  1195. dx = rand()%9 - 5;
  1196. dy = rand()%9 - 5;
  1197. if( dx == 0 && dy == 0) {
  1198. dx = (rand()%1)? 1:-1;
  1199. dy = (rand()%1)? 1:-1;
  1200. }
  1201. dx += mmd->bl.x;
  1202. dy += mmd->bl.y;
  1203. ret=mob_walktoxy(md,mmd->bl.x+dx,mmd->bl.y+dy,0);
  1204. i++;
  1205. } while(ret && i<10);
  1206. }
  1207. md->next_walktime=tick+500;
  1208. md->state.master_check = 1;
  1209. }
  1210. // There is the master, the master locks a target and he does not lock.
  1211. if( (mmd->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!md->target_id || md->state.targettype == NONE_ATTACKABLE) ){
  1212. struct map_session_data *sd=map_id2sd(mmd->target_id);
  1213. if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
  1214. race=mob_db[md->class].race;
  1215. if(mode&0x20 ||
  1216. (sd->sc_data[SC_TRICKDEAD].timer == -1 && sd->sc_data[SC_BASILICA].timer == -1 &&
  1217. ( (!pc_ishiding(sd) && !sd->state.gangsterparadise) || ((race == 4 || race == 6) && !sd->perfect_hiding) ) ) ){ // 妨害がないか判定
  1218. md->target_id=sd->bl.id;
  1219. md->state.targettype = ATTACKABLE;
  1220. md->min_chase=5+distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y);
  1221. md->state.master_check = 1;
  1222. }
  1223. }
  1224. }
  1225. // There is the master, the master locks a target and he does not lock.
  1226. /* if( (md->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!mmd->target_id || mmd->state.targettype == NONE_ATTACKABLE) ){
  1227. struct map_session_data *sd=map_id2sd(md->target_id);
  1228. if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
  1229. race=mob_db[mmd->class].race;
  1230. if(mode&0x20 ||
  1231. (sd->sc_data[SC_TRICKDEAD].timer == -1 &&
  1232. (!(sd->status.option&0x06) || race==4 || race==6)
  1233. ) ){ // It judges whether there is any disturbance.
  1234. mmd->target_id=sd->bl.id;
  1235. mmd->state.targettype = ATTACKABLE;
  1236. mmd->min_chase=5+distance(mmd->bl.x,mmd->bl.y,sd->bl.x,sd->bl.y);
  1237. }
  1238. }
  1239. }*/
  1240. return 0;
  1241. }
  1242. /*==========================================
  1243. * A lock of target is stopped and mob moves to a standby state.
  1244. *------------------------------------------
  1245. */
  1246. static int mob_unlocktarget(struct mob_data *md,int tick)
  1247. {
  1248. nullpo_retr(0, md);
  1249. md->target_id=0;
  1250. md->state.targettype = NONE_ATTACKABLE;
  1251. md->state.skillstate=MSS_IDLE;
  1252. md->next_walktime=tick+rand()%3000+3000;
  1253. return 0;
  1254. }
  1255. /*==========================================
  1256. * Random walk
  1257. *------------------------------------------
  1258. */
  1259. static int mob_randomwalk(struct mob_data *md,int tick)
  1260. {
  1261. const int retrycount=20;
  1262. int speed;
  1263. nullpo_retr(0, md);
  1264. speed=battle_get_speed(&md->bl);
  1265. if(DIFF_TICK(md->next_walktime,tick)<0){
  1266. int i,x,y,c,d=12-md->move_fail_count;
  1267. if(d<5) d=5;
  1268. for(i=0;i<retrycount;i++){ // Search of a movable place
  1269. int r=rand();
  1270. x=md->bl.x+r%(d*2+1)-d;
  1271. y=md->bl.y+r/(d*2+1)%(d*2+1)-d;
  1272. if((c=map_getcell(md->bl.m,x,y))!=1 && c!=5 && mob_walktoxy(md,x,y,1)==0){
  1273. md->move_fail_count=0;
  1274. break;
  1275. }
  1276. if(i+1>=retrycount){
  1277. md->move_fail_count++;
  1278. if(md->move_fail_count>1000){
  1279. if(battle_config.error_log)
  1280. printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class);
  1281. md->move_fail_count=0;
  1282. mob_spawn(md->bl.id);
  1283. }
  1284. }
  1285. }
  1286. for(i=c=0;i<md->walkpath.path_len;i++){ // The next walk start time is calculated.
  1287. if(md->walkpath.path[i]&1)
  1288. c+=speed*14/10;
  1289. else
  1290. c+=speed;
  1291. }
  1292. md->next_walktime = tick+rand()%3000+3000+c;
  1293. md->state.skillstate=MSS_WALK;
  1294. return 1;
  1295. }
  1296. return 0;
  1297. }
  1298. /*==========================================
  1299. * AI of MOB whose is near a Player
  1300. *------------------------------------------
  1301. */
  1302. static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
  1303. {
  1304. struct mob_data *md,*tmd=NULL;
  1305. struct map_session_data *tsd=NULL;
  1306. struct block_list *tbl=NULL;
  1307. struct flooritem_data *fitem;
  1308. unsigned int tick;
  1309. int i,dx,dy,ret,dist;
  1310. int attack_type=0;
  1311. int mode,race;
  1312. nullpo_retr(0, bl);
  1313. nullpo_retr(0, ap);
  1314. nullpo_retr(0, md=(struct mob_data*)bl);
  1315. tick=va_arg(ap,unsigned int);
  1316. if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME)
  1317. return 0;
  1318. md->last_thinktime=tick;
  1319. if( md->skilltimer!=-1 || md->bl.prev==NULL ){ // Under a skill aria and death
  1320. if(DIFF_TICK(tick,md->next_walktime)>MIN_MOBTHINKTIME)
  1321. md->next_walktime=tick;
  1322. return 0;
  1323. }
  1324. if(!md->mode)
  1325. mode=mob_db[md->class].mode;
  1326. else
  1327. mode=md->mode;
  1328. race=mob_db[md->class].race;
  1329. // Abnormalities
  1330. if((md->opt1 > 0 && md->opt1 != 6) || md->state.state==MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1)
  1331. return 0;
  1332. if(!(mode&0x80) && md->target_id > 0)
  1333. md->target_id = 0;
  1334. if(md->attacked_id > 0 && mode&0x08){ // Link monster
  1335. struct map_session_data *asd=map_id2sd(md->attacked_id);
  1336. if(asd){
  1337. if(asd->invincible_timer == -1 && !pc_isinvisible(asd)){
  1338. map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
  1339. md->bl.x-13,md->bl.y-13,
  1340. md->bl.x+13,md->bl.y+13,
  1341. BL_MOB,md,&asd->bl);
  1342. }
  1343. }
  1344. }
  1345. // It checks to see it was attacked first (if active, it is target change at 25% of probability).
  1346. if( mode>0 && md->attacked_id>0 && (!md->target_id || md->state.targettype == NONE_ATTACKABLE
  1347. || (mode&0x04 && rand()%100<25 ) ) ){
  1348. struct block_list *abl=map_id2bl(md->attacked_id);
  1349. struct map_session_data *asd=NULL;
  1350. if(abl){
  1351. if(abl->type==BL_PC)
  1352. asd=(struct map_session_data *)abl;
  1353. if(asd==NULL || md->bl.m != abl->m || abl->prev == NULL || asd->invincible_timer != -1 || pc_isinvisible(asd) ||
  1354. (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0)
  1355. md->attacked_id=0;
  1356. else {
  1357. //距離が遠い場合はタゲを変更しない
  1358. if (!md->target_id || (distance(md->bl.x,md->bl.y,abl->x,abl->y)<3)) {
  1359. md->target_id=md->attacked_id; // set target
  1360. md->state.targettype = ATTACKABLE;
  1361. attack_type = 1;
  1362. md->attacked_id=0;
  1363. md->min_chase=dist+13;
  1364. if(md->min_chase>26)
  1365. md->min_chase=26;
  1366. }
  1367. }
  1368. }
  1369. }
  1370. md->state.master_check = 0;
  1371. // Processing of slave monster
  1372. if( md->master_id > 0 && md->state.special_mob_ai==0)
  1373. mob_ai_sub_hard_slavemob(md,tick);
  1374. // アクティヴモンスターの策敵 (?? of a bitter taste TIVU monster)
  1375. if( (!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mode&0x04 && !md->state.master_check &&
  1376. battle_config.monster_active_enable){
  1377. i=0;
  1378. if(md->state.special_mob_ai){
  1379. map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
  1380. md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
  1381. md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
  1382. 0,md,&i);
  1383. }else{
  1384. map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
  1385. md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
  1386. md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
  1387. BL_PC,md,&i);
  1388. }
  1389. }
  1390. // The item search of a route monster
  1391. if( !md->target_id && mode&0x02 && !md->state.master_check){
  1392. i=0;
  1393. map_foreachinarea(mob_ai_sub_hard_lootsearch,md->bl.m,
  1394. md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
  1395. md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
  1396. BL_ITEM,md,&i);
  1397. }
  1398. // It will attack, if the candidate for an attack is.
  1399. if(md->target_id > 0){
  1400. if((tbl=map_id2bl(md->target_id))){
  1401. if(tbl->type==BL_PC)
  1402. tsd=(struct map_session_data *)tbl;
  1403. else if(tbl->type==BL_MOB)
  1404. tmd=(struct mob_data *)tbl;
  1405. if(tsd || tmd) {
  1406. if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase)
  1407. mob_unlocktarget(md,tick); // 別マップか、視界外
  1408. else if( tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
  1409. ((pc_ishiding(tsd) || tsd->state.gangsterparadise) &&
  1410. !((race == 4 || race == 6) && !tsd->perfect_hiding) )) )
  1411. mob_unlocktarget(md,tick); // スキルなどによる策敵妨害
  1412. else if(!battle_check_range(&md->bl,tbl,mob_db[md->class].range)){
  1413. // 攻撃範囲外なので移動
  1414. if(!(mode&1)){ // 移動しないモード
  1415. mob_unlocktarget(md,tick);
  1416. return 0;
  1417. }
  1418. if( !mob_can_move(md) ) // 動けない状態にある
  1419. return 0;
  1420. md->state.skillstate=MSS_CHASE; // 突撃時スキル
  1421. mobskill_use(md,tick,-1);
  1422. // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
  1423. if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
  1424. return 0; // 既に移動中
  1425. if( !mob_can_reach(md,tbl,(md->min_chase>13)?md->min_chase:13) )
  1426. mob_unlocktarget(md,tick); // 移動できないのでタゲ解除(IWとか?)
  1427. else{
  1428. // 追跡
  1429. md->next_walktime=tick+500;
  1430. i=0;
  1431. do {
  1432. if(i==0){ // 最初はAEGISと同じ方法で検索
  1433. dx=tbl->x - md->bl.x;
  1434. dy=tbl->y - md->bl.y;
  1435. if(dx<0) dx++;
  1436. else if(dx>0) dx--;
  1437. if(dy<0) dy++;
  1438. else if(dy>0) dy--;
  1439. }else{ // だめならAthena式(ランダム)
  1440. dx=tbl->x - md->bl.x + rand()%3 - 1;
  1441. dy=tbl->y - md->bl.y + rand()%3 - 1;
  1442. }
  1443. /* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
  1444. dx=tsd->bl.x - md->bl.x;
  1445. dy=tsd->bl.y - md->bl.y;
  1446. if(dx<0) dx--;
  1447. else if(dx>0) dx++;
  1448. if(dy<0) dy--;
  1449. else if(dy>0) dy++;
  1450. }*/
  1451. ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
  1452. i++;
  1453. } while(ret && i<5);
  1454. if(ret){ // 移動不可能な所からの攻撃なら2歩下る
  1455. if(dx<0) dx=2;
  1456. else if(dx>0) dx=-2;
  1457. if(dy<0) dy=2;
  1458. else if(dy>0) dy=-2;
  1459. mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
  1460. }
  1461. }
  1462. } else { // 攻撃射程範囲内
  1463. md->state.skillstate=MSS_ATTACK;
  1464. if(md->state.state==MS_WALK)
  1465. mob_stop_walking(md,1); // 歩行中なら停止
  1466. if(md->state.state==MS_ATTACK)
  1467. return 0; // 既に攻撃中
  1468. mob_changestate(md,MS_ATTACK,attack_type);
  1469. /* if(mode&0x08){ // リンクモンスター
  1470. map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
  1471. md->bl.x-13,md->bl.y-13,
  1472. md->bl.x+13,md->bl.y+13,
  1473. BL_MOB,md,&tsd->bl);
  1474. }*/
  1475. }
  1476. return 0;
  1477. }else{ // ルートモンスター処理
  1478. if(tbl == NULL || tbl->type != BL_ITEM ||tbl->m != md->bl.m ||
  1479. (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem){
  1480. // 遠すぎるかアイテムがなくなった
  1481. mob_unlocktarget(md,tick);
  1482. if(md->state.state==MS_WALK)
  1483. mob_stop_walking(md,1); // 歩行中なら停止
  1484. }else if(dist){
  1485. if(!(mode&1)){ // 移動しないモード
  1486. mob_unlocktarget(md,tick);
  1487. return 0;
  1488. }
  1489. if( !mob_can_move(md) ) // 動けない状態にある
  1490. return 0;
  1491. md->state.skillstate=MSS_LOOT; // ルート時スキル使用
  1492. mobskill_use(md,tick,-1);
  1493. // if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
  1494. if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y) <= 0))
  1495. return 0; // 既に移動中
  1496. md->next_walktime=tick+500;
  1497. dx=tbl->x - md->bl.x;
  1498. dy=tbl->y - md->bl.y;
  1499. /* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
  1500. dx=tbl->x - md->bl.x;
  1501. dy=tbl->y - md->bl.y;
  1502. }*/
  1503. ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
  1504. if(ret)
  1505. mob_unlocktarget(md,tick);// 移動できないのでタゲ解除(IWとか?)
  1506. }else{ // アイテムまでたどり着いた
  1507. if(md->state.state==MS_ATTACK)
  1508. return 0; // 攻撃中
  1509. if(md->state.state==MS_WALK)
  1510. mob_stop_walking(md,1); // 歩行中なら停止
  1511. fitem = (struct flooritem_data *)tbl;
  1512. if(md->lootitem_count < LOOTITEM_SIZE)
  1513. memcpy(&md->lootitem[md->lootitem_count++],&fitem->item_data,sizeof(md->lootitem[0]));
  1514. else if(battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) {
  1515. mob_unlocktarget(md,tick);
  1516. return 0;
  1517. }
  1518. else {
  1519. if(md->lootitem[0].card[0] == (short)0xff00)
  1520. intif_delete_petdata(*((long *)(&md->lootitem[0].card[1])));
  1521. for(i=0;i<LOOTITEM_SIZE-1;i++)
  1522. memcpy(&md->lootitem[i],&md->lootitem[i+1],sizeof(md->lootitem[0]));
  1523. memcpy(&md->lootitem[LOOTITEM_SIZE-1],&fitem->item_data,sizeof(md->lootitem[0]));
  1524. }
  1525. map_clearflooritem(tbl->id);
  1526. mob_unlocktarget(md,tick);
  1527. }
  1528. return 0;
  1529. }
  1530. }else{
  1531. mob_unlocktarget(md,tick);
  1532. if(md->state.state==MS_WALK)
  1533. mob_stop_walking(md,4); // 歩行中なら停止
  1534. return 0;
  1535. }
  1536. }
  1537. // It is skill use at the time of /standby at the time of a walk.
  1538. if( mobskill_use(md,tick,-1) )
  1539. return 0;
  1540. // 歩行処理
  1541. if( mode&1 && mob_can_move(md) && // 移動可能MOB&動ける状態にある
  1542. (md->master_id==0 || md->state.special_mob_ai || md->master_dist>10) ){ //取り巻きMOBじゃない
  1543. if( DIFF_TICK(md->next_walktime,tick) > + 7000 &&
  1544. (md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len) ){
  1545. md->next_walktime = tick + 3000*rand()%2000;
  1546. }
  1547. // Random movement
  1548. if( mob_randomwalk(md,tick) )
  1549. return 0;
  1550. }
  1551. // Since he has finished walking, it stands by.
  1552. if( md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len )
  1553. md->state.skillstate=MSS_IDLE;
  1554. return 0;
  1555. }
  1556. /*==========================================
  1557. * Serious processing for mob in PC field of view (foreachclient)
  1558. *------------------------------------------
  1559. */
  1560. static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
  1561. {
  1562. unsigned int tick;
  1563. nullpo_retr(0, sd);
  1564. nullpo_retr(0, ap);
  1565. tick=va_arg(ap,unsigned int);
  1566. map_foreachinarea(mob_ai_sub_hard,sd->bl.m,
  1567. sd->bl.x-AREA_SIZE*2,sd->bl.y-AREA_SIZE*2,
  1568. sd->bl.x+AREA_SIZE*2,sd->bl.y+AREA_SIZE*2,
  1569. BL_MOB,tick);
  1570. return 0;
  1571. }
  1572. /*==========================================
  1573. * Serious processing for mob in PC field of view (interval timer function)
  1574. *------------------------------------------
  1575. */
  1576. static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
  1577. {
  1578. clif_foreachclient(mob_ai_sub_foreachclient,tick);
  1579. return 0;
  1580. }
  1581. /*==========================================
  1582. * Negligent mode MOB AI (PC is not in near)
  1583. *------------------------------------------
  1584. */
  1585. static int mob_ai_sub_lazy(void * key,void * data,va_list app)
  1586. {
  1587. struct mob_data *md=data;
  1588. unsigned int tick;
  1589. va_list ap;
  1590. nullpo_retr(0, md);
  1591. nullpo_retr(0, app);
  1592. nullpo_retr(0, ap=va_arg(app,va_list));
  1593. if(md->bl.type!=BL_MOB)
  1594. return 0;
  1595. if(!md->bl.type || md->bl.type!=BL_MOB)
  1596. return 0;
  1597. tick=va_arg(ap,unsigned int);
  1598. if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME*10)
  1599. return 0;
  1600. md->last_thinktime=tick;
  1601. if(md->bl.prev==NULL || md->skilltimer!=-1){
  1602. if(DIFF_TICK(tick,md->next_walktime)>MIN_MOBTHINKTIME*10)
  1603. md->next_walktime=tick;
  1604. return 0;
  1605. }
  1606. if(DIFF_TICK(md->next_walktime,tick)<0 &&
  1607. (mob_db[md->class].mode&1) && mob_can_move(md) ){
  1608. if( map[md->bl.m].users>0 ){
  1609. // Since PC is in the same map, somewhat better negligent processing is carried out.
  1610. // It sometimes moves.
  1611. if(rand()%1000<MOB_LAZYMOVEPERC)
  1612. mob_randomwalk(md,tick);
  1613. // MOB which is not not the summons MOB but BOSS, either sometimes reboils.
  1614. else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
  1615. mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
  1616. mob_spawn(md->bl.id);
  1617. }else{
  1618. // Since PC is not even in the same map, suitable processing is carried out even if it takes.
  1619. // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
  1620. if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
  1621. mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
  1622. mob_warp(md,-1,-1,-1,-1);
  1623. }
  1624. md->next_walktime = tick+rand()%10000+5000;
  1625. }
  1626. return 0;
  1627. }
  1628. /*==========================================
  1629. * Negligent processing for mob outside PC field of view (interval timer function)
  1630. *------------------------------------------
  1631. */
  1632. static int mob_ai_lazy(int tid,unsigned int tick,int id,int data)
  1633. {
  1634. map_foreachiddb(mob_ai_sub_lazy,tick);
  1635. return 0;
  1636. }
  1637. /*==========================================
  1638. * The structure object for item drop with delay
  1639. * Since it is only two being able to pass [ int ] a timer function
  1640. * Data is put in and passed to this structure object.
  1641. *------------------------------------------
  1642. */
  1643. struct delay_item_drop {
  1644. int m,x,y;
  1645. int nameid,amount;
  1646. struct map_session_data *first_sd,*second_sd,*third_sd;
  1647. };
  1648. struct delay_item_drop2 {
  1649. int m,x,y;
  1650. struct item item_data;
  1651. struct map_session_data *first_sd,*second_sd,*third_sd;
  1652. };
  1653. /*==========================================
  1654. * item drop with delay (timer function)
  1655. *------------------------------------------
  1656. */
  1657. static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
  1658. {
  1659. struct delay_item_drop *ditem;
  1660. struct item temp_item;
  1661. int flag;
  1662. nullpo_retr(0, ditem=(struct delay_item_drop *)id);
  1663. memset(&temp_item,0,sizeof(temp_item));
  1664. temp_item.nameid = ditem->nameid;
  1665. temp_item.amount = ditem->amount;
  1666. temp_item.identify = !itemdb_isequip3(temp_item.nameid);
  1667. if(battle_config.item_auto_get){
  1668. if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
  1669. clif_additem(ditem->first_sd,0,0,flag);
  1670. map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
  1671. }
  1672. free(ditem);
  1673. return 0;
  1674. }
  1675. map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
  1676. free(ditem);
  1677. return 0;
  1678. }
  1679. /*==========================================
  1680. * item drop (timer function)-lootitem with delay
  1681. *------------------------------------------
  1682. */
  1683. static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
  1684. {
  1685. struct delay_item_drop2 *ditem;
  1686. int flag;
  1687. nullpo_retr(0, ditem=(struct delay_item_drop2 *)id);
  1688. if(battle_config.item_auto_get){
  1689. if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
  1690. clif_additem(ditem->first_sd,0,0,flag);
  1691. map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
  1692. }
  1693. free(ditem);
  1694. return 0;
  1695. }
  1696. map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
  1697. free(ditem);
  1698. return 0;
  1699. }
  1700. /*==========================================
  1701. * mob data is erased.
  1702. *------------------------------------------
  1703. */
  1704. int mob_delete(struct mob_data *md)
  1705. {
  1706. nullpo_retr(1, md);
  1707. if(md->bl.prev == NULL)
  1708. return 1;
  1709. mob_changestate(md,MS_DEAD,0);
  1710. clif_clearchar_area(&md->bl,1);
  1711. map_delblock(&md->bl);
  1712. if(mob_get_viewclass(md->class) <= 1000)
  1713. clif_clearchar_delay(gettick()+3000,&md->bl,0);
  1714. mob_deleteslave(md);
  1715. mob_setdelayspawn(md->bl.id);
  1716. return 0;
  1717. }
  1718. int mob_catch_delete(struct mob_data *md,int type)
  1719. {
  1720. nullpo_retr(1, md);
  1721. if(md->bl.prev == NULL)
  1722. return 1;
  1723. mob_changestate(md,MS_DEAD,0);
  1724. clif_clearchar_area(&md->bl,type);
  1725. map_delblock(&md->bl);
  1726. mob_setdelayspawn(md->bl.id);
  1727. return 0;
  1728. }
  1729. int mob_timer_delete(int tid, unsigned int tick, int id, int data)
  1730. {
  1731. struct block_list *bl=map_id2bl(id);
  1732. struct mob_data *md;
  1733. nullpo_retr(0, bl);
  1734. md = (struct mob_data *)bl;
  1735. mob_catch_delete(md,3);
  1736. return 0;
  1737. }
  1738. /*==========================================
  1739. *
  1740. *------------------------------------------
  1741. */
  1742. int mob_deleteslave_sub(struct block_list *bl,va_list ap)
  1743. {
  1744. struct mob_data *md;
  1745. int id;
  1746. nullpo_retr(0, bl);
  1747. nullpo_retr(0, ap);
  1748. nullpo_retr(0, md = (struct mob_data *)bl);
  1749. id=va_arg(ap,int);
  1750. if(md->master_id > 0 && md->master_id == id )
  1751. mob_damage(NULL,md,md->hp,1);
  1752. return 0;
  1753. }
  1754. /*==========================================
  1755. *
  1756. *------------------------------------------
  1757. */
  1758. int mob_deleteslave(struct mob_data *md)
  1759. {
  1760. nullpo_retr(0, md);
  1761. map_foreachinarea(mob_deleteslave_sub, md->bl.m,
  1762. 0,0,map[md->bl.m].xs,map[md->bl.m].ys,
  1763. BL_MOB,md->bl.id);
  1764. return 0;
  1765. }
  1766. /*==========================================
  1767. * It is the damage of sd to damage to md.
  1768. *------------------------------------------
  1769. */
  1770. int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
  1771. {
  1772. int i,count,minpos,mindmg;
  1773. struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE];
  1774. struct {
  1775. struct party *p;
  1776. int id,base_exp,job_exp,zeny;
  1777. } pt[DAMAGELOG_SIZE];
  1778. int pnum=0;
  1779. int mvp_damage,max_hp;
  1780. unsigned int tick = gettick();
  1781. struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL;
  1782. double dmg_rate,tdmg,temp;
  1783. struct item item;
  1784. int ret;
  1785. int drop_rate;
  1786. int skill,sp;
  1787. nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
  1788. max_hp = battle_get_max_hp(&md->bl);
  1789. if(src && src->type == BL_PC) {
  1790. sd = (struct map_session_data *)src;
  1791. mvp_sd = sd;
  1792. }
  1793. // if(battle_config.battle_log)
  1794. // printf("mob_damage %d %d %d\n",md->hp,max_hp,damage);
  1795. if(md->bl.prev==NULL){
  1796. if(battle_config.error_log==1)
  1797. printf("mob_damage : BlockError!!\n");
  1798. return 0;
  1799. }
  1800. if(md->state.state==MS_DEAD || md->hp<=0) {
  1801. if(md->bl.prev != NULL) {
  1802. mob_changestate(md,MS_DEAD,0);
  1803. mobskill_use(md,tick,-1); // It is skill at the time of death.
  1804. clif_clearchar_area(&md->bl,1);
  1805. map_delblock(&md->bl);
  1806. mob_setdelayspawn(md->bl.id);
  1807. }
  1808. return 0;
  1809. }
  1810. if(md->sc_data[SC_ENDURE].timer == -1)
  1811. mob_stop_walking(md,3);
  1812. if(damage > max_hp>>2)
  1813. skill_stop_dancing(&md->bl,0);
  1814. if(md->hp > max_hp)
  1815. md->hp = max_hp;
  1816. // The amount of overkill rounds to hp.
  1817. if(damage>md->hp)
  1818. damage=md->hp;
  1819. if(!(type&2)) {
  1820. if(sd!=NULL){
  1821. for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
  1822. if(md->dmglog[i].id==sd->bl.id)
  1823. break;
  1824. if(md->dmglog[i].id==0){
  1825. minpos=i;
  1826. mindmg=0;
  1827. }
  1828. else if(md->dmglog[i].dmg<mindmg){
  1829. minpos=i;
  1830. mindmg=md->dmglog[i].dmg;
  1831. }
  1832. }
  1833. if(i<DAMAGELOG_SIZE)
  1834. md->dmglog[i].dmg+=damage;
  1835. else {
  1836. md->dmglog[minpos].id=sd->bl.id;
  1837. md->dmglog[minpos].dmg=damage;
  1838. }
  1839. if(md->attacked_id <= 0 && md->state.special_mob_ai==0)
  1840. md->attacked_id = sd->bl.id;
  1841. }
  1842. if(src && src->type == BL_PET && battle_config.pet_attack_exp_to_master==1) {
  1843. struct pet_data *pd = (struct pet_data *)src;
  1844. nullpo_retr(0, pd);
  1845. for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
  1846. if(md->dmglog[i].id==pd->msd->bl.id)
  1847. break;
  1848. if(md->dmglog[i].id==0){
  1849. minpos=i;
  1850. mindmg=0;
  1851. }
  1852. else if(md->dmglog[i].dmg<mindmg){
  1853. minpos=i;
  1854. mindmg=md->dmglog[i].dmg;
  1855. }
  1856. }
  1857. if(i<DAMAGELOG_SIZE)
  1858. md->dmglog[i].dmg+=(damage*battle_config.pet_attack_exp_rate)/100;
  1859. else {
  1860. md->dmglog[minpos].id=pd->msd->bl.id;
  1861. md->dmglog[minpos].dmg=(damage*battle_config.pet_attack_exp_rate)/100;
  1862. }
  1863. }
  1864. if(src && src->type == BL_MOB && ((struct mob_data*)src)->state.special_mob_ai){
  1865. struct mob_data *md2 = (struct mob_data *)src;
  1866. nullpo_retr(0, md2);
  1867. for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
  1868. if(md->dmglog[i].id==md2->master_id)
  1869. break;
  1870. if(md->dmglog[i].id==0){
  1871. minpos=i;
  1872. mindmg=0;
  1873. }
  1874. else if(md->dmglog[i].dmg<mindmg){
  1875. minpos=i;
  1876. mindmg=md->dmglog[i].dmg;
  1877. }
  1878. }
  1879. if(i<DAMAGELOG_SIZE)
  1880. md->dmglog[i].dmg+=damage;
  1881. else {
  1882. md->dmglog[minpos].id=md2->master_id;
  1883. md->dmglog[minpos].dmg=damage;
  1884. if(md->attacked_id <= 0 && md->state.special_mob_ai==0)
  1885. md->attacked_id = md2->master_id;
  1886. }
  1887. }
  1888. }
  1889. md->hp-=damage;
  1890. if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
  1891. struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
  1892. if(gc) {
  1893. if(md->bl.id==gc->GID0) {
  1894. gc->Ghp0=md->hp;
  1895. if(gc->Ghp0<=0) {
  1896. guild_castledatasave(gc->castle_id,10,0);
  1897. guild_castledatasave(gc->castle_id,18,0);
  1898. }
  1899. }
  1900. if(md->bl.id==gc->GID1) {
  1901. gc->Ghp1=md->hp;
  1902. if(gc->Ghp1<=0) {
  1903. guild_castledatasave(gc->castle_id,11,0);
  1904. guild_castledatasave(gc->castle_id,19,0);
  1905. }
  1906. }
  1907. if(md->bl.id==gc->GID2) {
  1908. gc->Ghp2=md->hp;
  1909. if(gc->Ghp2<=0) {
  1910. guild_castledatasave(gc->castle_id,12,0);
  1911. guild_castledatasave(gc->castle_id,20,0);
  1912. }
  1913. }
  1914. if(md->bl.id==gc->GID3) {
  1915. gc->Ghp3=md->hp;
  1916. if(gc->Ghp3<=0) {
  1917. guild_castledatasave(gc->castle_id,13,0);
  1918. guild_castledatasave(gc->castle_id,21,0);
  1919. }
  1920. }
  1921. if(md->bl.id==gc->GID4) {
  1922. gc->Ghp4=md->hp;
  1923. if(gc->Ghp4<=0) {
  1924. guild_castledatasave(gc->castle_id,14,0);
  1925. guild_castledatasave(gc->castle_id,22,0);
  1926. }
  1927. }
  1928. if(md->bl.id==gc->GID5) {
  1929. gc->Ghp5=md->hp;
  1930. if(gc->Ghp5<=0) {
  1931. guild_castledatasave(gc->castle_id,15,0);
  1932. guild_castledatasave(gc->castle_id,23,0);
  1933. }
  1934. }
  1935. if(md->bl.id==gc->GID6) {
  1936. gc->Ghp6=md->hp;
  1937. if(gc->Ghp6<=0) {
  1938. guild_castledatasave(gc->castle_id,16,0);
  1939. guild_castledatasave(gc->castle_id,24,0);
  1940. }
  1941. }
  1942. if(md->bl.id==gc->GID7) {
  1943. gc->Ghp7=md->hp;
  1944. if(gc->Ghp7<=0) {
  1945. guild_castledatasave(gc->castle_id,17,0);
  1946. guild_castledatasave(gc->castle_id,25,0);
  1947. }
  1948. }
  1949. }
  1950. } // end addition [Valaris]
  1951. if(md->option&2 )
  1952. skill_status_change_end(&md->bl, SC_HIDING, -1);
  1953. if(md->option&4 )
  1954. skill_status_change_end(&md->bl, SC_CLOAKING, -1);
  1955. if(md->state.special_mob_ai == 2){//スフィアーマイン
  1956. int skillidx=0;
  1957. if((skillidx=mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION2))>=0){
  1958. md->mode |= 0x1;
  1959. md->next_walktime=tick;
  1960. mobskill_use_id(md,&md->bl,skillidx);//自爆詠唱開始
  1961. md->state.special_mob_ai++;
  1962. }
  1963. }
  1964. if(md->hp>0){
  1965. return 0;
  1966. }
  1967. // ----- ここから死亡処理 -----
  1968. map_freeblock_lock();
  1969. mob_changestate(md,MS_DEAD,0);
  1970. mobskill_use(md,tick,-1); // 死亡時スキル
  1971. memset(tmpsd,0,sizeof(tmpsd));
  1972. memset(pt,0,sizeof(pt));
  1973. max_hp = battle_get_max_hp(&md->bl);
  1974. if(src && src->type == BL_MOB)
  1975. mob_unlocktarget((struct mob_data *)src,tick);
  1976. /* ソウルドレイン */
  1977. if(sd && (skill=pc_checkskill(sd,HW_SOULDRAIN))>0){
  1978. clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,skill,1);
  1979. sp = (battle_get_lv(&md->bl))*(65+15*skill)/100;
  1980. if(sd->status.sp + sp > sd->status.max_sp)
  1981. sp = sd->status.max_sp - sd->status.sp;
  1982. sd->status.sp += sp;
  1983. clif_heal(sd->fd,SP_SP,sp);
  1984. }
  1985. // map外に消えた人は計算から除くので
  1986. // overkill分は無いけどsumはmax_hpとは違う
  1987. tdmg = 0;
  1988. for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){
  1989. if(md->dmglog[i].id==0)
  1990. continue;
  1991. tmpsd[i] = map_id2sd(md->dmglog[i].id);
  1992. if(tmpsd[i] == NULL)
  1993. continue;
  1994. count++;
  1995. if(tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
  1996. continue;
  1997. tdmg += (double)md->dmglog[i].dmg;
  1998. if(mvp_damage<md->dmglog[i].dmg){
  1999. third_sd = second_sd;
  2000. second_sd = mvp_sd;
  2001. mvp_sd=tmpsd[i];
  2002. mvp_damage=md->dmglog[i].dmg;
  2003. }
  2004. }
  2005. // [MouseJstr]
  2006. if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
  2007. if((double)max_hp < tdmg)
  2008. dmg_rate = ((double)max_hp) / tdmg;
  2009. else dmg_rate = 1;
  2010. // 経験値の分配
  2011. for(i=0;i<DAMAGELOG_SIZE;i++){
  2012. int pid,base_exp,job_exp,flag=1,zeny=0;
  2013. double per;
  2014. struct party *p;
  2015. if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m)
  2016. continue;
  2017. /* jAthena's exp formula
  2018. per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
  2019. temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
  2020. base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2021. if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
  2022. if(base_exp < 0) base_exp = 0;
  2023. temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
  2024. job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2025. if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1;
  2026. if(job_exp < 0) job_exp = 0;
  2027. */
  2028. //eAthena's exp formula rather than jAthena's
  2029. per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
  2030. if(per>512) per=512;
  2031. if(per<1) per=1;
  2032. base_exp=mob_db[md->class].base_exp*per/256;
  2033. if(base_exp < 1) base_exp = 1;
  2034. if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
  2035. base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
  2036. }
  2037. job_exp=mob_db[md->class].job_exp*per/256;
  2038. if(job_exp < 1) job_exp = 1;
  2039. if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
  2040. job_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
  2041. }
  2042. if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) { // for summoned creatures [Valaris]
  2043. base_exp = 0;
  2044. job_exp = 0;
  2045. }
  2046. else {
  2047. if(battle_config.zeny_from_mobs) {
  2048. if(md->level > 0) zeny=(md->level+rand()%md->level)*per/256; // zeny calculation moblv + random moblv [Valaris]
  2049. if(mob_db[md->class].mexp > 0)
  2050. zeny*=rand()%250;
  2051. }
  2052. if(battle_config.mobs_level_up && md->level > mob_db[md->class].lv) { // [Valaris]
  2053. job_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].job_exp*.03)*per/256;
  2054. base_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].base_exp*.03)*per/256;
  2055. }
  2056. }
  2057. if((pid=tmpsd[i]->status.party_id)>0){ // パーティに入っている
  2058. int j=0;
  2059. for(j=0;j<pnum;j++) // 公平パーティリストにいるかどうか
  2060. if(pt[j].id==pid)
  2061. break;
  2062. if(j==pnum){ // いないときは公平かどうか確認
  2063. if((p=party_search(pid))!=NULL && p->exp!=0){
  2064. pt[pnum].id=pid;
  2065. pt[pnum].p=p;
  2066. pt[pnum].base_exp=base_exp;
  2067. pt[pnum].job_exp=job_exp;
  2068. if(battle_config.zeny_from_mobs)
  2069. pt[pnum].zeny=zeny; // zeny share [Valaris]
  2070. pnum++;
  2071. flag=0;
  2072. }
  2073. }else{ // いるときは公平
  2074. pt[j].base_exp+=base_exp;
  2075. pt[j].job_exp+=job_exp;
  2076. if(battle_config.zeny_from_mobs)
  2077. pt[j].zeny+=zeny; // zeny share [Valaris]
  2078. flag=0;
  2079. }
  2080. }
  2081. if(flag) { // added zeny from mobs [Valaris]
  2082. if(base_exp > 0 || job_exp > 0)
  2083. pc_gainexp(tmpsd[i],base_exp,job_exp);
  2084. if (battle_config.zeny_from_mobs && zeny > 0) {
  2085. pc_getzeny(tmpsd[i],zeny); // zeny from mobs [Valaris]
  2086. }
  2087. }
  2088. }
  2089. // 公平分配
  2090. for(i=0;i<pnum;i++)
  2091. party_exp_share(pt[i].p,md->bl.m,pt[i].base_exp,pt[i].job_exp,pt[i].zeny);
  2092. // item drop
  2093. if(!(type&1)) {
  2094. int log_item[8] = {0};
  2095. for(i=0;i<8;i++){
  2096. struct delay_item_drop *ditem;
  2097. int drop_rate;
  2098. if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris]
  2099. break; // End
  2100. if(mob_db[md->class].dropitem[i].nameid <= 0)
  2101. continue;
  2102. drop_rate = mob_db[md->class].dropitem[i].p;
  2103. if(drop_rate <= 0 && battle_config.drop_rate0item)
  2104. drop_rate = 1;
  2105. if(battle_config.drops_by_luk>0 && sd && md) drop_rate+=(sd->status.luk*battle_config.drops_by_luk)/100; // drops affected by luk [Valaris]
  2106. if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) drop_rate*=1.25; // pk_mode increase drops if 20 level difference [Valaris]
  2107. if(drop_rate <= rand()%10000)
  2108. continue;
  2109. ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
  2110. ditem->nameid = mob_db[md->class].dropitem[i].nameid;
  2111. log_item[i] = ditem->nameid;
  2112. ditem->amount = 1;
  2113. ditem->m = md->bl.m;
  2114. ditem->x = md->bl.x;
  2115. ditem->y = md->bl.y;
  2116. ditem->first_sd = mvp_sd;
  2117. ditem->second_sd = second_sd;
  2118. ditem->third_sd = third_sd;
  2119. add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
  2120. }
  2121. #ifndef TXT_ONLY
  2122. if(log_config.drop > 0)
  2123. log_drop(mvp_sd, md->class, log_item);
  2124. #endif
  2125. // Ore Discovery [Celest]
  2126. if (pc_checkskill(sd,BS_FINDINGORE)>0 && 1 >= rand()%1000) {
  2127. struct delay_item_drop *ditem;
  2128. int itemid[17] = { 714, 756, 757, 969, 984, 985, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1002 };
  2129. ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
  2130. ditem->nameid = itemid[rand()%17];
  2131. log_item[i] = ditem->nameid;
  2132. ditem->amount = 1;
  2133. ditem->m = md->bl.m;
  2134. ditem->x = md->bl.x;
  2135. ditem->y = md->bl.y;
  2136. ditem->first_sd = mvp_sd;
  2137. ditem->second_sd = second_sd;
  2138. ditem->third_sd = third_sd;
  2139. add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
  2140. }
  2141. #ifndef TXT_ONLY
  2142. if(log_config.drop > 0)
  2143. log_drop(mvp_sd, md->class, log_item);
  2144. #endif
  2145. if(sd && sd->state.attack_type == BF_WEAPON) {
  2146. for(i=0;i<sd->monster_drop_item_count;i++) {
  2147. struct delay_item_drop *ditem;
  2148. int race = battle_get_race(&md->bl);
  2149. if(sd->monster_drop_itemid[i] <= 0)
  2150. continue;
  2151. if(sd->monster_drop_race[i] & (1<<race) ||
  2152. (mob_db[md->class].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) ||
  2153. (!(mob_db[md->class].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) {
  2154. if(sd->monster_drop_itemrate[i] <= rand()%10000)
  2155. continue;
  2156. ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
  2157. ditem->nameid = sd->monster_drop_itemid[i];
  2158. ditem->amount = 1;
  2159. ditem->m = md->bl.m;
  2160. ditem->x = md->bl.x;
  2161. ditem->y = md->bl.y;
  2162. ditem->first_sd = mvp_sd;
  2163. ditem->second_sd = second_sd;
  2164. ditem->third_sd = third_sd;
  2165. add_timer(tick+520+i,mob_delay_item_drop,(int)ditem,0);
  2166. }
  2167. }
  2168. if(sd->get_zeny_num > 0)
  2169. pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%(sd->get_zeny_num+1));
  2170. }
  2171. if(md->lootitem) {
  2172. for(i=0;i<md->lootitem_count;i++) {
  2173. struct delay_item_drop2 *ditem;
  2174. ditem=(struct delay_item_drop2 *)aCalloc(1,sizeof(struct delay_item_drop2));
  2175. memcpy(&ditem->item_data,&md->lootitem[i],sizeof(md->lootitem[0]));
  2176. ditem->m = md->bl.m;
  2177. ditem->x = md->bl.x;
  2178. ditem->y = md->bl.y;
  2179. ditem->first_sd = mvp_sd;
  2180. ditem->second_sd = second_sd;
  2181. ditem->third_sd = third_sd;
  2182. add_timer(tick+540+i,mob_delay_item_drop2,(int)ditem,0);
  2183. }
  2184. }
  2185. }
  2186. // mvp処理
  2187. if(mvp_sd && mob_db[md->class].mexp > 0 ){
  2188. int log_mvp[2] = {0};
  2189. int j;
  2190. int mexp;
  2191. temp = ((double)mob_db[md->class].mexp * (double)battle_config.mvp_exp_rate * (9.+(double)count)/1000.);
  2192. mexp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2193. if(mexp < 1) mexp = 1;
  2194. clif_mvp_effect(mvp_sd); // エフェクト
  2195. clif_mvp_exp(mvp_sd,mexp);
  2196. pc_gainexp(mvp_sd,mexp,0);
  2197. log_mvp[1] = mexp;
  2198. for(j=0;j<3;j++){
  2199. i = rand() % 3;
  2200. if(mob_db[md->class].mvpitem[i].nameid <= 0)
  2201. continue;
  2202. drop_rate = mob_db[md->class].mvpitem[i].p;
  2203. if(drop_rate <= 0 && battle_config.drop_rate0item)
  2204. drop_rate = 1;
  2205. if(drop_rate < battle_config.item_drop_mvp_min)
  2206. drop_rate = battle_config.item_drop_mvp_min;
  2207. if(drop_rate > battle_config.item_drop_mvp_max)
  2208. drop_rate = battle_config.item_drop_mvp_max;
  2209. if(drop_rate <= rand()%10000)
  2210. continue;
  2211. memset(&item,0,sizeof(item));
  2212. item.nameid=mob_db[md->class].mvpitem[i].nameid;
  2213. item.identify=!itemdb_isequip3(item.nameid);
  2214. clif_mvp_item(mvp_sd,item.nameid);
  2215. log_mvp[0] = item.nameid;
  2216. if(mvp_sd->weight*2 > mvp_sd->max_weight)
  2217. map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd,second_sd,third_sd,1);
  2218. else if((ret = pc_additem(mvp_sd,&item,1))) {
  2219. clif_additem(sd,0,0,ret);
  2220. map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd,second_sd,third_sd,1);
  2221. }
  2222. break;
  2223. }
  2224. #ifndef TXT_ONLY
  2225. if(log_config.mvpdrop > 0)
  2226. log_mvpdrop(mvp_sd, md->class, log_mvp);
  2227. #endif
  2228. }
  2229. } // [MouseJstr]
  2230. // <Agit> NPC Event [OnAgitBreak]
  2231. if(md->npc_event[0] && strcmp(((md->npc_event)+strlen(md->npc_event)-13),"::OnAgitBreak") == 0) {
  2232. printf("MOB.C: Run NPC_Event[OnAgitBreak].\n");
  2233. if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak]
  2234. guild_agit_break(md);
  2235. }
  2236. // SCRIPT実行
  2237. if(md->npc_event[0]){
  2238. // if(battle_config.battle_log)
  2239. // printf("mob_damage : run event : %s\n",md->npc_event);
  2240. if(src && src->type == BL_PET)
  2241. sd = ((struct pet_data *)src)->msd;
  2242. if(sd == NULL) {
  2243. if(mvp_sd != NULL)
  2244. sd = mvp_sd;
  2245. else {
  2246. struct map_session_data *tmpsd;
  2247. int i;
  2248. for(i=0;i<fd_max;i++){
  2249. if(session[i] && (tmpsd=session[i]->session_data) && tmpsd->state.auth) {
  2250. if(md->bl.m == tmpsd->bl.m) {
  2251. sd = tmpsd;
  2252. break;
  2253. }
  2254. }
  2255. }
  2256. }
  2257. }
  2258. if(sd)
  2259. npc_event(sd,md->npc_event,0);
  2260. }
  2261. clif_clearchar_area(&md->bl,1);
  2262. if(md->level) md->level=0;
  2263. map_delblock(&md->bl);
  2264. if(mob_get_viewclass(md->class) <= 1000)
  2265. clif_clearchar_delay(tick+3000,&md->bl,0);
  2266. mob_deleteslave(md);
  2267. mob_setdelayspawn(md->bl.id);
  2268. map_freeblock_unlock();
  2269. return 0;
  2270. }
  2271. /*==========================================
  2272. *
  2273. *------------------------------------------
  2274. */
  2275. int mob_class_change(struct mob_data *md,int *value)
  2276. {
  2277. unsigned int tick = gettick();
  2278. int i,c,hp_rate,max_hp,class,count = 0;
  2279. nullpo_retr(0, md);
  2280. nullpo_retr(0, value);
  2281. if(value[0]<=1000 || value[0]>2000)
  2282. return 0;
  2283. if(md->bl.prev == NULL) return 0;
  2284. while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
  2285. if(count < 1) return 0;
  2286. class = value[rand()%count];
  2287. if(class<=1000 || class>2000) return 0;
  2288. max_hp = battle_get_max_hp(&md->bl);
  2289. hp_rate = md->hp*100/max_hp;
  2290. clif_mob_class_change(md,class);
  2291. md->class = class;
  2292. max_hp = battle_get_max_hp(&md->bl);
  2293. if(battle_config.monster_class_change_full_recover==1) {
  2294. md->hp = max_hp;
  2295. memset(md->dmglog,0,sizeof(md->dmglog));
  2296. }
  2297. else
  2298. md->hp = max_hp*hp_rate/100;
  2299. if(md->hp > max_hp) md->hp = max_hp;
  2300. else if(md->hp < 1) md->hp = 1;
  2301. memcpy(md->name,mob_db[class].jname,24);
  2302. memset(&md->state,0,sizeof(md->state));
  2303. md->attacked_id = 0;
  2304. md->target_id = 0;
  2305. md->move_fail_count = 0;
  2306. md->speed = mob_db[md->class].speed;
  2307. md->def_ele = mob_db[md->class].element;
  2308. mob_changestate(md,MS_IDLE,0);
  2309. skill_castcancel(&md->bl,0);
  2310. md->state.skillstate = MSS_IDLE;
  2311. md->last_thinktime = tick;
  2312. md->next_walktime = tick+rand()%50+5000;
  2313. md->attackabletime = tick;
  2314. md->canmove_tick = tick;
  2315. md->sg_count=0;
  2316. for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
  2317. md->skilldelay[i] = c;
  2318. md->skillid=0;
  2319. md->skilllv=0;
  2320. if(md->lootitem == NULL && mob_db[class].mode&0x02)
  2321. md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  2322. skill_clear_unitgroup(&md->bl);
  2323. skill_cleartimerskill(&md->bl);
  2324. clif_clearchar_area(&md->bl,0);
  2325. clif_spawnmob(md);
  2326. return 0;
  2327. }
  2328. /*==========================================
  2329. * mob回復
  2330. *------------------------------------------
  2331. */
  2332. int mob_heal(struct mob_data *md,int heal)
  2333. {
  2334. int max_hp = battle_get_max_hp(&md->bl);
  2335. nullpo_retr(0, md);
  2336. md->hp += heal;
  2337. if( max_hp < md->hp )
  2338. md->hp = max_hp;
  2339. if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
  2340. struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
  2341. if(gc) {
  2342. if(md->bl.id==gc->GID0) gc->Ghp0=md->hp;
  2343. if(md->bl.id==gc->GID1) gc->Ghp1=md->hp;
  2344. if(md->bl.id==gc->GID2) gc->Ghp2=md->hp;
  2345. if(md->bl.id==gc->GID3) gc->Ghp3=md->hp;
  2346. if(md->bl.id==gc->GID4) gc->Ghp4=md->hp;
  2347. if(md->bl.id==gc->GID5) gc->Ghp5=md->hp;
  2348. if(md->bl.id==gc->GID6) gc->Ghp6=md->hp;
  2349. if(md->bl.id==gc->GID7) gc->Ghp7=md->hp;
  2350. }
  2351. } // end addition [Valaris]
  2352. return 0;
  2353. }
  2354. /*==========================================
  2355. * Added by RoVeRT
  2356. *------------------------------------------
  2357. */
  2358. int mob_warpslave_sub(struct block_list *bl,va_list ap)
  2359. {
  2360. struct mob_data *md=(struct mob_data *)bl;
  2361. int id,x,y;
  2362. id=va_arg(ap,int);
  2363. x=va_arg(ap,int);
  2364. y=va_arg(ap,int);
  2365. if( md->master_id==id ) {
  2366. mob_warp(md,-1,x,y,2);
  2367. }
  2368. return 0;
  2369. }
  2370. /*==========================================
  2371. * Added by RoVeRT
  2372. *------------------------------------------
  2373. */
  2374. int mob_warpslave(struct mob_data *md,int x, int y)
  2375. {
  2376. //printf("warp slave\n");
  2377. map_foreachinarea(mob_warpslave_sub, md->bl.m,
  2378. x-AREA_SIZE,y-AREA_SIZE,
  2379. x+AREA_SIZE,y+AREA_SIZE,BL_MOB,
  2380. md->bl.id, md->bl.x, md->bl.y );
  2381. return 0;
  2382. }
  2383. /*==========================================
  2384. * mobワープ
  2385. *------------------------------------------
  2386. */
  2387. int mob_warp(struct mob_data *md,int m,int x,int y,int type)
  2388. {
  2389. int i=0,c,xs=0,ys=0,bx=x,by=y;
  2390. nullpo_retr(0, md);
  2391. if( md->bl.prev==NULL )
  2392. return 0;
  2393. if( m<0 ) m=md->bl.m;
  2394. if(type >= 0) {
  2395. if(map[md->bl.m].flag.monster_noteleport)
  2396. return 0;
  2397. clif_clearchar_area(&md->bl,type);
  2398. }
  2399. skill_unit_out_all(&md->bl,gettick(),1);
  2400. map_delblock(&md->bl);
  2401. if(bx>0 && by>0){ // 位置指定の場合周囲9セルを探索
  2402. xs=ys=9;
  2403. }
  2404. while( ( x<0 || y<0 || ((c=read_gat(m,x,y))==1 || c==5) ) && (i++)<1000 ){
  2405. if( xs>0 && ys>0 && i<250 ){ // 指定位置付近の探索
  2406. x=bx+rand()%xs-xs/2;
  2407. y=by+rand()%ys-ys/2;
  2408. }else{ // 完全ランダム探索
  2409. x=rand()%(map[m].xs-2)+1;
  2410. y=rand()%(map[m].ys-2)+1;
  2411. }
  2412. }
  2413. md->dir=0;
  2414. if(i<1000){
  2415. md->bl.x=md->to_x=x;
  2416. md->bl.y=md->to_y=y;
  2417. md->bl.m=m;
  2418. }else {
  2419. m=md->bl.m;
  2420. if(battle_config.error_log==1)
  2421. printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class);
  2422. }
  2423. md->target_id=0; // タゲを解除する
  2424. md->state.targettype=NONE_ATTACKABLE;
  2425. md->attacked_id=0;
  2426. md->state.skillstate=MSS_IDLE;
  2427. mob_changestate(md,MS_IDLE,0);
  2428. if(type>0 && i==1000) {
  2429. if(battle_config.battle_log)
  2430. printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class);
  2431. }
  2432. map_addblock(&md->bl);
  2433. if(type>0)
  2434. {
  2435. clif_spawnmob(md);
  2436. mob_warpslave(md,md->bl.x,md->bl.y);
  2437. }
  2438. return 0;
  2439. }
  2440. /*==========================================
  2441. * 画面内の取り巻きの数計算用(foreachinarea)
  2442. *------------------------------------------
  2443. */
  2444. int mob_countslave_sub(struct block_list *bl,va_list ap)
  2445. {
  2446. int id,*c;
  2447. struct mob_data *md;
  2448. id=va_arg(ap,int);
  2449. nullpo_retr(0, bl);
  2450. nullpo_retr(0, ap);
  2451. nullpo_retr(0, c=va_arg(ap,int *));
  2452. nullpo_retr(0, md = (struct mob_data *)bl);
  2453. if( md->master_id==id )
  2454. (*c)++;
  2455. return 0;
  2456. }
  2457. /*==========================================
  2458. * 画面内の取り巻きの数計算
  2459. *------------------------------------------
  2460. */
  2461. int mob_countslave(struct mob_data *md)
  2462. {
  2463. int c=0;
  2464. nullpo_retr(0, md);
  2465. map_foreachinarea(mob_countslave_sub, md->bl.m,
  2466. 0,0,map[md->bl.m].xs-1,map[md->bl.m].ys-1,
  2467. BL_MOB,md->bl.id,&c);
  2468. return c;
  2469. }
  2470. /*==========================================
  2471. * 手下MOB召喚
  2472. *------------------------------------------
  2473. */
  2474. int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
  2475. {
  2476. struct mob_data *md;
  2477. int bx,by,m,count = 0,class,k,a = amount;
  2478. nullpo_retr(0, md2);
  2479. nullpo_retr(0, value);
  2480. bx=md2->bl.x;
  2481. by=md2->bl.y;
  2482. m=md2->bl.m;
  2483. if(value[0]<=1000 || value[0]>2000) // 値が異常なら召喚を止める
  2484. return 0;
  2485. while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
  2486. if(count < 1) return 0;
  2487. for(k=0;k<count;k++) {
  2488. amount = a;
  2489. class = value[k];
  2490. if(class<=1000 || class>2000) continue;
  2491. for(;amount>0;amount--){
  2492. int x=0,y=0,c=0,i=0;
  2493. md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
  2494. if(mob_db[class].mode&0x02)
  2495. md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  2496. else
  2497. md->lootitem=NULL;
  2498. while((x<=0 || y<=0 || (c=map_getcell(m,x,y))==1 || c==5 ) && (i++)<100){
  2499. x=rand()%9-4+bx;
  2500. y=rand()%9-4+by;
  2501. }
  2502. if(i>=100){
  2503. x=bx;
  2504. y=by;
  2505. }
  2506. mob_spawn_dataset(md,"--ja--",class);
  2507. md->bl.m=m;
  2508. md->bl.x=x;
  2509. md->bl.y=y;
  2510. md->m =m;
  2511. md->x0=x;
  2512. md->y0=y;
  2513. md->xs=0;
  2514. md->ys=0;
  2515. md->speed=md2->speed;
  2516. md->spawndelay1=-1; // 一度のみフラグ
  2517. md->spawndelay2=-1; // 一度のみフラグ
  2518. memset(md->npc_event,0,sizeof(md->npc_event));
  2519. md->bl.type=BL_MOB;
  2520. map_addiddb(&md->bl);
  2521. mob_spawn(md->bl.id);
  2522. clif_skill_nodamage(&md->bl,&md->bl,(flag)? NPC_SUMMONSLAVE:NPC_SUMMONMONSTER,a,1);
  2523. if(flag)
  2524. md->master_id=md2->bl.id;
  2525. }
  2526. }
  2527. return 0;
  2528. }
  2529. /*==========================================
  2530. * 自分をロックしているPCの数を数える(foreachclient)
  2531. *------------------------------------------
  2532. */
  2533. static int mob_counttargeted_sub(struct block_list *bl,va_list ap)
  2534. {
  2535. int id,*c,target_lv;
  2536. struct block_list *src;
  2537. id=va_arg(ap,int);
  2538. nullpo_retr(0, bl);
  2539. nullpo_retr(0, ap);
  2540. nullpo_retr(0, c=va_arg(ap,int *));
  2541. src=va_arg(ap,struct block_list *);
  2542. target_lv=va_arg(ap,int);
  2543. if(id == bl->id || (src && id == src->id)) return 0;
  2544. if(bl->type == BL_PC) {
  2545. struct map_session_data *sd = (struct map_session_data *)bl;
  2546. if(sd && sd->attacktarget == id && sd->attacktimer != -1 && sd->attacktarget_lv >= target_lv)
  2547. (*c)++;
  2548. }
  2549. else if(bl->type == BL_MOB) {
  2550. struct mob_data *md = (struct mob_data *)bl;
  2551. if(md && md->target_id == id && md->timer != -1 && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
  2552. (*c)++;
  2553. }
  2554. else if(bl->type == BL_PET) {
  2555. struct pet_data *pd = (struct pet_data *)bl;
  2556. if(pd->target_id == id && pd->timer != -1 && pd->state.state == MS_ATTACK && pd->target_lv >= target_lv)
  2557. (*c)++;
  2558. }
  2559. return 0;
  2560. }
  2561. /*==========================================
  2562. * 自分をロックしているPCの数を数える
  2563. *------------------------------------------
  2564. */
  2565. int mob_counttargeted(struct mob_data *md,struct block_list *src,int target_lv)
  2566. {
  2567. int c=0;
  2568. nullpo_retr(0, md);
  2569. map_foreachinarea(mob_counttargeted_sub, md->bl.m,
  2570. md->bl.x-AREA_SIZE,md->bl.y-AREA_SIZE,
  2571. md->bl.x+AREA_SIZE,md->bl.y+AREA_SIZE,0,md->bl.id,&c,src,target_lv);
  2572. return c;
  2573. }
  2574. /*==========================================
  2575. *MOBskillから該当skillidのskillidxを返す
  2576. *------------------------------------------
  2577. */
  2578. int mob_skillid2skillidx(int class,int skillid)
  2579. {
  2580. int i;
  2581. struct mob_skill *ms=mob_db[class].skill;
  2582. if(ms==NULL)
  2583. return -1;
  2584. for(i=0;i<mob_db[class].maxskill;i++){
  2585. if(ms[i].skill_id == skillid)
  2586. return i;
  2587. }
  2588. return -1;
  2589. }
  2590. //
  2591. // MOBスキル
  2592. //
  2593. /*==========================================
  2594. * スキル使用(詠唱完了、ID指定)
  2595. *------------------------------------------
  2596. */
  2597. int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
  2598. {
  2599. struct mob_data* md=NULL;
  2600. struct block_list *bl;
  2601. struct block_list *mbl;
  2602. int range;
  2603. if((mbl = map_id2bl(id)) == NULL ) //詠唱したMobがもういないというのは良くある正常処理
  2604. return 0;
  2605. if((md=(struct mob_data *)mbl) == NULL ){
  2606. printf("mobskill_castend_id nullpo mbl->id:%d\n",mbl->id);
  2607. return 0;
  2608. }
  2609. if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
  2610. return 0;
  2611. if( md->skilltimer != tid ) // タイマIDの確認
  2612. return 0;
  2613. md->skilltimer=-1;
  2614. //沈黙や状態異常など
  2615. if(md->sc_data){
  2616. if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
  2617. return 0;
  2618. if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  2619. return 0;
  2620. if(md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  2621. return 0;
  2622. if(md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  2623. return 0;
  2624. }
  2625. if(md->skillid != NPC_EMOTION)
  2626. md->last_thinktime=tick + battle_get_adelay(&md->bl);
  2627. if((bl = map_id2bl(md->skilltarget)) == NULL || bl->prev==NULL){ //スキルターゲットが存在しない
  2628. //printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
  2629. return 0;
  2630. }
  2631. if(md->bl.m != bl->m)
  2632. return 0;
  2633. if(md->skillid == PR_LEXAETERNA) {
  2634. struct status_change *sc_data = battle_get_sc_data(bl);
  2635. if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)))
  2636. return 0;
  2637. }
  2638. else if(md->skillid == RG_BACKSTAP) {
  2639. int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
  2640. int dist = distance(md->bl.x,md->bl.y,bl->x,bl->y);
  2641. if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir)))
  2642. return 0;
  2643. }
  2644. if( ( (skill_get_inf(md->skillid)&1) || (skill_get_inf2(md->skillid)&4) ) && // 彼我敵対関係チェック
  2645. battle_check_target(&md->bl,bl, BCT_ENEMY)<=0 )
  2646. return 0;
  2647. range = skill_get_range(md->skillid,md->skilllv);
  2648. if(range < 0)
  2649. range = battle_get_range(&md->bl) - (range + 1);
  2650. if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,bl->x,bl->y))
  2651. return 0;
  2652. md->skilldelay[md->skillidx]=tick;
  2653. if(battle_config.mob_skill_log)
  2654. printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
  2655. // mob_stop_walking(md,0);
  2656. switch( skill_get_nk(md->skillid) )
  2657. {
  2658. // 攻撃系/吹き飛ばし系
  2659. case 0: case 2:
  2660. skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
  2661. break;
  2662. case 1:// 支援系
  2663. if(!mob_db[md->class].skill[md->skillidx].val[0] &&
  2664. (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) )
  2665. skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
  2666. else
  2667. skill_castend_nodamage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
  2668. break;
  2669. }
  2670. return 0;
  2671. }
  2672. /*==========================================
  2673. * スキル使用(詠唱完了、場所指定)
  2674. *------------------------------------------
  2675. */
  2676. int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
  2677. {
  2678. struct mob_data* md=NULL;
  2679. struct block_list *bl;
  2680. int range,maxcount;
  2681. //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
  2682. if((bl=map_id2bl(id))==NULL)
  2683. return 0;
  2684. nullpo_retr(0, md=(struct mob_data *)bl);
  2685. if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
  2686. return 0;
  2687. if( md->skilltimer != tid ) // タイマIDの確認
  2688. return 0;
  2689. md->skilltimer=-1;
  2690. if(md->sc_data){
  2691. if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
  2692. return 0;
  2693. if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  2694. return 0;
  2695. if(md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  2696. return 0;
  2697. if(md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  2698. return 0;
  2699. }
  2700. if(battle_config.monster_skill_reiteration == 0) {
  2701. range = -1;
  2702. switch(md->skillid) {
  2703. case MG_SAFETYWALL:
  2704. case WZ_FIREPILLAR:
  2705. case HT_SKIDTRAP:
  2706. case HT_LANDMINE:
  2707. case HT_ANKLESNARE:
  2708. case HT_SHOCKWAVE:
  2709. case HT_SANDMAN:
  2710. case HT_FLASHER:
  2711. case HT_FREEZINGTRAP:
  2712. case HT_BLASTMINE:
  2713. case HT_CLAYMORETRAP:
  2714. case PF_SPIDERWEB: /* スパイダーウェッブ */
  2715. range = 0;
  2716. break;
  2717. case AL_PNEUMA:
  2718. case AL_WARP:
  2719. range = 1;
  2720. break;
  2721. }
  2722. if(range >= 0) {
  2723. if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0)
  2724. return 0;
  2725. }
  2726. }
  2727. if(battle_config.monster_skill_nofootset) {
  2728. range = -1;
  2729. switch(md->skillid) {
  2730. case WZ_FIREPILLAR:
  2731. case HT_SKIDTRAP:
  2732. case HT_LANDMINE:
  2733. case HT_ANKLESNARE:
  2734. case HT_SHOCKWAVE:
  2735. case HT_SANDMAN:
  2736. case HT_FLASHER:
  2737. case HT_FREEZINGTRAP:
  2738. case HT_BLASTMINE:
  2739. case HT_CLAYMORETRAP:
  2740. case AM_DEMONSTRATION:
  2741. case PF_SPIDERWEB: /* スパイダーウェッブ */
  2742. range = 1;
  2743. break;
  2744. case AL_WARP:
  2745. range = 0;
  2746. break;
  2747. }
  2748. if(range >= 0) {
  2749. if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0)
  2750. return 0;
  2751. }
  2752. }
  2753. if(battle_config.monster_land_skill_limit) {
  2754. maxcount = skill_get_maxcount(md->skillid);
  2755. if(maxcount > 0) {
  2756. int i,c;
  2757. for(i=c=0;i<MAX_MOBSKILLUNITGROUP;i++) {
  2758. if(md->skillunit[i].alive_count > 0 && md->skillunit[i].skill_id == md->skillid)
  2759. c++;
  2760. }
  2761. if(c >= maxcount)
  2762. return 0;
  2763. }
  2764. }
  2765. range = skill_get_range(md->skillid,md->skilllv);
  2766. if(range < 0)
  2767. range = battle_get_range(&md->bl) - (range + 1);
  2768. if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,md->skillx,md->skilly))
  2769. return 0;
  2770. md->skilldelay[md->skillidx]=tick;
  2771. if(battle_config.mob_skill_log)
  2772. printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
  2773. // mob_stop_walking(md,0);
  2774. skill_castend_pos2(&md->bl,md->skillx,md->skilly,md->skillid,md->skilllv,tick,0);
  2775. return 0;
  2776. }
  2777. /*==========================================
  2778. * Skill use (an aria start, ID specification)
  2779. *------------------------------------------
  2780. */
  2781. int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
  2782. {
  2783. int casttime,range;
  2784. struct mob_skill *ms;
  2785. int skill_id, skill_lv, forcecast = 0;
  2786. nullpo_retr(0, md);
  2787. nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
  2788. if( target==NULL && (target=map_id2bl(md->target_id))==NULL )
  2789. return 0;
  2790. if( target->prev==NULL || md->bl.prev==NULL )
  2791. return 0;
  2792. skill_id=ms->skill_id;
  2793. skill_lv=ms->skill_lv;
  2794. // 沈黙や異常
  2795. if(md->sc_data){
  2796. if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
  2797. return 0;
  2798. if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  2799. return 0;
  2800. if(md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  2801. return 0;
  2802. if(md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  2803. return 0;
  2804. }
  2805. if(md->option&4 && skill_id==TF_HIDING)
  2806. return 0;
  2807. if(md->option&2 && skill_id!=TF_HIDING && skill_id!=AS_GRIMTOOTH && skill_id!=RG_BACKSTAP && skill_id!=RG_RAID)
  2808. return 0;
  2809. if(map[md->bl.m].flag.gvg && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT || skill_id == AL_WARP ||
  2810. skill_id == WZ_ICEWALL || skill_id == TF_BACKSLIDING))
  2811. return 0;
  2812. if(skill_get_inf2(skill_id)&0x200 && md->bl.id == target->id)
  2813. return 0;
  2814. // 射程と障害物チェック
  2815. range = skill_get_range(skill_id,skill_lv);
  2816. if(range < 0)
  2817. range = battle_get_range(&md->bl) - (range + 1);
  2818. if(!battle_check_range(&md->bl,target,range))
  2819. return 0;
  2820. // delay=skill_delayfix(&md->bl, skill_get_delay( skill_id,skill_lv) );
  2821. casttime=skill_castfix(&md->bl,ms->casttime);
  2822. md->state.skillcastcancel=ms->cancel;
  2823. md->skilldelay[skill_idx]=gettick();
  2824. switch(skill_id){ /* 何か特殊な処理が必要 */
  2825. case ALL_RESURRECTION: /* リザレクション */
  2826. if(target->type != BL_PC && battle_check_undead(battle_get_race(target),battle_get_elem_type(target))){ /* 敵がアンデッドなら */
  2827. forcecast=1; /* ターンアンデットと同じ詠唱時間 */
  2828. casttime=skill_castfix(&md->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
  2829. }
  2830. break;
  2831. case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/
  2832. case SA_MAGICROD:
  2833. case SA_SPELLBREAKER:
  2834. forcecast=1;
  2835. break;
  2836. }
  2837. if(battle_config.mob_skill_log)
  2838. printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class);
  2839. if(casttime>0 || forcecast){ // 詠唱が必要
  2840. // struct mob_data *md2;
  2841. mob_stop_walking(md,0); // 歩行停止
  2842. clif_skillcasting( &md->bl,
  2843. md->bl.id, target->id, 0,0, skill_id,casttime);
  2844. // 詠唱反応モンスター
  2845. /* if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->class].mode&0x10 &&
  2846. md2->state.state!=MS_ATTACK){
  2847. md2->target_id=md->bl.id;
  2848. md->state.targettype = ATTACKABLE;
  2849. md2->min_chase=13;
  2850. }*/
  2851. }
  2852. if( casttime<=0 ) // 詠唱の無いものはキャンセルされない
  2853. md->state.skillcastcancel=0;
  2854. md->skilltarget = target->id;
  2855. md->skillx = 0;
  2856. md->skilly = 0;
  2857. md->skillid = skill_id;
  2858. md->skilllv = skill_lv;
  2859. md->skillidx = skill_idx;
  2860. if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
  2861. skill_status_change_end(&md->bl,SC_CLOAKING,-1);
  2862. if( casttime>0 ){
  2863. md->skilltimer =
  2864. add_timer( gettick()+casttime, mobskill_castend_id, md->bl.id, 0 );
  2865. }else{
  2866. md->skilltimer = -1;
  2867. mobskill_castend_id(md->skilltimer,gettick(),md->bl.id, 0);
  2868. }
  2869. return 1;
  2870. }
  2871. /*==========================================
  2872. * スキル使用(場所指定)
  2873. *------------------------------------------
  2874. */
  2875. int mobskill_use_pos( struct mob_data *md,
  2876. int skill_x, int skill_y, int skill_idx)
  2877. {
  2878. int casttime=0,range;
  2879. struct mob_skill *ms;
  2880. struct block_list bl;
  2881. int skill_id, skill_lv;
  2882. nullpo_retr(0, md);
  2883. nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
  2884. if( md->bl.prev==NULL )
  2885. return 0;
  2886. skill_id=ms->skill_id;
  2887. skill_lv=ms->skill_lv;
  2888. //沈黙や状態異常など
  2889. if(md->sc_data){
  2890. if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
  2891. return 0;
  2892. if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
  2893. return 0;
  2894. if(md->sc_data[SC_BLADESTOP].timer != -1) //白刃取り
  2895. return 0;
  2896. if(md->sc_data[SC_BERSERK].timer != -1) //バーサーク
  2897. return 0;
  2898. }
  2899. if(md->option&2)
  2900. return 0;
  2901. if(map[md->bl.m].flag.gvg && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT || skill_id == AL_WARP ||
  2902. skill_id == WZ_ICEWALL || skill_id == TF_BACKSLIDING))
  2903. return 0;
  2904. // 射程と障害物チェック
  2905. bl.type = BL_NUL;
  2906. bl.m = md->bl.m;
  2907. bl.x = skill_x;
  2908. bl.y = skill_y;
  2909. range = skill_get_range(skill_id,skill_lv);
  2910. if(range < 0)
  2911. range = battle_get_range(&md->bl) - (range + 1);
  2912. if(!battle_check_range(&md->bl,&bl,range))
  2913. return 0;
  2914. // delay=skill_delayfix(&sd->bl, skill_get_delay( skill_id,skill_lv) );
  2915. casttime=skill_castfix(&md->bl,ms->casttime);
  2916. md->skilldelay[skill_idx]=gettick();
  2917. md->state.skillcastcancel=ms->cancel;
  2918. if(battle_config.mob_skill_log)
  2919. printf("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n",
  2920. skill_x,skill_y,skill_id,skill_lv,casttime,md->class);
  2921. if( casttime>0 ) { // A cast time is required.
  2922. mob_stop_walking(md,0); // 歩行停止
  2923. clif_skillcasting( &md->bl,
  2924. md->bl.id, 0, skill_x,skill_y, skill_id,casttime);
  2925. }
  2926. if( casttime<=0 ) // A skill without a cast time wont be cancelled.
  2927. md->state.skillcastcancel=0;
  2928. md->skillx = skill_x;
  2929. md->skilly = skill_y;
  2930. md->skilltarget = 0;
  2931. md->skillid = skill_id;
  2932. md->skilllv = skill_lv;
  2933. md->skillidx = skill_idx;
  2934. if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
  2935. skill_status_change_end(&md->bl,SC_CLOAKING,-1);
  2936. if( casttime>0 ){
  2937. md->skilltimer =
  2938. add_timer( gettick()+casttime, mobskill_castend_pos, md->bl.id, 0 );
  2939. }else{
  2940. md->skilltimer = -1;
  2941. mobskill_castend_pos(md->skilltimer,gettick(),md->bl.id, 0);
  2942. }
  2943. return 1;
  2944. }
  2945. /*==========================================
  2946. * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
  2947. *------------------------------------------
  2948. */
  2949. int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap)
  2950. {
  2951. int rate;
  2952. struct mob_data **fr, *md, *mmd;
  2953. nullpo_retr(0, bl);
  2954. nullpo_retr(0, ap);
  2955. nullpo_retr(0, mmd=va_arg(ap,struct mob_data *));
  2956. md=(struct mob_data *)bl;
  2957. if( mmd->bl.id == bl->id )
  2958. return 0;
  2959. rate=va_arg(ap,int);
  2960. fr=va_arg(ap,struct mob_data **);
  2961. if( md->hp < mob_db[md->class].max_hp*rate/100 )
  2962. (*fr)=md;
  2963. return 0;
  2964. }
  2965. struct mob_data *mob_getfriendhpltmaxrate(struct mob_data *md,int rate)
  2966. {
  2967. struct mob_data *fr=NULL;
  2968. const int r=8;
  2969. nullpo_retr(NULL, md);
  2970. map_foreachinarea(mob_getfriendhpltmaxrate_sub, md->bl.m,
  2971. md->bl.x-r ,md->bl.y-r, md->bl.x+r, md->bl.y+r,
  2972. BL_MOB,md,rate,&fr);
  2973. return fr;
  2974. }
  2975. /*==========================================
  2976. * What a status state suits by nearby MOB is looked for.
  2977. *------------------------------------------
  2978. */
  2979. int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
  2980. {
  2981. int cond1,cond2;
  2982. struct mob_data **fr, *md, *mmd;
  2983. int flag=0;
  2984. nullpo_retr(0, bl);
  2985. nullpo_retr(0, ap);
  2986. nullpo_retr(0, md=(struct mob_data *)bl);
  2987. nullpo_retr(0, mmd=va_arg(ap,struct mob_data *));
  2988. if( mmd->bl.id == bl->id )
  2989. return 0;
  2990. cond1=va_arg(ap,int);
  2991. cond2=va_arg(ap,int);
  2992. fr=va_arg(ap,struct mob_data **);
  2993. if( cond2==-1 ){
  2994. int j;
  2995. for(j=SC_STONE;j<=SC_BLIND && !flag;j++){
  2996. flag=(md->sc_data[j].timer!=-1 );
  2997. }
  2998. }else
  2999. flag=( md->sc_data[cond2].timer!=-1 );
  3000. if( flag^( cond1==MSC_FRIENDSTATUSOFF ) )
  3001. (*fr)=md;
  3002. return 0;
  3003. }
  3004. struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2)
  3005. {
  3006. struct mob_data *fr=NULL;
  3007. const int r=8;
  3008. nullpo_retr(0, md);
  3009. map_foreachinarea(mob_getfriendstatus_sub, md->bl.m,
  3010. md->bl.x-r ,md->bl.y-r, md->bl.x+r, md->bl.y+r,
  3011. BL_MOB,md,cond1,cond2,&fr);
  3012. return fr;
  3013. }
  3014. /*==========================================
  3015. * Skill use judging
  3016. *------------------------------------------
  3017. */
  3018. int mobskill_use(struct mob_data *md,unsigned int tick,int event)
  3019. {
  3020. struct mob_skill *ms;
  3021. // struct block_list *target=NULL;
  3022. int i,max_hp;
  3023. nullpo_retr(0, md);
  3024. nullpo_retr(0, ms = mob_db[md->class].skill);
  3025. max_hp = battle_get_max_hp(&md->bl);
  3026. if(battle_config.mob_skill_use == 0 || md->skilltimer != -1)
  3027. return 0;
  3028. if(md->state.special_mob_ai)
  3029. return 0;
  3030. if(md->sc_data[SC_SELFDESTRUCTION].timer!=-1) //自爆中はスキルを使わない
  3031. return 0;
  3032. for(i=0;i<mob_db[md->class].maxskill;i++){
  3033. int c2=ms[i].cond2,flag=0;
  3034. struct mob_data *fmd=NULL;
  3035. // ディレイ中
  3036. if( DIFF_TICK(tick,md->skilldelay[i])<ms[i].delay )
  3037. continue;
  3038. // 状態判定
  3039. if( ms[i].state>=0 && ms[i].state!=md->state.skillstate )
  3040. continue;
  3041. // 条件判定
  3042. flag=(event==ms[i].cond1);
  3043. if(!flag){
  3044. switch( ms[i].cond1 ){
  3045. case MSC_ALWAYS:
  3046. flag=1; break;
  3047. case MSC_MYHPLTMAXRATE: // HP< maxhp%
  3048. flag=( md->hp < max_hp*c2/100 ); break;
  3049. case MSC_MYSTATUSON: // status[num] on
  3050. case MSC_MYSTATUSOFF: // status[num] off
  3051. if( ms[i].cond2==-1 ){
  3052. int j;
  3053. for(j=SC_STONE;j<=SC_BLIND && !flag;j++){
  3054. flag=(md->sc_data[j].timer!=-1 );
  3055. }
  3056. }else
  3057. flag=( md->sc_data[ms[i].cond2].timer!=-1 );
  3058. flag^=( ms[i].cond1==MSC_MYSTATUSOFF ); break;
  3059. case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
  3060. flag=(( fmd=mob_getfriendhpltmaxrate(md,ms[i].cond2) )!=NULL ); break;
  3061. case MSC_FRIENDSTATUSON: // friend status[num] on
  3062. case MSC_FRIENDSTATUSOFF: // friend status[num] off
  3063. flag=(( fmd=mob_getfriendstatus(md,ms[i].cond1,ms[i].cond2) )!=NULL ); break;
  3064. case MSC_SLAVELT: // slave < num
  3065. flag=( mob_countslave(md) < c2 ); break;
  3066. case MSC_ATTACKPCGT: // attack pc > num
  3067. flag=( mob_counttargeted(md,NULL,0) > c2 ); break;
  3068. case MSC_SLAVELE: // slave <= num
  3069. flag=( mob_countslave(md) <= c2 ); break;
  3070. case MSC_ATTACKPCGE: // attack pc >= num
  3071. flag=( mob_counttargeted(md,NULL,0) >= c2 ); break;
  3072. case MSC_SKILLUSED: // specificated skill used
  3073. flag=( (event&0xffff)==MSC_SKILLUSED && ((event>>16)==c2 || c2==0)); break;
  3074. }
  3075. }
  3076. // 確率判定
  3077. if( flag && rand()%10000 < ms[i].permillage ){
  3078. if( skill_get_inf(ms[i].skill_id)&2 ){
  3079. // 場所指定
  3080. struct block_list *bl = NULL;
  3081. int x=0,y=0;
  3082. if( ms[i].target<=MST_AROUND ){
  3083. bl= ((ms[i].target==MST_TARGET || ms[i].target==MST_AROUND5)? map_id2bl(md->target_id):
  3084. (ms[i].target==MST_FRIEND)? &fmd->bl : &md->bl);
  3085. if(bl!=NULL){
  3086. x=bl->x; y=bl->y;
  3087. }
  3088. }
  3089. if( x<=0 || y<=0 )
  3090. continue;
  3091. // 自分の周囲
  3092. if( ms[i].target>=MST_AROUND1 ){
  3093. int bx=x, by=y, i=0, c, m=bl->m, r=ms[i].target-MST_AROUND1;
  3094. do{
  3095. bx=x + rand()%(r*2+3) - r;
  3096. by=y + rand()%(r*2+3) - r;
  3097. }while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
  3098. ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
  3099. if(i<1000){
  3100. x=bx; y=by;
  3101. }
  3102. }
  3103. // 相手の周囲
  3104. if( ms[i].target>=MST_AROUND5 ){
  3105. int bx=x, by=y, i=0, c, m=bl->m, r=(ms[i].target-MST_AROUND5)+1;
  3106. do{
  3107. bx=x + rand()%(r*2+1) - r;
  3108. by=y + rand()%(r*2+1) - r;
  3109. }while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
  3110. ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
  3111. if(i<1000){
  3112. x=bx; y=by;
  3113. }
  3114. }
  3115. if(!mobskill_use_pos(md,x,y,i))
  3116. return 0;
  3117. }else{
  3118. // ID指定
  3119. if( ms[i].target<=MST_FRIEND ){
  3120. struct block_list *bl = NULL;
  3121. bl= ((ms[i].target==MST_TARGET)? map_id2bl(md->target_id):
  3122. (ms[i].target==MST_FRIEND)? &fmd->bl : &md->bl);
  3123. if(bl && !mobskill_use_id(md,bl,i))
  3124. return 0;
  3125. }
  3126. }
  3127. if(ms[i].emotion >= 0)
  3128. clif_emotion(&md->bl,ms[i].emotion);
  3129. return 1;
  3130. }
  3131. }
  3132. return 0;
  3133. }
  3134. /*==========================================
  3135. * Skill use event processing
  3136. *------------------------------------------
  3137. */
  3138. int mobskill_event(struct mob_data *md,int flag)
  3139. {
  3140. nullpo_retr(0, md);
  3141. if(flag==-1 && mobskill_use(md,gettick(),MSC_CASTTARGETED))
  3142. return 1;
  3143. if( (flag&BF_SHORT) && mobskill_use(md,gettick(),MSC_CLOSEDATTACKED))
  3144. return 1;
  3145. if( (flag&BF_LONG) && mobskill_use(md,gettick(),MSC_LONGRANGEATTACKED))
  3146. return 1;
  3147. return 0;
  3148. }
  3149. /*==========================================
  3150. * Mobがエンペリウムなどの場合の判定
  3151. *------------------------------------------
  3152. */
  3153. int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl)
  3154. {
  3155. struct mob_data *md=NULL;
  3156. nullpo_retr(0,sd);
  3157. nullpo_retr(0,bl);
  3158. if(bl->type==BL_MOB && (md=(struct mob_data *)bl) &&
  3159. (md->class == 1288 || md->class == 1287 || md->class == 1286 || md->class == 1285))
  3160. {
  3161. struct guild_castle *gc=guild_mapname2gc(map[sd->bl.m].name);
  3162. struct guild *g=guild_search(sd->status.guild_id);
  3163. if(g == NULL && md->class == 1288)
  3164. return 0;//ギルド未加入ならダメージ無し
  3165. else if(gc != NULL && !map[sd->bl.m].flag.gvg)
  3166. return 0;//砦内でGvじゃないときはダメージなし
  3167. else if(g && gc != NULL && g->guild_id == gc->guild_id)
  3168. return 0;//自占領ギルドのエンペならダメージ無し
  3169. else if(g && guild_checkskill(g,GD_APPROVAL) <= 0 && md->class == 1288)
  3170. return 0;//正規ギルド承認がないとダメージ無し
  3171. }
  3172. return 1;
  3173. }
  3174. /*==========================================
  3175. * スキル用タイマー削除
  3176. *------------------------------------------
  3177. */
  3178. int mobskill_deltimer(struct mob_data *md )
  3179. {
  3180. nullpo_retr(0, md);
  3181. if( md->skilltimer!=-1 ){
  3182. if( skill_get_inf( md->skillid )&2 )
  3183. delete_timer( md->skilltimer, mobskill_castend_pos );
  3184. else
  3185. delete_timer( md->skilltimer, mobskill_castend_id );
  3186. md->skilltimer=-1;
  3187. }
  3188. return 0;
  3189. }
  3190. //
  3191. // 初期化
  3192. //
  3193. /*==========================================
  3194. * Since un-setting [ mob ] up was used, it is an initial provisional value setup.
  3195. *------------------------------------------
  3196. */
  3197. static int mob_makedummymobdb(int class)
  3198. {
  3199. int i;
  3200. sprintf(mob_db[class].name,"mob%d",class);
  3201. sprintf(mob_db[class].jname,"mob%d",class);
  3202. mob_db[class].lv=1;
  3203. mob_db[class].max_hp=1000;
  3204. mob_db[class].max_sp=1;
  3205. mob_db[class].base_exp=2;
  3206. mob_db[class].job_exp=1;
  3207. mob_db[class].range=1;
  3208. mob_db[class].atk1=7;
  3209. mob_db[class].atk2=10;
  3210. mob_db[class].def=0;
  3211. mob_db[class].mdef=0;
  3212. mob_db[class].str=1;
  3213. mob_db[class].agi=1;
  3214. mob_db[class].vit=1;
  3215. mob_db[class].int_=1;
  3216. mob_db[class].dex=6;
  3217. mob_db[class].luk=2;
  3218. mob_db[class].range2=10;
  3219. mob_db[class].range3=10;
  3220. mob_db[class].size=0;
  3221. mob_db[class].race=0;
  3222. mob_db[class].element=0;
  3223. mob_db[class].mode=0;
  3224. mob_db[class].speed=300;
  3225. mob_db[class].adelay=1000;
  3226. mob_db[class].amotion=500;
  3227. mob_db[class].dmotion=500;
  3228. mob_db[class].dropitem[0].nameid=909; // Jellopy
  3229. mob_db[class].dropitem[0].p=1000;
  3230. for(i=1;i<8;i++){
  3231. mob_db[class].dropitem[i].nameid=0;
  3232. mob_db[class].dropitem[i].p=0;
  3233. }
  3234. // Item1,Item2
  3235. mob_db[class].mexp=0;
  3236. mob_db[class].mexpper=0;
  3237. for(i=0;i<3;i++){
  3238. mob_db[class].mvpitem[i].nameid=0;
  3239. mob_db[class].mvpitem[i].p=0;
  3240. }
  3241. for(i=0;i<MAX_RANDOMMONSTER;i++)
  3242. mob_db[class].summonper[i]=0;
  3243. return 0;
  3244. }
  3245. /*==========================================
  3246. * db/mob_db.txt reading
  3247. *------------------------------------------
  3248. */
  3249. static int mob_readdb(void)
  3250. {
  3251. FILE *fp;
  3252. char line[1024];
  3253. char *filename[]={ "db/mob_db.txt","db/mob_db2.txt" };
  3254. int i;
  3255. memset(mob_db,0,sizeof(mob_db));
  3256. for(i=0;i<2;i++){
  3257. fp=fopen(filename[i],"r");
  3258. if(fp==NULL){
  3259. if(i>0)
  3260. continue;
  3261. return -1;
  3262. }
  3263. while(fgets(line,1020,fp)){
  3264. int class,i;
  3265. char *str[55],*p,*np;
  3266. if(line[0] == '/' && line[1] == '/')
  3267. continue;
  3268. for(i=0,p=line;i<55;i++){
  3269. if((np=strchr(p,','))!=NULL){
  3270. str[i]=p;
  3271. *np=0;
  3272. p=np+1;
  3273. } else
  3274. str[i]=p;
  3275. }
  3276. class=atoi(str[0]);
  3277. if(class<=1000 || class>2000)
  3278. continue;
  3279. mob_db[class].view_class=class;
  3280. memcpy(mob_db[class].name,str[1],24);
  3281. memcpy(mob_db[class].jname,str[2],24);
  3282. mob_db[class].lv=atoi(str[3]);
  3283. mob_db[class].max_hp=atoi(str[4]);
  3284. mob_db[class].max_sp=atoi(str[5]);
  3285. mob_db[class].base_exp=atoi(str[6]);
  3286. if(mob_db[class].base_exp < 0)
  3287. mob_db[class].base_exp = 0;
  3288. else if(mob_db[class].base_exp > 0 && (mob_db[class].base_exp*battle_config.base_exp_rate/100 > 1000000000 ||
  3289. mob_db[class].base_exp*battle_config.base_exp_rate/100 < 0))
  3290. mob_db[class].base_exp=1000000000;
  3291. else
  3292. mob_db[class].base_exp*= battle_config.base_exp_rate/100;
  3293. mob_db[class].job_exp=atoi(str[7]);
  3294. if(mob_db[class].job_exp < 0)
  3295. mob_db[class].job_exp = 0;
  3296. else if(mob_db[class].job_exp > 0 && (mob_db[class].job_exp*battle_config.job_exp_rate/100 > 1000000000 ||
  3297. mob_db[class].job_exp*battle_config.job_exp_rate/100 < 0))
  3298. mob_db[class].job_exp=1000000000;
  3299. else
  3300. mob_db[class].job_exp*=battle_config.job_exp_rate/100;
  3301. mob_db[class].range=atoi(str[8]);
  3302. mob_db[class].atk1=atoi(str[9]);
  3303. mob_db[class].atk2=atoi(str[10]);
  3304. mob_db[class].def=atoi(str[11]);
  3305. mob_db[class].mdef=atoi(str[12]);
  3306. mob_db[class].str=atoi(str[13]);
  3307. mob_db[class].agi=atoi(str[14]);
  3308. mob_db[class].vit=atoi(str[15]);
  3309. mob_db[class].int_=atoi(str[16]);
  3310. mob_db[class].dex=atoi(str[17]);
  3311. mob_db[class].luk=atoi(str[18]);
  3312. mob_db[class].range2=atoi(str[19]);
  3313. mob_db[class].range3=atoi(str[20]);
  3314. mob_db[class].size=atoi(str[21]);
  3315. mob_db[class].race=atoi(str[22]);
  3316. mob_db[class].element=atoi(str[23]);
  3317. mob_db[class].mode=atoi(str[24]);
  3318. mob_db[class].speed=atoi(str[25]);
  3319. mob_db[class].adelay=atoi(str[26]);
  3320. mob_db[class].amotion=atoi(str[27]);
  3321. mob_db[class].dmotion=atoi(str[28]);
  3322. for(i=0;i<8;i++){
  3323. int rate = 0,type,ratemin,ratemax;
  3324. mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
  3325. type = itemdb_type(mob_db[class].dropitem[i].nameid);
  3326. if (type == 0) { // Added [Valaris]
  3327. rate = battle_config.item_rate_heal;
  3328. ratemin = battle_config.item_drop_heal_min;
  3329. ratemax = battle_config.item_drop_heal_max;
  3330. }
  3331. else if (type == 2) {
  3332. rate = battle_config.item_rate_use;
  3333. ratemin = battle_config.item_drop_use_min;
  3334. ratemax = battle_config.item_drop_use_max; // End
  3335. }
  3336. else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
  3337. rate = battle_config.item_rate_equip;
  3338. ratemin = battle_config.item_drop_equip_min;
  3339. ratemax = battle_config.item_drop_equip_max;
  3340. }
  3341. else if (type == 6) {
  3342. rate = battle_config.item_rate_card;
  3343. ratemin = battle_config.item_drop_card_min;
  3344. ratemax = battle_config.item_drop_card_max;
  3345. }
  3346. else {
  3347. rate = battle_config.item_rate_common;
  3348. ratemin = battle_config.item_drop_common_min;
  3349. ratemax = battle_config.item_drop_common_max;
  3350. }
  3351. rate = (rate / 100) * atoi(str[30+i*2]);
  3352. rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
  3353. mob_db[class].dropitem[i].p = rate;
  3354. }
  3355. // Item1,Item2
  3356. mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
  3357. mob_db[class].mexpper=atoi(str[46]);
  3358. for(i=0;i<3;i++){
  3359. mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
  3360. mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
  3361. }
  3362. for(i=0;i<MAX_RANDOMMONSTER;i++)
  3363. mob_db[class].summonper[i]=0;
  3364. mob_db[class].maxskill=0;
  3365. mob_db[class].sex=0;
  3366. mob_db[class].hair=0;
  3367. mob_db[class].hair_color=0;
  3368. mob_db[class].weapon=0;
  3369. mob_db[class].shield=0;
  3370. mob_db[class].head_top=0;
  3371. mob_db[class].head_mid=0;
  3372. mob_db[class].head_buttom=0;
  3373. mob_db[class].clothes_color=0; //Add for player monster dye - Valaris
  3374. }
  3375. fclose(fp);
  3376. printf("read %s done\n",filename[i]);
  3377. }
  3378. return 0;
  3379. }
  3380. /*==========================================
  3381. * MOB display graphic change data reading
  3382. *------------------------------------------
  3383. */
  3384. static int mob_readdb_mobavail(void)
  3385. {
  3386. FILE *fp;
  3387. char line[1024];
  3388. int ln=0;
  3389. int class,j,k;
  3390. char *str[20],*p,*np;
  3391. if( (fp=fopen("db/mob_avail.txt","r"))==NULL ){
  3392. printf("can't read db/mob_avail.txt\n");
  3393. return -1;
  3394. }
  3395. while(fgets(line,1020,fp)){
  3396. if(line[0]=='/' && line[1]=='/')
  3397. continue;
  3398. memset(str,0,sizeof(str));
  3399. for(j=0,p=line;j<12;j++){
  3400. if((np=strchr(p,','))!=NULL){
  3401. str[j]=p;
  3402. *np=0;
  3403. p=np+1;
  3404. } else
  3405. str[j]=p;
  3406. }
  3407. if(str[0]==NULL)
  3408. continue;
  3409. class=atoi(str[0]);
  3410. if(class<=1000 || class>2000) // 値が異常なら処理しない。
  3411. continue;
  3412. k=atoi(str[1]);
  3413. if(k >= 0)
  3414. mob_db[class].view_class=k;
  3415. if((mob_db[class].view_class < 24) || (mob_db[class].view_class > 4000)) {
  3416. mob_db[class].sex=atoi(str[2]);
  3417. mob_db[class].hair=atoi(str[3]);
  3418. mob_db[class].hair_color=atoi(str[4]);
  3419. mob_db[class].weapon=atoi(str[5]);
  3420. mob_db[class].shield=atoi(str[6]);
  3421. mob_db[class].head_top=atoi(str[7]);
  3422. mob_db[class].head_mid=atoi(str[8]);
  3423. mob_db[class].head_buttom=atoi(str[9]);
  3424. mob_db[class].option=atoi(str[10])&~0x46;
  3425. mob_db[class].clothes_color=atoi(str[11]); // Monster player dye option - Valaris
  3426. }
  3427. else if(atoi(str[2]) > 0) mob_db[class].equip=atoi(str[2]); // mob equipment [Valaris]
  3428. ln++;
  3429. }
  3430. fclose(fp);
  3431. printf("read db/mob_avail.txt done (count=%d)\n",ln);
  3432. return 0;
  3433. }
  3434. /*==========================================
  3435. * Reading of random monster data
  3436. *------------------------------------------
  3437. */
  3438. static int mob_read_randommonster(void)
  3439. {
  3440. FILE *fp;
  3441. char line[1024];
  3442. char *str[10],*p;
  3443. int i,j;
  3444. const char* mobfile[] = {
  3445. "db/mob_branch.txt",
  3446. "db/mob_poring.txt",
  3447. "db/mob_boss.txt" };
  3448. for(i=0;i<MAX_RANDOMMONSTER;i++){
  3449. mob_db[0].summonper[i] = 1002; // 設定し忘れた場合はポリンが出るようにしておく
  3450. fp=fopen(mobfile[i],"r");
  3451. if(fp==NULL){
  3452. printf("can't read %s\n",mobfile[i]);
  3453. return -1;
  3454. }
  3455. while(fgets(line,1020,fp)){
  3456. int class,per;
  3457. if(line[0] == '/' && line[1] == '/')
  3458. continue;
  3459. memset(str,0,sizeof(str));
  3460. for(j=0,p=line;j<3 && p;j++){
  3461. str[j]=p;
  3462. p=strchr(p,',');
  3463. if(p) *p++=0;
  3464. }
  3465. if(str[0]==NULL || str[2]==NULL)
  3466. continue;
  3467. class = atoi(str[0]);
  3468. per=atoi(str[2]);
  3469. if((class>1000 && class<=2000) || class==0)
  3470. mob_db[class].summonper[i]=per;
  3471. }
  3472. fclose(fp);
  3473. printf("read %s done\n",mobfile[i]);
  3474. }
  3475. return 0;
  3476. }
  3477. /*==========================================
  3478. * db/mob_skill_db.txt reading
  3479. *------------------------------------------
  3480. */
  3481. static int mob_readskilldb(void)
  3482. {
  3483. FILE *fp;
  3484. char line[1024];
  3485. int i;
  3486. const struct {
  3487. char str[32];
  3488. int id;
  3489. } cond1[] = {
  3490. { "always", MSC_ALWAYS },
  3491. { "myhpltmaxrate", MSC_MYHPLTMAXRATE },
  3492. { "friendhpltmaxrate",MSC_FRIENDHPLTMAXRATE },
  3493. { "mystatuson", MSC_MYSTATUSON },
  3494. { "mystatusoff", MSC_MYSTATUSOFF },
  3495. { "friendstatuson", MSC_FRIENDSTATUSON },
  3496. { "friendstatusoff", MSC_FRIENDSTATUSOFF },
  3497. { "attackpcgt", MSC_ATTACKPCGT },
  3498. { "attackpcge", MSC_ATTACKPCGE },
  3499. { "slavelt", MSC_SLAVELT },
  3500. { "slavele", MSC_SLAVELE },
  3501. { "closedattacked", MSC_CLOSEDATTACKED },
  3502. { "longrangeattacked",MSC_LONGRANGEATTACKED },
  3503. { "skillused", MSC_SKILLUSED },
  3504. { "casttargeted", MSC_CASTTARGETED },
  3505. }, cond2[] ={
  3506. { "anybad", -1 },
  3507. { "stone", SC_STONE },
  3508. { "freeze", SC_FREEZE },
  3509. { "stan", SC_STAN },
  3510. { "sleep", SC_SLEEP },
  3511. { "poison", SC_POISON },
  3512. { "curse", SC_CURSE },
  3513. { "silence", SC_SILENCE },
  3514. { "confusion", SC_CONFUSION },
  3515. { "blind", SC_BLIND },
  3516. { "hiding", SC_HIDING },
  3517. { "sight", SC_SIGHT },
  3518. }, state[] = {
  3519. { "any", -1 },
  3520. { "idle", MSS_IDLE },
  3521. { "walk", MSS_WALK },
  3522. { "attack", MSS_ATTACK },
  3523. { "dead", MSS_DEAD },
  3524. { "loot", MSS_LOOT },
  3525. { "chase", MSS_CHASE },
  3526. }, target[] = {
  3527. { "target", MST_TARGET },
  3528. { "self", MST_SELF },
  3529. { "friend", MST_FRIEND },
  3530. { "around5", MST_AROUND5 },
  3531. { "around6", MST_AROUND6 },
  3532. { "around7", MST_AROUND7 },
  3533. { "around8", MST_AROUND8 },
  3534. { "around1", MST_AROUND1 },
  3535. { "around2", MST_AROUND2 },
  3536. { "around3", MST_AROUND3 },
  3537. { "around4", MST_AROUND4 },
  3538. { "around", MST_AROUND },
  3539. };
  3540. int x;
  3541. char *filename[]={ "db/mob_skill_db.txt","db/mob_skill_db2.txt" };
  3542. for(x=0;x<2;x++){
  3543. fp=fopen(filename[x],"r");
  3544. if(fp==NULL){
  3545. if(x==0)
  3546. printf("can't read %s\n",filename[x]);
  3547. continue;
  3548. }
  3549. while(fgets(line,1020,fp)){
  3550. char *sp[20],*p;
  3551. int mob_id;
  3552. struct mob_skill *ms;
  3553. int j=0;
  3554. if(line[0] == '/' && line[1] == '/')
  3555. continue;
  3556. memset(sp,0,sizeof(sp));
  3557. for(i=0,p=line;i<18 && p;i++){
  3558. sp[i]=p;
  3559. if((p=strchr(p,','))!=NULL)
  3560. *p++=0;
  3561. }
  3562. if( (mob_id=atoi(sp[0]))<=0 )
  3563. continue;
  3564. if( strcmp(sp[1],"clear")==0 ){
  3565. memset(mob_db[mob_id].skill,0,sizeof(mob_db[mob_id].skill));
  3566. mob_db[mob_id].maxskill=0;
  3567. continue;
  3568. }
  3569. for(i=0;i<MAX_MOBSKILL;i++)
  3570. if( (ms=&mob_db[mob_id].skill[i])->skill_id == 0)
  3571. break;
  3572. if(i==MAX_MOBSKILL){
  3573. printf("mob_skill: readdb: too many skill ! [%s] in %d[%s]\n",
  3574. sp[1],mob_id,mob_db[mob_id].jname);
  3575. continue;
  3576. }
  3577. ms->state=atoi(sp[2]);
  3578. for(j=0;j<sizeof(state)/sizeof(state[0]);j++){
  3579. if( strcmp(sp[2],state[j].str)==0)
  3580. ms->state=state[j].id;
  3581. }
  3582. ms->skill_id=atoi(sp[3]);
  3583. ms->skill_lv=atoi(sp[4]);
  3584. ms->permillage=atoi(sp[5]);
  3585. ms->casttime=atoi(sp[6]);
  3586. ms->delay=atoi(sp[7]);
  3587. ms->cancel=atoi(sp[8]);
  3588. if( strcmp(sp[8],"yes")==0 ) ms->cancel=1;
  3589. ms->target=atoi(sp[9]);
  3590. for(j=0;j<sizeof(target)/sizeof(target[0]);j++){
  3591. if( strcmp(sp[9],target[j].str)==0)
  3592. ms->target=target[j].id;
  3593. }
  3594. ms->cond1=-1;
  3595. for(j=0;j<sizeof(cond1)/sizeof(cond1[0]);j++){
  3596. if( strcmp(sp[10],cond1[j].str)==0)
  3597. ms->cond1=cond1[j].id;
  3598. }
  3599. ms->cond2=atoi(sp[11]);
  3600. for(j=0;j<sizeof(cond2)/sizeof(cond2[0]);j++){
  3601. if( strcmp(sp[11],cond2[j].str)==0)
  3602. ms->cond2=cond2[j].id;
  3603. }
  3604. ms->val[0]=atoi(sp[12]);
  3605. ms->val[1]=atoi(sp[13]);
  3606. ms->val[2]=atoi(sp[14]);
  3607. ms->val[3]=atoi(sp[15]);
  3608. ms->val[4]=atoi(sp[16]);
  3609. if(sp[17] != NULL && strlen(sp[17])>2)
  3610. ms->emotion=atoi(sp[17]);
  3611. else
  3612. ms->emotion=-1;
  3613. mob_db[mob_id].maxskill=i+1;
  3614. }
  3615. fclose(fp);
  3616. printf("read %s done\n",filename[x]);
  3617. }
  3618. return 0;
  3619. }
  3620. void mob_reload(void)
  3621. {
  3622. /*
  3623. <empty monster database>
  3624. mob_read();
  3625. */
  3626. do_init_mob();
  3627. }
  3628. #ifndef TXT_ONLY
  3629. /*==========================================
  3630. * SQL reading
  3631. *------------------------------------------
  3632. */
  3633. static int mob_read_sqldb(void)
  3634. {
  3635. char line[1024];
  3636. int i,class,ln=0;
  3637. char *str[55],*p,*np;
  3638. memset(mob_db,0,sizeof(mob_db));
  3639. sprintf (tmp_sql, "SELECT * FROM `%s`",mob_db_db);
  3640. if(mysql_query(&mmysql_handle, tmp_sql) ) {
  3641. printf("DB server Error (select %s to Memory)- %s\n",mob_db_db,mysql_error(&mmysql_handle) );
  3642. }
  3643. sql_res = mysql_store_result(&mmysql_handle);
  3644. if (sql_res) {
  3645. while((sql_row = mysql_fetch_row(sql_res))){
  3646. sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
  3647. sql_row[0],sql_row[1],sql_row[2],sql_row[3],sql_row[4],
  3648. sql_row[5],sql_row[6],sql_row[7],sql_row[8],sql_row[9],
  3649. sql_row[10],sql_row[11],sql_row[12],sql_row[13],sql_row[14],
  3650. sql_row[15],sql_row[16],sql_row[17],sql_row[18],sql_row[19],
  3651. sql_row[20],sql_row[21],sql_row[22],sql_row[23],sql_row[24],
  3652. sql_row[25],sql_row[26],sql_row[27],sql_row[28],sql_row[29],
  3653. sql_row[30],sql_row[31],sql_row[32],sql_row[33],sql_row[34],
  3654. sql_row[35],sql_row[36],sql_row[37],sql_row[38],sql_row[39],
  3655. sql_row[40],sql_row[41],sql_row[42],sql_row[43],sql_row[44],
  3656. sql_row[45],sql_row[46],sql_row[47],sql_row[48],sql_row[49],
  3657. sql_row[50],sql_row[51],sql_row[52]);
  3658. for(i=0,p=line;i<55;i++){
  3659. if((np=strchr(p,','))!=NULL){
  3660. str[i]=p;
  3661. *np=0;
  3662. p=np+1;
  3663. } else
  3664. str[i]=p;
  3665. }
  3666. class=atoi(str[0]);
  3667. if(class<=1000 || class>2000)
  3668. continue;
  3669. ln++;
  3670. mob_db[class].view_class=class;
  3671. memcpy(mob_db[class].name,str[1],24);
  3672. memcpy(mob_db[class].jname,str[2],24);
  3673. mob_db[class].lv=atoi(str[3]);
  3674. mob_db[class].max_hp=atoi(str[4]);
  3675. mob_db[class].max_sp=atoi(str[5]);
  3676. mob_db[class].base_exp=atoi(str[6])*
  3677. battle_config.base_exp_rate/100;
  3678. if(mob_db[class].base_exp <= 0)
  3679. mob_db[class].base_exp = 1;
  3680. mob_db[class].job_exp=atoi(str[7])*
  3681. battle_config.job_exp_rate/100;
  3682. if(mob_db[class].job_exp <= 0)
  3683. mob_db[class].job_exp = 1;
  3684. mob_db[class].range=atoi(str[8]);
  3685. mob_db[class].atk1=atoi(str[9]);
  3686. mob_db[class].atk2=atoi(str[10]);
  3687. mob_db[class].def=atoi(str[11]);
  3688. mob_db[class].mdef=atoi(str[12]);
  3689. mob_db[class].str=atoi(str[13]);
  3690. mob_db[class].agi=atoi(str[14]);
  3691. mob_db[class].vit=atoi(str[15]);
  3692. mob_db[class].int_=atoi(str[16]);
  3693. mob_db[class].dex=atoi(str[17]);
  3694. mob_db[class].luk=atoi(str[18]);
  3695. mob_db[class].range2=atoi(str[19]);
  3696. mob_db[class].range3=atoi(str[20]);
  3697. mob_db[class].size=atoi(str[21]);
  3698. mob_db[class].race=atoi(str[22]);
  3699. mob_db[class].element=atoi(str[23]);
  3700. mob_db[class].mode=atoi(str[24]);
  3701. mob_db[class].speed=atoi(str[25]);
  3702. mob_db[class].adelay=atoi(str[26]);
  3703. mob_db[class].amotion=atoi(str[27]);
  3704. mob_db[class].dmotion=atoi(str[28]);
  3705. for(i=0;i<8;i++){
  3706. int rate = 0,type,ratemin,ratemax;
  3707. mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
  3708. type = itemdb_type(mob_db[class].dropitem[i].nameid);
  3709. if (type == 0) { // Added by Valaris
  3710. rate = battle_config.item_rate_heal;
  3711. ratemin = battle_config.item_drop_heal_min;
  3712. ratemax = battle_config.item_drop_heal_max;
  3713. }
  3714. else if (type == 2) {
  3715. rate = battle_config.item_rate_use;
  3716. ratemin = battle_config.item_drop_use_min;
  3717. ratemax = battle_config.item_drop_use_max; // End
  3718. }
  3719. else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
  3720. rate = battle_config.item_rate_equip;
  3721. ratemin = battle_config.item_drop_equip_min;
  3722. ratemax = battle_config.item_drop_equip_max;
  3723. }
  3724. else if (type == 6) {
  3725. rate = battle_config.item_rate_card;
  3726. ratemin = battle_config.item_drop_card_min;
  3727. ratemax = battle_config.item_drop_card_max;
  3728. }
  3729. else {
  3730. rate = battle_config.item_rate_common;
  3731. ratemin = battle_config.item_drop_common_min;
  3732. ratemax = battle_config.item_drop_common_max;
  3733. }
  3734. rate = (rate / 100) * atoi(str[30+i*2]);
  3735. rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
  3736. mob_db[class].dropitem[i].p = rate;
  3737. }
  3738. mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
  3739. mob_db[class].mexpper=atoi(str[46]);
  3740. for(i=0;i<3;i++){
  3741. mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
  3742. mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
  3743. }
  3744. for(i=0;i<MAX_RANDOMMONSTER;i++)
  3745. mob_db[class].summonper[i]=0;
  3746. mob_db[class].maxskill=0;
  3747. mob_db[class].sex=0;
  3748. mob_db[class].hair=0;
  3749. mob_db[class].hair_color=0;
  3750. mob_db[class].weapon=0;
  3751. mob_db[class].shield=0;
  3752. mob_db[class].head_top=0;
  3753. mob_db[class].head_mid=0;
  3754. mob_db[class].head_buttom=0;
  3755. }
  3756. mysql_free_result(sql_res);
  3757. printf("read %s done (count=%d)\n",mob_db_db,ln);
  3758. }
  3759. return 0;
  3760. }
  3761. #endif /* not TXT_ONLY */
  3762. /*==========================================
  3763. * Circumference initialization of mob
  3764. *------------------------------------------
  3765. */
  3766. int do_init_mob(void)
  3767. {
  3768. #ifndef TXT_ONLY
  3769. if(db_use_sqldbs)
  3770. mob_read_sqldb();
  3771. else
  3772. #endif /* TXT_ONLY */
  3773. mob_readdb();
  3774. mob_readdb_mobavail();
  3775. mob_read_randommonster();
  3776. mob_readskilldb();
  3777. add_timer_func_list(mob_timer,"mob_timer");
  3778. add_timer_func_list(mob_delayspawn,"mob_delayspawn");
  3779. add_timer_func_list(mob_delay_item_drop,"mob_delay_item_drop");
  3780. add_timer_func_list(mob_delay_item_drop2,"mob_delay_item_drop2");
  3781. add_timer_func_list(mob_ai_hard,"mob_ai_hard");
  3782. add_timer_func_list(mob_ai_lazy,"mob_ai_lazy");
  3783. add_timer_func_list(mobskill_castend_id,"mobskill_castend_id");
  3784. add_timer_func_list(mobskill_castend_pos,"mobskill_castend_pos");
  3785. add_timer_func_list(mob_timer_delete,"mob_timer_delete");
  3786. add_timer_interval(gettick()+MIN_MOBTHINKTIME,mob_ai_hard,0,0,MIN_MOBTHINKTIME);
  3787. add_timer_interval(gettick()+MIN_MOBTHINKTIME*10,mob_ai_lazy,0,0,MIN_MOBTHINKTIME*10);
  3788. return 0;
  3789. }