mob.c 159 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <stdarg.h>
  6. #include <string.h>
  7. #include <math.h>
  8. #include <limits.h>
  9. #include "timer.h"
  10. #include "socket.h"
  11. #include "db.h"
  12. #include "nullpo.h"
  13. #include "malloc.h"
  14. #include "map.h"
  15. #include "clif.h"
  16. #include "intif.h"
  17. #include "pc.h"
  18. #include "status.h"
  19. #include "mob.h"
  20. #include "guild.h"
  21. #include "itemdb.h"
  22. #include "skill.h"
  23. #include "battle.h"
  24. #include "party.h"
  25. #include "npc.h"
  26. #include "log.h"
  27. #include "showmsg.h"
  28. #include "script.h"
  29. #include "atcommand.h"
  30. #include "date.h"
  31. #include "irc.h"
  32. #define MIN_MOBTHINKTIME 100
  33. #define MIN_MOBLINKTIME 1000
  34. #define MOB_LAZYSKILLPERC 10 // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute)
  35. #define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute)
  36. #define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute)
  37. #define MOB_SLAVEDISTANCE 2 //Distance that slaves should keep from their master.
  38. //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex]
  39. struct mob_db *mob_db_data[MAX_MOB_DB+1];
  40. struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested.
  41. struct mob_db *mob_db(int index) { if (index < 0 || index > MAX_MOB_DB || mob_db_data[index] == NULL) return mob_dummy; return mob_db_data[index]; }
  42. #define CLASSCHANGE_BOSS_NUM 21
  43. /*==========================================
  44. * Local prototype declaration (only required thing)
  45. *------------------------------------------
  46. */
  47. static int mob_makedummymobdb(int);
  48. static int mob_timer(int,unsigned int,int,int);
  49. static int mob_spawn_guardian_sub(int,unsigned int,int,int);
  50. int mobskill_use(struct mob_data *md,unsigned int tick,int event);
  51. int mobskill_deltimer(struct mob_data *md );
  52. int mob_skillid2skillidx(int class_,int skillid);
  53. int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx);
  54. /*==========================================
  55. * Mob is searched with a name.
  56. *------------------------------------------
  57. */
  58. int mobdb_searchname(const char *str)
  59. {
  60. int i;
  61. struct mob_db* mob;
  62. for(i=0;i<=MAX_MOB_DB;i++){
  63. mob = mob_db(i);
  64. if(mob == mob_dummy) //Skip dummy mobs.
  65. continue;
  66. if(strcmpi(mob->name,str)==0 || strcmp(mob->jname,str)==0 ||
  67. memcmp(mob->name,str,NAME_LENGTH)==0 || memcmp(mob->jname,str,NAME_LENGTH)==0)
  68. return i;
  69. }
  70. return 0;
  71. }
  72. static int mobdb_searchname_array_sub(struct mob_db* mob, const char *str)
  73. {
  74. if (mob == mob_dummy)
  75. return 1; //Invalid item.
  76. if(strstr(mob->jname,str))
  77. return 0;
  78. if(strstr(mob->name,str))
  79. return 0;
  80. return strcmpi(mob->jname,str);
  81. }
  82. /*==========================================
  83. * Founds up to N matches. Returns number of matches [Skotlex]
  84. *------------------------------------------
  85. */
  86. int mobdb_searchname_array(struct mob_db** data, int size, const char *str)
  87. {
  88. int count = 0, i;
  89. struct mob_db* mob;
  90. for(i=0;i<=MAX_MOB_DB;i++){
  91. mob = mob_db(i);
  92. if (mob == mob_dummy)
  93. continue;
  94. if (!mobdb_searchname_array_sub(mob, str)) {
  95. if (count < size)
  96. data[count] = mob;
  97. count++;
  98. }
  99. }
  100. return count;
  101. }
  102. /*==========================================
  103. * Id Mob is checked.
  104. *------------------------------------------
  105. */
  106. int mobdb_checkid(const int id)
  107. {
  108. if (mob_db(id) == mob_dummy)
  109. return 0;
  110. if (mob_is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question.
  111. return 0;
  112. return id;
  113. }
  114. /*==========================================
  115. * The minimum data set for MOB spawning
  116. *------------------------------------------
  117. */
  118. int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class_)
  119. {
  120. nullpo_retr(0, md);
  121. md->bl.prev=NULL;
  122. md->bl.next=NULL;
  123. md->base_class = md->class_ = class_;
  124. md->db = mob_db(class_);
  125. if(strcmp(mobname,"--en--")==0)
  126. strncpy(md->name,md->db->name,NAME_LENGTH-1);
  127. else if(strcmp(mobname,"--ja--")==0)
  128. strncpy(md->name,md->db->jname,NAME_LENGTH-1);
  129. else
  130. strncpy(md->name,mobname,NAME_LENGTH-1);
  131. md->n = 0;
  132. md->bl.id= npc_get_new_npc_id();
  133. memset(&md->state,0,sizeof(md->state));
  134. md->timer = -1;
  135. md->target_id=0;
  136. md->attacked_id=0;
  137. md->attacked_count=0;
  138. md->speed=md->db->speed;
  139. return 0;
  140. }
  141. /*==========================================
  142. * Fetches a random mob_id [Skotlex]
  143. * type: Where to fetch from:
  144. * 0: dead branch list
  145. * 1: poring list
  146. * 2: bloody branch list
  147. * flag:
  148. * &1: Apply the summon success chance found in the list.
  149. * &2: Apply a monster check level.
  150. * lv: Mob level to check against
  151. *------------------------------------------
  152. */
  153. int mob_get_random_id(int type, int flag, int lv) {
  154. struct mob_db *mob;
  155. int i=0, k=0, class_;
  156. if(type < 0 || type >= MAX_RANDOMMONSTER) {
  157. if (battle_config.error_log)
  158. ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type);
  159. return 0;
  160. }
  161. do {
  162. class_ = rand() % MAX_MOB_DB;
  163. if (flag&1)
  164. k = rand() % 1000000;
  165. mob = mob_db(class_);
  166. } while ((mob == mob_dummy || mob->summonper[type] <= k ||
  167. (flag&2 && lv < mob->lv)) && (i++) < MAX_MOB_DB);
  168. if(i >= MAX_MOB_DB)
  169. class_ = mob_db_data[0]->summonper[type];
  170. return class_;
  171. }
  172. /*==========================================
  173. * The MOB appearance for one time (for scripts)
  174. *------------------------------------------
  175. */
  176. int mob_once_spawn (struct map_session_data *sd, char *mapname,
  177. int x, int y, const char *mobname, int class_, int amount, const char *event)
  178. {
  179. struct mob_data *md = NULL;
  180. int m, count, lv = 255;
  181. int i, j;
  182. if(sd) lv = sd->status.base_level;
  183. if(sd && strcmp(mapname,"this")==0)
  184. m = sd->bl.m;
  185. else
  186. m = map_mapname2mapid(mapname);
  187. if (m < 0 || amount <= 0 || (class_ >= 0 && class_ <= 1000) || class_ > MAX_MOB_DB + 2*MAX_MOB_DB) // 値が異常なら召喚を止める
  188. return 0;
  189. if (sd) { //even if the coords were wrong, spawn mob anyways (but look for most suitable coords first) Got from Freya [Lupus]
  190. if (x <= 0 || y <= 0) {
  191. if (x <= 0) x = sd->bl.x + rand() % 3 - 1;
  192. if (y <= 0) y = sd->bl.y + rand() % 3 - 1;
  193. if (map_getcell(m, x, y, CELL_CHKNOPASS)) {
  194. x = sd->bl.x;
  195. y = sd->bl.y;
  196. }
  197. }
  198. } else if (x <= 0 || y <= 0) {
  199. i = j = 0;
  200. do {
  201. x = rand() % (map[m].xs - 2) + 1;
  202. y = rand() % (map[m].ys - 2) + 1;
  203. } while ((i = map_getcell(m, x, y, CELL_CHKNOPASS)) && j++ < 64);
  204. if (i) { // not solved?
  205. x = 0;
  206. y = 0;
  207. }
  208. }
  209. for (count = 0; count < amount; count++) {
  210. md = (struct mob_data *)aCalloc(1,sizeof(struct mob_data));
  211. if (class_ > 2*MAX_MOB_DB) { // large/tiny mobs [Valaris]
  212. md->special_state.size = 2;
  213. class_ -= 2*MAX_MOB_DB;
  214. } else if (class_ > MAX_MOB_DB) {
  215. md->special_state.size = 1;
  216. class_ -= MAX_MOB_DB;
  217. }
  218. if (class_ < 0) {
  219. class_ = mob_get_random_id(-class_ -1, battle_config.random_monster_checklv?3:1, lv);
  220. if (!class_) {
  221. aFree(md);
  222. return 0;
  223. }
  224. if (battle_config.dead_branch_active)
  225. //Behold Aegis's masterful decisions yet again...
  226. //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3
  227. md->mode = mob_db(class_)->mode|MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE;
  228. }
  229. if(mob_db(class_)->mode & MD_LOOTER)
  230. md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  231. mob_spawn_dataset (md, mobname, class_);
  232. md->bl.m = m;
  233. md->bl.x = x;
  234. md->bl.y = y;
  235. md->m = m;
  236. md->x0 = x;
  237. md->y0 = y;
  238. //md->xs = 0;
  239. //md->ys = 0;
  240. md->spawndelay1 = -1; // 一度のみフラグ
  241. md->spawndelay2 = -1; // 一度のみフラグ
  242. //better safe than sorry, current md->npc_event has a size of 50
  243. if (strlen(event) < 50)
  244. memcpy(md->npc_event, event, strlen(event));
  245. md->bl.type = BL_MOB;
  246. map_addiddb (&md->bl);
  247. mob_spawn (md->bl.id);
  248. if(class_ == MOBID_EMPERIUM) { // emperium hp based on defense level [Valaris]
  249. struct guild_castle *gc = guild_mapname2gc(map[md->bl.m].name);
  250. struct guild *g = gc?guild_search(gc->guild_id):NULL;
  251. if(gc) {
  252. md->max_hp += 2000 * gc->defense;
  253. md->hp = md->max_hp;
  254. md->guardian_data = aCalloc(1, sizeof(struct guardian_data));
  255. md->guardian_data->castle = gc;
  256. md->guardian_data->number = MAX_GUARDIANS;
  257. md->guardian_data->guild_id = gc->guild_id;
  258. if (g)
  259. {
  260. md->guardian_data->emblem_id = g->emblem_id;
  261. memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
  262. }
  263. else if (gc->guild_id) //Guild not yet available, retry in 5.
  264. add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id);
  265. }
  266. } // end addition [Valaris]
  267. }
  268. return (amount > 0) ? md->bl.id : 0;
  269. }
  270. /*==========================================
  271. * The MOB appearance for one time (& area specification for scripts)
  272. *------------------------------------------
  273. */
  274. int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
  275. int x0,int y0,int x1,int y1,
  276. const char *mobname,int class_,int amount,const char *event)
  277. {
  278. int x,y,i,max,lx=-1,ly=-1,id=0;
  279. int m;
  280. if(strcmp(mapname,"this")==0)
  281. m=sd->bl.m;
  282. else
  283. m=map_mapname2mapid(mapname);
  284. max=(y1-y0+1)*(x1-x0+1)*3;
  285. if(max>1000)max=1000;
  286. if (m < 0 || amount <= 0 || (class_ >= 0 && class_ <= 1000) || class_ > MAX_MOB_DB + 2*MAX_MOB_DB) // 値が異常なら召喚を止める
  287. return 0;
  288. for(i=0;i<amount;i++){
  289. int j=0;
  290. do{
  291. x=rand()%(x1-x0+1)+x0;
  292. y=rand()%(y1-y0+1)+y0;
  293. } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (++j)<max);
  294. // freya }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
  295. if(j>=max){
  296. if(lx>=0){ // Since reference went wrong, the place which boiled before is used.
  297. x=lx;
  298. y=ly;
  299. }else
  300. return 0; // Since reference of the place which boils first went wrong, it stops.
  301. }
  302. if(x==0||y==0) ShowWarning("mob_once_spawn_area: xory=0, x=%d,y=%d,x0=%d,y0=%d\n",x,y,x0,y0);
  303. id=mob_once_spawn(sd,mapname,x,y,mobname,class_,1,event);
  304. lx=x;
  305. ly=y;
  306. }
  307. return id;
  308. }
  309. /*==========================================
  310. * Set a Guardian's guild data [Skotlex]
  311. *------------------------------------------
  312. */
  313. static int mob_spawn_guardian_sub(int tid,unsigned int tick,int id,int data)
  314. { //Needed because the guild_data may not be available at guardian spawn time.
  315. struct block_list* bl = map_id2bl(id);
  316. struct mob_data* md;
  317. struct guild* g;
  318. if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex]
  319. return 0;
  320. if (bl->type != BL_MOB || (md = (struct mob_data*)bl) == NULL)
  321. {
  322. ShowError("mob_spawn_guardian_sub: Block error!\n");
  323. return 0;
  324. }
  325. nullpo_retr(0, md->guardian_data);
  326. g = guild_search(data);
  327. if (g == NULL)
  328. { //Liberate castle, if the guild is not found this is an error! [Skotlex]
  329. ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n",data);
  330. if (md->class_ == MOBID_EMPERIUM)
  331. { //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
  332. md->guardian_data->guild_id = 0;
  333. if (md->guardian_data->castle->guild_id) //Free castle up.
  334. {
  335. ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name);
  336. guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0);
  337. }
  338. } else {
  339. if (md->guardian_data->castle->guardian[md->guardian_data->number].visible)
  340. { //Safe removal of guardian.
  341. md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
  342. guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  343. guild_castledatasave(md->guardian_data->castle->castle_id, 18+md->guardian_data->number,0);
  344. }
  345. mob_delete(md); //Remove guardian.
  346. }
  347. return 0;
  348. }
  349. md->guardian_data->emblem_id = g->emblem_id;
  350. memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH);
  351. md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP);
  352. return 0;
  353. }
  354. /*==========================================
  355. * Summoning Guardians [Valaris]
  356. *------------------------------------------
  357. */
  358. int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
  359. int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian)
  360. {
  361. struct mob_data *md=NULL;
  362. struct guild *g=NULL;
  363. struct guild_castle *gc;
  364. int m,count=1;
  365. if( sd && strcmp(mapname,"this")==0)
  366. m=sd->bl.m;
  367. else
  368. m=map_mapname2mapid(mapname);
  369. if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // Invalid monster classes
  370. return 0;
  371. if(class_<0)
  372. return 0;
  373. if(guardian < 0 || guardian >= MAX_GUARDIANS)
  374. {
  375. ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name);
  376. return 0;
  377. }
  378. if (amount > 1)
  379. ShowWarning("mob_spawn_guardian: Spawning %d guardians in position %d (castle map %s)\n", amount, map[m].name);
  380. if(sd){
  381. if(x<=0) x=sd->bl.x;
  382. if(y<=0) y=sd->bl.y;
  383. }
  384. else if(x<=0 || y<=0)
  385. ShowWarning("mob_spawn_guardian: Invalid coordinates (%d,%d)\n",x,y);
  386. gc=guild_mapname2gc(map[m].name);
  387. if (gc == NULL)
  388. {
  389. ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name);
  390. return 0;
  391. }
  392. if (!gc->guild_id)
  393. ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map[m].name);
  394. else
  395. g = guild_search(gc->guild_id);
  396. if (gc->guardian[guardian].id)
  397. ShowWarning("mob_spawn_guardian: Spawning guardian in position %d which already has a guardian (castle map %s)\n", guardian, map[m].name);
  398. for(count=0;count<amount;count++){
  399. md=(struct mob_data *) aCalloc(1, sizeof(struct mob_data));
  400. mob_spawn_dataset(md,mobname,class_);
  401. md->bl.m=m;
  402. md->bl.x=x;
  403. md->bl.y=y;
  404. md->m =m;
  405. md->x0=x;
  406. md->y0=y;
  407. md->xs=0;
  408. md->ys=0;
  409. md->spawndelay1=-1; // Only once is a flag.
  410. md->spawndelay2=-1; // Only once is a flag.
  411. //better safe than sorry, current md->npc_event has a size of 50 [Skotlex]
  412. if (strlen(event) < 50)
  413. memcpy(md->npc_event, event, strlen(event));
  414. md->bl.type=BL_MOB;
  415. map_addiddb(&md->bl);
  416. mob_spawn(md->bl.id);
  417. md->max_hp += 2000 * gc->defense;
  418. md->guardian_data = aCalloc(1, sizeof(struct guardian_data));
  419. md->guardian_data->number = guardian;
  420. md->guardian_data->guild_id = gc->guild_id;
  421. md->guardian_data->castle = gc;
  422. md->hp = gc->guardian[guardian].hp;
  423. gc->guardian[guardian].id = md->bl.id;
  424. if (g)
  425. {
  426. md->guardian_data->emblem_id = g->emblem_id;
  427. memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH);
  428. md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP);
  429. } else if (md->guardian_data->guild_id)
  430. add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id);
  431. }
  432. return (amount>0)?md->bl.id:0;
  433. }
  434. /*==========================================
  435. * Is MOB in the state in which the present movement is possible or not?
  436. *------------------------------------------
  437. */
  438. int mob_can_move(struct mob_data *md)
  439. {
  440. nullpo_retr(0, md);
  441. if(DIFF_TICK(md->canmove_tick, gettick()) > 0 || md->skilltimer != -1 || (md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.option&OPTION_HIDE)
  442. return 0;
  443. // アンクル中で動けないとか
  444. if(md->sc.count && (
  445. md->sc.data[SC_ANKLE].timer != -1 || //アンクルスネア
  446. md->sc.data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
  447. md->sc.data[SC_BLADESTOP].timer != -1 || //白刃取り
  448. md->sc.data[SC_SPIDERWEB].timer != -1 || //スパイダーウェッブ
  449. (md->sc.data[SC_DANCING].timer !=-1 && md->sc.data[SC_DANCING].val1 == CG_HERMODE) || //cannot move while Hermod is active.
  450. (md->sc.data[SC_GOSPEL].timer !=-1 && md->sc.data[SC_GOSPEL].val4 == BCT_SELF) || // cannot move while gospel is in effect
  451. md->sc.data[SC_STOP].timer != -1 ||
  452. md->sc.data[SC_CLOSECONFINE].timer != -1 ||
  453. md->sc.data[SC_CLOSECONFINE2].timer != -1
  454. ))
  455. return 0;
  456. return 1;
  457. }
  458. /*==========================================
  459. * Time calculation concerning one step next to mob
  460. *------------------------------------------
  461. */
  462. static int calc_next_walk_step(struct mob_data *md)
  463. {
  464. nullpo_retr(0, md);
  465. if(md->walkpath.path_pos>=md->walkpath.path_len)
  466. return -1;
  467. if(md->walkpath.path[md->walkpath.path_pos]&1)
  468. return status_get_speed(&md->bl)*14/10;
  469. return status_get_speed(&md->bl);
  470. }
  471. static int mob_walktoxy_sub(struct mob_data *md);
  472. /*==========================================
  473. * Mob Walk processing
  474. *------------------------------------------
  475. */
  476. static int mob_walk(struct mob_data *md,unsigned int tick,int data)
  477. {
  478. int i;
  479. static int dirx[8]={0,-1,-1,-1,0,1,1,1};
  480. static int diry[8]={1,1,0,-1,-1,-1,0,1};
  481. int x,y,dx,dy;
  482. nullpo_retr(0, md);
  483. md->state.state=MS_IDLE;
  484. if(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_pos!=data)
  485. return 0;
  486. md->walkpath.path_half ^= 1;
  487. if(md->walkpath.path_half==0){
  488. md->walkpath.path_pos++;
  489. if(md->state.change_walk_target){
  490. mob_walktoxy_sub(md);
  491. return 0;
  492. }
  493. }
  494. else {
  495. if(md->walkpath.path[md->walkpath.path_pos]>=8)
  496. return 1;
  497. x = md->bl.x;
  498. y = md->bl.y;
  499. #ifndef CELL_NOSTACK
  500. if(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS)) {
  501. mob_stop_walking(md,1);
  502. return 0;
  503. }
  504. #endif
  505. md->dir=md->walkpath.path[md->walkpath.path_pos];
  506. dx = dirx[md->dir];
  507. dy = diry[md->dir];
  508. if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) {
  509. mob_walktoxy_sub(md);
  510. return 0;
  511. }
  512. md->state.state=MS_WALK;
  513. map_foreachinmovearea(clif_moboutsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,md);
  514. if ( md->min_chase > md->db->range2)
  515. md->min_chase--;
  516. x += dx;
  517. y += dy;
  518. map_moveblock(&md->bl, x, y, tick);
  519. map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md);
  520. md->state.state=MS_IDLE;
  521. }
  522. if((i=calc_next_walk_step(md))>0){
  523. i = i>>1;
  524. if(i < 1 && md->walkpath.path_half == 0)
  525. i = 1;
  526. if(md->walkpath.path_pos>=md->walkpath.path_len)
  527. clif_fixmobpos(md); // とまったときに位置の再送信
  528. else {
  529. md->timer=add_timer(tick+i,mob_timer,md->bl.id,md->walkpath.path_pos);
  530. md->state.state=MS_WALK;
  531. }
  532. }
  533. return 0;
  534. }
  535. /*==========================================
  536. * Reachability to a Specification ID existence place
  537. * state indicates type of 'seek' mob should do:
  538. * - MSS_LOOT: Looking for item, path must be easy.
  539. * - MSS_RUSH: Chasing attacking player, path is determined by mob_ai&1
  540. * - MSS_FOLLOW: Initiative/support seek, path must be easy.
  541. *------------------------------------------
  542. */
  543. int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state)
  544. {
  545. int dx,dy;
  546. struct walkpath_data wpd;
  547. int i, easy = 0;
  548. nullpo_retr(0, md);
  549. nullpo_retr(0, bl);
  550. switch (state) {
  551. case MSS_RUSH:
  552. easy = (battle_config.mob_ai&1?0:1);
  553. break;
  554. case MSS_LOOT:
  555. case MSS_FOLLOW:
  556. default:
  557. easy = 1;
  558. break;
  559. }
  560. if( md->bl.m != bl->m) // 違うャbプ
  561. return 0;
  562. if( md->bl.x==bl->x && md->bl.y==bl->y ) // 同じマス
  563. return 1;
  564. if( range>0 && !check_distance_bl(&md->bl, bl, range))
  565. return 0;
  566. // Obstacle judging
  567. wpd.path_len=0;
  568. wpd.path_pos=0;
  569. wpd.path_half=0;
  570. if(path_search_real(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x,bl->y,easy,CELL_CHKNOREACH)!=-1)
  571. return 1;
  572. // It judges whether it can adjoin or not.
  573. dx=bl->x - md->bl.x;
  574. dy=bl->y - md->bl.y;
  575. dx=(dx>0)?1:((dx<0)?-1:0);
  576. dy=(dy>0)?1:((dy<0)?-1:0);
  577. if (map_getcell(md->bl.m,bl->x+dx,bl->y+dy,CELL_CHKNOREACH))
  578. { //Look for a suitable cell to place in.
  579. for(i=0;i<9 && map_getcell(md->bl.m,bl->x-1+i/3,bl->y-1+i%3,CELL_CHKNOREACH);i++);
  580. if (i<9) {
  581. dx = 1-i/3;
  582. dy = 1-i%3;
  583. }
  584. }
  585. if(path_search_real(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-dx,bl->y-dy,easy,CELL_CHKNOREACH)!=-1)
  586. return 1;
  587. return 0;
  588. }
  589. /*==========================================
  590. * Links nearby mobs (supportive mobs)
  591. *------------------------------------------
  592. */
  593. static int mob_linksearch(struct block_list *bl,va_list ap)
  594. {
  595. struct mob_data *md;
  596. int class_;
  597. struct block_list *target;
  598. unsigned int tick;
  599. nullpo_retr(0, bl);
  600. nullpo_retr(0, ap);
  601. md=(struct mob_data *)bl;
  602. class_ = va_arg(ap, int);
  603. target = va_arg(ap, struct block_list *);
  604. tick=va_arg(ap, unsigned int);
  605. if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME
  606. && (!md->target_id || md->state.targettype == NONE_ATTACKABLE))
  607. {
  608. md->last_linktime = tick;
  609. if( mob_can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging
  610. md->target_id = target->id;
  611. md->attacked_count = 0;
  612. md->state.targettype = ATTACKABLE;
  613. md->state.aggressive = (status_get_mode(&md->bl)&MD_ANGRY)?1:0;
  614. md->min_chase=md->db->range3;
  615. return 1;
  616. }
  617. }
  618. return 0;
  619. }
  620. /*==========================================
  621. * Attack processing of mob
  622. *------------------------------------------
  623. */
  624. static int mob_attack(struct mob_data *md,unsigned int tick,int data)
  625. {
  626. struct block_list *tbl=NULL;
  627. int range;
  628. nullpo_retr(0, md);
  629. md->min_chase=md->db->range3;
  630. md->state.state=MS_IDLE;
  631. md->state.skillstate=MSS_IDLE;
  632. if( md->skilltimer!=-1 ) // スキル使用中
  633. return 0;
  634. if((tbl=map_id2bl(md->target_id))==NULL || !status_check_skilluse(&md->bl, tbl, 0, 0)){
  635. md->target_id=0;
  636. md->state.targettype = NONE_ATTACKABLE;
  637. return 0;
  638. }
  639. if (!check_distance_bl(&md->bl, tbl, md->db->range3)){
  640. mob_stopattack(md);
  641. return 0;
  642. }
  643. range = md->db->range;
  644. if (range <= 3)
  645. range++; //Melee attackers get a bonus range cell when attacking.
  646. /* It seems mobs always teleport the last two tiles when chasing players, so do not give them this bonus range tile.[Skotlex]
  647. if(battle_iswalking(tbl)) range++;
  648. */
  649. if(!check_distance_bl(&md->bl, tbl, range))
  650. return 0;
  651. if(battle_config.monster_attack_direction_change)
  652. md->dir=map_calc_dir(&md->bl, tbl->x,tbl->y ); // 向き設定
  653. if (status_get_mode(&md->bl)&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME)
  654. { // Link monsters nearby [Skotlex]
  655. md->last_linktime = tick;
  656. map_foreachinrange(mob_linksearch, &md->bl, md->db->range2,
  657. BL_MOB, md->class_, tbl, tick);
  658. }
  659. md->state.skillstate=md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
  660. if( mobskill_use(md,tick,-1) ) // スキル使用
  661. return 0;
  662. if(md->sc.count && md->sc.data[SC_WINKCHARM].timer != -1)
  663. clif_emotion(&md->bl, 3);
  664. else
  665. md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,0);
  666. if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1)
  667. status_change_end(&md->bl,SC_CLOAKING,-1);
  668. //Mobs can't move if they can't attack neither.
  669. //Use the attack delay for next can attack try
  670. //But use the attack motion to know when it can start moving. [Skotlex]
  671. md->attackabletime = tick + status_get_adelay(&md->bl);
  672. battle_set_walkdelay(&md->bl, tick, status_get_amotion(&md->bl), 1);
  673. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  674. md->state.state=MS_ATTACK;
  675. return 0;
  676. }
  677. /*==========================================
  678. * The attack of PC which is attacking id is stopped.
  679. * The callback function of clif_foreachclient
  680. *------------------------------------------
  681. */
  682. int mob_stopattacked(struct map_session_data *sd,va_list ap)
  683. {
  684. int id;
  685. nullpo_retr(0, sd);
  686. nullpo_retr(0, ap);
  687. id=va_arg(ap,int);
  688. if(sd->attacktarget==id)
  689. pc_stopattack(sd);
  690. return 0;
  691. }
  692. /*==========================================
  693. * The timer in which the mob's states changes
  694. *------------------------------------------
  695. */
  696. int mob_changestate(struct mob_data *md,int state,int type)
  697. {
  698. unsigned int tick;
  699. int i;
  700. nullpo_retr(0, md);
  701. if(md->timer != -1)
  702. delete_timer(md->timer,mob_timer);
  703. md->timer=-1;
  704. md->state.state=state;
  705. switch(state){
  706. case MS_WALK:
  707. if((i=calc_next_walk_step(md))>0){
  708. i = i>>2;
  709. md->timer=add_timer(gettick()+i,mob_timer,md->bl.id, md->walkpath.path_pos);
  710. }
  711. else
  712. md->state.state=MS_IDLE;
  713. break;
  714. case MS_ATTACK:
  715. tick = gettick();
  716. i=DIFF_TICK(md->attackabletime,tick);
  717. if(i>0 && i<2000)
  718. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  719. else if(type) {
  720. md->attackabletime = tick + status_get_amotion(&md->bl);
  721. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  722. }
  723. else {
  724. md->attackabletime = tick + 1;
  725. md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
  726. }
  727. break;
  728. case MS_DELAY:
  729. md->timer=add_timer(gettick()+type,mob_timer,md->bl.id,0);
  730. break;
  731. case MS_DEAD:
  732. skill_castcancel(&md->bl,0);
  733. // mobskill_deltimer(md);
  734. md->state.skillstate=MSS_DEAD;
  735. md->last_deadtime=gettick();
  736. // Since it died, all aggressors' attack to this mob is stopped.
  737. clif_foreachclient(mob_stopattacked,md->bl.id);
  738. skill_unit_move(&md->bl,gettick(),4);
  739. status_change_clear(&md->bl,2); // ステータス異常を解除する
  740. if (battle_config.clear_unit_ondeath)
  741. skill_clear_unitgroup(&md->bl);
  742. skill_cleartimerskill(&md->bl);
  743. if(md->deletetimer!=-1)
  744. delete_timer(md->deletetimer,mob_timer_delete);
  745. md->deletetimer=-1;
  746. md->hp = md->target_id = md->attacked_id = md->attacked_count = 0;
  747. md->state.targettype = NONE_ATTACKABLE;
  748. break;
  749. }
  750. return 0;
  751. }
  752. /*==========================================
  753. * timer processing of mob (timer function)
  754. * It branches to a walk and an attack.
  755. *------------------------------------------
  756. */
  757. static int mob_timer(int tid,unsigned int tick,int id,int data)
  758. {
  759. struct mob_data *md;
  760. struct block_list *bl;
  761. if( (bl=map_id2bl(id)) == NULL ){ //攻撃してきた敵がもういないのは正常のようだ
  762. return 1;
  763. }
  764. if(!bl || !bl->type || bl->type!=BL_MOB)
  765. return 1;
  766. nullpo_retr(1, md=(struct mob_data*)bl);
  767. if(md->timer != tid){
  768. if(battle_config.error_log)
  769. ShowError("mob_timer %d != %d\n",md->timer,tid);
  770. return 0;
  771. }
  772. md->timer=-1;
  773. if(md->bl.prev == NULL || md->state.state == MS_DEAD)
  774. return 1;
  775. map_freeblock_lock();
  776. switch(md->state.state){
  777. case MS_WALK:
  778. mob_walk(md,tick,data);
  779. break;
  780. case MS_ATTACK:
  781. mob_attack(md,tick,data);
  782. break;
  783. case MS_DELAY:
  784. mob_changestate(md,MS_IDLE,0);
  785. break;
  786. default:
  787. if(battle_config.error_log)
  788. ShowError("mob_timer : %d ?\n",md->state.state);
  789. break;
  790. }
  791. if (md->timer == -1)
  792. mob_changestate(md,MS_WALK,0);
  793. map_freeblock_unlock();
  794. return 0;
  795. }
  796. /*==========================================
  797. *
  798. *------------------------------------------
  799. */
  800. static int mob_walktoxy_sub(struct mob_data *md)
  801. {
  802. struct walkpath_data wpd;
  803. nullpo_retr(0, md);
  804. memset(&wpd, 0, sizeof(wpd));
  805. if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy))
  806. return 1;
  807. if (wpd.path[0] >= 8)
  808. return 1;
  809. memcpy(&md->walkpath,&wpd,sizeof(wpd));
  810. md->state.change_walk_target=0;
  811. mob_changestate(md,MS_WALK,0);
  812. clif_movemob(md);
  813. return 0;
  814. }
  815. /*==========================================
  816. * mob move start
  817. *------------------------------------------
  818. */
  819. int mob_walktoxy(struct mob_data *md,int x,int y,int easy)
  820. {
  821. struct walkpath_data wpd;
  822. nullpo_retr(0, md);
  823. if(md->bl.prev == NULL || md->state.state == MS_DEAD) //Just-in-case check to prevent dead mobs from moving. [Skotlex]
  824. return 1;
  825. if(md->state.state == MS_WALK && path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,x,y,easy) )
  826. return 1;
  827. md->state.walk_easy = easy;
  828. md->to_x=x;
  829. md->to_y=y;
  830. if (md->sc.data[SC_CONFUSION].timer != -1) //Randomize target direction.
  831. map_random_dir(&md->bl, &md->to_x, &md->to_y);
  832. if(md->state.state == MS_WALK)
  833. md->state.change_walk_target=1;
  834. else
  835. return mob_walktoxy_sub(md);
  836. return 0;
  837. }
  838. /*==========================================
  839. * mob spawn with delay (timer function)
  840. *------------------------------------------
  841. */
  842. static int mob_delayspawn(int tid, unsigned int tick, int m, int n)
  843. {
  844. mob_spawn(m);
  845. return 0;
  846. }
  847. /*==========================================
  848. * spawn timing calculation
  849. *------------------------------------------
  850. */
  851. int mob_setdelayspawn(int id)
  852. {
  853. unsigned int spawntime, spawntime1, spawntime2, spawntime3;
  854. struct mob_data *md;
  855. struct block_list *bl;
  856. if ((bl = map_id2bl(id)) == NULL || bl->type != BL_MOB)
  857. return -1;
  858. nullpo_retr(-1, md = (struct mob_data*)bl);
  859. // Processing of MOB which is not revitalized
  860. if (md->spawndelay1 == -1 && md->spawndelay2 == -1 && md->n == 0) {
  861. if (md->lootitem) {
  862. aFree(md->lootitem);
  863. md->lootitem = NULL;
  864. }
  865. if (md->guardian_data)
  866. {
  867. if (md->guardian_data->number < MAX_GUARDIANS)
  868. md->guardian_data->castle->guardian[md->guardian_data->number].id = 0;
  869. aFree (md->guardian_data);
  870. md->guardian_data = NULL;
  871. }
  872. map_deliddb(&md->bl);
  873. map_delblock(bl); //In case it wasn't done before invoking the function.
  874. map_freeblock(bl);
  875. return 0;
  876. }
  877. spawntime1 = md->last_spawntime + md->spawndelay1;
  878. spawntime2 = md->last_deadtime + md->spawndelay2;
  879. spawntime3 = gettick() + 5000 + rand()%5000; //Lupus
  880. // spawntime = max(spawntime1,spawntime2,spawntime3);
  881. if (DIFF_TICK(spawntime1, spawntime2) > 0)
  882. spawntime = spawntime1;
  883. else
  884. spawntime = spawntime2;
  885. if (DIFF_TICK(spawntime3, spawntime) > 0)
  886. spawntime = spawntime3;
  887. add_timer(spawntime, mob_delayspawn, id, 0);
  888. return 0;
  889. }
  890. static int mob_count_sub(struct block_list *bl,va_list ap)
  891. {
  892. return 1;
  893. }
  894. /*==========================================
  895. * Mob spawning. Initialization is also variously here.
  896. *------------------------------------------
  897. */
  898. int mob_spawn (int id)
  899. {
  900. int x, y, i = 0;
  901. unsigned int c =0, tick = gettick();
  902. struct mob_data *md;
  903. struct block_list *bl;
  904. if ((bl = map_id2bl(id)) == NULL || bl->type != BL_MOB)
  905. return -1;
  906. nullpo_retr(-1, md = (struct mob_data*)bl);
  907. md->last_spawntime = tick;
  908. if (md->bl.prev != NULL)
  909. map_delblock(&md->bl);
  910. else {
  911. if(md->class_ != md->base_class){ // クラスチェンジしたMob
  912. md->class_ = md->base_class;
  913. md->db = mob_db(md->base_class);
  914. memcpy(md->name,md->db->jname,NAME_LENGTH);
  915. md->speed=md->db->speed;
  916. }
  917. }
  918. md->bl.m = md->m;
  919. while (i < 50) {
  920. if (md->x0 == 0 && md->y0 == 0) {
  921. x = rand()%(map[md->bl.m].xs-2)+1;
  922. y = rand()%(map[md->bl.m].ys-2)+1;
  923. } else {
  924. x = md->x0+rand()%(md->xs+1)-md->xs/2;
  925. y = md->y0+rand()%(md->ys+1)-md->ys/2;
  926. }
  927. i++;
  928. if (map_getcell(md->bl.m,x,y,CELL_CHKNOPASS))
  929. continue;
  930. //Avoid spawning on the view-range of players. [Skotlex]
  931. if (battle_config.no_spawn_on_player &&
  932. c++ < battle_config.no_spawn_on_player &&
  933. map_foreachinrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC)
  934. )
  935. continue;
  936. //Found a spot.
  937. break;
  938. }
  939. if (i >= 50) {
  940. if (md->spawndelay1 != -1 || md->spawndelay2 == -1)
  941. // retry again later
  942. add_timer(tick+5000,mob_delayspawn,id,0);
  943. return 1;
  944. }
  945. md->to_x = md->bl.x = x;
  946. md->to_y = md->bl.y = y;
  947. md->dir = 0;
  948. md->target_dir = 0;
  949. memset(&md->state, 0, sizeof(md->state));
  950. md->attacked_id = 0;
  951. md->attacked_count = 0;
  952. md->target_id = 0;
  953. md->mode = 0;
  954. md->move_fail_count = 0;
  955. if (!md->speed)
  956. md->speed = md->db->speed;
  957. md->def_ele = md->db->element;
  958. if (!md->level) // [Valaris]
  959. md->level=md->db->lv;
  960. md->master_id = 0;
  961. md->master_dist = 0;
  962. md->state.state = MS_IDLE;
  963. md->state.skillstate = MSS_IDLE;
  964. md->timer = -1;
  965. md->last_thinktime = tick;
  966. md->next_walktime = tick+rand()%50+5000;
  967. md->attackabletime = tick;
  968. md->canmove_tick = tick;
  969. md->last_linktime = tick;
  970. /* Guardians should be spawned using mob_spawn_guardian! [Skotlex]
  971. * and the Emperium is spawned using mob_once_spawn.
  972. md->guild_id = 0;
  973. if (md->class_ >= 1285 && md->class_ <= 1288) {
  974. struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
  975. if(gc)
  976. md->guild_id = gc->guild_id;
  977. }
  978. */
  979. md->deletetimer = -1;
  980. md->skilltimer = -1;
  981. for (i = 0, c = tick-1000*3600*10; i < MAX_MOBSKILL; i++)
  982. md->skilldelay[i] = c;
  983. md->skillid = 0;
  984. md->skilllv = 0;
  985. memset(md->dmglog, 0, sizeof(md->dmglog));
  986. md->tdmg = 0;
  987. if (md->lootitem)
  988. memset(md->lootitem, 0, sizeof(md->lootitem));
  989. md->lootitem_count = 0;
  990. for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
  991. md->skilltimerskill[i].timer = -1;
  992. for (i = 0; i < MAX_STATUSCHANGE; i++) {
  993. md->sc.data[i].timer = -1;
  994. md->sc.data[i].val1 = md->sc.data[i].val2 = md->sc.data[i].val3 = md->sc.data[i].val4 = 0;
  995. }
  996. md->sc.count = 0;
  997. md->sc.opt1 = md->sc.opt2 = md->sc.opt3 = md->sc.option = 0;
  998. if(md->db->option){ // Added for carts, falcons and pecos for cloned monsters. [Valaris]
  999. if(md->db->option & 0x0008)
  1000. md->sc.option |= 0x0008;
  1001. if(md->db->option & 0x0080)
  1002. md->sc.option |= 0x0080;
  1003. if(md->db->option & 0x0100)
  1004. md->sc.option |= 0x0100;
  1005. if(md->db->option & 0x0200)
  1006. md->sc.option |= 0x0200;
  1007. if(md->db->option & 0x0400)
  1008. md->sc.option |= 0x0400;
  1009. if(md->db->option & OPTION_FALCON)
  1010. md->sc.option |= OPTION_FALCON;
  1011. if(md->db->option & OPTION_RIDING)
  1012. md->sc.option |= OPTION_RIDING;
  1013. }
  1014. memset(md->skillunit, 0, sizeof(md->skillunit));
  1015. memset(md->skillunittick, 0, sizeof(md->skillunittick));
  1016. md->max_hp = md->db->max_hp;
  1017. if(md->special_state.size==1) // change for sized monsters [Valaris]
  1018. md->max_hp/=2;
  1019. else if(md->special_state.size==2)
  1020. md->max_hp*=2;
  1021. md->hp = md->max_hp;
  1022. map_addblock(&md->bl);
  1023. skill_unit_move(&md->bl,tick,1);
  1024. clif_spawnmob(md);
  1025. mobskill_use(md, tick, MSC_SPAWN);
  1026. return 0;
  1027. }
  1028. /*==========================================
  1029. * The stop of MOB's attack
  1030. *------------------------------------------
  1031. */
  1032. int mob_stopattack(struct mob_data *md)
  1033. {
  1034. md->target_id = 0;
  1035. md->state.targettype = NONE_ATTACKABLE;
  1036. md->attacked_id = 0;
  1037. md->attacked_count = 0;
  1038. return 0;
  1039. }
  1040. /*==========================================
  1041. * The stop of MOB's walking
  1042. *------------------------------------------
  1043. */
  1044. int mob_stop_walking(struct mob_data *md,int type)
  1045. {
  1046. nullpo_retr(0, md);
  1047. if(md->state.state == MS_WALK || md->state.state == MS_IDLE) {
  1048. int dx=0,dy=0;
  1049. md->walkpath.path_len=0;
  1050. if(type&2 && mob_can_move(md)){
  1051. dx=md->to_x-md->bl.x;
  1052. if(dx<0)
  1053. dx=-1;
  1054. else if(dx>0)
  1055. dx=1;
  1056. dy=md->to_y-md->bl.y;
  1057. if(dy<0)
  1058. dy=-1;
  1059. else if(dy>0)
  1060. dy=1;
  1061. }
  1062. md->to_x=md->bl.x+dx;
  1063. md->to_y=md->bl.y+dy;
  1064. if(dx!=0 || dy!=0){
  1065. mob_walktoxy_sub(md);
  1066. return 0;
  1067. }
  1068. mob_changestate(md,MS_IDLE,0);
  1069. }
  1070. if(type&0x01)
  1071. clif_fixmobpos(md);
  1072. return 0;
  1073. }
  1074. /*==========================================
  1075. * Determines if the mob can change target. [Skotlex]
  1076. *------------------------------------------
  1077. */
  1078. static int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode)
  1079. {
  1080. switch (md->state.skillstate) {
  1081. case MSS_BERSERK: //Only Assist, Angry or Aggressive+CastSensor mobs can change target while attacking.
  1082. if (mode&(MD_ASSIST|MD_ANGRY) || (mode&(MD_AGGRESSIVE|MD_CASTSENSOR)) == (MD_AGGRESSIVE|MD_CASTSENSOR))
  1083. return (battle_config.mob_ai&4 || check_distance_bl(&md->bl, target, 3));
  1084. else
  1085. return 0;
  1086. case MSS_RUSH:
  1087. return (mode&MD_AGGRESSIVE);
  1088. case MSS_FOLLOW:
  1089. case MSS_ANGRY:
  1090. case MSS_IDLE:
  1091. case MSS_WALK:
  1092. case MSS_LOOT:
  1093. return 1;
  1094. default:
  1095. return 0;
  1096. }
  1097. }
  1098. /*==========================================
  1099. * Determination for an attack of a monster
  1100. *------------------------------------------
  1101. */
  1102. int mob_target(struct mob_data *md,struct block_list *bl,int dist)
  1103. {
  1104. nullpo_retr(0, md);
  1105. nullpo_retr(0, bl);
  1106. // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
  1107. if((md->target_id > 0 && md->state.targettype == ATTACKABLE) && !mob_can_changetarget(md, bl, status_get_mode(&md->bl)) &&
  1108. // if the monster was provoked ignore the above rule [celest]
  1109. !(md->state.provoke_flag && md->state.provoke_flag == bl->id))
  1110. return 0;
  1111. if(!status_check_skilluse(&md->bl, bl, 0, 0))
  1112. return 0;
  1113. md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
  1114. if(bl->type == BL_PC || bl->type == BL_MOB)
  1115. md->state.targettype = ATTACKABLE;
  1116. else
  1117. md->state.targettype = NONE_ATTACKABLE;
  1118. if (md->state.provoke_flag)
  1119. md->state.provoke_flag = 0;
  1120. md->min_chase=dist+md->db->range2;
  1121. if(md->min_chase>26)
  1122. md->min_chase=26;
  1123. return 0;
  1124. }
  1125. /*==========================================
  1126. * The ?? routine of an active monster
  1127. *------------------------------------------
  1128. */
  1129. static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
  1130. {
  1131. struct mob_data *md;
  1132. struct block_list **target;
  1133. int dist;
  1134. nullpo_retr(0, bl);
  1135. nullpo_retr(0, ap);
  1136. md=va_arg(ap,struct mob_data *);
  1137. target= va_arg(ap,struct block_list**);
  1138. //If can't seek yet, not an enemy, or you can't attack it, skip.
  1139. if ((*target) == bl || battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || !status_check_skilluse(&md->bl, bl, 0, 0))
  1140. return 0;
  1141. switch (bl->type)
  1142. {
  1143. case BL_PC:
  1144. if (((struct map_session_data*)bl)->state.gangsterparadise &&
  1145. !(status_get_mode(&md->bl)&MD_BOSS))
  1146. return 0; //Gangster paradise protection.
  1147. case BL_MOB:
  1148. if((dist=distance_bl(&md->bl, bl)) < md->db->range2
  1149. && (md->db->range > 6 || mob_can_reach(md,bl,dist+1, MSS_FOLLOW))
  1150. && ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one.
  1151. ) {
  1152. (*target) = bl;
  1153. md->target_id=bl->id;
  1154. md->state.targettype = ATTACKABLE;
  1155. md->state.aggressive = (status_get_mode(&md->bl)&MD_ANGRY)?1:0;
  1156. md->min_chase= md->db->range3;
  1157. return 1;
  1158. }
  1159. break;
  1160. }
  1161. return 0;
  1162. }
  1163. /*==========================================
  1164. * chase target-change routine.
  1165. *------------------------------------------
  1166. */
  1167. static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap)
  1168. {
  1169. struct mob_data *md;
  1170. struct block_list **target;
  1171. nullpo_retr(0, bl);
  1172. nullpo_retr(0, ap);
  1173. md=va_arg(ap,struct mob_data *);
  1174. target= va_arg(ap,struct block_list**);
  1175. //If can't seek yet, not an enemy, or you can't attack it, skip.
  1176. if ((*target) == bl || battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || !status_check_skilluse(&md->bl, bl, 0, 0))
  1177. return 0;
  1178. switch (bl->type)
  1179. {
  1180. case BL_PC:
  1181. case BL_MOB:
  1182. if(check_distance_bl(&md->bl, bl, md->db->range) &&
  1183. battle_check_range (&md->bl, bl, md->db->range)
  1184. ) {
  1185. (*target) = bl;
  1186. md->target_id=bl->id;
  1187. md->state.targettype = ATTACKABLE;
  1188. md->state.aggressive = (status_get_mode(&md->bl)&MD_ANGRY)?1:0;
  1189. md->min_chase= md->db->range3;
  1190. return 1;
  1191. }
  1192. break;
  1193. }
  1194. return 0;
  1195. }
  1196. /*==========================================
  1197. * loot monster item search
  1198. *------------------------------------------
  1199. */
  1200. static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
  1201. {
  1202. struct mob_data* md;
  1203. int dist,*itc;
  1204. nullpo_retr(0, bl);
  1205. nullpo_retr(0, ap);
  1206. nullpo_retr(0, md=va_arg(ap,struct mob_data *));
  1207. nullpo_retr(0, itc=va_arg(ap,int *));
  1208. if(!md->lootitem || (battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE))
  1209. return 0;
  1210. if((dist=distance_bl(&md->bl, bl)) < md->db->range2 &&
  1211. mob_can_reach(md,bl,dist, MSS_LOOT) && rand()%1000<1000/(++(*itc)))
  1212. { // It is made a probability, such as within the limits PC.
  1213. md->target_id=bl->id;
  1214. md->state.targettype = NONE_ATTACKABLE;
  1215. md->min_chase=md->db->range3;
  1216. md->next_walktime = gettick() + 500; //So that the mob may go after the item inmediately.
  1217. }
  1218. return 0;
  1219. }
  1220. /*==========================================
  1221. * Processing of slave monsters
  1222. *------------------------------------------
  1223. */
  1224. static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
  1225. {
  1226. struct block_list *bl;
  1227. int old_dist;
  1228. nullpo_retr(0, md);
  1229. bl=map_id2bl(md->master_id);
  1230. if (!bl || status_isdead(bl)) { //主が死亡しているか見つからない
  1231. if(md->special_state.ai>0)
  1232. mob_timer_delete(0, 0, md->bl.id, 0);
  1233. else
  1234. mob_damage(NULL,md,md->hp,0);
  1235. return 0;
  1236. }
  1237. if(status_get_mode(&md->bl)&MD_CANMOVE)
  1238. { //If the mob can move, follow around. [Check by Skotlex]
  1239. if(bl->m != md->bl.m || md->master_dist > 30)
  1240. { // Since it is not in the same map (or is way to far), just warp it
  1241. mob_warp(md,bl->m,bl->x,bl->y,3);
  1242. return 0;
  1243. }
  1244. // Distance with between slave and master is measured.
  1245. old_dist=md->master_dist;
  1246. md->master_dist=distance_bl(&md->bl, bl);
  1247. // Since the master was in near immediately before, teleport is carried out and it pursues.
  1248. if(old_dist<10 && md->master_dist>18){
  1249. mob_warp(md,-1,bl->x,bl->y,3);
  1250. return 0;
  1251. }
  1252. // Approach master if within view range, chase back to Master's area also if standing on top of the master.
  1253. if(md->master_dist<md->db->range3 && (md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0) &&
  1254. mob_can_move(md) && md->state.state == MS_IDLE)
  1255. {
  1256. int i=0,dx,dy,ret;
  1257. do {
  1258. if(i<=5){
  1259. dx=bl->x - md->bl.x;
  1260. dy=bl->y - md->bl.y;
  1261. if(dx<0) dx+=rand()%MOB_SLAVEDISTANCE +1;
  1262. else if(dx>0) dx-=rand()%MOB_SLAVEDISTANCE +1;
  1263. if(dy<0) dy+=rand()%MOB_SLAVEDISTANCE +1;
  1264. else if(dy>0) dy-=rand()%MOB_SLAVEDISTANCE +1;
  1265. }else{
  1266. ret = MOB_SLAVEDISTANCE*2+1;
  1267. dx=bl->x - md->bl.x + rand()%ret - MOB_SLAVEDISTANCE;
  1268. dy=bl->y - md->bl.y + rand()%ret - MOB_SLAVEDISTANCE;
  1269. }
  1270. ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
  1271. i++;
  1272. } while(ret && i<10);
  1273. }
  1274. } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) {
  1275. //Delete the summoned mob if it's in a gvg ground and the master is elsewhere. [Skotlex]
  1276. if(md->special_state.ai>0)
  1277. mob_timer_delete(0, 0, md->bl.id, 0);
  1278. else
  1279. mob_damage(NULL,md,md->hp,0);
  1280. return 0;
  1281. }
  1282. //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex]
  1283. if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && (!md->target_id || md->state.targettype == NONE_ATTACKABLE)) {
  1284. md->last_linktime = tick;
  1285. switch (bl->type) {
  1286. case BL_MOB:
  1287. {
  1288. struct mob_data *mmd= (struct mob_data*)bl;
  1289. struct block_list *tbl;
  1290. if(mmd->target_id>0 && mmd->state.targettype == ATTACKABLE &&
  1291. (tbl=map_id2bl(mmd->target_id)) && status_check_skilluse(&md->bl, tbl, 0, 0)
  1292. ) {
  1293. md->target_id=tbl->id;
  1294. md->state.targettype = ATTACKABLE;
  1295. md->state.aggressive = (status_get_mode(&md->bl)&MD_ANGRY)?1:0;
  1296. md->min_chase=md->db->range2+distance_bl(&md->bl, tbl);
  1297. }
  1298. }
  1299. break;
  1300. case BL_PC:
  1301. {
  1302. struct map_session_data *msd = (struct map_session_data*)bl;
  1303. struct block_list *tbl = NULL;
  1304. if(msd->attacktarget)
  1305. tbl = map_id2bl(msd->attacktarget);
  1306. else if (msd->skilltarget) {
  1307. tbl = map_id2bl(msd->skilltarget);
  1308. if (tbl && battle_check_target(&md->bl, tbl, BCT_ENEMY) <= 0)
  1309. tbl = NULL; //Required check as skilltarget is not always an enemy. [Skotlex]
  1310. }
  1311. if(tbl && status_check_skilluse(&md->bl, tbl, 0, 0)) {
  1312. md->target_id=tbl->id;
  1313. md->state.targettype = ATTACKABLE;
  1314. md->state.aggressive = (status_get_mode(&md->bl)&MD_ANGRY)?1:0;
  1315. md->min_chase=md->db->range2+distance_bl(&md->bl, tbl);
  1316. }
  1317. }
  1318. break;
  1319. }
  1320. }
  1321. return 0;
  1322. }
  1323. /*==========================================
  1324. * A lock of target is stopped and mob moves to a standby state.
  1325. *------------------------------------------
  1326. */
  1327. int mob_unlocktarget(struct mob_data *md,int tick)
  1328. {
  1329. nullpo_retr(0, md);
  1330. md->target_id=0;
  1331. md->state.targettype = NONE_ATTACKABLE;
  1332. md->state.skillstate=MSS_IDLE;
  1333. md->next_walktime=tick+rand()%3000+3000;
  1334. return 0;
  1335. }
  1336. /*==========================================
  1337. * Random walk
  1338. *------------------------------------------
  1339. */
  1340. int mob_randomwalk(struct mob_data *md,int tick)
  1341. {
  1342. const int retrycount=20;
  1343. int speed;
  1344. nullpo_retr(0, md);
  1345. speed=status_get_speed(&md->bl);
  1346. if(DIFF_TICK(md->next_walktime,tick)<0){
  1347. int i,x,y,c,d=12-md->move_fail_count;
  1348. int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
  1349. if(d<5) d=5;
  1350. for(i=0;i<retrycount;i++){ // Search of a movable place
  1351. int r=rand();
  1352. x=r%(d*2+1)-d;
  1353. y=r/(d*2+1)%(d*2+1)-d;
  1354. if (md->target_dir){
  1355. if (x<0) x=0-x;
  1356. if (y<0) y=0-y;
  1357. x *= mask[md->target_dir-1][0];
  1358. y *= mask[md->target_dir-1][1];
  1359. }
  1360. x+=md->bl.x;
  1361. y+=md->bl.y;
  1362. if((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && mob_walktoxy(md,x,y,1)==0){
  1363. md->move_fail_count=0;
  1364. break;
  1365. }
  1366. if(i+1>=retrycount){
  1367. md->move_fail_count++;
  1368. md->target_dir = 0;
  1369. if(md->move_fail_count>1000){
  1370. if(battle_config.error_log)
  1371. ShowWarning("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class_);
  1372. md->move_fail_count=0;
  1373. mob_spawn(md->bl.id);
  1374. }
  1375. }
  1376. }
  1377. for(i=c=0;i<md->walkpath.path_len;i++){ // The next walk start time is calculated.
  1378. if(md->walkpath.path[i]&1)
  1379. c+=speed*14/10;
  1380. else
  1381. c+=speed;
  1382. }
  1383. md->next_walktime = tick+rand()%3000+3000+c;
  1384. md->state.skillstate=MSS_WALK;
  1385. return 1;
  1386. }
  1387. return 0;
  1388. }
  1389. /*==========================================
  1390. * AI of MOB whose is near a Player
  1391. *------------------------------------------
  1392. */
  1393. static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
  1394. {
  1395. struct mob_data *md;
  1396. struct block_list *tbl = NULL, *abl = NULL;
  1397. unsigned int tick;
  1398. int i, j, dx, dy, dist;
  1399. int attack_type = 0;
  1400. int mode;
  1401. int search_size = AREA_SIZE*2;
  1402. int blind_flag = 0;
  1403. nullpo_retr(0, bl);
  1404. nullpo_retr(0, ap);
  1405. md = (struct mob_data*)bl;
  1406. tick = va_arg(ap, unsigned int);
  1407. if(md->bl.prev == NULL || md->state.state == MS_DEAD)
  1408. return 1;
  1409. if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME)
  1410. return 0;
  1411. md->last_thinktime = tick;
  1412. if (md->skilltimer != -1){ // Casting skill, or has died
  1413. if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME)
  1414. md->next_walktime = tick;
  1415. return 0;
  1416. }
  1417. // Abnormalities
  1418. if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->state.state == MS_DELAY || md->sc.data[SC_BLADESTOP].timer != -1)
  1419. return 0;
  1420. if (md->sc.count && md->sc.data[SC_BLIND].timer != -1)
  1421. blind_flag = 1;
  1422. mode = status_get_mode(&md->bl);
  1423. if (md->target_id)
  1424. { //Check validity of current target. [Skotlex]
  1425. tbl = map_id2bl(md->target_id);
  1426. if (!tbl || tbl->m != md->bl.m || !status_check_skilluse(&md->bl, tbl, 0, 0) || (
  1427. tbl->type == BL_PC && !(mode&MD_BOSS) &&
  1428. ((struct map_session_data*)tbl)->state.gangsterparadise
  1429. )) { //Unlock current target.
  1430. if (md->state.state == MS_WALK && (battle_config.mob_ai&8 || !tbl)) //Inmediately stop chasing.
  1431. mob_stop_walking(md, 2);
  1432. mob_unlocktarget(md, tick-(battle_config.mob_ai&8?3000:0)); //Imediately do random walk.
  1433. tbl = NULL;
  1434. }
  1435. }
  1436. // Check for target change.
  1437. if (md->attacked_id && mode&MD_CANATTACK && md->attacked_id != md->target_id)
  1438. {
  1439. abl = map_id2bl(md->attacked_id);
  1440. if (abl && (!tbl || mob_can_changetarget(md, abl, mode))) {
  1441. if (md->bl.m != abl->m || abl->prev == NULL ||
  1442. (dist = distance_bl(&md->bl, abl)) >= 32 ||
  1443. battle_check_target(bl, abl, BCT_ENEMY) <= 0 ||
  1444. (battle_config.mob_ai&2 && !status_check_skilluse(bl, abl, 0, 0)) ||
  1445. !mob_can_reach(md, abl, md->db->range2, MSS_RUSH) ||
  1446. ( //Gangster Paradise check
  1447. abl->type == BL_PC && !(mode&MD_BOSS) &&
  1448. ((struct map_session_data*)abl)->state.gangsterparadise
  1449. )
  1450. ) { //Can't attack back
  1451. if (md->attacked_count++ > 3) {
  1452. if (mobskill_use(md, tick, MSC_RUDEATTACKED) == 0 &&
  1453. mode&MD_CANMOVE && mob_can_move(md))
  1454. {
  1455. int dist = rand() % 10 + 1;//後退する距離
  1456. int dir = map_calc_dir(abl, bl->x, bl->y);
  1457. int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
  1458. mob_walktoxy(md, md->bl.x + dist * mask[dir][0], md->bl.y + dist * mask[dir][1], 0);
  1459. md->next_walktime = tick + 500;
  1460. }
  1461. }
  1462. } else if (!(battle_config.mob_ai&2) && !status_check_skilluse(bl, abl, 0, 0)) {
  1463. //Can't attack back, but didn't invoke a rude attacked skill...
  1464. md->attacked_id = 0; //Simply unlock, shouldn't attempt to run away when in dumb_ai mode.
  1465. } else if (blind_flag && dist > 2 && DIFF_TICK(tick,md->next_walktime) < 0) { //Blinded, but can reach
  1466. if (!md->target_id)
  1467. { //Attempt to follow new target
  1468. if (mode&MD_CANMOVE && mob_can_move(md)) { // why is it moving to the target when the mob can't see the player? o.o
  1469. dx = abl->x - md->bl.x;
  1470. dy = abl->y - md->bl.y;
  1471. md->next_walktime = tick + 1000;
  1472. mob_walktoxy(md, md->bl.x+dx, md->bl.y+dy, 0);
  1473. }
  1474. }
  1475. } else { //Attackable
  1476. if (!tbl || dist < md->db->range || !check_distance_bl(&md->bl, tbl, dist)
  1477. || battle_gettarget(tbl) != md->bl.id)
  1478. { //Change if the new target is closer than the actual one
  1479. //or if the previous target is not attacking the mob. [Skotlex]
  1480. md->target_id = md->attacked_id; // set target
  1481. md->state.targettype = ATTACKABLE;
  1482. md->state.aggressive = 0; //Retaliating.
  1483. attack_type = 1;
  1484. md->attacked_count = 0;
  1485. md->min_chase = dist + md->db->range2;
  1486. if (md->min_chase > 26)
  1487. md->min_chase = 26;
  1488. tbl = abl; //Set the new target
  1489. }
  1490. }
  1491. }
  1492. }
  1493. if (md->attacked_id) {
  1494. if (md->state.aggressive && md->attacked_id == md->target_id)
  1495. md->state.aggressive = 0; //No longer aggressive, change to retaliate AI.
  1496. md->attacked_id = 0; //Clear it since it's been checked for already.
  1497. }
  1498. // Processing of slave monster, is it needed when there's a target to deal with?
  1499. if (md->master_id > 0 && !tbl)
  1500. mob_ai_sub_hard_slavemob(md, tick);
  1501. // Scan area for targets
  1502. if ((mode&MD_AGGRESSIVE && battle_config.monster_active_enable && !tbl) ||
  1503. (mode&MD_ANGRY && md->state.skillstate == MSS_FOLLOW)
  1504. ) {
  1505. search_size = (blind_flag) ? 3 : md->db->range2;
  1506. map_foreachinrange (mob_ai_sub_hard_activesearch, &md->bl,
  1507. search_size, md->special_state.ai?BL_CHAR:BL_PC, md, &tbl);
  1508. } else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) {
  1509. search_size = (blind_flag && md->db->range>3) ? 3 : md->db->range;
  1510. map_foreachinrange (mob_ai_sub_hard_changechase, &md->bl,
  1511. search_size, md->special_state.ai?BL_CHAR:BL_PC, md, &tbl);
  1512. }
  1513. // Scan area for items to loot, avoid trying to loot of the mob is full and can't consume the items.
  1514. if (!md->target_id && mode&MD_LOOTER && md->lootitem &&
  1515. (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1))
  1516. {
  1517. i = 0;
  1518. search_size = (blind_flag) ? 3 : md->db->range2;
  1519. map_foreachinrange (mob_ai_sub_hard_lootsearch, &md->bl,
  1520. search_size, BL_ITEM, md, &i);
  1521. }
  1522. if (tbl)
  1523. { //Target exists, attack or loot as applicable.
  1524. if (tbl->type != BL_ITEM)
  1525. { //Attempt to attack.
  1526. //At this point we know the target is attackable, we just gotta check if the range matches.
  1527. if (blind_flag && DIFF_TICK(tick,md->next_walktime) < 0 && !check_distance_bl(&md->bl, tbl, 1))
  1528. { //Run towards the enemy when out of range?
  1529. md->target_id = 0;
  1530. md->state.targettype = NONE_ATTACKABLE;
  1531. if (!(mode & MD_CANMOVE) || !mob_can_move(md))
  1532. return 0;
  1533. dx = tbl->x - md->bl.x;
  1534. dy = tbl->y - md->bl.y;
  1535. md->next_walktime = tick + 1000;
  1536. mob_walktoxy(md, md->bl.x+dx, md->bl.y+dy, 0);
  1537. return 0;
  1538. }
  1539. if (!battle_check_range (&md->bl, tbl, md->db->range))
  1540. { //Out of range...
  1541. if (!(mode&MD_CANMOVE))
  1542. { //Can't chase. Attempt to use a ranged skill at least?
  1543. if (mobskill_use(md, tick, MSC_LONGRANGEATTACKED) == 0)
  1544. md->attacked_count++; //Increase rude-attacked count as it can't attack back.
  1545. mob_unlocktarget(md,tick);
  1546. return 0;
  1547. }
  1548. if (!mob_can_move(md)) //Wait until you can move?
  1549. return 0;
  1550. //Follow up
  1551. md->state.skillstate = md->state.aggressive?MSS_FOLLOW:MSS_RUSH;
  1552. mobskill_use (md, tick, -1);
  1553. if (md->timer != -1 && md->state.state != MS_ATTACK &&
  1554. (DIFF_TICK (md->next_walktime, tick) < 0 ||
  1555. !(battle_config.mob_ai&1) ||
  1556. check_distance_blxy(tbl, md->to_x, md->to_y, md->db->range)) //Current target tile is still within attack range.
  1557. ) {
  1558. return 0; //No need to follow, already doing it?
  1559. }
  1560. search_size = (blind_flag) ? 3 : ((md->min_chase > md->db->range2) ? md->min_chase : md->db->range2);
  1561. if (!mob_can_reach(md, tbl, search_size, MSS_RUSH))
  1562. { //Can't reach
  1563. mob_unlocktarget(md,tick);
  1564. return 0;
  1565. }
  1566. //Target reachable. Locate suitable spot to move to.
  1567. i = j = 0;
  1568. dx = tbl->x - md->bl.x;
  1569. dy = tbl->y - md->bl.y;
  1570. if (dx < 0) dx=-1;
  1571. else if (dx > 0) dx=1;
  1572. if (dy < 0) dy=-1;
  1573. else if (dy > 0) dy=1;
  1574. if(mob_walktoxy(md, tbl->x -dx, tbl->y -dy, 0)) {
  1575. j = (dy+1) + 3*(dx+1);
  1576. for (i = j+1; i%9 != j; i++) {
  1577. dx = -1+(i%9)/3;
  1578. dy = -1+(i%3);
  1579. #ifdef CELL_NOSTACK
  1580. if (map_getcell(md->bl.m, tbl->x-dx, tbl->y-dy, CELL_CHKSTACK))
  1581. continue;
  1582. #endif
  1583. if (!mob_walktoxy(md, tbl->x-dx, tbl->y-dy, 0))
  1584. break;
  1585. }
  1586. #ifdef CELL_NOSTACK
  1587. if (i%9 == j)
  1588. { //All adjacent cells are taken. Try roaming around on 5x5
  1589. for (i = j+1; i%9 != j; i++) {
  1590. dx = 2*(-1+(i%9)/3);
  1591. dy = 2*(-1+(i%3));
  1592. if (map_getcell(md->bl.m, tbl->x-dx, tbl->y-dy, CELL_CHKSTACK))
  1593. continue;
  1594. if (!mob_walktoxy(md, tbl->x-dx, tbl->y-dy, 0)) {
  1595. md->next_walktime = tick + 1000;
  1596. break;
  1597. }
  1598. }
  1599. }
  1600. if (i%9 == j)
  1601. {
  1602. //On stacked mode, it is much more likely that you just can't reach the target. So unlock it
  1603. mob_unlocktarget(md, tick);
  1604. md->next_walktime = tick + 1000;
  1605. return 0;
  1606. }
  1607. #else
  1608. if (i%9 == j)
  1609. { //Failed? Try going away from the target before retrying.
  1610. if (dx < 0) dx = 2;
  1611. else if (dx > 0) dx = -2;
  1612. if (dy < 0) dy = 2;
  1613. else if (dy > 0) dy = -2;
  1614. mob_walktoxy (md, tbl->x+dx, tbl->y+dy, 0);
  1615. md->next_walktime = tick + 500;
  1616. }
  1617. #endif
  1618. }
  1619. return 0;
  1620. }
  1621. //Target within range, engage
  1622. md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
  1623. if (md->state.state == MS_WALK)
  1624. mob_stop_walking (md, 1);
  1625. else if (md->state.state == MS_ATTACK)
  1626. return 0; //Ah, we are already attacking.
  1627. mob_changestate(md, MS_ATTACK, attack_type);
  1628. return 0;
  1629. } else { //Target is BL_ITEM, attempt loot.
  1630. struct flooritem_data *fitem;
  1631. if ((dist = distance_bl(&md->bl, tbl)) >= md->min_chase || (blind_flag && dist >= 4) || md->lootitem == NULL)
  1632. { //Can't loot...
  1633. mob_unlocktarget (md, tick);
  1634. if (md->state.state == MS_WALK)
  1635. mob_stop_walking(md,0);
  1636. return 0;
  1637. }
  1638. if (dist)
  1639. { //Still not within loot range.
  1640. if (!(mode & MD_CANMOVE))
  1641. { //A looter that can't move? Real smart.
  1642. mob_unlocktarget(md,tick);
  1643. return 0;
  1644. }
  1645. if (!mob_can_move(md)) // 動けない状態にある
  1646. return 0;
  1647. md->state.skillstate = MSS_LOOT; // ルート時スキル使用
  1648. mobskill_use(md, tick, -1);
  1649. if (md->timer != -1 && md->state.state != MS_ATTACK &&
  1650. (DIFF_TICK(md->next_walktime,tick) < 0 ||
  1651. check_distance_blxy(tbl, md->to_x, md->to_y, 0)))
  1652. { //Already on the way to looting.
  1653. return 0;
  1654. }
  1655. md->next_walktime = tick + 500;
  1656. dx = tbl->x - md->bl.x;
  1657. dy = tbl->y - md->bl.y;
  1658. if (mob_walktoxy(md, md->bl.x+dx, md->bl.y+dy, 0))
  1659. mob_unlocktarget(md, tick); //Can't loot...
  1660. return 0;
  1661. }
  1662. //Within looting range.
  1663. if (md->state.state == MS_ATTACK)
  1664. return 0; //Busy attacking?
  1665. if (md->state.state == MS_WALK)
  1666. mob_stop_walking(md,0);
  1667. fitem = (struct flooritem_data *)tbl;
  1668. if (md->lootitem_count < LOOTITEM_SIZE) {
  1669. memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0]));
  1670. if(log_config.pick > 0) //Logs items, taken by (L)ooter Mobs [Lupus]
  1671. log_pick((struct map_session_data*)md, "L", md->class_, md->lootitem[md->lootitem_count-1].nameid, md->lootitem[md->lootitem_count-1].amount, &md->lootitem[md->lootitem_count-1]);
  1672. } else if (battle_config.monster_loot_type == 1) { //Can't loot, stuffed!
  1673. mob_unlocktarget(md,tick);
  1674. return 0;
  1675. } else { //Destroy first looted item...
  1676. if (md->lootitem[0].card[0] == (short)0xff00)
  1677. intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) );
  1678. for (i = 0; i < LOOTITEM_SIZE - 1; i++)
  1679. memcpy (&md->lootitem[i], &md->lootitem[i+1], sizeof(md->lootitem[0]));
  1680. memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0]));
  1681. }
  1682. //Clear item.
  1683. map_clearflooritem (tbl->id);
  1684. mob_unlocktarget (md,tick);
  1685. return 0;
  1686. }
  1687. }
  1688. // When there's no target, it is idling.
  1689. if (mobskill_use(md, tick, -1))
  1690. return 0;
  1691. // Nothing else to do... except random walking.
  1692. // Slaves do not random walk! [Skotlex]
  1693. if (mode&MD_CANMOVE && mob_can_move(md) && !md->master_id)
  1694. {
  1695. if (DIFF_TICK(md->next_walktime, tick) > 7000 &&
  1696. (md->walkpath.path_len == 0 || md->walkpath.path_pos >= md->walkpath.path_len))
  1697. md->next_walktime = tick + 3000 * rand() % 2000;
  1698. // Random movement
  1699. if (mob_randomwalk(md,tick))
  1700. return 0;
  1701. }
  1702. // Since he has finished walking, it stands by.
  1703. if (md->walkpath.path_len == 0 || md->walkpath.path_pos >= md->walkpath.path_len)
  1704. md->state.skillstate = MSS_IDLE;
  1705. return 0;
  1706. }
  1707. /*==========================================
  1708. * Serious processing for mob in PC field of view (foreachclient)
  1709. *------------------------------------------
  1710. */
  1711. static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
  1712. {
  1713. unsigned int tick;
  1714. nullpo_retr(0, sd);
  1715. nullpo_retr(0, ap);
  1716. tick=va_arg(ap,unsigned int);
  1717. map_foreachinrange(mob_ai_sub_hard,&sd->bl, AREA_SIZE*2, BL_MOB,tick);
  1718. return 0;
  1719. }
  1720. /*==========================================
  1721. * Serious processing for mob in PC field of view (interval timer function)
  1722. *------------------------------------------
  1723. */
  1724. static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
  1725. {
  1726. clif_foreachclient(mob_ai_sub_foreachclient,tick);
  1727. return 0;
  1728. }
  1729. /*==========================================
  1730. * Negligent mode MOB AI (PC is not in near)
  1731. *------------------------------------------
  1732. */
  1733. static int mob_ai_sub_lazy(DBKey key,void * data,va_list app)
  1734. {
  1735. struct mob_data *md = (struct mob_data *)data;
  1736. va_list ap;
  1737. unsigned int tick;
  1738. int mode;
  1739. nullpo_retr(0, md);
  1740. nullpo_retr(0, app);
  1741. if(md->bl.type!=BL_MOB)
  1742. return 0;
  1743. ap = va_arg(app, va_list);
  1744. tick=va_arg(ap,unsigned int);
  1745. if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME*10)
  1746. return 0;
  1747. md->last_thinktime=tick;
  1748. if (md->bl.prev==NULL || md->state.state == MS_DEAD)
  1749. return 1;
  1750. if(md->skilltimer!=-1){
  1751. if(DIFF_TICK(tick,md->next_walktime)>MIN_MOBTHINKTIME*10)
  1752. md->next_walktime=tick;
  1753. return 0;
  1754. }
  1755. // 取り巻きモンスターの処理(呼び戻しされた時)
  1756. if (md->master_id > 0) {
  1757. mob_ai_sub_hard_slavemob (md,tick);
  1758. return 0;
  1759. }
  1760. mode = status_get_mode(&md->bl);
  1761. if(DIFF_TICK(md->next_walktime,tick)<0 &&
  1762. (mode&MD_CANMOVE) && mob_can_move(md) ){
  1763. if( map[md->bl.m].users>0 ){
  1764. // Since PC is in the same map, somewhat better negligent processing is carried out.
  1765. // It sometimes moves.
  1766. if(rand()%1000<MOB_LAZYMOVEPERC)
  1767. mob_randomwalk(md,tick);
  1768. // MOB which is not not the summons MOB but BOSS, either sometimes reboils.
  1769. else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
  1770. !(mode&MD_BOSS))
  1771. mob_spawn(md->bl.id);
  1772. else if(rand()%1000<MOB_LAZYSKILLPERC) //Chance to do a mob's idle skill.
  1773. mobskill_use(md, tick, -1);
  1774. }else{
  1775. // Since PC is not even in the same map, suitable processing is carried out even if it takes.
  1776. // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
  1777. if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
  1778. !(mode&MD_BOSS))
  1779. mob_warp(md,-1,-1,-1,-1);
  1780. }
  1781. md->next_walktime = tick+rand()%10000+5000;
  1782. }
  1783. return 0;
  1784. }
  1785. /*==========================================
  1786. * Negligent processing for mob outside PC field of view (interval timer function)
  1787. *------------------------------------------
  1788. */
  1789. static int mob_ai_lazy(int tid,unsigned int tick,int id,int data)
  1790. {
  1791. map_foreachiddb(mob_ai_sub_lazy,tick);
  1792. return 0;
  1793. }
  1794. /*==========================================
  1795. * The structure object for item drop with delay
  1796. * Since it is only two being able to pass [ int ] a timer function
  1797. * Data is put in and passed to this structure object.
  1798. *------------------------------------------
  1799. */
  1800. struct delay_item_drop {
  1801. int m,x,y;
  1802. struct item item_data;
  1803. struct map_session_data *first_sd,*second_sd,*third_sd;
  1804. };
  1805. /*==========================================
  1806. * Initializes the delay drop structure for mob-dropped items.
  1807. *------------------------------------------
  1808. */
  1809. static struct delay_item_drop* mob_setdropitem(int nameid, int qty, int m, int x, int y,
  1810. struct map_session_data* first_sd, struct map_session_data* second_sd, struct map_session_data* third_sd)
  1811. {
  1812. struct delay_item_drop *drop = aCalloc(1, sizeof (struct delay_item_drop));
  1813. drop->item_data.nameid = nameid;
  1814. drop->item_data.amount = qty;
  1815. drop->item_data.identify = !itemdb_isequip3(nameid);
  1816. drop->m = m;
  1817. drop->x = x;
  1818. drop->y = y;
  1819. drop->first_sd = first_sd;
  1820. drop->second_sd = second_sd;
  1821. drop->third_sd = third_sd;
  1822. return drop;
  1823. };
  1824. /*==========================================
  1825. * Initializes the delay drop structure for mob-looted items.
  1826. *------------------------------------------
  1827. */
  1828. static struct delay_item_drop* mob_setlootitem(struct item* item, int m, int x, int y,
  1829. struct map_session_data* first_sd, struct map_session_data* second_sd, struct map_session_data* third_sd)
  1830. {
  1831. struct delay_item_drop *drop = aCalloc(1, sizeof (struct delay_item_drop));
  1832. memcpy(&drop->item_data, item, sizeof(struct item));
  1833. drop->m = m;
  1834. drop->x = x;
  1835. drop->y = y;
  1836. drop->first_sd = first_sd;
  1837. drop->second_sd = second_sd;
  1838. drop->third_sd = third_sd;
  1839. return drop;
  1840. };
  1841. /*==========================================
  1842. * item drop with delay (timer function)
  1843. *------------------------------------------
  1844. */
  1845. static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
  1846. {
  1847. struct delay_item_drop *ditem;
  1848. ditem=(struct delay_item_drop *)id;
  1849. map_addflooritem(&ditem->item_data,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
  1850. aFree(ditem);
  1851. return 0;
  1852. }
  1853. /*==========================================
  1854. * Sets a timer to drop an item on the ground
  1855. * Also performs logging and autoloot if enabled.
  1856. * rate is the drop-rate of the item, required for autoloot.
  1857. *------------------------------------------
  1858. * by [Skotlex]
  1859. */
  1860. static void mob_item_drop(struct mob_data *md, unsigned int tick, struct delay_item_drop * ditem, int loot, int drop_rate)
  1861. {
  1862. if(log_config.pick > 0)
  1863. { //Logs items, dropped by mobs [Lupus]
  1864. if (loot)
  1865. log_pick((struct map_session_data*)md, "L", md->class_, ditem->item_data.nameid, -ditem->item_data.amount, &ditem->item_data);
  1866. else
  1867. log_pick((struct map_session_data*)md, "M", md->class_, ditem->item_data.nameid, -ditem->item_data.amount, NULL);
  1868. }
  1869. if (ditem->first_sd && ditem->first_sd->state.autoloot &&
  1870. (drop_rate <= ditem->first_sd->state.autoloot ||
  1871. ditem->first_sd->state.autoloot >= 10000) //Fetch 100% drops
  1872. ) { //Autoloot.
  1873. if (party_share_loot(
  1874. ditem->first_sd->status.party_id?
  1875. party_search(ditem->first_sd->status.party_id):
  1876. NULL,
  1877. ditem->first_sd,&ditem->item_data) == 0
  1878. ) {
  1879. aFree(ditem);
  1880. return;
  1881. }
  1882. }
  1883. add_timer(tick, mob_delay_item_drop, (int)ditem, 0);
  1884. }
  1885. /*==========================================
  1886. * mob data is erased.
  1887. *------------------------------------------
  1888. */
  1889. void mob_unload(struct mob_data *md)
  1890. {
  1891. nullpo_retv(md);
  1892. mob_remove_map(md, 0);
  1893. map_deliddb(&md->bl);
  1894. map_freeblock((struct block_list*)md);
  1895. }
  1896. int mob_remove_map(struct mob_data *md, int type)
  1897. {
  1898. nullpo_retr(1, md);
  1899. if(md->bl.prev == NULL)
  1900. return 1;
  1901. mob_changestate(md,MS_DEAD,0);
  1902. clif_clearchar_area(&md->bl,type);
  1903. map_delblock(&md->bl);
  1904. if (md->lootitem){
  1905. aFree(md->lootitem);
  1906. md->lootitem = NULL;
  1907. }
  1908. if (md->guardian_data)
  1909. {
  1910. aFree(md->guardian_data);
  1911. md->guardian_data = NULL;
  1912. }
  1913. return 0;
  1914. }
  1915. int mob_delete(struct mob_data *md)
  1916. {
  1917. nullpo_retr(1, md);
  1918. mob_remove_map(md, 1);
  1919. if(pcdb_checkid(mob_get_viewclass(md->class_))) //Player mobs are not removed automatically by the client.
  1920. clif_clearchar_delay(gettick()+3000,&md->bl,0);
  1921. if(mob_is_clone(md->class_))
  1922. mob_clone_delete(md->class_);
  1923. mob_deleteslave(md);
  1924. mob_setdelayspawn(md->bl.id);
  1925. return 0;
  1926. }
  1927. int mob_timer_delete(int tid, unsigned int tick, int id, int data)
  1928. {
  1929. struct mob_data *md=(struct mob_data *)map_id2bl(id);
  1930. nullpo_retr(0, md);
  1931. //for Alchemist CANNIBALIZE [Lupus]
  1932. mob_remove_map(md, 3);
  1933. mob_setdelayspawn(md->bl.id);
  1934. return 0;
  1935. }
  1936. /*==========================================
  1937. *
  1938. *------------------------------------------
  1939. */
  1940. int mob_deleteslave_sub(struct block_list *bl,va_list ap)
  1941. {
  1942. struct mob_data *md;
  1943. int id;
  1944. nullpo_retr(0, bl);
  1945. nullpo_retr(0, ap);
  1946. nullpo_retr(0, md = (struct mob_data *)bl);
  1947. id=va_arg(ap,int);
  1948. if(md->master_id > 0 && md->master_id == id )
  1949. mob_damage(NULL,md,md->hp,1);
  1950. return 0;
  1951. }
  1952. /*==========================================
  1953. *
  1954. *------------------------------------------
  1955. */
  1956. int mob_deleteslave(struct mob_data *md)
  1957. {
  1958. nullpo_retr(0, md);
  1959. map_foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
  1960. return 0;
  1961. }
  1962. // Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
  1963. int mob_respawn(int tid, unsigned int tick, int id,int data )
  1964. {
  1965. struct mob_data *md = (struct mob_data*)map_id2bl(id);
  1966. if (!md || md->bl.type != BL_MOB)
  1967. return 0;
  1968. //Mob must be dead and not in a map to respawn!
  1969. if (md->bl.prev != NULL || md->state.state != MS_DEAD)
  1970. return 0;
  1971. md->state.state = MS_IDLE;
  1972. md->state.skillstate = MSS_IDLE;
  1973. md->timer = -1;
  1974. md->last_thinktime = tick;
  1975. md->next_walktime = tick+rand()%50+5000;
  1976. md->attackabletime = tick;
  1977. md->canmove_tick = tick;
  1978. md->last_linktime = tick;
  1979. map_addblock(&md->bl);
  1980. mob_heal(md,data*status_get_max_hp(&md->bl)/100);
  1981. skill_unit_move(&md->bl,tick,1);
  1982. clif_spawnmob(md);
  1983. mobskill_use(md, tick, MSC_SPAWN);
  1984. return 1;
  1985. }
  1986. /*==========================================
  1987. * It is the damage of sd to damage to md.
  1988. *------------------------------------------
  1989. */
  1990. int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
  1991. {
  1992. int i,count,minpos,mindmg;
  1993. struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE];
  1994. struct {
  1995. struct party *p;
  1996. int id,zeny;
  1997. unsigned int base_exp,job_exp;
  1998. } pt[DAMAGELOG_SIZE];
  1999. int pnum=0;
  2000. int mvp_damage,max_hp;
  2001. unsigned int tick = gettick();
  2002. struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL;
  2003. double temp;
  2004. struct item item;
  2005. int ret, mode;
  2006. int drop_rate;
  2007. int base_drop_delay;
  2008. int race;
  2009. nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
  2010. max_hp = status_get_max_hp(&md->bl);
  2011. race = status_get_race(&md->bl);
  2012. if(src && src->type == BL_PC) {
  2013. sd = (struct map_session_data *)src;
  2014. mvp_sd = sd;
  2015. }
  2016. if(md->bl.prev==NULL){
  2017. if(battle_config.error_log==1)
  2018. ShowError("mob_damage : BlockError!!\n");
  2019. return 0;
  2020. }
  2021. if(md->state.state==MS_DEAD || md->hp<=0) {
  2022. if(md->bl.prev != NULL) {
  2023. mob_changestate(md,MS_DEAD,0);
  2024. mobskill_use(md,tick,-1); // It is skill at the time of death.
  2025. clif_clearchar_area(&md->bl,1);
  2026. map_delblock(&md->bl);
  2027. mob_setdelayspawn(md->bl.id);
  2028. }
  2029. return 0;
  2030. }
  2031. if(md->sc.count) {
  2032. if(md->sc.data[SC_CONFUSION].timer != -1)
  2033. status_change_end(&md->bl, SC_CONFUSION, -1);
  2034. if(md->sc.data[SC_HIDING].timer != -1)
  2035. status_change_end(&md->bl, SC_HIDING, -1);
  2036. if(md->sc.data[SC_CLOAKING].timer != -1)
  2037. status_change_end(&md->bl, SC_CLOAKING, -1);
  2038. }
  2039. if(damage > max_hp>>2)
  2040. skill_stop_dancing(&md->bl);
  2041. if(md->hp > max_hp)
  2042. md->hp = max_hp;
  2043. // The amount of overkill rounds to hp.
  2044. if(damage>md->hp)
  2045. damage=md->hp;
  2046. md->hp-=damage;
  2047. md->tdmg+=damage; //Store total damage...
  2048. if(!(type&2)) {
  2049. int id = 0;
  2050. if (src) {
  2051. switch (src->type) {
  2052. case BL_PC:
  2053. id = sd->status.char_id;
  2054. if(md->attacked_id <= 0)
  2055. md->attacked_id = sd->bl.id;
  2056. break;
  2057. case BL_PET:
  2058. {
  2059. struct pet_data *pd = (struct pet_data*)src;
  2060. if (battle_config.pet_attack_exp_to_master) {
  2061. id = pd->msd->status.char_id;
  2062. damage=(damage*battle_config.pet_attack_exp_rate)/100; //Modify logged damage accordingly.
  2063. }
  2064. //Let mobs retaliate against the pet's master [Skotlex]
  2065. if(md->attacked_id <= 0)
  2066. md->attacked_id = pd->msd->bl.id;
  2067. break;
  2068. }
  2069. case BL_MOB:
  2070. {
  2071. struct mob_data* md2 = (struct mob_data*)src;
  2072. if(md2->special_state.ai && md2->master_id) {
  2073. struct map_session_data* msd = map_id2sd(md2->master_id);
  2074. if (msd) id = msd->status.char_id;
  2075. }
  2076. if(md->attacked_id <= 0)
  2077. { //Let players decide whether to retaliate versus the master or the mob. [Skotlex]
  2078. if (md2->master_id && battle_config.retaliate_to_master)
  2079. md->attacked_id = md2->master_id;
  2080. else
  2081. md->attacked_id = md2->bl.id;
  2082. }
  2083. break;
  2084. }
  2085. }
  2086. }
  2087. //Log damage...
  2088. if (id && damage > 0) {
  2089. for(i=0,minpos=DAMAGELOG_SIZE-1,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
  2090. if(md->dmglog[i].id==id)
  2091. break;
  2092. if(md->dmglog[i].id==0) { //Store data in first empty slot.
  2093. md->dmglog[i].id = id;
  2094. break;
  2095. }
  2096. if(md->dmglog[i].dmg<mindmg){
  2097. minpos=i;
  2098. mindmg=md->dmglog[i].dmg;
  2099. }
  2100. }
  2101. if(i<DAMAGELOG_SIZE)
  2102. md->dmglog[i].dmg+=damage;
  2103. else {
  2104. md->dmglog[minpos].id=id;
  2105. md->dmglog[minpos].dmg=damage;
  2106. }
  2107. }
  2108. }
  2109. if(md->guardian_data && md->guardian_data->number < MAX_GUARDIANS) { // guardian hp update [Valaris] (updated by [Skotlex])
  2110. if ((md->guardian_data->castle->guardian[md->guardian_data->number].hp = md->hp) <= 0)
  2111. {
  2112. guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  2113. guild_castledatasave(md->guardian_data->castle->castle_id, 18+md->guardian_data->number,0);
  2114. }
  2115. } // end addition
  2116. if(md->special_state.ai == 2 && //スフィアーマイン
  2117. src && md->master_id == src->id)
  2118. {
  2119. md->state.alchemist = 1;
  2120. md->target_dir = map_calc_dir(src,md->bl.x,md->bl.y)+1;
  2121. mobskill_use(md, tick, MSC_ALCHEMIST);
  2122. }
  2123. if (battle_config.show_mob_hp)
  2124. clif_charnameack (0, &md->bl);
  2125. if(md->hp > 0)
  2126. return damage;
  2127. // ----- ここから死亡処理 -----
  2128. mode = status_get_mode(&md->bl); //Mode will be used for various checks regarding exp/drops.
  2129. //changestate will clear all status effects, so we need to know if RICHMANKIM is in effect before then. [Skotlex]
  2130. //I just recycled ret because it isn't used until much later and I didn't want to add a new variable for it.
  2131. ret = (md->sc.data[SC_RICHMANKIM].timer != -1)?(25 + 11*md->sc.data[SC_RICHMANKIM].val1):0;
  2132. md->state.skillstate = MSS_DEAD;
  2133. mobskill_use(md,tick,-1); //On Dead skill.
  2134. if (md->sc.data[SC_KAIZEL].timer != -1) {
  2135. //Revive in a bit.
  2136. max_hp = 10*md->sc.data[SC_KAIZEL].val1; //% of life to rebirth with
  2137. mob_changestate(md,MS_DEAD,0);
  2138. clif_clearchar_area(&md->bl,1);
  2139. map_delblock(&md->bl);
  2140. add_timer(gettick()+3000, mob_respawn, md->bl.id, max_hp);
  2141. return damage;
  2142. }
  2143. map_freeblock_lock();
  2144. mob_changestate(md,MS_DEAD,0);
  2145. memset(tmpsd,0,sizeof(tmpsd));
  2146. memset(pt,0,sizeof(pt));
  2147. max_hp = status_get_max_hp(&md->bl);
  2148. if(src && src->type == BL_MOB)
  2149. mob_unlocktarget((struct mob_data *)src,tick);
  2150. base_drop_delay = battle_config.delay_battle_damage?0:500;
  2151. if(sd) {
  2152. int sp = 0, hp = 0;
  2153. if (sd->state.attack_type == BF_MAGIC)
  2154. base_drop_delay = 500;
  2155. if (sd->state.attack_type == BF_MAGIC && sd->skilltarget == md->bl.id && (i=pc_checkskill(sd,HW_SOULDRAIN))>0)
  2156. { //Soul Drain should only work on targetted spells [Skotlex]
  2157. if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
  2158. clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,i,1);
  2159. sp += (status_get_lv(&md->bl))*(65+15*i)/100;
  2160. }
  2161. sp += sd->sp_gain_value;
  2162. sp += sd->sp_gain_race[race];
  2163. sp += sd->sp_gain_race[mode&MD_BOSS?10:11];
  2164. hp += sd->hp_gain_value;
  2165. if (sp > 0) {
  2166. if(sd->status.sp + sp > sd->status.max_sp)
  2167. sp = sd->status.max_sp - sd->status.sp;
  2168. sd->status.sp += sp;
  2169. if (sp > 0 && battle_config.show_hp_sp_gain)
  2170. clif_heal(sd->fd,SP_SP,sp);
  2171. }
  2172. if (hp > 0) {
  2173. if(sd->status.hp + hp > sd->status.max_hp)
  2174. hp = sd->status.max_hp - sd->status.hp;
  2175. sd->status.hp += hp;
  2176. if (hp > 0 && battle_config.show_hp_sp_gain)
  2177. clif_heal(sd->fd,SP_HP,hp);
  2178. }
  2179. if (sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex]
  2180. //Recycling hp for new random target id...
  2181. if (++sd->mission_count >= 100 && (hp = mob_get_random_id(0, 0, sd->status.base_level)))
  2182. {
  2183. pc_addfame(sd, 1);
  2184. sd->mission_mobid = hp;
  2185. pc_setglobalreg(sd,"TK_MISSION_ID", hp);
  2186. sd->mission_count = 0;
  2187. clif_mission_mob(sd, hp, 0);
  2188. }
  2189. pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count);
  2190. }
  2191. }
  2192. // map外に消えた人は計算から除くので
  2193. // overkill分は無いけどsumはmax_hpとは違う
  2194. for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){
  2195. if(md->dmglog[i].id==0)
  2196. break; //Reached end of log.
  2197. count++; //Count an attacker even if he is dead/logged-out.
  2198. tmpsd[i] = map_charid2sd(md->dmglog[i].id);
  2199. if(tmpsd[i] == NULL)
  2200. continue;
  2201. if(tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
  2202. continue;
  2203. if(mvp_damage<md->dmglog[i].dmg){
  2204. third_sd = second_sd;
  2205. second_sd = mvp_sd;
  2206. mvp_sd=tmpsd[i];
  2207. mvp_damage=md->dmglog[i].dmg;
  2208. }
  2209. }
  2210. // [MouseJstr]
  2211. if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
  2212. // 経験値の分配
  2213. for(i=0;i<DAMAGELOG_SIZE;i++){
  2214. int pid,flag=1,zeny=0;
  2215. unsigned int base_exp,job_exp;
  2216. double per;
  2217. struct party *p;
  2218. if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
  2219. continue;
  2220. if (battle_config.exp_calc_type) // eAthena's exp formula based on max hp.
  2221. per = (double)md->dmglog[i].dmg/(double)max_hp;
  2222. else //jAthena's exp formula based on total damage.
  2223. per = (double)md->dmglog[i].dmg/(double)md->tdmg;
  2224. if (count>1)
  2225. per *= (9.+(double)((count > 6)? 6:count))/10.; //attackers count bonus.
  2226. base_exp = md->db->base_exp;
  2227. job_exp = md->db->job_exp;
  2228. if (ret)
  2229. per += per*ret/100.; //SC_RICHMANKIM bonus. [Skotlex]
  2230. if(sd) {
  2231. if (sd->expaddrace[race])
  2232. per += per*sd->expaddrace[race]/100.;
  2233. per += per*sd->expaddrace[mode&MD_BOSS?10:11]/100.;
  2234. }
  2235. if (battle_config.pk_mode && (md->db->lv - tmpsd[i]->status.base_level >= 20))
  2236. per *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris]
  2237. //SG additional exp from Blessings [Komurka] - probably can be optimalized ^^;;
  2238. if (tmpsd[i]->sc.data[SC_MIRACLE].timer!=-1)
  2239. per += per*20*pc_checkskill(tmpsd[i],SG_STAR_BLESS)/100.;
  2240. else if(md->class_ == tmpsd[i]->hate_mob[0] && (battle_config.allow_skill_without_day || is_day_of_sun()))
  2241. per += per*10*pc_checkskill(tmpsd[i],SG_SUN_BLESS)/100.;
  2242. else if(md->class_ == tmpsd[i]->hate_mob[1] && (battle_config.allow_skill_without_day || is_day_of_moon()))
  2243. per += per*10*pc_checkskill(tmpsd[i],SG_MOON_BLESS)/100.;
  2244. else if(md->class_ == tmpsd[i]->hate_mob[2] && (battle_config.allow_skill_without_day || is_day_of_star()))
  2245. per += per*20*pc_checkskill(tmpsd[i],SG_STAR_BLESS)/100.;
  2246. if(md->special_state.size==1) // change experience for different sized monsters [Valaris]
  2247. per /=2.;
  2248. else if(md->special_state.size==2)
  2249. per *=2.;
  2250. if(md->master_id && md->special_state.ai) //New rule: Only player-summoned mobs do not give exp. [Skotlex]
  2251. per = 0;
  2252. else {
  2253. if(battle_config.zeny_from_mobs) {
  2254. if(md->level > 0) zeny=(int) ((md->level+rand()%md->level)*per); // zeny calculation moblv + random moblv [Valaris]
  2255. if(md->db->mexp > 0)
  2256. zeny*=rand()%250;
  2257. if(md->special_state.size==1 && zeny >=2) // change zeny for different sized monsters [Valaris]
  2258. zeny/=2;
  2259. else if(md->special_state.size==2 && zeny >1)
  2260. zeny*=2;
  2261. }
  2262. if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris]
  2263. per+= per*(md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate/100;
  2264. }
  2265. if (per > 4) per = 4; //Limit gained exp to quadro the mob's exp. [3->4 Komurka]
  2266. if (base_exp*per > UINT_MAX)
  2267. base_exp = UINT_MAX;
  2268. else
  2269. base_exp = (unsigned int)(base_exp*per);
  2270. if (job_exp*per > UINT_MAX)
  2271. job_exp = UINT_MAX;
  2272. else
  2273. job_exp = (unsigned int)(job_exp*per);
  2274. if (base_exp < 1) base_exp = 1;
  2275. if (job_exp < 1) job_exp = 1;
  2276. //mapflags: noexp check [Lorky]
  2277. if (map[md->bl.m].flag.nobaseexp == 1) base_exp=0;
  2278. if (map[md->bl.m].flag.nojobexp == 1) job_exp=0;
  2279. //end added Lorky
  2280. if((pid=tmpsd[i]->status.party_id)>0){ // パーティに入っている
  2281. int j;
  2282. for(j=0;j<pnum;j++) // 公平パーティリストにいるかどうか
  2283. if(pt[j].id==pid)
  2284. break;
  2285. if(j==pnum){ // いないときは公平かどうか確認
  2286. if((p=party_search(pid))!=NULL && p->exp!=0){
  2287. pt[pnum].id=pid;
  2288. pt[pnum].p=p;
  2289. pt[pnum].base_exp=base_exp;
  2290. pt[pnum].job_exp=job_exp;
  2291. if(battle_config.zeny_from_mobs)
  2292. pt[pnum].zeny=zeny; // zeny share [Valaris]
  2293. pnum++;
  2294. flag=0;
  2295. }
  2296. }else{ // いるときは公平
  2297. if (pt[j].base_exp > UINT_MAX - base_exp)
  2298. pt[j].base_exp=UINT_MAX;
  2299. else
  2300. pt[j].base_exp+=base_exp;
  2301. if (pt[j].job_exp > UINT_MAX - job_exp)
  2302. pt[j].job_exp=UINT_MAX;
  2303. else
  2304. pt[j].job_exp+=job_exp;
  2305. if(battle_config.zeny_from_mobs)
  2306. pt[j].zeny+=zeny; // zeny share [Valaris]
  2307. flag=0;
  2308. }
  2309. }
  2310. if(flag) { // added zeny from mobs [Valaris]
  2311. if(base_exp > 0 || job_exp > 0)
  2312. pc_gainexp(tmpsd[i],base_exp,job_exp);
  2313. if (battle_config.zeny_from_mobs && zeny > 0) {
  2314. pc_getzeny(tmpsd[i],zeny); // zeny from mobs [Valaris]
  2315. }
  2316. }
  2317. }
  2318. // 公平分配
  2319. for(i=0;i<pnum;i++)
  2320. party_exp_share(pt[i].p,md->bl.m,pt[i].base_exp,pt[i].job_exp,pt[i].zeny);
  2321. // item drop
  2322. if (!(type&1)) {
  2323. int drop_ore = -1, drop_items = 0; //slot N for DROP LOG, number of dropped items
  2324. int log_item[10]; //8 -> 10 Lupus
  2325. memset(&log_item,0,sizeof(log_item));
  2326. for (i = 0; i < 10; i++) { // 8 -> 10 Lupus
  2327. struct delay_item_drop *ditem;
  2328. if (md->master_id && md->special_state.ai && (
  2329. battle_config.alchemist_summon_reward == 0 || //Noone gives items
  2330. (md->class_ != 1142 && battle_config.alchemist_summon_reward == 1) //Non Marine spheres don't drop items
  2331. ))
  2332. break; // End
  2333. //mapflag: noloot check [Lorky]
  2334. if (map[md->bl.m].flag.nomobloot) break;;
  2335. //end added [Lorky]
  2336. if (md->db->dropitem[i].nameid <= 0)
  2337. continue;
  2338. drop_rate = md->db->dropitem[i].p;
  2339. if (drop_rate <= 0 && !battle_config.drop_rate0item)
  2340. drop_rate = 1;
  2341. // change drops depending on monsters size [Valaris]
  2342. if(md->special_state.size==1 && drop_rate >= 2)
  2343. drop_rate/=2;
  2344. else if(md->special_state.size==2 && drop_rate > 0)
  2345. drop_rate*=2;
  2346. //Drops affected by luk as a fixed increase [Valaris]
  2347. if (src && battle_config.drops_by_luk > 0)
  2348. drop_rate += status_get_luk(src)*battle_config.drops_by_luk/100;
  2349. //Drops affected by luk as a % increase [Skotlex]
  2350. if (src && battle_config.drops_by_luk2 > 0)
  2351. drop_rate += (int)(0.5+drop_rate*status_get_luk(src)*battle_config.drops_by_luk2/10000.0);
  2352. if (sd && battle_config.pk_mode == 1 && (md->db->lv - sd->status.base_level >= 20))
  2353. drop_rate = (int)(drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris]
  2354. if (drop_rate < rand() % 10000 + 1) { //fixed 0.01% impossible drops bug [Lupus]
  2355. drop_ore = i; //we remember an empty slot to put there ORE DISCOVERY drop later.
  2356. continue;
  2357. }
  2358. drop_items++; //we count if there were any drops
  2359. ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
  2360. log_item[i] = ditem->item_data.nameid;
  2361. //A Rare Drop Global Announce by Lupus
  2362. if(drop_rate<=battle_config.rare_drop_announce) {
  2363. struct item_data *i_data;
  2364. char message[128];
  2365. i_data = itemdb_exists(ditem->item_data.nameid);
  2366. sprintf (message, msg_txt(541), (mvp_sd?mvp_sd->status.name:"???"), md->db->jname, i_data->jname, (float)drop_rate/100);
  2367. //MSG: "'%s' won %s's %s (chance: %%%0.02f)"
  2368. intif_GMmessage(message,strlen(message)+1,0);
  2369. }
  2370. // Announce first, or else ditem will be freed. [Lance]
  2371. // By popular demand, use base drop rate for autoloot code. [Skotlex]
  2372. mob_item_drop(md, tick+base_drop_delay+i, ditem, 0, md->db->dropitem[i].p);
  2373. }
  2374. // Ore Discovery [Celest]
  2375. if (sd == mvp_sd && map[md->bl.m].flag.nomobloot==0 && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rand()%10000) {
  2376. struct delay_item_drop *ditem;
  2377. ditem = mob_setdropitem(itemdb_searchrandomid(6), 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
  2378. if (drop_ore<0) drop_ore=8; //we have only 10 slots in LOG, there's a check to not overflow (9th item usually a card, so we use 8th slot)
  2379. log_item[drop_ore] = ditem->item_data.nameid; //it's for logging only
  2380. drop_items++; //we count if there were any drops
  2381. mob_item_drop(md, tick+base_drop_delay+drop_ore, ditem, 0, battle_config.finding_ore_rate/10);
  2382. }
  2383. //this drop log contains ALL dropped items + ORE (if there was ORE Recovery) [Lupus]
  2384. if(sd && log_config.drop > 0 && drop_items) //we check were there any drops.. and if not - don't write the log
  2385. log_drop(sd, md->class_, log_item); //mvp_sd
  2386. if(sd/* && sd->state.attack_type == BF_WEAPON*/) { //Player reports indicate this SHOULD work with all skills. [Skotlex]
  2387. int itemid = 0;
  2388. for (i = 0; i < sd->add_drop_count; i++) {
  2389. struct delay_item_drop *ditem;
  2390. if (sd->add_drop[i].id < 0)
  2391. continue;
  2392. if (sd->add_drop[i].race & (1<<race) ||
  2393. sd->add_drop[i].race & 1<<(mode&MD_BOSS?10:11))
  2394. {
  2395. //check if the bonus item drop rate should be multiplied with mob level/10 [Lupus]
  2396. if(sd->add_drop[i].rate<0)
  2397. //it's negative, then it should be multiplied. e.g. for Mimic,Myst Case Cards, etc
  2398. // rate = base_rate * (mob_level/10) + 1
  2399. drop_rate = -sd->add_drop[i].rate*(md->level/10)+1;
  2400. else
  2401. //it's positive, then it goes as it is
  2402. drop_rate = sd->add_drop[i].rate;
  2403. if (drop_rate < rand()%10000 +1)
  2404. continue;
  2405. itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id :
  2406. itemdb_searchrandomgroup(sd->add_drop[i].group);
  2407. ditem = mob_setdropitem(itemid, 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
  2408. mob_item_drop(md, tick+base_drop_delay+20+i, ditem, 0, drop_rate);
  2409. }
  2410. }
  2411. if(sd->get_zeny_num && rand()%100 < sd->get_zeny_rate) //Gets get_zeny_num per level +/-10% [Skotlex]
  2412. pc_getzeny(sd,md->db->lv*sd->get_zeny_num*(90+rand()%21)/100);
  2413. }
  2414. if(md->lootitem) {
  2415. for(i=0;i<md->lootitem_count;i++) {
  2416. struct delay_item_drop *ditem;
  2417. ditem = mob_setlootitem(&md->lootitem[i], md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
  2418. mob_item_drop(md, tick+base_drop_delay+40+i, ditem, 1, 10000);
  2419. }
  2420. }
  2421. }
  2422. // mvp処理
  2423. if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai){
  2424. int log_mvp[2] = {0};
  2425. int j;
  2426. int mexp;
  2427. temp = ((double)md->db->mexp * (9.+(double)count)/10.); //[Gengar]
  2428. mexp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
  2429. //mapflag: noexp check [Lorky]
  2430. if (map[md->bl.m].flag.nobaseexp == 1 || map[md->bl.m].flag.nojobexp == 1) mexp=1;
  2431. //end added [Lorky]
  2432. if(mexp < 1) mexp = 1;
  2433. if(use_irc && irc_announce_mvp_flag)
  2434. irc_announce_mvp(mvp_sd,md);
  2435. clif_mvp_effect(mvp_sd); // エフェクト
  2436. clif_mvp_exp(mvp_sd,mexp);
  2437. pc_gainexp(mvp_sd,mexp,0);
  2438. log_mvp[1] = mexp;
  2439. for(j=0;j<3;j++){
  2440. i = rand() % 3;
  2441. //mapflag: noloot check [Lorky]
  2442. if (map[md->bl.m].flag.nomvploot == 1) break;
  2443. //end added Lorky
  2444. if(md->db->mvpitem[i].nameid <= 0)
  2445. continue;
  2446. drop_rate = md->db->mvpitem[i].p;
  2447. if(drop_rate <= 0 && !battle_config.drop_rate0item)
  2448. drop_rate = 1;
  2449. if(drop_rate <= rand()%10000+1) //if ==0, then it doesn't drop
  2450. continue;
  2451. memset(&item,0,sizeof(item));
  2452. item.nameid=md->db->mvpitem[i].nameid;
  2453. item.identify=!itemdb_isequip3(item.nameid);
  2454. clif_mvp_item(mvp_sd,item.nameid);
  2455. log_mvp[0] = item.nameid;
  2456. if(mvp_sd->weight*2 > mvp_sd->max_weight)
  2457. map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd,second_sd,third_sd,1);
  2458. else if((ret = pc_additem(mvp_sd,&item,1))) {
  2459. clif_additem(sd,0,0,ret);
  2460. map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd,second_sd,third_sd,1);
  2461. }
  2462. //A Rare MVP Drop Global Announce by Lupus
  2463. if(drop_rate<=battle_config.rare_drop_announce) {
  2464. struct item_data *i_data;
  2465. char message[128];
  2466. i_data = itemdb_exists(item.nameid);
  2467. sprintf (message, msg_txt(541), mvp_sd?mvp_sd->status.name :"???", md->db->jname, i_data->jname, (float)drop_rate/100);
  2468. //MSG: "'%s' won %s's %s (chance: %%%0.02f)"
  2469. intif_GMmessage(message,strlen(message)+1,0);
  2470. }
  2471. if(log_config.pick > 0) {//Logs items, MVP prizes [Lupus]
  2472. log_pick((struct map_session_data*)md, "M", md->class_, item.nameid, -1, NULL);
  2473. log_pick(mvp_sd, "P", 0, item.nameid, 1, NULL);
  2474. }
  2475. break;
  2476. }
  2477. if(log_config.mvpdrop > 0)
  2478. log_mvpdrop(mvp_sd, md->class_, log_mvp);
  2479. }
  2480. } // [MouseJstr]
  2481. // <Agit> NPC Event [OnAgitBreak]
  2482. if(md->npc_event[0] && strcmp(((md->npc_event)+strlen(md->npc_event)-13),"::OnAgitBreak") == 0) {
  2483. ShowNotice("MOB.C: Run NPC_Event[OnAgitBreak].\n");
  2484. if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak]
  2485. guild_agit_break(md);
  2486. }
  2487. // SCRIPT実行
  2488. if(md->npc_event[0]){
  2489. // if(battle_config.battle_log)
  2490. // printf("mob_damage : run event : %s\n",md->npc_event);
  2491. if(src && src->type == BL_PET)
  2492. sd = ((struct pet_data *)src)->msd;
  2493. if(sd && battle_config.mob_npc_event_type)
  2494. npc_event(sd,md->npc_event,0);
  2495. else if(mvp_sd)
  2496. npc_event(mvp_sd,md->npc_event,0);
  2497. } else if (mvp_sd) {
  2498. //lordalfa
  2499. pc_setglobalreg(mvp_sd,"killedrid",(md->class_));
  2500. if (script_config.event_script_type == 0) {
  2501. struct npc_data *npc;
  2502. if ((npc = npc_name2id("NPCKillEvent"))) {
  2503. run_script(npc->u.scr.script,0,mvp_sd->bl.id,npc->bl.id); // NPCKillNPC
  2504. ShowStatus("Event '"CL_WHITE"NPCKillEvent"CL_RESET"' executed.\n");
  2505. }
  2506. } else {
  2507. ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
  2508. npc_event_doall_id("NPCKillEvent", mvp_sd->bl.id), "NPCKillEvent");
  2509. }
  2510. }
  2511. //[lordalfa]
  2512. (battle_config.mob_clear_delay) ? clif_clearchar_delay(tick+battle_config.mob_clear_delay,&md->bl,1) : clif_clearchar_area(&md->bl,1);
  2513. // clif_clearchar_area(&md->bl,1); //eh? Why send the same packet twice? [Skotlex]
  2514. if(md->level) md->level=0;
  2515. map_delblock(&md->bl);
  2516. if(pcdb_checkid(mob_get_viewclass(md->class_)))
  2517. clif_clearchar_delay(tick+3000,&md->bl,0);
  2518. if(mob_is_clone(md->class_))
  2519. mob_clone_delete(md->class_);
  2520. mob_deleteslave(md);
  2521. mob_setdelayspawn(md->bl.id);
  2522. map_freeblock_unlock();
  2523. return damage;
  2524. }
  2525. int mob_guardian_guildchange(struct block_list *bl,va_list ap)
  2526. {
  2527. struct mob_data *md;
  2528. struct guild* g;
  2529. nullpo_retr(0, bl);
  2530. nullpo_retr(0, md = (struct mob_data *)bl);
  2531. if (!md->guardian_data)
  2532. return 0;
  2533. if (md->guardian_data->castle->guild_id == 0)
  2534. { //Castle with no owner? Delete the guardians.
  2535. if (md->class_ == MOBID_EMPERIUM)
  2536. { //But don't delete the emperium, just clear it's guild-data
  2537. md->guardian_data->guild_id = 0;
  2538. md->guardian_data->emblem_id = 0;
  2539. md->guardian_data->guild_name[0] = '\0';
  2540. } else {
  2541. if (md->guardian_data->castle->guardian[md->guardian_data->number].visible)
  2542. { //Safe removal of guardian.
  2543. md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
  2544. guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  2545. guild_castledatasave(md->guardian_data->castle->castle_id, 18+md->guardian_data->number,0);
  2546. }
  2547. mob_delete(md); //Remove guardian.
  2548. }
  2549. return 0;
  2550. }
  2551. g = guild_search(md->guardian_data->castle->guild_id);
  2552. if (g == NULL)
  2553. { //Properly remove guardian info from Castle data.
  2554. ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id);
  2555. md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
  2556. guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  2557. guild_castledatasave(md->guardian_data->castle->castle_id, 18+md->guardian_data->number,0);
  2558. mob_delete(md);
  2559. return 0;
  2560. }
  2561. md->guardian_data->guild_id = md->guardian_data->castle->guild_id;
  2562. md->guardian_data->emblem_id = g->emblem_id;
  2563. md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP);
  2564. memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
  2565. return 1;
  2566. }
  2567. /*==========================================
  2568. * Pick a random class for the mob
  2569. *------------------------------------------
  2570. */
  2571. int mob_random_class (int *value, size_t count)
  2572. {
  2573. nullpo_retr(0, value);
  2574. // no count specified, look into the array manually, but take only max 5 elements
  2575. if (count < 1) {
  2576. count = 0;
  2577. while(count < 5 && mobdb_checkid(value[count])) count++;
  2578. if(count < 1) // nothing found
  2579. return 0;
  2580. } else {
  2581. // check if at least the first value is valid
  2582. if(mobdb_checkid(value[0]) == 0)
  2583. return 0;
  2584. }
  2585. //Pick a random value, hoping it exists. [Skotlex]
  2586. return mobdb_checkid(value[rand()%count]);
  2587. }
  2588. /*==========================================
  2589. * Change mob base class
  2590. *------------------------------------------
  2591. */
  2592. int mob_class_change (struct mob_data *md, int class_)
  2593. {
  2594. unsigned int tick = gettick();
  2595. int i, c, hp_rate;
  2596. nullpo_retr(0, md);
  2597. if (md->bl.prev == NULL)
  2598. return 0;
  2599. hp_rate = md->hp*100/status_get_max_hp(&md->bl);
  2600. clif_mob_class_change(md,class_);
  2601. md->class_ = class_;
  2602. md->db = mob_db(class_);
  2603. md->max_hp = md->db->max_hp; //Update the mob's max HP
  2604. if (battle_config.monster_class_change_full_recover) {
  2605. md->hp = md->max_hp;
  2606. memset(md->dmglog, 0, sizeof(md->dmglog));
  2607. md->tdmg = 0;
  2608. } else
  2609. md->hp = md->max_hp*hp_rate/100;
  2610. if(md->hp > md->max_hp) md->hp = md->max_hp;
  2611. else if(md->hp < 1) md->hp = 1;
  2612. memcpy(md->name,md->db->jname,NAME_LENGTH-1);
  2613. memset(&md->state,0,sizeof(md->state));
  2614. md->attacked_id = 0;
  2615. md->target_id = 0;
  2616. md->move_fail_count = 0;
  2617. md->speed = md->db->speed;
  2618. md->def_ele = md->db->element;
  2619. mob_changestate(md,MS_IDLE,0);
  2620. skill_castcancel(&md->bl,0);
  2621. md->state.skillstate = MSS_IDLE;
  2622. md->last_thinktime = tick;
  2623. md->next_walktime = tick+rand()%50+5000;
  2624. md->attackabletime = tick;
  2625. md->canmove_tick = tick;
  2626. md->last_linktime = tick;
  2627. for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
  2628. md->skilldelay[i] = c;
  2629. md->skillid=0;
  2630. md->skilllv=0;
  2631. if(md->lootitem == NULL && md->db->mode&MD_LOOTER)
  2632. md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  2633. skill_clear_unitgroup(&md->bl);
  2634. skill_cleartimerskill(&md->bl);
  2635. clif_clearchar_area(&md->bl,0);
  2636. clif_spawnmob(md);
  2637. if (battle_config.show_mob_hp)
  2638. clif_charnameack(0, &md->bl);
  2639. return 0;
  2640. }
  2641. /*==========================================
  2642. * mob回復
  2643. *------------------------------------------
  2644. */
  2645. int mob_heal(struct mob_data *md,int heal)
  2646. {
  2647. int max_hp;
  2648. nullpo_retr(0, md);
  2649. max_hp = status_get_max_hp(&md->bl);
  2650. md->hp += heal;
  2651. if( max_hp < md->hp )
  2652. md->hp = max_hp;
  2653. if(md->guardian_data && md->guardian_data->number < MAX_GUARDIANS) { // guardian hp update [Valaris] (updated by [Skotlex])
  2654. if ((md->guardian_data->castle->guardian[md->guardian_data->number].hp = md->hp) <= 0)
  2655. {
  2656. guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
  2657. guild_castledatasave(md->guardian_data->castle->castle_id, 18+md->guardian_data->number,0);
  2658. }
  2659. } // end addition
  2660. if (battle_config.show_mob_hp)
  2661. clif_charnameack(0, &md->bl);
  2662. return 0;
  2663. }
  2664. /*==========================================
  2665. * Added by RoVeRT
  2666. *------------------------------------------
  2667. */
  2668. int mob_warpslave_sub(struct block_list *bl,va_list ap)
  2669. {
  2670. struct mob_data *md=(struct mob_data *)bl;
  2671. struct block_list *master;
  2672. int x,y,range,i=0;
  2673. master = va_arg(ap, struct block_list*);
  2674. range = va_arg(ap, int);
  2675. if(md->master_id!=master->id)
  2676. return 0;
  2677. do {
  2678. x = master->x - range/2 + rand()%range;
  2679. y = master->y - range/2 + rand()%range;
  2680. } while (map_getcell(master->m,x,y,CELL_CHKNOPASS) && i<25);
  2681. if (i == 100)
  2682. mob_warp(md, master->m, master->x, master->y,2);
  2683. else
  2684. mob_warp(md, master->m, x, y,2);
  2685. return 1;
  2686. }
  2687. /*==========================================
  2688. * Added by RoVeRT
  2689. * Warps slaves. Range is the area around the master that they can
  2690. * appear in randomly.
  2691. *------------------------------------------
  2692. */
  2693. int mob_warpslave(struct block_list *bl, int range)
  2694. {
  2695. if (range < 1)
  2696. range = 1; //Min range needed to avoid crashes and stuff. [Skotlex]
  2697. return map_foreachinmap(mob_warpslave_sub, bl->m, BL_MOB, bl, range);
  2698. }
  2699. /*==========================================
  2700. * mobワープ
  2701. *------------------------------------------
  2702. */
  2703. int mob_warp(struct mob_data *md,int m,int x,int y,int type)
  2704. {
  2705. int i=0,xs=0,ys=0,bx=x,by=y;
  2706. int tick = gettick();
  2707. nullpo_retr(0, md);
  2708. if( md->bl.prev==NULL )
  2709. return 0;
  2710. if( m<0 ) m=md->bl.m;
  2711. if(type >= 0) {
  2712. if(map[md->bl.m].flag.monster_noteleport)
  2713. return 0;
  2714. if(md->sc.count) { //Clear a few status changes (taken directly from pc_setpos). [Skotlex]
  2715. if(md->sc.data[SC_TRICKDEAD].timer != -1)
  2716. status_change_end(&md->bl, SC_TRICKDEAD, -1);
  2717. if(md->sc.data[SC_BLADESTOP].timer!=-1)
  2718. status_change_end(&md->bl,SC_BLADESTOP,-1);
  2719. if(md->sc.data[SC_RUN].timer!=-1)
  2720. status_change_end(&md->bl,SC_RUN,-1);
  2721. if(md->sc.data[SC_DANCING].timer!=-1)
  2722. skill_stop_dancing(&md->bl);
  2723. if (md->sc.data[SC_DEVOTION].timer!=-1)
  2724. status_change_end(&md->bl,SC_DEVOTION,-1);
  2725. if (md->sc.data[SC_CLOSECONFINE].timer!=-1)
  2726. status_change_end(&md->bl,SC_CLOSECONFINE,-1);
  2727. if (md->sc.data[SC_CLOSECONFINE2].timer!=-1)
  2728. status_change_end(&md->bl,SC_CLOSECONFINE2,-1);
  2729. if (md->sc.data[SC_RUN].timer!=-1)
  2730. status_change_end(&md->bl,SC_RUN,-1);
  2731. }
  2732. clif_clearchar_area(&md->bl,type);
  2733. }
  2734. skill_unit_move(&md->bl,tick,4);
  2735. map_delblock(&md->bl);
  2736. if(bx>0 && by>0){ // 位置指定の場合周囲9セルを探索
  2737. xs=ys=9;
  2738. }
  2739. while( ( x<0 || y<0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<1000 ){
  2740. if( xs>0 && ys>0 && i<250 ){ // 指定位置付近の探索
  2741. x=bx+rand()%xs-xs/2;
  2742. y=by+rand()%ys-ys/2;
  2743. }else{ // 完全ランダム探索
  2744. x=rand()%(map[m].xs-2)+1;
  2745. y=rand()%(map[m].ys-2)+1;
  2746. }
  2747. }
  2748. md->dir=0;
  2749. if(i<1000){
  2750. md->bl.x=md->to_x=x;
  2751. md->bl.y=md->to_y=y;
  2752. md->bl.m=m;
  2753. }else {
  2754. m=md->bl.m;
  2755. if(battle_config.error_log==1)
  2756. ShowWarning("MOB %d warp failed, class = %d\n",md->bl.id,md->class_);
  2757. }
  2758. md->target_id=0; // タゲを解除する
  2759. md->state.targettype=NONE_ATTACKABLE;
  2760. md->attacked_id=0;
  2761. if (md->master_id)
  2762. md->master_dist = 0; //Assume mob warped to leader. [Skotlex]
  2763. md->state.skillstate=MSS_IDLE;
  2764. mob_changestate(md,MS_IDLE,0);
  2765. if(type>0 && i==1000) {
  2766. if(battle_config.battle_log)
  2767. ShowInfo("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class_);
  2768. }
  2769. map_addblock(&md->bl);
  2770. skill_unit_move(&md->bl,tick,1);
  2771. if(type>0)
  2772. {
  2773. clif_spawnmob(md);
  2774. mob_warpslave(&md->bl,AREA_SIZE);
  2775. }
  2776. return 0;
  2777. }
  2778. /*==========================================
  2779. * 画面内の取り巻きの数計算用(foreachinarea)
  2780. *------------------------------------------
  2781. */
  2782. int mob_countslave_sub(struct block_list *bl,va_list ap)
  2783. {
  2784. int id;
  2785. struct mob_data *md;
  2786. id=va_arg(ap,int);
  2787. md = (struct mob_data *)bl;
  2788. if( md->master_id==id )
  2789. return 1;
  2790. return 0;
  2791. }
  2792. /*==========================================
  2793. * 画面内の取り巻きの数計算
  2794. *------------------------------------------
  2795. */
  2796. int mob_countslave(struct block_list *bl)
  2797. {
  2798. return map_foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id);
  2799. }
  2800. /*==========================================
  2801. * Summons amount slaves contained in the value[5] array using round-robin. [adapted by Skotlex]
  2802. *------------------------------------------
  2803. */
  2804. int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id)
  2805. {
  2806. struct mob_data *md;
  2807. int bx,by,m,count = 0,class_,k=0;
  2808. nullpo_retr(0, md2);
  2809. nullpo_retr(0, value);
  2810. bx=md2->bl.x;
  2811. by=md2->bl.y;
  2812. m=md2->bl.m;
  2813. if(mobdb_checkid(value[0]) == 0)
  2814. return 0;
  2815. while(count < 5 && mobdb_checkid(value[count])) count++;
  2816. if(count < 1) return 0;
  2817. if (amount > 0 && amount < count) { //Do not start on 0, pick some random sub subset [Skotlex]
  2818. k = rand()%count;
  2819. amount+=k; //Increase final value by same amount to preserve total number to summon.
  2820. }
  2821. for(;k<amount;k++) {
  2822. int x=0,y=0,i=0;
  2823. class_ = value[k%count]; //Summon slaves in round-robin fashion. [Skotlex]
  2824. if (mobdb_checkid(class_) == 0)
  2825. continue;
  2826. md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
  2827. if(mob_db(class_)->mode&MD_LOOTER)
  2828. md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
  2829. while((x<=0 || y<=0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<100){
  2830. x=rand()%9-4+bx;
  2831. y=rand()%9-4+by;
  2832. }
  2833. if(i>=100){
  2834. x=bx;
  2835. y=by;
  2836. }
  2837. mob_spawn_dataset(md,"--ja--",class_);
  2838. md->bl.m=m;
  2839. md->bl.x=x;
  2840. md->bl.y=y;
  2841. md->m =m;
  2842. md->x0=x;
  2843. md->y0=y;
  2844. md->xs=0;
  2845. md->ys=0;
  2846. if (battle_config.slaves_inherit_speed && md2->db->mode&MD_CANMOVE
  2847. && (skill_id != NPC_METAMORPHOSIS && skill_id != NPC_TRANSFORMATION))
  2848. md->speed=md2->speed;
  2849. md->special_state.cached= battle_config.dynamic_mobs; //[Skotlex]
  2850. md->spawndelay1=-1; // 一度のみフラグ
  2851. md->spawndelay2=-1; // 一度のみフラグ
  2852. if (!battle_config.monster_class_change_full_recover &&
  2853. (skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS))
  2854. { //Scale HP
  2855. md->hp = (md->max_hp*md2->hp)/md2->max_hp;
  2856. }
  2857. memset(md->npc_event,0,sizeof(md->npc_event));
  2858. md->bl.type=BL_MOB;
  2859. map_addiddb(&md->bl);
  2860. mob_spawn(md->bl.id);
  2861. clif_skill_nodamage(&md->bl,&md->bl,skill_id,amount,1);
  2862. if(skill_id == NPC_SUMMONSLAVE)
  2863. md->master_id=md2->bl.id;
  2864. }
  2865. return 0;
  2866. }
  2867. /*==========================================
  2868. *MOBskillから該当skillidのskillidxを返す
  2869. *------------------------------------------
  2870. */
  2871. int mob_skillid2skillidx(int class_,int skillid)
  2872. {
  2873. int i, max = mob_db(class_)->maxskill;
  2874. struct mob_skill *ms=mob_db(class_)->skill;
  2875. if(ms==NULL)
  2876. return -1;
  2877. for(i=0;i<max;i++){
  2878. if(ms[i].skill_id == skillid)
  2879. return i;
  2880. }
  2881. return -1;
  2882. }
  2883. //
  2884. // MOBスキル
  2885. //
  2886. /*==========================================
  2887. * スキル使用(詠唱完了、ID指定)
  2888. *------------------------------------------
  2889. */
  2890. int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
  2891. {
  2892. struct mob_data* md=NULL;
  2893. struct block_list *bl;
  2894. int inf;
  2895. //Code cleanup. Insert any code that should be executed if the skill fails here.
  2896. #define skill_failed(md) { md->skillid = md->skilllv = -1; }
  2897. if((md = (struct mob_data*)map_id2bl(id)) == NULL ) //詠唱したMobがもういないというのは良くある正常処理
  2898. return 0;
  2899. if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
  2900. return 0;
  2901. if( md->skilltimer != tid ) {
  2902. if (battle_config.error_log)
  2903. ShowError("mobskill_castend_id: Timer mismatch %d!=%d\n", md->skilltimer, tid);
  2904. md->skilltimer = -1;
  2905. return 0;
  2906. }
  2907. md->skilltimer=-1;
  2908. if((bl = map_id2bl(md->skilltarget)) == NULL || bl->prev==NULL || md->bl.m != bl->m) {
  2909. skill_failed(md);
  2910. return 0;
  2911. }
  2912. if(md->skillid != NPC_EMOTION)
  2913. //Set afterskill delay.
  2914. md->last_thinktime=tick + (tid==-1?status_get_adelay(&md->bl):status_get_amotion(&md->bl));
  2915. if(md->skillid == RG_BACKSTAP) {
  2916. int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = status_get_dir(bl);
  2917. if(bl->type != BL_SKILL && (check_distance_bl(&md->bl, bl, 0) || map_check_dir(dir,t_dir))) {
  2918. skill_failed(md);
  2919. return 0;
  2920. }
  2921. }
  2922. inf = skill_get_inf(md->skillid);
  2923. if((inf&INF_ATTACK_SKILL ||
  2924. (inf&INF_SELF_SKILL && md->bl.id != bl->id && !(skill_get_nk(md->skillid)&NK_NO_DAMAGE)))
  2925. && battle_check_target(&md->bl,bl, BCT_ENEMY)<=0 ) {
  2926. skill_failed(md);
  2927. return 0;
  2928. }
  2929. if(tid != -1)
  2930. {
  2931. if (md->skillid == -1 ||!status_check_skilluse(&md->bl, bl, md->skillid, 1)) {
  2932. skill_failed(md);
  2933. return 0;
  2934. }
  2935. if(!check_distance_bl(&md->bl, bl, skill_get_range2(&md->bl, md->skillid,md->skilllv) + battle_config.mob_skill_add_range)) {
  2936. skill_failed(md);
  2937. return 0;
  2938. }
  2939. }
  2940. md->skilldelay[md->skillidx]=tick;
  2941. if(battle_config.mob_skill_log)
  2942. ShowInfo("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
  2943. // mob_stop_wShowInfo(md,0);
  2944. if (skill_get_casttype(md->skillid) == CAST_NODAMAGE)
  2945. skill_castend_nodamage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
  2946. else
  2947. skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
  2948. if (md->sc.count && md->sc.data[SC_MAGICPOWER].timer != -1 && md->skillid != HW_MAGICPOWER)
  2949. status_change_end(&md->bl, SC_MAGICPOWER, -1);
  2950. if (md->db->skill[md->skillidx].emotion >= 0)
  2951. clif_emotion(&md->bl, md->db->skill[md->skillidx].emotion);
  2952. //TODO: This value is used for the "afterskill" mob condition, what could one do to clean it other than
  2953. //to use a "previous skill" struct variable?
  2954. //md->skillid = md->skilllv = -1; //Clean up skill-data for battle_getcurrentskill references. [Skotlex]
  2955. return 0;
  2956. }
  2957. /*==========================================
  2958. * スキル使用(詠唱完了、場所指定)
  2959. *------------------------------------------
  2960. */
  2961. int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
  2962. {
  2963. struct mob_data* md=NULL;
  2964. int maxcount;
  2965. //Code cleanup. Insert any code that should be executed if the skill fails here.
  2966. #define skill_failed(md) { md->skillid = md->skilllv = -1; }
  2967. nullpo_retr(0, md=(struct mob_data *)map_id2bl(id));
  2968. if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
  2969. return 0;
  2970. if( md->skilltimer != tid ) {
  2971. if (battle_config.error_log)
  2972. ShowError("mobskill_castend_pos: Timer mismatch %d!=%d\n", md->skilltimer, tid);
  2973. md->skilltimer = -1;
  2974. return 0;
  2975. }
  2976. md->skilltimer=-1;
  2977. if (tid != -1)
  2978. { //Avoid unnecessary checks for instant-cast skills. [Skotlex]
  2979. if (md->skillid == -1 || !status_check_skilluse(&md->bl, NULL, md->skillid, 1)) {
  2980. skill_failed(md);
  2981. return 0;
  2982. }
  2983. if(!check_distance_blxy(&md->bl, md->skillx, md->skilly, skill_get_range2(&md->bl, md->skillid,md->skilllv) + battle_config.mob_skill_add_range)) {
  2984. skill_failed(md);
  2985. return 0;
  2986. }
  2987. }
  2988. if (!battle_config.monster_skill_reiteration &&
  2989. skill_get_unit_flag (md->skillid) & UF_NOREITERATION &&
  2990. skill_check_unit_range (md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv)) {
  2991. skill_failed(md);
  2992. return 0;
  2993. }
  2994. if(battle_config.monster_skill_nofootset &&
  2995. skill_get_unit_flag (md->skillid) & UF_NOFOOTSET &&
  2996. skill_check_unit_range2(&md->bl, md->bl.m, md->skillx, md->skilly, md->skillid, md->skilllv)) {
  2997. skill_failed(md);
  2998. return 0;
  2999. }
  3000. if(battle_config.monster_land_skill_limit) {
  3001. maxcount = skill_get_maxcount(md->skillid);
  3002. if(maxcount > 0) {
  3003. int i,c;
  3004. for(i=c=0;i<MAX_MOBSKILLUNITGROUP;i++) {
  3005. if(md->skillunit[i].alive_count > 0 && md->skillunit[i].skill_id == md->skillid)
  3006. c++;
  3007. }
  3008. if(c >= maxcount) {
  3009. skill_failed(md);
  3010. return 0;
  3011. }
  3012. }
  3013. }
  3014. md->skilldelay[md->skillidx]=tick;
  3015. //Set afterskill delay.
  3016. md->last_thinktime=tick + (tid==-1?status_get_adelay(&md->bl):status_get_amotion(&md->bl));
  3017. if(battle_config.mob_skill_log)
  3018. ShowInfo("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
  3019. // mob_stop_walking(md,0);
  3020. skill_castend_pos2(&md->bl,md->skillx,md->skilly,md->skillid,md->skilllv,tick,0);
  3021. if (md->db->skill[md->skillidx].emotion >= 0)
  3022. clif_emotion(&md->bl, md->db->skill[md->skillidx].emotion);
  3023. //TODO: This value is used for the "afterskill" mob condition, what could one do to clean it other than
  3024. //to use a "previous skill" struct variable?
  3025. //md->skillid = md->skilllv = -1; //Clean up skill data for future references to battle_getcurrentskill [Skotlex]
  3026. return 0;
  3027. }
  3028. /*==========================================
  3029. * Skill use (an aria start, ID specification)
  3030. *------------------------------------------
  3031. */
  3032. int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
  3033. {
  3034. int casttime;
  3035. struct mob_skill *ms;
  3036. int skill_id, skill_lv, forcecast = 0;
  3037. int selfdestruct_flag = 0;
  3038. nullpo_retr(0, md);
  3039. nullpo_retr(0, ms=&md->db->skill[skill_idx]);
  3040. if( target==NULL && (target=map_id2bl(md->target_id))==NULL )
  3041. return 0;
  3042. if( target->prev==NULL || md->bl.prev==NULL )
  3043. return 0;
  3044. skill_id=ms->skill_id;
  3045. skill_lv=ms->skill_lv;
  3046. if(map_flag_gvg(md->bl.m) && skill_db[skill_id].nocast & 4)
  3047. return 0;
  3048. if(skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF && md->bl.id == target->id)
  3049. return 0;
  3050. if(!status_check_skilluse(&md->bl, target, skill_id, 0))
  3051. return 0;
  3052. if(md->sc.count && md->sc.data[SC_WINKCHARM].timer != -1 && target->type == BL_PC) {
  3053. clif_emotion(&md->bl, 3);
  3054. return 0;
  3055. }
  3056. // 射程と障害物チェック
  3057. if(!battle_check_range(&md->bl,target,skill_get_range2(&md->bl,skill_id,skill_lv)))
  3058. return 0;
  3059. // delay=skill_delayfix(&md->bl, skill_id, skill_lv, 0);
  3060. casttime=skill_castfix(&md->bl, skill_id, skill_lv, ms->casttime);
  3061. md->state.skillcastcancel=ms->cancel;
  3062. md->skilldelay[skill_idx]=gettick();
  3063. switch(skill_id){ /* 何か特殊な処理が必要 */
  3064. case ALL_RESURRECTION: /* リザレクション */
  3065. if(target->type != BL_PC && battle_check_undead(status_get_race(target),status_get_elem_type(target))){ /* 敵がアンデッドなら */
  3066. forcecast=1; /* ターンアンデットと同じ詠唱時間 */
  3067. casttime=skill_castfix(&md->bl, PR_TURNUNDEAD,skill_lv, 0);
  3068. }
  3069. break;
  3070. case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/
  3071. case SA_MAGICROD:
  3072. case SA_SPELLBREAKER:
  3073. forcecast=1;
  3074. break;
  3075. case NPC_SUMMONSLAVE:
  3076. case NPC_SUMMONMONSTER:
  3077. if(md->master_id!=0)
  3078. return 0;
  3079. break;
  3080. case NPC_SELFDESTRUCTION:
  3081. if (casttime == 0 && md->special_state.ai == 2) {
  3082. casttime = skill_get_time(skill_id,skill_lv);
  3083. selfdestruct_flag = 1;
  3084. }
  3085. break;
  3086. }
  3087. if(battle_config.mob_skill_log)
  3088. ShowInfo("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class_);
  3089. if (casttime || forcecast) { // 詠唱が必要
  3090. if (!selfdestruct_flag)
  3091. mob_stop_walking(md,1); // 歩行停止
  3092. clif_skillcasting(&md->bl, md->bl.id, target->id, 0,0, skill_id, casttime);
  3093. }
  3094. if (casttime <= 0) // 詠唱の無いものはキャンセルされない
  3095. md->state.skillcastcancel = 0;
  3096. md->skilltarget = target->id;
  3097. md->skillx = 0;
  3098. md->skilly = 0;
  3099. md->skillid = skill_id;
  3100. md->skilllv = skill_lv;
  3101. md->skillidx = skill_idx;
  3102. if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
  3103. status_change_end(&md->bl,SC_CLOAKING,-1);
  3104. if( casttime>0 ){
  3105. md->skilltimer =
  3106. add_timer( gettick()+casttime, mobskill_castend_id, md->bl.id, 0 );
  3107. }else{
  3108. md->skilltimer = -1;
  3109. mobskill_castend_id(md->skilltimer,gettick(),md->bl.id, 0);
  3110. }
  3111. return 1;
  3112. }
  3113. /*==========================================
  3114. * スキル使用(場所指定)
  3115. *------------------------------------------
  3116. */
  3117. int mobskill_use_pos( struct mob_data *md,
  3118. int skill_x, int skill_y, int skill_idx)
  3119. {
  3120. int casttime=0;
  3121. struct mob_skill *ms;
  3122. struct block_list bl;
  3123. int skill_id, skill_lv;
  3124. nullpo_retr(0, md);
  3125. nullpo_retr(0, ms=&md->db->skill[skill_idx]);
  3126. if( md->bl.prev==NULL )
  3127. return 0;
  3128. skill_id=ms->skill_id;
  3129. skill_lv=ms->skill_lv;
  3130. if(map_flag_gvg(md->bl.m) && skill_db[skill_id].nocast & 4)
  3131. return 0;
  3132. if(!status_check_skilluse(&md->bl, NULL, skill_id, 0))
  3133. return 0;
  3134. // 射程と障害物チェック
  3135. bl.type = BL_NUL;
  3136. bl.m = md->bl.m;
  3137. bl.x = skill_x;
  3138. bl.y = skill_y;
  3139. if(!battle_check_range(&md->bl,&bl,skill_get_range2(&md->bl,skill_id,skill_lv)))
  3140. return 0;
  3141. // delay=skill_delayfix(&md->bl, skill_id, skill_lv, 0);
  3142. casttime=skill_castfix(&md->bl,skill_id, skill_lv, ms->casttime);
  3143. md->skilldelay[skill_idx]=gettick();
  3144. md->state.skillcastcancel=ms->cancel;
  3145. if(battle_config.mob_skill_log)
  3146. ShowInfo("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n",
  3147. skill_x,skill_y,skill_id,skill_lv,casttime,md->class_);
  3148. if( casttime>0 ) { // A cast time is required.
  3149. mob_stop_walking(md,1); // 歩行停止
  3150. clif_skillcasting( &md->bl,
  3151. md->bl.id, 0, skill_x,skill_y, skill_id,casttime);
  3152. }
  3153. if( casttime<=0 ) // A skill without a cast time wont be cancelled.
  3154. md->state.skillcastcancel=0;
  3155. md->skillx = skill_x;
  3156. md->skilly = skill_y;
  3157. md->skilltarget = 0;
  3158. md->skillid = skill_id;
  3159. md->skilllv = skill_lv;
  3160. md->skillidx = skill_idx;
  3161. if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1)
  3162. status_change_end(&md->bl,SC_CLOAKING,-1);
  3163. if( casttime>0 ){
  3164. md->skilltimer =
  3165. add_timer( gettick()+casttime, mobskill_castend_pos, md->bl.id, 0 );
  3166. }else{
  3167. md->skilltimer = -1;
  3168. mobskill_castend_pos(md->skilltimer,gettick(),md->bl.id, 0);
  3169. }
  3170. return 1;
  3171. }
  3172. /*==========================================
  3173. * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
  3174. *------------------------------------------
  3175. */
  3176. int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
  3177. {
  3178. int min_rate, max_rate,rate;
  3179. struct block_list **fr;
  3180. struct mob_data *md;
  3181. md = va_arg(ap,struct mob_data *);
  3182. min_rate=va_arg(ap,int);
  3183. max_rate=va_arg(ap,int);
  3184. fr=va_arg(ap,struct block_list **);
  3185. if( md->bl.id == bl->id && !(battle_config.mob_ai&16))
  3186. return 0;
  3187. if ((*fr) != NULL) //A friend was already found.
  3188. return 0;
  3189. if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0)
  3190. return 0;
  3191. rate = 100*status_get_hp(bl)/status_get_max_hp(bl);
  3192. if (rate >= min_rate && rate <= max_rate)
  3193. (*fr) = bl;
  3194. return 1;
  3195. }
  3196. static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate)
  3197. {
  3198. struct block_list *fr=NULL;
  3199. int type = BL_MOB;
  3200. nullpo_retr(NULL, md);
  3201. if (md->special_state.ai) //Summoned creatures. [Skotlex]
  3202. type = BL_PC;
  3203. map_foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr);
  3204. return fr;
  3205. }
  3206. /*==========================================
  3207. * Check hp rate of its master
  3208. *------------------------------------------
  3209. */
  3210. struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate)
  3211. {
  3212. if (md && md->master_id > 0) {
  3213. struct block_list *bl = map_id2bl(md->master_id);
  3214. if (status_get_hp(bl) < status_get_max_hp(bl) * rate / 100)
  3215. return bl;
  3216. }
  3217. return NULL;
  3218. }
  3219. /*==========================================
  3220. * What a status state suits by nearby MOB is looked for.
  3221. *------------------------------------------
  3222. */
  3223. int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
  3224. {
  3225. int cond1,cond2;
  3226. struct mob_data **fr, *md, *mmd;
  3227. int flag=0;
  3228. nullpo_retr(0, bl);
  3229. nullpo_retr(0, ap);
  3230. nullpo_retr(0, md=(struct mob_data *)bl);
  3231. nullpo_retr(0, mmd=va_arg(ap,struct mob_data *));
  3232. if( mmd->bl.id == bl->id && !(battle_config.mob_ai&16) )
  3233. return 0;
  3234. if (battle_check_target(&mmd->bl,bl,BCT_ENEMY)>0)
  3235. return 0;
  3236. cond1=va_arg(ap,int);
  3237. cond2=va_arg(ap,int);
  3238. fr=va_arg(ap,struct mob_data **);
  3239. if( cond2==-1 ){
  3240. int j;
  3241. for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){
  3242. if ((flag=(md->sc.data[j].timer!=-1))) //Once an effect was found, break out. [Skotlex]
  3243. break;
  3244. }
  3245. }else
  3246. flag=( md->sc.data[cond2].timer!=-1 );
  3247. if( flag^( cond1==MSC_FRIENDSTATUSOFF ) )
  3248. (*fr)=md;
  3249. return 0;
  3250. }
  3251. struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2)
  3252. {
  3253. struct mob_data *fr=NULL;
  3254. nullpo_retr(0, md);
  3255. map_foreachinrange(mob_getfriendstatus_sub, &md->bl, 8,
  3256. BL_MOB,md,cond1,cond2,&fr);
  3257. return fr;
  3258. }
  3259. /*==========================================
  3260. * Skill use judging
  3261. *------------------------------------------
  3262. */
  3263. int mobskill_use(struct mob_data *md, unsigned int tick, int event)
  3264. {
  3265. struct mob_skill *ms;
  3266. struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
  3267. struct mob_data *fmd = NULL;
  3268. int i;
  3269. nullpo_retr (0, md);
  3270. nullpo_retr (0, ms = md->db->skill);
  3271. if (battle_config.mob_skill_rate == 0 || md->skilltimer != -1)
  3272. return 0;
  3273. for (i = 0; i < md->db->maxskill; i++) {
  3274. int c2 = ms[i].cond2, flag = 0;
  3275. // ディレイ中
  3276. if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay)
  3277. continue;
  3278. // 状態判定
  3279. if (ms[i].state >= 0 && ms[i].state != md->state.skillstate)
  3280. continue;
  3281. if (rand() % 10000 > ms[i].permillage) //Lupus (max value = 10000)
  3282. continue;
  3283. // 条件判定
  3284. flag = (event == ms[i].cond1);
  3285. //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function
  3286. //in battle. The only exception is MSC_SKILLUSED which explicitly uses the event value to trigger. [Skotlex]
  3287. if (!flag && (event == -1 || event == MSC_SKILLUSED)){
  3288. switch (ms[i].cond1)
  3289. {
  3290. case MSC_ALWAYS:
  3291. flag = 1; break;
  3292. case MSC_MYHPLTMAXRATE: // HP< maxhp%
  3293. flag = 100*md->hp/status_get_max_hp(&md->bl);
  3294. flag = (flag <= c2);
  3295. break;
  3296. case MSC_MYHPINRATE:
  3297. flag = 100*md->hp/status_get_max_hp(&md->bl);
  3298. flag = (flag >= c2 && flag <= ms[i].val[0]);
  3299. break;
  3300. case MSC_MYSTATUSON: // status[num] on
  3301. case MSC_MYSTATUSOFF: // status[num] off
  3302. if (!md->sc.count) {
  3303. flag = 0;
  3304. } else if (ms[i].cond2 == -1) {
  3305. int j;
  3306. for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++)
  3307. if ((flag = (md->sc.data[j].timer != -1)) != 0)
  3308. break;
  3309. } else {
  3310. flag = (md->sc.data[ms[i].cond2].timer != -1);
  3311. }
  3312. flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
  3313. case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
  3314. flag = ((fbl = mob_getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
  3315. case MSC_FRIENDHPINRATE :
  3316. flag = ((fbl = mob_getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
  3317. case MSC_FRIENDSTATUSON: // friend status[num] on
  3318. case MSC_FRIENDSTATUSOFF: // friend status[num] off
  3319. flag = ((fmd = mob_getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
  3320. case MSC_SLAVELT: // slave < num
  3321. flag = (mob_countslave(&md->bl) < c2 ); break;
  3322. case MSC_ATTACKPCGT: // attack pc > num
  3323. flag = (battle_counttargeted(&md->bl, NULL, 0) > c2); break;
  3324. case MSC_SLAVELE: // slave <= num
  3325. flag = (mob_countslave(&md->bl) <= c2 ); break;
  3326. case MSC_ATTACKPCGE: // attack pc >= num
  3327. flag = (battle_counttargeted(&md->bl, NULL, 0) >= c2); break;
  3328. case MSC_AFTERSKILL:
  3329. flag = (md->skillid == c2); break;
  3330. case MSC_SKILLUSED: // specificated skill used
  3331. flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0)); break;
  3332. case MSC_RUDEATTACKED:
  3333. flag = (!md->attacked_id && md->attacked_count > 0);
  3334. if (flag) md->attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
  3335. break;
  3336. case MSC_MASTERHPLTMAXRATE:
  3337. flag = ((fbl = mob_getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
  3338. case MSC_MASTERATTACKED:
  3339. flag = (md->master_id > 0 && battle_counttargeted(map_id2bl(md->master_id), NULL, 0) > 0); break;
  3340. case MSC_ALCHEMIST:
  3341. flag = (md->state.alchemist);
  3342. break;
  3343. }
  3344. }
  3345. if (!flag)
  3346. continue; //Skill requisite failed to be fulfilled.
  3347. //Execute skill
  3348. if (skill_get_casttype(ms[i].skill_id) == CAST_GROUND)
  3349. {
  3350. // 場所指定
  3351. struct block_list *bl = NULL;
  3352. int x = 0, y = 0;
  3353. if (ms[i].target <= MST_AROUND) {
  3354. switch (ms[i].target) {
  3355. case MST_TARGET:
  3356. case MST_AROUND5:
  3357. case MST_AROUND6:
  3358. case MST_AROUND7:
  3359. case MST_AROUND8:
  3360. bl = map_id2bl(md->target_id);
  3361. break;
  3362. case MST_MASTER:
  3363. bl = &md->bl;
  3364. if (md->master_id)
  3365. bl = map_id2bl(md->master_id);
  3366. if (bl) //Otherwise, fall through.
  3367. break;
  3368. case MST_FRIEND:
  3369. if (fbl)
  3370. {
  3371. bl = fbl;
  3372. break;
  3373. } else if (fmd) {
  3374. bl= &fmd->bl;
  3375. break;
  3376. } // else fall through
  3377. default:
  3378. bl = &md->bl;
  3379. break;
  3380. }
  3381. if (bl != NULL) {
  3382. x = bl->x; y=bl->y;
  3383. }
  3384. }
  3385. if (x <= 0 || y <= 0)
  3386. continue;
  3387. // 自分の周囲
  3388. if (ms[i].target >= MST_AROUND1) {
  3389. int bx = x, by = y, i = 0, m = bl->m, r = (ms[i].target-MST_AROUND1) +1;
  3390. do {
  3391. bx = x + rand() % (r*2+1) - r;
  3392. by = y + rand() % (r*2+1) - r;
  3393. } while (map_getcell(m, bx, by, CELL_CHKNOREACH) && (i++) < 1000);
  3394. if (i < 1000){
  3395. x = bx; y = by;
  3396. }
  3397. }
  3398. // 相手の周囲
  3399. if (ms[i].target >= MST_AROUND5) {
  3400. int bx = x, by = y, i = 0, m = bl->m, r = (ms[i].target-MST_AROUND5) + 1;
  3401. do {
  3402. bx = x + rand() % (r*2+1) - r;
  3403. by = y + rand() % (r*2+1) - r;
  3404. } while (map_getcell(m, bx, by, CELL_CHKNOREACH) && (i++) < 1000);
  3405. if (i < 1000){
  3406. x = bx; y = by;
  3407. }
  3408. }
  3409. if (!mobskill_use_pos(md, x, y, i))
  3410. return 0;
  3411. } else {
  3412. // ID指定
  3413. if (ms[i].target <= MST_MASTER) {
  3414. struct block_list *bl;
  3415. switch (ms[i].target) {
  3416. case MST_TARGET:
  3417. bl = map_id2bl(md->target_id);
  3418. break;
  3419. case MST_MASTER:
  3420. bl = &md->bl;
  3421. if (md->master_id)
  3422. bl = map_id2bl(md->master_id);
  3423. if (bl) //Otherwise, fall through.
  3424. break;
  3425. case MST_FRIEND:
  3426. if (fbl) {
  3427. bl = fbl;
  3428. break;
  3429. } else if (fmd) {
  3430. bl = &fmd->bl;
  3431. break;
  3432. } // else fall through
  3433. default:
  3434. bl = &md->bl;
  3435. break;
  3436. }
  3437. if (bl && !mobskill_use_id(md, bl, i))
  3438. return 0;
  3439. } else {
  3440. if (battle_config.error_log)
  3441. ShowWarning("Wrong mob skill target 'around' for non-ground skill %d (%s). Mob %d - %s\n",
  3442. ms[i].skill_id, skill_get_name(ms[i].skill_id), md->class_, md->db->jname);
  3443. continue;
  3444. }
  3445. }
  3446. return 1;
  3447. }
  3448. return 0;
  3449. }
  3450. /*==========================================
  3451. * Skill use event processing
  3452. *------------------------------------------
  3453. */
  3454. int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tick, int flag)
  3455. {
  3456. int target_id, res = 0;
  3457. target_id = md->target_id;
  3458. if (!target_id || battle_config.mob_changetarget_byskill)
  3459. md->target_id = src->id;
  3460. if (flag == -1)
  3461. res = mobskill_use(md, tick, MSC_CASTTARGETED);
  3462. else if ((flag&0xffff) == MSC_SKILLUSED)
  3463. res = mobskill_use(md,tick,flag);
  3464. else if (flag&BF_SHORT)
  3465. res = mobskill_use(md, tick, MSC_CLOSEDATTACKED);
  3466. else if (flag&BF_LONG)
  3467. res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED);
  3468. if (!res)
  3469. //Restore previous target only if skill condition failed to trigger. [Skotlex]
  3470. md->target_id = target_id;
  3471. //Otherwise check if the target is an enemy, and unlock if needed.
  3472. else if (battle_check_target(&md->bl, src, BCT_ENEMY) <= 0)
  3473. md->target_id = target_id;
  3474. return res;
  3475. }
  3476. /*==========================================
  3477. * スキル用タイマー削除
  3478. *------------------------------------------
  3479. */
  3480. int mobskill_deltimer(struct mob_data *md )
  3481. {
  3482. nullpo_retr(0, md);
  3483. if( md->skilltimer!=-1 ){
  3484. if( skill_get_inf( md->skillid )& INF_GROUND_SKILL )
  3485. delete_timer( md->skilltimer, mobskill_castend_pos );
  3486. else
  3487. delete_timer( md->skilltimer, mobskill_castend_id );
  3488. md->skilltimer=-1;
  3489. }
  3490. return 0;
  3491. }
  3492. // Player cloned mobs. [Valaris]
  3493. int mob_is_clone(int class_)
  3494. {
  3495. if(class_ >= MOB_CLONE_START && class_ <= MOB_CLONE_END)
  3496. return 1;
  3497. return 0;
  3498. }
  3499. //Flag values:
  3500. //&1: Set special ai (fight mobs, not players)
  3501. //If mode is not passed, a default aggressive mode is used.
  3502. //If master_id is passed, clone is attached to him.
  3503. //Returns: ID of newly crafted copy.
  3504. int mob_clone_spawn(struct map_session_data *sd, char *map, int x, int y, const char *event, int master_id, int mode, int flag, unsigned int duration)
  3505. {
  3506. int class_;
  3507. int i,j,inf,skill_id;
  3508. struct mob_skill *ms;
  3509. nullpo_retr(0, sd);
  3510. for(class_=MOB_CLONE_START; class_<MOB_CLONE_END; class_++){
  3511. if(mob_db_data[class_]==NULL)
  3512. break;
  3513. }
  3514. if(class_>MOB_CLONE_END)
  3515. return 0;
  3516. mob_db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
  3517. mob_db_data[class_]->view_class=sd->status.class_;
  3518. sprintf(mob_db_data[class_]->name,sd->status.name);
  3519. sprintf(mob_db_data[class_]->jname,sd->status.name);
  3520. mob_db_data[class_]->lv=status_get_lv(&sd->bl);
  3521. mob_db_data[class_]->max_hp=status_get_max_hp(&sd->bl);
  3522. mob_db_data[class_]->max_sp=0;
  3523. mob_db_data[class_]->base_exp=1;
  3524. mob_db_data[class_]->job_exp=1;
  3525. mob_db_data[class_]->range=status_get_range(&sd->bl);
  3526. mob_db_data[class_]->atk1=status_get_batk(&sd->bl); //Base attack as minimum damage.
  3527. mob_db_data[class_]->atk2=mob_db_data[class_]->atk1 + status_get_atk(&sd->bl)+status_get_atk2(&sd->bl); //batk + weapon dmg
  3528. mob_db_data[class_]->def=status_get_def(&sd->bl);
  3529. mob_db_data[class_]->mdef=status_get_mdef(&sd->bl);
  3530. mob_db_data[class_]->str=status_get_str(&sd->bl);
  3531. mob_db_data[class_]->agi=status_get_agi(&sd->bl);
  3532. mob_db_data[class_]->vit=status_get_vit(&sd->bl);
  3533. mob_db_data[class_]->int_=status_get_int(&sd->bl);
  3534. mob_db_data[class_]->dex=status_get_dex(&sd->bl);
  3535. mob_db_data[class_]->luk=status_get_luk(&sd->bl);
  3536. mob_db_data[class_]->range2=AREA_SIZE*2/3; //Chase area of 2/3rds of a screen.
  3537. mob_db_data[class_]->range3=AREA_SIZE; //Let them have the same view-range as players.
  3538. mob_db_data[class_]->size=status_get_size(&sd->bl);
  3539. mob_db_data[class_]->race=status_get_race(&sd->bl);
  3540. mob_db_data[class_]->element=status_get_element(&sd->bl);
  3541. mob_db_data[class_]->mode=mode?mode:(MD_AGGRESSIVE|MD_ASSIST|MD_CANATTACK|MD_CANMOVE);
  3542. mob_db_data[class_]->speed=status_get_speed(&sd->bl);
  3543. mob_db_data[class_]->adelay=status_get_adelay(&sd->bl);
  3544. mob_db_data[class_]->amotion=status_get_amotion(&sd->bl);
  3545. mob_db_data[class_]->dmotion=status_get_dmotion(&sd->bl);
  3546. mob_db_data[class_]->sex=sd->status.sex;
  3547. mob_db_data[class_]->hair=sd->status.hair;
  3548. mob_db_data[class_]->hair_color=sd->status.hair_color;
  3549. #if PACKETVER < 4
  3550. mob_db_data[class_]->weapon = sd->status.weapon;
  3551. mob_db_data[class_]->shield = sd->status.shield;
  3552. #else
  3553. if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]] && sd->view_class != JOB_WEDDING && sd->view_class != JOB_XMAS) {
  3554. if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
  3555. mob_db_data[class_]->weapon=sd->inventory_data[sd->equip_index[9]]->view_id;
  3556. else
  3557. mob_db_data[class_]->weapon=sd->status.inventory[sd->equip_index[9]].nameid;
  3558. } else
  3559. mob_db_data[class_]->shield=0;
  3560. if (sd->equip_index[8] >= 0 && sd->equip_index[8] != sd->equip_index[9] && sd->inventory_data[sd->equip_index[8]] && sd->view_class != JOB_WEDDING && sd->view_class != JOB_XMAS) {
  3561. if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
  3562. mob_db_data[class_]->shield=sd->inventory_data[sd->equip_index[8]]->view_id;
  3563. else
  3564. mob_db_data[class_]->shield=sd->status.inventory[sd->equip_index[8]].nameid;
  3565. } else
  3566. mob_db_data[class_]->shield=0;
  3567. #endif
  3568. mob_db_data[class_]->head_top=sd->status.head_top;
  3569. mob_db_data[class_]->head_mid=sd->status.head_mid;
  3570. mob_db_data[class_]->head_buttom=sd->status.head_bottom;
  3571. mob_db_data[class_]->option=sd->sc.option;
  3572. mob_db_data[class_]->clothes_color=sd->status.clothes_color;
  3573. //Skill copy [Skotlex]
  3574. ms = &mob_db_data[class_]->skill[0];
  3575. //Go Backwards to give better priority to advanced skills.
  3576. for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
  3577. skill_id = skill_tree[sd->status.class_][j].id;
  3578. if (!skill_id || sd->status.skill[skill_id].lv < 1 || (skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)))
  3579. continue;
  3580. memset (&ms[i], 0, sizeof(struct mob_skill));
  3581. ms[i].skill_id = skill_id;
  3582. ms[i].skill_lv = sd->status.skill[skill_id].lv;
  3583. ms[i].state = -1;
  3584. ms[i].permillage = 500; //Default chance for moving/idle skills.
  3585. ms[i].emotion = -1;
  3586. ms[i].cancel = 0;
  3587. ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv, 0);
  3588. ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv, 0);
  3589. inf = skill_get_inf(skill_id);
  3590. if (inf&INF_ATTACK_SKILL) {
  3591. ms[i].target = MST_TARGET;
  3592. ms[i].cond1 = MSC_ALWAYS;
  3593. if (skill_get_range(skill_id, ms[i].skill_lv) > 3) {
  3594. ms[i].state = MSS_RUSH;
  3595. } else {
  3596. ms[i].state = MSS_BERSERK;
  3597. ms[i].permillage = 2500;
  3598. }
  3599. } else if(inf&INF_GROUND_SKILL) {
  3600. //Normal aggressive mob, disable skills that cannot help them fight
  3601. //against players (those with flags UF_NOMOB and UF_NOPC are specific
  3602. //to always aid players!) [Skotlex]
  3603. if (!(flag&1) && skill_get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC))
  3604. continue;
  3605. ms[i].permillage = 1000;
  3606. if (skill_get_inf2(skill_id)&INF2_TRAP) { //Traps!
  3607. ms[i].state = MSS_IDLE;
  3608. ms[i].target = MST_AROUND2;
  3609. ms[i].delay = 60000;
  3610. } else if (skill_get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy
  3611. ms[i].target = MST_TARGET;
  3612. ms[i].cond1 = MSC_ALWAYS;
  3613. } else { //Target allies
  3614. ms[i].target = MST_FRIEND;
  3615. ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
  3616. ms[i].cond2 = 95;
  3617. }
  3618. } else if (inf&INF_SELF_SKILL) {
  3619. if (!(skill_get_nk(skill_id)&NK_NO_DAMAGE)) { //Offensive skill
  3620. ms[i].target = MST_TARGET;
  3621. ms[i].state = MSS_BERSERK;
  3622. } else //Self skill
  3623. ms[i].target = MST_SELF;
  3624. ms[i].cond1 = MSC_MYHPLTMAXRATE;
  3625. ms[i].cond2 = 90;
  3626. ms[i].permillage = 2000;
  3627. //Delay: Remove the stock 5 secs and add half of the support time.
  3628. ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2;
  3629. if (ms[i].delay < 5000)
  3630. ms[i].delay = 5000; //With a minimum of 5 secs.
  3631. } else if (inf&INF_SUPPORT_SKILL) {
  3632. ms[i].target = MST_FRIEND;
  3633. ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
  3634. ms[i].cond2 = 90;
  3635. if (skill_id == AL_HEAL)
  3636. ms[i].permillage = 5000; //Higher skill rate usage for heal.
  3637. else if (skill_id == ALL_RESURRECTION)
  3638. ms[i].cond2 = 1;
  3639. //Delay: Remove the stock 5 secs and add half of the support time.
  3640. ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2;
  3641. if (ms[i].delay < 2000)
  3642. ms[i].delay = 2000; //With a minimum of 2 secs.
  3643. if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self.
  3644. memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill));
  3645. mob_db_data[class_]->maxskill = ++i;
  3646. ms[i].target = MST_SELF;
  3647. ms[i].cond1 = MSC_MYHPLTMAXRATE;
  3648. }
  3649. } else {
  3650. switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered.
  3651. case MO_TRIPLEATTACK:
  3652. case TF_DOUBLE:
  3653. ms[i].state = MSS_BERSERK;
  3654. ms[i].target = MST_TARGET;
  3655. ms[i].cond1 = MSC_ALWAYS;
  3656. ms[i].permillage = skill_id==TF_DOUBLE?(ms[i].skill_lv*500):(3000-ms[i].skill_lv*100);
  3657. ms[i].delay -= 5000; //Remove the added delay as these could trigger on "all hits".
  3658. break;
  3659. default: //Untreated Skill
  3660. continue;
  3661. }
  3662. }
  3663. if (battle_config.mob_skill_rate!= 100)
  3664. ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100;
  3665. if (battle_config.mob_skill_delay != 100)
  3666. ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100;
  3667. mob_db_data[class_]->maxskill = ++i;
  3668. }
  3669. //Finally, spawn it.
  3670. i = mob_once_spawn(sd,(char*)map,x,y,"--en--",class_,1,event);
  3671. if ((master_id || flag || duration) && i) { //Further manipulate crafted char.
  3672. struct mob_data* md = (struct mob_data*)map_id2bl(i);
  3673. if (md && md->bl.type == BL_MOB) {
  3674. if (flag&1) //Friendly Character
  3675. md->special_state.ai = 1;
  3676. if (master_id) //Attach to Master
  3677. md->master_id = master_id;
  3678. if (duration) //Auto Delete after a while.
  3679. md->deletetimer = add_timer (gettick() + duration, mob_timer_delete, i, 0);
  3680. }
  3681. #if 0
  3682. //I am playing with this for packet-research purposes, enable it if you want, but don't remove it :X [Skotlex]
  3683. //Guardian data
  3684. if (sd->status.guild_id) {
  3685. struct guild* g = guild_search(sd->status.guild_id);
  3686. md->guardian_data = aCalloc(1, sizeof(struct guardian_data));
  3687. md->guardian_data->castle = NULL;
  3688. md->guardian_data->number = MAX_GUARDIANS;
  3689. md->guardian_data->guild_id = sd->status.guild_id;
  3690. if (g)
  3691. {
  3692. md->guardian_data->emblem_id = g->emblem_id;
  3693. memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
  3694. }
  3695. }
  3696. #endif
  3697. }
  3698. return i;
  3699. }
  3700. int mob_clone_delete(int class_)
  3701. {
  3702. int i;
  3703. for(i=MOB_CLONE_START; i<MOB_CLONE_END; i++){
  3704. if(i==class_ && mob_db_data[i]!=NULL){
  3705. aFree(mob_db_data[i]);
  3706. mob_db_data[i]=NULL;
  3707. break;
  3708. }
  3709. }
  3710. return 0;
  3711. }
  3712. //
  3713. // 初期化
  3714. //
  3715. /*==========================================
  3716. * Since un-setting [ mob ] up was used, it is an initial provisional value setup.
  3717. *------------------------------------------
  3718. */
  3719. static int mob_makedummymobdb(int class_)
  3720. {
  3721. if (mob_dummy != NULL)
  3722. {
  3723. if (mob_db(class_) == mob_dummy)
  3724. return 1; //Using the mob_dummy data already. [Skotlex]
  3725. if (class_ > 0 && class_ <= MAX_MOB_DB)
  3726. { //Remove the mob data so that it uses the dummy data instead.
  3727. aFree(mob_db_data[class_]);
  3728. mob_db_data[class_] = NULL;
  3729. }
  3730. return 0;
  3731. }
  3732. //Initialize dummy data.
  3733. mob_dummy = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); //Initializing the dummy mob.
  3734. sprintf(mob_dummy->name,"DUMMY");
  3735. sprintf(mob_dummy->jname,"Dummy");
  3736. mob_dummy->lv=1;
  3737. mob_dummy->max_hp=1000;
  3738. mob_dummy->max_sp=1;
  3739. mob_dummy->base_exp=2;
  3740. mob_dummy->job_exp=1;
  3741. mob_dummy->range=1;
  3742. mob_dummy->atk1=7;
  3743. mob_dummy->atk2=10;
  3744. mob_dummy->def=0;
  3745. mob_dummy->mdef=0;
  3746. mob_dummy->str=1;
  3747. mob_dummy->agi=1;
  3748. mob_dummy->vit=1;
  3749. mob_dummy->int_=1;
  3750. mob_dummy->dex=6;
  3751. mob_dummy->luk=2;
  3752. mob_dummy->range2=10;
  3753. mob_dummy->range3=10;
  3754. mob_dummy->race=0;
  3755. mob_dummy->element=0;
  3756. mob_dummy->mode=0;
  3757. mob_dummy->speed=300;
  3758. mob_dummy->adelay=1000;
  3759. mob_dummy->amotion=500;
  3760. mob_dummy->dmotion=500;
  3761. return 0;
  3762. }
  3763. //Adjusts the drop rate of item according to the criteria given. [Skotlex]
  3764. static int mob_drop_adjust(int rate, int rate_adjust, int rate_min, int rate_max)
  3765. {
  3766. if (battle_config.logarithmic_drops && rate_adjust > 0) //Logarithmic drops equation by Ishizu-Chan
  3767. //Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5))
  3768. //x is the normal Droprate, y is the Modificator.
  3769. rate = (int)(rate * pow((5.0 - log10(rate)), (log(rate_adjust/100.) / log(5.0))) + 0.5);
  3770. else //Classical linear rate adjustment.
  3771. rate = rate*rate_adjust/100;
  3772. return (rate>rate_max)?rate_max:((rate<rate_min)?rate_min:rate);
  3773. }
  3774. /*==========================================
  3775. * mob_db.txt reading
  3776. *------------------------------------------
  3777. */
  3778. static int mob_readdb(void)
  3779. {
  3780. FILE *fp;
  3781. char line[1024];
  3782. char *filename[]={ "mob_db.txt","mob_db2.txt" };
  3783. int class_, i, fi, k;
  3784. for(fi=0;fi<2;fi++){
  3785. sprintf(line, "%s/%s", db_path, filename[fi]);
  3786. fp=fopen(line,"r");
  3787. if(fp==NULL){
  3788. if(fi>0)
  3789. continue;
  3790. return -1;
  3791. }
  3792. while(fgets(line,1020,fp)){
  3793. double exp, maxhp;
  3794. char *str[60], *p, *np; // 55->60 Lupus
  3795. if(line[0] == '/' && line[1] == '/')
  3796. continue;
  3797. for(i=0,p=line;i<60;i++){
  3798. if((np=strchr(p,','))!=NULL){
  3799. str[i]=p;
  3800. *np=0;
  3801. p=np+1;
  3802. } else
  3803. str[i]=p;
  3804. }
  3805. class_ = atoi(str[0]);
  3806. if (class_ == 0)
  3807. continue; //Leave blank lines alone... [Skotlex]
  3808. if (class_ <= 1000 || class_ > MAX_MOB_DB)
  3809. {
  3810. ShowWarning("Mob with ID: %d not loaded. ID must be in range [%d-%d]\n", class_, 1000, MAX_MOB_DB);
  3811. continue;
  3812. } else if (pcdb_checkid(class_))
  3813. {
  3814. ShowWarning("Mob with ID: %d not loaded. That ID is reserved for player classes.\n");
  3815. continue;
  3816. }
  3817. if (mob_db_data[class_] == NULL)
  3818. mob_db_data[class_] = aCalloc(1, sizeof (struct mob_data));
  3819. mob_db_data[class_]->view_class = class_;
  3820. memcpy(mob_db_data[class_]->name, str[1], NAME_LENGTH-1);
  3821. memcpy(mob_db_data[class_]->jname, str[2], NAME_LENGTH-1);
  3822. mob_db_data[class_]->lv = atoi(str[3]);
  3823. mob_db_data[class_]->max_hp = atoi(str[4]);
  3824. mob_db_data[class_]->max_sp = atoi(str[5]);
  3825. exp = (double)atoi(str[6]) * (double)battle_config.base_exp_rate / 100.;
  3826. if (exp < 0)
  3827. mob_db_data[class_]->base_exp = 0;
  3828. if (exp > UINT_MAX)
  3829. mob_db_data[class_]->base_exp = UINT_MAX;
  3830. else
  3831. mob_db_data[class_]->base_exp = (unsigned int)exp;
  3832. exp = (double)atoi(str[7]) * (double)battle_config.job_exp_rate / 100.;
  3833. if (exp < 0)
  3834. mob_db_data[class_]->job_exp = 0;
  3835. else if (exp > UINT_MAX)
  3836. mob_db_data[class_]->job_exp = UINT_MAX;
  3837. else
  3838. mob_db_data[class_]->job_exp = (unsigned int)exp;
  3839. mob_db_data[class_]->range=atoi(str[8]);
  3840. mob_db_data[class_]->atk1=atoi(str[9]);
  3841. mob_db_data[class_]->atk2=atoi(str[10]);
  3842. mob_db_data[class_]->def=atoi(str[11]);
  3843. mob_db_data[class_]->mdef=atoi(str[12]);
  3844. mob_db_data[class_]->str=atoi(str[13]);
  3845. mob_db_data[class_]->agi=atoi(str[14]);
  3846. mob_db_data[class_]->vit=atoi(str[15]);
  3847. mob_db_data[class_]->int_=atoi(str[16]);
  3848. mob_db_data[class_]->dex=atoi(str[17]);
  3849. mob_db_data[class_]->luk=atoi(str[18]);
  3850. mob_db_data[class_]->range2=atoi(str[19]);
  3851. mob_db_data[class_]->range3=atoi(str[20]);
  3852. mob_db_data[class_]->size=atoi(str[21]);
  3853. mob_db_data[class_]->race=atoi(str[22]);
  3854. mob_db_data[class_]->element=atoi(str[23]);
  3855. mob_db_data[class_]->mode=atoi(str[24]);
  3856. mob_db_data[class_]->speed=atoi(str[25]);
  3857. mob_db_data[class_]->adelay=atoi(str[26]);
  3858. mob_db_data[class_]->amotion=atoi(str[27]);
  3859. mob_db_data[class_]->dmotion=atoi(str[28]);
  3860. for(i=0;i<10;i++){ // 8 -> 10 Lupus
  3861. int rate = 0,rate_adjust,type,ratemin,ratemax;
  3862. struct item_data *id;
  3863. mob_db_data[class_]->dropitem[i].nameid=atoi(str[29+i*2]);
  3864. if (!mob_db_data[class_]->dropitem[i].nameid) {
  3865. //No drop.
  3866. mob_db_data[class_]->dropitem[i].p = 0;
  3867. continue;
  3868. }
  3869. type = itemdb_type(mob_db_data[class_]->dropitem[i].nameid);
  3870. rate = atoi(str[30+i*2]);
  3871. if (class_ >= 1324 && class_ <= 1363)
  3872. { //Treasure box drop rates [Skotlex]
  3873. rate_adjust = battle_config.item_rate_treasure;
  3874. ratemin = battle_config.item_drop_treasure_min;
  3875. ratemax = battle_config.item_drop_treasure_max;
  3876. }
  3877. else switch (type)
  3878. {
  3879. case 0:
  3880. rate_adjust = battle_config.item_rate_heal;
  3881. ratemin = battle_config.item_drop_heal_min;
  3882. ratemax = battle_config.item_drop_heal_max;
  3883. break;
  3884. case 2:
  3885. rate_adjust = battle_config.item_rate_use;
  3886. ratemin = battle_config.item_drop_use_min;
  3887. ratemax = battle_config.item_drop_use_max;
  3888. break;
  3889. case 4:
  3890. case 5:
  3891. case 8: // Changed to include Pet Equip
  3892. rate_adjust = battle_config.item_rate_equip;
  3893. ratemin = battle_config.item_drop_equip_min;
  3894. ratemax = battle_config.item_drop_equip_max;
  3895. break;
  3896. case 6:
  3897. rate_adjust = battle_config.item_rate_card;
  3898. ratemin = battle_config.item_drop_card_min;
  3899. ratemax = battle_config.item_drop_card_max;
  3900. break;
  3901. default:
  3902. rate_adjust = battle_config.item_rate_common;
  3903. ratemin = battle_config.item_drop_common_min;
  3904. ratemax = battle_config.item_drop_common_max;
  3905. break;
  3906. }
  3907. mob_db_data[class_]->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax);
  3908. //calculate and store Max available drop chance of the item
  3909. if (mob_db_data[class_]->dropitem[i].p) {
  3910. id = itemdb_search(mob_db_data[class_]->dropitem[i].nameid);
  3911. if (id->maxchance==10000 || (id->maxchance < mob_db_data[class_]->dropitem[i].p) ) {
  3912. //item has bigger drop chance or sold in shops
  3913. id->maxchance = mob_db_data[class_]->dropitem[i].p;
  3914. }
  3915. for (k = 0; k< MAX_SEARCH; k++) {
  3916. if (id->mob[k].chance < mob_db_data[class_]->dropitem[i].p && id->mob[k].id != class_)
  3917. break;
  3918. }
  3919. if (k == MAX_SEARCH)
  3920. continue;
  3921. memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0]));
  3922. id->mob[k].chance = mob_db_data[class_]->dropitem[i].p;
  3923. id->mob[k].id = class_;
  3924. }
  3925. }
  3926. // MVP EXP Bonus, Chance: MEXP,ExpPer
  3927. mob_db_data[class_]->mexp=atoi(str[49])*battle_config.mvp_exp_rate/100;
  3928. mob_db_data[class_]->mexpper=atoi(str[50]);
  3929. //Now that we know if it is an mvp or not,
  3930. //apply battle_config modifiers [Skotlex]
  3931. maxhp = (double)mob_db_data[class_]->max_hp;
  3932. if (mob_db_data[class_]->mexp > 0)
  3933. { //Mvp
  3934. if (battle_config.mvp_hp_rate != 100)
  3935. maxhp = maxhp * (double)battle_config.mvp_hp_rate /100.;
  3936. } else if (battle_config.monster_hp_rate != 100) //Normal mob
  3937. maxhp = maxhp * (double)battle_config.monster_hp_rate /100.;
  3938. if (maxhp < 1) maxhp = 1;
  3939. else if (maxhp > 0x7fffffff) maxhp = 0x7fffffff;
  3940. mob_db_data[class_]->max_hp = (int)maxhp;
  3941. // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
  3942. for(i=0;i<3;i++){
  3943. struct item_data *id;
  3944. mob_db_data[class_]->mvpitem[i].nameid=atoi(str[51+i*2]);
  3945. if (!mob_db_data[class_]->mvpitem[i].nameid) {
  3946. //No item....
  3947. mob_db_data[class_]->mvpitem[i].p = 0;
  3948. continue;
  3949. }
  3950. mob_db_data[class_]->mvpitem[i].p= mob_drop_adjust(atoi(str[52+i*2]), battle_config.item_rate_mvp,
  3951. battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max);
  3952. //calculate and store Max available drop chance of the MVP item
  3953. if (mob_db_data[class_]->mvpitem[i].p) {
  3954. id = itemdb_search(mob_db_data[class_]->mvpitem[i].nameid);
  3955. if (id->maxchance==10000 || (id->maxchance < mob_db_data[class_]->mvpitem[i].p/10+1) ) {
  3956. //item has bigger drop chance or sold in shops
  3957. id->maxchance = mob_db_data[class_]->mvpitem[i].p/10+1; //reduce MVP drop info to not spoil common drop rate
  3958. }
  3959. }
  3960. }
  3961. if (mob_db_data[class_]->max_hp <= 0) {
  3962. ShowWarning ("Mob %d (%s) has no HP, using poring data for it\n", class_, mob_db_data[class_]->jname);
  3963. mob_makedummymobdb(class_);
  3964. }
  3965. }
  3966. fclose(fp);
  3967. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[fi]);
  3968. }
  3969. return 0;
  3970. }
  3971. /*==========================================
  3972. * MOB display graphic change data reading
  3973. *------------------------------------------
  3974. */
  3975. static int mob_readdb_mobavail(void)
  3976. {
  3977. FILE *fp;
  3978. char line[1024];
  3979. int ln=0;
  3980. int class_,j,k;
  3981. char *str[20],*p,*np;
  3982. sprintf(line, "%s/mob_avail.txt", db_path);
  3983. if( (fp=fopen(line,"r"))==NULL ){
  3984. ShowError("can't read %s\n", line);
  3985. return -1;
  3986. }
  3987. while(fgets(line,1020,fp)){
  3988. if(line[0]=='/' && line[1]=='/')
  3989. continue;
  3990. memset(str,0,sizeof(str));
  3991. for(j=0,p=line;j<12;j++){
  3992. if((np=strchr(p,','))!=NULL){
  3993. str[j]=p;
  3994. *np=0;
  3995. p=np+1;
  3996. } else
  3997. str[j]=p;
  3998. }
  3999. if(str[0]==NULL)
  4000. continue;
  4001. class_=atoi(str[0]);
  4002. if (class_ == 0)
  4003. continue; //Leave blank lines alone... [Skotlex]
  4004. if(mob_db(class_) == mob_dummy) // 値が異常なら処理しない。
  4005. continue;
  4006. k=atoi(str[1]);
  4007. if(k < 0)
  4008. continue;
  4009. if (j > 3 && k > 23 && k < 69)
  4010. k += 3977; // advanced job/baby class
  4011. mob_db_data[class_]->view_class=k;
  4012. //Player sprites
  4013. if(pcdb_checkid(k)) {
  4014. mob_db_data[class_]->sex=atoi(str[2]);
  4015. mob_db_data[class_]->hair=atoi(str[3]);
  4016. mob_db_data[class_]->hair_color=atoi(str[4]);
  4017. mob_db_data[class_]->weapon=atoi(str[5]);
  4018. mob_db_data[class_]->shield=atoi(str[6]);
  4019. mob_db_data[class_]->head_top=atoi(str[7]);
  4020. mob_db_data[class_]->head_mid=atoi(str[8]);
  4021. mob_db_data[class_]->head_buttom=atoi(str[9]);
  4022. mob_db_data[class_]->option=atoi(str[10])&~0x46;
  4023. mob_db_data[class_]->clothes_color=atoi(str[11]); // Monster player dye option - Valaris
  4024. }
  4025. else if(atoi(str[2]) > 0) mob_db_data[class_]->equip=atoi(str[2]); // mob equipment [Valaris]
  4026. ln++;
  4027. }
  4028. fclose(fp);
  4029. ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"mob_avail.txt");
  4030. return 0;
  4031. }
  4032. /*==========================================
  4033. * Reading of random monster data
  4034. *------------------------------------------
  4035. */
  4036. static int mob_read_randommonster(void)
  4037. {
  4038. FILE *fp;
  4039. char line[1024];
  4040. char *str[10],*p;
  4041. int i,j;
  4042. const char* mobfile[] = {
  4043. "mob_branch.txt",
  4044. "mob_poring.txt",
  4045. "mob_boss.txt" };
  4046. for(i=0;i<MAX_RANDOMMONSTER;i++){
  4047. mob_db_data[0]->summonper[i] = 1002; // 設定し忘れた場合はポリンが出るようにしておく
  4048. sprintf(line, "%s/%s", db_path, mobfile[i]);
  4049. fp=fopen(line,"r");
  4050. if(fp==NULL){
  4051. ShowError("can't read %s\n",line);
  4052. return -1;
  4053. }
  4054. while(fgets(line,1020,fp)){
  4055. int class_,per;
  4056. if(line[0] == '/' && line[1] == '/')
  4057. continue;
  4058. memset(str,0,sizeof(str));
  4059. for(j=0,p=line;j<3 && p;j++){
  4060. str[j]=p;
  4061. p=strchr(p,',');
  4062. if(p) *p++=0;
  4063. }
  4064. if(str[0]==NULL || str[2]==NULL)
  4065. continue;
  4066. class_ = atoi(str[0]);
  4067. per=atoi(str[2]);
  4068. if(mob_db(class_) != mob_dummy)
  4069. mob_db_data[class_]->summonper[i]=per;
  4070. }
  4071. fclose(fp);
  4072. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]);
  4073. }
  4074. return 0;
  4075. }
  4076. /*==========================================
  4077. * mob_skill_db.txt reading
  4078. *------------------------------------------
  4079. */
  4080. static int mob_readskilldb(void)
  4081. {
  4082. FILE *fp;
  4083. char line[1024];
  4084. int i,tmp, count;
  4085. const struct {
  4086. char str[32];
  4087. int id;
  4088. } cond1[] = {
  4089. { "always", MSC_ALWAYS },
  4090. { "myhpltmaxrate", MSC_MYHPLTMAXRATE },
  4091. { "myhpinrate", MSC_MYHPINRATE },
  4092. { "friendhpltmaxrate",MSC_FRIENDHPLTMAXRATE },
  4093. { "friendhpinrate", MSC_FRIENDHPINRATE },
  4094. { "mystatuson", MSC_MYSTATUSON },
  4095. { "mystatusoff", MSC_MYSTATUSOFF },
  4096. { "friendstatuson", MSC_FRIENDSTATUSON },
  4097. { "friendstatusoff", MSC_FRIENDSTATUSOFF },
  4098. { "attackpcgt", MSC_ATTACKPCGT },
  4099. { "attackpcge", MSC_ATTACKPCGE },
  4100. { "slavelt", MSC_SLAVELT },
  4101. { "slavele", MSC_SLAVELE },
  4102. { "closedattacked", MSC_CLOSEDATTACKED },
  4103. { "longrangeattacked",MSC_LONGRANGEATTACKED },
  4104. { "skillused", MSC_SKILLUSED },
  4105. { "afterskill", MSC_AFTERSKILL },
  4106. { "casttargeted", MSC_CASTTARGETED },
  4107. { "rudeattacked", MSC_RUDEATTACKED },
  4108. { "masterhpltmaxrate",MSC_MASTERHPLTMAXRATE },
  4109. { "masterattacked", MSC_MASTERATTACKED },
  4110. { "alchemist", MSC_ALCHEMIST },
  4111. { "onspawn", MSC_SPAWN},
  4112. }, cond2[] ={
  4113. { "anybad", -1 },
  4114. { "stone", SC_STONE },
  4115. { "freeze", SC_FREEZE },
  4116. { "stan", SC_STUN },
  4117. { "sleep", SC_SLEEP },
  4118. { "poison", SC_POISON },
  4119. { "curse", SC_CURSE },
  4120. { "silence", SC_SILENCE },
  4121. { "confusion", SC_CONFUSION },
  4122. { "blind", SC_BLIND },
  4123. { "hiding", SC_HIDING },
  4124. { "sight", SC_SIGHT },
  4125. }, state[] = {
  4126. { "any", -1 },
  4127. { "idle", MSS_IDLE },
  4128. { "walk", MSS_WALK },
  4129. { "loot", MSS_LOOT },
  4130. { "dead", MSS_DEAD },
  4131. { "attack", MSS_BERSERK }, //Retaliating attack
  4132. { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs)
  4133. { "chase", MSS_RUSH }, //Chase escaping target
  4134. { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs)
  4135. }, target[] = {
  4136. { "target", MST_TARGET },
  4137. { "self", MST_SELF },
  4138. { "friend", MST_FRIEND },
  4139. { "master", MST_MASTER },
  4140. { "around5", MST_AROUND5 },
  4141. { "around6", MST_AROUND6 },
  4142. { "around7", MST_AROUND7 },
  4143. { "around8", MST_AROUND8 },
  4144. { "around1", MST_AROUND1 },
  4145. { "around2", MST_AROUND2 },
  4146. { "around3", MST_AROUND3 },
  4147. { "around4", MST_AROUND4 },
  4148. { "around", MST_AROUND },
  4149. };
  4150. int x;
  4151. char *filename[]={ "mob_skill_db.txt","mob_skill_db2.txt" };
  4152. if (!battle_config.mob_skill_rate) {
  4153. ShowStatus("Mob skill use disabled. Not reading mob skills.\n");
  4154. return 0;
  4155. }
  4156. for(x=0;x<2;x++){
  4157. count = 0;
  4158. sprintf(line, "%s/%s", db_path, filename[x]);
  4159. fp=fopen(line,"r");
  4160. if(fp==NULL){
  4161. if(x==0)
  4162. ShowError("can't read %s\n",line);
  4163. continue;
  4164. }
  4165. while(fgets(line,1020,fp)){
  4166. char *sp[20],*p;
  4167. int mob_id;
  4168. struct mob_skill *ms, gms;
  4169. int j=0;
  4170. count++;
  4171. if(line[0] == '/' && line[1] == '/')
  4172. continue;
  4173. memset(sp,0,sizeof(sp));
  4174. for(i=0,p=line;i<18 && p;i++){
  4175. sp[i]=p;
  4176. if((p=strchr(p,','))!=NULL)
  4177. *p++=0;
  4178. }
  4179. if(i == 0 || (mob_id=atoi(sp[0]))== 0)
  4180. continue;
  4181. if(i < 18) {
  4182. ShowError("mob_skill: Insufficient number of fields for skill at %s, line %d\n", filename[x], count);
  4183. continue;
  4184. }
  4185. if (mob_id > 0 && mob_db(mob_id) == mob_dummy)
  4186. {
  4187. ShowError("mob_skill: Invalid mob id %d at %s, line %d\n", mob_id, filename[x], count);
  4188. continue;
  4189. }
  4190. if( strcmp(sp[1],"clear")==0 ){
  4191. if (mob_id < 0)
  4192. continue;
  4193. memset(mob_db_data[mob_id]->skill,0,sizeof(struct mob_skill));
  4194. mob_db_data[mob_id]->maxskill=0;
  4195. continue;
  4196. }
  4197. if (mob_id < 0)
  4198. { //Prepare global skill. [Skotlex]
  4199. memset(&gms, 0, sizeof (struct mob_skill));
  4200. ms = &gms;
  4201. } else {
  4202. for(i=0;i<MAX_MOBSKILL;i++)
  4203. if( (ms=&mob_db_data[mob_id]->skill[i])->skill_id == 0)
  4204. break;
  4205. if(i==MAX_MOBSKILL){
  4206. ShowWarning("mob_skill: readdb: too many skill ! [%s] in %d[%s]\n",
  4207. sp[1],mob_id,mob_db_data[mob_id]->jname);
  4208. continue;
  4209. }
  4210. }
  4211. ms->state=atoi(sp[2]);
  4212. tmp = sizeof(state)/sizeof(state[0]);
  4213. for(j=0;j<tmp && strcmp(sp[2],state[j].str);j++);
  4214. if (j < tmp)
  4215. ms->state=state[j].id;
  4216. else
  4217. ShowError("mob_skill: Unrecognized state %s at %s, line %d\n", sp[2], filename[x], count);
  4218. //Skill ID
  4219. j=atoi(sp[3]);
  4220. if (j<=0 || j>MAX_SKILL_DB) //fixed Lupus
  4221. {
  4222. if (mob_id < 0)
  4223. ShowWarning("Invalid Skill ID (%d) for all mobs\n", j);
  4224. else
  4225. ShowWarning("Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob_db_data[mob_id]->jname);
  4226. continue;
  4227. }
  4228. ms->skill_id=j;
  4229. //Skill lvl
  4230. j= atoi(sp[4])<=0 ? 1 : atoi(sp[4]);
  4231. ms->skill_lv= j>battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : j; //we strip max skill level
  4232. //Apply battle_config modifiers to rate (permillage) and delay [Skotlex]
  4233. tmp = atoi(sp[5]);
  4234. if (battle_config.mob_skill_rate != 100)
  4235. tmp = tmp*battle_config.mob_skill_rate/100;
  4236. if (tmp > 10000)
  4237. ms->permillage= 10000;
  4238. else
  4239. ms->permillage= tmp;
  4240. ms->casttime=atoi(sp[6]);
  4241. ms->delay=atoi(sp[7]);
  4242. if (battle_config.mob_skill_delay != 100)
  4243. ms->delay = ms->delay*battle_config.mob_skill_delay/100;
  4244. if (ms->delay < 0) //time overflow?
  4245. ms->delay = INT_MAX;
  4246. ms->cancel=atoi(sp[8]);
  4247. if( strcmp(sp[8],"yes")==0 ) ms->cancel=1;
  4248. ms->target=atoi(sp[9]);
  4249. for(j=0;j<sizeof(target)/sizeof(target[0]);j++){
  4250. if( strcmp(sp[9],target[j].str)==0)
  4251. ms->target=target[j].id;
  4252. }
  4253. ms->cond1=-1;
  4254. tmp = sizeof(cond1)/sizeof(cond1[0]);
  4255. for(j=0;j<tmp && strcmp(sp[10],cond1[j].str);j++);
  4256. if (j < tmp)
  4257. ms->cond1=cond1[j].id;
  4258. else
  4259. ShowError("mob_skill: Unrecognized condition 1 %s at %s, line %d\n", sp[10], filename[x], count);
  4260. ms->cond2=atoi(sp[11]);
  4261. tmp = sizeof(cond2)/sizeof(cond2[0]);
  4262. for(j=0;j<tmp && strcmp(sp[11],cond2[j].str);j++);
  4263. if (j < tmp)
  4264. ms->cond2=cond2[j].id;
  4265. ms->val[0]=atoi(sp[12]);
  4266. ms->val[1]=atoi(sp[13]);
  4267. ms->val[2]=atoi(sp[14]);
  4268. ms->val[3]=atoi(sp[15]);
  4269. ms->val[4]=atoi(sp[16]);
  4270. if(sp[17] != NULL && strlen(sp[17])>2)
  4271. ms->emotion=atoi(sp[17]);
  4272. else
  4273. ms->emotion=-1;
  4274. if (mob_id < 0)
  4275. { //Set this skill to ALL mobs. [Skotlex]
  4276. mob_id *= -1;
  4277. for (i = 1; i < MAX_MOB_DB; i++)
  4278. {
  4279. if (mob_db_data[i] == NULL)
  4280. continue;
  4281. if (mob_db_data[i]->mode&MD_BOSS)
  4282. {
  4283. if (!(mob_id&2)) //Skill not for bosses
  4284. continue;
  4285. } else
  4286. if (!(mob_id&1)) //Skill not for normal enemies.
  4287. continue;
  4288. for(j=0;j<MAX_MOBSKILL;j++)
  4289. if( mob_db_data[i]->skill[j].skill_id == 0)
  4290. break;
  4291. if(j==MAX_MOBSKILL)
  4292. continue;
  4293. memcpy (&mob_db_data[i]->skill[j], ms, sizeof(struct mob_skill));
  4294. mob_db_data[i]->maxskill=j+1;
  4295. }
  4296. } else //Skill set on a single mob.
  4297. mob_db_data[mob_id]->maxskill=i+1;
  4298. }
  4299. fclose(fp);
  4300. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[x]);
  4301. }
  4302. return 0;
  4303. }
  4304. /*==========================================
  4305. * mob_race_db.txt reading
  4306. *------------------------------------------
  4307. */
  4308. static int mob_readdb_race(void)
  4309. {
  4310. FILE *fp;
  4311. char line[1024];
  4312. int race,j,k;
  4313. char *str[20],*p,*np;
  4314. sprintf(line, "%s/mob_race2_db.txt", db_path);
  4315. if( (fp=fopen(line,"r"))==NULL ){
  4316. ShowError("can't read %s\n", line);
  4317. return -1;
  4318. }
  4319. while(fgets(line,1020,fp)){
  4320. if(line[0]=='/' && line[1]=='/')
  4321. continue;
  4322. memset(str,0,sizeof(str));
  4323. for(j=0,p=line;j<12;j++){
  4324. if((np=strchr(p,','))!=NULL){
  4325. str[j]=p;
  4326. *np=0;
  4327. p=np+1;
  4328. } else
  4329. str[j]=p;
  4330. }
  4331. if(str[0]==NULL)
  4332. continue;
  4333. race=atoi(str[0]);
  4334. if (race < 0 || race >= MAX_MOB_RACE_DB)
  4335. continue;
  4336. for (j=1; j<20; j++) {
  4337. if (!str[j])
  4338. break;
  4339. k=atoi(str[j]);
  4340. if (mob_db(k) == mob_dummy)
  4341. continue;
  4342. mob_db_data[k]->race2 = race;
  4343. }
  4344. }
  4345. fclose(fp);
  4346. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","mob_race2_db.txt");
  4347. return 0;
  4348. }
  4349. #ifndef TXT_ONLY
  4350. /*==========================================
  4351. * SQL reading
  4352. *------------------------------------------
  4353. */
  4354. static int mob_read_sqldb(void)
  4355. {
  4356. const char unknown_str[NAME_LENGTH] ="unknown";
  4357. int i, fi, class_, k;
  4358. double exp, maxhp;
  4359. long unsigned int ln = 0;
  4360. char *mob_db_name[] = { mob_db_db, mob_db2_db };
  4361. //For easier handling of converting. [Skotlex]
  4362. #define TO_INT(a) (sql_row[a]==NULL?0:atoi(sql_row[a]))
  4363. #define TO_STR(a) (sql_row[a]==NULL?unknown_str:sql_row[a])
  4364. for (fi = 0; fi < 2; fi++) {
  4365. sprintf (tmp_sql, "SELECT * FROM `%s`", mob_db_name[fi]);
  4366. if (mysql_query(&mmysql_handle, tmp_sql)) {
  4367. ShowSQL("DB error (%s) - %s\n", mob_db_name[fi], mysql_error(&mmysql_handle));
  4368. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  4369. continue;
  4370. }
  4371. sql_res = mysql_store_result(&mmysql_handle);
  4372. if (sql_res) {
  4373. while((sql_row = mysql_fetch_row(sql_res))){
  4374. class_ = TO_INT(0);
  4375. if (class_ <= 1000 || class_ > MAX_MOB_DB)
  4376. {
  4377. ShowWarning("Mob with ID: %d not loaded. ID must be in range [%d-%d]\n", class_, 1000, MAX_MOB_DB);
  4378. continue;
  4379. } else if (pcdb_checkid(class_))
  4380. {
  4381. ShowWarning("Mob with ID: %d not loaded. That ID is reserved for Upper Classes.\n");
  4382. continue;
  4383. }
  4384. if (mob_db_data[class_] == NULL)
  4385. mob_db_data[class_] = aCalloc(1, sizeof (struct mob_data));
  4386. ln++;
  4387. mob_db_data[class_]->view_class = class_;
  4388. memcpy(mob_db_data[class_]->name, TO_STR(1), NAME_LENGTH-1);
  4389. memcpy(mob_db_data[class_]->jname, TO_STR(2), NAME_LENGTH-1);
  4390. mob_db_data[class_]->lv = TO_INT(3);
  4391. mob_db_data[class_]->max_hp = TO_INT(4);
  4392. mob_db_data[class_]->max_sp = TO_INT(5);
  4393. exp = (double)TO_INT(6) * (double)battle_config.base_exp_rate / 100.;
  4394. if (exp < 0)
  4395. mob_db_data[class_]->base_exp = 0;
  4396. else if (exp > UINT_MAX)
  4397. mob_db_data[class_]->base_exp = UINT_MAX;
  4398. else
  4399. mob_db_data[class_]->base_exp = (unsigned int)exp;
  4400. exp = (double)TO_INT(7) * (double)battle_config.job_exp_rate / 100.;
  4401. if (exp < 0)
  4402. mob_db_data[class_]->job_exp = 0;
  4403. else if (exp > UINT_MAX)
  4404. mob_db_data[class_]->job_exp = UINT_MAX;
  4405. else
  4406. mob_db_data[class_]->job_exp = (unsigned int)exp;
  4407. mob_db_data[class_]->range = TO_INT(8);
  4408. mob_db_data[class_]->atk1 = TO_INT(9);
  4409. mob_db_data[class_]->atk2 = TO_INT(10);
  4410. mob_db_data[class_]->def = TO_INT(11);
  4411. mob_db_data[class_]->mdef = TO_INT(12);
  4412. mob_db_data[class_]->str = TO_INT(13);
  4413. mob_db_data[class_]->agi = TO_INT(14);
  4414. mob_db_data[class_]->vit = TO_INT(15);
  4415. mob_db_data[class_]->int_ = TO_INT(16);
  4416. mob_db_data[class_]->dex = TO_INT(17);
  4417. mob_db_data[class_]->luk = TO_INT(18);
  4418. mob_db_data[class_]->range2 = TO_INT(19);
  4419. mob_db_data[class_]->range3 = TO_INT(20);
  4420. mob_db_data[class_]->size = TO_INT(21);
  4421. mob_db_data[class_]->race = TO_INT(22);
  4422. mob_db_data[class_]->element = TO_INT(23);
  4423. mob_db_data[class_]->mode = TO_INT(24);
  4424. mob_db_data[class_]->speed = TO_INT(25);
  4425. mob_db_data[class_]->adelay = TO_INT(26);
  4426. mob_db_data[class_]->amotion = TO_INT(27);
  4427. mob_db_data[class_]->dmotion = TO_INT(28);
  4428. for (i = 0; i < 10; i++){ // 8 -> 10 Lupus
  4429. int rate = 0, rate_adjust, type, ratemin, ratemax;
  4430. struct item_data *id;
  4431. mob_db_data[class_]->dropitem[i].nameid=TO_INT(29+i*2);
  4432. if (!mob_db_data[class_]->dropitem[i].nameid) {
  4433. //No drop.
  4434. mob_db_data[class_]->dropitem[i].p = 0;
  4435. continue;
  4436. }
  4437. type = itemdb_type(mob_db_data[class_]->dropitem[i].nameid);
  4438. rate = TO_INT(30+i*2);
  4439. if (class_ >= 1324 && class_ <= 1363)
  4440. { //Treasure box drop rates [Skotlex]
  4441. rate_adjust = battle_config.item_rate_treasure;
  4442. ratemin = battle_config.item_drop_treasure_min;
  4443. ratemax = battle_config.item_drop_treasure_max;
  4444. }
  4445. else switch(type)
  4446. {
  4447. case 0: // Added by Valaris
  4448. rate_adjust = battle_config.item_rate_heal;
  4449. ratemin = battle_config.item_drop_heal_min;
  4450. ratemax = battle_config.item_drop_heal_max;
  4451. break;
  4452. case 2:
  4453. rate_adjust = battle_config.item_rate_use;
  4454. ratemin = battle_config.item_drop_use_min;
  4455. ratemax = battle_config.item_drop_use_max; // End
  4456. break;
  4457. case 4:
  4458. case 5:
  4459. case 8: // Changed to include Pet Equip
  4460. rate_adjust = battle_config.item_rate_equip;
  4461. ratemin = battle_config.item_drop_equip_min;
  4462. ratemax = battle_config.item_drop_equip_max;
  4463. break;
  4464. case 6:
  4465. rate_adjust = battle_config.item_rate_card;
  4466. ratemin = battle_config.item_drop_card_min;
  4467. ratemax = battle_config.item_drop_card_max;
  4468. break;
  4469. default:
  4470. rate_adjust = battle_config.item_rate_common;
  4471. ratemin = battle_config.item_drop_common_min;
  4472. ratemax = battle_config.item_drop_common_max;
  4473. break;
  4474. }
  4475. mob_db_data[class_]->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax);
  4476. //calculate and store Max available drop chance of the item
  4477. if (mob_db_data[class_]->dropitem[i].p) {
  4478. id = itemdb_search(mob_db_data[class_]->dropitem[i].nameid);
  4479. if (id->maxchance==10000 || (id->maxchance < mob_db_data[class_]->dropitem[i].p) ) {
  4480. //item has bigger drop chance or sold in shops
  4481. id->maxchance = mob_db_data[class_]->dropitem[i].p;
  4482. }
  4483. for (k = 0; k< MAX_SEARCH; k++) {
  4484. if (id->mob[k].chance < mob_db_data[class_]->dropitem[i].p && id->mob[k].id != class_)
  4485. break;
  4486. }
  4487. if (k == MAX_SEARCH)
  4488. continue;
  4489. memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0]));
  4490. id->mob[k].chance = mob_db_data[class_]->dropitem[i].p;
  4491. id->mob[k].id = class_;
  4492. }
  4493. }
  4494. // MVP EXP Bonus, Chance: MEXP,ExpPer
  4495. mob_db_data[class_]->mexp = TO_INT(49) * battle_config.mvp_exp_rate / 100;
  4496. mob_db_data[class_]->mexpper = TO_INT(50);
  4497. //Now that we know if it is an mvp or not,
  4498. //apply battle_config modifiers [Skotlex]
  4499. maxhp = (double)mob_db_data[class_]->max_hp;
  4500. if (mob_db_data[class_]->mexp > 0)
  4501. { //Mvp
  4502. if (battle_config.mvp_hp_rate != 100)
  4503. maxhp = maxhp * (double)battle_config.mvp_hp_rate /100.;
  4504. } else if (battle_config.monster_hp_rate != 100) //Normal mob
  4505. maxhp = maxhp * (double)battle_config.monster_hp_rate /100.;
  4506. if (maxhp < 0) maxhp = 1;
  4507. else if (maxhp > 0x7fffffff) maxhp = 0x7fffffff;
  4508. mob_db_data[class_]->max_hp = (int)maxhp;
  4509. // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
  4510. for (i=0; i<3; i++) {
  4511. struct item_data *id;
  4512. mob_db_data[class_]->mvpitem[i].nameid = TO_INT(51+i*2);
  4513. if (!mob_db_data[class_]->mvpitem[i].nameid) {
  4514. //No item....
  4515. mob_db_data[class_]->mvpitem[i].p = 0;
  4516. continue;
  4517. }
  4518. mob_db_data[class_]->mvpitem[i].p = mob_drop_adjust(TO_INT(52+i*2),
  4519. battle_config.item_rate_mvp, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max);
  4520. //calculate and store Max available drop chance of the MVP item
  4521. id = itemdb_search(mob_db_data[class_]->mvpitem[i].nameid);
  4522. if (mob_db_data[class_]->mvpitem[i].p) {
  4523. if (id->maxchance==10000 || (id->maxchance < mob_db_data[class_]->mvpitem[i].p/10+1) ) {
  4524. //item has bigger drop chance or sold in shops
  4525. id->maxchance = mob_db_data[class_]->mvpitem[i].p/10+1; //reduce MVP drop info to not spoil common drop rate
  4526. }
  4527. }
  4528. }
  4529. if (mob_db_data[class_]->max_hp <= 0) {
  4530. ShowWarning ("Mob %d (%s) has no HP, using poring data for it\n", class_, mob_db_data[class_]->jname);
  4531. mob_makedummymobdb(class_);
  4532. }
  4533. }
  4534. mysql_free_result(sql_res);
  4535. ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, mob_db_name[fi]);
  4536. ln = 0;
  4537. }
  4538. }
  4539. return 0;
  4540. }
  4541. #endif /* not TXT_ONLY */
  4542. void mob_reload(void)
  4543. {
  4544. int i;
  4545. #ifndef TXT_ONLY
  4546. if(db_use_sqldbs)
  4547. mob_read_sqldb();
  4548. else
  4549. #endif /* TXT_ONLY */
  4550. mob_readdb();
  4551. mob_readdb_mobavail();
  4552. mob_read_randommonster();
  4553. //Mob skills need to be cleared before re-reading them. [Skotlex]
  4554. for (i = 0; i < MAX_MOB_DB; i++)
  4555. if (mob_db_data[i])
  4556. {
  4557. memset(&mob_db_data[i]->skill,0,sizeof(mob_db_data[i]->skill));
  4558. mob_db_data[i]->maxskill=0;
  4559. }
  4560. mob_readskilldb();
  4561. mob_readdb_race();
  4562. }
  4563. /*==========================================
  4564. * Circumference initialization of mob
  4565. *------------------------------------------
  4566. */
  4567. int do_init_mob(void)
  4568. { //Initialize the mob database
  4569. memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
  4570. mob_db_data[0] = aCalloc(1, sizeof (struct mob_data)); //This mob is used for random spawns
  4571. mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
  4572. #ifndef TXT_ONLY
  4573. if(db_use_sqldbs)
  4574. mob_read_sqldb();
  4575. else
  4576. #endif /* TXT_ONLY */
  4577. mob_readdb();
  4578. mob_readdb_mobavail();
  4579. mob_read_randommonster();
  4580. mob_readskilldb();
  4581. mob_readdb_race();
  4582. add_timer_func_list(mob_timer,"mob_timer");
  4583. add_timer_func_list(mob_delayspawn,"mob_delayspawn");
  4584. add_timer_func_list(mob_delay_item_drop,"mob_delay_item_drop");
  4585. add_timer_func_list(mob_ai_hard,"mob_ai_hard");
  4586. add_timer_func_list(mob_ai_lazy,"mob_ai_lazy");
  4587. add_timer_func_list(mobskill_castend_id,"mobskill_castend_id");
  4588. add_timer_func_list(mobskill_castend_pos,"mobskill_castend_pos");
  4589. add_timer_func_list(mob_timer_delete,"mob_timer_delete");
  4590. add_timer_func_list(mob_spawn_guardian_sub,"mob_spawn_guardian_sub");
  4591. add_timer_func_list(mob_respawn,"mob_respawn");
  4592. add_timer_interval(gettick()+MIN_MOBTHINKTIME,mob_ai_hard,0,0,MIN_MOBTHINKTIME);
  4593. add_timer_interval(gettick()+MIN_MOBTHINKTIME*10,mob_ai_lazy,0,0,MIN_MOBTHINKTIME*10);
  4594. return 0;
  4595. }
  4596. /*==========================================
  4597. * Clean memory usage.
  4598. *------------------------------------------
  4599. */
  4600. int do_final_mob(void)
  4601. {
  4602. int i;
  4603. if (mob_dummy)
  4604. {
  4605. aFree(mob_dummy);
  4606. mob_dummy = NULL;
  4607. }
  4608. for (i = 0; i <= MAX_MOB_DB; i++)
  4609. {
  4610. if (mob_db_data[i] != NULL)
  4611. {
  4612. aFree(mob_db_data[i]);
  4613. mob_db_data[i] = NULL;
  4614. }
  4615. }
  4616. return 0;
  4617. }