skill.c 354 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974
  1. // $Id: skill.c,v 1.8 2004/12/15 8:56:46 PM Celestia $
  2. /* スキル?係 */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include "timer.h"
  8. #include "nullpo.h"
  9. #include "malloc.h"
  10. #include "skill.h"
  11. #include "map.h"
  12. #include "clif.h"
  13. #include "pc.h"
  14. #include "pet.h"
  15. #include "mob.h"
  16. #include "battle.h"
  17. #include "party.h"
  18. #include "itemdb.h"
  19. #include "script.h"
  20. #include "intif.h"
  21. #include "log.h"
  22. #include "chrif.h"
  23. #include "guild.h"
  24. #include "showmsg.h"
  25. #ifdef MEMWATCH
  26. #include "memwatch.h"
  27. #endif
  28. #define SKILLUNITTIMER_INVERVAL 100
  29. #define STATE_BLIND 0x10
  30. /* スキル番?=>ステ?タス異常番??換テ?ブル */
  31. int SkillStatusChangeTable[]={ /* skill.hのenumのSC_***とあわせること */
  32. /* 0- */
  33. -1,-1,-1,-1,-1,-1,
  34. SC_PROVOKE, /* プロボック */
  35. -1, 1,-1,
  36. /* 10- */
  37. SC_SIGHT, /* サイト */
  38. -1,-1,-1,-1,
  39. SC_FREEZE, /* フロストダイバ? */
  40. SC_STONE, /* スト?ンカ?ス */
  41. -1,-1,-1,
  42. /* 20- */
  43. -1,-1,-1,-1,
  44. SC_RUWACH, /* ルアフ */
  45. -1,-1,-1,-1,
  46. SC_INCREASEAGI, /* 速度?加 */
  47. /* 30- */
  48. SC_DECREASEAGI, /* 速度減少 */
  49. -1,
  50. SC_SIGNUMCRUCIS, /* シグナムクルシス */
  51. SC_ANGELUS, /* エンジェラス */
  52. SC_BLESSING, /* ブレッシング */
  53. -1,-1,-1,-1,-1,
  54. /* 40- */
  55. -1,-1,-1,-1,-1,
  56. SC_CONCENTRATE, /* 集中力向上 */
  57. -1,-1,-1,-1,
  58. /* 50- */
  59. -1,
  60. SC_HIDING, /* ハイディング */
  61. -1,-1,-1,-1,-1,-1,-1,-1,
  62. /* 60- */
  63. SC_TWOHANDQUICKEN, /* 2HQ */
  64. SC_AUTOCOUNTER,
  65. -1,-1,-1,-1,
  66. SC_IMPOSITIO, /* インポシティオマヌス */
  67. SC_SUFFRAGIUM, /* サフラギウム */
  68. SC_ASPERSIO, /* アスペルシオ */
  69. SC_BENEDICTIO, /* 聖?降福 */
  70. /* 70- */
  71. -1,
  72. SC_SLOWPOISON,
  73. -1,
  74. SC_KYRIE, /* キリエエレイソン */
  75. SC_MAGNIFICAT, /* マグニフィカ?ト */
  76. SC_GLORIA, /* グロリア */
  77. SC_DIVINA, /* レックスディビ?ナ */
  78. -1,
  79. SC_AETERNA, /* レックスエ?テルナ */
  80. -1,
  81. /* 80- */
  82. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  83. /* 90- */
  84. -1,-1,
  85. SC_QUAGMIRE, /* クァグマイア */
  86. -1,-1,-1,-1,-1,-1,-1,
  87. /* 100- */
  88. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  89. /* 110- */
  90. -1,
  91. SC_ADRENALINE, /* アドレナリンラッシュ */
  92. SC_WEAPONPERFECTION,/* ウェポンパ?フェクション */
  93. SC_OVERTHRUST, /* オ?バ?トラスト */
  94. SC_MAXIMIZEPOWER, /* マキシマイズパワ? */
  95. -1,-1,-1,-1,-1,
  96. /* 120- */
  97. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  98. /* 130- */
  99. -1,-1,-1,-1,-1,
  100. SC_CLOAKING, /* クロ?キング */
  101. SC_STAN, /* ソニックブロ? */
  102. -1,
  103. SC_ENCPOISON, /* エンチャントポイズン */
  104. SC_POISONREACT, /* ポイズンリアクト */
  105. /* 140- */
  106. SC_POISON, /* ベノムダスト */
  107. SC_SPLASHER, /* ベナムスプラッシャ? */
  108. -1,
  109. SC_TRICKDEAD, /* 死んだふり */
  110. -1,-1,SC_AUTOBERSERK,-1,-1,-1,
  111. /* 150- */
  112. -1,-1,-1,-1,-1,
  113. SC_LOUD, /* ラウドボイス */
  114. -1,
  115. SC_ENERGYCOAT, /* エナジ?コ?ト */
  116. -1,-1,
  117. /* 160- */
  118. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  119. -1,-1,-1,
  120. SC_SELFDESTRUCTION,
  121. -1,-1,-1,-1,-1,-1,
  122. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  123. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  124. -1,
  125. SC_KEEPING,
  126. -1,-1,
  127. SC_BARRIER,
  128. -1,-1,
  129. SC_HALLUCINATION,
  130. -1,-1,
  131. /* 210- */
  132. -1,-1,-1,-1,-1,
  133. SC_STRIPWEAPON,
  134. SC_STRIPSHIELD,
  135. SC_STRIPARMOR,
  136. SC_STRIPHELM,
  137. -1,
  138. /* 220- */
  139. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  140. /* 230- */
  141. -1,-1,-1,-1,
  142. SC_CP_WEAPON,
  143. SC_CP_SHIELD,
  144. SC_CP_ARMOR,
  145. SC_CP_HELM,
  146. -1,-1,
  147. /* 240- */
  148. -1,-1,-1,-1,-1,-1,-1,-1,-1,
  149. SC_AUTOGUARD,
  150. /* 250- */
  151. -1,-1,
  152. SC_REFLECTSHIELD,
  153. -1,-1,
  154. SC_DEVOTION,
  155. SC_PROVIDENCE,
  156. SC_DEFENDER,
  157. SC_SPEARSQUICKEN,
  158. -1,
  159. /* 260- */
  160. -1,-1,-1,-1,-1,-1,-1,-1,
  161. SC_STEELBODY,
  162. SC_BLADESTOP_WAIT,
  163. /* 270- */
  164. SC_EXPLOSIONSPIRITS,
  165. SC_EXTREMITYFIST,
  166. -1,-1,-1,-1,
  167. SC_MAGICROD,
  168. -1,-1,-1,
  169. /* 280- */
  170. SC_FLAMELAUNCHER,
  171. SC_FROSTWEAPON,
  172. SC_LIGHTNINGLOADER,
  173. SC_SEISMICWEAPON,
  174. -1,
  175. SC_VOLCANO,
  176. SC_DELUGE,
  177. SC_VIOLENTGALE,
  178. SC_LANDPROTECTOR,
  179. -1,
  180. /* 290- */
  181. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  182. /* 300- */
  183. -1,-1,-1,-1,-1,-1,
  184. SC_LULLABY,
  185. SC_RICHMANKIM,
  186. SC_ETERNALCHAOS,
  187. SC_DRUMBATTLE,
  188. /* 310- */
  189. SC_NIBELUNGEN,
  190. SC_ROKISWEIL,
  191. SC_INTOABYSS,
  192. SC_SIEGFRIED,
  193. -1,-1,-1,
  194. SC_DISSONANCE,
  195. -1,
  196. SC_WHISTLE,
  197. /* 320- */
  198. SC_ASSNCROS,
  199. SC_POEMBRAGI,
  200. SC_APPLEIDUN,
  201. -1,-1,
  202. SC_UGLYDANCE,
  203. -1,
  204. SC_HUMMING,
  205. SC_DONTFORGETME,
  206. SC_FORTUNE,
  207. /* 330- */
  208. SC_SERVICE4U,
  209. SC_SELFDESTRUCTION,
  210. -1,-1,-1,-1,-1,-1,-1,-1,
  211. /* 340- */
  212. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  213. /* 350- */
  214. -1,-1,-1,-1,-1,
  215. SC_AURABLADE,
  216. SC_PARRYING,
  217. SC_CONCENTRATION,
  218. SC_TENSIONRELAX,
  219. SC_BERSERK,
  220. /* 360- */
  221. SC_BERSERK,
  222. SC_ASSUMPTIO,
  223. SC_BASILICA,
  224. -1,-1,-1,
  225. SC_MAGICPOWER,
  226. -1,-1,
  227. SC_GOSPEL,
  228. /* 370- */
  229. -1,-1,-1,-1,-1,-1,-1,-1,
  230. SC_EDP,
  231. -1,
  232. /* 380- */
  233. SC_TRUESIGHT,
  234. -1,-1,
  235. SC_WINDWALK,
  236. SC_MELTDOWN,
  237. -1,-1,
  238. SC_CARTBOOST,
  239. -1,
  240. SC_CHASEWALK,
  241. /* 390- */
  242. SC_REJECTSWORD,
  243. -1,-1,-1,-1,-1,
  244. SC_MARIONETTE,
  245. -1,
  246. SC_HEADCRUSH,
  247. SC_JOINTBEAT,
  248. /* 400 */
  249. -1,-1,
  250. SC_MINDBREAKER,
  251. SC_MEMORIZE,
  252. SC_FOGWALL,
  253. SC_SPIDERWEB,
  254. -1,-1,-1,-1,
  255. /* 410- */
  256. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  257. };
  258. const struct skill_name_db skill_names[] = {
  259. { AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } ,
  260. { AC_CONCENTRATION, "CONCENTRATION", "Improve_Concentration" } ,
  261. { AC_DOUBLE, "DOUBLE", "Double_Strafe" } ,
  262. { AC_MAKINGARROW, "MAKINGARROW", "Arrow_Creation" } ,
  263. { AC_OWL, "OWL", "Owl's_Eye" } ,
  264. { AC_SHOWER, "SHOWER", "Arrow_Shower" } ,
  265. { AC_VULTURE, "VULTURE", "Vulture's_Eye" } ,
  266. { ALL_RESURRECTION, "RESURRECTION", "Resurrection" } ,
  267. { AL_ANGELUS, "ANGELUS", "Angelus" } ,
  268. { AL_BLESSING, "BLESSING", "Blessing" } ,
  269. { AL_CRUCIS, "CRUCIS", "Signum_Crusis" } ,
  270. { AL_CURE, "CURE", "Cure" } ,
  271. { AL_DECAGI, "DECAGI", "Decrease_AGI" } ,
  272. { AL_DEMONBANE, "DEMONBANE", "Demon_Bane" } ,
  273. { AL_DP, "DP", "Divine_Protection" } ,
  274. { AL_HEAL, "HEAL", "Heal" } ,
  275. { AL_HOLYLIGHT, "HOLYLIGHT", "Holy_Light" } ,
  276. { AL_HOLYWATER, "HOLYWATER", "Aqua_Benedicta" } ,
  277. { AL_INCAGI, "INCAGI", "Increase_AGI" } ,
  278. { AL_PNEUMA, "PNEUMA", "Pneuma" } ,
  279. { AL_RUWACH, "RUWACH", "Ruwach" } ,
  280. { AL_TELEPORT, "TELEPORT", "Teleport" } ,
  281. { AL_WARP, "WARP", "Warp_Portal" } ,
  282. { AM_ACIDTERROR, "ACIDTERROR", "Acid_Terror" } ,
  283. { AM_AXEMASTERY, "AXEMASTERY", "Axe_Mastery" } ,
  284. { AM_BERSERKPITCHER, "BERSERKPITCHER", "Berserk Pitcher" } ,
  285. { AM_BIOETHICS, "BIOETHICS", "Bioethics" } ,
  286. { AM_BIOTECHNOLOGY, "BIOTECHNOLOGY", "Biotechnology" } ,
  287. { AM_CALLHOMUN, "CALLHOMUN", "Call_Homunculus" } ,
  288. { AM_CANNIBALIZE, "CANNIBALIZE", "Bio_Cannibalize" } ,
  289. { AM_CP_ARMOR, "ARMOR", "Chemical_Protection_Armor" } ,
  290. { AM_CP_HELM, "HELM", "Chemical_Protection_Helm" } ,
  291. { AM_CP_SHIELD, "SHIELD", "Chemical_Protection_Shield" } ,
  292. { AM_CP_WEAPON, "WEAPON", "Chemical_Protection_Weapon" } ,
  293. { AM_CREATECREATURE, "CREATECREATURE", "Life_Creation" } ,
  294. { AM_CULTIVATION, "CULTIVATION", "Cultivation" } ,
  295. { AM_DEMONSTRATION, "DEMONSTRATION", "Demonstration" } ,
  296. { AM_DRILLMASTER, "DRILLMASTER", "Drillmaster" } ,
  297. { AM_FLAMECONTROL, "FLAMECONTROL", "Flame_Control" } ,
  298. { AM_HEALHOMUN, "HEALHOMUN", "Heal_Homunculus" } ,
  299. { AM_LEARNINGPOTION, "LEARNINGPOTION", "AM_LEARNINGPOTION" } ,
  300. { AM_PHARMACY, "PHARMACY", "Pharmacy" } ,
  301. { AM_POTIONPITCHER, "POTIONPITCHER", "Potion_Pitcher" } ,
  302. { AM_REST, "REST", "Sabbath" } ,
  303. { AM_RESURRECTHOMUN, "RESURRECTHOMUN", "Ressurect_Homunculus" } ,
  304. { AM_SPHEREMINE, "SPHEREMINE", "Sphere_Mine" } ,
  305. { ASC_BREAKER, "BREAKER", "Breaker" } ,
  306. { ASC_CDP, "CDP", "Create_Deadly_Poison" } ,
  307. { ASC_EDP, "EDP", "Deadly_Poison_Enchantment" } ,
  308. { ASC_HALLUCINATION, "HALLUCINATION", "Hallucination_Walk" } ,
  309. { ASC_KATAR, "KATAR", "Advanced_Katar_Mastery" } ,
  310. { ASC_METEORASSAULT, "METEORASSAULT", "Meteor_Assault" } ,
  311. { AS_CLOAKING, "CLOAKING", "Cloaking" } ,
  312. { AS_ENCHANTPOISON, "ENCHANTPOISON", "Enchant_Poison" } ,
  313. { AS_GRIMTOOTH, "GRIMTOOTH", "Grimtooth" } ,
  314. { AS_KATAR, "KATAR", "Katar_Mastery" } ,
  315. { AS_LEFT, "LEFT", "Lefthand_Mastery" } ,
  316. { AS_POISONREACT, "POISONREACT", "Poison_React" } ,
  317. { AS_RIGHT, "RIGHT", "Righthand_Mastery" } ,
  318. { AS_SONICBLOW, "SONICBLOW", "Sonic_Blow" } ,
  319. { AS_SPLASHER, "SPLASHER", "Venom_Splasher" } ,
  320. { AS_VENOMDUST, "VENOMDUST", "Venom_Dust" } ,
  321. { BA_APPLEIDUN, "APPLEIDUN", "Apple_of_Idun" } ,
  322. { BA_ASSASSINCROSS, "ASSASSINCROSS", "Assassin_Cross" } ,
  323. { BA_DISSONANCE, "DISSONANCE", "Dissonance" } ,
  324. { BA_FROSTJOKE, "FROSTJOKE", "Dumb_Joke" } ,
  325. { BA_MUSICALLESSON, "MUSICALLESSON", "Musical_Lesson" } ,
  326. { BA_MUSICALSTRIKE, "MUSICALSTRIKE", "Musical_Strike" } ,
  327. { BA_POEMBRAGI, "POEMBRAGI", "Poem_of_Bragi" } ,
  328. { BA_WHISTLE, "WHISTLE", "Whistle" } ,
  329. { BD_ADAPTATION, "ADAPTATION", "Adaption" } ,
  330. { BD_DRUMBATTLEFIELD, "DRUMBATTLEFIELD", "Drumb_BattleField" } ,
  331. { BD_ENCORE, "ENCORE", "Encore" } ,
  332. { BD_ETERNALCHAOS, "ETERNALCHAOS", "Eternal_Chaos" } ,
  333. { BD_INTOABYSS, "INTOABYSS", "Into_the_Abyss" } ,
  334. { BD_LULLABY, "LULLABY", "Lullaby" } ,
  335. { BD_RAGNAROK, "RAGNAROK", "Ragnarok" } ,
  336. { BD_RICHMANKIM, "RICHMANKIM", "Rich_Mankim" } ,
  337. { BD_RINGNIBELUNGEN, "RINGNIBELUNGEN", "Ring_of_Nibelugen" } ,
  338. { BD_ROKISWEIL, "ROKISWEIL", "Loki's_Wail" } ,
  339. { BD_SIEGFRIED, "SIEGFRIED", "Invulnerable_Siegfried" } ,
  340. { BS_ADRENALINE, "ADRENALINE", "Adrenaline_Rush" } ,
  341. { BS_ADRENALINE2, "ADRENALINE2", "Adrenaline Rush 2" } ,
  342. { BS_AXE, "AXE", "Smith_Axe" } ,
  343. { BS_DAGGER, "DAGGER", "Smith_Dagger" } ,
  344. { BS_ENCHANTEDSTONE, "ENCHANTEDSTONE", "Enchantedstone_Craft" } ,
  345. { BS_FINDINGORE, "FINDINGORE", "Ore_Discovery" } ,
  346. { BS_HAMMERFALL, "HAMMERFALL", "Hammer_Fall" } ,
  347. { BS_HILTBINDING, "HILTBINDING", "Hilt_Binding" } ,
  348. { BS_IRON, "IRON", "Iron_Tempering" } ,
  349. { BS_KNUCKLE, "KNUCKLE", "Smith_Knucklebrace" } ,
  350. { BS_MACE, "MACE", "Smith_Mace" } ,
  351. { BS_MAXIMIZE, "MAXIMIZE", "Power_Maximize" } ,
  352. { BS_ORIDEOCON, "ORIDEOCON", "Orideocon_Research" } ,
  353. { BS_OVERTHRUST, "OVERTHRUST", "Power-Thrust" } ,
  354. { BS_REPAIRWEAPON, "REPAIRWEAPON", "Weapon_Repair" } ,
  355. { BS_SKINTEMPER, "SKINTEMPER", "Skin_Tempering" } ,
  356. { BS_SPEAR, "SPEAR", "Smith_Spear" } ,
  357. { BS_STEEL, "STEEL", "Steel_Tempering" } ,
  358. { BS_SWORD, "SWORD", "Smith_Sword" } ,
  359. { BS_TWOHANDSWORD, "TWOHANDSWORD", "Smith_Two-handed_Sword" } ,
  360. { BS_WEAPONPERFECT, "WEAPONPERFECT", "Weapon_Perfection" } ,
  361. { BS_WEAPONRESEARCH, "WEAPONRESEARCH", "Weaponry_Research" } ,
  362. { CG_ARROWVULCAN, "ARROWVULCAN", "Vulcan_Arrow" } ,
  363. { CG_MARIONETTE, "MARIONETTE", "Marionette_Control" } ,
  364. { CG_MOONLIT, "MOONLIT", "Moonlight_Petals" } ,
  365. { CH_CHAINCRUSH, "CHAINCRUSH", "Chain_Crush_Combo" } ,
  366. { CH_PALMSTRIKE, "PALMSTRIKE", "Palm_Push_Strike" } ,
  367. { CH_SOULCOLLECT, "SOULCOLLECT", "Collect_Soul" } ,
  368. { CH_TIGERFIST, "TIGERFIST", "Tiger_Knuckle_Fist" } ,
  369. { CR_ALCHEMY, "ALCHEMY", "Alchemy" } ,
  370. { CR_SLIMPITCHER, "SLIMPITCHER", "Slim_Pitcher" } ,
  371. { CR_FULLPROTECTION, "FULLPROTECTION", "Full_Chemical_Protection" } ,
  372. { CR_AUTOGUARD, "AUTOGUARD", "Guard" } ,
  373. { CR_DEFENDER, "DEFENDER", "Defender" } ,
  374. { CR_DEVOTION, "DEVOTION", "Sacrifice" } ,
  375. { CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross" } ,
  376. { CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross" } ,
  377. { CR_PROVIDENCE, "PROVIDENCE", "Providence" } ,
  378. { CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect" } ,
  379. { CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang" } ,
  380. { CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge" } ,
  381. { CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken" } ,
  382. { CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis" } ,
  383. { CR_TRUST, "TRUST", "Faith" } ,
  384. { DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson" } ,
  385. { DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me" } ,
  386. { DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss" } ,
  387. { DC_HUMMING, "HUMMING", "Humming" } ,
  388. { DC_SCREAM, "SCREAM", "Scream" } ,
  389. { DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } ,
  390. { DC_THROWARROW, "THROWARROW", "Throw_Arrow" } ,
  391. { DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } ,
  392. { GD_BATTLEORDER, "BATTLEORDER", "Battle_Orders" } ,
  393. { GD_REGENERATION, "REGENERATION", "Regeneration" } ,
  394. { GD_RESTORE, "RESTORE", "Restore" } ,
  395. { GD_EMERGENCYCALL, "EMERGENCYCALL", "Emergency_Call" } ,
  396. { HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } ,
  397. { HP_BASILICA, "BASILICA", "Basilica" } ,
  398. { HP_MEDITATIO, "MEDITATIO", "Meditation" } ,
  399. { HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare" } ,
  400. { HT_BEASTBANE, "BEASTBANE", "Beast_Bane" } ,
  401. { HT_BLASTMINE, "BLASTMINE", "Blast_Mine" } ,
  402. { HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat" } ,
  403. { HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap" } ,
  404. { HT_DETECTING, "DETECTING", "Detect" } ,
  405. { HT_FALCON, "FALCON", "Falconry_Mastery" } ,
  406. { HT_FLASHER, "FLASHER", "Flasher" } ,
  407. { HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap" } ,
  408. { HT_LANDMINE, "LANDMINE", "Land_Mine" } ,
  409. { HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap" } ,
  410. { HT_SANDMAN, "SANDMAN", "Sandman" } ,
  411. { HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap" } ,
  412. { HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap" } ,
  413. { HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap" } ,
  414. { HT_STEELCROW, "STEELCROW", "Steel_Crow" } ,
  415. { HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box" } ,
  416. { HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher" } ,
  417. { HW_MAGICPOWER, "MAGICPOWER", "Magic_Power" } ,
  418. { HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan" } ,
  419. { HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain" } ,
  420. { ITM_TOMAHAWK, "TOMAHAWK", "Throw_Tomahawk" } ,
  421. { KN_AUTOCOUNTER, "AUTOCOUNTER", "Counter_Attack" } ,
  422. { KN_BOWLINGBASH, "BOWLINGBASH", "Bowling_Bash" } ,
  423. { KN_BRANDISHSPEAR, "BRANDISHSPEAR", "Brandish_Spear" } ,
  424. { KN_CAVALIERMASTERY, "CAVALIERMASTERY", "Cavalier_Mastery" } ,
  425. { KN_PIERCE, "PIERCE", "Pierce" } ,
  426. { KN_RIDING, "RIDING", "Peco_Peco_Ride" } ,
  427. { KN_SPEARBOOMERANG, "SPEARBOOMERANG", "Spear_Boomerang" } ,
  428. { KN_SPEARMASTERY, "SPEARMASTERY", "Spear_Mastery" } ,
  429. { KN_SPEARSTAB, "SPEARSTAB", "Spear_Stab" } ,
  430. { KN_TWOHANDQUICKEN, "TWOHANDQUICKEN", "Twohand_Quicken" } ,
  431. { LK_AURABLADE, "AURABLADE", "Aura_Blade" } ,
  432. { LK_BERSERK, "BERSERK", "Berserk" } ,
  433. { LK_CONCENTRATION, "CONCENTRATION", "Concentration" } ,
  434. { LK_FURY, "FURY", "LK_FURY" } ,
  435. { LK_HEADCRUSH, "HEADCRUSH", "Head_Crusher" } ,
  436. { LK_JOINTBEAT, "JOINTBEAT", "Joint_Beat" } ,
  437. { LK_PARRYING, "PARRYING", "Parrying" } ,
  438. { LK_SPIRALPIERCE, "SPIRALPIERCE", "Spiral_Pierce" } ,
  439. { LK_TENSIONRELAX, "TENSIONRELAX", "Tension_Relax" } ,
  440. { MC_CARTREVOLUTION, "CARTREVOLUTION", "Cart_Revolution" } ,
  441. { MC_CHANGECART, "CHANGECART", "Change_Cart" } ,
  442. { MC_DISCOUNT, "DISCOUNT", "Discount" } ,
  443. { MC_IDENTIFY, "IDENTIFY", "Item_Appraisal" } ,
  444. { MC_INCCARRY, "INCCARRY", "Enlarge_Weight_Limit" } ,
  445. { MC_LOUD, "LOUD", "Lord_Exclamation" } ,
  446. { MC_MAMMONITE, "MAMMONITE", "Mammonite" } ,
  447. { MC_OVERCHARGE, "OVERCHARGE", "Overcharge" } ,
  448. { MC_PUSHCART, "PUSHCART", "Pushcart" } ,
  449. { MC_VENDING, "VENDING", "Vending" } ,
  450. { MG_COLDBOLT, "COLDBOLT", "Cold_Bolt" } ,
  451. { MG_ENERGYCOAT, "ENERGYCOAT", "Energy_Coat" } ,
  452. { MG_FIREBALL, "FIREBALL", "Fire_Ball" } ,
  453. { MG_FIREBOLT, "FIREBOLT", "Fire_Bolt" } ,
  454. { MG_FIREWALL, "FIREWALL", "Fire_Wall" } ,
  455. { MG_FROSTDIVER, "FROSTDIVER", "Frost_Diver" } ,
  456. { MG_LIGHTNINGBOLT, "LIGHTNINGBOLT", "Lightening_Bolt" } ,
  457. { MG_NAPALMBEAT, "NAPALMBEAT", "Napalm_Beat" } ,
  458. { MG_SAFETYWALL, "SAFETYWALL", "Safety_Wall" } ,
  459. { MG_SIGHT, "SIGHT", "Sight" } ,
  460. { MG_SOULSTRIKE, "SOULSTRIKE", "Soul_Strike" } ,
  461. { MG_SRECOVERY, "SRECOVERY", "Increase_SP_Recovery" } ,
  462. { MG_STONECURSE, "STONECURSE", "Stone_Curse" } ,
  463. { MG_THUNDERSTORM, "THUNDERSTORM", "Thunderstorm" } ,
  464. { MO_ABSORBSPIRITS, "ABSORBSPIRITS", "Absorb_Spirits" } ,
  465. { MO_BLADESTOP, "BLADESTOP", "Blade_Stop" } ,
  466. { MO_BODYRELOCATION, "BODYRELOCATION", "Body_Relocation" } ,
  467. { MO_CALLSPIRITS, "CALLSPIRITS", "Call_Spirits" } ,
  468. { MO_CHAINCOMBO, "CHAINCOMBO", "Chain_Combo" } ,
  469. { MO_COMBOFINISH, "COMBOFINISH", "Combo_Finish" } ,
  470. { MO_DODGE, "DODGE", "Dodge" } ,
  471. { MO_EXPLOSIONSPIRITS, "EXPLOSIONSPIRITS", "Explosion_Spirits" } ,
  472. { MO_EXTREMITYFIST, "EXTREMITYFIST", "Extremity_Fist" } ,
  473. { MO_FINGEROFFENSIVE, "FINGEROFFENSIVE", "Finger_Offensive" } ,
  474. { MO_INVESTIGATE, "INVESTIGATE", "Investigate" } ,
  475. { MO_IRONHAND, "IRONHAND", "Iron_Hand" } ,
  476. { MO_SPIRITSRECOVERY, "SPIRITSRECOVERY", "Spirit_Recovery" } ,
  477. { MO_STEELBODY, "STEELBODY", "Steel_Body" } ,
  478. { MO_TRIPLEATTACK, "TRIPLEATTACK", "Triple_Blows" } ,
  479. { NPC_ATTRICHANGE, "ATTRICHANGE", "NPC_ATTRICHANGE" } ,
  480. { NPC_BARRIER, "BARRIER", "NPC_BARRIER" } ,
  481. { NPC_BLINDATTACK, "BLINDATTACK", "NPC_BLINDATTACK" } ,
  482. { NPC_BLOODDRAIN, "BLOODDRAIN", "NPC_BLOODDRAIN" } ,
  483. { NPC_CHANGEDARKNESS, "CHANGEDARKNESS", "NPC_CHANGEDARKNESS" } ,
  484. { NPC_CHANGEFIRE, "CHANGEFIRE", "NPC_CHANGEFIRE" } ,
  485. { NPC_CHANGEGROUND, "CHANGEGROUND", "NPC_CHANGEGROUND" } ,
  486. { NPC_CHANGEHOLY, "CHANGEHOLY", "NPC_CHANGEHOLY" } ,
  487. { NPC_CHANGEPOISON, "CHANGEPOISON", "NPC_CHANGEPOISON" } ,
  488. { NPC_CHANGETELEKINESIS, "CHANGETELEKINESIS", "NPC_CHANGETELEKINESIS" } ,
  489. { NPC_CHANGEWATER, "CHANGEWATER", "NPC_CHANGEWATER" } ,
  490. { NPC_CHANGEWIND, "CHANGEWIND", "NPC_CHANGEWIND" } ,
  491. { NPC_COMBOATTACK, "COMBOATTACK", "NPC_COMBOATTACK" } ,
  492. { NPC_CRITICALSLASH, "CRITICALSLASH", "NPC_CRITICALSLASH" } ,
  493. { NPC_CURSEATTACK, "CURSEATTACK", "NPC_CURSEATTACK" } ,
  494. { NPC_DARKBLESSING, "DARKBLESSING", "NPC_DARKBLESSING" } ,
  495. { NPC_DARKBREATH, "DARKBREATH", "NPC_DARKBREATH" } ,
  496. { NPC_DARKCROSS, "DARKCROSS", "NPC_DARKCROSS" } ,
  497. { NPC_DARKNESSATTACK, "DARKNESSATTACK", "NPC_DARKNESSATTACK" } ,
  498. { NPC_DEFENDER, "DEFENDER", "NPC_DEFENDER" } ,
  499. { NPC_EMOTION, "EMOTION", "NPC_EMOTION" } ,
  500. { NPC_ENERGYDRAIN, "ENERGYDRAIN", "NPC_ENERGYDRAIN" } ,
  501. { NPC_FIREATTACK, "FIREATTACK", "NPC_FIREATTACK" } ,
  502. { NPC_GROUNDATTACK, "GROUNDATTACK", "NPC_GROUNDATTACK" } ,
  503. { NPC_GUIDEDATTACK, "GUIDEDATTACK", "NPC_GUIDEDATTACK" } ,
  504. { NPC_HALLUCINATION, "HALLUCINATION", "NPC_HALLUCINATION" } ,
  505. { NPC_HOLYATTACK, "HOLYATTACK", "NPC_HOLYATTACK" } ,
  506. { NPC_KEEPING, "KEEPING", "NPC_KEEPING" } ,
  507. { NPC_LICK, "LICK", "NPC_LICK" } ,
  508. { NPC_MAGICALATTACK, "MAGICALATTACK", "NPC_MAGICALATTACK" } ,
  509. { NPC_MENTALBREAKER, "MENTALBREAKER", "NPC_MENTALBREAKER" } ,
  510. { NPC_METAMORPHOSIS, "METAMORPHOSIS", "NPC_METAMORPHOSIS" } ,
  511. { NPC_PETRIFYATTACK, "PETRIFYATTACK", "NPC_PETRIFYATTACK" } ,
  512. { NPC_PIERCINGATT, "PIERCINGATT", "NPC_PIERCINGATT" } ,
  513. { NPC_POISON, "POISON", "NPC_POISON" } ,
  514. { NPC_POISONATTACK, "POISONATTACK", "NPC_POISONATTACK" } ,
  515. { NPC_PROVOCATION, "PROVOCATION", "NPC_PROVOCATION" } ,
  516. { NPC_RANDOMATTACK, "RANDOMATTACK", "NPC_RANDOMATTACK" } ,
  517. { NPC_RANGEATTACK, "RANGEATTACK", "NPC_RANGEATTACK" } ,
  518. { NPC_REBIRTH, "REBIRTH", "NPC_REBIRTH" } ,
  519. { NPC_SELFDESTRUCTION, "SELFDESTRUCTION", "Kabooooom!" } ,
  520. { NPC_SELFDESTRUCTION2, "SELFDESTRUCTION2", "NPC_SELFDESTRUCTION2" } ,
  521. { NPC_SILENCEATTACK, "SILENCEATTACK", "NPC_SILENCEATTACK" } ,
  522. { NPC_SLEEPATTACK, "SLEEPATTACK", "NPC_SLEEPATTACK" } ,
  523. { NPC_SMOKING, "SMOKING", "NPC_SMOKING" } ,
  524. { NPC_SPLASHATTACK, "SPLASHATTACK", "NPC_SPLASHATTACK" } ,
  525. { NPC_STUNATTACK, "STUNATTACK", "NPC_STUNATTACK" } ,
  526. { NPC_SUICIDE, "SUICIDE", "NPC_SUICIDE" } ,
  527. { NPC_SUMMONMONSTER, "SUMMONMONSTER", "NPC_SUMMONMONSTER" } ,
  528. { NPC_SUMMONSLAVE, "SUMMONSLAVE", "NPC_SUMMONSLAVE" } ,
  529. { NPC_TELEKINESISATTACK, "TELEKINESISATTACK", "NPC_TELEKINESISATTACK" } ,
  530. { NPC_TRANSFORMATION, "TRANSFORMATION", "NPC_TRANSFORMATION" } ,
  531. { NPC_WATERATTACK, "WATERATTACK", "NPC_WATERATTACK" } ,
  532. { NPC_WINDATTACK, "WINDATTACK", "NPC_WINDATTACK" } ,
  533. { NV_BASIC, "BASIC", "Basic_Skill" } ,
  534. { NV_FIRSTAID, "FIRSTAID", "First Aid" } ,
  535. { NV_TRICKDEAD, "TRICKDEAD", "Play_Dead" } ,
  536. { PA_GOSPEL, "GOSPEL", "Gospel" } ,
  537. { PA_PRESSURE, "PRESSURE", "Pressure" } ,
  538. { PA_SACRIFICE, "SACRIFICE", "Sacrificial_Ritual" } ,
  539. { PF_FOGWALL, "FOGWALL", "Wall_of_Fog" } ,
  540. { PF_HPCONVERSION, "HPCONVERSION", "Health_Conversion" } ,
  541. { PF_MEMORIZE, "MEMORIZE", "Memorize" } ,
  542. { PF_MINDBREAKER, "MINDBREAKER", "Mind_Breaker" } ,
  543. { PF_SOULBURN, "SOULBURN", "Soul_Burn" } ,
  544. { PF_SOULCHANGE, "SOULCHANGE", "Soul_Change" } ,
  545. { PF_SPIDERWEB, "SPIDERWEB", "Spider_Web" } ,
  546. { PR_ASPERSIO, "ASPERSIO", "Aspersio" } ,
  547. { PR_BENEDICTIO, "BENEDICTIO", "B.S_Sacramenti" } ,
  548. { PR_GLORIA, "GLORIA", "Gloria" } ,
  549. { PR_IMPOSITIO, "IMPOSITIO", "Impositio_Manus" } ,
  550. { PR_KYRIE, "KYRIE", "Kyrie_Eleison" } ,
  551. { PR_LEXAETERNA, "LEXAETERNA", "Lex_Aeterna" } ,
  552. { PR_LEXDIVINA, "LEXDIVINA", "Lex_Divina" } ,
  553. { PR_MACEMASTERY, "MACEMASTERY", "Mace_Mastery" } ,
  554. { PR_MAGNIFICAT, "MAGNIFICAT", "Magnificat" } ,
  555. { PR_MAGNUS, "MAGNUS", "Magnus_Exorcismus" } ,
  556. { PR_SANCTUARY, "SANCTUARY", "Santuary" } ,
  557. { PR_SLOWPOISON, "SLOWPOISON", "Slow_Poison" } ,
  558. { PR_STRECOVERY, "STRECOVERY", "Status_Recovery" } ,
  559. { PR_SUFFRAGIUM, "SUFFRAGIUM", "Suffragium" } ,
  560. { PR_TURNUNDEAD, "TURNUNDEAD", "Turn_Undead" } ,
  561. { RG_BACKSTAP, "BACKSTAP", "Back_Stab" } ,
  562. { RG_CLEANER, "CLEANER", "Remover" } ,
  563. { RG_COMPULSION, "COMPULSION", "Compulsion_Discount" } ,
  564. { RG_FLAGGRAFFITI, "FLAGGRAFFITI", "Flag_Graffity" } ,
  565. { RG_GANGSTER, "GANGSTER", "Gangster's_Paradise" } ,
  566. { RG_GRAFFITI, "GRAFFITI", "Graffiti" } ,
  567. { RG_INTIMIDATE, "INTIMIDATE", "Intimidate" } ,
  568. { RG_PLAGIARISM, "PLAGIARISM", "Plagiarism" } ,
  569. { RG_RAID, "RAID", "Raid" } ,
  570. { RG_SNATCHER, "SNATCHER", "Snatcher" } ,
  571. { RG_STEALCOIN, "STEALCOIN", "Steal_Coin" } ,
  572. { RG_STRIPARMOR, "STRIPARMOR", "Strip_Armor" } ,
  573. { RG_STRIPHELM, "STRIPHELM", "Strip_Helm" } ,
  574. { RG_STRIPSHIELD, "STRIPSHIELD", "Strip_Shield" } ,
  575. { RG_STRIPWEAPON, "STRIPWEAPON", "Strip_Weapon" } ,
  576. { RG_TUNNELDRIVE, "TUNNELDRIVE", "Tunnel_Drive" } ,
  577. { SA_ABRACADABRA, "ABRACADABRA", "Hocus-pocus" } ,
  578. { SA_ADVANCEDBOOK, "ADVANCEDBOOK", "Advanced_Book" } ,
  579. { SA_AUTOSPELL, "AUTOSPELL", "Auto_Cast" } ,
  580. { SA_CASTCANCEL, "CASTCANCEL", "Cast_Cancel" } ,
  581. { SA_CLASSCHANGE, "CLASSCHANGE", "Class_Change" } ,
  582. { SA_COMA, "COMA", "Coma" } ,
  583. { SA_DEATH, "DEATH", "Death" } ,
  584. { SA_DELUGE, "DELUGE", "Deluge" } ,
  585. { SA_DISPELL, "DISPELL", "Dispel" } ,
  586. { SA_DRAGONOLOGY, "DRAGONOLOGY", "Dragonology" } ,
  587. { SA_FLAMELAUNCHER, "FLAMELAUNCHER", "Flame_Launcher" } ,
  588. { SA_FORTUNE, "FORTUNE", "Fortune" } ,
  589. { SA_FREECAST, "FREECAST", "Cast_Freedom" } ,
  590. { SA_FROSTWEAPON, "FROSTWEAPON", "Frost_Weapon" } ,
  591. { SA_FULLRECOVERY, "FULLRECOVERY", "Full_Recovery" } ,
  592. { SA_GRAVITY, "GRAVITY", "Gravity" } ,
  593. { SA_INSTANTDEATH, "INSTANTDEATH", "Instant_Death" } ,
  594. { SA_LANDPROTECTOR, "LANDPROTECTOR", "Land_Protector" } ,
  595. { SA_LEVELUP, "LEVELUP", "Level_Up" } ,
  596. { SA_LIGHTNINGLOADER, "LIGHTNINGLOADER", "Lightning_Loader" } ,
  597. { SA_MAGICROD, "MAGICROD", "Magic_Rod" } ,
  598. { SA_MONOCELL, "MONOCELL", "Monocell" } ,
  599. { SA_QUESTION, "QUESTION", "Question?" } ,
  600. { SA_REVERSEORCISH, "REVERSEORCISH", "Reverse_Orcish" } ,
  601. { SA_SEISMICWEAPON, "SEISMICWEAPON", "Seismic_Weapon" } ,
  602. { SA_SPELLBREAKER, "SPELLBREAKER", "Break_Spell" } ,
  603. { SA_SUMMONMONSTER, "SUMMONMONSTER", "Summon_Monster" } ,
  604. { SA_TAMINGMONSTER, "TAMINGMONSTER", "Taming_Monster" } ,
  605. { SA_VIOLENTGALE, "VIOLENTGALE", "Violent_Gale" } ,
  606. { SA_VOLCANO, "VOLCANO", "Volcano" } ,
  607. { SG_DEVIL, "DEVIL", "Devil" } ,
  608. { SG_FEEL, "FEEL", "Feel" } ,
  609. { SG_FRIEND, "FRIEND", "Friend" } ,
  610. { SG_FUSION, "FUSION", "Fusion" } ,
  611. { SG_HATE, "HATE", "Hate" } ,
  612. { SG_KNOWLEDGE, "KNOWLEDGE", "Knowledge" } ,
  613. { SG_MOON_ANGER, "ANGER", "Moon Anger" } ,
  614. { SG_MOON_BLESS, "BLESS", "Moon Bless" } ,
  615. { SG_MOON_COMFORT, "COMFORT", "Moon Comfort" } ,
  616. { SG_MOON_WARM, "WARM", "Moon Warm" } ,
  617. { SG_STAR_ANGER, "ANGER", "Star Anger" } ,
  618. { SG_STAR_BLESS, "BLESS", "Star Bless" } ,
  619. { SG_STAR_COMFORT, "COMFORT", "Star Comfort" } ,
  620. { SG_STAR_WARM, "WARM", "Star Warm" } ,
  621. { SG_SUN_ANGER, "ANGER", "Sun Anger" } ,
  622. { SG_SUN_BLESS, "BLESS", "Sun Bless" } ,
  623. { SG_SUN_COMFORT, "COMFORT", "Sun Comfort" } ,
  624. { SG_SUN_WARM, "WARM", "Sun Warm" } ,
  625. { SL_ALCHEMIST, "ALCHEMIST", "Alchemist" } ,
  626. { SL_ASSASIN, "ASSASIN", "Assasin" } ,
  627. { SL_BARDDANCER, "BARDDANCER", "Bard Dancer" } ,
  628. { SL_BLACKSMITH, "BLACKSMITH", "Black Smith" } ,
  629. { SL_CRUSADER, "CRUSADER", "Crusader" } ,
  630. { SL_HUNTER, "HUNTER", "Hunter" } ,
  631. { SL_KAAHI, "KAAHI", "Kaahi" } ,
  632. { SL_KAINA, "KAINA", "Kaina" } ,
  633. { SL_KAITE, "KAITE", "Kaite" } ,
  634. { SL_KAIZEL, "KAIZEL", "Kaizel" } ,
  635. { SL_KAUPE, "KAUPE", "Kaupe" } ,
  636. { SL_KNIGHT, "KNIGHT", "Knight" } ,
  637. { SL_MONK, "MONK", "Monk" } ,
  638. { SL_PRIEST, "PRIEST", "Priest" } ,
  639. { SL_ROGUE, "ROGUE", "Rogue" } ,
  640. { SL_SAGE, "SAGE", "Sage" } ,
  641. { SL_SKA, "SKA", "SKA" } ,
  642. { SL_SKE, "SKE", "SKE" } ,
  643. { SL_SMA, "SMA", "SMA" } ,
  644. { SL_SOULLINKER, "SOULLINKER", "Soul Linker" } ,
  645. { SL_STAR, "STAR", "Star" } ,
  646. { SL_STIN, "STIN", "Stin" } ,
  647. { SL_STUN, "STUN", "Stun" } ,
  648. { SL_SUPERNOVICE, "SUPERNOVICE", "Super Novice" } ,
  649. { SL_SWOO, "SWOO", "Swoo" } ,
  650. { SL_WIZARD, "WIZARD", "Wizard" } ,
  651. { SM_AUTOBERSERK, "AUTOBERSERK", "Auto_Berserk" } ,
  652. { SM_BASH, "BASH", "Bash" } ,
  653. { SM_ENDURE, "ENDURE", "Endure" } ,
  654. { SM_FATALBLOW, "FATALBLOW", "Attack_Weak_Point" } ,
  655. { SM_MAGNUM, "MAGNUM", "Magnum_Break" } ,
  656. { SM_MOVINGRECOVERY, "MOVINGRECOVERY", "Moving_HP_Recovery" } ,
  657. { SM_PROVOKE, "PROVOKE", "Provoke" } ,
  658. { SM_RECOVERY, "RECOVERY", "Increase_HP_Recovery" } ,
  659. { SM_SWORD, "SWORD", "Sword_Mastery" } ,
  660. { SM_TWOHAND, "TWOHAND", "Two-Handed_Sword_Mastery" } ,
  661. { SN_FALCONASSAULT, "FALCONASSAULT", "Falcon_Assault" } ,
  662. { SN_SHARPSHOOTING, "SHARPSHOOTING", "Sharpshooting" } ,
  663. { SN_SIGHT, "SIGHT", "True_Sight" } ,
  664. { SN_WINDWALK, "WINDWALK", "Wind_Walk" } ,
  665. { ST_CHASEWALK, "CHASEWALK", "Chase_Walk" } ,
  666. { ST_REJECTSWORD, "REJECTSWORD", "Reject_Sword" } ,
  667. { ST_STEALBACKPACK, "STEALBACKPACK", "Steal_Backpack" } ,
  668. { ST_PRESERVE, "PRESERVE", "Preserve" } ,
  669. { ST_FULLSTRIP, "FULLSTRIP", "Full_Strip" } ,
  670. { TF_BACKSLIDING, "BACKSLIDING", "Back_Sliding" } ,
  671. { TF_DETOXIFY, "DETOXIFY", "Detoxify" } ,
  672. { TF_DOUBLE, "DOUBLE", "Double_Attack" } ,
  673. { TF_HIDING, "HIDING", "Hiding" } ,
  674. { TF_MISS, "MISS", "Improve_Dodge" } ,
  675. { TF_PICKSTONE, "PICKSTONE", "Take_Stone" } ,
  676. { TF_POISON, "POISON", "Envenom" } ,
  677. { TF_SPRINKLESAND, "SPRINKLESAND", "Throw_Sand" } ,
  678. { TF_STEAL, "STEAL", "Steal" } ,
  679. { TF_THROWSTONE, "THROWSTONE", "Throw_Stone" } ,
  680. { TK_COUNTER, "COUNTER", "Counter" } ,
  681. { TK_DODGE, "DODGE", "Dodge" } ,
  682. { TK_DOWNKICK, "DOWNKICK", "Down Kick" } ,
  683. { TK_HIGHJUMP, "HIGHJUMP", "High Jump" } ,
  684. { TK_HPTIME, "HPTIME", "HP Time" } ,
  685. { TK_JUMPKICK, "JUMPKICK", "Jump Kick" } ,
  686. { TK_POWER, "POWER", "Power" } ,
  687. { TK_READYCOUNTER, "READYCOUNTER", "Ready Counter" } ,
  688. { TK_READYDOWN, "READYDOWN", "Ready Down" } ,
  689. { TK_READYSTORM, "READYSTORM", "Ready Storm" } ,
  690. { TK_READYTURN, "READYTURN", "Ready Turn" } ,
  691. { TK_RUN, "RUN", "TK_RUN" } ,
  692. { TK_SEVENWIND, "SEVENWIND", "Seven Wind" } ,
  693. { TK_SPTIME, "SPTIME", "SP Time" } ,
  694. { TK_STORMKICK, "STORMKICK", "Storm Kick" } ,
  695. { TK_TURNKICK, "TURNKICK", "Turn Kick" } ,
  696. { WE_BABY, "BABY", "Adopt_Baby" } ,
  697. { WE_CALLBABY, "CALLBABY", "Call_Baby" } ,
  698. { WE_CALLPARENT, "CALLPARENT", "Call_Parent" } ,
  699. { WE_CALLPARTNER, "CALLPARTNER", "I Want to See You" } ,
  700. { WE_FEMALE, "FEMALE", "I Only Look Up to You" } ,
  701. { WE_MALE, "MALE", "I Will Protect You" } ,
  702. { WS_CARTBOOST, "CARTBOOST", "Cart_Boost" } ,
  703. { WS_CREATECOIN, "CREATECOIN", "Create_Coins" } ,
  704. { WS_CREATENUGGET, "CREATENUGGET", "Create_Nuggets" } ,
  705. { WS_MELTDOWN, "MELTDOWN", "Meltdown" } ,
  706. { WS_SYSTEMCREATE, "SYSTEMCREATE", "Create_System_tower" } ,
  707. { WS_WEAPONREFINE, "WEAPONREFINE", "Weapon_Refine" } ,
  708. { WZ_EARTHSPIKE, "EARTHSPIKE", "Earth_Spike" } ,
  709. { WZ_ESTIMATION, "ESTIMATION", "Sense" } ,
  710. { WZ_FIREIVY, "FIREIVY", "Fire_Ivy" } ,
  711. { WZ_FIREPILLAR, "FIREPILLAR", "Fire_Pillar" } ,
  712. { WZ_FROSTNOVA, "FROSTNOVA", "Frost_Nova" } ,
  713. { WZ_HEAVENDRIVE, "HEAVENDRIVE", "Heaven's_Drive" } ,
  714. { WZ_ICEWALL, "ICEWALL", "Ice_Wall" } ,
  715. { WZ_JUPITEL, "JUPITEL", "Jupitel_Thunder" } ,
  716. { WZ_METEOR, "METEOR", "Meteor_Storm" } ,
  717. { WZ_QUAGMIRE, "QUAGMIRE", "Quagmire" } ,
  718. { WZ_SIGHTRASHER, "SIGHTRASHER", "Sightrasher" } ,
  719. { WZ_STORMGUST, "STORMGUST", "Storm_Gust" } ,
  720. { WZ_VERMILION, "VERMILION", "Lord_of_Vermilion" } ,
  721. { WZ_WATERBALL, "WATERBALL", "Water_Ball" } ,
  722. { 0, 0, 0 }
  723. };
  724. static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
  725. static const int diry[8]={1,1,0,-1,-1,-1,0,1};
  726. static int rdamage;
  727. /* スキルデ?タベ?ス */
  728. struct skill_db skill_db[MAX_SKILL_DB];
  729. /* アイテム作成デ?タベ?ス */
  730. struct skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
  731. /* 矢作成スキルデ?タベ?ス */
  732. struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
  733. /* アブラカダブラ?動スキルデ?タベ?ス */
  734. struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
  735. int skill_get_hit( int id ){
  736. if (id >= 10000 && id < 10015) id -= 9500;
  737. return skill_db[id].hit;
  738. }
  739. int skill_get_inf( int id ){
  740. return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id);
  741. }
  742. int skill_get_pl( int id ){
  743. if (id >= 10000 && id < 10015) id-= 9500;
  744. return skill_db[id].pl;
  745. }
  746. int skill_get_nk( int id ){
  747. if (id >= 10000 && id < 10015) id-= 9500;
  748. return skill_db[id].nk;
  749. }
  750. int skill_get_max( int id ){
  751. return (id < 500) ? skill_db[id].max : guild_skill_get_max(id);
  752. }
  753. int skill_get_range( int id , int lv ){
  754. if (lv <= 0) return 0;
  755. return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id);
  756. }
  757. int skill_get_hp( int id ,int lv ){
  758. if (id >= 10000 && id < 10015) id-= 9500;
  759. return (lv <= 0) ? 0: skill_db[id].hp[lv-1];
  760. }
  761. int skill_get_sp( int id ,int lv ){
  762. if (id >= 10000 && id < 10015) id-= 9500;
  763. //if (lv <= 0) return 0;
  764. //return (id < 500) ? skill_db[id].sp[lv-1] : guild_skill_get_sp(id, lv);
  765. return (lv <= 0) ? 0: skill_db[id].sp[lv-1];
  766. }
  767. int skill_get_zeny( int id ,int lv ){
  768. if (id >= 10000 && id < 10015) id-= 9500;
  769. return (lv <= 0) ? 0:skill_db[id].zeny[lv-1];
  770. }
  771. int skill_get_num( int id ,int lv ){
  772. if (id >= 10000 && id < 10015) id-= 9500;
  773. return (lv <= 0) ? 0:skill_db[id].num[lv-1];
  774. }
  775. int skill_get_cast( int id ,int lv ){
  776. if (id >= 10000 && id < 10015) id-= 9500;
  777. return (lv <= 0) ? 0:skill_db[id].cast[lv-1];
  778. }
  779. int skill_get_delay( int id ,int lv ){
  780. if (id >= 10000 && id < 10015) id-= 9500;
  781. return (lv <= 0) ? 0:skill_db[id].delay[lv-1];
  782. }
  783. int skill_get_time( int id ,int lv ){
  784. if (id >= 10000 && id < 10015) id-= 9500;
  785. return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1];
  786. }
  787. int skill_get_time2( int id ,int lv ){
  788. if (id >= 10000 && id < 10015) id-= 9500;
  789. return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1];
  790. }
  791. int skill_get_castdef( int id ){
  792. if (id >= 10000 && id < 10015) id-= 9500;
  793. return skill_db[id].cast_def_rate;
  794. }
  795. int skill_get_weapontype( int id ){
  796. if (id >= 10000 && id < 10015) id-= 9500;
  797. return skill_db[id].weapon;
  798. }
  799. int skill_get_inf2( int id ){
  800. if (id >= 10000 && id < 10015) id-= 9500;
  801. return skill_db[id].inf2;
  802. }
  803. int skill_get_castcancel( int id ){
  804. if (id >= 10000 && id < 10015) id-= 9500;
  805. return skill_db[id].castcancel;
  806. }
  807. int skill_get_maxcount( int id ){
  808. if (id >= 10000 && id < 10015) id-= 9500;
  809. return skill_db[id].maxcount;
  810. }
  811. int skill_get_blewcount( int id ,int lv ){
  812. if (id >= 10000 && id < 10015) id-= 9500;
  813. return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1];
  814. }
  815. int skill_get_mhp( int id ,int lv ){
  816. if (id >= 10000 && id < 10015) id-= 9500;
  817. return (lv <= 0) ? 0:skill_db[id].mhp[lv-1];
  818. }
  819. int skill_get_castnodex( int id ,int lv ){
  820. if (id >= 10000 && id < 10015) id-= 9500;
  821. return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1];
  822. }
  823. int skill_get_nocast ( int id ){
  824. if (id >= 10000 && id < 10015) id-= 9500;
  825. return skill_db[id].nocast;
  826. }
  827. int skill_tree_get_max(int id, int b_class){
  828. struct pc_base_job s_class = pc_calc_base_job(b_class);
  829. int i, skillid;
  830. for(i=0;(skillid=skill_tree[s_class.upper][s_class.job][i].id)>0;i++)
  831. if (id == skillid) return skill_tree[s_class.upper][s_class.job][i].max;
  832. return skill_get_max (id);
  833. }
  834. /* プロトタイプ */
  835. //struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag);
  836. int skill_check_condition( struct map_session_data *sd,int type);
  837. int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag );
  838. int skill_frostjoke_scream(struct block_list *bl,va_list ap);
  839. int skill_status_change_timer_sub(struct block_list *bl, va_list ap );
  840. int skill_attack_area(struct block_list *bl,va_list ap);
  841. int skill_abra_dataset(int skilllv);
  842. int skill_clear_element_field(struct block_list *bl);
  843. int skill_landprotector(struct block_list *bl, va_list ap );
  844. int skill_trap_splash(struct block_list *bl, va_list ap );
  845. int skill_count_target(struct block_list *bl, va_list ap );
  846. // [MouseJstr] - skill ok to cast? and when?
  847. int skillnotok(int skillid, struct map_session_data *sd) {
  848. if (sd == 0)
  849. return 0;
  850. if (pc_isGM(sd) >= 20)
  851. return 0; // gm's can do anything damn thing they want
  852. // Check skill restrictions [Celest]
  853. if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 1)
  854. return 1;
  855. if(map[sd->bl.m].flag.pvp && skill_get_nocast (skillid) & 2)
  856. return 1;
  857. if(map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 4)
  858. return 1;
  859. if (agit_flag && skill_get_nocast (skillid) & 8)
  860. return 1;
  861. if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_get_nocast (skillid) & 16)
  862. return 1;
  863. switch (skillid) {
  864. case AL_WARP:
  865. case AL_TELEPORT:
  866. case MC_VENDING:
  867. case MC_IDENTIFY:
  868. return 0; // always allowed
  869. default:
  870. return(map[sd->bl.m].flag.noskill);
  871. }
  872. }
  873. static int distance(int x0,int y0,int x1,int y1)
  874. {
  875. int dx,dy;
  876. dx=abs(x0-x1);
  877. dy=abs(y0-y1);
  878. return dx>dy ? dx : dy;
  879. }
  880. /* スキルユニットIDを返す(これもデ?タベ?スに入れたいな) */
  881. int skill_get_unit_id(int id,int flag)
  882. {
  883. switch(id){
  884. case MG_SAFETYWALL: return 0x7e; /* セイフティウォ?ル */
  885. case MG_FIREWALL: return 0x7f; /* ファイア?ウォ?ル */
  886. case AL_WARP: return (flag==0)?0x81:0x80; /* ワ?プポ?タル */
  887. case PR_BENEDICTIO: return 0x82; /* 聖?降福 */
  888. case PR_SANCTUARY: return 0x83; /* サンクチュアリ */
  889. case PR_MAGNUS: return 0x84; /* マグヌスエクソシズム */
  890. case AL_PNEUMA: return 0x85; /* ニュ?マ */
  891. case MG_THUNDERSTORM: return 0x86; /* サンダ?スト?ム */
  892. case WZ_HEAVENDRIVE: return 0x86; /* ヘヴンズドライブ */
  893. case WZ_SIGHTRASHER: return 0x86; /* サイトラッシャ? */
  894. case WZ_METEOR: return 0x86; /* メテオスト?ム */
  895. case WZ_VERMILION: return 0x86; /* ロ?ドオブヴァ?ミリオン */
  896. case WZ_FROSTNOVA: return 0x86; /* フロストノヴァ */
  897. case WZ_STORMGUST: return 0x86; /* スト?ムガスト(とりあえずLoVと同じで?理) */
  898. case CR_GRANDCROSS: return 0x86; /* グランドクロス */
  899. case NPC_DARKGRANDCROSS: return 0x86; /*闇グランドクロス*/
  900. case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ファイア?ピラ? */
  901. case HT_TALKIEBOX: return 0x99; /* ト?キ?ボックス */
  902. case WZ_ICEWALL: return 0x8d; /* アイスウォ?ル */
  903. case WZ_QUAGMIRE: return 0x8e; /* クァグマイア */
  904. case HT_BLASTMINE: return 0x8f; /* ブラストマイン */
  905. case HT_SKIDTRAP: return 0x90; /* スキッドトラップ */
  906. case HT_ANKLESNARE: return 0x91; /* アンクルスネア */
  907. case AS_VENOMDUST: return 0x92; /* ベノムダスト */
  908. case HT_LANDMINE: return 0x93; /* ランドマイン */
  909. case HT_SHOCKWAVE: return 0x94; /* ショックウェ?ブトラップ */
  910. case HT_SANDMAN: return 0x95; /* サンドマン */
  911. case HT_FLASHER: return 0x96; /* フラッシャ? */
  912. case HT_FREEZINGTRAP: return 0x97; /* フリ?ジングトラップ */
  913. case HT_CLAYMORETRAP: return 0x98; /* クレイモア?トラップ */
  914. case SA_VOLCANO: return 0x9a; /* ボルケ?ノ */
  915. case SA_DELUGE: return 0x9b; /* デリュ?ジ */
  916. case SA_VIOLENTGALE: return 0x9c; /* バイオレントゲイル */
  917. case SA_LANDPROTECTOR: return 0x9d; /* ランドプロテクタ? */
  918. case BD_LULLABY: return 0x9e; /* 子守歌 */
  919. case BD_RICHMANKIM: return 0x9f; /* ニヨルドの宴 */
  920. case BD_ETERNALCHAOS: return 0xa0; /* 永遠の混沌 */
  921. case BD_DRUMBATTLEFIELD:return 0xa1; /* ?太鼓の響き */
  922. case BD_RINGNIBELUNGEN: return 0xa2; /* ニ?ベルングの指輪 */
  923. case BD_ROKISWEIL: return 0xa3; /* ロキの叫び */
  924. case BD_INTOABYSS: return 0xa4; /* 深淵の中に */
  925. case BD_SIEGFRIED: return 0xa5; /* 不死身のジ?クフリ?ド */
  926. case BA_DISSONANCE: return 0xa6; /* 不協和音 */
  927. case BA_WHISTLE: return 0xa7; /* 口笛 */
  928. case BA_ASSASSINCROSS: return 0xa8; /* 夕陽のアサシンクロス */
  929. case BA_POEMBRAGI: return 0xa9; /* ブラギの詩 */
  930. case BA_APPLEIDUN: return 0xaa; /* イドゥンの林檎 */
  931. case DC_UGLYDANCE: return 0xab; /* 自分勝手なダンス */
  932. case DC_HUMMING: return 0xac; /* ハミング */
  933. case DC_DONTFORGETME: return 0xad; /* 私を忘れないで… */
  934. case DC_FORTUNEKISS: return 0xae; /* 幸運のキス */
  935. case DC_SERVICEFORYOU: return 0xaf; /* サ?ビスフォ?ユ? */
  936. case RG_GRAFFITI: return 0xb0; /* グラフィティ */
  937. case AM_DEMONSTRATION: return 0xb1; /* デモンストレ?ション */
  938. case WE_CALLPARTNER: return 0xb2; /* あなたに逢いたい */
  939. case PA_GOSPEL: return 0xb3; /* ゴスペル */
  940. case HP_BASILICA: return 0xb4; /* バジリカ */
  941. case CG_MOONLIT: return 0xb5;
  942. case PF_FOGWALL: return 0xb6; /* フォグウォ?ル */
  943. case PF_SPIDERWEB: return 0xb7; /* スパイダ?ウェッブ */
  944. // temporary unit ID's [Celest]
  945. case GD_LEADERSHIP: return 0xc1;
  946. case GD_GLORYWOUNDS: return 0xc2;
  947. case GD_SOULCOLD: return 0xc3;
  948. case GD_HAWKEYES: return 0xc4;
  949. }
  950. return 0;
  951. /*
  952. 0x89,0x8a,0x8b 表示無し
  953. 0x9a 炎?性の詠唱みたいなエフェクト
  954. 0x9b 水?性の詠唱みたいなエフェクト
  955. 0x9c 風?性の詠唱みたいなエフェクト
  956. 0x9d 白い小さなエフェクト
  957. 0xb1 Alchemist Demonstration
  958. 0xb2 = Pink Warp Portal
  959. 0xb3 = Gospel For Paladin
  960. 0xb4 = Basilica
  961. 0xb5 = Empty
  962. 0xb6 = Fog Wall for Professor
  963. 0xb7 = Spider Web for Professor
  964. 0xb8 = Empty
  965. 0xb9 =
  966. */
  967. }
  968. /*==========================================
  969. * スキル追加?果
  970. *------------------------------------------
  971. */
  972. int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick)
  973. {
  974. /* MOB追加?果スキル用 */
  975. const int sc[]={
  976. SC_POISON, SC_BLIND, SC_SILENCE, SC_STAN,
  977. SC_STONE, SC_CURSE, SC_SLEEP
  978. };
  979. const int sc2[]={
  980. MG_STONECURSE,MG_FROSTDIVER,NPC_STUNATTACK,
  981. NPC_SLEEPATTACK,TF_POISON,NPC_CURSEATTACK,
  982. NPC_SILENCEATTACK,0,NPC_BLINDATTACK
  983. };
  984. struct map_session_data *sd=NULL;
  985. struct map_session_data *dstsd=NULL;
  986. struct mob_data *md=NULL;
  987. struct mob_data *dstmd=NULL;
  988. struct pet_data *pd=NULL;
  989. int skill,skill2;
  990. int rate,luk;
  991. int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk;
  992. int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2;
  993. nullpo_retr(0, src);
  994. nullpo_retr(0, bl);
  995. //if(skilllv <= 0) return 0;
  996. if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest
  997. if(src->type==BL_PC){
  998. nullpo_retr(0, sd=(struct map_session_data *)src);
  999. }else if(src->type==BL_MOB){
  1000. nullpo_retr(0, md=(struct mob_data *)src); //未使用?
  1001. }else if(src->type==BL_PET){
  1002. nullpo_retr(0, pd=(struct pet_data *)src); // [Valaris]
  1003. }
  1004. //?象の耐性
  1005. luk = battle_get_luk(bl);
  1006. sc_def_mdef=100 - (3 + battle_get_mdef(bl) + luk/3);
  1007. sc_def_vit=100 - (3 + battle_get_vit(bl) + luk/3);
  1008. sc_def_int=100 - (3 + battle_get_int(bl) + luk/3);
  1009. sc_def_luk=100 - (3 + luk);
  1010. //自分の耐性
  1011. luk = battle_get_luk(src);
  1012. sc_def_mdef2=100 - (3 + battle_get_mdef(src) + luk/3);
  1013. sc_def_vit2=100 - (3 + battle_get_vit(src) + luk/3);
  1014. sc_def_int2=100 - (3 + battle_get_int(src) + luk/3);
  1015. sc_def_luk2=100 - (3 + luk);
  1016. if(bl->type==BL_PC)
  1017. dstsd=(struct map_session_data *)bl;
  1018. else if(bl->type==BL_MOB){
  1019. dstmd=(struct mob_data *)bl; //未使用?
  1020. if(sc_def_mdef<50)
  1021. sc_def_mdef=50;
  1022. if(sc_def_vit<50)
  1023. sc_def_vit=50;
  1024. if(sc_def_int<50)
  1025. sc_def_int=50;
  1026. if(sc_def_luk<50)
  1027. sc_def_luk=50;
  1028. }
  1029. if(sc_def_mdef<0)
  1030. sc_def_mdef=0;
  1031. if(sc_def_vit<0)
  1032. sc_def_vit=0;
  1033. if(sc_def_int<0)
  1034. sc_def_int=0;
  1035. switch(skillid){
  1036. case 0: /* 通常攻? */
  1037. /* 自動鷹 */
  1038. if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
  1039. rand()%1000 <= sd->paramc[5]*10/3+1 ) {
  1040. int lv=(sd->status.job_level+9)/10;
  1041. skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
  1042. }
  1043. // スナッチャ?
  1044. if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0)
  1045. if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
  1046. if(pc_steal_item(sd,bl))
  1047. clif_skill_nodamage(src,bl,TF_STEAL,skill2,1);
  1048. else if (battle_config.display_snatcher_skill_fail)
  1049. clif_skill_fail(sd,skillid,0,0);
  1050. }
  1051. // エンチャントデットリ?ポイズン(猛毒?果)
  1052. if (sd && sd->sc_data[SC_EDP].timer != -1 && rand() % 10000 < sd->sc_data[SC_EDP].val2 * sc_def_vit) {
  1053. int mhp = battle_get_max_hp(bl);
  1054. int hp = battle_get_hp(bl);
  1055. int lvl = sd->sc_data[SC_EDP].val1;
  1056. int diff;
  1057. // MHPの1/4以下にはならない
  1058. if(hp > mhp>>2) {
  1059. if(bl->type == BL_PC) {
  1060. diff = mhp*10/100;
  1061. if (hp - diff < mhp>>2)
  1062. diff = hp - (mhp>>2);
  1063. pc_heal((struct map_session_data *)bl, -hp, 0);
  1064. } else if(bl->type == BL_MOB) {
  1065. struct mob_data *md = (struct mob_data *)bl;
  1066. hp -= mhp*15/100;
  1067. if (hp > mhp>>2)
  1068. md->hp = hp;
  1069. else
  1070. md->hp = mhp>>2;
  1071. }
  1072. }
  1073. skill_status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0);
  1074. }
  1075. break;
  1076. case SM_BASH: /* バッシュ(急所攻?) */
  1077. if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){
  1078. if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 )
  1079. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0);
  1080. }
  1081. break;
  1082. case TF_POISON: /* インベナム */
  1083. case AS_SPLASHER: /* ベナムスプラッシャ? */
  1084. if(rand()%100< (2*skilllv+10)*sc_def_vit/100 )
  1085. skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1086. else{
  1087. if(sd && skillid==TF_POISON)
  1088. clif_skill_fail(sd,skillid,0,0);
  1089. }
  1090. break;
  1091. case AS_SONICBLOW: /* ソニックブロ? */
  1092. if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
  1093. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1094. break;
  1095. case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
  1096. rate=skilllv*3+35;
  1097. if(rand()%100 < rate*sc_def_mdef/100)
  1098. skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1099. break;
  1100. case MG_FROSTDIVER: /* フロストダイバ? */
  1101. case WZ_FROSTNOVA: /* フロストノヴァ */
  1102. rate=(skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15;
  1103. rate=rate<=5?5:rate;
  1104. if(rand()%100 < rate)
  1105. skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1106. else if(sd && skillid==MG_FROSTDIVER)
  1107. clif_skill_fail(sd,skillid,0,0);
  1108. break;
  1109. case WZ_STORMGUST: /* スト?ムガスト */
  1110. {
  1111. struct status_change *sc_data = battle_get_sc_data(bl);
  1112. if(sc_data) {
  1113. sc_data[SC_FREEZE].val3++;
  1114. if(sc_data[SC_FREEZE].val3 >= 3)
  1115. skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1116. }
  1117. }
  1118. break;
  1119. case HT_LANDMINE: /* ランドマイン */
  1120. if( rand()%100 < (5*skilllv+30)*sc_def_vit/100 )
  1121. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1122. break;
  1123. case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */
  1124. if(map[bl->m].flag.pvp && dstsd){
  1125. dstsd->status.sp -= dstsd->status.sp*(5+15*skilllv)/100;
  1126. pc_calcstatus(dstsd,0);
  1127. }
  1128. break;
  1129. case HT_SANDMAN: /* サンドマン */
  1130. if( rand()%100 < (5*skilllv+30)*sc_def_int/100 )
  1131. skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1132. break;
  1133. case TF_SPRINKLESAND: /* 砂まき */
  1134. if( rand()%100 < 20*sc_def_int/100 )
  1135. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1136. break;
  1137. case TF_THROWSTONE: /* 石投げ */
  1138. if( rand()%100 < 7*sc_def_vit/100 )
  1139. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1140. break;
  1141. case CR_HOLYCROSS: /* ホ?リ?クロス */
  1142. if( rand()%100 < 3*skilllv*sc_def_int/100 )
  1143. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1144. break;
  1145. case CR_GRANDCROSS: /* グランドクロス */
  1146. case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
  1147. {
  1148. int race = battle_get_race(bl);
  1149. if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?制付?だが完全耐性には無?
  1150. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1151. }
  1152. break;
  1153. case AM_ACIDTERROR:
  1154. if( rand()%100 < (skilllv*3)*sc_def_vit/100 )
  1155. skill_status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1156. break;
  1157. case CR_SHIELDCHARGE: /* シ?ルドチャ?ジ */
  1158. if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
  1159. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1160. break;
  1161. case RG_RAID: /* サプライズアタック */
  1162. if( rand()%100 < (10+3*skilllv)*sc_def_vit/100 )
  1163. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1164. if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
  1165. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1166. break;
  1167. case BA_FROSTJOKE:
  1168. if(rand()%100 < (15+5*skilllv)*sc_def_mdef/100)
  1169. skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1170. break;
  1171. case DC_SCREAM:
  1172. if( rand()%100 < (25+5*skilllv)*sc_def_vit/100 )
  1173. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1174. break;
  1175. case BD_LULLABY: /* 子守唄 */
  1176. if( rand()%100 < 15*sc_def_int/100 )
  1177. skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1178. break;
  1179. /* MOBの追加?果付きスキル */
  1180. case NPC_PETRIFYATTACK:
  1181. if(rand()%100 < sc_def_mdef)
  1182. skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1183. break;
  1184. case NPC_POISON:
  1185. case NPC_SILENCEATTACK:
  1186. case NPC_STUNATTACK:
  1187. if(rand()%100 < sc_def_vit && src->type!=BL_PET)
  1188. skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1189. if(src->type==BL_PET)
  1190. skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
  1191. break;
  1192. case NPC_CURSEATTACK:
  1193. if(rand()%100 < sc_def_luk)
  1194. skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1195. break;
  1196. case NPC_SLEEPATTACK:
  1197. case NPC_BLINDATTACK:
  1198. if(rand()%100 < sc_def_int)
  1199. skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1200. break;
  1201. case NPC_MENTALBREAKER:
  1202. if(dstsd) {
  1203. int sp = dstsd->status.max_sp*(10+skilllv)/100;
  1204. if(sp < 1) sp = 1;
  1205. pc_heal(dstsd,0,-sp);
  1206. }
  1207. break;
  1208. // -- moonsoul (adding status effect chance given to wizard aoe skills meteor and vermillion)
  1209. //
  1210. case WZ_METEOR:
  1211. if(rand()%100 < sc_def_vit)
  1212. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1213. break;
  1214. case WZ_VERMILION:
  1215. if(rand()%100 < sc_def_int)
  1216. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1217. break;
  1218. // -- moonsoul (stun ability of new champion skill tigerfist)
  1219. //
  1220. case CH_TIGERFIST:
  1221. if( rand()%100 < (10 + skilllv*10)*sc_def_vit/100 ) {
  1222. int sec = skill_get_time2 (skillid,skilllv) - (double)battle_get_agi(bl)*0.1;
  1223. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,sec,0);
  1224. }
  1225. break;
  1226. case LK_SPIRALPIERCE:
  1227. if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
  1228. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1229. break;
  1230. case ST_REJECTSWORD: /* フリ?ジングトラップ */
  1231. if( rand()%100 < (skilllv*15) )
  1232. skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1233. break;
  1234. case PF_FOGWALL: /* ホ?リ?クロス */
  1235. if(src!=bl && rand()%100 < 3*skilllv*sc_def_int/100 )
  1236. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1237. break;
  1238. case LK_HEADCRUSH: /* ヘッドクラッシュ */
  1239. {//?件が良く分からないので適?に
  1240. int race=battle_get_race(bl);
  1241. if( !(battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
  1242. skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1243. }
  1244. break;
  1245. case LK_JOINTBEAT: /* ジョイントビ?ト */
  1246. //?件が良く分からないので適?に
  1247. if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
  1248. skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1249. break;
  1250. case PF_SPIDERWEB: /* スパイダ?ウェッブ */
  1251. {
  1252. if(bl->type == BL_MOB)
  1253. {
  1254. int sec=skill_get_time2(skillid,skilllv);
  1255. if(map[src->m].flag.pvp) //PvPでは拘束時間半減?
  1256. sec = sec/2;
  1257. battle_stopwalking(bl,1);
  1258. skill_status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0);
  1259. }
  1260. }
  1261. break;
  1262. case ASC_METEORASSAULT: /* メテオアサルト */
  1263. if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) //?態異常は詳細が分からないので適?に
  1264. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1265. if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
  1266. skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  1267. break;
  1268. case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */
  1269. //阿修羅を使うと5分間自然回復しないようになる
  1270. skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 );
  1271. break;
  1272. case HW_NAPALMVULCAN: /* ナパ?ムバルカン */
  1273. // skilllv*5%の確率で呪い
  1274. if (rand()%10000 < 5*skilllv*sc_def_luk)
  1275. skill_status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
  1276. break;
  1277. }
  1278. if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */
  1279. int i;
  1280. int sc_def_card=100;
  1281. for(i=SC_STONE;i<=SC_BLIND;i++){
  1282. //?象に?態異常
  1283. if(i==SC_STONE || i==SC_FREEZE)
  1284. sc_def_card=sc_def_mdef;
  1285. else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
  1286. sc_def_card=sc_def_vit;
  1287. else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
  1288. sc_def_card=sc_def_int;
  1289. else if(i==SC_CURSE)
  1290. sc_def_card=sc_def_luk;
  1291. if(!sd->state.arrow_atk) {
  1292. if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
  1293. if(battle_config.battle_log)
  1294. printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
  1295. skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
  1296. }
  1297. }
  1298. else {
  1299. if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
  1300. if(battle_config.battle_log)
  1301. printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
  1302. skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
  1303. }
  1304. }
  1305. //自分に?態異常
  1306. if(i==SC_STONE || i==SC_FREEZE)
  1307. sc_def_card=sc_def_mdef2;
  1308. else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
  1309. sc_def_card=sc_def_vit2;
  1310. else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
  1311. sc_def_card=sc_def_int2;
  1312. else if(i==SC_CURSE)
  1313. sc_def_card=sc_def_luk2;
  1314. if(!sd->state.arrow_atk) {
  1315. if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
  1316. if(battle_config.battle_log)
  1317. printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
  1318. skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
  1319. }
  1320. }
  1321. else {
  1322. if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
  1323. if(battle_config.battle_log)
  1324. printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
  1325. skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
  1326. }
  1327. }
  1328. }
  1329. }
  1330. return 0;
  1331. }
  1332. /*=========================================================================
  1333. スキル攻?吹き飛ばし?理
  1334. -------------------------------------------------------------------------*/
  1335. int skill_blown( struct block_list *src, struct block_list *target,int count)
  1336. {
  1337. int dx=0,dy=0,nx,ny;
  1338. int x=target->x,y=target->y;
  1339. int ret,prev_state=MS_IDLE;
  1340. int moveblock;
  1341. struct map_session_data *sd=NULL;
  1342. struct mob_data *md=NULL;
  1343. struct pet_data *pd=NULL;
  1344. struct skill_unit *su=NULL;
  1345. nullpo_retr(0, src);
  1346. nullpo_retr(0, target);
  1347. if(target->type==BL_PC){
  1348. nullpo_retr(0, sd=(struct map_session_data *)target);
  1349. }else if(target->type==BL_MOB){
  1350. nullpo_retr(0, md=(struct mob_data *)target);
  1351. }else if(target->type==BL_PET){
  1352. nullpo_retr(0, pd=(struct pet_data *)target);
  1353. }else if(target->type==BL_SKILL){
  1354. nullpo_retr(0, su=(struct skill_unit *)target);
  1355. }else return 0;
  1356. if(!(count&0x10000 && (sd||md||pd||su))){ /* 指定なしなら位置?係から方向を求める */
  1357. dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0);
  1358. dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0);
  1359. }
  1360. if(dx==0 && dy==0){
  1361. int dir=battle_get_dir(target);
  1362. if(dir>=0 && dir<8){
  1363. dx=-dirx[dir];
  1364. dy=-diry[dir];
  1365. }
  1366. }
  1367. ret=path_blownpos(target->m,x,y,dx,dy,count&0xffff);
  1368. nx=ret>>16;
  1369. ny=ret&0xffff;
  1370. moveblock=( x/BLOCK_SIZE != nx/BLOCK_SIZE || y/BLOCK_SIZE != ny/BLOCK_SIZE);
  1371. if(count&0x20000) {
  1372. battle_stopwalking(target,1);
  1373. if(sd){
  1374. sd->to_x=nx;
  1375. sd->to_y=ny;
  1376. sd->walktimer = 1;
  1377. clif_walkok(sd);
  1378. clif_movechar(sd);
  1379. }
  1380. else if(md) {
  1381. md->to_x=nx;
  1382. md->to_y=ny;
  1383. prev_state = md->state.state;
  1384. md->state.state = MS_WALK;
  1385. clif_fixmobpos(md);
  1386. }
  1387. else if(pd) {
  1388. pd->to_x=nx;
  1389. pd->to_y=ny;
  1390. prev_state = pd->state.state;
  1391. pd->state.state = MS_WALK;
  1392. clif_fixpetpos(pd);
  1393. }
  1394. }
  1395. else
  1396. battle_stopwalking(target,2);
  1397. dx = nx - x;
  1398. dy = ny - y;
  1399. if(sd) /* ?面外に出たので消去 */
  1400. map_foreachinmovearea(clif_pcoutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,0,sd);
  1401. else if(md)
  1402. map_foreachinmovearea(clif_moboutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,md);
  1403. else if(pd)
  1404. map_foreachinmovearea(clif_petoutsight,target->m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,pd);
  1405. if(su){
  1406. skill_unit_move_unit_group(su->group,target->m,dx,dy);
  1407. }else{
  1408. // struct status_change *sc_data=battle_get_sc_data(target);
  1409. if(moveblock) map_delblock(target);
  1410. target->x=nx;
  1411. target->y=ny;
  1412. if(moveblock) map_addblock(target);
  1413. /*ダンス中にエフェクトは移動しないらしい
  1414. if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?象がダンス中なのでエフェクトも移動
  1415. struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2;
  1416. if(sg)
  1417. skill_unit_move_unit_group(sg,target->m,dx,dy);
  1418. }
  1419. */
  1420. }
  1421. if(sd) { /* ?面?に入ってきたので表示 */
  1422. map_foreachinmovearea(clif_pcinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,0,sd);
  1423. if(count&0x20000)
  1424. sd->walktimer = -1;
  1425. }
  1426. else if(md) {
  1427. map_foreachinmovearea(clif_mobinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,BL_PC,md);
  1428. if(count&0x20000)
  1429. md->state.state = prev_state;
  1430. }
  1431. else if(pd) {
  1432. map_foreachinmovearea(clif_petinsight,target->m,nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE,-dx,-dy,BL_PC,pd);
  1433. if(count&0x20000)
  1434. pd->state.state = prev_state;
  1435. }
  1436. skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */
  1437. return 0;
  1438. }
  1439. /*
  1440. * =========================================================================
  1441. * スキル攻??果?理まとめ
  1442. * flagの?明。16進?
  1443. * 00XRTTff
  1444. * ff = magicで計算に渡される)
  1445. * TT = パケットのtype部分(0でデフォルト)
  1446. * X = パケットのスキルLv
  1447. * R = 予約(skill_area_subで使用する)
  1448. *-------------------------------------------------------------------------
  1449. */
  1450. int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,
  1451. struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
  1452. {
  1453. struct Damage dmg;
  1454. struct status_change *sc_data;
  1455. int type,lv,damage;
  1456. if(skillid > 0 && skilllv <= 0) return 0;
  1457. rdamage = 0;
  1458. nullpo_retr(0, src);
  1459. nullpo_retr(0, dsrc);
  1460. nullpo_retr(0, bl);
  1461. sc_data = battle_get_sc_data(bl);
  1462. //何もしない判定ここから
  1463. if(dsrc->m != bl->m) //?象が同じマップにいなければ何もしない
  1464. return 0;
  1465. if(src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL) //prevよくわからない※
  1466. return 0;
  1467. if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //術者?がPCですでに死んでいたら何もしない
  1468. return 0;
  1469. if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない
  1470. return 0;
  1471. if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?象がPCですでに死んでいたら何もしない
  1472. return 0;
  1473. if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *) bl))
  1474. return 0; // [MouseJstr]
  1475. if(sc_data && sc_data[SC_HIDING].timer != -1) { //ハイディング?態で
  1476. if(skill_get_pl(skillid) != 2) //スキルの?性が地?性でなければ何もしない
  1477. return 0;
  1478. }
  1479. if(sc_data && sc_data[SC_TRICKDEAD].timer != -1) //死んだふり中は何もしない
  1480. return 0;
  1481. if(skillid == WZ_STORMGUST) { //使用スキルがスト?ムガストで
  1482. if(sc_data && sc_data[SC_FREEZE].timer != -1) //凍結?態なら何もしない
  1483. return 0;
  1484. }
  1485. if(skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) //使用スキルがフロストノヴァで、dsrcとblが同じ場所なら何もしない
  1486. return 0;
  1487. if(src->type == BL_PC && ((struct map_session_data *)src)->chatID) //術者がPCでチャット中なら何もしない
  1488. return 0;
  1489. if(dsrc->type == BL_PC && ((struct map_session_data *)dsrc)->chatID) //術者がPCでチャット中なら何もしない
  1490. return 0;
  1491. if(src->type == BL_PC && bl && mob_gvmobcheck(((struct map_session_data *)src),bl)==0)
  1492. return 0;
  1493. //何もしない判定ここまで
  1494. type=-1;
  1495. lv=(flag>>20)&0xf;
  1496. dmg=battle_calc_attack(attack_type,src,bl,skillid,skilllv,flag&0xff ); //ダメ?ジ計算
  1497. //マジックロッド?理ここから
  1498. if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //魔法攻?でマジックロッド?態でsrc=dsrcなら
  1499. dmg.damage = dmg.damage2 = 0; //ダメ?ジ0
  1500. if(bl->type == BL_PC) { //?象がPCの場合
  1501. int sp = skill_get_sp(skillid,skilllv); //使用されたスキルのSPを吸?
  1502. sp = sp * sc_data[SC_MAGICROD].val2 / 100; //吸?率計算
  1503. if(skillid == WZ_WATERBALL && skilllv > 1) //ウォ?タ?ボ?ルLv1以上
  1504. sp = sp/((skilllv|1)*(skilllv|1)); //さらに計算?
  1505. if(sp > 0x7fff) sp = 0x7fff; //SP多すぎの場合は理論最大値
  1506. else if(sp < 1) sp = 1; //1以下の場合は1
  1507. if(((struct map_session_data *)bl)->status.sp + sp > ((struct map_session_data *)bl)->status.max_sp) { //回復SP+現在のSPがMSPより大きい場合
  1508. sp = ((struct map_session_data *)bl)->status.max_sp - ((struct map_session_data *)bl)->status.sp; //SPをMSP-現在SPにする
  1509. ((struct map_session_data *)bl)->status.sp = ((struct map_session_data *)bl)->status.max_sp; //現在のSPにMSPを代入
  1510. }
  1511. else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
  1512. ((struct map_session_data *)bl)->status.sp += sp;
  1513. clif_heal(((struct map_session_data *)bl)->fd,SP_SP,sp); //SP回復エフェクトの表示
  1514. ((struct map_session_data *)bl)->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); //
  1515. }
  1516. clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //マジックロッドエフェクトを表示
  1517. }
  1518. //マジックロッド?理ここまで
  1519. if(src->type==BL_PET) { // [Valaris]
  1520. dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), battle_get_element(bl) );
  1521. dmg.damage2=0;
  1522. }
  1523. damage = dmg.damage + dmg.damage2;
  1524. if(lv==15)
  1525. lv=-1;
  1526. if( flag&0xff00 )
  1527. type=(flag&0xff00)>>8;
  1528. if(damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※
  1529. dmg.blewcount = 0;
  1530. if(skillid == CR_GRANDCROSS||skillid == NPC_DARKGRANDCROSS) {//グランドクロス
  1531. if(battle_config.gx_disptype) dsrc = src; // 敵ダメ?ジ白文字表示
  1532. if( src == bl) type = 4; // 反動はダメ?ジモ?ションなし
  1533. }
  1534. //使用者がPCの場合の?理ここから
  1535. if(src->type == BL_PC) {
  1536. struct map_session_data *sd = (struct map_session_data *)src;
  1537. nullpo_retr(0, sd);
  1538. //連打掌(MO_CHAINCOMBO)ここから
  1539. if(skillid == MO_CHAINCOMBO) {
  1540. int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); //基本ディレイの計算
  1541. if(damage < battle_get_hp(bl)) { //ダメ?ジが?象のHPより小さい場合
  1542. if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //猛龍拳(MO_COMBOFINISH)取得&?球保持時は+300ms
  1543. delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
  1544. skill_status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //コンボ?態に
  1545. }
  1546. sd->attackabletime = sd->canmove_tick = tick + delay;
  1547. clif_combo_delay(src,delay); //コンボディレイパケットの送信
  1548. }
  1549. //連打掌(MO_CHAINCOMBO)ここまで
  1550. //猛龍拳(MO_COMBOFINISH)ここから
  1551. else if(skillid == MO_COMBOFINISH) {
  1552. int delay = 700 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
  1553. if(damage < battle_get_hp(bl)) {
  1554. //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&?球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)?態時は+300ms
  1555. //伏虎拳(CH_TIGERFIST)取得時も+300ms
  1556. if((pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) ||
  1557. (pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) ||
  1558. (pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1))
  1559. delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
  1560. skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //コンボ?態に
  1561. }
  1562. sd->attackabletime = sd->canmove_tick = tick + delay;
  1563. clif_combo_delay(src,delay); //コンボディレイパケットの送信
  1564. }
  1565. //猛龍拳(MO_COMBOFINISH)ここまで
  1566. //伏虎拳(CH_TIGERFIST)ここから
  1567. else if(skillid == CH_TIGERFIST) {
  1568. int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
  1569. if(damage < battle_get_hp(bl)) {
  1570. if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //連柱崩?(CH_CHAINCRUSH)取得時は+300ms
  1571. delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
  1572. skill_status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //コンボ?態に
  1573. }
  1574. sd->attackabletime = sd->canmove_tick = tick + delay;
  1575. clif_combo_delay(src,delay); //コンボディレイパケットの送信
  1576. }
  1577. //伏虎拳(CH_TIGERFIST)ここまで
  1578. //連柱崩?(CH_CHAINCRUSH)ここから
  1579. else if(skillid == CH_CHAINCRUSH) {
  1580. int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
  1581. if(damage < battle_get_hp(bl)) {
  1582. //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&?球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)?態時は+300ms
  1583. if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
  1584. delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
  1585. skill_status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //コンボ?態に
  1586. }
  1587. sd->attackabletime = sd->canmove_tick = tick + delay;
  1588. clif_combo_delay(src,delay); //コンボディレイパケットの送信
  1589. }
  1590. //連柱崩?(CH_CHAINCRUSH)ここまで
  1591. }
  1592. //使用者がPCの場合の?理ここまで
  1593. //武器スキル?ここから
  1594. //AppleGirl Was Here
  1595. if(attack_type&BF_MAGIC && damage > 0 && src != bl && src == dsrc) { //Blah Blah
  1596. if(bl->type == BL_PC) { //Blah Blah
  1597. struct map_session_data *tsd = (struct map_session_data *)bl;
  1598. if(tsd->magic_damage_return > 0) { //More Blah
  1599. rdamage += damage * tsd->magic_damage_return / 100;
  1600. if(rdamage < 1) rdamage = 1;
  1601. }
  1602. }
  1603. }
  1604. //Stop Here
  1605. if(attack_type&BF_WEAPON && damage > 0 && src != bl && src == dsrc) { //武器スキル&ダメ?ジあり&使用者と?象者が違う&src=dsrc
  1606. if(dmg.flag&BF_SHORT) { //近距離攻?時?※
  1607. if(bl->type == BL_PC) { //?象がPCの時
  1608. struct map_session_data *tsd = (struct map_session_data *)bl;
  1609. nullpo_retr(0, tsd);
  1610. if(tsd->short_weapon_damage_return > 0) { //近距離攻?跳ね返し?※
  1611. rdamage += damage * tsd->short_weapon_damage_return / 100;
  1612. if(rdamage < 1) rdamage = 1;
  1613. }
  1614. }
  1615. if(sc_data && sc_data[SC_REFLECTSHIELD].timer != -1) { //リフレクトシ?ルド時
  1616. rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100; //跳ね返し計算
  1617. if(rdamage < 1) rdamage = 1;
  1618. }
  1619. }
  1620. else if(dmg.flag&BF_LONG) { //遠距離攻?時?※
  1621. if(bl->type == BL_PC) { //?象がPCの時
  1622. struct map_session_data *tsd = (struct map_session_data *)bl;
  1623. nullpo_retr(0, tsd);
  1624. if(tsd->long_weapon_damage_return > 0) { //遠距離攻?跳ね返し?※
  1625. rdamage += damage * tsd->long_weapon_damage_return / 100;
  1626. if(rdamage < 1) rdamage = 1;
  1627. }
  1628. }
  1629. }
  1630. if(rdamage > 0)
  1631. clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0);
  1632. }
  1633. //武器スキル?ここまで
  1634. switch(skillid){
  1635. case WZ_SIGHTRASHER:
  1636. clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5);
  1637. break;
  1638. case AS_SPLASHER:
  1639. clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5);
  1640. break;
  1641. case NPC_SELFDESTRUCTION:
  1642. case NPC_SELFDESTRUCTION2:
  1643. break;
  1644. default:
  1645. clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
  1646. }
  1647. if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 吹き飛ばし?理とそのパケット */
  1648. if(skillid == WZ_SIGHTRASHER)
  1649. skill_blown(src,bl,dmg.blewcount);
  1650. else
  1651. skill_blown(dsrc,bl,dmg.blewcount);
  1652. if(bl->type == BL_MOB)
  1653. clif_fixmobpos((struct mob_data *)bl);
  1654. else if(bl->type == BL_PET)
  1655. clif_fixpetpos((struct pet_data *)bl);
  1656. else
  1657. clif_fixpos(bl);
  1658. }
  1659. map_freeblock_lock();
  1660. /* ?際にダメ?ジ?理を行う */
  1661. if(skillid != KN_BOWLINGBASH || flag)
  1662. battle_damage(src,bl,damage,0);
  1663. if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
  1664. int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl);
  1665. int rate = 50 + skilllv * 5;
  1666. rate = rate + (s_lv - t_lv);
  1667. if(rand()%100 < rate)
  1668. skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
  1669. }
  1670. if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer != -1){
  1671. struct map_session_data *tsd = (struct map_session_data *)bl;
  1672. nullpo_retr(0, tsd);
  1673. if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
  1674. && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
  1675. //?に?んでいるスキルがあれば該?スキルを消す
  1676. if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
  1677. tsd->status.skill[tsd->cloneskill_id].id=0;
  1678. tsd->status.skill[tsd->cloneskill_id].lv=0;
  1679. tsd->status.skill[tsd->cloneskill_id].flag=0;
  1680. }
  1681. tsd->cloneskill_id=skillid;
  1682. tsd->cloneskill_lv=skilllv;
  1683. tsd->status.skill[skillid].id=skillid;
  1684. tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
  1685. skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
  1686. tsd->status.skill[skillid].flag=13;//cloneskill flag
  1687. clif_skillinfoblock(tsd);
  1688. }
  1689. }
  1690. /* ダメ?ジがあるなら追加?果判定 */
  1691. if(bl->prev != NULL){
  1692. struct map_session_data *sd = (struct map_session_data *)bl;
  1693. nullpo_retr(0, sd);
  1694. if( bl->type != BL_PC || (sd && !pc_isdead(sd)) ) {
  1695. if(damage > 0)
  1696. skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick);
  1697. if(bl->type==BL_MOB && src!=bl) /* スキル使用?件のMOBスキル */
  1698. {
  1699. struct mob_data *md=(struct mob_data *)bl;
  1700. nullpo_retr(0, md);
  1701. if(battle_config.mob_changetarget_byskill == 1)
  1702. {
  1703. int target;
  1704. target=md->target_id;
  1705. if(src->type == BL_PC)
  1706. md->target_id=src->id;
  1707. mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16));
  1708. md->target_id=target;
  1709. }
  1710. else
  1711. mobskill_use(md,tick,MSC_SKILLUSED|(skillid<<16));
  1712. }
  1713. }
  1714. }
  1715. if(src->type == BL_PC && dmg.flag&BF_WEAPON && src != bl && src == dsrc && damage > 0) {
  1716. struct map_session_data *sd = (struct map_session_data *)src;
  1717. int hp = 0,sp = 0;
  1718. nullpo_retr(0, sd);
  1719. if(sd->hp_drain_rate && sd->hp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->hp_drain_rate) {
  1720. hp += (dmg.damage * sd->hp_drain_per)/100;
  1721. if(sd->hp_drain_rate > 0 && hp < 1) hp = 1;
  1722. else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1;
  1723. }
  1724. if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) {
  1725. hp += (dmg.damage2 * sd->hp_drain_per_)/100;
  1726. if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1;
  1727. else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1;
  1728. }
  1729. if(sd->sp_drain_rate > 0 && sd->sp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->sp_drain_rate) {
  1730. sp += (dmg.damage * sd->sp_drain_per)/100;
  1731. if(sd->sp_drain_rate > 0 && sp < 1) sp = 1;
  1732. else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1;
  1733. }
  1734. if(sd->sp_drain_rate_ > 0 && sd->sp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) {
  1735. sp += (dmg.damage2 * sd->sp_drain_per_)/100;
  1736. if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
  1737. else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
  1738. }
  1739. if(hp || sp) pc_heal(sd,hp,sp);
  1740. }
  1741. if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
  1742. battle_damage(bl,src,rdamage,0);
  1743. if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) {
  1744. if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
  1745. battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1);
  1746. skill_status_change_end(bl,SC_AUTOCOUNTER,-1);
  1747. }
  1748. map_freeblock_unlock();
  1749. return (dmg.damage+dmg.damage2); /* ?ダメを返す */
  1750. }
  1751. /*==========================================
  1752. * スキル範?攻?用(map_foreachinareaから呼ばれる)
  1753. * flagについて:16進?を確認
  1754. * MSB <- 00fTffff ->LSB
  1755. * T =タ?ゲット選?用(BCT_*)
  1756. * ffff=自由に使用可能
  1757. * 0 =予約。0に固定
  1758. *------------------------------------------
  1759. */
  1760. static int skill_area_temp[8]; /* 一時??。必要なら使う。 */
  1761. typedef int (*SkillFunc)(struct block_list *,struct block_list *,int,int,unsigned int,int);
  1762. int skill_area_sub( struct block_list *bl,va_list ap )
  1763. {
  1764. struct block_list *src;
  1765. int skill_id,skill_lv,flag;
  1766. unsigned int tick;
  1767. SkillFunc func;
  1768. nullpo_retr(0, bl);
  1769. nullpo_retr(0, ap);
  1770. if(bl->type!=BL_PC && bl->type!=BL_MOB && bl->type!=BL_SKILL)
  1771. return 0;
  1772. src=va_arg(ap,struct block_list *); //ここではsrcの値を?照していないのでNULLチェックはしない
  1773. skill_id=va_arg(ap,int);
  1774. skill_lv=va_arg(ap,int);
  1775. tick=va_arg(ap,unsigned int);
  1776. flag=va_arg(ap,int);
  1777. func=va_arg(ap,SkillFunc);
  1778. if(battle_check_target(src,bl,flag) > 0)
  1779. func(src,bl,skill_id,skill_lv,tick,flag);
  1780. return 0;
  1781. }
  1782. static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
  1783. {
  1784. struct skill_unit *unit;
  1785. int *c,x,y,range,sx[4],sy[4];
  1786. int t_range,tx[4],ty[4];
  1787. int i,r_flag,skillid;
  1788. nullpo_retr(0, bl);
  1789. nullpo_retr(0, ap);
  1790. nullpo_retr(0, unit = (struct skill_unit *)bl);
  1791. nullpo_retr(0, c = va_arg(ap,int *));
  1792. if(bl->prev == NULL || bl->type != BL_SKILL)
  1793. return 0;
  1794. if(!unit->alive)
  1795. return 0;
  1796. x = va_arg(ap,int);
  1797. y = va_arg(ap,int);
  1798. range = va_arg(ap,int);
  1799. skillid = va_arg(ap,int);
  1800. if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) {
  1801. if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
  1802. return 0;
  1803. }
  1804. else if(skillid == AL_WARP) {
  1805. if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
  1806. return 0;
  1807. }
  1808. else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) {
  1809. if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
  1810. return 0;
  1811. }
  1812. else if(skillid == WZ_FIREPILLAR) {
  1813. if(unit->group->unit_id != 0x87)
  1814. return 0;
  1815. }
  1816. else return 0;
  1817. t_range=(unit->range!=0)? unit->range:unit->group->range;
  1818. tx[0] = tx[3] = unit->bl.x - t_range;
  1819. tx[1] = tx[2] = unit->bl.x + t_range;
  1820. ty[0] = ty[1] = unit->bl.y - t_range;
  1821. ty[2] = ty[3] = unit->bl.y + t_range;
  1822. sx[0] = sx[3] = x - range;
  1823. sx[1] = sx[2] = x + range;
  1824. sy[0] = sy[1] = y - range;
  1825. sy[2] = sy[3] = y + range;
  1826. for(i=r_flag=0;i<4;i++) {
  1827. if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) {
  1828. r_flag = 1;
  1829. break;
  1830. }
  1831. if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) {
  1832. r_flag = 1;
  1833. break;
  1834. }
  1835. }
  1836. if(r_flag) (*c)++;
  1837. return 0;
  1838. }
  1839. int skill_check_unit_range(int m,int x,int y,int range,int skillid)
  1840. {
  1841. int c = 0;
  1842. map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid);
  1843. return c;
  1844. }
  1845. static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
  1846. {
  1847. int *c;
  1848. nullpo_retr(0, bl);
  1849. nullpo_retr(0, ap);
  1850. nullpo_retr(0, c = va_arg(ap,int *));
  1851. if(bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB))
  1852. return 0;
  1853. if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
  1854. return 0;
  1855. (*c)++;
  1856. return 0;
  1857. }
  1858. int skill_check_unit_range2(int m,int x,int y,int range)
  1859. {
  1860. int c = 0;
  1861. map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
  1862. return c;
  1863. }
  1864. /*=========================================================================
  1865. * 範?スキル使用?理小分けここから
  1866. */
  1867. /* ?象の?をカウントする。(skill_area_temp[0]を初期化しておくこと) */
  1868. int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag)
  1869. {
  1870. //if(skilllv <= 0) return 0;
  1871. if(skillid > 0 && skilllv <= 0) return 0; // celest
  1872. if(skill_area_temp[0] < 0xffff)
  1873. skill_area_temp[0]++;
  1874. return 0;
  1875. }
  1876. /*==========================================
  1877. *
  1878. *------------------------------------------
  1879. */
  1880. static int skill_timerskill(int tid, unsigned int tick, int id,int data )
  1881. {
  1882. struct map_session_data *sd = NULL;
  1883. struct mob_data *md = NULL;
  1884. struct pet_data *pd = NULL;
  1885. struct block_list *src = map_id2bl(id),*target;
  1886. struct skill_timerskill *skl = NULL;
  1887. int range;
  1888. nullpo_retr(0, src);
  1889. if(src->prev == NULL)
  1890. return 0;
  1891. if(src->type == BL_PC) {
  1892. nullpo_retr(0, sd = (struct map_session_data *)src);
  1893. skl = &sd->skilltimerskill[data];
  1894. }
  1895. else if(src->type == BL_MOB) {
  1896. nullpo_retr(0, md = (struct mob_data *)src);
  1897. skl = &md->skilltimerskill[data];
  1898. }
  1899. else if(src->type == BL_PET) { // [Valaris]
  1900. nullpo_retr(0, pd = (struct pet_data *)src);
  1901. skl = &pd->skilltimerskill[data];
  1902. }
  1903. else
  1904. return 0;
  1905. nullpo_retr(0, skl);
  1906. skl->timer = -1;
  1907. if(skl->target_id) {
  1908. struct block_list tbl;
  1909. target = map_id2bl(skl->target_id);
  1910. if(skl->skill_id == RG_INTIMIDATE) {
  1911. if(target == NULL) {
  1912. target = &tbl; //初期化してないのにアドレス突っ?んでいいのかな?
  1913. target->type = BL_NUL;
  1914. target->m = src->m;
  1915. target->prev = target->next = NULL;
  1916. }
  1917. }
  1918. if(target == NULL)
  1919. return 0;
  1920. if(target->prev == NULL && skl->skill_id != RG_INTIMIDATE)
  1921. return 0;
  1922. if(src->m != target->m)
  1923. return 0;
  1924. if(sd && pc_isdead(sd))
  1925. return 0;
  1926. if(target->type == BL_PC && pc_isdead((struct map_session_data *)target) && skl->skill_id != RG_INTIMIDATE)
  1927. return 0;
  1928. switch(skl->skill_id) {
  1929. case TF_BACKSLIDING:
  1930. clif_skill_nodamage(src,src,skl->skill_id,skl->skill_lv,1);
  1931. break;
  1932. case RG_INTIMIDATE:
  1933. if(sd && !map[src->m].flag.noteleport) {
  1934. int x,y,i,j,c;
  1935. pc_randomwarp(sd,3);
  1936. for(i=0;i<16;i++) {
  1937. j = rand()%8;
  1938. x = sd->bl.x + dirx[j];
  1939. y = sd->bl.y + diry[j];
  1940. if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5)
  1941. break;
  1942. }
  1943. if(i >= 16) {
  1944. x = sd->bl.x;
  1945. y = sd->bl.y;
  1946. }
  1947. if(target->prev != NULL) {
  1948. if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
  1949. pc_setpos((struct map_session_data *)target,map[sd->bl.m].name,x,y,3);
  1950. else if(target->type == BL_MOB)
  1951. mob_warp((struct mob_data *)target,-1,x,y,3);
  1952. }
  1953. }
  1954. else if(md && !map[src->m].flag.monster_noteleport) {
  1955. int x,y,i,j,c;
  1956. mob_warp(md,-1,-1,-1,3);
  1957. for(i=0;i<16;i++) {
  1958. j = rand()%8;
  1959. x = md->bl.x + dirx[j];
  1960. y = md->bl.y + diry[j];
  1961. if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5)
  1962. break;
  1963. }
  1964. if(i >= 16) {
  1965. x = md->bl.x;
  1966. y = md->bl.y;
  1967. }
  1968. if(target->prev != NULL) {
  1969. if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
  1970. pc_setpos((struct map_session_data *)target,map[md->bl.m].name,x,y,3);
  1971. else if(target->type == BL_MOB)
  1972. mob_warp((struct mob_data *)target,-1,x,y,3);
  1973. }
  1974. }
  1975. break;
  1976. case BA_FROSTJOKE: /* 寒いジョ?ク */
  1977. case DC_SCREAM: /* スクリ?ム */
  1978. range=15; //視界全?
  1979. map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range,
  1980. src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick);
  1981. break;
  1982. default:
  1983. skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
  1984. break;
  1985. }
  1986. }
  1987. else {
  1988. if(src->m != skl->map)
  1989. return 0;
  1990. switch(skl->skill_id) {
  1991. case WZ_METEOR:
  1992. if(skl->type >= 0) {
  1993. skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->type>>16,skl->type&0xFFFF,0);
  1994. clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
  1995. }
  1996. else
  1997. skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,0);
  1998. break;
  1999. }
  2000. }
  2001. return 0;
  2002. }
  2003. /*==========================================
  2004. *
  2005. *------------------------------------------
  2006. */
  2007. int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int x,int y,int skill_id,int skill_lv,int type,int flag)
  2008. {
  2009. int i;
  2010. nullpo_retr(1, src);
  2011. if(src->type == BL_PC) {
  2012. struct map_session_data *sd = (struct map_session_data *)src;
  2013. nullpo_retr(1, sd);
  2014. for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
  2015. if(sd->skilltimerskill[i].timer == -1) {
  2016. sd->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
  2017. sd->skilltimerskill[i].src_id = src->id;
  2018. sd->skilltimerskill[i].target_id = target;
  2019. sd->skilltimerskill[i].skill_id = skill_id;
  2020. sd->skilltimerskill[i].skill_lv = skill_lv;
  2021. sd->skilltimerskill[i].map = src->m;
  2022. sd->skilltimerskill[i].x = x;
  2023. sd->skilltimerskill[i].y = y;
  2024. sd->skilltimerskill[i].type = type;
  2025. sd->skilltimerskill[i].flag = flag;
  2026. return 0;
  2027. }
  2028. }
  2029. return 1;
  2030. }
  2031. else if(src->type == BL_MOB) {
  2032. struct mob_data *md = (struct mob_data *)src;
  2033. nullpo_retr(1, md);
  2034. for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
  2035. if(md->skilltimerskill[i].timer == -1) {
  2036. md->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
  2037. md->skilltimerskill[i].src_id = src->id;
  2038. md->skilltimerskill[i].target_id = target;
  2039. md->skilltimerskill[i].skill_id = skill_id;
  2040. md->skilltimerskill[i].skill_lv = skill_lv;
  2041. md->skilltimerskill[i].map = src->m;
  2042. md->skilltimerskill[i].x = x;
  2043. md->skilltimerskill[i].y = y;
  2044. md->skilltimerskill[i].type = type;
  2045. md->skilltimerskill[i].flag = flag;
  2046. return 0;
  2047. }
  2048. }
  2049. return 1;
  2050. }
  2051. else if(src->type == BL_PET) { // [Valaris]
  2052. struct pet_data *pd = (struct pet_data *)src;
  2053. nullpo_retr(1, pd);
  2054. for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
  2055. if(pd->skilltimerskill[i].timer == -1) {
  2056. pd->skilltimerskill[i].timer = add_timer(tick, skill_timerskill, src->id, i);
  2057. pd->skilltimerskill[i].src_id = src->id;
  2058. pd->skilltimerskill[i].target_id = target;
  2059. pd->skilltimerskill[i].skill_id = skill_id;
  2060. pd->skilltimerskill[i].skill_lv = skill_lv;
  2061. pd->skilltimerskill[i].map = src->m;
  2062. pd->skilltimerskill[i].x = x;
  2063. pd->skilltimerskill[i].y = y;
  2064. pd->skilltimerskill[i].type = type;
  2065. pd->skilltimerskill[i].flag = flag;
  2066. return 0;
  2067. }
  2068. }
  2069. return 1;
  2070. }
  2071. return 1;
  2072. }
  2073. /*==========================================
  2074. *
  2075. *------------------------------------------
  2076. */
  2077. int skill_cleartimerskill(struct block_list *src)
  2078. {
  2079. int i;
  2080. nullpo_retr(0, src);
  2081. if(src->type == BL_PC) {
  2082. struct map_session_data *sd = (struct map_session_data *)src;
  2083. nullpo_retr(0, sd);
  2084. for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
  2085. if(sd->skilltimerskill[i].timer != -1) {
  2086. delete_timer(sd->skilltimerskill[i].timer, skill_timerskill);
  2087. sd->skilltimerskill[i].timer = -1;
  2088. }
  2089. }
  2090. }
  2091. else if(src->type == BL_MOB) {
  2092. struct mob_data *md = (struct mob_data *)src;
  2093. nullpo_retr(0, md);
  2094. for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++) {
  2095. if(md->skilltimerskill[i].timer != -1) {
  2096. delete_timer(md->skilltimerskill[i].timer, skill_timerskill);
  2097. md->skilltimerskill[i].timer = -1;
  2098. }
  2099. }
  2100. }
  2101. return 0;
  2102. }
  2103. /* 範?スキル使用?理小分けここまで
  2104. * -------------------------------------------------------------------------
  2105. */
  2106. /*==========================================
  2107. * スキル使用(詠唱完了、ID指定攻?系)
  2108. * (スパゲッティに向けて1?前進!(ダメポ))
  2109. *------------------------------------------
  2110. */
  2111. int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
  2112. {
  2113. struct map_session_data *sd=NULL;
  2114. struct status_change *sc_data = battle_get_sc_data(src);
  2115. int i;
  2116. if(skillid > 0 && skilllv <= 0) return 0;
  2117. nullpo_retr(1, src);
  2118. nullpo_retr(1, bl);
  2119. if(src->type==BL_PC)
  2120. sd=(struct map_session_data *)src;
  2121. if(sd && pc_isdead(sd))
  2122. return 1;
  2123. if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
  2124. bl = src;
  2125. if(bl->prev == NULL)
  2126. return 1;
  2127. if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
  2128. return 1;
  2129. map_freeblock_lock();
  2130. switch(skillid)
  2131. {
  2132. /* 武器攻?系スキル */
  2133. case SM_BASH: /* バッシュ */
  2134. case MC_MAMMONITE: /* メマ?ナイト */
  2135. case AC_DOUBLE: /* ダブルストレイフィング */
  2136. case AS_SONICBLOW: /* ソニックブロ? */
  2137. case KN_PIERCE: /* ピア?ス */
  2138. case KN_SPEARBOOMERANG: /* スピアブ?メラン */
  2139. case TF_POISON: /* インベナム */
  2140. case TF_SPRINKLESAND: /* 砂まき */
  2141. case AC_CHARGEARROW: /* チャ?ジアロ? */
  2142. case KN_SPEARSTAB: /* スピアスタブ */
  2143. case RG_RAID: /* サプライズアタック */
  2144. case RG_INTIMIDATE: /* インティミデイト */
  2145. case BA_MUSICALSTRIKE: /* ミュ?ジカルストライク */
  2146. case DC_THROWARROW: /* 矢?ち */
  2147. case BA_DISSONANCE: /* 不協和音 */
  2148. case CR_HOLYCROSS: /* ホ?リ?クロス */
  2149. case CR_SHIELDCHARGE:
  2150. case CR_SHIELDBOOMERANG:
  2151. /* 以下MOB?用 */
  2152. /* ??攻?、SP減少攻?、遠距離攻?、防御無視攻?、多段攻? */
  2153. case NPC_PIERCINGATT:
  2154. case NPC_MENTALBREAKER:
  2155. case NPC_RANGEATTACK:
  2156. case NPC_CRITICALSLASH:
  2157. case NPC_COMBOATTACK:
  2158. /* 必中攻?、毒攻?、暗?攻?、沈?攻?、スタン攻? */
  2159. case NPC_GUIDEDATTACK:
  2160. case NPC_POISON:
  2161. case NPC_BLINDATTACK:
  2162. case NPC_SILENCEATTACK:
  2163. case NPC_STUNATTACK:
  2164. /* 石化攻?、呪い攻?、睡眠攻?、ランダムATK攻? */
  2165. case NPC_PETRIFYATTACK:
  2166. case NPC_CURSEATTACK:
  2167. case NPC_SLEEPATTACK:
  2168. case NPC_RANDOMATTACK:
  2169. /* 水?性攻?、地?性攻?、火?性攻?、風?性攻? */
  2170. case NPC_WATERATTACK:
  2171. case NPC_GROUNDATTACK:
  2172. case NPC_FIREATTACK:
  2173. case NPC_WINDATTACK:
  2174. /* 毒?性攻?、聖?性攻?、闇?性攻?、念?性攻?、SP減少攻? */
  2175. case NPC_POISONATTACK:
  2176. case NPC_HOLYATTACK:
  2177. case NPC_DARKNESSATTACK:
  2178. case NPC_TELEKINESISATTACK:
  2179. case NPC_UNDEADATTACK:
  2180. case LK_AURABLADE: /* オ?ラブレ?ド */
  2181. case LK_SPIRALPIERCE: /* スパイラルピア?ス */
  2182. case LK_HEADCRUSH: /* ヘッドクラッシュ */
  2183. case LK_JOINTBEAT: /* ジョイントビ?ト */
  2184. case PA_PRESSURE: /* プレッシャ? */
  2185. case PA_SACRIFICE: /* サクリファイス */
  2186. case SN_SHARPSHOOTING: /* シャ?プシュ?ティング */
  2187. case CG_ARROWVULCAN: /* アロ?バルカン */
  2188. case ASC_BREAKER: /* ソウルブレ?カ? */
  2189. case HW_MAGICCRASHER: /* マジッククラッシャ? */
  2190. case ITM_TOMAHAWK:
  2191. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2192. break;
  2193. case NPC_DARKBREATH:
  2194. clif_emotion(src,7);
  2195. skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
  2196. break;
  2197. case MO_INVESTIGATE: /* ?勁 */
  2198. {
  2199. struct status_change *sc_data = battle_get_sc_data(src);
  2200. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2201. if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
  2202. skill_status_change_end(src,SC_BLADESTOP,-1);
  2203. }
  2204. break;
  2205. case SN_FALCONASSAULT: /* ファルコンアサルト */
  2206. skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
  2207. break;
  2208. case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
  2209. {
  2210. struct mob_data *md = (struct mob_data *)bl;
  2211. nullpo_retr(1, md);
  2212. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2213. if(md->hp > 0){
  2214. skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
  2215. if(bl->type == BL_MOB)
  2216. clif_fixmobpos((struct mob_data *)bl);
  2217. else if(bl->type == BL_PET)
  2218. clif_fixpetpos((struct pet_data *)bl);
  2219. else
  2220. clif_fixpos(bl);
  2221. }
  2222. }
  2223. break;
  2224. case RG_BACKSTAP: /* バックスタブ */
  2225. {
  2226. int dir = map_calc_dir(src,bl->x,bl->y),t_dir = battle_get_dir(bl);
  2227. int dist = distance(src->x,src->y,bl->x,bl->y);
  2228. if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) {
  2229. struct status_change *sc_data = battle_get_sc_data(src);
  2230. if(sc_data && sc_data[SC_HIDING].timer != -1)
  2231. skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除
  2232. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2233. dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
  2234. if (bl->type == BL_PC)
  2235. ((struct map_session_data *)bl)->dir=dir;
  2236. else if (bl->type == BL_MOB)
  2237. ((struct mob_data *)bl)->dir=dir;
  2238. //skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
  2239. }
  2240. else if(src->type == BL_PC)
  2241. clif_skill_fail(sd,sd->skillid,0,0);
  2242. }
  2243. break;
  2244. case AM_ACIDTERROR: /* アシッドテラ? */
  2245. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2246. if(bl->type == BL_PC && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking) {
  2247. pc_breakarmor((struct map_session_data *)bl);
  2248. clif_emotion(bl, 23);
  2249. }
  2250. break;
  2251. case MO_FINGEROFFENSIVE: /* 指? */
  2252. {
  2253. struct status_change *sc_data = battle_get_sc_data(src);
  2254. if(!battle_config.finger_offensive_type)
  2255. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2256. else {
  2257. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2258. if(sd) {
  2259. for(i=1;i<sd->spiritball_old;i++)
  2260. skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag);
  2261. sd->canmove_tick = tick + (sd->spiritball_old-1)*200;
  2262. }
  2263. }
  2264. if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
  2265. skill_status_change_end(src,SC_BLADESTOP,-1);
  2266. }
  2267. break;
  2268. case MO_CHAINCOMBO: /* 連打掌 */
  2269. {
  2270. struct status_change *sc_data = battle_get_sc_data(src);
  2271. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2272. if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
  2273. skill_status_change_end(src,SC_BLADESTOP,-1);
  2274. }
  2275. break;
  2276. case MO_COMBOFINISH: /* 猛龍拳 */
  2277. case CH_TIGERFIST: /* 伏虎拳 */
  2278. case CH_CHAINCRUSH: /* 連柱崩? */
  2279. case CH_PALMSTRIKE: /* 猛虎硬派山 */
  2280. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2281. break;
  2282. case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */
  2283. {
  2284. struct status_change *sc_data = battle_get_sc_data(src);
  2285. if(sd) {
  2286. struct walkpath_data wpd;
  2287. int dx,dy;
  2288. dx = bl->x - sd->bl.x;
  2289. dy = bl->y - sd->bl.y;
  2290. if(dx > 0) dx++;
  2291. else if(dx < 0) dx--;
  2292. if(dy > 0) dy++;
  2293. else if(dy < 0) dy--;
  2294. if(dx == 0 && dy == 0) dx++;
  2295. if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
  2296. dx = bl->x - sd->bl.x;
  2297. dy = bl->y - sd->bl.y;
  2298. if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
  2299. clif_skill_fail(sd,sd->skillid,0,0);
  2300. break;
  2301. }
  2302. }
  2303. sd->to_x = sd->bl.x + dx;
  2304. sd->to_y = sd->bl.y + dy;
  2305. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2306. clif_walkok(sd);
  2307. clif_movechar(sd);
  2308. if(dx < 0) dx = -dx;
  2309. if(dy < 0) dy = -dy;
  2310. sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
  2311. if(sd->canact_tick < sd->canmove_tick)
  2312. sd->canact_tick = sd->canmove_tick;
  2313. pc_movepos(sd,sd->to_x,sd->to_y);
  2314. skill_status_change_end(&sd->bl,SC_COMBO,-1);
  2315. }
  2316. else
  2317. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
  2318. skill_status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
  2319. if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
  2320. skill_status_change_end(src,SC_BLADESTOP,-1);
  2321. }
  2322. break;
  2323. /* 武器系範?攻?スキル */
  2324. case AC_SHOWER: /* アロ?シャワ? */
  2325. case SM_MAGNUM: /* マグナムブレイク */
  2326. case AS_GRIMTOOTH: /* グリムトゥ?ス */
  2327. case MC_CARTREVOLUTION: /* カ?トレヴォリュ?ション */
  2328. case NPC_SPLASHATTACK: /* スプラッシュアタック */
  2329. case ASC_METEORASSAULT: /* メテオアサルト */
  2330. case AS_SPLASHER: /* [Valaris] */
  2331. if(flag&1){
  2332. /* 個別にダメ?ジを?える */
  2333. if(bl->id!=skill_area_temp[1]){
  2334. int dist=0;
  2335. if(skillid==SM_MAGNUM){ /* マグナムブレイクなら中心からの距離を計算 */
  2336. int dx=abs( bl->x - skill_area_temp[2] );
  2337. int dy=abs( bl->y - skill_area_temp[3] );
  2338. dist=((dx>dy)?dx:dy);
  2339. }
  2340. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
  2341. 0x0500|dist );
  2342. if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) {
  2343. struct status_change *sc_data = battle_get_sc_data(bl);
  2344. if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
  2345. skill_status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
  2346. }
  2347. }
  2348. }else{
  2349. int ar=1;
  2350. int x=bl->x,y=bl->y;
  2351. if( skillid==SM_MAGNUM){
  2352. x=src->x;
  2353. y=src->y;
  2354. }else if(skillid==AC_SHOWER || skillid==ASC_METEORASSAULT) /* アロ?シャワ?、メテオアサルト範?5*5 */
  2355. ar=2;
  2356. else if(skillid==AS_SPLASHER) /* ベナムスプラッシャ?範?3*3 */
  2357. ar=1;
  2358. else if(skillid==NPC_SPLASHATTACK) /* スプラッシュアタックは範?7*7 */
  2359. ar=3;
  2360. if (skillid == ASC_METEORASSAULT)
  2361. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2362. skill_area_temp[1]=bl->id;
  2363. skill_area_temp[2]=x;
  2364. skill_area_temp[3]=y;
  2365. /* まずタ?ゲットに攻?を加える */
  2366. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
  2367. /* その後タ?ゲット以外の範??の敵全?に?理を行う */
  2368. map_foreachinarea(skill_area_sub,
  2369. bl->m,x-ar,y-ar,x+ar,y+ar,0,
  2370. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2371. skill_castend_damage_id);
  2372. if (skillid == SM_MAGNUM) // fire element for 10 seconds
  2373. skill_status_change_start(src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
  2374. }
  2375. break;
  2376. case KN_BOWLINGBASH: /* ボウリングバッシュ */
  2377. if(flag&1){
  2378. /* 個別にダメ?ジを?える */
  2379. if(bl->id!=skill_area_temp[1])
  2380. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
  2381. }
  2382. else {
  2383. int damage;
  2384. map_freeblock_lock();
  2385. damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
  2386. if(damage > 0) {
  2387. int i,c; /* 他人から聞いた動きなので間違ってる可能性大&?率が?いっす>< */
  2388. c = skill_get_blewcount(skillid,skilllv);
  2389. if(map[bl->m].flag.gvg) c = 0;
  2390. for(i=0;i<c;i++){
  2391. skill_blown(src,bl,1);
  2392. if(bl->type == BL_MOB)
  2393. clif_fixmobpos((struct mob_data *)bl);
  2394. else if(bl->type == BL_PET)
  2395. clif_fixpetpos((struct pet_data *)bl);
  2396. else
  2397. clif_fixpos(bl);
  2398. skill_area_temp[0]=0;
  2399. map_foreachinarea(skill_area_sub,
  2400. bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2401. src,skillid,skilllv,tick, flag|BCT_ENEMY ,
  2402. skill_area_sub_count);
  2403. if(skill_area_temp[0]>1) break;
  2404. }
  2405. skill_area_temp[1]=bl->id;
  2406. skill_area_temp[2]=bl->x;
  2407. skill_area_temp[3]=bl->y;
  2408. /* その後タ?ゲット以外の範??の敵全?に?理を行う */
  2409. map_foreachinarea(skill_area_sub,
  2410. bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2411. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2412. skill_castend_damage_id);
  2413. battle_damage(src,bl,damage,1);
  2414. if(rdamage > 0)
  2415. battle_damage(bl,src,rdamage,0);
  2416. }
  2417. map_freeblock_unlock();
  2418. }
  2419. break;
  2420. case ALL_RESURRECTION: /* リザレクション */
  2421. case PR_TURNUNDEAD: /* タ?ンアンデッド */
  2422. if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
  2423. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2424. else {
  2425. map_freeblock_unlock();
  2426. return 1;
  2427. }
  2428. break;
  2429. /* 魔法系スキル */
  2430. case MG_SOULSTRIKE: /* ソウルストライク */
  2431. case NPC_DARKSOULSTRIKE: /*闇ソウルストライク*/
  2432. case MG_COLDBOLT: /* コールドボルト */
  2433. case MG_FIREBOLT: /* ファイアーボルト */
  2434. case MG_LIGHTNINGBOLT: /* ライトニングボルト */
  2435. case WZ_EARTHSPIKE: /* アーススパイク */
  2436. case AL_HEAL: /* ヒール */
  2437. case AL_HOLYLIGHT: /* ホーリーライト */
  2438. case MG_FROSTDIVER: /* フロストダイバー */
  2439. case WZ_JUPITEL: /* ユピテルサンダー */
  2440. case NPC_DARKJUPITEL: /*闇ユピテル*/
  2441. case NPC_MAGICALATTACK: /* MOB:魔法打?攻? */
  2442. case PR_ASPERSIO: /* アスペルシオ */
  2443. // case HW_NAPALMVULCAN: /* ナパームバルカン */
  2444. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2445. break;
  2446. case WZ_WATERBALL: /* ウォ?タ?ボ?ル */
  2447. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2448. if(skilllv>1)
  2449. skill_status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0);
  2450. break;
  2451. case PR_BENEDICTIO: /* 聖?降福 */
  2452. if(battle_get_race(bl)==1 || battle_get_race(bl)==6)
  2453. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2454. break;
  2455. /* 魔法系範?攻?スキル */
  2456. case MG_NAPALMBEAT: /* ナパ?ムビ?ト */
  2457. case MG_FIREBALL: /* ファイヤ?ボ?ル */
  2458. if(flag&1){
  2459. /* 個別にダメ?ジを?える */
  2460. if(bl->id!=skill_area_temp[1]){
  2461. if(skillid==MG_FIREBALL){ /* ファイヤ?ボ?ルなら中心からの距離を計算 */
  2462. int dx=abs( bl->x - skill_area_temp[2] );
  2463. int dy=abs( bl->y - skill_area_temp[3] );
  2464. skill_area_temp[0]=((dx>dy)?dx:dy);
  2465. }
  2466. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
  2467. skill_area_temp[0]| 0x0500);
  2468. }
  2469. }else{
  2470. int ar=(skillid==MG_NAPALMBEAT)?1:2;
  2471. skill_area_temp[1]=bl->id;
  2472. if(skillid==MG_NAPALMBEAT){ /* ナパ?ムでは先に?える */
  2473. skill_area_temp[0]=0;
  2474. map_foreachinarea(skill_area_sub,
  2475. bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2476. src,skillid,skilllv,tick, flag|BCT_ENEMY ,
  2477. skill_area_sub_count);
  2478. }else{
  2479. skill_area_temp[0]=0;
  2480. skill_area_temp[2]=bl->x;
  2481. skill_area_temp[3]=bl->y;
  2482. }
  2483. /* まずタ?ゲットに攻?を加える */
  2484. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
  2485. skill_area_temp[0] );
  2486. /* その後タ?ゲット以外の範??の敵全?に?理を行う */
  2487. map_foreachinarea(skill_area_sub,
  2488. bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
  2489. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2490. skill_castend_damage_id);
  2491. }
  2492. break;
  2493. case HW_NAPALMVULCAN: // Fixed By SteelViruZ
  2494. if(flag&1){
  2495. if(bl->id!=skill_area_temp[1]){
  2496. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
  2497. skill_area_temp[0]);
  2498. }
  2499. }else{
  2500. int ar=(skillid==HW_NAPALMVULCAN)?1:2;
  2501. skill_area_temp[1]=bl->id;
  2502. if(skillid==HW_NAPALMVULCAN){
  2503. skill_area_temp[0]=0;
  2504. map_foreachinarea(skill_area_sub,
  2505. bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2506. src,skillid,skilllv,tick, flag|BCT_ENEMY ,
  2507. skill_area_sub_count);
  2508. }else{
  2509. skill_area_temp[0]=0;
  2510. skill_area_temp[2]=bl->x;
  2511. skill_area_temp[3]=bl->y;
  2512. }
  2513. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
  2514. skill_area_temp[0] );
  2515. map_foreachinarea(skill_area_sub,
  2516. bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
  2517. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2518. skill_castend_damage_id);
  2519. }
  2520. break;
  2521. case WZ_FROSTNOVA: /* フロストノヴァ */
  2522. skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
  2523. //skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2524. map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
  2525. break;
  2526. case WZ_SIGHTRASHER:
  2527. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2528. skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
  2529. skill_status_change_end(src,SC_SIGHT,-1);
  2530. break;
  2531. /* その他 */
  2532. case HT_BLITZBEAT: /* ブリッツビ?ト */
  2533. if(flag&1){
  2534. /* 個別にダメ?ジを?える */
  2535. if(bl->id!=skill_area_temp[1])
  2536. skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(flag&0xf00000));
  2537. }else{
  2538. skill_area_temp[0]=0;
  2539. skill_area_temp[1]=bl->id;
  2540. if(flag&0xf00000)
  2541. map_foreachinarea(skill_area_sub,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2542. src,skillid,skilllv,tick, flag|BCT_ENEMY ,skill_area_sub_count);
  2543. /* まずタ?ゲットに攻?を加える */
  2544. skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,skill_area_temp[0]|(flag&0xf00000));
  2545. /* その後タ?ゲット以外の範??の敵全?に?理を行う */
  2546. map_foreachinarea(skill_area_sub,
  2547. bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
  2548. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2549. skill_castend_damage_id);
  2550. }
  2551. break;
  2552. case CR_GRANDCROSS: /* グランドクロス */
  2553. case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
  2554. /* スキルユニット配置 */
  2555. skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
  2556. if(sd)
  2557. sd->canmove_tick = tick + 1000;
  2558. else if(src->type == BL_MOB)
  2559. mob_changestate((struct mob_data *)src,MS_DELAY,1000);
  2560. break;
  2561. case TF_THROWSTONE: /* 石投げ */
  2562. case NPC_SMOKING: /* スモ?キング */
  2563. skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 );
  2564. break;
  2565. // Celest
  2566. case PF_SOULBURN:
  2567. {
  2568. int per = skilllv < 5 ? 20+ skilllv*10 : 60;
  2569. if (rand()%100 < per) {
  2570. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2571. if (skilllv == 5)
  2572. skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
  2573. if (bl->type == BL_PC)
  2574. ((struct map_session_data *)bl)->status.sp = 0;
  2575. } else {
  2576. clif_skill_nodamage(src,src,skillid,skilllv,1);
  2577. if (skilllv == 5)
  2578. skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,0 );
  2579. sd->status.sp = 0;
  2580. clif_updatestatus(sd,SP_SP);
  2581. }
  2582. skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0, (skilllv < 5 ? 10000: 15000),0 );
  2583. }
  2584. break;
  2585. case NPC_SELFDESTRUCTION: /* 自爆 */
  2586. case NPC_SELFDESTRUCTION2: /* 自爆2 */
  2587. if(flag&1){
  2588. /* 個別にダメ?ジを?える */
  2589. if(src->type==BL_MOB){
  2590. struct mob_data* mb = (struct mob_data*)src;
  2591. nullpo_retr(1, mb);
  2592. mb->hp=skill_area_temp[2];
  2593. if(bl->id!=skill_area_temp[1])
  2594. skill_attack(BF_MISC,src,src,bl,NPC_SELFDESTRUCTION,skilllv,tick,flag );
  2595. mb->hp=1;
  2596. }
  2597. }else{
  2598. struct mob_data *md;
  2599. if((md=(struct mob_data *)src)){
  2600. skill_area_temp[1]=bl->id;
  2601. skill_area_temp[2]=battle_get_hp(src);
  2602. clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1);
  2603. map_foreachinarea(skill_area_sub,
  2604. bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0,
  2605. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2606. skill_castend_damage_id);
  2607. battle_damage(src,src,md->hp,0);
  2608. }
  2609. }
  2610. break;
  2611. /* HP吸?/HP吸?魔法 */
  2612. case NPC_BLOODDRAIN:
  2613. case NPC_ENERGYDRAIN:
  2614. {
  2615. int heal;
  2616. heal = skill_attack((skillid==NPC_BLOODDRAIN)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
  2617. if( heal > 0 ){
  2618. struct block_list tbl;
  2619. tbl.id = 0;
  2620. tbl.m = src->m;
  2621. tbl.x = src->x;
  2622. tbl.y = src->y;
  2623. clif_skill_nodamage(&tbl,src,AL_HEAL,heal,1);
  2624. battle_heal(NULL,src,heal,0,0);
  2625. }
  2626. }
  2627. break;
  2628. // unknown skills [Celest]
  2629. case NPC_BIND:
  2630. case NPC_EXPLOSIONSPIRITS:
  2631. case NPC_INCAGI:
  2632. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2633. break;
  2634. case 0:
  2635. if(sd) {
  2636. if(flag&3){
  2637. if(bl->id!=skill_area_temp[1])
  2638. skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
  2639. }
  2640. else{
  2641. int ar=sd->splash_range;
  2642. skill_area_temp[1]=bl->id;
  2643. map_foreachinarea(skill_area_sub,
  2644. bl->m, bl->x - ar, bl->y - ar, bl->x + ar, bl->y + ar, 0,
  2645. src, skillid, skilllv, tick, flag | BCT_ENEMY | 1,
  2646. skill_castend_damage_id);
  2647. }
  2648. }
  2649. break;
  2650. default:
  2651. printf("Unknown skill used:%d\n",skillid);
  2652. map_freeblock_unlock();
  2653. return 1;
  2654. }
  2655. if(sc_data) {
  2656. if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //マジックパワ?の?果終了
  2657. skill_status_change_end(src,SC_MAGICPOWER,-1);
  2658. }
  2659. map_freeblock_unlock();
  2660. return 0;
  2661. }
  2662. /*==========================================
  2663. * スキル使用(詠唱完了、ID指定支援系)
  2664. *------------------------------------------
  2665. */
  2666. int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
  2667. {
  2668. struct map_session_data *sd=NULL;
  2669. struct map_session_data *dstsd=NULL;
  2670. struct mob_data *md=NULL;
  2671. struct mob_data *dstmd=NULL;
  2672. int i,abra_skillid=0,abra_skilllv;
  2673. int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per;
  2674. int sc_dex,sc_luk;
  2675. //クラスチェンジ用ボスモンスタ?ID
  2676. int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
  2677. ,1157,1159,1190,1272,1312,1373,1492};
  2678. int poringclass[]={1002};
  2679. //if(skilllv <= 0) return 0;
  2680. if(skillid > 0 && skilllv <= 0) return 0; // celest
  2681. nullpo_retr(1, src);
  2682. nullpo_retr(1, bl);
  2683. if(src->type==BL_PC)
  2684. sd=(struct map_session_data *)src;
  2685. else if(src->type==BL_MOB)
  2686. md=(struct mob_data *)src;
  2687. sc_dex=battle_get_mdef(bl);
  2688. sc_luk=battle_get_luk(bl);
  2689. sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
  2690. //sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
  2691. sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3);
  2692. strip_fix = battle_get_dex(src) - battle_get_dex(bl);
  2693. if(bl->type==BL_PC){
  2694. nullpo_retr(1, dstsd=(struct map_session_data *)bl);
  2695. }else if(bl->type==BL_MOB){
  2696. nullpo_retr(1, dstmd=(struct mob_data *)bl);
  2697. if(sc_def_vit>50)
  2698. sc_def_vit=50;
  2699. if(sc_def_mdef>50)
  2700. sc_def_mdef=50;
  2701. }
  2702. if(sc_def_vit < 0)
  2703. sc_def_vit=0;
  2704. if(sc_def_mdef < 0)
  2705. sc_def_mdef=0;
  2706. if(strip_fix < 0)
  2707. strip_fix=0;
  2708. if(bl == NULL || bl->prev == NULL)
  2709. return 1;
  2710. if(sd && pc_isdead(sd))
  2711. return 1;
  2712. if(dstsd && pc_isdead(dstsd) && skillid != ALL_RESURRECTION)
  2713. return 1;
  2714. if(battle_get_class(bl) == 1288)
  2715. return 1;
  2716. if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr]
  2717. return 0;
  2718. map_freeblock_lock();
  2719. switch(skillid)
  2720. {
  2721. case AL_HEAL: /* ヒ?ル */
  2722. {
  2723. int heal=skill_calc_heal( src, skilllv );
  2724. int heal_get_jobexp;
  2725. int skill;
  2726. struct pc_base_job s_class;
  2727. if( dstsd && dstsd->special_state.no_magic_damage )
  2728. heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */
  2729. if (sd){
  2730. s_class = pc_calc_base_job(sd->status.class);
  2731. if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // メディテイティオ
  2732. heal += heal*skill*2/100;
  2733. if(sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //自分も?象もPC、?象が自分のパ?トナ?、自分がスパノビ、自分が♀なら
  2734. heal = heal*2; //スパノビの嫁が旦那にヒ?ルすると2倍になる
  2735. }
  2736. clif_skill_nodamage(src,bl,skillid,heal,1);
  2737. heal_get_jobexp = battle_heal(NULL,bl,heal,0,0);
  2738. // JOB??値獲得
  2739. if(src->type == BL_PC && bl->type==BL_PC && heal > 0 && src != bl && battle_config.heal_exp > 0){
  2740. heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
  2741. if(heal_get_jobexp <= 0)
  2742. heal_get_jobexp = 1;
  2743. pc_gainexp((struct map_session_data *)src,0,heal_get_jobexp);
  2744. }
  2745. }
  2746. break;
  2747. case ALL_RESURRECTION: /* リザレクション */
  2748. if(bl->type==BL_PC){
  2749. int per=0;
  2750. struct map_session_data *tsd = (struct map_session_data*)bl;
  2751. nullpo_retr(1, tsd);
  2752. if( (map[bl->m].flag.pvp) && tsd->pvp_point<0 )
  2753. break; /* PVPで復活不可能?態 */
  2754. if(pc_isdead(tsd)){ /* 死亡判定 */
  2755. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2756. switch(skilllv){
  2757. case 1: per=10; break;
  2758. case 2: per=30; break;
  2759. case 3: per=50; break;
  2760. case 4: per=80; break;
  2761. }
  2762. tsd->status.hp=tsd->status.max_hp*per/100;
  2763. if(tsd->status.hp<=0) tsd->status.hp=1;
  2764. if(tsd->special_state.restart_full_recover ){ /* オシリスカ?ド */
  2765. tsd->status.hp=tsd->status.max_hp;
  2766. tsd->status.sp=tsd->status.max_sp;
  2767. }
  2768. pc_setstand(tsd);
  2769. if(battle_config.pc_invincible_time > 0)
  2770. pc_setinvincibletimer(tsd,battle_config.pc_invincible_time);
  2771. clif_updatestatus(tsd,SP_HP);
  2772. clif_resurrection(&tsd->bl,1);
  2773. if(src != bl && sd && battle_config.resurrection_exp > 0) {
  2774. int exp = 0,jexp = 0;
  2775. int lv = tsd->status.base_level - sd->status.base_level, jlv = tsd->status.job_level - sd->status.job_level;
  2776. if(lv > 0) {
  2777. exp = (int)((double)tsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
  2778. if(exp < 1) exp = 1;
  2779. }
  2780. if(jlv > 0) {
  2781. jexp = (int)((double)tsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
  2782. if(jexp < 1) jexp = 1;
  2783. }
  2784. if(exp > 0 || jexp > 0)
  2785. pc_gainexp(sd,exp,jexp);
  2786. }
  2787. }
  2788. }
  2789. break;
  2790. case AL_DECAGI: /* 速度減少 */
  2791. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  2792. break;
  2793. if( rand()%100 < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) {
  2794. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2795. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  2796. }
  2797. break;
  2798. case AL_CRUCIS:
  2799. if(flag&1) {
  2800. int race = battle_get_race(bl),ele = battle_get_elem_type(bl);
  2801. if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) {
  2802. int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate;
  2803. rate = 25 + skilllv*2 + slv - tlv;
  2804. if(rand()%100 < rate)
  2805. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
  2806. }
  2807. }
  2808. else {
  2809. int range = 15;
  2810. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2811. map_foreachinarea(skill_area_sub,
  2812. src->m,src->x-range,src->y-range,src->x+range,src->y+range,0,
  2813. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  2814. skill_castend_nodamage_id);
  2815. }
  2816. break;
  2817. case PR_LEXDIVINA: /* レックスディビ?ナ */
  2818. {
  2819. struct status_change *sc_data = battle_get_sc_data(bl);
  2820. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2821. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  2822. break;
  2823. if(sc_data && sc_data[SC_DIVINA].timer != -1)
  2824. skill_status_change_end(bl,SC_DIVINA,-1);
  2825. else if( rand()%100 < sc_def_vit ) {
  2826. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  2827. }
  2828. }
  2829. break;
  2830. case SA_ABRACADABRA:
  2831. //require 1 yellow gemstone even with mistress card or Into the Abyss
  2832. if ((i=pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
  2833. clif_skill_fail(sd,sd->skillid,0,0);
  2834. break;
  2835. }
  2836. //pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0);
  2837. pc_delitem(sd, i, 1, 0);
  2838. //
  2839. do{
  2840. abra_skillid=skill_abra_dataset(skilllv);
  2841. }while(abra_skillid == 0);
  2842. abra_skilllv=skill_get_max(abra_skillid)>pc_checkskill(sd,SA_ABRACADABRA)?pc_checkskill(sd,SA_ABRACADABRA):skill_get_max(abra_skillid);
  2843. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2844. sd->skillitem=abra_skillid;
  2845. sd->skillitemlv=abra_skilllv;
  2846. clif_item_skill(sd,abra_skillid,abra_skilllv,"アブラカダブラ");
  2847. break;
  2848. case SA_COMA:
  2849. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2850. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  2851. break;
  2852. if(dstsd){
  2853. dstsd->status.hp=1;
  2854. dstsd->status.sp=1;
  2855. clif_updatestatus(dstsd,SP_HP);
  2856. clif_updatestatus(dstsd,SP_SP);
  2857. }
  2858. if(dstmd) dstmd->hp=1;
  2859. break;
  2860. case SA_FULLRECOVERY:
  2861. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2862. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  2863. break;
  2864. if(dstsd) pc_heal(dstsd,dstsd->status.max_hp,dstsd->status.max_sp);
  2865. if(dstmd) dstmd->hp=battle_get_max_hp(&dstmd->bl);
  2866. break;
  2867. case SA_SUMMONMONSTER:
  2868. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2869. if (sd) mob_once_spawn(sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,"--ja--",-1,1,"");
  2870. break;
  2871. case SA_LEVELUP:
  2872. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2873. if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd,pc_nextbaseexp(sd)*10/100,0);
  2874. break;
  2875. case SA_INSTANTDEATH:
  2876. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2877. if (sd) pc_damage(NULL,sd,sd->status.max_hp);
  2878. break;
  2879. case SA_QUESTION:
  2880. case SA_GRAVITY:
  2881. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2882. break;
  2883. case SA_CLASSCHANGE:
  2884. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2885. if(dstmd) mob_class_change(dstmd,changeclass);
  2886. break;
  2887. case SA_MONOCELL:
  2888. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2889. if(dstmd) mob_class_change(dstmd,poringclass);
  2890. break;
  2891. case SA_DEATH:
  2892. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2893. if (dstsd) pc_damage(NULL,dstsd,dstsd->status.max_hp);
  2894. if (dstmd) mob_damage(NULL,dstmd,dstmd->hp,1);
  2895. break;
  2896. case SA_REVERSEORCISH:
  2897. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2898. if (dstsd) pc_setoption(dstsd,dstsd->status.option|0x0800);
  2899. break;
  2900. case SA_FORTUNE:
  2901. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2902. if(sd) pc_getzeny(sd,battle_get_lv(bl)*100);
  2903. break;
  2904. case SA_TAMINGMONSTER:
  2905. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2906. if (dstmd){
  2907. for(i=0;i<MAX_PET_DB;i++){
  2908. if(dstmd->class == pet_db[i].class){
  2909. pet_catch_process1(sd,dstmd->class);
  2910. break;
  2911. }
  2912. }
  2913. }
  2914. break;
  2915. case AL_INCAGI: /* 速度?加 */
  2916. case AL_BLESSING: /* ブレッシング */
  2917. case PR_SLOWPOISON:
  2918. case PR_IMPOSITIO: /* イムポシティオマヌス */
  2919. case PR_LEXAETERNA: /* レックスエ?テルナ */
  2920. case PR_SUFFRAGIUM: /* サフラギウム */
  2921. case PR_BENEDICTIO: /* 聖?降福 */
  2922. case CR_PROVIDENCE: /* プロヴィデンス */
  2923. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
  2924. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2925. }else{
  2926. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  2927. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2928. }
  2929. break;
  2930. case CG_MARIONETTE: /* マリオネットコントロ?ル */
  2931. if(sd && dstsd){
  2932. struct status_change *sc_data = battle_get_sc_data(src);
  2933. struct status_change *tsc_data = battle_get_sc_data(bl);
  2934. int sc = SkillStatusChangeTable[skillid];
  2935. int sc2 = SC_MARIONETTE2;
  2936. if((dstsd->bl.type!=BL_PC)
  2937. || (sd->bl.id == dstsd->bl.id)
  2938. || (!sd->status.party_id)
  2939. || (sd->status.party_id != dstsd->status.party_id)) {
  2940. clif_skill_fail(sd,skillid,0,0);
  2941. map_freeblock_unlock();
  2942. return 1;
  2943. }
  2944. if(sc_data && tsc_data){
  2945. if(sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
  2946. skill_status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
  2947. skill_status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
  2948. }
  2949. else if (sc_data[sc].timer != -1 && tsc_data[sc2].timer != -1 &&
  2950. sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
  2951. skill_status_change_end(src, sc, -1);
  2952. skill_status_change_end(bl, sc2, -1);
  2953. }
  2954. else {
  2955. clif_skill_fail(sd,skillid,0,0);
  2956. map_freeblock_unlock();
  2957. return 1;
  2958. }
  2959. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2960. }
  2961. }
  2962. break;
  2963. case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
  2964. case SA_FROSTWEAPON:
  2965. case SA_LIGHTNINGLOADER:
  2966. case SA_SEISMICWEAPON:
  2967. if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
  2968. clif_skill_nodamage(src,bl,skillid,skilllv,0);
  2969. break;
  2970. }
  2971. if(bl->type==BL_PC) {
  2972. struct map_session_data *sd2=(struct map_session_data *)bl;
  2973. if(sd2->status.weapon==0 || sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
  2974. sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
  2975. sd2->sc_data[SC_ENCPOISON].timer!=-1) {
  2976. clif_skill_fail(sd,skillid,0,0);
  2977. clif_skill_nodamage(src,bl,skillid,skilllv,0);
  2978. break;
  2979. }
  2980. }
  2981. if(rand()%100 > (60+skilllv*10) && (skilllv != 5)) {
  2982. clif_skill_fail(sd,skillid,0,0);
  2983. clif_skill_nodamage(src,bl,skillid,skilllv,0);
  2984. if(bl->type==BL_PC && battle_config.equipment_breaking) {
  2985. struct map_session_data *sd2=(struct map_session_data *)bl;
  2986. if(sd!=sd2) clif_displaymessage(sd->fd,"You broke target's weapon");
  2987. pc_breakweapon(sd2);
  2988. }
  2989. break;
  2990. }
  2991. else {
  2992. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  2993. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2994. }
  2995. break;
  2996. case PR_ASPERSIO: /* アスペルシオ */
  2997. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  2998. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  2999. break;
  3000. if(bl->type==BL_MOB)
  3001. break;
  3002. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3003. break;
  3004. case PR_KYRIE: /* キリエエレイソン */
  3005. clif_skill_nodamage(bl,bl,skillid,skilllv,1);
  3006. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3007. break;
  3008. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3009. break;
  3010. case KN_AUTOCOUNTER: /* オ?トカウンタ? */
  3011. case KN_TWOHANDQUICKEN: /* ツ?ハンドクイッケン */
  3012. case CR_SPEARQUICKEN: /* スピアクイッケン */
  3013. case CR_REFLECTSHIELD:
  3014. case AS_POISONREACT: /* ポイズンリアクト */
  3015. case MC_LOUD: /* ラウドボイス */
  3016. case MG_ENERGYCOAT: /* エナジ?コ?ト */
  3017. // case SM_ENDURE: /* インデュア */
  3018. case MG_SIGHT: /* サイト */
  3019. case AL_RUWACH: /* ルアフ */
  3020. case MO_EXPLOSIONSPIRITS: // 爆裂波動
  3021. case MO_STEELBODY: // 金剛
  3022. case LK_AURABLADE: /* オ?ラブレ?ド */
  3023. case LK_PARRYING: /* パリイング */
  3024. case LK_CONCENTRATION: /* コンセントレ?ション */
  3025. // case LK_BERSERK: /* バ?サ?ク */
  3026. case HP_ASSUMPTIO: /* */
  3027. case WS_CARTBOOST: /* カ?トブ?スト */
  3028. case SN_SIGHT: /* トゥル?サイト */
  3029. case WS_MELTDOWN: /* メルトダウン */
  3030. case ST_REJECTSWORD: /* リジェクトソ?ド */
  3031. case HW_MAGICPOWER: /* 魔法力?幅 */
  3032. case PF_MEMORIZE: /* メモライズ */
  3033. case ASC_EDP: // [Celest]
  3034. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3035. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3036. break;
  3037. case SM_ENDURE: /* インデュア */
  3038. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3039. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3040. skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,10000,0 );
  3041. break;
  3042. case SM_AUTOBERSERK: // Celest
  3043. {
  3044. struct status_change *tsc_data = battle_get_sc_data(bl);
  3045. int sc=SkillStatusChangeTable[skillid];
  3046. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3047. if( tsc_data ){
  3048. if( tsc_data[sc].timer==-1 )
  3049. skill_status_change_start(bl,sc,skilllv,0,0,0,0,0);
  3050. else
  3051. skill_status_change_end(bl, sc, -1);
  3052. }
  3053. }
  3054. break;
  3055. case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
  3056. if(bl->type==BL_PC) {
  3057. struct map_session_data *sd2=(struct map_session_data *)bl;
  3058. if(sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
  3059. sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
  3060. sd2->sc_data[SC_ENCPOISON].timer!=-1) {
  3061. clif_skill_nodamage(src,bl,skillid,skilllv,0);
  3062. clif_skill_fail(sd,skillid,0,0);
  3063. break;
  3064. }
  3065. }
  3066. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3067. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3068. break;
  3069. case LK_TENSIONRELAX: /* テンションリラックス */
  3070. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3071. pc_setsit(sd);
  3072. clif_sitting(sd);
  3073. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3074. break;
  3075. case LK_BERSERK: /* バ?サ?ク */
  3076. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3077. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3078. //sd->status.hp = sd->status.max_hp * 3;
  3079. break;
  3080. case MC_CHANGECART:
  3081. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3082. break;
  3083. case AC_CONCENTRATION: /* 集中力向上 */
  3084. {
  3085. int range = 1;
  3086. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3087. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3088. map_foreachinarea( skill_status_change_timer_sub,
  3089. src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
  3090. src,SkillStatusChangeTable[skillid],tick);
  3091. }
  3092. break;
  3093. case SM_PROVOKE: /* プロボック */
  3094. {
  3095. struct status_change *sc_data = battle_get_sc_data(bl);
  3096. /* MVPmobと不死には?かない */
  3097. if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には?かない
  3098. {
  3099. map_freeblock_unlock();
  3100. return 1;
  3101. }
  3102. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3103. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3104. if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害
  3105. skill_castcancel(bl,0);
  3106. if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg)
  3107. && dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2)
  3108. skill_castcancel(bl,0);
  3109. if(sc_data){
  3110. if(sc_data[SC_FREEZE].timer!=-1)
  3111. skill_status_change_end(bl,SC_FREEZE,-1);
  3112. if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
  3113. skill_status_change_end(bl,SC_STONE,-1);
  3114. if(sc_data[SC_SLEEP].timer!=-1)
  3115. skill_status_change_end(bl,SC_SLEEP,-1);
  3116. }
  3117. if(bl->type==BL_MOB) {
  3118. int range = skill_get_range(skillid,skilllv);
  3119. if(range < 0)
  3120. range = battle_get_range(src) - (range + 1);
  3121. mob_target((struct mob_data *)bl,src,range);
  3122. }
  3123. }
  3124. break;
  3125. case CR_DEVOTION: /* ディボ?ション */
  3126. if(sd && dstsd){
  3127. //?生や養子の場合の元の職業を算出する
  3128. struct pc_base_job dst_s_class = pc_calc_base_job(dstsd->status.class);
  3129. int lv = sd->status.base_level-dstsd->status.base_level;
  3130. lv = (lv<0)?-lv:lv;
  3131. if((dstsd->bl.type!=BL_PC) // 相手はPCじゃないとだめ
  3132. ||(sd->bl.id == dstsd->bl.id) // 相手が自分はだめ
  3133. ||(lv > 10) // レベル差±10まで
  3134. ||(!sd->status.party_id && !sd->status.guild_id) // PTにもギルドにも所?無しはだめ
  3135. ||((sd->status.party_id != dstsd->status.party_id) // 同じパ?ティ?か、
  3136. &&(sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ
  3137. ||(dst_s_class.job==14||dst_s_class.job==21)){ // クルセだめ
  3138. clif_skill_fail(sd,skillid,0,0);
  3139. map_freeblock_unlock();
  3140. return 1;
  3141. }
  3142. for(i=0;i<skilllv;i++){
  3143. if(!sd->dev.val1[i]){ // 空きがあったら入れる
  3144. sd->dev.val1[i] = bl->id;
  3145. sd->dev.val2[i] = bl->id;
  3146. break;
  3147. }else if(i==skilllv-1){ // 空きがなかった
  3148. clif_skill_fail(sd,skillid,0,0);
  3149. map_freeblock_unlock();
  3150. return 1;
  3151. }
  3152. }
  3153. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3154. clif_devotion(sd,bl->id);
  3155. skill_status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 );
  3156. }
  3157. else clif_skill_fail(sd,skillid,0,0);
  3158. break;
  3159. case MO_CALLSPIRITS: // ?功
  3160. if(sd) {
  3161. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3162. pc_addspiritball(sd,skill_get_time(skillid,skilllv),skilllv);
  3163. }
  3164. break;
  3165. case CH_SOULCOLLECT: // 狂?功
  3166. if(sd) {
  3167. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3168. for(i=0;i<5;i++)
  3169. pc_addspiritball(sd,skill_get_time(skillid,skilllv),5);
  3170. }
  3171. break;
  3172. case MO_BLADESTOP: // 白刃取り
  3173. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3174. skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3175. break;
  3176. case MO_ABSORBSPIRITS: // ?奪
  3177. i=0;
  3178. if(sd && dstsd) {
  3179. if(sd == dstsd || map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg) {
  3180. if(dstsd->spiritball > 0) {
  3181. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3182. i = dstsd->spiritball * 7;
  3183. pc_delspiritball(dstsd,dstsd->spiritball,0);
  3184. if(i > 0x7FFF)
  3185. i = 0x7FFF;
  3186. if(sd->status.sp + i > sd->status.max_sp)
  3187. i = sd->status.max_sp - sd->status.sp;
  3188. }
  3189. }
  3190. }else if(sd && dstmd){ //?象がモンスタ?の場合
  3191. //20%の確率で?象のLv*2のSPを回復する。成功したときはタ?ゲット(σ?Д?)σ????!!
  3192. if(rand()%100<20){
  3193. i=2*mob_db[dstmd->class].lv;
  3194. mob_target(dstmd,src,0);
  3195. }
  3196. }
  3197. if(i){
  3198. sd->status.sp += i;
  3199. clif_heal(sd->fd,SP_SP,i);
  3200. }
  3201. else
  3202. clif_skill_nodamage(src,bl,skillid,skilllv,0);
  3203. break;
  3204. case AC_MAKINGARROW: /* 矢作成 */
  3205. if(sd) {
  3206. clif_arrow_create_list(sd);
  3207. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3208. }
  3209. break;
  3210. case AM_PHARMACY: /* ポ?ション作成 */
  3211. if(sd) {
  3212. clif_skill_produce_mix_list(sd,32);
  3213. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3214. }
  3215. break;
  3216. case WS_CREATECOIN: /* クリエイトコイン */
  3217. if(sd) {
  3218. clif_skill_produce_mix_list(sd,64);
  3219. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3220. }
  3221. break;
  3222. case WS_CREATENUGGET: /* 塊製造 */
  3223. if(sd) {
  3224. clif_skill_produce_mix_list(sd,128);
  3225. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3226. }
  3227. break;
  3228. case ASC_CDP: // [DracoRPG]
  3229. // notes: success rate (from emperium.org) = 20 + [(20*Dex)/50] + [(20*Luk)/100]
  3230. if(sd) {
  3231. clif_skill_produce_mix_list(sd,256);
  3232. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3233. }
  3234. break;
  3235. case BS_HAMMERFALL: /* ハンマ?フォ?ル */
  3236. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3237. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
  3238. break;
  3239. if( rand()%100 < (20+ 10*skilllv)*sc_def_vit/100 ) {
  3240. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  3241. }
  3242. break;
  3243. case RG_RAID: /* サプライズアタック */
  3244. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3245. {
  3246. int x=bl->x,y=bl->y;
  3247. skill_area_temp[1]=bl->id;
  3248. skill_area_temp[2]=x;
  3249. skill_area_temp[3]=y;
  3250. map_foreachinarea(skill_area_sub,
  3251. bl->m,x-1,y-1,x+1,y+1,0,
  3252. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  3253. skill_castend_damage_id);
  3254. }
  3255. skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除
  3256. break;
  3257. case KN_BRANDISHSPEAR: /*ブランディッシュスピア*/
  3258. {
  3259. int c,n=4,ar;
  3260. int dir = map_calc_dir(src,bl->x,bl->y);
  3261. struct square tc;
  3262. int x=bl->x,y=bl->y;
  3263. ar=skilllv/3;
  3264. skill_brandishspear_first(&tc,dir,x,y);
  3265. skill_brandishspear_dir(&tc,dir,4);
  3266. /* 範?④ */
  3267. if(skilllv == 10){
  3268. for(c=1;c<4;c++){
  3269. map_foreachinarea(skill_area_sub,
  3270. bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],0,
  3271. src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
  3272. skill_castend_damage_id);
  3273. }
  3274. }
  3275. /* 範?③② */
  3276. if(skilllv > 6){
  3277. skill_brandishspear_dir(&tc,dir,-1);
  3278. n--;
  3279. }else{
  3280. skill_brandishspear_dir(&tc,dir,-2);
  3281. n-=2;
  3282. }
  3283. if(skilllv > 3){
  3284. for(c=0;c<5;c++){
  3285. map_foreachinarea(skill_area_sub,
  3286. bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],0,
  3287. src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
  3288. skill_castend_damage_id);
  3289. if(skilllv > 6 && n==3 && c==4){
  3290. skill_brandishspear_dir(&tc,dir,-1);
  3291. n--;c=-1;
  3292. }
  3293. }
  3294. }
  3295. /* 範?① */
  3296. for(c=0;c<10;c++){
  3297. if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1);
  3298. map_foreachinarea(skill_area_sub,
  3299. bl->m,tc.val1[c%5],tc.val2[c%5],tc.val1[c%5],tc.val2[c%5],0,
  3300. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  3301. skill_castend_damage_id);
  3302. }
  3303. }
  3304. break;
  3305. /* パ?ティスキル */
  3306. case AL_ANGELUS: /* エンジェラス */
  3307. case PR_MAGNIFICAT: /* マグニフィカ?ト */
  3308. case PR_GLORIA: /* グロリア */
  3309. case SN_WINDWALK: /* ウインドウォ?ク */
  3310. if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
  3311. /* 個別の?理 */
  3312. clif_skill_nodamage(bl,bl,skillid,skilllv,1);
  3313. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3314. break;
  3315. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3316. }
  3317. else{
  3318. /* パ?ティ全?への?理 */
  3319. party_foreachsamemap(skill_area_sub,
  3320. sd,1,
  3321. src,skillid,skilllv,tick, flag|BCT_PARTY|1,
  3322. skill_castend_nodamage_id);
  3323. }
  3324. break;
  3325. case BS_ADRENALINE: /* アドレナリンラッシュ */
  3326. case BS_WEAPONPERFECT: /* ウェポンパ?フェクション */
  3327. case BS_OVERTHRUST: /* オ?バ?トラスト */
  3328. if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
  3329. /* 個別の?理 */
  3330. clif_skill_nodamage(bl,bl,skillid,skilllv,1);
  3331. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
  3332. }
  3333. else{
  3334. /* パ?ティ全?への?理 */
  3335. party_foreachsamemap(skill_area_sub,
  3336. sd,1,
  3337. src,skillid,skilllv,tick, flag|BCT_PARTY|1,
  3338. skill_castend_nodamage_id);
  3339. }
  3340. break;
  3341. /*(付加と解除が必要) */
  3342. case BS_MAXIMIZE: /* マキシマイズパワ? */
  3343. case NV_TRICKDEAD: /* 死んだふり */
  3344. case CR_DEFENDER: /* ディフェンダ? */
  3345. case CR_AUTOGUARD: /* オ?トガ?ド */
  3346. {
  3347. struct status_change *tsc_data = battle_get_sc_data(bl);
  3348. int sc=SkillStatusChangeTable[skillid];
  3349. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3350. if( tsc_data ){
  3351. if( tsc_data[sc].timer==-1 )
  3352. /* 付加する */
  3353. skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3354. else
  3355. /* 解除する */
  3356. skill_status_change_end(bl, sc, -1);
  3357. }
  3358. }
  3359. break;
  3360. case TF_HIDING: /* ハイディング */
  3361. {
  3362. struct status_change *tsc_data = battle_get_sc_data(bl);
  3363. int sc=SkillStatusChangeTable[skillid];
  3364. clif_skill_nodamage(src,bl,skillid,-1,1);
  3365. if(tsc_data && tsc_data[sc].timer!=-1 )
  3366. /* 解除する */
  3367. skill_status_change_end(bl, sc, -1);
  3368. else
  3369. /* 付加する */
  3370. skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3371. }
  3372. break;
  3373. case AS_CLOAKING: /* クロ?キング */
  3374. {
  3375. struct status_change *tsc_data = battle_get_sc_data(bl);
  3376. int sc=SkillStatusChangeTable[skillid];
  3377. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3378. if(tsc_data && tsc_data[sc].timer!=-1 )
  3379. /* 解除する */
  3380. skill_status_change_end(bl, sc, -1);
  3381. else
  3382. /* 付加する */
  3383. skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3384. //skill_check_cloaking(bl);
  3385. }
  3386. break;
  3387. case ST_CHASEWALK: /* ハイディング */
  3388. {
  3389. struct status_change *tsc_data = battle_get_sc_data(bl);
  3390. int sc=SkillStatusChangeTable[skillid];
  3391. clif_skill_nodamage(src,bl,skillid,-1,1);
  3392. if(tsc_data && tsc_data[sc].timer!=-1 )
  3393. /* 解除する */
  3394. skill_status_change_end(bl, sc, -1);
  3395. else
  3396. /* 付加する */
  3397. skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3398. }
  3399. break;
  3400. /* ?地スキル */
  3401. case BD_LULLABY: /* 子守唄 */
  3402. case BD_RICHMANKIM: /* ニヨルドの宴 */
  3403. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  3404. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  3405. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  3406. case BD_ROKISWEIL: /* ロキの叫び */
  3407. case BD_INTOABYSS: /* 深淵の中に */
  3408. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  3409. case BA_DISSONANCE: /* 不協和音 */
  3410. case BA_POEMBRAGI: /* ブラギの詩 */
  3411. case BA_WHISTLE: /* 口笛 */
  3412. case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
  3413. case BA_APPLEIDUN: /* イドゥンの林檎 */
  3414. case DC_UGLYDANCE: /* 自分勝手なダンス */
  3415. case DC_HUMMING: /* ハミング */
  3416. case DC_DONTFORGETME: /* 私を忘れないで… */
  3417. case DC_FORTUNEKISS: /* 幸運のキス */
  3418. case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
  3419. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  3420. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3421. skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
  3422. break;
  3423. case HP_BASILICA: /* バジリカ */
  3424. {
  3425. // cancel Basilica if already in effect
  3426. struct status_change *sc_data = battle_get_sc_data(src);
  3427. if(sc_data && sc_data[SC_BASILICA].timer != -1){
  3428. struct skill_unit *su;
  3429. if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
  3430. struct skill_unit_group *sg;
  3431. if ((sg = su->group) && sg->src_id == sd->bl.id) {
  3432. skill_status_change_end(src,SC_BASILICA,-1);
  3433. skill_delunitgroup (sg);
  3434. break;
  3435. }
  3436. }
  3437. } else {
  3438. // otherwise allow casting
  3439. skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
  3440. skill_clear_unitgroup(src);
  3441. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3442. skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
  3443. }
  3444. }
  3445. break;
  3446. case PA_GOSPEL: /* ゴスペル */
  3447. skill_clear_unitgroup(src);
  3448. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3449. skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
  3450. break;
  3451. case BD_ADAPTATION: /* アドリブ */
  3452. {
  3453. struct status_change *sc_data = battle_get_sc_data(src);
  3454. if(sc_data && sc_data[SC_DANCING].timer!=-1){
  3455. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3456. skill_stop_dancing(src,0);
  3457. }
  3458. }
  3459. break;
  3460. case BA_FROSTJOKE: /* 寒いジョ?ク */
  3461. case DC_SCREAM: /* スクリ?ム */
  3462. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3463. skill_addtimerskill(src,tick+3000,bl->id,0,0,skillid,skilllv,0,flag);
  3464. break;
  3465. case TF_STEAL: // スティ?ル
  3466. if(sd) {
  3467. if(pc_steal_item(sd,bl))
  3468. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3469. else
  3470. clif_skill_fail(sd,skillid,0x0a,0);
  3471. }
  3472. break;
  3473. case RG_STEALCOIN: // スティ?ルコイン
  3474. if(sd) {
  3475. if(pc_steal_coin(sd,bl)) {
  3476. int range = skill_get_range(skillid,skilllv);
  3477. if(range < 0)
  3478. range = battle_get_range(src) - (range + 1);
  3479. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3480. mob_target((struct mob_data *)bl,src,range);
  3481. }
  3482. else
  3483. clif_skill_fail(sd,skillid,0,0);
  3484. }
  3485. break;
  3486. case MG_STONECURSE: /* スト?ンカ?ス */
  3487. {
  3488. // Level 6-10 doesn't consume a red gem if it fails [celest]
  3489. int i, gem_flag = 1;
  3490. if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) {
  3491. clif_skill_fail(sd,sd->skillid,0,0);
  3492. break;
  3493. }
  3494. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3495. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3496. break;
  3497. if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
  3498. skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  3499. else if(sd) {
  3500. if (skilllv > 5) gem_flag = 0;
  3501. clif_skill_fail(sd,skillid,0,0);
  3502. }
  3503. if (dstmd)
  3504. mob_target(dstmd,src,skill_get_range(skillid,skilllv));
  3505. if (sd && gem_flag) {
  3506. if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
  3507. clif_skill_fail(sd,sd->skillid,0,0);
  3508. break;
  3509. }
  3510. pc_delitem(sd, i, skill_db[skillid].amount[0], 0);
  3511. }
  3512. }
  3513. break;
  3514. case NV_FIRSTAID: /* ?急手? */
  3515. clif_skill_nodamage(src,bl,skillid,5,1);
  3516. battle_heal(NULL,bl,5,0,0);
  3517. break;
  3518. case AL_CURE: /* キュア? */
  3519. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3520. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3521. break;
  3522. skill_status_change_end(bl, SC_SILENCE , -1 );
  3523. skill_status_change_end(bl, SC_BLIND , -1 );
  3524. skill_status_change_end(bl, SC_CONFUSION, -1 );
  3525. if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇?果
  3526. skill_status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
  3527. }
  3528. break;
  3529. case TF_DETOXIFY: /* 解毒 */
  3530. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3531. skill_status_change_end(bl, SC_POISON , -1 );
  3532. skill_status_change_end(bl, SC_DPOISON , -1 );
  3533. break;
  3534. case PR_STRECOVERY: /* リカバリ? */
  3535. {
  3536. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3537. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3538. break;
  3539. skill_status_change_end(bl, SC_FREEZE , -1 );
  3540. skill_status_change_end(bl, SC_STONE , -1 );
  3541. skill_status_change_end(bl, SC_SLEEP , -1 );
  3542. skill_status_change_end(bl, SC_STAN , -1 );
  3543. if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇?果
  3544. int blind_time;
  3545. //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15;
  3546. blind_time=30*(100-(battle_get_int(bl)+battle_get_vit(bl))/2)/100;
  3547. if(rand()%100 < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10)))
  3548. skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0);
  3549. }
  3550. if(dstmd){
  3551. dstmd->attacked_id=0;
  3552. dstmd->target_id=0;
  3553. dstmd->state.targettype = NONE_ATTACKABLE;
  3554. dstmd->state.skillstate=MSS_IDLE;
  3555. dstmd->next_walktime=tick+rand()%3000+3000;
  3556. }
  3557. }
  3558. break;
  3559. case WZ_ESTIMATION: /* モンスタ?情報 */
  3560. if(src->type==BL_PC){
  3561. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3562. clif_skill_estimation((struct map_session_data *)src,bl);
  3563. }
  3564. break;
  3565. case MC_IDENTIFY: /* アイテム鑑定 */
  3566. if(sd)
  3567. clif_item_identify_list(sd);
  3568. break;
  3569. case BS_REPAIRWEAPON: /* 武器修理 */
  3570. if(sd) {
  3571. //動作しないのでとりあえずコメントアウト
  3572. /*if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!)
  3573. clif_skill_fail(sd,sd->skillid,0,0);
  3574. map_freeblock_unlock();
  3575. return 1;
  3576. }*/
  3577. clif_item_repair_list(sd);
  3578. }
  3579. break;
  3580. case MC_VENDING: /* 露店開設 */
  3581. if(sd)
  3582. clif_openvendingreq(sd,2+sd->skilllv);
  3583. break;
  3584. case AL_TELEPORT: /* テレポ?ト */
  3585. if( sd ){
  3586. if(map[sd->bl.m].flag.noteleport){ /* テレポ禁止 */
  3587. clif_skill_teleportmessage(sd,0);
  3588. break;
  3589. }
  3590. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3591. if( sd->skilllv==1 )
  3592. clif_skill_warppoint(sd,sd->skillid,"Random","","","");
  3593. else{
  3594. clif_skill_warppoint(sd,sd->skillid,"Random",
  3595. sd->status.save_point.map,"","");
  3596. }
  3597. }else if( bl->type==BL_MOB )
  3598. mob_warp((struct mob_data *)bl,-1,-1,-1,3);
  3599. break;
  3600. case AL_HOLYWATER: /* アクアベネディクタ */
  3601. if(sd) {
  3602. int eflag;
  3603. struct item item_tmp;
  3604. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3605. memset(&item_tmp,0,sizeof(item_tmp));
  3606. item_tmp.nameid = 523;
  3607. item_tmp.identify = 1;
  3608. if(battle_config.holywater_name_input) {
  3609. item_tmp.card[0] = 0xfe;
  3610. item_tmp.card[1] = 0;
  3611. *((unsigned long *)(&item_tmp.card[2]))=sd->char_id; /* キャラID */
  3612. }
  3613. eflag = pc_additem(sd,&item_tmp,1);
  3614. if(eflag) {
  3615. clif_additem(sd,0,0,eflag);
  3616. map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  3617. }
  3618. }
  3619. break;
  3620. case TF_PICKSTONE:
  3621. if(sd) {
  3622. int eflag;
  3623. struct item item_tmp;
  3624. struct block_list tbl;
  3625. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3626. memset(&item_tmp,0,sizeof(item_tmp));
  3627. memset(&tbl,0,sizeof(tbl)); // [MouseJstr]
  3628. item_tmp.nameid = 7049;
  3629. item_tmp.identify = 1;
  3630. tbl.id = 0;
  3631. clif_takeitem(&sd->bl,&tbl);
  3632. eflag = pc_additem(sd,&item_tmp,1);
  3633. if(eflag) {
  3634. clif_additem(sd,0,0,eflag);
  3635. map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  3636. }
  3637. }
  3638. break;
  3639. case RG_STRIPWEAPON: /* ストリップウェポン */
  3640. {
  3641. struct status_change *tsc_data = battle_get_sc_data(bl);
  3642. if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 )
  3643. break;
  3644. strip_per = 5+2*skilllv+strip_fix/5;
  3645. strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
  3646. if(rand()%100 < strip_per){
  3647. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3648. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
  3649. if(dstsd){
  3650. for(i=0;i<MAX_INVENTORY;i++){
  3651. if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){
  3652. pc_unequipitem(dstsd,i,3);
  3653. break;
  3654. }
  3655. }
  3656. }
  3657. }
  3658. }
  3659. break;
  3660. case RG_STRIPSHIELD: /* ストリップシ?ルド */
  3661. {
  3662. struct status_change *tsc_data = battle_get_sc_data(bl);
  3663. if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 )
  3664. break;
  3665. strip_per = 5+2*skilllv+strip_fix/5;
  3666. strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
  3667. if(rand()%100 < strip_per){
  3668. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3669. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
  3670. if(dstsd){
  3671. for(i=0;i<MAX_INVENTORY;i++){
  3672. if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){
  3673. pc_unequipitem(dstsd,i,3);
  3674. break;
  3675. }
  3676. }
  3677. }
  3678. }
  3679. }
  3680. break;
  3681. case RG_STRIPARMOR: /* ストリップア?マ? */
  3682. {
  3683. struct status_change *tsc_data = battle_get_sc_data(bl);
  3684. if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 )
  3685. break;
  3686. strip_per = 5+2*skilllv+strip_fix/5;
  3687. strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
  3688. if(rand()%100 < strip_per){
  3689. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3690. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
  3691. if(dstsd){
  3692. for(i=0;i<MAX_INVENTORY;i++){
  3693. if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){
  3694. pc_unequipitem(dstsd,i,3);
  3695. break;
  3696. }
  3697. }
  3698. }
  3699. }
  3700. }
  3701. break;
  3702. case RG_STRIPHELM: /* ストリップヘルム */
  3703. {
  3704. struct status_change *tsc_data = battle_get_sc_data(bl);
  3705. if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 )
  3706. break;
  3707. strip_per = 5+2*skilllv+strip_fix/5;
  3708. strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
  3709. if(rand()%100 < strip_per){
  3710. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3711. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
  3712. if(dstsd){
  3713. for(i=0;i<MAX_INVENTORY;i++){
  3714. if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){
  3715. pc_unequipitem(dstsd,i,3);
  3716. break;
  3717. }
  3718. }
  3719. }
  3720. }
  3721. }
  3722. break;
  3723. // Full Strip [Celest]
  3724. case ST_FULLSTRIP:
  3725. {
  3726. struct status_change *tsc_data = battle_get_sc_data(bl);
  3727. int c=0, i, j;
  3728. int striplist[2][4] = { { 0, 0, 0, 0 },
  3729. { 0x0002, 0x0020, 0x0010, 0x0100 } };
  3730. strip_per = 5+2*skilllv+strip_fix/5;
  3731. strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
  3732. for (i=0; i<4; i++) {
  3733. if(tsc_data && tsc_data[SC_CP_WEAPON + i].timer != -1)
  3734. break;
  3735. if(rand()%100 < strip_per) {
  3736. striplist[0][i] = 1;
  3737. c++;
  3738. }
  3739. }
  3740. if (c > 0) {
  3741. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3742. for (j=0; j<4 && c > 0; j++) {
  3743. if (striplist[0][j]) {
  3744. skill_status_change_start(bl,SC_STRIPWEAPON + i,skilllv,0,0,0,strip_time,0 );
  3745. if(dstsd){
  3746. for(i=0;i<MAX_INVENTORY;i++){
  3747. if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & striplist[1][j]){
  3748. pc_unequipitem(dstsd,i,3);
  3749. --c;
  3750. break;
  3751. }
  3752. }
  3753. }
  3754. }
  3755. }
  3756. }
  3757. }
  3758. break;
  3759. /* PotionPitcher */
  3760. case AM_POTIONPITCHER: /* ポ?ションピッチャ? */
  3761. {
  3762. struct block_list tbl;
  3763. int i,x,hp = 0,sp = 0;
  3764. if(sd) {
  3765. if(sd==dstsd) { // cancel use on oneself
  3766. map_freeblock_unlock();
  3767. return 1;
  3768. }
  3769. x = skilllv%11 - 1;
  3770. i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
  3771. if(i < 0 || skill_db[skillid].itemid[x] <= 0) {
  3772. clif_skill_fail(sd,skillid,0,0);
  3773. map_freeblock_unlock();
  3774. return 1;
  3775. }
  3776. if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
  3777. clif_skill_fail(sd,skillid,0,0);
  3778. map_freeblock_unlock();
  3779. return 1;
  3780. }
  3781. sd->state.potionpitcher_flag = 1;
  3782. sd->potion_hp = sd->potion_sp = sd->potion_per_hp = sd->potion_per_sp = 0;
  3783. sd->skilltarget = bl->id;
  3784. run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
  3785. pc_delitem(sd,i,skill_db[skillid].amount[x],0);
  3786. sd->state.potionpitcher_flag = 0;
  3787. if(sd->potion_per_hp > 0 || sd->potion_per_sp > 0) {
  3788. hp = battle_get_max_hp(bl) * sd->potion_per_hp / 100;
  3789. hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
  3790. if(dstsd) {
  3791. sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
  3792. sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
  3793. }
  3794. }
  3795. else {
  3796. if(sd->potion_hp > 0) {
  3797. hp = sd->potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
  3798. hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
  3799. if(dstsd)
  3800. hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
  3801. }
  3802. if(sd->potion_sp > 0) {
  3803. sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
  3804. sp = sp * (100 + (battle_get_int(bl)<<1)) / 100;
  3805. if(dstsd)
  3806. sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
  3807. }
  3808. }
  3809. }
  3810. else {
  3811. hp = (1 + rand()%400) * (100 + skilllv*10) / 100;
  3812. hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
  3813. if(dstsd)
  3814. hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
  3815. }
  3816. tbl.id = 0;
  3817. tbl.m = src->m;
  3818. tbl.x = src->x;
  3819. tbl.y = src->y;
  3820. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3821. if(hp > 0 || (hp <= 0 && sp <= 0))
  3822. clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1);
  3823. if(sp > 0)
  3824. clif_skill_nodamage(&tbl,bl,MG_SRECOVERY,sp,1);
  3825. battle_heal(src,bl,hp,sp,0);
  3826. }
  3827. break;
  3828. case AM_CP_WEAPON:
  3829. {
  3830. struct status_change *tsc_data = battle_get_sc_data(bl);
  3831. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3832. if(tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1)
  3833. skill_status_change_end(bl, SC_STRIPWEAPON, -1 );
  3834. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3835. }
  3836. break;
  3837. case AM_CP_SHIELD:
  3838. {
  3839. struct status_change *tsc_data = battle_get_sc_data(bl);
  3840. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3841. if(tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1)
  3842. skill_status_change_end(bl, SC_STRIPSHIELD, -1 );
  3843. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3844. }
  3845. break;
  3846. case AM_CP_ARMOR:
  3847. {
  3848. struct status_change *tsc_data = battle_get_sc_data(bl);
  3849. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3850. if(tsc_data && tsc_data[SC_STRIPARMOR].timer != -1)
  3851. skill_status_change_end(bl, SC_STRIPARMOR, -1 );
  3852. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3853. }
  3854. break;
  3855. case AM_CP_HELM:
  3856. {
  3857. struct status_change *tsc_data = battle_get_sc_data(bl);
  3858. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3859. if(tsc_data && tsc_data[SC_STRIPHELM].timer != -1)
  3860. skill_status_change_end(bl, SC_STRIPHELM, -1 );
  3861. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3862. }
  3863. break;
  3864. case SA_DISPELL: /* ディスペル */
  3865. {
  3866. int i;
  3867. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3868. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3869. break;
  3870. for(i=0;i<136;i++){
  3871. if(i==SC_RIDING || i== SC_FALCON || i==SC_HALLUCINATION || i==SC_WEIGHT50
  3872. || i==SC_WEIGHT90 || i==SC_STRIPWEAPON || i==SC_STRIPSHIELD || i==SC_STRIPARMOR
  3873. || i==SC_STRIPHELM || i==SC_CP_WEAPON || i==SC_CP_SHIELD || i==SC_CP_ARMOR
  3874. || i==SC_CP_HELM || i==SC_COMBO)
  3875. continue;
  3876. skill_status_change_end(bl,i,-1);
  3877. }
  3878. }
  3879. break;
  3880. case TF_BACKSLIDING: /* バックステップ */
  3881. battle_stopwalking(src,1);
  3882. skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)|0x10000);
  3883. if(src->type == BL_MOB)
  3884. clif_fixmobpos((struct mob_data *)src);
  3885. else if(src->type == BL_PET)
  3886. clif_fixpetpos((struct pet_data *)src);
  3887. else if(src->type == BL_PC)
  3888. clif_fixpos(src);
  3889. skill_addtimerskill(src,tick + 200,src->id,0,0,skillid,skilllv,0,flag);
  3890. break;
  3891. case SA_CASTCANCEL:
  3892. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3893. skill_castcancel(src,1);
  3894. if(sd) {
  3895. int sp = skill_get_sp(sd->skillid_old,sd->skilllv_old);
  3896. sp = sp * (90 - (skilllv-1)*20) / 100;
  3897. if(sp < 0) sp = 0;
  3898. pc_heal(sd,0,-sp);
  3899. }
  3900. break;
  3901. case SA_SPELLBREAKER: // スペルブレイカ?
  3902. {
  3903. struct status_change *sc_data = battle_get_sc_data(bl);
  3904. int sp;
  3905. if(sc_data && sc_data[SC_MAGICROD].timer != -1) {
  3906. if(dstsd) {
  3907. sp = skill_get_sp(skillid,skilllv);
  3908. sp = sp * sc_data[SC_MAGICROD].val2 / 100;
  3909. if(sp > 0x7fff) sp = 0x7fff;
  3910. else if(sp < 1) sp = 1;
  3911. if(dstsd->status.sp + sp > dstsd->status.max_sp) {
  3912. sp = dstsd->status.max_sp - dstsd->status.sp;
  3913. dstsd->status.sp = dstsd->status.max_sp;
  3914. }
  3915. else
  3916. dstsd->status.sp += sp;
  3917. clif_heal(dstsd->fd,SP_SP,sp);
  3918. }
  3919. clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1);
  3920. if(sd) {
  3921. sp = sd->status.max_sp/5;
  3922. if(sp < 1) sp = 1;
  3923. pc_heal(sd,0,-sp);
  3924. }
  3925. }
  3926. else {
  3927. int bl_skillid=0,bl_skilllv=0;
  3928. if(bl->type == BL_PC) {
  3929. if(dstsd && dstsd->skilltimer != -1) {
  3930. bl_skillid = dstsd->skillid;
  3931. bl_skilllv = dstsd->skilllv;
  3932. }
  3933. }
  3934. else if(bl->type == BL_MOB) {
  3935. if(dstmd && dstmd->skilltimer != -1) {
  3936. bl_skillid = dstmd->skillid;
  3937. bl_skilllv = dstmd->skilllv;
  3938. }
  3939. }
  3940. if(bl_skillid > 0 && skill_db[bl_skillid].skill_type == BF_MAGIC) {
  3941. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3942. skill_castcancel(bl,0);
  3943. sp = skill_get_sp(bl_skillid,bl_skilllv);
  3944. if(dstsd)
  3945. pc_heal(dstsd,0,-sp);
  3946. if(sd) {
  3947. sp = sp*(25*(skilllv-1))/100;
  3948. if(skilllv > 1 && sp < 1) sp = 1;
  3949. if(sp > 0x7fff) sp = 0x7fff;
  3950. else if(sp < 1) sp = 1;
  3951. if(sd->status.sp + sp > sd->status.max_sp) {
  3952. sp = sd->status.max_sp - sd->status.sp;
  3953. sd->status.sp = sd->status.max_sp;
  3954. }
  3955. else
  3956. sd->status.sp += sp;
  3957. clif_heal(sd->fd,SP_SP,sp);
  3958. }
  3959. }
  3960. else if(sd)
  3961. clif_skill_fail(sd,skillid,0,0);
  3962. }
  3963. }
  3964. break;
  3965. case SA_MAGICROD:
  3966. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  3967. break;
  3968. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  3969. break;
  3970. case SA_AUTOSPELL: /* オ?トスペル */
  3971. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  3972. if(sd)
  3973. clif_autospell(sd,skilllv);
  3974. else {
  3975. int maxlv=1,spellid=0;
  3976. static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT };
  3977. if(skilllv >= 10) {
  3978. spellid = MG_FROSTDIVER;
  3979. maxlv = skilllv - 9;
  3980. }
  3981. else if(skilllv >=8) {
  3982. spellid = MG_FIREBALL;
  3983. maxlv = skilllv - 7;
  3984. }
  3985. else if(skilllv >=5) {
  3986. spellid = MG_SOULSTRIKE;
  3987. maxlv = skilllv - 4;
  3988. }
  3989. else if(skilllv >=2) {
  3990. int i = rand()%3;
  3991. spellid = spellarray[i];
  3992. maxlv = skilllv - 1;
  3993. }
  3994. else if(skilllv > 0) {
  3995. spellid = MG_NAPALMBEAT;
  3996. maxlv = 3;
  3997. }
  3998. if(spellid > 0)
  3999. skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
  4000. skill_get_time(SA_AUTOSPELL,skilllv),0);
  4001. }
  4002. break;
  4003. /* ランダム?性?化、水?性?化、地、火、風 */
  4004. case NPC_ATTRICHANGE:
  4005. case NPC_CHANGEWATER:
  4006. case NPC_CHANGEGROUND:
  4007. case NPC_CHANGEFIRE:
  4008. case NPC_CHANGEWIND:
  4009. /* 毒、聖、念、闇 */
  4010. case NPC_CHANGEPOISON:
  4011. case NPC_CHANGEHOLY:
  4012. case NPC_CHANGEDARKNESS:
  4013. case NPC_CHANGETELEKINESIS:
  4014. if(md){
  4015. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4016. md->def_ele=skill_get_pl(skillid);
  4017. if(md->def_ele==0) /* ランダム?化、ただし、*/
  4018. md->def_ele=rand()%10; /* 不死?性は除く */
  4019. md->def_ele+=(1+rand()%4)*20; /* ?性レベルはランダム */
  4020. }
  4021. break;
  4022. case NPC_PROVOCATION:
  4023. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4024. if(md)
  4025. clif_pet_performance(src,mob_db[md->class].skill[md->skillidx].val[0]);
  4026. break;
  4027. case NPC_HALLUCINATION:
  4028. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4029. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  4030. break;
  4031. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  4032. break;
  4033. case NPC_KEEPING:
  4034. case NPC_BARRIER:
  4035. {
  4036. int skill_time = skill_get_time(skillid,skilllv);
  4037. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4038. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
  4039. if (src->type == BL_MOB)
  4040. mob_changestate((struct mob_data *)src,MS_DELAY,skill_time);
  4041. else if (src->type == BL_PC)
  4042. sd->attackabletime = sd->canmove_tick = tick + skill_time;
  4043. }
  4044. break;
  4045. case NPC_DARKBLESSING:
  4046. {
  4047. int sc_def = 100 - battle_get_mdef(bl);
  4048. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4049. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  4050. break;
  4051. if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6)
  4052. break;
  4053. if(rand()%100 < sc_def*(50+skilllv*5)/100) {
  4054. if(dstsd) {
  4055. int hp = battle_get_hp(bl)-1;
  4056. pc_heal(dstsd,-hp,0);
  4057. }
  4058. else if(dstmd)
  4059. dstmd->hp = 1;
  4060. }
  4061. }
  4062. break;
  4063. case NPC_SELFDESTRUCTION: /* 自爆 */
  4064. case NPC_SELFDESTRUCTION2: /* 自爆2 */
  4065. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0);
  4066. break;
  4067. case NPC_LICK:
  4068. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4069. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
  4070. break;
  4071. if(dstsd)
  4072. pc_heal(dstsd,0,-100);
  4073. if(rand()%100 < (skilllv*5)*sc_def_vit/100)
  4074. skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
  4075. break;
  4076. case NPC_SUICIDE: /* 自決 */
  4077. if(src && bl){
  4078. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4079. if (md)
  4080. mob_damage(NULL,md,md->hp,0);
  4081. else if (sd)
  4082. pc_damage(NULL,sd,sd->status.hp);
  4083. }
  4084. break;
  4085. case NPC_SUMMONSLAVE: /* 手下召喚 */
  4086. case NPC_SUMMONMONSTER: /* MOB召喚 */
  4087. if(md)
  4088. mob_summonslave(md,mob_db[md->class].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0);
  4089. break;
  4090. case NPC_TRANSFORMATION:
  4091. case NPC_METAMORPHOSIS:
  4092. if(md)
  4093. mob_class_change(md,mob_db[md->class].skill[md->skillidx].val);
  4094. break;
  4095. case NPC_EMOTION: /* エモ?ション */
  4096. if(md)
  4097. clif_emotion(&md->bl,mob_db[md->class].skill[md->skillidx].val[0]);
  4098. break;
  4099. case NPC_DEFENDER:
  4100. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4101. break;
  4102. // Equipment breaking monster skills [Celest]
  4103. case NPC_BREAKWEAPON:
  4104. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4105. if(bl->type == BL_PC && rand()%100 < skilllv && battle_config.equipment_breaking)
  4106. pc_breakweapon((struct map_session_data *)bl);
  4107. break;
  4108. case NPC_BREAKARMOR:
  4109. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4110. if(bl->type == BL_PC && rand()%100 < skilllv && battle_config.equipment_breaking)
  4111. pc_breakarmor((struct map_session_data *)bl);
  4112. break;
  4113. case NPC_BREAKHELM:
  4114. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4115. if(bl->type == BL_PC && rand()%100 < skilllv && battle_config.equipment_breaking)
  4116. // since we don't have any code for helm breaking yet...
  4117. pc_breakweapon((struct map_session_data *)bl);
  4118. break;
  4119. case NPC_BREAKSHIELD:
  4120. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4121. if(bl->type == BL_PC && rand()%100 < skilllv && battle_config.equipment_breaking)
  4122. // since we don't have any code for helm breaking yet...
  4123. pc_breakweapon((struct map_session_data *)bl);
  4124. break;
  4125. case WE_MALE: /* 君だけは護るよ */
  4126. if(sd && dstsd){
  4127. int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1];
  4128. int gain_hp=sd->status.max_hp*abs(hp_rate)/100;// 15%
  4129. clif_skill_nodamage(src,bl,skillid,gain_hp,1);
  4130. battle_heal(NULL,bl,gain_hp,0,0);
  4131. }
  4132. break;
  4133. case WE_FEMALE: /* あなたの?に?牲になります */
  4134. if(sd && dstsd){
  4135. int sp_rate=(skilllv <= 0)? 0:skill_db[skillid].sp_rate[skilllv-1];
  4136. int gain_sp=sd->status.max_sp*abs(sp_rate)/100;// 15%
  4137. clif_skill_nodamage(src,bl,skillid,gain_sp,1);
  4138. battle_heal(NULL,bl,0,gain_sp,0);
  4139. }
  4140. break;
  4141. case WE_CALLPARTNER: /* あなたに?いたい */
  4142. if(sd && dstsd){
  4143. if((dstsd = pc_get_partner(sd)) == NULL){
  4144. clif_skill_fail(sd,skillid,0,0);
  4145. return 0;
  4146. }
  4147. if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
  4148. clif_skill_teleportmessage(sd,1);
  4149. return 0;
  4150. }
  4151. skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0);
  4152. }
  4153. break;
  4154. case PF_HPCONVERSION: /* ライフ置き換え */
  4155. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4156. if(sd){
  4157. int conv_hp=0,conv_sp=0;
  4158. conv_hp=sd->status.hp/10; //基本はHPの10%
  4159. sd->status.hp -= conv_hp; //HPを減らす
  4160. conv_sp=conv_hp*10*skilllv/100;
  4161. conv_sp=(sd->status.sp+conv_sp>sd->status.max_sp)?sd->status.max_sp-sd->status.sp:conv_sp;
  4162. sd->status.sp += conv_sp; //SPを?やす
  4163. pc_heal(sd,-conv_hp,conv_sp);
  4164. clif_heal(sd->fd,SP_SP,conv_sp);
  4165. }
  4166. break;
  4167. case HT_REMOVETRAP: /* リム?ブトラップ */
  4168. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4169. {
  4170. struct skill_unit *su=NULL;
  4171. struct item item_tmp;
  4172. int flag;
  4173. if((bl->type==BL_SKILL) &&
  4174. (su=(struct skill_unit *)bl) &&
  4175. (su->group->src_id == src->id || map[bl->m].flag.pvp || map[bl->m].flag.gvg) &&
  4176. (su->group->unit_id >= 0x8f && su->group->unit_id <= 0x99) &&
  4177. (su->group->unit_id != 0x92)){ //?を取り返す
  4178. if(sd){
  4179. if(battle_config.skill_removetrap_type == 1){
  4180. for(i=0;i<10;i++) {
  4181. if(skill_db[su->group->skill_id].itemid[i] > 0){
  4182. memset(&item_tmp,0,sizeof(item_tmp));
  4183. item_tmp.nameid = skill_db[su->group->skill_id].itemid[i];
  4184. item_tmp.identify = 1;
  4185. if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){
  4186. clif_additem(sd,0,0,flag);
  4187. map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  4188. }
  4189. }
  4190. }
  4191. }else{
  4192. memset(&item_tmp,0,sizeof(item_tmp));
  4193. item_tmp.nameid = 1065;
  4194. item_tmp.identify = 1;
  4195. if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1))){
  4196. clif_additem(sd,0,0,flag);
  4197. map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  4198. }
  4199. }
  4200. }
  4201. if(su->group->unit_id == 0x91 && su->group->val2){
  4202. struct block_list *target=map_id2bl(su->group->val2);
  4203. if(target && (target->type == BL_PC || target->type == BL_MOB))
  4204. skill_status_change_end(target,SC_ANKLE,-1);
  4205. }
  4206. skill_delunit(su);
  4207. }
  4208. }
  4209. break;
  4210. case HT_SPRINGTRAP: /* スプリングトラップ */
  4211. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4212. {
  4213. struct skill_unit *su=NULL;
  4214. if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){
  4215. switch(su->group->unit_id){
  4216. case 0x8f: /* ブラストマイン */
  4217. case 0x90: /* スキッドトラップ */
  4218. case 0x93: /* ランドマイン */
  4219. case 0x94: /* ショックウェ?ブトラップ */
  4220. case 0x95: /* サンドマン */
  4221. case 0x96: /* フラッシャ? */
  4222. case 0x97: /* フリ?ジングトラップ */
  4223. case 0x98: /* クレイモア?トラップ */
  4224. case 0x99: /* ト?キ?ボックス */
  4225. su->group->unit_id = 0x8c;
  4226. clif_changelook(bl,LOOK_BASE,su->group->unit_id);
  4227. su->group->limit=DIFF_TICK(tick+1500,su->group->tick);
  4228. su->limit=DIFF_TICK(tick+1500,su->group->tick);
  4229. }
  4230. }
  4231. }
  4232. break;
  4233. case BD_ENCORE: /* アンコ?ル */
  4234. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4235. if(sd)
  4236. skill_use_id(sd,src->id,sd->skillid_dance,sd->skilllv_dance);
  4237. break;
  4238. case AS_SPLASHER: /* ベナムスプラッシャ? */
  4239. if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HPが2/3以上?っていたら失敗
  4240. return 1;
  4241. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4242. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000,0 );
  4243. break;
  4244. case PF_MINDBREAKER: /* プロボック */
  4245. {
  4246. struct status_change *sc_data = battle_get_sc_data(bl);
  4247. /* MVPmobと不死には?かない */
  4248. if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には?かない
  4249. {
  4250. map_freeblock_unlock();
  4251. return 1;
  4252. }
  4253. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4254. skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
  4255. if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害
  4256. skill_castcancel(bl,0);
  4257. if(dstsd && dstsd->skilltimer!=-1 && (!dstsd->special_state.no_castcancel || map[bl->m].flag.gvg)
  4258. && dstsd->state.skillcastcancel && !dstsd->special_state.no_castcancel2)
  4259. skill_castcancel(bl,0);
  4260. if(sc_data){
  4261. if(sc_data[SC_FREEZE].timer!=-1)
  4262. skill_status_change_end(bl,SC_FREEZE,-1);
  4263. if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
  4264. skill_status_change_end(bl,SC_STONE,-1);
  4265. if(sc_data[SC_SLEEP].timer!=-1)
  4266. skill_status_change_end(bl,SC_SLEEP,-1);
  4267. }
  4268. if(bl->type==BL_MOB) {
  4269. int range = skill_get_range(skillid,skilllv);
  4270. if(range < 0)
  4271. range = battle_get_range(src) - (range + 1);
  4272. mob_target((struct mob_data *)bl,src,range);
  4273. }
  4274. }
  4275. break;
  4276. case PF_SOULCHANGE:
  4277. {
  4278. int sp1 = 0, sp2 = 0;
  4279. if (sd) {
  4280. if (dstsd) {
  4281. sp1 = sd->status.sp > dstsd->status.max_sp ? dstsd->status.max_sp : sd->status.sp;
  4282. sp2 = dstsd->status.sp > sd->status.max_sp ? sd->status.max_sp : dstsd->status.sp;
  4283. sd->status.sp = sp2;
  4284. dstsd->status.sp = sp1;
  4285. clif_heal(sd->fd,SP_SP,sp2);
  4286. clif_heal(dstsd->fd,SP_SP,sp1);
  4287. } else if (dstmd) {
  4288. if (dstmd->state.soul_change_flag) {
  4289. clif_skill_fail(sd,skillid,0,0);
  4290. map_freeblock_unlock();
  4291. return 0;
  4292. }
  4293. sp2 = sd->status.max_sp * 3 /100;
  4294. if (sd->status.sp + sp2 > sd->status.max_sp)
  4295. sp2 = sd->status.max_sp - sd->status.sp;
  4296. sd->status.sp += sp2;
  4297. clif_heal(sd->fd,SP_SP,sp2);
  4298. dstmd->state.soul_change_flag = 1;
  4299. }
  4300. }
  4301. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4302. }
  4303. break;
  4304. // Weapon Refining [Celest]
  4305. case WS_WEAPONREFINE:
  4306. if(sd)
  4307. clif_item_refine_list(sd);
  4308. break;
  4309. // Slim Pitcher
  4310. case CR_SLIMPITCHER:
  4311. {
  4312. if (sd && flag&1) {
  4313. int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*10 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
  4314. hp = hp * (100 + (battle_get_vit(bl)<<1))/100;
  4315. if (dstsd)
  4316. hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10)/100;
  4317. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4318. battle_heal(src,bl,hp,0,0);
  4319. }
  4320. }
  4321. break;
  4322. // Full Chemical Protection
  4323. case CR_FULLPROTECTION:
  4324. {
  4325. int i, skilltime;
  4326. struct status_change *tsc_data = battle_get_sc_data(bl);
  4327. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4328. skilltime = skill_get_time(skillid,skilllv);
  4329. for (i=0; i<4; i++) {
  4330. if(tsc_data && tsc_data[SC_STRIPWEAPON + i].timer != -1)
  4331. skill_status_change_end(bl, SC_STRIPWEAPON + i, -1 );
  4332. skill_status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
  4333. }
  4334. }
  4335. break;
  4336. case RG_CLEANER: //AppleGirl
  4337. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4338. {
  4339. struct skill_unit *su=NULL;
  4340. if((bl->type==BL_SKILL) &&
  4341. (su=(struct skill_unit *)bl) &&
  4342. (su->group->src_id == src->id || map[bl->m].flag.pvp || map[bl->m].flag.gvg) &&
  4343. (su->group->unit_id == 0xb0)){ //?を取り返す
  4344. if(sd)
  4345. skill_delunit(su);
  4346. }
  4347. }
  4348. break;
  4349. // New guild skills [Celest]
  4350. case GD_BATTLEORDER:
  4351. {
  4352. struct guild *g = NULL;
  4353. // Only usable during WoE
  4354. if (!agit_flag) {
  4355. clif_skill_fail(sd,skillid,0,0);
  4356. map_freeblock_unlock();
  4357. return 0;
  4358. }
  4359. if(flag&1) {
  4360. if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
  4361. skill_status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
  4362. }
  4363. }
  4364. else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
  4365. strcmp(sd->status.name,g->master)==0) {
  4366. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4367. map_foreachinarea(skill_area_sub,
  4368. src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
  4369. src,skillid,skilllv,tick, flag|BCT_ALL|1,
  4370. skill_castend_nodamage_id);
  4371. }
  4372. }
  4373. break;
  4374. case GD_REGENERATION:
  4375. {
  4376. struct guild *g = NULL;
  4377. // Only usable during WoE
  4378. if (!agit_flag) {
  4379. clif_skill_fail(sd,skillid,0,0);
  4380. map_freeblock_unlock();
  4381. return 0;
  4382. }
  4383. if(flag&1) {
  4384. if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
  4385. skill_status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
  4386. }
  4387. }
  4388. else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
  4389. strcmp(sd->status.name,g->master)==0) {
  4390. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4391. map_foreachinarea(skill_area_sub,
  4392. src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
  4393. src,skillid,skilllv,tick, flag|BCT_ALL|1,
  4394. skill_castend_nodamage_id);
  4395. }
  4396. }
  4397. break;
  4398. case GD_RESTORE:
  4399. {
  4400. struct guild *g = NULL;
  4401. // Only usable during WoE
  4402. if (!agit_flag) {
  4403. clif_skill_fail(sd,skillid,0,0);
  4404. map_freeblock_unlock();
  4405. return 0;
  4406. }
  4407. if(flag&1) {
  4408. if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
  4409. int hp, sp;
  4410. hp = dstsd->status.max_hp*0.9;
  4411. sp = dstsd->status.max_sp*0.9;
  4412. sp = dstsd->status.sp + sp <= dstsd->status.max_sp ? sp : dstsd->status.max_sp - dstsd->status.sp;
  4413. clif_skill_nodamage(src,bl,AL_HEAL,hp,1);
  4414. battle_heal(NULL,bl,hp,sp,0);
  4415. }
  4416. }
  4417. else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
  4418. strcmp(sd->status.name,g->master)==0) {
  4419. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4420. map_foreachinarea(skill_area_sub,
  4421. src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
  4422. src,skillid,skilllv,tick, flag|BCT_ALL|1,
  4423. skill_castend_nodamage_id);
  4424. }
  4425. }
  4426. break;
  4427. case GD_EMERGENCYCALL:
  4428. {
  4429. int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0};
  4430. int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0};
  4431. int c, j = 0;
  4432. struct guild *g = NULL;
  4433. // Only usable during WoE
  4434. if (!agit_flag) {
  4435. clif_skill_fail(sd,skillid,0,0);
  4436. map_freeblock_unlock();
  4437. return 0;
  4438. }
  4439. // i don't know if it actually summons in a circle, but oh well. ;P
  4440. if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
  4441. strcmp(sd->status.name,g->master)==0) {
  4442. for(i = 0; i < g->max_member; i++, j++) {
  4443. if (j>8) j=0;
  4444. if ((dstsd = g->member[i].sd) != NULL && sd != dstsd &&
  4445. !map[sd->bl.m].flag.nowarpto && !map[dstsd->bl.m].flag.nowarp) {
  4446. clif_skill_nodamage(src,bl,skillid,skilllv,1);
  4447. if ((c=read_gat(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j]))==1 || c==5)
  4448. dx[j] = dy[j] = 0;
  4449. pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2);
  4450. }
  4451. }
  4452. skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,300000,0 );
  4453. }
  4454. }
  4455. break;
  4456. default:
  4457. printf("Unknown skill used:%d\n",skillid);
  4458. map_freeblock_unlock();
  4459. return 1;
  4460. }
  4461. map_freeblock_unlock();
  4462. return 0;
  4463. }
  4464. /*==========================================
  4465. * スキル使用(詠唱完了、ID指定)
  4466. *------------------------------------------
  4467. */
  4468. int skill_castend_id( int tid, unsigned int tick, int id,int data )
  4469. {
  4470. struct map_session_data* sd = map_id2sd(id)/*,*target_sd=NULL*/;
  4471. struct block_list *bl;
  4472. int range,inf2;
  4473. nullpo_retr(0, sd);
  4474. if( sd->bl.prev == NULL ) //prevが無いのはありなの?
  4475. return 0;
  4476. if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid ) /* タイマIDの確認 */
  4477. return 0;
  4478. if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0) {
  4479. sd->speed = sd->prev_speed;
  4480. clif_updatestatus(sd,SP_SPEED);
  4481. }
  4482. if(sd->skillid != SA_CASTCANCEL)
  4483. sd->skilltimer=-1;
  4484. if((bl=map_id2bl(sd->skilltarget))==NULL || bl->prev==NULL) {
  4485. sd->canact_tick = tick;
  4486. sd->canmove_tick = tick;
  4487. sd->skillitem = sd->skillitemlv = -1;
  4488. return 0;
  4489. }
  4490. if(sd->bl.m != bl->m || pc_isdead(sd)) { //マップが違うか自分が死んでいる
  4491. sd->canact_tick = tick;
  4492. sd->canmove_tick = tick;
  4493. sd->skillitem = sd->skillitemlv = -1;
  4494. return 0;
  4495. }
  4496. if(sd->skillid == PR_LEXAETERNA) {
  4497. struct status_change *sc_data = battle_get_sc_data(bl);
  4498. if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) {
  4499. clif_skill_fail(sd,sd->skillid,0,0);
  4500. sd->canact_tick = tick;
  4501. sd->canmove_tick = tick;
  4502. sd->skillitem = sd->skillitemlv = -1;
  4503. return 0;
  4504. }
  4505. }
  4506. else if(sd->skillid == RG_BACKSTAP) {
  4507. int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
  4508. int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y);
  4509. if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) {
  4510. clif_skill_fail(sd,sd->skillid,0,0);
  4511. sd->canact_tick = tick;
  4512. sd->canmove_tick = tick;
  4513. sd->skillitem = sd->skillitemlv = -1;
  4514. return 0;
  4515. }
  4516. }
  4517. inf2 = skill_get_inf2(sd->skillid);
  4518. if( ( (skill_get_inf(sd->skillid)&1) || inf2&4 ) && // 彼我敵??係チェック
  4519. battle_check_target(&sd->bl,bl, BCT_ENEMY)<=0 ) {
  4520. sd->canact_tick = tick;
  4521. sd->canmove_tick = tick;
  4522. sd->skillitem = sd->skillitemlv = -1;
  4523. return 0;
  4524. }
  4525. if(inf2 & 0xC00 && sd->bl.id != bl->id) {
  4526. int fail_flag = 1;
  4527. if(inf2 & 0x400 && battle_check_target(&sd->bl,bl, BCT_PARTY) > 0)
  4528. fail_flag = 0;
  4529. if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == battle_get_guild_id(bl))
  4530. fail_flag = 0;
  4531. if(fail_flag) {
  4532. clif_skill_fail(sd,sd->skillid,0,0);
  4533. sd->canact_tick = tick;
  4534. sd->canmove_tick = tick;
  4535. sd->skillitem = sd->skillitemlv = -1;
  4536. return 0;
  4537. }
  4538. }
  4539. range = skill_get_range(sd->skillid,sd->skilllv);
  4540. if(range < 0)
  4541. range = battle_get_range(&sd->bl) - (range + 1);
  4542. range += battle_config.pc_skill_add_range;
  4543. if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
  4544. (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
  4545. (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
  4546. (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST))
  4547. range += skill_get_blewcount(MO_COMBOFINISH,sd->sc_data[SC_COMBO].val2);
  4548. if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
  4549. if(range < distance(sd->bl.x,sd->bl.y,bl->x,bl->y)) {
  4550. clif_skill_fail(sd,sd->skillid,0,0);
  4551. sd->canact_tick = tick;
  4552. sd->canmove_tick = tick;
  4553. sd->skillitem = sd->skillitemlv = -1;
  4554. return 0;
  4555. }
  4556. }
  4557. if(!skill_check_condition(sd,1)) { /* 使用?件チェック */
  4558. sd->canact_tick = tick;
  4559. sd->canmove_tick = tick;
  4560. sd->skillitem = sd->skillitemlv = -1;
  4561. return 0;
  4562. }
  4563. sd->skillitem = sd->skillitemlv = -1;
  4564. if(battle_config.skill_out_range_consume) {
  4565. if(range < distance(sd->bl.x,sd->bl.y,bl->x,bl->y)) {
  4566. clif_skill_fail(sd,sd->skillid,0,0);
  4567. sd->canact_tick = tick;
  4568. sd->canmove_tick = tick;
  4569. return 0;
  4570. }
  4571. }
  4572. if(battle_config.pc_skill_log)
  4573. printf("PC %d skill castend skill=%d\n",sd->bl.id,sd->skillid);
  4574. pc_stop_walking(sd,0);
  4575. switch( skill_get_nk(sd->skillid) )
  4576. {
  4577. /* 攻?系/吹き飛ばし系 */
  4578. case 0: case 2:
  4579. skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
  4580. break;
  4581. case 1:/* 支援系 */
  4582. if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
  4583. skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
  4584. else
  4585. skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
  4586. break;
  4587. }
  4588. return 0;
  4589. }
  4590. /*==========================================
  4591. * スキル使用(詠唱完了、場所指定の?際の?理)
  4592. *------------------------------------------
  4593. */
  4594. int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag)
  4595. {
  4596. struct map_session_data *sd=NULL;
  4597. int i,tmpx = 0,tmpy = 0, x1 = 0, y1 = 0;
  4598. //if(skilllv <= 0) return 0;
  4599. if(skillid > 0 && skilllv <= 0) return 0; // celest
  4600. nullpo_retr(0, src);
  4601. if(src->type==BL_PC){
  4602. nullpo_retr(0, sd=(struct map_session_data *)src);
  4603. }
  4604. if( skillid != WZ_METEOR &&
  4605. skillid != WZ_SIGHTRASHER &&
  4606. skillid != AM_CANNIBALIZE &&
  4607. skillid != AM_SPHEREMINE)
  4608. clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
  4609. if (skillnotok(skillid, sd)) // [MouseJstr]
  4610. return 0;
  4611. switch(skillid)
  4612. {
  4613. case PR_BENEDICTIO: /* 聖?降福 */
  4614. skill_area_temp[1]=src->id;
  4615. map_foreachinarea(skill_area_sub,
  4616. src->m,x-1,y-1,x+1,y+1,0,
  4617. src,skillid,skilllv,tick, flag|BCT_NOENEMY|1,
  4618. skill_castend_nodamage_id);
  4619. map_foreachinarea(skill_area_sub,
  4620. src->m,x-1,y-1,x+1,y+1,0,
  4621. src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
  4622. skill_castend_damage_id);
  4623. break;
  4624. case BS_HAMMERFALL: /* ハンマ?フォ?ル */
  4625. skill_area_temp[1]=src->id;
  4626. skill_area_temp[2]=x;
  4627. skill_area_temp[3]=y;
  4628. map_foreachinarea(skill_area_sub,
  4629. src->m,x-2,y-2,x+2,y+2,0,
  4630. src,skillid,skilllv,tick, flag|BCT_ENEMY|2,
  4631. skill_castend_nodamage_id);
  4632. break;
  4633. case HT_DETECTING: /* ディテクティング */
  4634. {
  4635. const int range=7;
  4636. if(src->x!=x)
  4637. x+=(src->x-x>0)?-range:range;
  4638. if(src->y!=y)
  4639. y+=(src->y-y>0)?-range:range;
  4640. map_foreachinarea( skill_status_change_timer_sub,
  4641. src->m, x-range, y-range, x+range,y+range,0,
  4642. src,SC_SIGHT,tick);
  4643. }
  4644. break;
  4645. case MG_SAFETYWALL: /* セイフティウォ?ル */
  4646. case MG_FIREWALL: /* ファイヤ?ウォ?ル */
  4647. case MG_THUNDERSTORM: /* サンダ?スト?ム */
  4648. case AL_PNEUMA: /* ニュ?マ */
  4649. case WZ_ICEWALL: /* アイスウォ?ル */
  4650. case WZ_FIREPILLAR: /* ファイアピラ? */
  4651. case WZ_SIGHTRASHER:
  4652. case WZ_QUAGMIRE: /* クァグマイア */
  4653. case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */
  4654. case WZ_FROSTNOVA: /* フロストノヴァ */
  4655. case WZ_STORMGUST: /* スト?ムガスト */
  4656. case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */
  4657. case PR_SANCTUARY: /* サンクチュアリ */
  4658. case PR_MAGNUS: /* マグヌスエクソシズム */
  4659. case CR_GRANDCROSS: /* グランドクロス */
  4660. case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
  4661. case HT_SKIDTRAP: /* スキッドトラップ */
  4662. case HT_LANDMINE: /* ランドマイン */
  4663. case HT_ANKLESNARE: /* アンクルスネア */
  4664. case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */
  4665. case HT_SANDMAN: /* サンドマン */
  4666. case HT_FLASHER: /* フラッシャ? */
  4667. case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
  4668. case HT_BLASTMINE: /* ブラストマイン */
  4669. case HT_CLAYMORETRAP: /* クレイモア?トラップ */
  4670. case AS_VENOMDUST: /* ベノムダスト */
  4671. case AM_DEMONSTRATION: /* デモンストレ?ション */
  4672. case PF_SPIDERWEB: /* スパイダ?ウェッブ */
  4673. case PF_FOGWALL: /* フォグウォ?ル */
  4674. case HT_TALKIEBOX: /* ト?キ?ボックス */
  4675. skill_unitsetting(src,skillid,skilllv,x,y,0);
  4676. break;
  4677. case RG_GRAFFITI: /* Graffiti [Valaris] */
  4678. skill_clear_unitgroup(src);
  4679. skill_unitsetting(src,skillid,skilllv,x,y,0);
  4680. break;
  4681. case SA_VOLCANO: /* ボルケ?ノ */
  4682. case SA_DELUGE: /* デリュ?ジ */
  4683. case SA_VIOLENTGALE: /* バイオレントゲイル */
  4684. case SA_LANDPROTECTOR: /* ランドプロテクタ? */
  4685. skill_clear_element_field(src);//?に自分が?動している?性場をクリア
  4686. skill_unitsetting(src,skillid,skilllv,x,y,0);
  4687. break;
  4688. case WZ_METEOR: //メテオスト?ム
  4689. {
  4690. int flag=0;
  4691. for(i=0;i<2+(skilllv>>1);i++) {
  4692. int j=0, c;
  4693. do {
  4694. tmpx = x + (rand()%7 - 3);
  4695. tmpy = y + (rand()%7 - 3);
  4696. if(tmpx < 0)
  4697. tmpx = 0;
  4698. else if(tmpx >= map[src->m].xs)
  4699. tmpx = map[src->m].xs - 1;
  4700. if(tmpy < 0)
  4701. tmpy = 0;
  4702. else if(tmpy >= map[src->m].ys)
  4703. tmpy = map[src->m].ys - 1;
  4704. j++;
  4705. } while(((c=map_getcell(src->m,tmpx,tmpy))==1 || c==5) && j<100);
  4706. if(j >= 100)
  4707. continue;
  4708. if(flag==0){
  4709. clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick);
  4710. flag=1;
  4711. }
  4712. if(i > 0)
  4713. skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,flag);
  4714. x1 = tmpx;
  4715. y1 = tmpy;
  4716. }
  4717. skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,flag);
  4718. }
  4719. break;
  4720. case AL_WARP: /* ワ?プポ?タル */
  4721. if(sd) {
  4722. if(map[sd->bl.m].flag.noteleport) /* テレポ禁止 */
  4723. break;
  4724. clif_skill_warppoint(sd,sd->skillid,sd->status.save_point.map,
  4725. (sd->skilllv>1)?sd->status.memo_point[0].map:"",
  4726. (sd->skilllv>2)?sd->status.memo_point[1].map:"",
  4727. (sd->skilllv>3)?sd->status.memo_point[2].map:"");
  4728. }
  4729. break;
  4730. case MO_BODYRELOCATION:
  4731. if(sd){
  4732. pc_movepos(sd,x,y);
  4733. }else if( src->type==BL_MOB )
  4734. mob_warp((struct mob_data *)src,-1,x,y,0);
  4735. skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,MO_EXTREMITYFIST,0,2000,0 );
  4736. break;
  4737. case AM_CANNIBALIZE: // バイオプラント
  4738. if(sd){
  4739. int mx,my,id=0;
  4740. int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
  4741. struct mob_data *md;
  4742. mx = x;// + (rand()%10 - 5);
  4743. my = y;// + (rand()%10 - 5);
  4744. id=mob_once_spawn(sd,"this",mx,my,"--ja--", summons[skilllv-1] ,1,"");
  4745. if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
  4746. md->master_id=sd->bl.id;
  4747. md->hp=2210+skilllv*200;
  4748. md->state.special_mob_ai=1;
  4749. md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
  4750. }
  4751. clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
  4752. }
  4753. break;
  4754. case AM_SPHEREMINE: // スフィア?マイン
  4755. if(sd){
  4756. int mx,my,id=0;
  4757. struct mob_data *md;
  4758. mx = x;// + (rand()%10 - 5);
  4759. my = y;// + (rand()%10 - 5);
  4760. id=mob_once_spawn(sd,"this",mx,my,"--ja--",1142,1,"");
  4761. if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
  4762. md->master_id=sd->bl.id;
  4763. md->hp=2000+skilllv*400;
  4764. md->state.special_mob_ai=2;
  4765. md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
  4766. }
  4767. clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
  4768. }
  4769. break;
  4770. // Slim Pitcher [Celest]
  4771. case CR_SLIMPITCHER:
  4772. {
  4773. if (sd) {
  4774. int x = skilllv%11 - 1;
  4775. int i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
  4776. if(i < 0 || skill_db[skillid].itemid[x] <= 0 || sd->inventory_data[i] == NULL ||
  4777. sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
  4778. clif_skill_fail(sd,skillid,0,0);
  4779. map_freeblock_unlock();
  4780. return 1;
  4781. }
  4782. sd->state.potionpitcher_flag = 1;
  4783. sd->potion_hp = 0;
  4784. run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
  4785. pc_delitem(sd,i,skill_db[skillid].amount[x],0);
  4786. sd->state.potionpitcher_flag = 0;
  4787. if(sd->potion_hp > 0) {
  4788. map_foreachinarea(skill_area_sub,
  4789. src->m,x-3,y-3,x+3,y+3,0,
  4790. src,skillid,skilllv,tick,flag|BCT_ALL|1,
  4791. skill_castend_nodamage_id);
  4792. }
  4793. }
  4794. }
  4795. break;
  4796. }
  4797. return 0;
  4798. }
  4799. /*==========================================
  4800. * スキル使用(詠唱完了、map指定)
  4801. *------------------------------------------
  4802. */
  4803. int skill_castend_map( struct map_session_data *sd,int skill_num, const char *map)
  4804. {
  4805. int x=0,y=0;
  4806. nullpo_retr(0, sd);
  4807. if( sd->bl.prev == NULL || pc_isdead(sd) )
  4808. return 0;
  4809. if(skillnotok(skill_num, sd))
  4810. return 0;
  4811. if( sd->opt1>0 || sd->status.option&2 )
  4812. return 0;
  4813. //スキルが使えない?態異常中
  4814. if(sd->sc_count){
  4815. if( sd->sc_data[SC_DIVINA].timer!=-1 ||
  4816. sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
  4817. sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
  4818. sd->sc_data[SC_STEELBODY].timer != -1 ||
  4819. sd->sc_data[SC_DANCING].timer!=-1 ||
  4820. sd->sc_data[SC_BERSERK].timer != -1 ||
  4821. sd->sc_data[SC_MARIONETTE].timer != -1)
  4822. return 0;
  4823. if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
  4824. if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
  4825. return 0;
  4826. }
  4827. if( skill_num != sd->skillid) /* 不正パケットらしい */
  4828. return 0;
  4829. pc_stopattack(sd);
  4830. if(battle_config.pc_skill_log)
  4831. printf("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_num,map);
  4832. pc_stop_walking(sd,0);
  4833. if(strcmp(map,"cancel")==0)
  4834. return 0;
  4835. switch(skill_num){
  4836. case AL_TELEPORT: /* テレポ?ト */
  4837. if(strcmp(map,"Random")==0)
  4838. pc_randomwarp(sd,3);
  4839. else
  4840. pc_setpos(sd,sd->status.save_point.map,
  4841. sd->status.save_point.x,sd->status.save_point.y,3);
  4842. break;
  4843. case AL_WARP: /* ワ?プポ?タル */
  4844. {
  4845. const struct point *p[]={
  4846. &sd->status.save_point,&sd->status.memo_point[0],
  4847. &sd->status.memo_point[1],&sd->status.memo_point[2],
  4848. };
  4849. struct skill_unit_group *group;
  4850. int i;
  4851. int maxcount=0;
  4852. if((maxcount = skill_get_maxcount(sd->skillid)) > 0) {
  4853. int c;
  4854. for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
  4855. if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid)
  4856. c++;
  4857. }
  4858. if(c >= maxcount) {
  4859. clif_skill_fail(sd,sd->skillid,0,0);
  4860. sd->canact_tick = gettick();
  4861. sd->canmove_tick = gettick();
  4862. sd->skillitem = sd->skillitemlv = -1;
  4863. return 0;
  4864. }
  4865. }
  4866. if(sd->skilllv <= 0) return 0;
  4867. for(i=0;i<sd->skilllv;i++){
  4868. if(strcmp(map,p[i]->map)==0){
  4869. x=p[i]->x;
  4870. y=p[i]->y;
  4871. break;
  4872. }
  4873. }
  4874. if(x==0 || y==0) /* 不正パケット? */
  4875. return 0;
  4876. if(!skill_check_condition(sd,3))
  4877. return 0;
  4878. if((group=skill_unitsetting(&sd->bl,sd->skillid,sd->skilllv,sd->skillx,sd->skilly,0))==NULL)
  4879. return 0;
  4880. group->valstr=(char *)aCalloc(24,sizeof(char));
  4881. memcpy(group->valstr,map,24);
  4882. group->val2=(x<<16)|y;
  4883. }
  4884. break;
  4885. }
  4886. return 0;
  4887. }
  4888. /*==========================================
  4889. * スキルユニット設定?理
  4890. *------------------------------------------
  4891. */
  4892. struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag)
  4893. {
  4894. struct skill_unit_group *group;
  4895. int i,count=1,limit=10000,val1=0,val2=0;
  4896. int target=BCT_ENEMY,interval=1000,range=0;
  4897. int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
  4898. struct status_change *sc_data = battle_get_sc_data(src); // for firewall and fogwall - celest
  4899. nullpo_retr(0, src);
  4900. switch(skillid){ /* 設定 */
  4901. case MG_SAFETYWALL: /* セイフティウォ?ル */
  4902. limit=skill_get_time(skillid,skilllv);
  4903. val2=skilllv+1;
  4904. interval = -1;
  4905. target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
  4906. break;
  4907. case MG_FIREWALL: /* ファイヤ?ウォ?ル */
  4908. if(src->x == x && src->y == y)
  4909. dir = 2;
  4910. else
  4911. dir=map_calc_dir(src,x,y);
  4912. if(dir&1) count=5;
  4913. else count=3;
  4914. limit=skill_get_time(skillid,skilllv);
  4915. if(sc_data) {
  4916. if (sc_data[SC_VIOLENTGALE].timer!=-1) limit *= 1.5;
  4917. }
  4918. // check for sc_data first - Celest
  4919. // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1)
  4920. // limit *= 1.5;
  4921. val2=4+skilllv;
  4922. interval=1;
  4923. break;
  4924. case AL_PNEUMA: /* ニュ?マ */
  4925. limit=skill_get_time(skillid,skilllv);
  4926. interval = -1;
  4927. target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
  4928. count = 9;
  4929. break;
  4930. case AL_WARP: /* ワ?プポ?タル */
  4931. target=BCT_ALL;
  4932. val1=skilllv+6;
  4933. if(flag==0)
  4934. limit=2000;
  4935. else
  4936. limit=skill_get_time(skillid,skilllv);
  4937. break;
  4938. case PR_SANCTUARY: /* サンクチュアリ */
  4939. count=21;
  4940. limit=skill_get_time(skillid,skilllv);
  4941. val1=(skilllv+3)*2;
  4942. val2=(skilllv>6)?777:skilllv*100;
  4943. target=BCT_ALL;
  4944. range=1;
  4945. break;
  4946. case PR_MAGNUS: /* マグヌスエクソシズム */
  4947. count=33;
  4948. limit=skill_get_time(skillid,skilllv);
  4949. interval=3000;
  4950. break;
  4951. case WZ_FIREPILLAR: /* ファイア?ピラ? */
  4952. if(flag==0)
  4953. limit=skill_get_time(skillid,skilllv);
  4954. else
  4955. limit=1000;
  4956. interval=2000;
  4957. val1=skilllv+2;
  4958. if(skilllv < 6)
  4959. range=1;
  4960. else
  4961. range=2;
  4962. break;
  4963. case MG_THUNDERSTORM: /* サンダ?スト?ム */
  4964. limit=500;
  4965. range=1;
  4966. break;
  4967. case WZ_FROSTNOVA: /* フロストノヴァ */
  4968. limit=500;
  4969. range=5;
  4970. break;
  4971. case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */
  4972. limit=500;
  4973. range=2;
  4974. break;
  4975. case WZ_METEOR: /* メテオスト?ム */
  4976. limit=500;
  4977. range=3;
  4978. break;
  4979. case WZ_SIGHTRASHER:
  4980. limit=500;
  4981. count=41;
  4982. break;
  4983. case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */
  4984. limit=4100;
  4985. interval=1000;
  4986. range=6;
  4987. break;
  4988. case WZ_ICEWALL: /* アイスウォ?ル */
  4989. limit=skill_get_time(skillid,skilllv);
  4990. count=5;
  4991. break;
  4992. case WZ_STORMGUST: /* スト?ムガスト */
  4993. limit=4600;
  4994. interval=450;
  4995. range=5;
  4996. break;
  4997. case WZ_QUAGMIRE: /* クァグマイア */
  4998. limit=skill_get_time(skillid,skilllv);
  4999. interval=200;
  5000. count=25;
  5001. break;
  5002. case HT_SANDMAN: /* サンドマン */
  5003. case HT_CLAYMORETRAP: /* クレイモア?トラップ */
  5004. limit=skill_get_time(skillid,skilllv);
  5005. // longer trap times in WOE [celest]
  5006. if (map[src->m].flag.gvg) limit *= 4;
  5007. range=2;
  5008. break;
  5009. case HT_SKIDTRAP: /* スキッドトラップ */
  5010. case HT_LANDMINE: /* ランドマイン */
  5011. case HT_ANKLESNARE: /* アンクルスネア */
  5012. case PF_SPIDERWEB: /* スパイダ?ウェッブ */
  5013. case HT_FLASHER: /* フラッシャ? */
  5014. case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
  5015. case HT_BLASTMINE: /* ブラストマイン */
  5016. limit=skill_get_time(skillid,skilllv);
  5017. // longer trap times in WOE [celest]
  5018. if (skillid != PF_SPIDERWEB && map[src->m].flag.gvg)
  5019. limit *= 4;
  5020. range=1;
  5021. break;
  5022. case HT_TALKIEBOX: /* ト?キ?ボックス */
  5023. limit=skill_get_time(skillid,skilllv);
  5024. range=1;
  5025. target=BCT_ALL;
  5026. break;
  5027. case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */
  5028. limit=skill_get_time(skillid,skilllv);
  5029. range=1;
  5030. val1=skilllv*15+10;
  5031. break;
  5032. case AS_VENOMDUST: /* ベノムダスト */
  5033. limit=skill_get_time(skillid,skilllv);
  5034. interval=1000;
  5035. count=5;
  5036. break;
  5037. case CR_GRANDCROSS: /* グランドクロス */
  5038. case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
  5039. count=29;
  5040. limit=1000;
  5041. interval=300;
  5042. break;
  5043. case SA_VOLCANO: /* ボルケ?ノ */
  5044. case SA_DELUGE: /* デリュ?ジ */
  5045. case SA_VIOLENTGALE: /* バイオレントゲイル */
  5046. limit=skill_get_time(skillid,skilllv);
  5047. //count=skilllv<=2?25:(skilllv<=4?49:81);
  5048. count=49;
  5049. target=BCT_ALL;
  5050. break;
  5051. case SA_LANDPROTECTOR: /* グランドクロス */
  5052. limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul)
  5053. val1=skilllv*15+10;
  5054. aoe_diameter=skilllv+skilllv%2+5;
  5055. target=BCT_ALL;
  5056. count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
  5057. break;
  5058. case BD_LULLABY: /* 子守唄 */
  5059. case BD_ETERNALCHAOS: /* エタ?ナルカオス */
  5060. case BD_ROKISWEIL: /* ロキの叫び */
  5061. count=81;
  5062. limit=skill_get_time(skillid,skilllv);
  5063. range=5;
  5064. target=(skillid==BD_ETERNALCHAOS ? BCT_ENEMY : BCT_ALL);
  5065. break;
  5066. case BD_RICHMANKIM:
  5067. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  5068. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  5069. case BD_INTOABYSS: /* 深淵の中に */
  5070. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  5071. count=81;
  5072. limit=skill_get_time(skillid,skilllv);
  5073. range=5;
  5074. target=BCT_PARTY;
  5075. break;
  5076. case BA_WHISTLE: /* 口笛 */
  5077. count=49;
  5078. limit=skill_get_time(skillid,skilllv);
  5079. range=5;
  5080. target=BCT_NOENEMY;
  5081. if(src->type == BL_PC)
  5082. val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
  5083. val2 = ((battle_get_agi(src)/10)&0xffff)<<16;
  5084. val2 |= (battle_get_luk(src)/10)&0xffff;
  5085. break;
  5086. case DC_HUMMING: /* ハミング */
  5087. count=49;
  5088. limit=skill_get_time(skillid,skilllv);
  5089. range=5;
  5090. target=BCT_NOENEMY;
  5091. if(src->type == BL_PC)
  5092. val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
  5093. val2 = battle_get_dex(src)/10;
  5094. break;
  5095. case BA_DISSONANCE: /* 不協和音 */
  5096. case DC_UGLYDANCE: /* 自分勝手なダンス */
  5097. count=49;
  5098. limit=skill_get_time(skillid,skilllv);
  5099. range=5;
  5100. target=BCT_ENEMY;
  5101. break;
  5102. case DC_DONTFORGETME: /* 私を忘れないで… */
  5103. count=49;
  5104. limit=skill_get_time(skillid,skilllv);
  5105. range=5;
  5106. target=BCT_ENEMY;
  5107. if(src->type == BL_PC)
  5108. val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
  5109. val2 = ((battle_get_str(src)/20)&0xffff)<<16;
  5110. val2 |= (battle_get_agi(src)/10)&0xffff;
  5111. break;
  5112. case BA_POEMBRAGI: /* ブラギの詩 */
  5113. count=49;
  5114. limit=skill_get_time(skillid,skilllv);
  5115. range=5;
  5116. target=BCT_NOENEMY;
  5117. if(src->type == BL_PC)
  5118. val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON);
  5119. val2 = ((battle_get_dex(src)/10)&0xffff)<<16;
  5120. val2 |= (battle_get_int(src)/5)&0xffff;
  5121. break;
  5122. case BA_APPLEIDUN: /* イドゥンの林檎 */
  5123. count=49;
  5124. limit=skill_get_time(skillid,skilllv);
  5125. range=5;
  5126. target=BCT_NOENEMY;
  5127. if(src->type == BL_PC)
  5128. val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16;
  5129. else
  5130. val1 = 0;
  5131. val1 |= (battle_get_vit(src))&0xffff;
  5132. val2 = 0;//回復用タイムカウンタ(6秒?に1?加)
  5133. break;
  5134. case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
  5135. count=49;
  5136. limit=skill_get_time(skillid,skilllv);
  5137. range=5;
  5138. target=BCT_PARTY;
  5139. if(src->type == BL_PC)
  5140. val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
  5141. val2 = battle_get_int(src)/10;
  5142. break;
  5143. case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
  5144. count=49;
  5145. limit=skill_get_time(skillid,skilllv);
  5146. range=5;
  5147. target=BCT_NOENEMY;
  5148. if(src->type == BL_PC)
  5149. val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
  5150. val2 = battle_get_agi(src)/20;
  5151. break;
  5152. case DC_FORTUNEKISS: /* 幸運のキス */
  5153. count=49;
  5154. limit=skill_get_time(skillid,skilllv);
  5155. range=5;
  5156. target=BCT_NOENEMY;
  5157. if(src->type == BL_PC)
  5158. val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
  5159. val2 = battle_get_luk(src)/10;
  5160. break;
  5161. case AM_DEMONSTRATION: /* デモンストレ?ション */
  5162. limit=skill_get_time(skillid,skilllv);
  5163. interval=1000;
  5164. range=1;
  5165. target=BCT_ENEMY;
  5166. break;
  5167. case WE_CALLPARTNER: /* あなたに逢いたい */
  5168. limit=skill_get_time(skillid,skilllv);
  5169. range=-1;
  5170. break;
  5171. case HP_BASILICA: /* バジリカ */
  5172. limit=skill_get_time(skillid,skilllv);
  5173. target=BCT_ALL;
  5174. range=3;
  5175. //Fix to prevent the priest from walking while Basilica is up.
  5176. battle_stopwalking(src,1);
  5177. //skill_status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0);
  5178. //sd->canmove_tick = gettick() + limit; // added later [celest]
  5179. break;
  5180. case PA_GOSPEL: /* ゴスペル */
  5181. count=49;
  5182. target=BCT_PARTY;
  5183. limit=skill_get_time(skillid,skilllv);
  5184. break;
  5185. case CG_MOONLIT:
  5186. range=1;
  5187. target=BCT_ALL;
  5188. limit=skill_get_time(skillid,skilllv);
  5189. break;
  5190. case PF_FOGWALL: /* フォグウォ?ル */
  5191. count=15;
  5192. limit=skill_get_time(skillid,skilllv);
  5193. if(sc_data) {
  5194. if (sc_data[SC_DELUGE].timer!=-1) limit *= 2;
  5195. }
  5196. break;
  5197. case RG_GRAFFITI: /* Graffiti */
  5198. count=1; // Leave this at 1 [Valaris]
  5199. limit=600000; // Time length [Valaris]
  5200. break;
  5201. case GD_LEADERSHIP:
  5202. case GD_GLORYWOUNDS:
  5203. case GD_SOULCOLD:
  5204. case GD_HAWKEYES:
  5205. range=2;
  5206. target=BCT_ALL;
  5207. limit=60000;
  5208. break;
  5209. default:
  5210. if(battle_config.error_log)
  5211. printf ("skill_unitsetting: Unknown skill id = %d\n",skillid);
  5212. return 0;
  5213. }
  5214. nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
  5215. group->limit=limit;
  5216. group->val1=val1;
  5217. group->val2=val2;
  5218. group->target_flag=target;
  5219. group->interval=interval;
  5220. group->range=range;
  5221. if(skillid==HT_TALKIEBOX ||
  5222. skillid==RG_GRAFFITI){
  5223. group->valstr=calloc(80, 1);
  5224. if(group->valstr==NULL){
  5225. printf("skill_castend_map: out of memory !\n");
  5226. exit(1);
  5227. }
  5228. memcpy(group->valstr,talkie_mes,80);
  5229. }
  5230. for(i=0;i<count;i++){
  5231. struct skill_unit *unit;
  5232. int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1;
  5233. int range=group->range;
  5234. switch(skillid){ /* 設定 */
  5235. case AL_PNEUMA: /* ニュ?マ */
  5236. {
  5237. static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1};
  5238. static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1};
  5239. ux+=dx[i];
  5240. uy+=dy[i];
  5241. }
  5242. break;
  5243. case MG_FIREWALL: /* ファイヤ?ウォ?ル */
  5244. {
  5245. if(dir&1){ /* 斜め配置 */
  5246. static const int dx[][5]={
  5247. { 1,1,0,0,-1 }, { -1,-1,0,0,1 },
  5248. },dy[][5]={
  5249. { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 },
  5250. };
  5251. ux+=dx[(dir>>1)&1][i];
  5252. uy+=dy[(dir>>1)&1][i];
  5253. }else{ /* 上下配置 */
  5254. if(dir%4==0) /* 上下 */
  5255. ux+=i-1;
  5256. else /* 左右 */
  5257. uy+=i-1;
  5258. }
  5259. val2=group->val2;
  5260. }
  5261. break;
  5262. case PR_SANCTUARY: /* サンクチュアリ */
  5263. {
  5264. static const int dx[]={
  5265. -1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 };
  5266. static const int dy[]={
  5267. -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, };
  5268. ux+=dx[i];
  5269. uy+=dy[i];
  5270. }
  5271. break;
  5272. case PR_MAGNUS: /* マグヌスエクソシズム */
  5273. {
  5274. static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3,
  5275. -3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, };
  5276. static const int dy[]={
  5277. -3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1,
  5278. 0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 };
  5279. ux+=dx[i];
  5280. uy+=dy[i];
  5281. }
  5282. break;
  5283. case WZ_SIGHTRASHER:
  5284. {
  5285. static const int dx[]={
  5286. -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 };
  5287. static const int dy[]={
  5288. -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
  5289. ux+=dx[i];
  5290. uy+=dy[i];
  5291. }
  5292. break;
  5293. case WZ_ICEWALL: /* アイスウォ?ル */
  5294. {
  5295. static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
  5296. static const int diry[8]={1,1,0,-1,-1,-1,0,1};
  5297. if(skilllv <= 1)
  5298. val1 = 500;
  5299. else
  5300. val1 = 200 + 200*skilllv;
  5301. if(src->x == x && src->y == y)
  5302. dir = 2;
  5303. else
  5304. dir=map_calc_dir(src,x,y);
  5305. ux+=(2-i)*diry[dir];
  5306. uy+=(i-2)*dirx[dir];
  5307. }
  5308. break;
  5309. case WZ_QUAGMIRE: /* クァグマイア */
  5310. ux+=(i%5-2);
  5311. uy+=(i/5-2);
  5312. if(i==12)
  5313. range=2;
  5314. else
  5315. range=-1;
  5316. break;
  5317. case AS_VENOMDUST: /* ベノムダスト */
  5318. {
  5319. static const int dx[]={-1,0,0,0,1};
  5320. static const int dy[]={0,-1,0,1,0};
  5321. ux+=dx[i];
  5322. uy+=dy[i];
  5323. }
  5324. break;
  5325. case CR_GRANDCROSS: /* グランドクロス */
  5326. case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
  5327. {
  5328. static const int dx[]={
  5329. 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, };
  5330. static const int dy[]={
  5331. -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, };
  5332. ux+=dx[i];
  5333. uy+=dy[i];
  5334. }
  5335. break;
  5336. case SA_VOLCANO: /* ボルケ?ノ */
  5337. case SA_DELUGE: /* デリュ?ジ */
  5338. case SA_VIOLENTGALE: /* バイオレントゲイル */
  5339. {
  5340. int u_range=0,central=0;
  5341. if(skilllv<=2){
  5342. u_range=2;
  5343. central=12;
  5344. }else if(skilllv<=4){
  5345. u_range=3;
  5346. central=24;
  5347. }else if(skilllv>=5){
  5348. u_range=4;
  5349. central=40;
  5350. }
  5351. ux+=(i%(u_range*2+1)-u_range);
  5352. uy+=(i/(u_range*2+1)-u_range);
  5353. if(i==central)
  5354. range=u_range;//中央のユニットの?果範?は全範?
  5355. else
  5356. range=-1;//中央以外のユニットは飾り
  5357. }
  5358. break;
  5359. case SA_LANDPROTECTOR: /* ランドプロテクタ? */
  5360. {
  5361. int u_range=0;
  5362. if(skilllv<=2) u_range=3;
  5363. else if(skilllv<=4) u_range=4;
  5364. else if(skilllv>=5) u_range=5;
  5365. ux+=(i%(u_range*2+1)-u_range);
  5366. uy+=(i/(u_range*2+1)-u_range);
  5367. range=0;
  5368. }
  5369. break;
  5370. /* ダンスなど */
  5371. case BD_LULLABY: /* 子守歌 */
  5372. case BD_RICHMANKIM: /* ニヨルドの宴 */
  5373. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  5374. case BD_DRUMBATTLEFIELD:/* ?太鼓の響き */
  5375. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  5376. case BD_ROKISWEIL: /* ロキの叫び */
  5377. case BD_INTOABYSS: /* 深淵の中に */
  5378. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  5379. ux+=(i%9-4);
  5380. uy+=(i/9-4);
  5381. if(i==40)
  5382. range=4; /* 中心の場合は範?を4にオ?バ?ライド */
  5383. else
  5384. range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */
  5385. break;
  5386. case BA_DISSONANCE: /* 不協和音 */
  5387. case BA_WHISTLE: /* 口笛 */
  5388. case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
  5389. case BA_POEMBRAGI: /* ブラギの詩 */
  5390. case BA_APPLEIDUN: /* イドゥンの林檎 */
  5391. case DC_UGLYDANCE: /* 自分勝手なダンス */
  5392. case DC_HUMMING: /* ハミング */
  5393. case DC_DONTFORGETME: /* 私を忘れないで… */
  5394. case DC_FORTUNEKISS: /* 幸運のキス */
  5395. case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
  5396. case CG_MOONLIT:
  5397. ux+=(i%7-3);
  5398. uy+=(i/7-3);
  5399. if(i==40)
  5400. range=4; /* 中心の場合は範?を4にオ?バ?ライド */
  5401. else
  5402. range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */
  5403. break;
  5404. case PA_GOSPEL: /* ゴスペル */
  5405. ux+=(i%7-3);
  5406. uy+=(i/7-3);
  5407. break;
  5408. case PF_FOGWALL: /* フォグウォ?ル */
  5409. ux+=(i%5-2);
  5410. uy+=(i/5-1);
  5411. break;
  5412. case RG_GRAFFITI: /* Graffiti [Valaris] */
  5413. ux+=(i%5-2);
  5414. uy+=(i/5-2);
  5415. break;
  5416. }
  5417. //直上スキルの場合設置座標上にランドプロテクタ?がないかチェック
  5418. if(range<=0)
  5419. map_foreachinarea(skill_landprotector,src->m,ux,uy,ux,uy,BL_SKILL,skillid,&alive);
  5420. if(skillid==WZ_ICEWALL && alive){
  5421. val2=map_getcell(src->m,ux,uy);
  5422. if(val2==5 || val2==1)
  5423. alive=0;
  5424. else {
  5425. map_setcell(src->m,ux,uy,5);
  5426. clif_changemapcell(src->m,ux,uy,5,0);
  5427. }
  5428. }
  5429. if(alive){
  5430. nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy));
  5431. unit->val1=val1;
  5432. unit->val2=val2;
  5433. unit->limit=limit;
  5434. unit->range=range;
  5435. // [celest]
  5436. if (sc_data) {
  5437. // attach the unit's id to the caster
  5438. switch (skillid) {
  5439. case HP_BASILICA:
  5440. if (sc_data[SC_BASILICA].timer!=-1)
  5441. sc_data[SC_BASILICA].val4 = (int)unit;
  5442. break;
  5443. case GD_LEADERSHIP:
  5444. sc_data[SC_LEADERSHIP].val4 = (int)unit;
  5445. break;
  5446. case GD_GLORYWOUNDS:
  5447. sc_data[SC_GLORYWOUNDS].val4 = (int)unit;
  5448. break;
  5449. case GD_SOULCOLD:
  5450. sc_data[SC_SOULCOLD].val4 = (int)unit;
  5451. break;
  5452. case GD_HAWKEYES:
  5453. sc_data[SC_HAWKEYES].val4 = (int)unit;
  5454. break;
  5455. }
  5456. }
  5457. }
  5458. }
  5459. return group;
  5460. }
  5461. /*==========================================
  5462. * スキルユニットの?動イベント
  5463. *------------------------------------------
  5464. */
  5465. int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick)
  5466. {
  5467. struct skill_unit_group *sg;
  5468. struct block_list *ss;
  5469. struct skill_unit_group_tickset *ts;
  5470. struct map_session_data *srcsd=NULL;
  5471. int diff,goflag,splash_count=0;
  5472. nullpo_retr(0, src);
  5473. nullpo_retr(0, bl);
  5474. if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) )
  5475. return 0;
  5476. nullpo_retr(0, sg=src->group);
  5477. nullpo_retr(0, ss=map_id2bl(sg->src_id));
  5478. if(ss->type == BL_PC)
  5479. nullpo_retr(0, srcsd=(struct map_session_data *)ss);
  5480. if(srcsd && srcsd->chatID)
  5481. return 0;
  5482. if( bl->type!=BL_PC && bl->type!=BL_MOB )
  5483. return 0;
  5484. nullpo_retr(0, ts=skill_unitgrouptickset_search( bl, sg->group_id));
  5485. diff=DIFF_TICK(tick,ts->tick);
  5486. goflag=(diff>sg->interval || diff<0);
  5487. if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない
  5488. goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0);
  5489. //?象がLP上に居る場合は無?
  5490. map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag);
  5491. if(!goflag)
  5492. return 0;
  5493. ts->tick=tick;
  5494. ts->group_id=sg->group_id;
  5495. switch(sg->unit_id){
  5496. case 0x83: /* サンクチュアリ */
  5497. {
  5498. int race=battle_get_race(bl);
  5499. int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
  5500. if( battle_get_hp(bl)>=battle_get_max_hp(bl) && !damage_flag)
  5501. break;
  5502. if((sg->val1--)<=0){
  5503. skill_delunitgroup(sg);
  5504. return 0;
  5505. }
  5506. if(!damage_flag) {
  5507. int heal=sg->val2;
  5508. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
  5509. heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */
  5510. clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1);
  5511. battle_heal(NULL,bl,heal,0,0);
  5512. }
  5513. else {
  5514. // reduce healing count if this was meant for damaging [celest]
  5515. sg->val1 /= 2;
  5516. skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5517. }
  5518. }
  5519. break;
  5520. case 0x84: /* マグヌスエクソシズム */
  5521. {
  5522. int race=battle_get_race(bl);
  5523. int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
  5524. if(!damage_flag)
  5525. return 0;
  5526. skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5527. }
  5528. break;
  5529. case 0x85: /* ニュ?マ */
  5530. {
  5531. struct skill_unit *unit2;
  5532. struct status_change *sc_data=battle_get_sc_data(bl);
  5533. int type=SC_PNEUMA;
  5534. if(sc_data) {
  5535. if (sc_data[type].timer==-1)
  5536. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
  5537. else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
  5538. if(DIFF_TICK(sg->tick,unit2->group->tick)>0 )
  5539. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
  5540. ts->tick-=sg->interval;
  5541. }
  5542. }
  5543. }
  5544. break;
  5545. case 0x7e: /* セイフティウォ?ル */
  5546. {
  5547. struct skill_unit *unit2;
  5548. struct status_change *sc_data=battle_get_sc_data(bl);
  5549. int type=SC_SAFETYWALL;
  5550. if(sc_data) {
  5551. if (sc_data[type].timer==-1)
  5552. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
  5553. else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
  5554. if(sg->val1 < unit2->group->val1 )
  5555. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
  5556. ts->tick-=sg->interval;
  5557. }
  5558. }
  5559. }
  5560. break;
  5561. case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */
  5562. skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5563. break;
  5564. case 0x7f: /* ファイヤ?ウォ?ル */
  5565. if( (src->val2--)>0)
  5566. skill_attack(BF_MAGIC,ss,&src->bl,bl,
  5567. sg->skill_id,sg->skill_lv,tick,0);
  5568. if( src->val2<=0 )
  5569. skill_delunit(src);
  5570. break;
  5571. case 0x87: /* ファイア?ピラ?(?動前) */
  5572. skill_delunit(src);
  5573. skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1);
  5574. break;
  5575. case 0x88: /* ファイア?ピラ?(?動後) */
  5576. if(DIFF_TICK(tick,sg->tick) < 150)
  5577. //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5578. map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
  5579. break;
  5580. case 0x90: /* スキッドトラップ */
  5581. {
  5582. int i,c = skill_get_blewcount(sg->skill_id,sg->skill_lv);
  5583. if(map[bl->m].flag.gvg) c = 0;
  5584. for(i=0;i<c;i++)
  5585. skill_blown(&src->bl,bl,1|0x30000);
  5586. sg->unit_id = 0x8c;
  5587. clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
  5588. sg->limit=DIFF_TICK(tick,sg->tick)+1500;
  5589. }
  5590. break;
  5591. case 0x93: /* ランドマイン */
  5592. skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5593. sg->unit_id = 0x8c;
  5594. clif_changelook(&src->bl,LOOK_BASE,0x88);
  5595. sg->limit=DIFF_TICK(tick,sg->tick)+1500;
  5596. break;
  5597. case 0x8f: /* ブラストマイン */
  5598. case 0x94: /* ショックウェ?ブトラップ */
  5599. case 0x95: /* サンドマン */
  5600. case 0x96: /* フラッシャ? */
  5601. case 0x97: /* フリ?ジングトラップ */
  5602. case 0x98: /* クレイモア?トラップ */
  5603. map_foreachinarea(skill_count_target,src->bl.m
  5604. ,src->bl.x-src->range,src->bl.y-src->range
  5605. ,src->bl.x+src->range,src->bl.y+src->range
  5606. ,0,&src->bl,&splash_count);
  5607. map_foreachinarea(skill_trap_splash,src->bl.m
  5608. ,src->bl.x-src->range,src->bl.y-src->range
  5609. ,src->bl.x+src->range,src->bl.y+src->range
  5610. ,0,&src->bl,tick,splash_count);
  5611. sg->unit_id = 0x8c;
  5612. clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
  5613. sg->limit=DIFF_TICK(tick,sg->tick)+1500;
  5614. break;
  5615. case 0x91: /* アンクルスネア */
  5616. {
  5617. struct status_change *sc_data=battle_get_sc_data(bl);
  5618. if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){
  5619. int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
  5620. int sec=skill_get_time2(sg->skill_id,sg->skill_lv) - (double)battle_get_agi(bl)*0.1;
  5621. if(battle_get_mode(bl)&0x20)
  5622. sec = sec/5;
  5623. battle_stopwalking(bl,1);
  5624. skill_status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
  5625. if(moveblock) map_delblock(bl);
  5626. bl->x = src->bl.x;
  5627. bl->y = src->bl.y;
  5628. if(moveblock) map_addblock(bl);
  5629. if(bl->type == BL_MOB)
  5630. clif_fixmobpos((struct mob_data *)bl);
  5631. else if(bl->type == BL_PET)
  5632. clif_fixpetpos((struct pet_data *)bl);
  5633. else
  5634. clif_fixpos(bl);
  5635. clif_01ac(&src->bl);
  5636. sg->limit=DIFF_TICK(tick,sg->tick) + sec;
  5637. sg->val2=bl->id;
  5638. }
  5639. }
  5640. break;
  5641. case 0x80: /* ワ?プポ?タル(?動後) */
  5642. if(bl->type==BL_PC){
  5643. struct map_session_data *sd = (struct map_session_data *)bl;
  5644. if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) {
  5645. if( battle_config.chat_warpportal || !sd->chatID ){
  5646. if((sg->val1--)>0){
  5647. pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3);
  5648. if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) ))
  5649. skill_delunitgroup(sg);
  5650. }else
  5651. skill_delunitgroup(sg);
  5652. }
  5653. }
  5654. }else if(bl->type==BL_MOB && battle_config.mob_warpportal){
  5655. int m=map_mapname2mapid(sg->valstr);
  5656. struct mob_data *md;
  5657. md=(struct mob_data *)bl;
  5658. mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
  5659. }
  5660. break;
  5661. case 0x8e: /* クァグマイア */
  5662. {
  5663. struct status_change *sc_data=battle_get_sc_data(bl);
  5664. int type=SkillStatusChangeTable[sg->skill_id];
  5665. if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
  5666. break;
  5667. if(sc_data && sc_data[type].timer==-1)
  5668. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5669. }
  5670. break;
  5671. case 0x92: /* ベノムダスト */
  5672. {
  5673. struct status_change *sc_data=battle_get_sc_data(bl);
  5674. int type=SkillStatusChangeTable[sg->skill_id];
  5675. if(sc_data && sc_data[type].timer==-1 )
  5676. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5677. }
  5678. break;
  5679. case 0x9a: /* ボルケ?ノ */
  5680. case 0x9b: /* デリュ?ジ */
  5681. case 0x9c: /* バイオレントゲイル */
  5682. {
  5683. struct skill_unit *unit2;
  5684. struct status_change *sc_data=battle_get_sc_data(bl);
  5685. int type=SkillStatusChangeTable[sg->skill_id];
  5686. if(sc_data) {
  5687. if (sc_data[type].timer==-1)
  5688. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5689. else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
  5690. if( unit2->group != 0 && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
  5691. skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5692. ts->tick-=sg->interval;
  5693. }
  5694. }
  5695. } break;
  5696. case 0x9e: /* 子守唄 */
  5697. case 0x9f: /* ニヨルドの宴 */
  5698. case 0xa0: /* 永遠の混沌 */
  5699. case 0xa1: /* ?太鼓の響き */
  5700. case 0xa2: /* ニ?ベルングの指輪 */
  5701. case 0xa3: /* ロキの叫び */
  5702. case 0xa4: /* 深淵の中に */
  5703. case 0xa5: /* 不死身のジ?クフリ?ド */
  5704. case 0xa6: /* 不協和音 */
  5705. case 0xa7: /* 口笛 */
  5706. case 0xa8: /* 夕陽のアサシンクロス */
  5707. case 0xa9: /* ブラギの詩 */
  5708. case 0xab: /* 自分勝手なダンス */
  5709. case 0xac: /* ハミング */
  5710. case 0xad: /* 私を忘れないで… */
  5711. case 0xae: /* 幸運のキス */
  5712. case 0xaf: /* サ?ビスフォ?ユ? */
  5713. case 0xb4:
  5714. // case 0xb6: /* フォグウォ?ル */
  5715. {
  5716. struct skill_unit *unit2;
  5717. struct status_change *sc_data=battle_get_sc_data(bl);
  5718. int type=SkillStatusChangeTable[sg->skill_id];
  5719. if(sg->src_id == bl->id)
  5720. break;
  5721. if(sc_data) {
  5722. if (sc_data[type].timer==-1)
  5723. skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
  5724. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5725. else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
  5726. if( unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
  5727. skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
  5728. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5729. ts->tick-=sg->interval;
  5730. }
  5731. }
  5732. } break;
  5733. case 0xaa: /* イドゥンの林檎 */
  5734. {
  5735. struct skill_unit *unit2;
  5736. struct status_change *sc_data=battle_get_sc_data(bl);
  5737. int type=SkillStatusChangeTable[sg->skill_id];
  5738. if(sg->src_id == bl->id)
  5739. break;
  5740. if(sc_data) {
  5741. if (sc_data[type].timer==-1)
  5742. skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
  5743. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5744. else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
  5745. if( unit2->group != 0 && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
  5746. skill_status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
  5747. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5748. ts->tick-=sg->interval;
  5749. }
  5750. }
  5751. } break;
  5752. case 0xb6: /* フォグウォ?ル */
  5753. {
  5754. struct skill_unit *unit2;
  5755. struct status_change *sc_data=battle_get_sc_data(bl);
  5756. int type=SkillStatusChangeTable[sg->skill_id];
  5757. if(sc_data) {
  5758. if (sc_data[type].timer==-1) {
  5759. skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
  5760. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5761. skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
  5762. }
  5763. else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
  5764. if( unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) {
  5765. skill_status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
  5766. (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
  5767. skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
  5768. }
  5769. // ts->tick-=sg->interval;
  5770. }
  5771. }
  5772. } break;
  5773. case 0xb1: /* デモンストレ?ション */
  5774. skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
  5775. if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking)
  5776. pc_breakweapon((struct map_session_data *)bl);
  5777. break;
  5778. case 0x99: /* ト?キ?ボックス */
  5779. if(sg->src_id == bl->id) //自分が踏んでも?動しない
  5780. break;
  5781. if(sg->val2==0){
  5782. clif_talkiebox(&src->bl,sg->valstr);
  5783. sg->unit_id = 0x8c;
  5784. clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
  5785. sg->limit=DIFF_TICK(tick,sg->tick)+5000;
  5786. sg->val2=-1; //踏んだ
  5787. }
  5788. break;
  5789. case 0xb2: /* あなたを_?いたいです */
  5790. case 0xb3: /* ゴスペル */
  5791. //case 0xb6: /* フォグウォ?ル */ - moved [celest]
  5792. //とりあえず何もしない
  5793. break;
  5794. case 0xb7: /* スパイダ?ウェッブ */
  5795. if(sg->val2==0){
  5796. int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
  5797. skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
  5798. if(moveblock) map_delblock(bl);
  5799. bl->x = (&src->bl)->x;
  5800. bl->y = (&src->bl)->y;
  5801. if(moveblock) map_addblock(bl);
  5802. if(bl->type == BL_MOB)
  5803. clif_fixmobpos((struct mob_data *)bl);
  5804. else if(bl->type == BL_PET)
  5805. clif_fixpetpos((struct pet_data *)bl);
  5806. else
  5807. clif_fixpos(bl);
  5808. clif_01ac(&src->bl);
  5809. sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv);
  5810. sg->val2=bl->id;
  5811. }
  5812. break;
  5813. // New guild skills [Celest]
  5814. case 0xc1: // GD_LEADERSHIP
  5815. {
  5816. struct map_session_data *sd;
  5817. if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
  5818. sd->status.guild_id == srcsd->status.guild_id &&
  5819. sd->sc_data[SC_LEADERSHIP].timer == -1 && !sd->sc_data[SC_LEADERSHIP].val4)
  5820. skill_status_change_start(bl,SC_LEADERSHIP,1,0,0,0,0,0 );
  5821. }
  5822. break;
  5823. case 0xc2: // GD_GLORYWOUNDS
  5824. {
  5825. struct map_session_data *sd;
  5826. if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
  5827. sd->status.guild_id == srcsd->status.guild_id &&
  5828. sd->sc_data[SC_GLORYWOUNDS].timer == -1 && !sd->sc_data[SC_GLORYWOUNDS].val4)
  5829. skill_status_change_start(bl,SC_GLORYWOUNDS,1,0,0,0,0,0 );
  5830. }
  5831. break;
  5832. case 0xc3: // GD_SOULCOLD
  5833. {
  5834. struct map_session_data *sd;
  5835. if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
  5836. sd->status.guild_id == srcsd->status.guild_id &&
  5837. sd->sc_data[SC_SOULCOLD].timer == -1 && !sd->sc_data[SC_SOULCOLD].val4)
  5838. skill_status_change_start(bl,SC_SOULCOLD,1,0,0,0,0,0 );
  5839. }
  5840. break;
  5841. case 0xc4: // GD_HAWKEYES
  5842. {
  5843. struct map_session_data *sd;
  5844. if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
  5845. sd->status.guild_id == srcsd->status.guild_id &&
  5846. sd->sc_data[SC_HAWKEYES].timer == -1 && !sd->sc_data[SC_HAWKEYES].val4)
  5847. skill_status_change_start(bl,SC_HAWKEYES,1,0,0,0,0,0 );
  5848. }
  5849. break;
  5850. /* default:
  5851. if(battle_config.error_log)
  5852. printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
  5853. break;*/
  5854. }
  5855. if(bl->type==BL_MOB && ss!=bl) /* スキル使用?件のMOBスキル */
  5856. {
  5857. if(battle_config.mob_changetarget_byskill == 1)
  5858. {
  5859. int target=((struct mob_data *)bl)->target_id;
  5860. if(ss->type == BL_PC)
  5861. ((struct mob_data *)bl)->target_id=ss->id;
  5862. mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(sg->skill_id<<16));
  5863. ((struct mob_data *)bl)->target_id=target;
  5864. }
  5865. else
  5866. mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(sg->skill_id<<16));
  5867. }
  5868. return 0;
  5869. }
  5870. /*==========================================
  5871. * スキルユニットから離?する(もしくはしている)場合
  5872. *------------------------------------------
  5873. */
  5874. int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick)
  5875. {
  5876. struct skill_unit_group *sg;
  5877. nullpo_retr(0, src);
  5878. nullpo_retr(0, bl);
  5879. nullpo_retr(0, sg=src->group);
  5880. if( bl->prev==NULL || !src->alive )
  5881. return 0;
  5882. if( bl->type!=BL_PC && bl->type!=BL_MOB )
  5883. return 0;
  5884. switch(sg->unit_id){
  5885. case 0x7e: /* セイフティウォ?ル */
  5886. case 0x85: /* ニュ?マ */
  5887. case 0x8e: /* クァグマイア */
  5888. {
  5889. struct status_change *sc_data=battle_get_sc_data(bl);
  5890. int type=
  5891. (sg->unit_id==0x85)?SC_PNEUMA:
  5892. ((sg->unit_id==0x7e)?SC_SAFETYWALL:
  5893. SC_QUAGMIRE);
  5894. if((type != SC_QUAGMIRE || bl->type != BL_MOB) &&
  5895. sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){
  5896. skill_status_change_end(bl,type,-1);
  5897. }
  5898. } break;
  5899. case 0x91: /* アンクルスネア */
  5900. {
  5901. struct block_list *target=map_id2bl(sg->val2);
  5902. if( target && target==bl ){
  5903. skill_status_change_end(bl,SC_ANKLE,-1);
  5904. sg->limit=DIFF_TICK(tick,sg->tick)+1000;
  5905. }
  5906. }
  5907. break;
  5908. case 0xb5:
  5909. case 0xb8:
  5910. {
  5911. struct block_list *target=map_id2bl(sg->val2);
  5912. if( target==bl )
  5913. skill_status_change_end(bl,SC_SPIDERWEB,-1);
  5914. sg->limit=DIFF_TICK(tick,sg->tick)+1000;
  5915. }
  5916. break;
  5917. case 0xb6:
  5918. {
  5919. struct block_list *target=map_id2bl(sg->val2);
  5920. struct status_change *sc_data=battle_get_sc_data(bl);
  5921. if( target==bl ) {
  5922. skill_status_change_end(bl,SC_FOGWALL,-1);
  5923. if (sc_data && sc_data[SC_BLIND].timer!=-1)
  5924. sc_data[SC_BLIND].timer = add_timer(
  5925. gettick() + 30000, skill_status_change_timer, bl->id, 0);
  5926. }
  5927. //sg->limit=DIFF_TICK(tick,sg->tick)+1000;
  5928. }
  5929. break;
  5930. case 0x9a: /* ボルケ?ノ */
  5931. case 0x9b: /* デリュ?ジ */
  5932. case 0x9c: /* バイオレントゲイル */
  5933. {
  5934. struct status_change *sc_data=battle_get_sc_data(bl);
  5935. struct skill_unit *su;
  5936. int type=SkillStatusChangeTable[sg->skill_id];
  5937. if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){
  5938. skill_status_change_end(bl,type,-1);
  5939. }
  5940. }
  5941. break;
  5942. case 0x9e: /* 子守唄 */
  5943. case 0x9f: /* ニヨルドの宴 */
  5944. case 0xa0: /* 永遠の混沌 */
  5945. case 0xa1: /* ?太鼓の響き */
  5946. case 0xa2: /* ニ?ベルングの指輪 */
  5947. case 0xa3: /* ロキの叫び */
  5948. case 0xa4: /* 深淵の中に */
  5949. case 0xa5: /* 不死身のジ?クフリ?ド */
  5950. case 0xa6: /* 不協和音 */
  5951. case 0xa7: /* 口笛 */
  5952. case 0xa8: /* 夕陽のアサシンクロス */
  5953. case 0xa9: /* ブラギの詩 */
  5954. case 0xaa: /* イドゥンの林檎 */
  5955. case 0xab: /* 自分勝手なダンス */
  5956. case 0xac: /* ハミング */
  5957. case 0xad: /* 私を忘れないで… */
  5958. case 0xae: /* 幸運のキス */
  5959. case 0xaf: /* サ?ビスフォ?ユ? */
  5960. case 0xb4:
  5961. {
  5962. struct status_change *sc_data=battle_get_sc_data(bl);
  5963. struct skill_unit *su;
  5964. int type=SkillStatusChangeTable[sg->skill_id];
  5965. if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){
  5966. skill_status_change_end(bl,type,-1);
  5967. }
  5968. }
  5969. break;
  5970. case 0xb7: /* スパイダ?ウェッブ */
  5971. {
  5972. struct block_list *target=map_id2bl(sg->val2);
  5973. if( target && target==bl )
  5974. skill_status_change_end(bl,SC_SPIDERWEB,-1);
  5975. sg->limit=DIFF_TICK(tick,sg->tick)+1000;
  5976. }
  5977. break;
  5978. // New guild skills [Celest]
  5979. case 0xc1: // GD_LEADERSHIP
  5980. {
  5981. struct status_change *sc_data=battle_get_sc_data(bl);
  5982. if (sc_data && sc_data[SC_LEADERSHIP].timer != -1)
  5983. skill_status_change_end(bl,SC_LEADERSHIP,-1);
  5984. }
  5985. break;
  5986. case 0xc2: // GD_GLORYWOUNDS
  5987. {
  5988. struct status_change *sc_data=battle_get_sc_data(bl);
  5989. if (sc_data && sc_data[SC_GLORYWOUNDS].timer != -1)
  5990. skill_status_change_end(bl,SC_GLORYWOUNDS,-1);
  5991. }
  5992. break;
  5993. case 0xc3: // GD_SOULCOLD
  5994. {
  5995. struct status_change *sc_data=battle_get_sc_data(bl);
  5996. if (sc_data && sc_data[SC_SOULCOLD].timer != -1)
  5997. skill_status_change_end(bl,SC_SOULCOLD,-1);
  5998. }
  5999. break;
  6000. case 0xc4: // GD_HAWKEYES
  6001. {
  6002. struct status_change *sc_data=battle_get_sc_data(bl);
  6003. if (sc_data && sc_data[SC_HAWKEYES].timer != -1)
  6004. skill_status_change_end(bl,SC_HAWKEYES,-1);
  6005. }
  6006. break;
  6007. /* default:
  6008. if(battle_config.error_log)
  6009. printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
  6010. break;*/
  6011. }
  6012. skill_unitgrouptickset_delete(bl,sg->group_id);
  6013. return 0;
  6014. }
  6015. /*==========================================
  6016. * スキルユニットの削除イベント
  6017. *------------------------------------------
  6018. */
  6019. int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick)
  6020. {
  6021. struct skill_unit_group *sg;
  6022. nullpo_retr(0, src);
  6023. nullpo_retr(0, bl);
  6024. nullpo_retr(0, sg = src->group);
  6025. if( bl->prev==NULL || !src->alive )
  6026. return 0;
  6027. if( bl->type!=BL_PC && bl->type!=BL_MOB )
  6028. return 0;
  6029. switch(sg->unit_id){
  6030. case 0x85: /* ニュ?マ */
  6031. case 0x7e: /* セイフティウォ?ル */
  6032. case 0x8e: /* クァグマイヤ */
  6033. case 0x9a: /* ボルケ?ノ */
  6034. case 0x9b: /* デリュ?ジ */
  6035. case 0x9c: /* バイオレントゲイル */
  6036. case 0x9e: /* 子守唄 */
  6037. case 0x9f: /* ニヨルドの宴 */
  6038. case 0xa0: /* 永遠の混沌 */
  6039. case 0xa1: /* ?太鼓の響き */
  6040. case 0xa2: /* ニ?ベルングの指輪 */
  6041. case 0xa3: /* ロキの叫び */
  6042. case 0xa4: /* 深淵の中に */
  6043. case 0xa5: /* 不死身のジ?クフリ?ド */
  6044. case 0xa6: /* 不協和音 */
  6045. case 0xa7: /* 口笛 */
  6046. case 0xa8: /* 夕陽のアサシンクロス */
  6047. case 0xa9: /* ブラギの詩 */
  6048. case 0xaa: /* イドゥンの林檎 */
  6049. case 0xab: /* 自分勝手なダンス */
  6050. case 0xac: /* ハミング */
  6051. case 0xad: /* 私を忘れないで… */
  6052. case 0xae: /* 幸運のキス */
  6053. case 0xaf: /* サ?ビスフォ?ユ? */
  6054. case 0xb4:
  6055. case 0xc1:
  6056. case 0xc2:
  6057. case 0xc3:
  6058. case 0xc4:
  6059. return skill_unit_onout(src,bl,tick);
  6060. /* default:
  6061. if(battle_config.error_log)
  6062. printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
  6063. break;*/
  6064. }
  6065. skill_unitgrouptickset_delete(bl,sg->group_id);
  6066. return 0;
  6067. }
  6068. /*==========================================
  6069. * スキルユニットの限界イベント
  6070. *------------------------------------------
  6071. */
  6072. int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
  6073. {
  6074. struct skill_unit_group *sg;
  6075. nullpo_retr(0, src);
  6076. nullpo_retr(0, sg=src->group);
  6077. switch(sg->unit_id){
  6078. case 0x81: /* ワ?プポ?タル(?動前) */
  6079. {
  6080. struct skill_unit_group *group=
  6081. skill_unitsetting(map_id2bl(sg->src_id),sg->skill_id,sg->skill_lv,
  6082. src->bl.x,src->bl.y,1);
  6083. if(group == NULL)
  6084. return 0;
  6085. group->valstr=calloc(24, 1);
  6086. if(group->valstr==NULL){
  6087. printf("skill_unit_onlimit: out of memory !\n");
  6088. exit(1);
  6089. }
  6090. memcpy(group->valstr,sg->valstr,24);
  6091. group->val2=sg->val2;
  6092. }
  6093. break;
  6094. case 0x8d: /* アイスウォ?ル */
  6095. map_setcell(src->bl.m,src->bl.x,src->bl.y,src->val2);
  6096. clif_changemapcell(src->bl.m,src->bl.x,src->bl.y,src->val2,1);
  6097. break;
  6098. case 0xb2: /* あなたに?いたい */
  6099. {
  6100. struct map_session_data *sd = NULL;
  6101. struct map_session_data *p_sd = NULL;
  6102. if((sd = (struct map_session_data *)(map_id2bl(sg->src_id))) == NULL)
  6103. return 0;
  6104. if((p_sd = pc_get_partner(sd)) == NULL)
  6105. return 0;
  6106. pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3);
  6107. }
  6108. break;
  6109. case 0xc1: // GD_LEADERSHIP
  6110. {
  6111. struct map_session_data *sd;
  6112. if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
  6113. sd->sc_data[SC_LEADERSHIP].val4 = 0;
  6114. }
  6115. }
  6116. break;
  6117. case 0xc2: // GD_GLORYWOUNDS
  6118. {
  6119. struct map_session_data *sd;
  6120. if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
  6121. sd->sc_data[SC_GLORYWOUNDS].val4 = 0;
  6122. }
  6123. }
  6124. break;
  6125. case 0xc3: // GD_SOULCOLD
  6126. {
  6127. struct map_session_data *sd;
  6128. if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
  6129. sd->sc_data[SC_SOULCOLD].val4 = 0;
  6130. }
  6131. }
  6132. break;
  6133. case 0xc4: // GD_HAWKEYES
  6134. {
  6135. struct map_session_data *sd;
  6136. if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
  6137. sd->sc_data[SC_HAWKEYES].val4 = 0;
  6138. }
  6139. }
  6140. break;
  6141. }
  6142. return 0;
  6143. }
  6144. /*==========================================
  6145. * スキルユニットのダメ?ジイベント
  6146. *------------------------------------------
  6147. */
  6148. int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
  6149. int damage,unsigned int tick)
  6150. {
  6151. struct skill_unit_group *sg;
  6152. nullpo_retr(0, src);
  6153. nullpo_retr(0, sg=src->group);
  6154. switch(sg->unit_id){
  6155. case 0x8d: /* アイスウォ?ル */
  6156. src->val1-=damage;
  6157. break;
  6158. case 0x8f: /* ブラストマイン */
  6159. case 0x98: /* クレイモア?トラップ */
  6160. skill_blown(bl,&src->bl,2); //吹き飛ばしてみる
  6161. break;
  6162. default:
  6163. damage = 0;
  6164. break;
  6165. }
  6166. return damage;
  6167. }
  6168. /*---------------------------------------------------------------------------- */
  6169. /*==========================================
  6170. * スキル使用(詠唱完了、場所指定)
  6171. *------------------------------------------
  6172. */
  6173. int skill_castend_pos( int tid, unsigned int tick, int id,int data )
  6174. {
  6175. struct map_session_data* sd=map_id2sd(id)/*,*target_sd=NULL*/;
  6176. int range,maxcount;
  6177. nullpo_retr(0, sd);
  6178. if( sd->bl.prev == NULL )
  6179. return 0;
  6180. if( sd->skilltimer != tid ) /* タイマIDの確認 */
  6181. return 0;
  6182. if(sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) > 0) {
  6183. sd->speed = sd->prev_speed;
  6184. clif_updatestatus(sd,SP_SPEED);
  6185. }
  6186. sd->skilltimer=-1;
  6187. if(pc_isdead(sd)) {
  6188. sd->canact_tick = tick;
  6189. sd->canmove_tick = tick;
  6190. sd->skillitem = sd->skillitemlv = -1;
  6191. return 0;
  6192. }
  6193. if(battle_config.pc_skill_reiteration == 0) {
  6194. range = -1;
  6195. switch(sd->skillid) {
  6196. case MG_SAFETYWALL:
  6197. case WZ_FIREPILLAR:
  6198. case HT_SKIDTRAP:
  6199. case HT_LANDMINE:
  6200. case HT_ANKLESNARE:
  6201. case HT_SHOCKWAVE:
  6202. case HT_SANDMAN:
  6203. case HT_FLASHER:
  6204. case HT_FREEZINGTRAP:
  6205. case HT_BLASTMINE:
  6206. case HT_CLAYMORETRAP:
  6207. case HT_TALKIEBOX:
  6208. case AL_WARP:
  6209. case PF_SPIDERWEB: /* スパイダ?ウェッブ */
  6210. case RG_GRAFFITI: /* グラフィティ */
  6211. range = 0;
  6212. break;
  6213. case AL_PNEUMA:
  6214. range = 1;
  6215. break;
  6216. }
  6217. if(range >= 0) {
  6218. if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) {
  6219. clif_skill_fail(sd,sd->skillid,0,0);
  6220. sd->canact_tick = tick;
  6221. sd->canmove_tick = tick;
  6222. sd->skillitem = sd->skillitemlv = -1;
  6223. return 0;
  6224. }
  6225. }
  6226. }
  6227. if(battle_config.pc_skill_nofootset) {
  6228. range = -1;
  6229. switch(sd->skillid) {
  6230. case WZ_FIREPILLAR:
  6231. case HT_SKIDTRAP:
  6232. case HT_LANDMINE:
  6233. case HT_ANKLESNARE:
  6234. case HT_SHOCKWAVE:
  6235. case HT_SANDMAN:
  6236. case HT_FLASHER:
  6237. case HT_FREEZINGTRAP:
  6238. case HT_BLASTMINE:
  6239. case HT_CLAYMORETRAP:
  6240. case HT_TALKIEBOX:
  6241. case PF_SPIDERWEB: /* スパイダ?ウェッブ */
  6242. case WZ_ICEWALL:
  6243. range = 1;
  6244. break;
  6245. case AL_WARP:
  6246. range = 0;
  6247. break;
  6248. }
  6249. if(range >= 0) {
  6250. if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) {
  6251. clif_skill_fail(sd,sd->skillid,0,0);
  6252. sd->canact_tick = tick;
  6253. sd->canmove_tick = tick;
  6254. sd->skillitem = sd->skillitemlv = -1;
  6255. return 0;
  6256. }
  6257. }
  6258. }
  6259. if(battle_config.pc_land_skill_limit) {
  6260. maxcount = skill_get_maxcount(sd->skillid);
  6261. if(maxcount > 0) {
  6262. int i,c;
  6263. for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
  6264. if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == sd->skillid)
  6265. c++;
  6266. }
  6267. if(c >= maxcount) {
  6268. clif_skill_fail(sd,sd->skillid,0,0);
  6269. sd->canact_tick = tick;
  6270. sd->canmove_tick = tick;
  6271. sd->skillitem = sd->skillitemlv = -1;
  6272. return 0;
  6273. }
  6274. }
  6275. }
  6276. if(sd->skilllv <= 0) return 0;
  6277. range = skill_get_range(sd->skillid,sd->skilllv);
  6278. if(range < 0)
  6279. range = battle_get_range(&sd->bl) - (range + 1);
  6280. range += battle_config.pc_skill_add_range;
  6281. if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
  6282. if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
  6283. clif_skill_fail(sd,sd->skillid,0,0);
  6284. sd->canact_tick = tick;
  6285. sd->canmove_tick = tick;
  6286. sd->skillitem = sd->skillitemlv = -1;
  6287. return 0;
  6288. }
  6289. }
  6290. if(!skill_check_condition(sd,1)) { /* 使用?件チェック */
  6291. sd->canact_tick = tick;
  6292. sd->canmove_tick = tick;
  6293. sd->skillitem = sd->skillitemlv = -1;
  6294. return 0;
  6295. }
  6296. sd->skillitem = sd->skillitemlv = -1;
  6297. if(battle_config.skill_out_range_consume) {
  6298. if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
  6299. clif_skill_fail(sd,sd->skillid,0,0);
  6300. sd->canact_tick = tick;
  6301. sd->canmove_tick = tick;
  6302. return 0;
  6303. }
  6304. }
  6305. if(battle_config.pc_skill_log)
  6306. printf("PC %d skill castend skill=%d\n",sd->bl.id,sd->skillid);
  6307. pc_stop_walking(sd,0);
  6308. skill_castend_pos2(&sd->bl,sd->skillx,sd->skilly,sd->skillid,sd->skilllv,tick,0);
  6309. return 0;
  6310. }
  6311. /*==========================================
  6312. * 範??キャラ存在確認判定?理(foreachinarea)
  6313. *------------------------------------------
  6314. */
  6315. static int skill_check_condition_char_sub(struct block_list *bl,va_list ap)
  6316. {
  6317. int *c;
  6318. struct block_list *src;
  6319. struct map_session_data *sd;
  6320. struct map_session_data *ssd;
  6321. struct pc_base_job s_class;
  6322. struct pc_base_job ss_class;
  6323. nullpo_retr(0, bl);
  6324. nullpo_retr(0, ap);
  6325. nullpo_retr(0, sd=(struct map_session_data*)bl);
  6326. nullpo_retr(0, src=va_arg(ap,struct block_list *));
  6327. nullpo_retr(0, c=va_arg(ap,int *));
  6328. nullpo_retr(0, ssd=(struct map_session_data*)src);
  6329. s_class = pc_calc_base_job(sd->status.class);
  6330. //チェックしない設定ならcにありえない大きな?字を返して終了
  6331. if(!battle_config.player_skill_partner_check){ //本?はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
  6332. (*c)=99;
  6333. return 0;
  6334. }
  6335. ss_class = pc_calc_base_job(ssd->status.class);
  6336. switch(ssd->skillid){
  6337. case PR_BENEDICTIO: /* 聖?降福 */
  6338. if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
  6339. (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10)
  6340. (*c)++;
  6341. break;
  6342. case BD_LULLABY: /* 子守歌 */
  6343. case BD_RICHMANKIM: /* ニヨルドの宴 */
  6344. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  6345. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  6346. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  6347. case BD_ROKISWEIL: /* ロキの叫び */
  6348. case BD_INTOABYSS: /* 深淵の中に */
  6349. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  6350. case BD_RAGNAROK: /* 神?の?昏 */
  6351. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  6352. if(sd != ssd &&
  6353. ((ss_class.job==19 && s_class.job==20) ||
  6354. (ss_class.job==20 && s_class.job==19)) &&
  6355. pc_checkskill(sd,ssd->skillid) > 0 &&
  6356. (*c)==0 &&
  6357. sd->status.party_id == ssd->status.party_id &&
  6358. !pc_issit(sd) &&
  6359. sd->sc_data[SC_DANCING].timer==-1
  6360. )
  6361. (*c)=pc_checkskill(sd,ssd->skillid);
  6362. break;
  6363. }
  6364. return 0;
  6365. }
  6366. /*==========================================
  6367. * 範??キャラ存在確認判定後スキル使用?理(foreachinarea)
  6368. *------------------------------------------
  6369. */
  6370. static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
  6371. {
  6372. int *c;
  6373. struct block_list *src;
  6374. struct map_session_data *sd;
  6375. struct map_session_data *ssd;
  6376. struct pc_base_job s_class;
  6377. struct pc_base_job ss_class;
  6378. int skillid,skilllv;
  6379. nullpo_retr(0, bl);
  6380. nullpo_retr(0, ap);
  6381. nullpo_retr(0, sd=(struct map_session_data*)bl);
  6382. nullpo_retr(0, src=va_arg(ap,struct block_list *));
  6383. nullpo_retr(0, c=va_arg(ap,int *));
  6384. nullpo_retr(0, ssd=(struct map_session_data*)src);
  6385. s_class = pc_calc_base_job(sd->status.class);
  6386. //チェックしない設定ならcにありえない大きな?字を返して終了
  6387. if(!battle_config.player_skill_partner_check){ //本?はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
  6388. (*c)=99;
  6389. return 0;
  6390. }
  6391. ss_class = pc_calc_base_job(ssd->status.class);
  6392. skillid=ssd->skillid;
  6393. skilllv=ssd->skilllv;
  6394. //if(skilllv <= 0) return 0;
  6395. if(skillid > 0 && skilllv <= 0) return 0; // celest
  6396. switch(skillid){
  6397. case PR_BENEDICTIO: /* 聖?降福 */
  6398. if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
  6399. (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){
  6400. sd->status.sp -= 10;
  6401. pc_calcstatus(sd,0);
  6402. (*c)++;
  6403. }
  6404. break;
  6405. case BD_LULLABY: /* 子守歌 */
  6406. case BD_RICHMANKIM: /* ニヨルドの宴 */
  6407. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  6408. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  6409. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  6410. case BD_ROKISWEIL: /* ロキの叫び */
  6411. case BD_INTOABYSS: /* 深淵の中に */
  6412. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  6413. case BD_RAGNAROK: /* 神?の?昏 */
  6414. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  6415. if(sd != ssd && //本人以外で
  6416. ((ss_class.job==19 && s_class.job==20) || //自分がバ?ドならダンサ?で
  6417. (ss_class.job==20 && s_class.job==19)) && //自分がダンサ?ならバ?ドで
  6418. pc_checkskill(sd,skillid) > 0 && //スキルを持っていて
  6419. (*c)==0 && //最初の一人で
  6420. sd->status.party_id == ssd->status.party_id && //パ?ティ?が同じで
  6421. !pc_issit(sd) && //座ってない
  6422. sd->sc_data[SC_DANCING].timer==-1 //ダンス中じゃない
  6423. ){
  6424. ssd->sc_data[SC_DANCING].val4=bl->id;
  6425. clif_skill_nodamage(bl,src,skillid,skilllv,1);
  6426. skill_status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0);
  6427. sd->skillid_dance=sd->skillid=skillid;
  6428. sd->skilllv_dance=sd->skilllv=skilllv;
  6429. (*c)++;
  6430. }
  6431. break;
  6432. }
  6433. return 0;
  6434. }
  6435. /*==========================================
  6436. * 範??バイオプラント、スフィアマイン用Mob存在確認判定?理(foreachinarea)
  6437. *------------------------------------------
  6438. */
  6439. static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap)
  6440. {
  6441. int *c,src_id=0,mob_class=0;
  6442. struct mob_data *md;
  6443. nullpo_retr(0, bl);
  6444. nullpo_retr(0, ap);
  6445. nullpo_retr(0, md=(struct mob_data*)bl);
  6446. nullpo_retr(0, src_id=va_arg(ap,int));
  6447. nullpo_retr(0, mob_class=va_arg(ap,int));
  6448. nullpo_retr(0, c=va_arg(ap,int *));
  6449. if(md->class==mob_class && md->master_id==src_id)
  6450. (*c)++;
  6451. return 0;
  6452. }
  6453. /*==========================================
  6454. * スキル使用?件(?で使用失敗)
  6455. *------------------------------------------
  6456. */
  6457. int skill_check_condition(struct map_session_data *sd,int type)
  6458. {
  6459. int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp;
  6460. int index[10],itemid[10],amount[10];
  6461. int arrow_flag = 0;
  6462. nullpo_retr(0, sd);
  6463. if( battle_config.gm_skilluncond>0 && pc_isGM(sd)>= battle_config.gm_skilluncond ) {
  6464. sd->skillitem = sd->skillitemlv = -1;
  6465. return 1;
  6466. }
  6467. if( sd->opt1>0) {
  6468. clif_skill_fail(sd,sd->skillid,0,0);
  6469. sd->skillitem = sd->skillitemlv = -1;
  6470. return 0;
  6471. }
  6472. if(pc_is90overweight(sd)) {
  6473. clif_skill_fail(sd,sd->skillid,9,0);
  6474. sd->skillitem = sd->skillitemlv = -1;
  6475. return 0;
  6476. }
  6477. if(sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1) {
  6478. sd->skillitem = sd->skillitemlv = -1;
  6479. return 0;
  6480. }
  6481. if((sd->skillid == AM_PHARMACY || sd->skillid == ASC_CDP)
  6482. && sd->state.produce_flag == 1) {
  6483. sd->skillitem = sd->skillitemlv = -1;
  6484. return 0;
  6485. }
  6486. if(sd->skillitem == sd->skillid) { /* アイテムの場合無?件成功 */
  6487. if(type&1)
  6488. sd->skillitem = sd->skillitemlv = -1;
  6489. return 1;
  6490. }
  6491. if( sd->opt1>0 ){
  6492. clif_skill_fail(sd,sd->skillid,0,0);
  6493. return 0;
  6494. }
  6495. if(sd->sc_count){
  6496. if( sd->sc_data[SC_DIVINA].timer!=-1 ||
  6497. sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
  6498. (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
  6499. sd->sc_data[SC_STEELBODY].timer != -1 ||
  6500. sd->sc_data[SC_BERSERK].timer != -1 ||
  6501. (sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
  6502. clif_skill_fail(sd,sd->skillid,0,0);
  6503. return 0; /* ?態異常や沈?など */
  6504. }
  6505. }
  6506. skill = sd->skillid;
  6507. lv = sd->skilllv;
  6508. if(lv <= 0) return 0;
  6509. hp=skill_get_hp(skill, lv); /* 消費HP */
  6510. sp=skill_get_sp(skill, lv); /* 消費SP */
  6511. if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance)
  6512. sp=sp/2; //アンコ?ル時はSP消費が半分
  6513. hp_rate = (lv <= 0)? 0:skill_db[skill].hp_rate[lv-1];
  6514. sp_rate = (lv <= 0)? 0:skill_db[skill].sp_rate[lv-1];
  6515. zeny = skill_get_zeny(skill,lv);
  6516. weapon = skill_db[skill].weapon;
  6517. state = skill_db[skill].state;
  6518. spiritball = (lv <= 0)? 0:skill_db[skill].spiritball[lv-1];
  6519. mhp=skill_get_mhp(skill, lv); /* 消費HP */
  6520. for(i=0;i<10;i++) {
  6521. itemid[i] = skill_db[skill].itemid[i];
  6522. amount[i] = skill_db[skill].amount[i];
  6523. }
  6524. if(mhp > 0)
  6525. hp += (sd->status.max_hp * mhp)/100;
  6526. if(hp_rate > 0)
  6527. hp += (sd->status.hp * hp_rate)/100;
  6528. else
  6529. hp += (sd->status.max_hp * abs(hp_rate))/100;
  6530. if(sp_rate > 0)
  6531. sp += (sd->status.sp * sp_rate)/100;
  6532. else
  6533. sp += (sd->status.max_sp * abs(sp_rate))/100;
  6534. if(sd->dsprate!=100)
  6535. sp=sp*sd->dsprate/100; /* 消費SP修正 */
  6536. switch(skill) {
  6537. case SA_CASTCANCEL:
  6538. if(sd->skilltimer == -1) {
  6539. clif_skill_fail(sd,skill,0,0);
  6540. return 0;
  6541. }
  6542. break;
  6543. case BS_MAXIMIZE: /* マキシマイズパワ? */
  6544. case NV_TRICKDEAD: /* 死んだふり */
  6545. case TF_HIDING: /* ハイディング */
  6546. case AS_CLOAKING: /* クロ?キング */
  6547. case CR_AUTOGUARD: /* オ?トガ?ド */
  6548. case CR_DEFENDER: /* ディフェンダ? */
  6549. case ST_CHASEWALK:
  6550. if(sd->sc_data[SkillStatusChangeTable[skill]].timer!=-1)
  6551. return 1; /* 解除する場合はSP消費しない */
  6552. break;
  6553. case AL_TELEPORT:
  6554. case AL_WARP:
  6555. if(map[sd->bl.m].flag.noteleport) {
  6556. clif_skill_teleportmessage(sd,0);
  6557. return 0;
  6558. }
  6559. break;
  6560. case MO_CALLSPIRITS: /* ?功 */
  6561. if(sd->spiritball >= lv) {
  6562. clif_skill_fail(sd,skill,0,0);
  6563. return 0;
  6564. }
  6565. break;
  6566. case CH_SOULCOLLECT: /* 狂?功 */
  6567. if(sd->spiritball >= 5) {
  6568. clif_skill_fail(sd,skill,0,0);
  6569. return 0;
  6570. }
  6571. break;
  6572. case MO_FINGEROFFENSIVE: //指?
  6573. if (sd->spiritball > 0 && sd->spiritball < spiritball) {
  6574. spiritball = sd->spiritball;
  6575. sd->spiritball_old = sd->spiritball;
  6576. }
  6577. else sd->spiritball_old = lv;
  6578. break;
  6579. case MO_BODYRELOCATION:
  6580. if (sd->sc_count && sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
  6581. spiritball = 0;
  6582. break;
  6583. case MO_CHAINCOMBO: //連打掌
  6584. if(sd->sc_data[SC_BLADESTOP].timer==-1){
  6585. if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
  6586. return 0;
  6587. }
  6588. break;
  6589. case MO_COMBOFINISH: //猛龍拳
  6590. if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO)
  6591. return 0;
  6592. break;
  6593. case CH_TIGERFIST: //伏虎拳
  6594. if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
  6595. return 0;
  6596. break;
  6597. case CH_CHAINCRUSH: //連柱崩?
  6598. if(sd->sc_data[SC_COMBO].timer == -1)
  6599. return 0;
  6600. if(sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH && sd->sc_data[SC_COMBO].val1 != CH_TIGERFIST)
  6601. return 0;
  6602. break;
  6603. case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
  6604. if((sd->sc_data[SC_COMBO].timer != -1 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) || sd->sc_data[SC_BLADESTOP].timer!=-1)
  6605. spiritball--;
  6606. break;
  6607. case BD_ADAPTATION: /* アドリブ */
  6608. {
  6609. struct skill_unit_group *group=NULL;
  6610. if(sd->sc_data[SC_DANCING].timer==-1 || ((group=(struct skill_unit_group*)sd->sc_data[SC_DANCING].val2) && (skill_get_time(sd->sc_data[SC_DANCING].val1,group->skill_lv) - sd->sc_data[SC_DANCING].val3*1000) <= skill_get_time2(skill,lv))){ //ダンス中で使用後5秒以上のみ?
  6611. clif_skill_fail(sd,skill,0,0);
  6612. return 0;
  6613. }
  6614. }
  6615. break;
  6616. case PR_BENEDICTIO: /* 聖?降福 */
  6617. {
  6618. int range=1;
  6619. int c=0;
  6620. if(!(type&1)){
  6621. map_foreachinarea(skill_check_condition_char_sub,sd->bl.m,
  6622. sd->bl.x-range,sd->bl.y-range,
  6623. sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
  6624. if(c<2){
  6625. clif_skill_fail(sd,skill,0,0);
  6626. return 0;
  6627. }
  6628. }else{
  6629. map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
  6630. sd->bl.x-range,sd->bl.y-range,
  6631. sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
  6632. }
  6633. }
  6634. break;
  6635. case WE_CALLPARTNER: /* あなたに逢いたい */
  6636. if(!sd->status.partner_id){
  6637. clif_skill_fail(sd,skill,0,0);
  6638. return 0;
  6639. }
  6640. break;
  6641. case AM_CANNIBALIZE: /* バイオプラント */
  6642. case AM_SPHEREMINE: /* スフィア?マイン */
  6643. if(type&1){
  6644. int c=0;
  6645. int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
  6646. int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill);
  6647. int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142;
  6648. if(battle_config.pc_land_skill_limit && maxcount>0) {
  6649. map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c );
  6650. if(c >= maxcount){
  6651. clif_skill_fail(sd,skill,0,0);
  6652. return 0;
  6653. }
  6654. }
  6655. }
  6656. break;
  6657. case MG_FIREWALL: /* ファイア?ウォ?ル */
  6658. case WZ_QUAGMIRE:
  6659. case WZ_FIREPILLAR: // celest
  6660. case PF_FOGWALL:
  6661. /* ?制限 */
  6662. if(battle_config.pc_land_skill_limit) {
  6663. int maxcount = skill_get_maxcount(skill);
  6664. if(maxcount > 0) {
  6665. int i,c;
  6666. for(i=c=0;i<MAX_SKILLUNITGROUP;i++) {
  6667. if(sd->skillunit[i].alive_count > 0 && sd->skillunit[i].skill_id == skill)
  6668. c++;
  6669. }
  6670. if(c >= maxcount) {
  6671. clif_skill_fail(sd,skill,0,0);
  6672. return 0;
  6673. }
  6674. }
  6675. }
  6676. break;
  6677. // skills require arrows as of 12/07 [celest]
  6678. case AC_DOUBLE:
  6679. case AC_SHOWER:
  6680. case AC_CHARGEARROW:
  6681. case BA_MUSICALSTRIKE:
  6682. case DC_THROWARROW:
  6683. case SN_SHARPSHOOTING:
  6684. case CG_ARROWVULCAN:
  6685. if(sd->equip_index[10] < 0) {
  6686. clif_arrow_fail(sd,0);
  6687. return 0;
  6688. }
  6689. arrow_flag = 1;
  6690. break;
  6691. }
  6692. if(!(type&2)){
  6693. if( hp>0 && sd->status.hp < hp) { /* HPチェック */
  6694. clif_skill_fail(sd,skill,2,0); /* HP不足:失敗通知 */
  6695. return 0;
  6696. }
  6697. if( sp>0 && sd->status.sp < sp) { /* SPチェック */
  6698. clif_skill_fail(sd,skill,1,0); /* SP不足:失敗通知 */
  6699. return 0;
  6700. }
  6701. if( zeny>0 && sd->status.zeny < zeny) {
  6702. clif_skill_fail(sd,skill,5,0);
  6703. return 0;
  6704. }
  6705. if(!(weapon & (1<<sd->status.weapon) ) ) {
  6706. clif_skill_fail(sd,skill,6,0);
  6707. return 0;
  6708. }
  6709. if( spiritball > 0 && sd->spiritball < spiritball) {
  6710. clif_skill_fail(sd,skill,0,0); // 氣球不足
  6711. return 0;
  6712. }
  6713. }
  6714. switch(state) {
  6715. case ST_HIDING:
  6716. if(!(sd->status.option&2)) {
  6717. clif_skill_fail(sd,skill,0,0);
  6718. return 0;
  6719. }
  6720. break;
  6721. case ST_CLOAKING:
  6722. if(!(sd->status.option&4)) {
  6723. clif_skill_fail(sd,skill,0,0);
  6724. return 0;
  6725. }
  6726. break;
  6727. case ST_HIDDEN:
  6728. if(!pc_ishiding(sd)) {
  6729. clif_skill_fail(sd,skill,0,0);
  6730. return 0;
  6731. }
  6732. break;
  6733. case ST_RIDING:
  6734. if(!pc_isriding(sd)) {
  6735. clif_skill_fail(sd,skill,0,0);
  6736. return 0;
  6737. }
  6738. break;
  6739. case ST_FALCON:
  6740. if(!pc_isfalcon(sd)) {
  6741. clif_skill_fail(sd,skill,0,0);
  6742. return 0;
  6743. }
  6744. break;
  6745. case ST_CART:
  6746. if(!pc_iscarton(sd)) {
  6747. clif_skill_fail(sd,skill,0,0);
  6748. return 0;
  6749. }
  6750. break;
  6751. case ST_SHIELD:
  6752. if(sd->status.shield <= 0) {
  6753. clif_skill_fail(sd,skill,0,0);
  6754. return 0;
  6755. }
  6756. break;
  6757. case ST_SIGHT:
  6758. if(sd->sc_data[SC_SIGHT].timer == -1 && type&1) {
  6759. clif_skill_fail(sd,skill,0,0);
  6760. return 0;
  6761. }
  6762. break;
  6763. case ST_EXPLOSIONSPIRITS:
  6764. if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) {
  6765. clif_skill_fail(sd,skill,0,0);
  6766. return 0;
  6767. }
  6768. break;
  6769. case ST_RECOV_WEIGHT_RATE:
  6770. if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= battle_config.natural_heal_weight_rate) {
  6771. clif_skill_fail(sd,skill,0,0);
  6772. return 0;
  6773. }
  6774. break;
  6775. case ST_MOVE_ENABLE:
  6776. {
  6777. struct walkpath_data wpd;
  6778. if(path_search(&wpd,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillx,sd->skilly,1)==-1) {
  6779. clif_skill_fail(sd,skill,0,0);
  6780. return 0;
  6781. }
  6782. }
  6783. break;
  6784. case ST_WATER:
  6785. if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定
  6786. clif_skill_fail(sd,skill,0,0);
  6787. return 0;
  6788. }
  6789. break;
  6790. }
  6791. for(i=0;i<10;i++) {
  6792. int x = lv%11 - 1;
  6793. index[i] = -1;
  6794. if(itemid[i] <= 0)
  6795. continue;
  6796. if(itemid[i] >= 715 && itemid[i] <= 717 && sd->special_state.no_gemstone)
  6797. continue;
  6798. if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1)
  6799. continue;
  6800. if(skill == WZ_FIREPILLAR && lv<=5)
  6801. continue; // no gemstones for 1-5 [Celest]
  6802. if(skill == AM_POTIONPITCHER && i != x)
  6803. continue;
  6804. index[i] = pc_search_inventory(sd,itemid[i]);
  6805. if(index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) {
  6806. if(itemid[i] == 716 || itemid[i] == 717)
  6807. clif_skill_fail(sd,skill,(7+(itemid[i]-716)),0);
  6808. else
  6809. clif_skill_fail(sd,skill,0,0);
  6810. return 0;
  6811. }
  6812. }
  6813. if(!(type&1))
  6814. return 1;
  6815. if(skill != AM_POTIONPITCHER &&
  6816. skill != CR_SLIMPITCHER &&
  6817. skill != MG_STONECURSE) {
  6818. if(skill == AL_WARP && !(type&2))
  6819. return 1;
  6820. for(i=0;i<10;i++) {
  6821. if(index[i] >= 0)
  6822. pc_delitem(sd,index[i],amount[i],0); // アイテム消費
  6823. }
  6824. if (arrow_flag && battle_config.arrow_decrement)
  6825. pc_delitem(sd,sd->equip_index[10],1,0);
  6826. }
  6827. if(type&2)
  6828. return 1;
  6829. if(sp > 0) { // SP消費
  6830. sd->status.sp-=sp;
  6831. clif_updatestatus(sd,SP_SP);
  6832. }
  6833. if(hp > 0) { // HP消費
  6834. sd->status.hp-=hp;
  6835. clif_updatestatus(sd,SP_HP);
  6836. }
  6837. if(zeny > 0) // Zeny消費
  6838. pc_payzeny(sd,zeny);
  6839. if(spiritball > 0) // 氣球消費
  6840. pc_delspiritball(sd,spiritball,0);
  6841. return 1;
  6842. }
  6843. /*==========================================
  6844. * 詠唱時間計算
  6845. *------------------------------------------
  6846. */
  6847. int skill_castfix( struct block_list *bl, int time )
  6848. {
  6849. struct map_session_data *sd;
  6850. struct mob_data *md; // [Valaris]
  6851. struct status_change *sc_data;
  6852. int dex;
  6853. int castrate=100;
  6854. int skill,lv,castnodex;
  6855. nullpo_retr(0, bl);
  6856. if(bl->type==BL_MOB){ // Crash fix [Valaris]
  6857. md=(struct mob_data*)bl;
  6858. skill = md->skillid;
  6859. lv = md->skilllv;
  6860. }
  6861. else {
  6862. sd=(struct map_session_data*)bl;
  6863. skill = sd->skillid;
  6864. lv = sd->skilllv;
  6865. }
  6866. if(lv <= 0) return 0;
  6867. sc_data = battle_get_sc_data(bl);
  6868. dex=battle_get_dex(bl);
  6869. if (skill > MAX_SKILL_DB || skill < 0)
  6870. return 0;
  6871. castnodex=skill_get_castnodex(skill, lv);
  6872. if(time==0)
  6873. return 0;
  6874. if(castnodex > 0 && bl->type==BL_PC)
  6875. castrate=((struct map_session_data *)bl)->castrate;
  6876. else if (castnodex <= 0 && bl->type==BL_PC) {
  6877. castrate=((struct map_session_data *)bl)->castrate;
  6878. time=time*castrate*(battle_config.castrate_dex_scale - dex)/(battle_config.castrate_dex_scale * 100);
  6879. time=time*battle_config.cast_rate/100;
  6880. }
  6881. /* サフラギウム */
  6882. if(sc_data) {
  6883. if ( sc_data[SC_SUFFRAGIUM].timer!=-1 ){
  6884. time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
  6885. skill_status_change_end( bl, SC_SUFFRAGIUM, -1);
  6886. }
  6887. /* ブラギの詩 */
  6888. if( sc_data[SC_POEMBRAGI].timer!=-1 )
  6889. time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
  6890. +(sc_data[SC_POEMBRAGI].val3>>16)))/100;
  6891. }
  6892. return (time>0)?time:0;
  6893. }
  6894. /*==========================================
  6895. * ディレイ計算
  6896. *------------------------------------------
  6897. */
  6898. int skill_delayfix( struct block_list *bl, int time )
  6899. {
  6900. struct status_change *sc_data;
  6901. nullpo_retr(0, bl);
  6902. sc_data = battle_get_sc_data(bl);
  6903. if(time<=0)
  6904. return 0;
  6905. if(bl->type == BL_PC) {
  6906. if( battle_config.delay_dependon_dex ) /* dexの影響を計算する */
  6907. time=time*(battle_config.castrate_dex_scale - battle_get_dex(bl))/battle_config.castrate_dex_scale;
  6908. time=time*battle_config.delay_rate/100;
  6909. }
  6910. /* ブラギの詩 */
  6911. if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 )
  6912. time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
  6913. +(sc_data[SC_POEMBRAGI].val3&0xffff)))/100;
  6914. return (time>0)?time:0;
  6915. }
  6916. /*==========================================
  6917. * スキル使用(ID指定)
  6918. *------------------------------------------
  6919. */
  6920. int skill_use_id( struct map_session_data *sd, int target_id,
  6921. int skill_num, int skill_lv)
  6922. {
  6923. unsigned int tick;
  6924. int casttime=0,delay=0,skill,range;
  6925. struct map_session_data* target_sd=NULL;
  6926. int forcecast=0;
  6927. struct block_list *bl;
  6928. struct status_change *sc_data;
  6929. tick=gettick();
  6930. nullpo_retr(0, sd);
  6931. if( (bl=map_id2bl(target_id)) == NULL ){
  6932. /* if(battle_config.error_log)
  6933. printf("skill target not found %d\n",target_id); */
  6934. return 0;
  6935. }
  6936. if(sd->bl.m != bl->m || pc_isdead(sd))
  6937. return 0;
  6938. if(skillnotok(skill_num, sd)) // [MouseJstr]
  6939. return 0;
  6940. sc_data=sd->sc_data;
  6941. /* 沈?や異常(ただし、グリムなどの判定をする) */
  6942. if( sd->opt1>0 )
  6943. return 0;
  6944. if(sc_data){
  6945. // allow to use only Chasewalk [celest]
  6946. if(sc_data[SC_CHASEWALK].timer != -1 && skill_num != ST_CHASEWALK)
  6947. return 0;
  6948. if(sc_data[SC_VOLCANO].timer != -1){
  6949. if(skill_num==WZ_ICEWALL) return 0;
  6950. }
  6951. if(sc_data[SC_ROKISWEIL].timer!=-1){
  6952. if(skill_num==BD_ADAPTATION) return 0;
  6953. }
  6954. if(sc_data[SC_DIVINA].timer!=-1 ||
  6955. sc_data[SC_ROKISWEIL].timer!=-1 ||
  6956. (sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
  6957. sc_data[SC_STEELBODY].timer != -1 ||
  6958. sc_data[SC_BERSERK].timer != -1 ||
  6959. (sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
  6960. return 0; /* ?態異常や沈?など */
  6961. }
  6962. if(sc_data[SC_BLADESTOP].timer != -1){
  6963. int lv = sc_data[SC_BLADESTOP].val1;
  6964. if(sc_data[SC_BLADESTOP].val2==1) return 0;//白羽された側なのでダメ
  6965. if(lv==1) return 0;
  6966. if(lv==2 && skill_num!=MO_FINGEROFFENSIVE) return 0;
  6967. if(lv==3 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE) return 0;
  6968. if(lv==4 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO) return 0;
  6969. if(lv==5 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0;
  6970. }
  6971. if (sc_data[SC_BLOCKSKILL].timer!=-1)
  6972. if (skill_num == sc_data[SC_BLOCKSKILL].val3)
  6973. return 0;
  6974. if (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest]
  6975. struct skill_unit *su;
  6976. if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
  6977. struct skill_unit_group *sg;
  6978. // if caster is the owner of basilica
  6979. if ((sg = su->group) && sg->src_id == sd->bl.id) {
  6980. // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
  6981. // skill_delunitgroup (sg);
  6982. if (skill_num != HP_BASILICA) return 0;
  6983. } // otherwise...
  6984. else
  6985. return 0;
  6986. }
  6987. }
  6988. /* 演奏/ダンス中 */
  6989. if(sc_data[SC_DANCING].timer!=-1 ){
  6990. // if(battle_config.pc_skill_log)
  6991. // printf("dancing! %d\n",skill_num);
  6992. if( sc_data[SC_DANCING].val4 && skill_num!=BD_ADAPTATION ) //合奏中はアドリブ以外不可
  6993. return 0;
  6994. if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){
  6995. return 0;
  6996. }
  6997. }
  6998. }
  6999. if(sd->status.option&4 && skill_num==TF_HIDING)
  7000. return 0;
  7001. if(sd->status.option&2 && skill_num!=TF_HIDING && skill_num!=AS_GRIMTOOTH && skill_num!=RG_BACKSTAP && skill_num!=RG_RAID )
  7002. return 0;
  7003. /*if(map[sd->bl.m].flag.gvg){ //GvGで使用できないスキル
  7004. switch(skill_num){
  7005. case SM_ENDURE:
  7006. case AL_TELEPORT:
  7007. case AL_WARP:
  7008. case WZ_ICEWALL:
  7009. case TF_BACKSLIDING:
  7010. //case LK_BERSERK: // now usable in WoE - celest
  7011. case HP_BASILICA:
  7012. case HP_ASSUMPTIO:
  7013. case ST_CHASEWALK:
  7014. return 0;
  7015. }
  7016. }*/
  7017. if(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id)
  7018. return 0;
  7019. //直前のスキルが何か?える必要のあるスキル
  7020. switch(skill_num){
  7021. case SA_CASTCANCEL:
  7022. if(sd->skillid != skill_num){ //キャストキャンセル自?は?えない
  7023. sd->skillid_old = sd->skillid;
  7024. sd->skilllv_old = sd->skilllv;
  7025. break;
  7026. }
  7027. case BD_ENCORE: /* アンコ?ル */
  7028. if(!sd->skillid_dance){ //前回使用した踊りがないとだめ
  7029. clif_skill_fail(sd,skill_num,0,0);
  7030. return 0;
  7031. }else{
  7032. sd->skillid_old = skill_num;
  7033. }
  7034. break;
  7035. case GD_BATTLEORDER:
  7036. case GD_REGENERATION:
  7037. case GD_RESTORE:
  7038. case GD_EMERGENCYCALL:
  7039. {
  7040. struct guild *g;
  7041. if (!sd->status.guild_id)
  7042. return 0;
  7043. if ((g = guild_search(sd->status.guild_id)) == NULL)
  7044. return 0;
  7045. if (strcmp(sd->status.name,g->master))
  7046. return 0;
  7047. skill_lv = guild_checkskill(g, skill_num);
  7048. if (skill_lv <= 0) return 0;
  7049. }
  7050. break;
  7051. }
  7052. sd->skillid = skill_num;
  7053. sd->skilllv = skill_lv;
  7054. switch(skill_num){ //事前にレベルが?わったりするスキル
  7055. case BD_LULLABY: /* 子守歌 */
  7056. case BD_RICHMANKIM: /* ニヨルドの宴 */
  7057. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  7058. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  7059. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  7060. case BD_ROKISWEIL: /* ロキの叫び */
  7061. case BD_INTOABYSS: /* 深淵の中に */
  7062. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  7063. case BD_RAGNAROK: /* 神?の?昏 */
  7064. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  7065. {
  7066. int range=1;
  7067. int c=0;
  7068. map_foreachinarea(skill_check_condition_char_sub,sd->bl.m,
  7069. sd->bl.x-range,sd->bl.y-range,
  7070. sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
  7071. if(c<1){
  7072. clif_skill_fail(sd,skill_num,0,0);
  7073. return 0;
  7074. }else if(c==99){ //相方不要設定だった
  7075. ;
  7076. }else{
  7077. sd->skilllv=(c + skill_lv)/2;
  7078. }
  7079. }
  7080. break;
  7081. }
  7082. if(!skill_check_condition(sd,0)) return 0;
  7083. /* 射程と障害物チェック */
  7084. range = skill_get_range(skill_num,skill_lv);
  7085. if(range < 0)
  7086. range = battle_get_range(&sd->bl) - (range + 1);
  7087. if(!battle_check_range(&sd->bl,bl,range) )
  7088. return 0;
  7089. if(bl->type==BL_PC) {
  7090. target_sd=(struct map_session_data*)bl;
  7091. if(target_sd && skill_num == ALL_RESURRECTION && !pc_isdead(target_sd))
  7092. return 0;
  7093. }
  7094. if((skill_num != MO_CHAINCOMBO &&
  7095. skill_num != MO_COMBOFINISH &&
  7096. skill_num != MO_EXTREMITYFIST &&
  7097. skill_num != CH_TIGERFIST &&
  7098. skill_num != CH_CHAINCRUSH) ||
  7099. (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) )
  7100. pc_stopattack(sd);
  7101. casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
  7102. if(skill_num != SA_MAGICROD)
  7103. delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
  7104. //sd->state.skillcastcancel = skill_db[skill_num].castcancel;
  7105. sd->state.skillcastcancel = skill_get_castcancel(skill_num);
  7106. switch(skill_num){ /* 何か特殊な?理が必要 */
  7107. // case AL_HEAL: /* ヒ?ル */
  7108. // if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
  7109. // forcecast=1; /* ヒ?ルアタックなら詠唱エフェクト有り */
  7110. // break;
  7111. case ALL_RESURRECTION: /* リザレクション */
  7112. if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))){ /* 敵がアンデッドなら */
  7113. forcecast=1; /* タ?ンアンデットと同じ詠唱時間 */
  7114. casttime=skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
  7115. }
  7116. break;
  7117. case MO_FINGEROFFENSIVE: /* 指? */
  7118. casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv);
  7119. break;
  7120. case MO_CHAINCOMBO: /*連打掌*/
  7121. target_id = sd->attacktarget;
  7122. if( sc_data && sc_data[SC_BLADESTOP].timer!=-1 ){
  7123. struct block_list *tbl;
  7124. if((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //タ?ゲットがいない?
  7125. return 0;
  7126. target_id = tbl->id;
  7127. }
  7128. break;
  7129. case MO_COMBOFINISH: /*猛龍拳*/
  7130. case CH_TIGERFIST: /* 伏虎拳 */
  7131. case CH_CHAINCRUSH: /* 連柱崩? */
  7132. target_id = sd->attacktarget;
  7133. break;
  7134. // -- moonsoul (altered to allow proper usage of extremity from new champion combos)
  7135. //
  7136. case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/
  7137. if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) {
  7138. casttime = 0;
  7139. target_id = sd->attacktarget;
  7140. }
  7141. forcecast=1;
  7142. break;
  7143. case SA_MAGICROD:
  7144. case SA_SPELLBREAKER:
  7145. forcecast=1;
  7146. break;
  7147. case WE_MALE:
  7148. case WE_FEMALE:
  7149. {
  7150. struct map_session_data *p_sd = NULL;
  7151. if((p_sd = pc_get_partner(sd)) == NULL)
  7152. return 0;
  7153. target_id = p_sd->bl.id;
  7154. //rangeをもう1回?査
  7155. range = skill_get_range(skill_num,skill_lv);
  7156. if(range < 0)
  7157. range = battle_get_range(&sd->bl) - (range + 1);
  7158. if(!battle_check_range(&sd->bl,&p_sd->bl,range))
  7159. return 0;
  7160. }
  7161. break;
  7162. // removed on 12/14's patch [celest]
  7163. //case AS_SPLASHER: /* ベナムスプラッシャ? */
  7164. /* {
  7165. struct status_change *t_sc_data = battle_get_sc_data(bl);
  7166. if(t_sc_data && t_sc_data[SC_POISON].timer==-1){
  7167. clif_skill_fail(sd,skill_num,0,10);
  7168. return 0;
  7169. }
  7170. }
  7171. break;*/
  7172. case PF_MEMORIZE: /* メモライズ */
  7173. casttime = 12000;
  7174. break;
  7175. case GD_BATTLEORDER:
  7176. case GD_REGENERATION:
  7177. case GD_RESTORE:
  7178. case GD_EMERGENCYCALL:
  7179. casttime = 1000; // temporary [Celest]
  7180. break;
  7181. }
  7182. //メモライズ?態ならキャストタイムが1/3
  7183. if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
  7184. casttime = casttime/2;
  7185. if((--sc_data[SC_MEMORIZE].val2)<=0)
  7186. skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
  7187. }
  7188. if(battle_config.pc_skill_log)
  7189. printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime);
  7190. // if(sd->skillitem == skill_num)
  7191. // casttime = delay = 0;
  7192. if( casttime>0 || forcecast ){ /* 詠唱が必要 */
  7193. struct mob_data *md;
  7194. clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
  7195. /* 詠唱反?モンスタ? */
  7196. if( bl->type==BL_MOB && (md=(struct mob_data *)bl) && mob_db[md->class].mode&0x10 &&
  7197. md->state.state!=MS_ATTACK && sd->invincible_timer == -1){
  7198. md->target_id=sd->bl.id;
  7199. md->state.targettype = ATTACKABLE;
  7200. md->min_chase=13;
  7201. }
  7202. }
  7203. if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */
  7204. sd->state.skillcastcancel=0;
  7205. sd->skilltarget = target_id;
  7206. /* sd->cast_target_bl = bl; */
  7207. sd->skillx = 0;
  7208. sd->skilly = 0;
  7209. sd->canact_tick = tick + casttime + delay;
  7210. sd->canmove_tick = tick;
  7211. if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
  7212. skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
  7213. if(casttime > 0) {
  7214. sd->skilltimer = add_timer( tick+casttime, skill_castend_id, sd->bl.id, 0 );
  7215. if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
  7216. sd->prev_speed = sd->speed;
  7217. sd->speed = sd->speed*(175 - skill*5)/100;
  7218. clif_updatestatus(sd,SP_SPEED);
  7219. }
  7220. else
  7221. pc_stop_walking(sd,0);
  7222. }
  7223. else {
  7224. if(skill_num != SA_CASTCANCEL)
  7225. sd->skilltimer = -1;
  7226. skill_castend_id(sd->skilltimer,tick,sd->bl.id,0);
  7227. }
  7228. //マジックパワ?の?果終了
  7229. //if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
  7230. // skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); // moved
  7231. return 0;
  7232. }
  7233. /*==========================================
  7234. * スキル使用(場所指定)
  7235. *------------------------------------------
  7236. */
  7237. int skill_use_pos( struct map_session_data *sd,
  7238. int skill_x, int skill_y, int skill_num, int skill_lv)
  7239. {
  7240. struct block_list bl;
  7241. struct status_change *sc_data;
  7242. unsigned int tick;
  7243. int casttime=0,delay=0,skill,range;
  7244. nullpo_retr(0, sd);
  7245. if(pc_isdead(sd))
  7246. return 0;
  7247. if (skillnotok(skill_num, sd)) // [MoueJstr]
  7248. return 0;
  7249. if(skill_num==WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
  7250. clif_skill_fail(sd,sd->skillid,0,0);
  7251. return 0;
  7252. }
  7253. sc_data=sd->sc_data;
  7254. if( sd->opt1>0 )
  7255. return 0;
  7256. if(sc_data){
  7257. if( sc_data[SC_DIVINA].timer!=-1 ||
  7258. sc_data[SC_ROKISWEIL].timer!=-1 ||
  7259. sc_data[SC_AUTOCOUNTER].timer != -1 ||
  7260. sc_data[SC_STEELBODY].timer != -1 ||
  7261. sc_data[SC_DANCING].timer!=-1 ||
  7262. sc_data[SC_BERSERK].timer != -1 ||
  7263. sc_data[SC_MARIONETTE].timer != -1)
  7264. return 0; /* ?態異常や沈?など */
  7265. if (sc_data[SC_BLOCKSKILL].timer!=-1)
  7266. if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
  7267. return 0;
  7268. if (sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest]
  7269. struct skill_unit *su;
  7270. if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
  7271. struct skill_unit_group *sg;
  7272. // if caster is the owner of basilica
  7273. if ((sg = su->group) && sg->src_id == sd->bl.id) {
  7274. // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
  7275. // skill_delunitgroup (sg);
  7276. if (skill_num != HP_BASILICA) return 0;
  7277. } // otherwise...
  7278. else
  7279. return 0;
  7280. }
  7281. }
  7282. }
  7283. if(sd->status.option&2)
  7284. return 0;
  7285. /* if(map[sd->bl.m].flag.gvg &&
  7286. (skill_num == SM_ENDURE || skill_num == AL_TELEPORT ||
  7287. skill_num == AL_WARP || skill_num == WZ_ICEWALL ||
  7288. skill_num == TF_BACKSLIDING))
  7289. return 0;*/
  7290. sd->skillid = skill_num;
  7291. sd->skilllv = skill_lv;
  7292. if(skill_lv <= 0) return 0;
  7293. sd->skillx = skill_x;
  7294. sd->skilly = skill_y;
  7295. if(!skill_check_condition(sd,0)) return 0;
  7296. /* 射程と障害物チェック */
  7297. bl.type = BL_NUL;
  7298. bl.m = sd->bl.m;
  7299. bl.x = skill_x;
  7300. bl.y = skill_y;
  7301. range = skill_get_range(skill_num,skill_lv);
  7302. if(range < 0)
  7303. range = battle_get_range(&sd->bl) - (range + 1);
  7304. if(!battle_check_range(&sd->bl,&bl,range) )
  7305. return 0;
  7306. pc_stopattack(sd);
  7307. casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
  7308. delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
  7309. sd->state.skillcastcancel = skill_db[skill_num].castcancel;
  7310. if(battle_config.pc_skill_log)
  7311. printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",sd->bl.id,skill_x,skill_y,skill_num,skill_lv,casttime);
  7312. // if(sd->skillitem == skill_num)
  7313. // casttime = delay = 0;
  7314. //メモライズ?態ならキャストタイムが1/3
  7315. if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
  7316. casttime = casttime/3;
  7317. if((--sc_data[SC_MEMORIZE].val2)<=0)
  7318. skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
  7319. }
  7320. if( casttime>0 ) /* 詠唱が必要 */
  7321. clif_skillcasting( &sd->bl,
  7322. sd->bl.id, 0, skill_x,skill_y, skill_num,casttime);
  7323. if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */
  7324. sd->state.skillcastcancel=0;
  7325. sd->skilltarget = 0;
  7326. /* sd->cast_target_bl = NULL; */
  7327. tick=gettick();
  7328. sd->canact_tick = tick + casttime + delay;
  7329. sd->canmove_tick = tick;
  7330. if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1)
  7331. skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
  7332. if(casttime > 0) {
  7333. sd->skilltimer = add_timer( tick+casttime, skill_castend_pos, sd->bl.id, 0 );
  7334. if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
  7335. sd->prev_speed = sd->speed;
  7336. sd->speed = sd->speed*(175 - skill*5)/100;
  7337. clif_updatestatus(sd,SP_SPEED);
  7338. }
  7339. else
  7340. pc_stop_walking(sd,0);
  7341. }
  7342. else {
  7343. sd->skilltimer = -1;
  7344. skill_castend_pos(sd->skilltimer,tick,sd->bl.id,0);
  7345. }
  7346. //マジックパワ?の?果終了
  7347. if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
  7348. skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1);
  7349. return 0;
  7350. }
  7351. /*==========================================
  7352. * スキル詠唱キャンセル
  7353. *------------------------------------------
  7354. */
  7355. int skill_castcancel(struct block_list *bl,int type)
  7356. {
  7357. int inf;
  7358. int ret=0;
  7359. nullpo_retr(0, bl);
  7360. if(bl->type==BL_PC){
  7361. struct map_session_data *sd=(struct map_session_data *)bl;
  7362. unsigned long tick=gettick();
  7363. nullpo_retr(0, sd);
  7364. sd->canact_tick=tick;
  7365. sd->canmove_tick = tick;
  7366. if( sd->skilltimer!=-1){
  7367. if(pc_checkskill(sd,SA_FREECAST) > 0) {
  7368. sd->speed = sd->prev_speed;
  7369. clif_updatestatus(sd,SP_SPEED);
  7370. }
  7371. if(!type) {
  7372. if((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32)
  7373. ret=delete_timer( sd->skilltimer, skill_castend_pos );
  7374. else
  7375. ret=delete_timer( sd->skilltimer, skill_castend_id );
  7376. if(ret<0)
  7377. printf("delete timer error : skillid : %d\n",sd->skillid);
  7378. }
  7379. else {
  7380. if((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32)
  7381. ret=delete_timer( sd->skilltimer, skill_castend_pos );
  7382. else
  7383. ret=delete_timer( sd->skilltimer, skill_castend_id );
  7384. if(ret<0)
  7385. printf("delete timer error : skillid : %d\n",sd->skillid_old);
  7386. }
  7387. sd->skilltimer=-1;
  7388. clif_skillcastcancel(bl);
  7389. }
  7390. return 0;
  7391. }else if(bl->type==BL_MOB){
  7392. struct mob_data *md=(struct mob_data *)bl;
  7393. nullpo_retr(0, md);
  7394. if( md->skilltimer!=-1 ){
  7395. if((inf = skill_get_inf( md->skillid )) == 2 || inf == 32)
  7396. ret=delete_timer( md->skilltimer, mobskill_castend_pos );
  7397. else
  7398. ret=delete_timer( md->skilltimer, mobskill_castend_id );
  7399. md->skilltimer=-1;
  7400. clif_skillcastcancel(bl);
  7401. }
  7402. if(ret<0)
  7403. printf("delete timer error : skillid : %d\n",md->skillid);
  7404. return 0;
  7405. }
  7406. return 1;
  7407. }
  7408. /*=========================================
  7409. * ブランディッシュスピア 初期範?決定
  7410. *----------------------------------------
  7411. */
  7412. void skill_brandishspear_first(struct square *tc,int dir,int x,int y){
  7413. nullpo_retv(tc);
  7414. if(dir == 0){
  7415. tc->val1[0]=x-2;
  7416. tc->val1[1]=x-1;
  7417. tc->val1[2]=x;
  7418. tc->val1[3]=x+1;
  7419. tc->val1[4]=x+2;
  7420. tc->val2[0]=
  7421. tc->val2[1]=
  7422. tc->val2[2]=
  7423. tc->val2[3]=
  7424. tc->val2[4]=y-1;
  7425. }
  7426. else if(dir==2){
  7427. tc->val1[0]=
  7428. tc->val1[1]=
  7429. tc->val1[2]=
  7430. tc->val1[3]=
  7431. tc->val1[4]=x+1;
  7432. tc->val2[0]=y+2;
  7433. tc->val2[1]=y+1;
  7434. tc->val2[2]=y;
  7435. tc->val2[3]=y-1;
  7436. tc->val2[4]=y-2;
  7437. }
  7438. else if(dir==4){
  7439. tc->val1[0]=x-2;
  7440. tc->val1[1]=x-1;
  7441. tc->val1[2]=x;
  7442. tc->val1[3]=x+1;
  7443. tc->val1[4]=x+2;
  7444. tc->val2[0]=
  7445. tc->val2[1]=
  7446. tc->val2[2]=
  7447. tc->val2[3]=
  7448. tc->val2[4]=y+1;
  7449. }
  7450. else if(dir==6){
  7451. tc->val1[0]=
  7452. tc->val1[1]=
  7453. tc->val1[2]=
  7454. tc->val1[3]=
  7455. tc->val1[4]=x-1;
  7456. tc->val2[0]=y+2;
  7457. tc->val2[1]=y+1;
  7458. tc->val2[2]=y;
  7459. tc->val2[3]=y-1;
  7460. tc->val2[4]=y-2;
  7461. }
  7462. else if(dir==1){
  7463. tc->val1[0]=x-1;
  7464. tc->val1[1]=x;
  7465. tc->val1[2]=x+1;
  7466. tc->val1[3]=x+2;
  7467. tc->val1[4]=x+3;
  7468. tc->val2[0]=y-4;
  7469. tc->val2[1]=y-3;
  7470. tc->val2[2]=y-1;
  7471. tc->val2[3]=y;
  7472. tc->val2[4]=y+1;
  7473. }
  7474. else if(dir==3){
  7475. tc->val1[0]=x+3;
  7476. tc->val1[1]=x+2;
  7477. tc->val1[2]=x+1;
  7478. tc->val1[3]=x;
  7479. tc->val1[4]=x-1;
  7480. tc->val2[0]=y-1;
  7481. tc->val2[1]=y;
  7482. tc->val2[2]=y+1;
  7483. tc->val2[3]=y+2;
  7484. tc->val2[4]=y+3;
  7485. }
  7486. else if(dir==5){
  7487. tc->val1[0]=x+1;
  7488. tc->val1[1]=x;
  7489. tc->val1[2]=x-1;
  7490. tc->val1[3]=x-2;
  7491. tc->val1[4]=x-3;
  7492. tc->val2[0]=y+3;
  7493. tc->val2[1]=y+2;
  7494. tc->val2[2]=y+1;
  7495. tc->val2[3]=y;
  7496. tc->val2[4]=y-1;
  7497. }
  7498. else if(dir==7){
  7499. tc->val1[0]=x-3;
  7500. tc->val1[1]=x-2;
  7501. tc->val1[2]=x-1;
  7502. tc->val1[3]=x;
  7503. tc->val1[4]=x+1;
  7504. tc->val2[1]=y;
  7505. tc->val2[0]=y+1;
  7506. tc->val2[2]=y-1;
  7507. tc->val2[3]=y-2;
  7508. tc->val2[4]=y-3;
  7509. }
  7510. }
  7511. /*=========================================
  7512. * ブランディッシュスピア 方向判定 範??張
  7513. *-----------------------------------------
  7514. */
  7515. void skill_brandishspear_dir(struct square *tc,int dir,int are){
  7516. int c;
  7517. nullpo_retv(tc);
  7518. for(c=0;c<5;c++){
  7519. if(dir==0){
  7520. tc->val2[c]+=are;
  7521. }else if(dir==1){
  7522. tc->val1[c]-=are; tc->val2[c]+=are;
  7523. }else if(dir==2){
  7524. tc->val1[c]-=are;
  7525. }else if(dir==3){
  7526. tc->val1[c]-=are; tc->val2[c]-=are;
  7527. }else if(dir==4){
  7528. tc->val2[c]-=are;
  7529. }else if(dir==5){
  7530. tc->val1[c]+=are; tc->val2[c]-=are;
  7531. }else if(dir==6){
  7532. tc->val1[c]+=are;
  7533. }else if(dir==7){
  7534. tc->val1[c]+=are; tc->val2[c]+=are;
  7535. }
  7536. }
  7537. }
  7538. /*==========================================
  7539. * ディボ?ション 有?確認
  7540. *------------------------------------------
  7541. */
  7542. void skill_devotion(struct map_session_data *md,int target)
  7543. {
  7544. // ?確認
  7545. int n;
  7546. nullpo_retv(md);
  7547. for(n=0;n<5;n++){
  7548. if(md->dev.val1[n]){
  7549. struct map_session_data *sd = map_id2sd(md->dev.val1[n]);
  7550. // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる
  7551. if( sd == NULL || (sd->sc_data && (md->bl.id != sd->sc_data[SC_DEVOTION].val1)) || skill_devotion3(&md->bl,md->dev.val1[n])){
  7552. skill_devotion_end(md,sd,n);
  7553. }
  7554. }
  7555. }
  7556. }
  7557. void skill_devotion2(struct block_list *bl,int crusader)
  7558. {
  7559. // 被ディボ?ションが?いた時の距離チェック
  7560. struct map_session_data *sd = map_id2sd(crusader);
  7561. nullpo_retv(bl);
  7562. if(sd) skill_devotion3(&sd->bl,bl->id);
  7563. }
  7564. int skill_devotion3(struct block_list *bl,int target)
  7565. {
  7566. // クルセが?いた時の距離チェック
  7567. struct map_session_data *md;
  7568. struct map_session_data *sd;
  7569. int n,r=0;
  7570. nullpo_retr(1, bl);
  7571. if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL )
  7572. return 1;
  7573. else
  7574. r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y);
  7575. if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // 許容範?を超えてた
  7576. for(n=0;n<5;n++)
  7577. if(md->dev.val1[n]==target)
  7578. md->dev.val2[n]=0; // 離れた時は、?を切るだけ
  7579. clif_devotion(md,sd->bl.id);
  7580. return 1;
  7581. }
  7582. return 0;
  7583. }
  7584. void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,int target)
  7585. {
  7586. // クルセと被ディボキャラのリセット
  7587. nullpo_retv(md);
  7588. nullpo_retv(sd);
  7589. md->dev.val1[target]=md->dev.val2[target]=0;
  7590. if(sd && sd->sc_data){
  7591. // skill_status_change_end(sd->bl,SC_DEVOTION,-1);
  7592. sd->sc_data[SC_DEVOTION].val1=0;
  7593. sd->sc_data[SC_DEVOTION].val2=0;
  7594. clif_status_change(&sd->bl,SC_DEVOTION,0);
  7595. clif_devotion(md,sd->bl.id);
  7596. }
  7597. }
  7598. /*==========================================
  7599. * オ?トスペル
  7600. *------------------------------------------
  7601. */
  7602. int skill_autospell(struct map_session_data *sd,int skillid)
  7603. {
  7604. int skilllv;
  7605. int maxlv=1,lv;
  7606. nullpo_retr(0, sd);
  7607. skilllv = pc_checkskill(sd,SA_AUTOSPELL);
  7608. if(skilllv <= 0) return 0;
  7609. if(skillid==MG_NAPALMBEAT) maxlv=3;
  7610. else if(skillid==MG_COLDBOLT || skillid==MG_FIREBOLT || skillid==MG_LIGHTNINGBOLT){
  7611. if(skilllv==2) maxlv=1;
  7612. else if(skilllv==3) maxlv=2;
  7613. else if(skilllv>=4) maxlv=3;
  7614. }
  7615. else if(skillid==MG_SOULSTRIKE){
  7616. if(skilllv==5) maxlv=1;
  7617. else if(skilllv==6) maxlv=2;
  7618. else if(skilllv>=7) maxlv=3;
  7619. }
  7620. else if(skillid==MG_FIREBALL){
  7621. if(skilllv==8) maxlv=1;
  7622. else if(skilllv>=9) maxlv=2;
  7623. }
  7624. else if(skillid==MG_FROSTDIVER) maxlv=1;
  7625. else return 0;
  7626. if(maxlv > (lv=pc_checkskill(sd,skillid)))
  7627. maxlv = lv;
  7628. skill_status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:スキルID val2:使用最大Lv
  7629. skill_get_time(SA_AUTOSPELL,skilllv),0);// にしてみたけどbscriptが書き易い????
  7630. return 0;
  7631. }
  7632. /*==========================================
  7633. * ギャングスタ?パラダイス判定?理(foreachinarea)
  7634. *------------------------------------------
  7635. */
  7636. static int skill_gangster_count(struct block_list *bl,va_list ap)
  7637. {
  7638. int *c;
  7639. struct map_session_data *sd;
  7640. nullpo_retr(0, bl);
  7641. nullpo_retr(0, ap);
  7642. sd=(struct map_session_data*)bl;
  7643. c=va_arg(ap,int *);
  7644. if(sd && c && pc_issit(sd) && pc_checkskill(sd,RG_GANGSTER) > 0)
  7645. (*c)++;
  7646. return 0;
  7647. }
  7648. static int skill_gangster_in(struct block_list *bl,va_list ap)
  7649. {
  7650. struct map_session_data *sd;
  7651. nullpo_retr(0, bl);
  7652. nullpo_retr(0, ap);
  7653. sd=(struct map_session_data*)bl;
  7654. if(sd && pc_issit(sd) && pc_checkskill(sd,RG_GANGSTER) > 0)
  7655. sd->state.gangsterparadise=1;
  7656. return 0;
  7657. }
  7658. static int skill_gangster_out(struct block_list *bl,va_list ap)
  7659. {
  7660. struct map_session_data *sd;
  7661. nullpo_retr(0, bl);
  7662. nullpo_retr(0, ap);
  7663. sd=(struct map_session_data*)bl;
  7664. if(sd && sd->state.gangsterparadise)
  7665. sd->state.gangsterparadise=0;
  7666. return 0;
  7667. }
  7668. int skill_gangsterparadise(struct map_session_data *sd ,int type)
  7669. {
  7670. int range=1;
  7671. int c=0;
  7672. nullpo_retr(0, sd);
  7673. if(pc_checkskill(sd,RG_GANGSTER) <= 0)
  7674. return 0;
  7675. if(type==1) {/* 座った時の?理 */
  7676. map_foreachinarea(skill_gangster_count,sd->bl.m,
  7677. sd->bl.x-range,sd->bl.y-range,
  7678. sd->bl.x+range,sd->bl.y+range,BL_PC,&c);
  7679. if(c > 1) {/*ギャングスタ?成功したら自分にもギャングスタ??性付?*/
  7680. map_foreachinarea(skill_gangster_in,sd->bl.m,
  7681. sd->bl.x-range,sd->bl.y-range,
  7682. sd->bl.x+range,sd->bl.y+range,BL_PC);
  7683. sd->state.gangsterparadise = 1;
  7684. }
  7685. return 0;
  7686. }
  7687. else if(type==0) {/* 立ち上がったときの?理 */
  7688. map_foreachinarea(skill_gangster_count,sd->bl.m,
  7689. sd->bl.x-range,sd->bl.y-range,
  7690. sd->bl.x+range,sd->bl.y+range,BL_PC,&c);
  7691. if(c < 2)
  7692. map_foreachinarea(skill_gangster_out,sd->bl.m,
  7693. sd->bl.x-range,sd->bl.y-range,
  7694. sd->bl.x+range,sd->bl.y+range,BL_PC);
  7695. sd->state.gangsterparadise = 0;
  7696. return 0;
  7697. }
  7698. return 0;
  7699. }
  7700. /*==========================================
  7701. * 寒いジョ?ク?スクリ?ム判定?理(foreachinarea)
  7702. *------------------------------------------
  7703. */
  7704. int skill_frostjoke_scream(struct block_list *bl,va_list ap)
  7705. {
  7706. struct block_list *src;
  7707. int skillnum,skilllv;
  7708. unsigned int tick;
  7709. nullpo_retr(0, bl);
  7710. nullpo_retr(0, ap);
  7711. nullpo_retr(0, src=va_arg(ap,struct block_list*));
  7712. skillnum=va_arg(ap,int);
  7713. skilllv=va_arg(ap,int);
  7714. if(skilllv <= 0) return 0;
  7715. tick=va_arg(ap,unsigned int);
  7716. if(src == bl)//自分には?かない
  7717. return 0;
  7718. if(battle_check_target(src,bl,BCT_ENEMY) > 0)
  7719. skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
  7720. else if(battle_check_target(src,bl,BCT_PARTY) > 0) {
  7721. if(rand()%100 < 10)//PTメンバにも低確率でかかる(とりあえず10%)
  7722. skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
  7723. }
  7724. return 0;
  7725. }
  7726. /*==========================================
  7727. *アブラカダブラの使用スキル決定(決定スキルがダメなら0を返す)
  7728. *------------------------------------------
  7729. */
  7730. int skill_abra_dataset(int skilllv)
  7731. {
  7732. int skill = rand()%331;
  7733. if(skilllv <= 0) return 0;
  7734. //dbに基づくレベル?確率判定
  7735. if(skill_abra_db[skill].req_lv > skilllv || rand()%10000 >= skill_abra_db[skill].per) return 0;
  7736. //NPCスキルはダメ
  7737. if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
  7738. //演奏スキルはダメ
  7739. if(skill_is_danceskill(skill)) return 0;
  7740. return skill;
  7741. }
  7742. /*==========================================
  7743. *
  7744. *------------------------------------------
  7745. */
  7746. int skill_attack_area(struct block_list *bl,va_list ap)
  7747. {
  7748. struct block_list *src,*dsrc;
  7749. int atk_type,skillid,skilllv,flag,type;
  7750. unsigned int tick;
  7751. nullpo_retr(0, bl);
  7752. nullpo_retr(0, ap);
  7753. atk_type = va_arg(ap,int);
  7754. if((src=va_arg(ap,struct block_list*)) == NULL)
  7755. return 0;
  7756. if((dsrc=va_arg(ap,struct block_list*)) == NULL)
  7757. return 0;
  7758. skillid=va_arg(ap,int);
  7759. skilllv=va_arg(ap,int);
  7760. //if(skilllv <= 0) return 0;
  7761. if(skillid > 0 && skilllv <= 0) return 0; // celest
  7762. tick=va_arg(ap,unsigned int);
  7763. flag=va_arg(ap,int);
  7764. type=va_arg(ap,int);
  7765. if(battle_check_target(dsrc,bl,type) > 0)
  7766. skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag);
  7767. return 0;
  7768. }
  7769. /*==========================================
  7770. *
  7771. *------------------------------------------
  7772. */
  7773. int skill_clear_element_field(struct block_list *bl)
  7774. {
  7775. struct mob_data *md=NULL;
  7776. struct map_session_data *sd=NULL;
  7777. int i,skillid;
  7778. nullpo_retr(0, bl);
  7779. if(bl->type==BL_MOB)
  7780. md=(struct mob_data *)bl;
  7781. if(bl->type==BL_PC)
  7782. sd=(struct map_session_data *)bl;
  7783. for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){
  7784. if(sd){
  7785. skillid=sd->skillunit[i].skill_id;
  7786. if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
  7787. skill_delunitgroup(&sd->skillunit[i]);
  7788. }else if(md){
  7789. skillid=md->skillunit[i].skill_id;
  7790. if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
  7791. skill_delunitgroup(&md->skillunit[i]);
  7792. }
  7793. }
  7794. return 0;
  7795. }
  7796. /*==========================================
  7797. * ランドプロテクタ?チェック(foreachinarea)
  7798. *------------------------------------------
  7799. */
  7800. int skill_landprotector(struct block_list *bl, va_list ap )
  7801. {
  7802. int skillid;
  7803. int *alive;
  7804. struct skill_unit *unit;
  7805. nullpo_retr(0, bl);
  7806. nullpo_retr(0, ap);
  7807. skillid=va_arg(ap,int);
  7808. alive=va_arg(ap,int *);
  7809. if((unit=(struct skill_unit *)bl) == NULL)
  7810. return 0;
  7811. if(skillid==SA_LANDPROTECTOR){
  7812. skill_delunit(unit);
  7813. }else{
  7814. if(alive && unit->group->skill_id==SA_LANDPROTECTOR)
  7815. (*alive)=0;
  7816. }
  7817. return 0;
  7818. }
  7819. /*==========================================
  7820. * イドゥンの林檎の回復?理(foreachinarea)
  7821. *------------------------------------------
  7822. */
  7823. int skill_idun_heal(struct block_list *bl, va_list ap )
  7824. {
  7825. struct skill_unit *unit;
  7826. struct skill_unit_group *sg;
  7827. int heal;
  7828. nullpo_retr(0, bl);
  7829. nullpo_retr(0, ap);
  7830. nullpo_retr(0, unit = va_arg(ap,struct skill_unit *));
  7831. nullpo_retr(0, sg = unit->group);
  7832. heal=30+sg->skill_lv*5+((sg->val1)>>16)*5+((sg->val1)&0xfff)/2;
  7833. if(bl->type == BL_SKILL || bl->id == sg->src_id)
  7834. return 0;
  7835. if(bl->type == BL_PC || bl->type == BL_MOB){
  7836. clif_skill_nodamage(&unit->bl,bl,AL_HEAL,heal,1);
  7837. battle_heal(NULL,bl,heal,0,0);
  7838. }
  7839. return 0;
  7840. }
  7841. /*==========================================
  7842. * 指定範??でsrcに?して有?なタ?ゲットのblの?を?える(foreachinarea)
  7843. *------------------------------------------
  7844. */
  7845. int skill_count_target(struct block_list *bl, va_list ap ){
  7846. struct block_list *src;
  7847. int *c;
  7848. nullpo_retr(0, bl);
  7849. nullpo_retr(0, ap);
  7850. if((src = va_arg(ap,struct block_list *)) == NULL)
  7851. return 0;
  7852. if((c = va_arg(ap,int *)) == NULL)
  7853. return 0;
  7854. if(battle_check_target(src,bl,BCT_ENEMY) > 0)
  7855. (*c)++;
  7856. return 0;
  7857. }
  7858. /*==========================================
  7859. * トラップ範??理(foreachinarea)
  7860. *------------------------------------------
  7861. */
  7862. int skill_trap_splash(struct block_list *bl, va_list ap )
  7863. {
  7864. struct block_list *src;
  7865. int tick;
  7866. int splash_count;
  7867. struct skill_unit *unit;
  7868. struct skill_unit_group *sg;
  7869. struct block_list *ss;
  7870. int i;
  7871. nullpo_retr(0, bl);
  7872. nullpo_retr(0, ap);
  7873. nullpo_retr(0, src = va_arg(ap,struct block_list *));
  7874. nullpo_retr(0, unit = (struct skill_unit *)src);
  7875. nullpo_retr(0, sg = unit->group);
  7876. nullpo_retr(0, ss = map_id2bl(sg->src_id));
  7877. tick = va_arg(ap,int);
  7878. splash_count = va_arg(ap,int);
  7879. if(battle_check_target(src,bl,BCT_ENEMY) > 0){
  7880. switch(sg->unit_id){
  7881. case 0x95: /* サンドマン */
  7882. case 0x96: /* フラッシャ? */
  7883. case 0x94: /* ショックウェ?ブトラップ */
  7884. skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
  7885. break;
  7886. case 0x8f: /* ブラストマイン */
  7887. case 0x98: /* クレイモア?トラップ */
  7888. for(i=0;i<splash_count;i++){
  7889. skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
  7890. }
  7891. case 0x97: /* フリ?ジングトラップ */
  7892. skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
  7893. break;
  7894. default:
  7895. break;
  7896. }
  7897. }
  7898. return 0;
  7899. }
  7900. /*----------------------------------------------------------------------------
  7901. * ステ?タス異常
  7902. *----------------------------------------------------------------------------
  7903. */
  7904. /*==========================================
  7905. * ステ?タス異常タイマ?範??理
  7906. *------------------------------------------
  7907. */
  7908. int skill_status_change_timer_sub(struct block_list *bl, va_list ap )
  7909. {
  7910. struct block_list *src;
  7911. int type;
  7912. unsigned int tick;
  7913. nullpo_retr(0, bl);
  7914. nullpo_retr(0, ap);
  7915. nullpo_retr(0, src=va_arg(ap,struct block_list*));
  7916. type=va_arg(ap,int);
  7917. tick=va_arg(ap,unsigned int);
  7918. if(bl->type!=BL_PC && bl->type!=BL_MOB)
  7919. return 0;
  7920. switch( type ){
  7921. case SC_SIGHT: /* サイト */
  7922. case SC_CONCENTRATE:
  7923. if( (*battle_get_option(bl))&6 ){
  7924. skill_status_change_end( bl, SC_HIDING, -1);
  7925. skill_status_change_end( bl, SC_CLOAKING, -1);
  7926. }
  7927. break;
  7928. case SC_RUWACH: /* ルアフ */
  7929. if( (*battle_get_option(bl))&6 ){
  7930. skill_status_change_end( bl, SC_HIDING, -1);
  7931. skill_status_change_end( bl, SC_CLOAKING, -1);
  7932. if(battle_check_target( src,bl, BCT_ENEMY ) > 0) {
  7933. struct status_change *sc_data = battle_get_sc_data(bl);
  7934. if (sc_data)
  7935. skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0);
  7936. }
  7937. }
  7938. break;
  7939. }
  7940. return 0;
  7941. }
  7942. /*==========================================
  7943. * ステ?タス異常終了
  7944. *------------------------------------------
  7945. */
  7946. int skill_status_change_end(struct block_list* bl, int type, int tid)
  7947. {
  7948. struct status_change* sc_data;
  7949. int opt_flag=0, calc_flag = 0;
  7950. short *sc_count, *option, *opt1, *opt2, *opt3;
  7951. nullpo_retr(0, bl);
  7952. if(bl->type!=BL_PC && bl->type!=BL_MOB) {
  7953. if(battle_config.error_log)
  7954. printf("skill_status_change_end: neither MOB nor PC !\n");
  7955. return 0;
  7956. }
  7957. nullpo_retr(0, sc_data = battle_get_sc_data(bl));
  7958. nullpo_retr(0, sc_count = battle_get_sc_count(bl));
  7959. nullpo_retr(0, option = battle_get_option(bl));
  7960. nullpo_retr(0, opt1 = battle_get_opt1(bl));
  7961. nullpo_retr(0, opt2 = battle_get_opt2(bl));
  7962. nullpo_retr(0, opt3 = battle_get_opt3(bl));
  7963. if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) {
  7964. if (tid == -1) // タイマから呼ばれていないならタイマ削除をする
  7965. delete_timer(sc_data[type].timer,skill_status_change_timer);
  7966. /* 該?の異常を正常に?す */
  7967. sc_data[type].timer=-1;
  7968. (*sc_count)--;
  7969. switch(type){ /* 異常の種類ごとの?理 */
  7970. case SC_PROVOKE: /* プロボック */
  7971. case SC_ENDURE: // celest
  7972. case SC_CONCENTRATE: /* 集中力向上 */
  7973. case SC_BLESSING: /* ブレッシング */
  7974. case SC_ANGELUS: /* アンゼルス */
  7975. case SC_INCREASEAGI: /* 速度上昇 */
  7976. case SC_DECREASEAGI: /* 速度減少 */
  7977. case SC_SIGNUMCRUCIS: /* シグナムクルシス */
  7978. case SC_HIDING:
  7979. case SC_TWOHANDQUICKEN: /* 2HQ */
  7980. case SC_ADRENALINE: /* アドレナリンラッシュ */
  7981. case SC_ENCPOISON: /* エンチャントポイズン */
  7982. case SC_IMPOSITIO: /* インポシティオマヌス */
  7983. case SC_GLORIA: /* グロリア */
  7984. case SC_LOUD: /* ラウドボイス */
  7985. case SC_QUAGMIRE: /* クァグマイア */
  7986. case SC_PROVIDENCE: /* プロヴィデンス */
  7987. case SC_SPEARSQUICKEN: /* スピアクイッケン */
  7988. case SC_VOLCANO:
  7989. case SC_DELUGE:
  7990. case SC_VIOLENTGALE:
  7991. case SC_ETERNALCHAOS: /* エタ?ナルカオス */
  7992. case SC_DRUMBATTLE: /* ?太鼓の響き */
  7993. case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
  7994. case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  7995. case SC_WHISTLE: /* 口笛 */
  7996. case SC_ASSNCROS: /* 夕陽のアサシンクロス */
  7997. case SC_HUMMING: /* ハミング */
  7998. case SC_DONTFORGETME: /* 私を忘れないで */
  7999. case SC_FORTUNE: /* 幸運のキス */
  8000. case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
  8001. case SC_EXPLOSIONSPIRITS: // 爆裂波動
  8002. case SC_STEELBODY: // 金剛
  8003. case SC_DEFENDER:
  8004. case SC_SPEEDPOTION0: /* ?速ポ?ション */
  8005. case SC_SPEEDPOTION1:
  8006. case SC_SPEEDPOTION2:
  8007. case SC_APPLEIDUN: /* イドゥンの林檎 */
  8008. case SC_RIDING:
  8009. case SC_BLADESTOP_WAIT:
  8010. case SC_AURABLADE: /* オ?ラブレ?ド */
  8011. case SC_PARRYING: /* パリイング */
  8012. case SC_CONCENTRATION: /* コンセントレ?ション */
  8013. case SC_TENSIONRELAX: /* テンションリラックス */
  8014. case SC_ASSUMPTIO: /* アシャンプティオ */
  8015. case SC_WINDWALK: /* ウインドウォ?ク */
  8016. case SC_TRUESIGHT: /* トゥル?サイト */
  8017. case SC_SPIDERWEB: /* スパイダ?ウェッブ */
  8018. case SC_MAGICPOWER: /* 魔法力?幅 */
  8019. case SC_CHASEWALK:
  8020. case SC_ATKPOT: /* attack potion [Valaris] */
  8021. case SC_MATKPOT: /* magic attack potion [Valaris] */
  8022. case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
  8023. case SC_MELTDOWN: /* メルトダウン */
  8024. // Celest
  8025. case SC_EDP:
  8026. case SC_MARIONETTE:
  8027. case SC_MARIONETTE2:
  8028. case SC_SLOWDOWN:
  8029. case SC_LEADERSHIP:
  8030. case SC_GLORYWOUNDS:
  8031. case SC_SOULCOLD:
  8032. case SC_HAWKEYES:
  8033. case SC_BATTLEORDERS:
  8034. case SC_REGENERATION:
  8035. calc_flag = 1;
  8036. break;
  8037. case SC_AUTOBERSERK:
  8038. if (sc_data[SC_PROVOKE].timer != -1)
  8039. skill_status_change_end(bl,SC_PROVOKE,-1);
  8040. break;
  8041. case SC_BERSERK: /* バ?サ?ク */
  8042. calc_flag = 1;
  8043. clif_status_change(bl,SC_INCREASEAGI,0); /* アイコン消去 */
  8044. break;
  8045. case SC_DEVOTION: /* ディボ?ション */
  8046. {
  8047. struct map_session_data *md = map_id2sd(sc_data[type].val1);
  8048. sc_data[type].val1=sc_data[type].val2=0;
  8049. skill_devotion(md,bl->id);
  8050. calc_flag = 1;
  8051. }
  8052. break;
  8053. case SC_BLADESTOP:
  8054. {
  8055. struct status_change *t_sc_data = battle_get_sc_data((struct block_list *)sc_data[type].val4);
  8056. //片方が切れたので相手の白刃?態が切れてないのなら解除
  8057. if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1)
  8058. skill_status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1);
  8059. if(sc_data[type].val2==2)
  8060. clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0);
  8061. }
  8062. break;
  8063. case SC_DANCING:
  8064. {
  8065. struct map_session_data *dsd;
  8066. struct status_change *d_sc_data;
  8067. if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){
  8068. d_sc_data = dsd->sc_data;
  8069. //合奏で相手がいる場合相手のval4を0にする
  8070. if(d_sc_data && d_sc_data[type].timer!=-1)
  8071. d_sc_data[type].val4=0;
  8072. }
  8073. }
  8074. calc_flag = 1;
  8075. break;
  8076. case SC_GRAFFITI:
  8077. {
  8078. struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[type].val4; //val4がグラフィティのgroup_id
  8079. if(sg)
  8080. skill_delunitgroup(sg);
  8081. }
  8082. break;
  8083. case SC_NOCHAT: //チャット禁止?態
  8084. {
  8085. struct map_session_data *sd=NULL;
  8086. if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
  8087. if (sd->status.manner >= 0) // weeee ^^ [celest]
  8088. sd->status.manner = 0;
  8089. clif_updatestatus(sd,SP_MANNER);
  8090. }
  8091. }
  8092. break;
  8093. case SC_SPLASHER: /* ベナムスプラッシャ? */
  8094. {
  8095. struct block_list *src=map_id2bl(sc_data[type].val3);
  8096. if(src && tid!=-1){
  8097. //自分にダメ?ジ&周?3*3にダメ?ジ
  8098. skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
  8099. }
  8100. }
  8101. break;
  8102. case SC_SELFDESTRUCTION: /* 自爆 */
  8103. {
  8104. //自分のダメ?ジは0にして
  8105. struct mob_data *md=NULL;
  8106. if(bl->type == BL_MOB && (md=(struct mob_data*)bl))
  8107. skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
  8108. }
  8109. break;
  8110. /* option1 */
  8111. case SC_FREEZE:
  8112. sc_data[type].val3 = 0;
  8113. break;
  8114. /* option2 */
  8115. case SC_POISON: /* 毒 */
  8116. case SC_BLIND: /* 暗? */
  8117. case SC_CURSE:
  8118. calc_flag = 1;
  8119. break;
  8120. // celest
  8121. case SC_CONFUSION:
  8122. {
  8123. struct map_session_data *sd=NULL;
  8124. if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
  8125. sd->next_walktime = -1;
  8126. }
  8127. }
  8128. break;
  8129. }
  8130. if(bl->type==BL_PC && type<SC_SENDMAX)
  8131. clif_status_change(bl,type,0); /* アイコン消去 */
  8132. switch(type){ /* 正常に?るときなにか?理が必要 */
  8133. case SC_STONE:
  8134. case SC_FREEZE:
  8135. case SC_STAN:
  8136. case SC_SLEEP:
  8137. *opt1 = 0;
  8138. opt_flag = 1;
  8139. break;
  8140. case SC_POISON:
  8141. if (sc_data[SC_DPOISON].timer != -1) //
  8142. break; // DPOISON用のオプション
  8143. *opt2 &= ~1; // が?用に用意された場合には
  8144. opt_flag = 1; // ここは削除する
  8145. break; //
  8146. case SC_CURSE:
  8147. case SC_SILENCE:
  8148. case SC_BLIND:
  8149. *opt2 &= ~(1<<(type-SC_POISON));
  8150. opt_flag = 1;
  8151. break;
  8152. case SC_DPOISON:
  8153. if (sc_data[SC_POISON].timer != -1) // DPOISON用のオプションが
  8154. break; // 用意されたら削除
  8155. *opt2 &= ~1; // 毒?態解除
  8156. opt_flag = 1;
  8157. break;
  8158. case SC_SIGNUMCRUCIS:
  8159. *opt2 &= ~0x40;
  8160. opt_flag = 1;
  8161. break;
  8162. case SC_HIDING:
  8163. case SC_CLOAKING:
  8164. *option &= ~((type == SC_HIDING) ? 2 : 4);
  8165. calc_flag = 1; // orn
  8166. opt_flag = 1 ;
  8167. break;
  8168. case SC_CHASEWALK:
  8169. *option &= ~16388;
  8170. opt_flag = 1 ;
  8171. break;
  8172. case SC_SIGHT:
  8173. *option &= ~1;
  8174. opt_flag = 1;
  8175. break;
  8176. case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
  8177. *option &= ~4096;
  8178. opt_flag = 1;
  8179. break;
  8180. case SC_RUWACH:
  8181. *option &= ~8192;
  8182. opt_flag = 1;
  8183. break;
  8184. //opt3
  8185. case SC_TWOHANDQUICKEN: /* 2HQ */
  8186. case SC_SPEARSQUICKEN: /* スピアクイッケン */
  8187. case SC_CONCENTRATION: /* コンセントレ?ション */
  8188. *opt3 &= ~1;
  8189. break;
  8190. case SC_OVERTHRUST: /* オ?バ?スラスト */
  8191. *opt3 &= ~2;
  8192. break;
  8193. case SC_ENERGYCOAT: /* エナジ?コ?ト */
  8194. *opt3 &= ~4;
  8195. break;
  8196. case SC_EXPLOSIONSPIRITS: // 爆裂波動
  8197. *opt3 &= ~8;
  8198. break;
  8199. case SC_STEELBODY: // 金剛
  8200. *opt3 &= ~16;
  8201. break;
  8202. case SC_BLADESTOP: /* 白刃取り */
  8203. *opt3 &= ~32;
  8204. break;
  8205. case SC_BERSERK: /* バ?サ?ク */
  8206. *opt3 &= ~128;
  8207. break;
  8208. case SC_MARIONETTE: /* マリオネットコントロ?ル */
  8209. case SC_MARIONETTE2:
  8210. *opt3 &= ~1024;
  8211. break;
  8212. case SC_ASSUMPTIO: /* アスムプティオ */
  8213. *opt3 &= ~2048;
  8214. break;
  8215. }
  8216. if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor]
  8217. !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest]
  8218. *opt2 |= STATE_BLIND;
  8219. opt_flag = 1;
  8220. }
  8221. if(opt_flag) /* optionの?更を?える */
  8222. clif_changeoption(bl);
  8223. if (bl->type == BL_PC && calc_flag)
  8224. pc_calcstatus((struct map_session_data *)bl,0); /* ステ?タス再計算 */
  8225. }
  8226. return 0;
  8227. }
  8228. /*==========================================
  8229. * ステ?タス異常終了タイマ?
  8230. *------------------------------------------
  8231. */
  8232. int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
  8233. {
  8234. int type=data;
  8235. struct block_list *bl;
  8236. struct map_session_data *sd=NULL;
  8237. struct status_change *sc_data;
  8238. //short *sc_count; //使ってない?
  8239. nullpo_retr(0, bl=map_id2bl(id));
  8240. nullpo_retr(0, sc_data=battle_get_sc_data(bl));
  8241. if(bl->type==BL_PC)
  8242. nullpo_retr(0, sd=(struct map_session_data *)bl);
  8243. //sc_count=battle_get_sc_count(bl); //使ってない?
  8244. if(sc_data[type].timer != tid) {
  8245. if(battle_config.error_log)
  8246. printf("skill_status_change_timer %d != %d\n",tid,sc_data[type].timer);
  8247. return 0;
  8248. }
  8249. switch(type){ /* 特殊な?理になる場合 */
  8250. case SC_MAXIMIZEPOWER: /* マキシマイズパワ? */
  8251. case SC_CLOAKING:
  8252. if(sd){
  8253. if( sd->status.sp > 0 ){ /* SP切れるまで持? */
  8254. sd->status.sp--;
  8255. clif_updatestatus(sd,SP_SP);
  8256. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8257. sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
  8258. return 0;
  8259. }
  8260. }
  8261. break;
  8262. case SC_CHASEWALK:
  8263. if(sd){
  8264. int sp = 10+sc_data[SC_CHASEWALK].val1*2;
  8265. if (map[sd->bl.m].flag.gvg) sp *= 5;
  8266. if( sd->status.sp > sp){
  8267. sd->status.sp -= sp; // update sp cost [Celest]
  8268. clif_updatestatus(sd,SP_SP);
  8269. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8270. sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
  8271. sc_data[SC_CHASEWALK].val4++;
  8272. if (sc_data[SC_CHASEWALK].val4 > 3)
  8273. sc_data[SC_CHASEWALK].val4 = 0;
  8274. pc_calcstatus (sd, 0);
  8275. return 0;
  8276. }
  8277. }
  8278. break;
  8279. case SC_HIDING: /* ハイディング */
  8280. if(sd){ /* SPがあって、時間制限の間は持? */
  8281. if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){
  8282. if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
  8283. sd->status.sp--;
  8284. clif_updatestatus(sd,SP_SP);
  8285. }
  8286. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8287. 1000+tick, skill_status_change_timer,
  8288. bl->id, data);
  8289. return 0;
  8290. }
  8291. }
  8292. break;
  8293. case SC_SIGHT: /* サイト */
  8294. {
  8295. const int range=7;
  8296. map_foreachinarea( skill_status_change_timer_sub,
  8297. bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
  8298. bl,type,tick);
  8299. if( (--sc_data[type].val2)>0 ){
  8300. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8301. 250+tick, skill_status_change_timer,
  8302. bl->id, data);
  8303. return 0;
  8304. }
  8305. }
  8306. break;
  8307. case SC_RUWACH: /* ルアフ */
  8308. {
  8309. const int range=5;
  8310. map_foreachinarea( skill_status_change_timer_sub,
  8311. bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
  8312. bl,type,tick);
  8313. if( (--sc_data[type].val2)>0 ){
  8314. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8315. 250+tick, skill_status_change_timer,
  8316. bl->id, data);
  8317. return 0;
  8318. }
  8319. }
  8320. break;
  8321. case SC_SIGNUMCRUCIS: /* シグナムクルシス */
  8322. {
  8323. int race = battle_get_race(bl);
  8324. if(race == 6 || battle_check_undead(race,battle_get_elem_type(bl))) {
  8325. sc_data[type].timer=add_timer(1000*600+tick,skill_status_change_timer, bl->id, data );
  8326. return 0;
  8327. }
  8328. }
  8329. break;
  8330. case SC_PROVOKE: /* プロボック/オ?トバ?サ?ク */
  8331. if(sc_data[type].val2!=0){ /* オ?トバ?サ?ク(1秒ごとにHPチェック) */
  8332. if(sd && sd->status.hp>sd->status.max_hp>>2) /* 停止 */
  8333. break;
  8334. sc_data[type].timer=add_timer( 1000+tick,skill_status_change_timer, bl->id, data );
  8335. return 0;
  8336. }
  8337. break;
  8338. case SC_WATERBALL: /* ウォ?タ?ボ?ル */
  8339. {
  8340. struct block_list *target=map_id2bl(sc_data[type].val2);
  8341. nullpo_retb(target);
  8342. nullpo_retb(target->prev);
  8343. skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0);
  8344. if((--sc_data[type].val3)>0) {
  8345. sc_data[type].timer=add_timer( 150+tick,skill_status_change_timer, bl->id, data );
  8346. return 0;
  8347. }
  8348. }
  8349. break;
  8350. case SC_ENDURE: /* インデュア */
  8351. case SC_AUTOBERSERK: // Celest
  8352. if(sd && sd->special_state.infinite_endure) {
  8353. #ifdef TWILIGHT
  8354. sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data );
  8355. #else
  8356. sc_data[type].timer=add_timer( 1000*60+tick,skill_status_change_timer, bl->id, data );
  8357. #endif
  8358. //sc_data[type].val2=1;
  8359. return 0;
  8360. }
  8361. break;
  8362. case SC_DISSONANCE: /* 不協和音 */
  8363. if( (--sc_data[type].val2)>0){
  8364. struct skill_unit *unit=
  8365. (struct skill_unit *)sc_data[type].val4;
  8366. struct block_list *src;
  8367. /*if(!unit || !unit->group)
  8368. break;
  8369. src=map_id2bl(unit->group->src_id);
  8370. if(!src)
  8371. break;*/
  8372. nullpo_retb(unit);
  8373. nullpo_retb(unit->group);
  8374. nullpo_retr(0, src=map_id2bl(unit->group->src_id));
  8375. skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0);
  8376. sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick,
  8377. skill_status_change_timer, bl->id, data );
  8378. return 0;
  8379. }
  8380. break;
  8381. case SC_LULLABY: /* 子守唄 */
  8382. if( (--sc_data[type].val2)>0){
  8383. struct skill_unit *unit=
  8384. (struct skill_unit *)sc_data[type].val4;
  8385. nullpo_retb(unit);
  8386. nullpo_retb(unit->group);
  8387. if(unit->group->src_id == bl->id)
  8388. break;
  8389. skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick);
  8390. if (unit->group != 0)
  8391. sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick,
  8392. skill_status_change_timer, bl->id, data );
  8393. return 0;
  8394. }
  8395. break;
  8396. case SC_STONE:
  8397. if(sc_data[type].val2 != 0) {
  8398. short *opt1 = battle_get_opt1(bl);
  8399. sc_data[type].val2 = 0;
  8400. sc_data[type].val4 = 0;
  8401. battle_stopwalking(bl,1);
  8402. if(opt1) {
  8403. *opt1 = 1;
  8404. clif_changeoption(bl);
  8405. }
  8406. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8407. return 0;
  8408. }
  8409. else if( (--sc_data[type].val3) > 0) {
  8410. int hp = battle_get_max_hp(bl);
  8411. if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) {
  8412. hp = hp/100;
  8413. if(hp < 1) hp = 1;
  8414. if(sd)
  8415. pc_heal(sd,-hp,0);
  8416. else if(bl->type == BL_MOB){
  8417. struct mob_data *md;
  8418. if((md=((struct mob_data *)bl)) == NULL)
  8419. break;
  8420. md->hp -= hp;
  8421. }
  8422. }
  8423. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8424. return 0;
  8425. }
  8426. break;
  8427. case SC_POISON:
  8428. if(sc_data[SC_SLOWPOISON].timer == -1) {
  8429. if( (--sc_data[type].val3) > 0) {
  8430. int hp = battle_get_max_hp(bl);
  8431. if(battle_get_hp(bl) > hp>>2) {
  8432. if(bl->type == BL_PC) {
  8433. hp = 3 + hp*3/200;
  8434. pc_heal((struct map_session_data *)bl,-hp,0);
  8435. }
  8436. else if(bl->type == BL_MOB) {
  8437. struct mob_data *md;
  8438. nullpo_retr(0, md=(struct mob_data *)bl);
  8439. /*if((md=((struct mob_data *)bl)) == NULL)
  8440. break;*/
  8441. hp = 3 + hp/200;
  8442. md->hp -= hp;
  8443. }
  8444. }
  8445. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8446. }
  8447. }
  8448. else
  8449. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8450. break;
  8451. case SC_DPOISON:
  8452. if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) {
  8453. int hp = battle_get_max_hp(bl);
  8454. if (battle_get_hp(bl) > hp>>2) {
  8455. if(sd) {
  8456. hp = 3 + hp/50;
  8457. pc_heal(sd, -hp, 0);
  8458. } else if (bl->type == BL_MOB) {
  8459. struct mob_data *md;
  8460. nullpo_retr(0, md=(struct mob_data *)bl);
  8461. /*if ((md=((struct mob_data *)bl)) == NULL)
  8462. break;*/
  8463. hp = 3 + hp/100;
  8464. md->hp -= hp;
  8465. }
  8466. }
  8467. }
  8468. if (sc_data[type].val3 > 0)
  8469. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8470. break;
  8471. case SC_TENSIONRELAX: /* テンションリラックス */
  8472. if(sd){ /* SPがあって、HPが?タンでなければ?? */
  8473. if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){
  8474. /* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
  8475. sd->status.sp -= 12;
  8476. clif_updatestatus(sd,SP_SP);
  8477. } */
  8478. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8479. 10000+tick, skill_status_change_timer,
  8480. bl->id, data);
  8481. return 0;
  8482. }
  8483. if(sd->status.max_hp <= sd->status.hp)
  8484. skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
  8485. }
  8486. break;
  8487. case SC_HEADCRUSH: // temporary damage [celest]
  8488. // case SC_BLEEDING:
  8489. if((--sc_data[type].val3) > 0) {
  8490. int hp = battle_get_max_hp(bl);
  8491. if(sd) {
  8492. hp = 3 + hp*3/200;
  8493. pc_heal(sd,-hp,0);
  8494. }
  8495. else if(bl->type == BL_MOB) {
  8496. struct mob_data *md;
  8497. nullpo_retr(0, md=(struct mob_data *)bl);
  8498. /*if((md=((struct mob_data *)bl)) == NULL)
  8499. break;*/
  8500. hp = 3 + hp/200;
  8501. md->hp -= hp;
  8502. }
  8503. sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
  8504. }
  8505. break;
  8506. /* 時間切れ無し?? */
  8507. case SC_AETERNA:
  8508. case SC_TRICKDEAD:
  8509. case SC_RIDING:
  8510. case SC_FALCON:
  8511. case SC_WEIGHT50:
  8512. case SC_WEIGHT90:
  8513. case SC_MAGICPOWER: /* 魔法力?幅 */
  8514. case SC_REJECTSWORD: /* リジェクトソ?ド */
  8515. case SC_MEMORIZE: /* メモライズ */
  8516. case SC_BROKNWEAPON:
  8517. case SC_BROKNARMOR:
  8518. // if(sc_data[type].timer==tid)
  8519. sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data );
  8520. return 0;
  8521. case SC_DANCING: //ダンススキルの時間SP消費
  8522. {
  8523. int s=0;
  8524. if(sd){
  8525. if(sd->status.sp > 0 && (--sc_data[type].val3)>0){
  8526. switch(sc_data[type].val1){
  8527. case BD_RICHMANKIM: /* ニヨルドの宴 3秒にSP1 */
  8528. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き 3秒にSP1 */
  8529. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 3秒にSP1 */
  8530. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド 3秒にSP1 */
  8531. case BA_DISSONANCE: /* 不協和音 3秒でSP1 */
  8532. case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */
  8533. case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */
  8534. s=3;
  8535. break;
  8536. case BD_LULLABY: /* 子守歌 4秒にSP1 */
  8537. case BD_ETERNALCHAOS: /* 永遠の混沌 4秒にSP1 */
  8538. case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */
  8539. case DC_FORTUNEKISS: /* 幸運のキス 4秒でSP1 */
  8540. s=4;
  8541. break;
  8542. case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */
  8543. case BA_WHISTLE: /* 口笛 5秒でSP1 */
  8544. case DC_HUMMING: /* ハミング 5秒でSP1 */
  8545. case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */
  8546. case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? 5秒でSP1 */
  8547. s=5;
  8548. break;
  8549. case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */
  8550. s=6;
  8551. break;
  8552. case DC_DONTFORGETME: /* 私を忘れないで… 10秒でSP1 */
  8553. case CG_MOONLIT: /* 月明りの泉に落ちる花びら 10秒でSP1? */
  8554. s=10;
  8555. break;
  8556. }
  8557. if(s && ((sc_data[type].val3 % s) == 0)){
  8558. sd->status.sp--;
  8559. clif_updatestatus(sd,SP_SP);
  8560. }
  8561. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8562. 1000+tick, skill_status_change_timer,
  8563. bl->id, data);
  8564. return 0;
  8565. }
  8566. }
  8567. }
  8568. break;
  8569. case SC_BERSERK: /* バ?サ?ク */
  8570. if(sd){ /* HPが100以上なら?? */
  8571. if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG]
  8572. sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest]
  8573. clif_updatestatus(sd,SP_HP);
  8574. sc_data[type].timer = add_timer( /* タイマ?再設定 */
  8575. 10000+tick, skill_status_change_timer,
  8576. bl->id, data);
  8577. return 0;
  8578. }
  8579. }
  8580. break;
  8581. case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
  8582. if(sd){
  8583. time_t timer;
  8584. if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1時間たっていないので??
  8585. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8586. 10000+tick, skill_status_change_timer,
  8587. bl->id, data);
  8588. return 0;
  8589. }
  8590. }
  8591. break;
  8592. case SC_NOCHAT: //チャット禁止?態
  8593. if(sd && battle_config.muting_players){
  8594. time_t timer;
  8595. if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //開始からstatus.manner分?ってないので??
  8596. clif_updatestatus(sd,SP_MANNER);
  8597. sc_data[type].timer=add_timer( /* タイマ?再設定(60秒) */
  8598. 60000+tick, skill_status_change_timer,
  8599. bl->id, data);
  8600. return 0;
  8601. }
  8602. }
  8603. break;
  8604. case SC_SELFDESTRUCTION: /* 自爆 */
  8605. if(--sc_data[type].val3>0){
  8606. struct mob_data *md;
  8607. if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){
  8608. md->speed -= 250;
  8609. md->next_walktime=tick;
  8610. }
  8611. sc_data[type].timer=add_timer( /* タイマ?再設定 */
  8612. 1000+tick, skill_status_change_timer,
  8613. bl->id, data);
  8614. return 0;
  8615. }
  8616. break;
  8617. case SC_SPLASHER:
  8618. if (sc_data[type].val4 % 1000 == 0) {
  8619. char timer[2];
  8620. sprintf (timer, "%d", sc_data[type].val4/1000);
  8621. clif_message(bl, timer);
  8622. }
  8623. if((sc_data[type].val4 -= 500) > 0) {
  8624. sc_data[type].timer = add_timer(
  8625. 500 + tick, skill_status_change_timer,
  8626. bl->id, data);
  8627. return 0;
  8628. }
  8629. break;
  8630. case SC_MARIONETTE: /* マリオネットコントロ?ル */
  8631. case SC_MARIONETTE2:
  8632. {
  8633. struct block_list *pbl = map_id2bl(sc_data[type].val3);
  8634. if (pbl && battle_check_range(bl, pbl, 7) &&
  8635. (sc_data[type].val2 -= 1000)>0) {
  8636. sc_data[type].timer = add_timer(
  8637. 1000 + tick, skill_status_change_timer,
  8638. bl->id, data);
  8639. return 0;
  8640. }
  8641. }
  8642. break;
  8643. case SC_LEADERSHIP:
  8644. case SC_GLORYWOUNDS:
  8645. case SC_SOULCOLD:
  8646. case SC_HAWKEYES:
  8647. if (sd) {
  8648. sc_data[type].timer = add_timer(
  8649. 1000+tick, skill_status_change_timer,
  8650. bl->id, data);
  8651. }
  8652. break;
  8653. // Celest
  8654. case SC_CONFUSION:
  8655. {
  8656. int i = 3000;
  8657. //struct mob_data *md;
  8658. if (sd) {
  8659. pc_randomwalk (sd, gettick());
  8660. sd->next_walktime = tick + (i=1000 + rand()%1000);
  8661. } /*else if (bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->mode&1 && mob_can_move(md)) {
  8662. md->state.state=MS_WALK;
  8663. if( DIFF_TICK(md->next_walktime,tick) > + 7000 &&
  8664. (md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len) )
  8665. md->next_walktime = tick + 3000*rand()%2000;
  8666. mob_randomwalk(md,tick);
  8667. }*/
  8668. if ((sc_data[type].val2 -= 1000) > 0) {
  8669. sc_data[type].timer = add_timer(
  8670. i + tick, skill_status_change_timer,
  8671. bl->id, data);
  8672. return 0;
  8673. }
  8674. }
  8675. break;
  8676. }
  8677. return skill_status_change_end( bl,type,tid );
  8678. }
  8679. /*==========================================
  8680. * ステ?タス異常終了
  8681. *------------------------------------------
  8682. */
  8683. int skill_encchant_eremental_end(struct block_list *bl,int type)
  8684. {
  8685. struct status_change *sc_data;
  8686. nullpo_retr(0, bl);
  8687. nullpo_retr(0, sc_data=battle_get_sc_data(bl));
  8688. if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* エンチャントポイズン解除 */
  8689. skill_status_change_end(bl,SC_ENCPOISON,-1);
  8690. if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* アスペルシオ解除 */
  8691. skill_status_change_end(bl,SC_ASPERSIO,-1);
  8692. if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* フレイムランチャ解除 */
  8693. skill_status_change_end(bl,SC_FLAMELAUNCHER,-1);
  8694. if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* フロストウェポン解除 */
  8695. skill_status_change_end(bl,SC_FROSTWEAPON,-1);
  8696. if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ライトニングロ?ダ?解除 */
  8697. skill_status_change_end(bl,SC_LIGHTNINGLOADER,-1);
  8698. if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* サイスミックウェポン解除 */
  8699. skill_status_change_end(bl,SC_SEISMICWEAPON,-1);
  8700. return 0;
  8701. }
  8702. /*==========================================
  8703. * ステ?タス異常開始
  8704. *------------------------------------------
  8705. */
  8706. int skill_status_change_start(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag)
  8707. {
  8708. struct map_session_data *sd = NULL;
  8709. struct status_change* sc_data;
  8710. short *sc_count, *option, *opt1, *opt2, *opt3;
  8711. int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag;
  8712. int scdef=0;
  8713. nullpo_retr(0, bl);
  8714. if(bl->type == BL_SKILL)
  8715. return 0;
  8716. nullpo_retr(0, sc_data=battle_get_sc_data(bl));
  8717. nullpo_retr(0, sc_count=battle_get_sc_count(bl));
  8718. nullpo_retr(0, option=battle_get_option(bl));
  8719. nullpo_retr(0, opt1=battle_get_opt1(bl));
  8720. nullpo_retr(0, opt2=battle_get_opt2(bl));
  8721. nullpo_retr(0, opt3=battle_get_opt3(bl));
  8722. race=battle_get_race(bl);
  8723. mode=battle_get_mode(bl);
  8724. elem=battle_get_elem_type(bl);
  8725. undead_flag=battle_check_undead(race,elem);
  8726. if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) )
  8727. return 0;
  8728. switch(type){
  8729. case SC_STONE:
  8730. case SC_FREEZE:
  8731. scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3;
  8732. break;
  8733. case SC_STAN:
  8734. case SC_SILENCE:
  8735. case SC_POISON:
  8736. case SC_DPOISON:
  8737. scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3;
  8738. break;
  8739. case SC_SLEEP:
  8740. case SC_BLIND:
  8741. scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3;
  8742. break;
  8743. case SC_CURSE:
  8744. scdef=3+battle_get_luk(bl);
  8745. break;
  8746. // case SC_CONFUSION:
  8747. default:
  8748. scdef=0;
  8749. }
  8750. if(scdef>=100)
  8751. return 0;
  8752. if(bl->type==BL_PC){
  8753. sd=(struct map_session_data *)bl;
  8754. if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
  8755. return 0;
  8756. if(SC_STONE<=type && type<=SC_BLIND){ /* カ?ドによる耐性 */
  8757. if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){
  8758. if(battle_config.battle_log)
  8759. printf("PC %d skill_sc_start: cardによる異常耐性?動\n",sd->bl.id);
  8760. return 0;
  8761. }
  8762. }
  8763. }
  8764. else if(bl->type == BL_MOB) {
  8765. }
  8766. else {
  8767. if(battle_config.error_log)
  8768. printf("skill_status_change_start: neither MOB nor PC !\n");
  8769. return 0;
  8770. }
  8771. if(type==SC_FREEZE && undead_flag && !(flag&1))
  8772. return 0;
  8773. if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) &&
  8774. sc_data[type].timer != -1 && sc_data[type].val2 && !val2)
  8775. return 0;
  8776. if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE ||
  8777. type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE ||
  8778. (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){
  8779. /* ボスには?かない(ただしカ?ドによる?果は適用される) */
  8780. return 0;
  8781. }
  8782. if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP)
  8783. battle_stopwalking(bl,1);
  8784. if(sc_data[type].timer != -1){ /* すでに同じ異常になっている場合タイマ解除 */
  8785. if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION &&
  8786. type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2
  8787. && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
  8788. return 0;
  8789. if ((type >=SC_STAN && type <= SC_BLIND) || type == SC_DPOISON)
  8790. return 0;/* ?ぎ足しができない?態異常である時は?態異常を行わない */
  8791. if(type == SC_GRAFFITI){ //異常中にもう一度?態異常になった時に解除してから再度かかる
  8792. skill_status_change_end(bl,type,-1);
  8793. } else {
  8794. (*sc_count)--;
  8795. delete_timer(sc_data[type].timer, skill_status_change_timer);
  8796. sc_data[type].timer = -1;
  8797. }
  8798. }
  8799. switch(type){ /* 異常の種類ごとの?理 */
  8800. case SC_PROVOKE: /* プロボック */
  8801. calc_flag = 1;
  8802. if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
  8803. break;
  8804. case SC_ENDURE: /* インデュア */
  8805. if(tick <= 0) tick = 1000 * 60;
  8806. calc_flag = 1; // for updating mdef
  8807. val2 = 7; // [Celest]
  8808. break;
  8809. case SC_AUTOBERSERK:
  8810. {
  8811. tick = 60*1000;
  8812. if (bl->type == BL_PC && sd->status.hp<sd->status.max_hp>>2 &&
  8813. (sc_data[SC_PROVOKE].timer==-1 || sc_data[SC_PROVOKE].val2==0))
  8814. skill_status_change_start(bl,SC_PROVOKE,10,1,0,0,0,0);
  8815. }
  8816. break;
  8817. case SC_CONCENTRATE: /* 集中力向上 */
  8818. calc_flag = 1;
  8819. break;
  8820. case SC_BLESSING: /* ブレッシング */
  8821. {
  8822. if(bl->type == BL_PC || (!undead_flag && race != 6)) {
  8823. if(sc_data[SC_CURSE].timer!=-1 )
  8824. skill_status_change_end(bl,SC_CURSE,-1);
  8825. if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0)
  8826. skill_status_change_end(bl,SC_STONE,-1);
  8827. }
  8828. calc_flag = 1;
  8829. }
  8830. break;
  8831. case SC_ANGELUS: /* アンゼルス */
  8832. calc_flag = 1;
  8833. break;
  8834. case SC_INCREASEAGI: /* 速度上昇 */
  8835. calc_flag = 1;
  8836. if(sc_data[SC_DECREASEAGI].timer!=-1 )
  8837. skill_status_change_end(bl,SC_DECREASEAGI,-1);
  8838. if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
  8839. skill_status_change_end(bl,SC_WINDWALK,-1);
  8840. break;
  8841. case SC_DECREASEAGI: /* 速度減少 */
  8842. if (bl->type == BL_PC) // Celest
  8843. tick>>=1;
  8844. calc_flag = 1;
  8845. if(sc_data[SC_INCREASEAGI].timer!=-1 )
  8846. skill_status_change_end(bl,SC_INCREASEAGI,-1);
  8847. if(sc_data[SC_ADRENALINE].timer!=-1 )
  8848. skill_status_change_end(bl,SC_ADRENALINE,-1);
  8849. if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
  8850. skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
  8851. if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
  8852. skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
  8853. break;
  8854. case SC_SIGNUMCRUCIS: /* シグナムクルシス */
  8855. calc_flag = 1;
  8856. // val2 = 14 + val1;
  8857. val2 = 10 + val1*2;
  8858. tick = 600*1000;
  8859. clif_emotion(bl,4);
  8860. break;
  8861. case SC_SLOWPOISON:
  8862. if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1)
  8863. return 0;
  8864. break;
  8865. case SC_TWOHANDQUICKEN: /* 2HQ */
  8866. if(sc_data[SC_DECREASEAGI].timer!=-1)
  8867. return 0;
  8868. *opt3 |= 1;
  8869. calc_flag = 1;
  8870. break;
  8871. case SC_ADRENALINE: /* アドレナリンラッシュ */
  8872. if(sc_data[SC_DECREASEAGI].timer!=-1)
  8873. return 0;
  8874. calc_flag = 1;
  8875. break;
  8876. case SC_WEAPONPERFECTION: /* ウェポンパ?フェクション */
  8877. // Lasting time penalties have been removed on sakray as of 12/14 [celest]
  8878. //if(battle_config.party_skill_penalty && !val2) tick /= 5;
  8879. break;
  8880. case SC_OVERTHRUST: /* オ?バ?スラスト */
  8881. *opt3 |= 2;
  8882. // Lasting time penalties have been removed on sakray as of 12/14 [celest]
  8883. //if(battle_config.party_skill_penalty && !val2) tick /= 10;
  8884. break;
  8885. case SC_MAXIMIZEPOWER: /* マキシマイズパワ?(SPが1減る時間,val2にも) */
  8886. if(bl->type == BL_PC)
  8887. val2 = tick;
  8888. else
  8889. tick = 5000*val1;
  8890. break;
  8891. case SC_ENCPOISON: /* エンチャントポイズン */
  8892. calc_flag = 1;
  8893. val2=(((val1 - 1) / 2) + 3)*100; /* 毒付?確率 */
  8894. skill_encchant_eremental_end(bl,SC_ENCPOISON);
  8895. break;
  8896. case SC_EDP: // [Celest]
  8897. val2 = val1 + 2; /* 猛毒付?確率(%) */
  8898. calc_flag = 1;
  8899. break;
  8900. case SC_POISONREACT: /* ポイズンリアクト */
  8901. val2=val1/2 + val1%2; // [Celest]
  8902. break;
  8903. case SC_IMPOSITIO: /* インポシティオマヌス */
  8904. calc_flag = 1;
  8905. break;
  8906. case SC_ASPERSIO: /* アスペルシオ */
  8907. skill_encchant_eremental_end(bl,SC_ASPERSIO);
  8908. break;
  8909. case SC_SUFFRAGIUM: /* サフラギム */
  8910. case SC_BENEDICTIO: /* 聖? */
  8911. case SC_MAGNIFICAT: /* マグニフィカ?ト */
  8912. case SC_AETERNA: /* エ?テルナ */
  8913. break;
  8914. case SC_ENERGYCOAT: /* エナジ?コ?ト */
  8915. *opt3 |= 4;
  8916. break;
  8917. case SC_MAGICROD:
  8918. val2 = val1*20;
  8919. break;
  8920. case SC_KYRIE: /* キリエエレイソン */
  8921. val2 = battle_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* 耐久度 */
  8922. val3 = (val1 / 2 + 5); /* 回? */
  8923. // -- moonsoul (added to undo assumptio status if target has it)
  8924. if(sc_data[SC_ASSUMPTIO].timer!=-1 )
  8925. skill_status_change_end(bl,SC_ASSUMPTIO,-1);
  8926. break;
  8927. case SC_MINDBREAKER:
  8928. calc_flag = 1;
  8929. if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
  8930. case SC_GLORIA: /* グロリア */
  8931. calc_flag = 1;
  8932. break;
  8933. case SC_LOUD: /* ラウドボイス */
  8934. calc_flag = 1;
  8935. break;
  8936. case SC_TRICKDEAD: /* 死んだふり */
  8937. break;
  8938. case SC_QUAGMIRE: /* クァグマイア */
  8939. calc_flag = 1;
  8940. if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* 集中力向上解除 */
  8941. skill_status_change_end(bl,SC_CONCENTRATE,-1);
  8942. if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
  8943. skill_status_change_end(bl,SC_INCREASEAGI,-1);
  8944. if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
  8945. skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
  8946. if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
  8947. skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
  8948. if(sc_data[SC_ADRENALINE].timer!=-1 )
  8949. skill_status_change_end(bl,SC_ADRENALINE,-1);
  8950. if(sc_data[SC_LOUD].timer!=-1 )
  8951. skill_status_change_end(bl,SC_LOUD,-1);
  8952. if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
  8953. skill_status_change_end(bl,SC_TRUESIGHT,-1);
  8954. if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
  8955. skill_status_change_end(bl,SC_WINDWALK,-1);
  8956. if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
  8957. skill_status_change_end(bl,SC_CARTBOOST,-1);
  8958. break;
  8959. case SC_FLAMELAUNCHER: /* フレ?ムランチャ? */
  8960. skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER);
  8961. break;
  8962. case SC_FROSTWEAPON: /* フロストウェポン */
  8963. skill_encchant_eremental_end(bl,SC_FROSTWEAPON);
  8964. break;
  8965. case SC_LIGHTNINGLOADER: /* ライトニングロ?ダ? */
  8966. skill_encchant_eremental_end(bl,SC_LIGHTNINGLOADER);
  8967. break;
  8968. case SC_SEISMICWEAPON: /* サイズミックウェポン */
  8969. skill_encchant_eremental_end(bl,SC_SEISMICWEAPON);
  8970. break;
  8971. case SC_DEVOTION: /* ディボ?ション */
  8972. calc_flag = 1;
  8973. break;
  8974. case SC_PROVIDENCE: /* プロヴィデンス */
  8975. calc_flag = 1;
  8976. val2=val1*5;
  8977. break;
  8978. case SC_REFLECTSHIELD:
  8979. val2=10+val1*3;
  8980. break;
  8981. case SC_STRIPWEAPON:
  8982. if (val2==0) val2=90;
  8983. break;
  8984. case SC_STRIPSHIELD:
  8985. if (val2==0) val2=85;
  8986. break;
  8987. case SC_STRIPARMOR:
  8988. case SC_STRIPHELM:
  8989. case SC_CP_WEAPON:
  8990. case SC_CP_SHIELD:
  8991. case SC_CP_ARMOR:
  8992. case SC_CP_HELM:
  8993. break;
  8994. case SC_AUTOSPELL: /* オ?トスペル */
  8995. val4 = 5 + val1*2;
  8996. break;
  8997. case SC_VOLCANO:
  8998. calc_flag = 1;
  8999. val3 = val1*10;
  9000. val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
  9001. break;
  9002. case SC_DELUGE:
  9003. calc_flag = 1;
  9004. val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) );
  9005. val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
  9006. break;
  9007. case SC_VIOLENTGALE:
  9008. calc_flag = 1;
  9009. val3 = val1*3;
  9010. val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
  9011. break;
  9012. case SC_SPEARSQUICKEN: /* スピアクイッケン */
  9013. calc_flag = 1;
  9014. val2 = 20+val1;
  9015. *opt3 |= 1;
  9016. break;
  9017. case SC_COMBO:
  9018. break;
  9019. case SC_BLADESTOP_WAIT: /* 白刃取り(待ち) */
  9020. break;
  9021. case SC_BLADESTOP: /* 白刃取り */
  9022. if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1);
  9023. *opt3 |= 32;
  9024. break;
  9025. case SC_LULLABY: /* 子守唄 */
  9026. val2 = 11;
  9027. break;
  9028. case SC_RICHMANKIM:
  9029. break;
  9030. case SC_ETERNALCHAOS: /* エタ?ナルカオス */
  9031. calc_flag = 1;
  9032. break;
  9033. case SC_DRUMBATTLE: /* ?太鼓の響き */
  9034. calc_flag = 1;
  9035. val2 = (val1+1)*25;
  9036. val3 = (val1+1)*2;
  9037. break;
  9038. case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
  9039. calc_flag = 1;
  9040. //val2 = (val1+2)*50;
  9041. val3 = (val1+2)*25;
  9042. break;
  9043. case SC_ROKISWEIL: /* ロキの叫び */
  9044. break;
  9045. case SC_INTOABYSS: /* 深淵の中に */
  9046. break;
  9047. case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  9048. calc_flag = 1;
  9049. val2 = 55 + val1*5;
  9050. val3 = val1*10;
  9051. break;
  9052. case SC_DISSONANCE: /* 不協和音 */
  9053. val2 = 10;
  9054. break;
  9055. case SC_WHISTLE: /* 口笛 */
  9056. calc_flag = 1;
  9057. break;
  9058. case SC_ASSNCROS: /* 夕陽のアサシンクロス */
  9059. calc_flag = 1;
  9060. break;
  9061. case SC_POEMBRAGI: /* ブラギの詩 */
  9062. break;
  9063. case SC_APPLEIDUN: /* イドゥンの林檎 */
  9064. calc_flag = 1;
  9065. break;
  9066. case SC_UGLYDANCE: /* 自分勝手なダンス */
  9067. val2 = 10;
  9068. break;
  9069. case SC_HUMMING: /* ハミング */
  9070. calc_flag = 1;
  9071. break;
  9072. case SC_DONTFORGETME: /* 私を忘れないで */
  9073. calc_flag = 1;
  9074. if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
  9075. skill_status_change_end(bl,SC_INCREASEAGI,-1);
  9076. if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
  9077. skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
  9078. if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
  9079. skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
  9080. if(sc_data[SC_ADRENALINE].timer!=-1 )
  9081. skill_status_change_end(bl,SC_ADRENALINE,-1);
  9082. if(sc_data[SC_ASSNCROS].timer!=-1 )
  9083. skill_status_change_end(bl,SC_ASSNCROS,-1);
  9084. if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
  9085. skill_status_change_end(bl,SC_TRUESIGHT,-1);
  9086. if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
  9087. skill_status_change_end(bl,SC_WINDWALK,-1);
  9088. if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
  9089. skill_status_change_end(bl,SC_CARTBOOST,-1);
  9090. break;
  9091. case SC_FORTUNE: /* 幸運のキス */
  9092. calc_flag = 1;
  9093. break;
  9094. case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
  9095. calc_flag = 1;
  9096. break;
  9097. case SC_DANCING: /* ダンス/演奏中 */
  9098. calc_flag = 1;
  9099. val3= tick / 1000;
  9100. tick = 1000;
  9101. break;
  9102. case SC_EXPLOSIONSPIRITS: // 爆裂波動
  9103. calc_flag = 1;
  9104. val2 = 75 + 25*val1;
  9105. *opt3 |= 8;
  9106. break;
  9107. case SC_STEELBODY: // 金剛
  9108. calc_flag = 1;
  9109. *opt3 |= 16;
  9110. break;
  9111. case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */
  9112. break;
  9113. case SC_AUTOCOUNTER:
  9114. val3 = val4 = 0;
  9115. break;
  9116. case SC_SPEEDPOTION0: /* ?速ポ?ション */
  9117. case SC_SPEEDPOTION1:
  9118. case SC_SPEEDPOTION2:
  9119. calc_flag = 1;
  9120. tick = 1000 * tick;
  9121. val2 = 5*(2+type-SC_SPEEDPOTION0);
  9122. break;
  9123. /* atk & matk potions [Valaris] */
  9124. case SC_ATKPOT:
  9125. case SC_MATKPOT:
  9126. calc_flag = 1;
  9127. tick = 1000 * tick;
  9128. break;
  9129. case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
  9130. {
  9131. time_t timer;
  9132. calc_flag = 1;
  9133. tick = 10000;
  9134. if(!val2)
  9135. val2 = time(&timer);
  9136. }
  9137. break;
  9138. case SC_NOCHAT: //チャット禁止?態
  9139. {
  9140. time_t timer;
  9141. if(!battle_config.muting_players)
  9142. break;
  9143. tick = 60000;
  9144. if(!val2)
  9145. val2 = time(&timer);
  9146. updateflag = SP_MANNER;
  9147. save_flag = 1; // celest
  9148. }
  9149. break;
  9150. case SC_SELFDESTRUCTION: //自爆
  9151. clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1));
  9152. val3 = tick / 1000;
  9153. tick = 1000;
  9154. break;
  9155. /* option1 */
  9156. case SC_STONE: /* 石化 */
  9157. if(!(flag&2)) {
  9158. int sc_def = battle_get_mdef(bl)*200;
  9159. tick = tick - sc_def;
  9160. }
  9161. val3 = tick/1000;
  9162. if(val3 < 1) val3 = 1;
  9163. tick = 5000;
  9164. val2 = 1;
  9165. break;
  9166. case SC_SLEEP: /* 睡眠 */
  9167. if(!(flag&2)) {
  9168. // int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
  9169. // tick = tick * sc_def / 100;
  9170. // if(tick < 1000) tick = 1000;
  9171. tick = 30000;//睡眠はステ?タス耐性に?わらず30秒
  9172. }
  9173. break;
  9174. case SC_FREEZE: /* 凍結 */
  9175. if(!(flag&2)) {
  9176. int sc_def = 100 - battle_get_mdef(bl);
  9177. tick = tick * sc_def / 100;
  9178. }
  9179. break;
  9180. case SC_STAN: /* スタン(val2にミリ秒セット) */
  9181. if(!(flag&2)) {
  9182. int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/3);
  9183. tick = tick * sc_def / 100;
  9184. }
  9185. break;
  9186. /* option2 */
  9187. case SC_POISON: /* 毒 */
  9188. case SC_DPOISON: /* 猛毒 */
  9189. calc_flag = 1;
  9190. if(!(flag&2)) {
  9191. int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5);
  9192. tick = tick * sc_def / 100;
  9193. }
  9194. val3 = tick/1000;
  9195. if(val3 < 1) val3 = 1;
  9196. tick = 1000;
  9197. break;
  9198. case SC_SILENCE: /* 沈?(レックスデビ?ナ) */
  9199. if(!(flag&2)) {
  9200. int sc_def = 100 - battle_get_vit(bl);
  9201. tick = tick * sc_def / 100;
  9202. }
  9203. break;
  9204. case SC_CONFUSION:
  9205. val2 = tick;
  9206. tick = 100;
  9207. clif_emotion(bl,1);
  9208. if (sd) {
  9209. pc_stop_walking (sd, 0);
  9210. }
  9211. break;
  9212. case SC_BLIND: /* 暗? */
  9213. calc_flag = 1;
  9214. if(!(flag&2)) {
  9215. int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15;
  9216. tick = 30000 - sc_def;
  9217. }
  9218. break;
  9219. case SC_CURSE:
  9220. calc_flag = 1;
  9221. if(!(flag&2)) {
  9222. int sc_def = 100 - battle_get_vit(bl);
  9223. tick = tick * sc_def / 100;
  9224. }
  9225. break;
  9226. /* option */
  9227. case SC_HIDING: /* ハイディング */
  9228. calc_flag = 1;
  9229. if(bl->type == BL_PC) {
  9230. val2 = tick / 1000; /* 持?時間 */
  9231. tick = 1000;
  9232. }
  9233. break;
  9234. case SC_CHASEWALK:
  9235. case SC_CLOAKING: /* クロ?キング */
  9236. if(bl->type == BL_PC) {
  9237. calc_flag = 1; // [Celest]
  9238. val2 = tick;
  9239. val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5;
  9240. }
  9241. else
  9242. tick = 5000*val1;
  9243. break;
  9244. case SC_SIGHT: /* サイト/ルアフ */
  9245. case SC_RUWACH:
  9246. val2 = tick/250;
  9247. tick = 10;
  9248. break;
  9249. /* セ?フティウォ?ル、ニュ?マ */
  9250. case SC_SAFETYWALL: case SC_PNEUMA:
  9251. tick=((struct skill_unit *)val2)->group->limit;
  9252. break;
  9253. /* アンクル */
  9254. case SC_ANKLE:
  9255. break;
  9256. /* ウォ?タ?ボ?ル */
  9257. case SC_WATERBALL:
  9258. tick=150;
  9259. if(val1>5) //レベルが5以上の場合は25?に制限(1?目はすでに打ってるので-1)
  9260. val3=5*5-1;
  9261. else
  9262. val3= (val1|1)*(val1|1)-1;
  9263. break;
  9264. /* スキルじゃない/時間に?係しない */
  9265. case SC_RIDING:
  9266. calc_flag = 1;
  9267. tick = 600*1000;
  9268. break;
  9269. case SC_FALCON:
  9270. case SC_WEIGHT50:
  9271. case SC_WEIGHT90:
  9272. case SC_BROKNWEAPON:
  9273. case SC_BROKNARMOR:
  9274. tick=600*1000;
  9275. break;
  9276. case SC_AUTOGUARD:
  9277. {
  9278. int i,t;
  9279. for(i=val2=0;i<val1;i++) {
  9280. t = 5-(i>>1);
  9281. val2 += (t < 0)? 1:t;
  9282. }
  9283. }
  9284. break;
  9285. case SC_DEFENDER:
  9286. calc_flag = 1;
  9287. val2 = 5 + val1*15;
  9288. break;
  9289. case SC_KEEPING:
  9290. case SC_BARRIER:
  9291. calc_flag = 1;
  9292. case SC_HALLUCINATION:
  9293. break;
  9294. case SC_CONCENTRATION: /* コンセントレ?ション */
  9295. *opt3 |= 1;
  9296. calc_flag = 1;
  9297. break;
  9298. case SC_TENSIONRELAX: /* テンションリラックス */
  9299. calc_flag = 1;
  9300. if(bl->type == BL_PC) {
  9301. tick = 10000;
  9302. }
  9303. break;
  9304. case SC_AURABLADE: /* オ?ラブレ?ド */
  9305. case SC_PARRYING: /* パリイング */
  9306. // case SC_ASSUMPTIO: /* */
  9307. case SC_HEADCRUSH: /* ヘッドクラッシュ */
  9308. case SC_JOINTBEAT: /* ジョイントビ?ト */
  9309. // case SC_MARIONETTE: /* マリオネットコントロ?ル */
  9310. //とりあえず手?き
  9311. break;
  9312. // -- moonsoul (for new upper class related skill status effects)
  9313. /*
  9314. case SC_AURABLADE:
  9315. val2 = val1*10;
  9316. break;
  9317. case SC_PARRYING:
  9318. val2=val1*3;
  9319. break;
  9320. case SC_CONCENTRATION:
  9321. calc_flag=1;
  9322. val2=val1*10;
  9323. val3=val1*5;
  9324. break;
  9325. case SC_TENSIONRELAX:
  9326. // val2 = 10;
  9327. // val3 = 15;
  9328. break;
  9329. case SC_BERSERK:
  9330. calc_flag=1;
  9331. break;
  9332. case SC_ASSUMPTIO:
  9333. if(sc_data[SC_KYRIE].timer!=-1 )
  9334. skill_status_change_end(bl,SC_KYRIE,-1);
  9335. break;*/
  9336. case SC_WINDWALK: /* ウインドウォ?ク */
  9337. calc_flag = 1;
  9338. val2 = (val1 / 2); //Flee上昇率
  9339. break;
  9340. case SC_BERSERK: /* バ?サ?ク */
  9341. if(sd){
  9342. sd->status.hp = sd->status.max_hp * 3;
  9343. sd->status.sp = 0;
  9344. clif_updatestatus(sd,SP_HP);
  9345. clif_updatestatus(sd,SP_SP);
  9346. clif_status_change(bl,SC_INCREASEAGI,1); /* アイコン表示 */
  9347. sd->canregen_tick = gettick() + 300000;
  9348. }
  9349. *opt3 |= 128;
  9350. tick = 10000;
  9351. calc_flag = 1;
  9352. break;
  9353. case SC_ASSUMPTIO: /* アスムプティオ */
  9354. if(sc_data[SC_KYRIE].timer!=-1 )
  9355. skill_status_change_end(bl,SC_KYRIE,-1);
  9356. break;
  9357. *opt3 |= 2048;
  9358. break;
  9359. case SC_BASILICA: // [celest]
  9360. break;
  9361. case SC_MARIONETTE: /* マリオネットコントロ?ル */
  9362. case SC_MARIONETTE2:
  9363. val2 = tick;
  9364. if (!val3)
  9365. return 0;
  9366. tick = 1000;
  9367. calc_flag = 1;
  9368. *opt3 |= 1024;
  9369. break;
  9370. case SC_MELTDOWN: /* メルトダウン */
  9371. case SC_CARTBOOST: /* カ?トブ?スト */
  9372. case SC_TRUESIGHT: /* トゥル?サイト */
  9373. case SC_SPIDERWEB: /* スパイダ?ウェッブ */
  9374. case SC_MAGICPOWER: /* 魔法力?幅 */
  9375. calc_flag = 1;
  9376. break;
  9377. case SC_REJECTSWORD: /* リジェクトソ?ド */
  9378. val2 = 3; //3回攻?を跳ね返す
  9379. break;
  9380. case SC_MEMORIZE: /* メモライズ */
  9381. val2 = 3; //3回詠唱を1/3にする
  9382. break;
  9383. case SC_GRAFFITI: /* グラフィティ */
  9384. {
  9385. struct skill_unit_group *sg = skill_unitsetting(bl,RG_GRAFFITI,val1,val2,val3,0);
  9386. if(sg)
  9387. val4 = (int)sg;
  9388. }
  9389. break;
  9390. case SC_SPLASHER: /* ベナムスプラッシャ? */
  9391. break;
  9392. case SC_FOGWALL:
  9393. val2 = 75;
  9394. // calc_flag = 1; // not sure of effects yet [celest]
  9395. break;
  9396. case SC_BLOCKSKILL:
  9397. if (!tick) tick = 60000;
  9398. if (!val3) val3 = -1;
  9399. break;
  9400. case SC_SLOWDOWN:
  9401. calc_flag = 1;
  9402. break;
  9403. case SC_LEADERSHIP:
  9404. case SC_GLORYWOUNDS:
  9405. case SC_SOULCOLD:
  9406. case SC_HAWKEYES:
  9407. tick = 1000;
  9408. calc_flag = 1;
  9409. //val4 = 1;
  9410. break;
  9411. case SC_REGENERATION:
  9412. val1 = 2;
  9413. case SC_BATTLEORDERS:
  9414. tick = 60000; // 1 minute
  9415. calc_flag = 1;
  9416. break;
  9417. default:
  9418. if(battle_config.error_log)
  9419. printf("UnknownStatusChange [%d]\n", type);
  9420. return 0;
  9421. }
  9422. if(bl->type==BL_PC && type<SC_SENDMAX)
  9423. clif_status_change(bl,type,1); /* アイコン表示 */
  9424. /* optionの?更 */
  9425. switch(type){
  9426. case SC_STONE:
  9427. case SC_FREEZE:
  9428. case SC_STAN:
  9429. case SC_SLEEP:
  9430. battle_stopattack(bl); /* 攻?停止 */
  9431. skill_stop_dancing(bl,0); /* 演奏/ダンスの中? */
  9432. { /* 同時に掛からないステ?タス異常を解除 */
  9433. int i;
  9434. for(i = SC_STONE; i <= SC_SLEEP; i++){
  9435. if(sc_data[i].timer != -1){
  9436. (*sc_count)--;
  9437. delete_timer(sc_data[i].timer, skill_status_change_timer);
  9438. sc_data[i].timer = -1;
  9439. }
  9440. }
  9441. }
  9442. if(type == SC_STONE)
  9443. *opt1 = 6;
  9444. else
  9445. *opt1 = type - SC_STONE + 1;
  9446. opt_flag = 1;
  9447. break;
  9448. case SC_POISON:
  9449. case SC_CURSE:
  9450. case SC_SILENCE:
  9451. case SC_BLIND:
  9452. *opt2 |= 1<<(type-SC_POISON);
  9453. opt_flag = 1;
  9454. break;
  9455. case SC_DPOISON: // 暫定で毒のエフェクトを使用
  9456. *opt2 |= 1;
  9457. opt_flag = 1;
  9458. break;
  9459. case SC_SIGNUMCRUCIS:
  9460. *opt2 |= 0x40;
  9461. opt_flag = 1;
  9462. break;
  9463. case SC_HIDING:
  9464. case SC_CLOAKING:
  9465. battle_stopattack(bl); /* 攻?停止 */
  9466. *option |= ((type==SC_HIDING)?2:4);
  9467. opt_flag =1 ;
  9468. break;
  9469. case SC_CHASEWALK:
  9470. battle_stopattack(bl); /* 攻?停止 */
  9471. *option |= 16388;
  9472. opt_flag =1 ;
  9473. break;
  9474. case SC_SIGHT:
  9475. *option |= 1;
  9476. opt_flag = 1;
  9477. break;
  9478. case SC_RUWACH:
  9479. *option |= 8192;
  9480. opt_flag = 1;
  9481. break;
  9482. case SC_WEDDING:
  9483. *option |= 4096;
  9484. opt_flag = 1;
  9485. }
  9486. if(opt_flag) /* optionの?更 */
  9487. clif_changeoption(bl);
  9488. (*sc_count)++; /* ステ?タス異常の? */
  9489. sc_data[type].val1 = val1;
  9490. sc_data[type].val2 = val2;
  9491. sc_data[type].val3 = val3;
  9492. sc_data[type].val4 = val4;
  9493. /* タイマ?設定 */
  9494. sc_data[type].timer = add_timer(
  9495. gettick() + tick, skill_status_change_timer, bl->id, type);
  9496. if(bl->type==BL_PC && calc_flag)
  9497. pc_calcstatus(sd,0); /* ステ?タス再計算 */
  9498. if(bl->type==BL_PC && save_flag)
  9499. chrif_save(sd); // save the player status
  9500. if(bl->type==BL_PC && updateflag)
  9501. clif_updatestatus(sd,updateflag); /* ステ?タスをクライアントに送る */
  9502. return 0;
  9503. }
  9504. /*==========================================
  9505. * ステ?タス異常全解除
  9506. *------------------------------------------
  9507. */
  9508. int skill_status_change_clear(struct block_list *bl, int type)
  9509. {
  9510. struct status_change* sc_data;
  9511. short *sc_count, *option, *opt1, *opt2, *opt3;
  9512. int i;
  9513. nullpo_retr(0, bl);
  9514. nullpo_retr(0, sc_data = battle_get_sc_data(bl));
  9515. nullpo_retr(0, sc_count = battle_get_sc_count(bl));
  9516. nullpo_retr(0, option = battle_get_option(bl));
  9517. nullpo_retr(0, opt1 = battle_get_opt1(bl));
  9518. nullpo_retr(0, opt2 = battle_get_opt2(bl));
  9519. nullpo_retr(0, opt3 = battle_get_opt3(bl));
  9520. if (*sc_count == 0)
  9521. return 0;
  9522. for(i = 0; i < MAX_STATUSCHANGE; i++){
  9523. if(sc_data[i].timer != -1){ /* 異常があるならタイマ?を削除する */
  9524. /*
  9525. delete_timer(sc_data[i].timer, skill_status_change_timer);
  9526. sc_data[i].timer = -1;
  9527. if (!type && i < SC_SENDMAX)
  9528. clif_status_change(bl, i, 0);
  9529. */
  9530. skill_status_change_end(bl, i, -1);
  9531. }
  9532. }
  9533. *sc_count = 0;
  9534. *opt1 = 0;
  9535. *opt2 = 0;
  9536. *opt3 = 0;
  9537. *option &= OPTION_MASK;
  9538. if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor]
  9539. !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest]
  9540. *opt2 |= STATE_BLIND;
  9541. if(!type || type&2)
  9542. clif_changeoption(bl);
  9543. return 0;
  9544. }
  9545. /* クロ?キング?査(周りに移動不可能地?があるか) */
  9546. int skill_check_cloaking(struct block_list *bl)
  9547. {
  9548. static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
  9549. static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
  9550. int end=1,i;
  9551. //missing sd [Found by Celest, commited by Aria]
  9552. struct map_session_data *sd=(struct map_session_data *)bl;
  9553. nullpo_retr(0, bl);
  9554. if(bl->type == BL_PC && !battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
  9555. return 0;
  9556. else if(bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
  9557. return 0;
  9558. for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){
  9559. int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
  9560. if(c==1 || c==5) {
  9561. end=0;
  9562. break;
  9563. }
  9564. }
  9565. if(end){
  9566. if ((bl->type == BL_PC && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
  9567. skill_status_change_end(bl, SC_CLOAKING, -1);
  9568. *battle_get_option(bl)&=~4; /* 念のための?理 */
  9569. }
  9570. else if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 130) {
  9571. sd->sc_data[SC_CLOAKING].val3 = 130;
  9572. pc_calcspeed (sd);
  9573. }
  9574. }
  9575. else {
  9576. if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 103) {
  9577. sd->sc_data[SC_CLOAKING].val3 = 103;
  9578. pc_calcspeed (sd);
  9579. }
  9580. }
  9581. return end;
  9582. }
  9583. int skill_type_cloaking(struct block_list *bl)
  9584. {
  9585. static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
  9586. static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
  9587. int i;
  9588. nullpo_retr(0, bl);
  9589. if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
  9590. return 0;
  9591. else if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1)
  9592. return 0;
  9593. for(i=0; i<sizeof(dx)/sizeof(dx[0]); i++)
  9594. {
  9595. int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
  9596. if(c==1 || c==5)
  9597. return 0;
  9598. }
  9599. return 1;
  9600. }
  9601. /*
  9602. *----------------------------------------------------------------------------
  9603. * スキルユニット
  9604. *----------------------------------------------------------------------------
  9605. */
  9606. /*==========================================
  9607. * 演奏/ダンススキルかどうか判定
  9608. * 引? スキルID
  9609. * ?り ダンスじゃない=0 合奏=2 それ以外のダンス=1
  9610. *------------------------------------------
  9611. */
  9612. int skill_is_danceskill(int id)
  9613. {
  9614. int i;
  9615. switch(id){
  9616. case BD_LULLABY: /* 子守歌 */
  9617. case BD_RICHMANKIM: /* ニヨルドの宴 */
  9618. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  9619. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  9620. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  9621. case BD_ROKISWEIL: /* ロキの叫び */
  9622. case BD_INTOABYSS: /* 深淵の中に */
  9623. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  9624. case BD_RAGNAROK: /* 神?の?昏 */
  9625. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  9626. i=2;
  9627. break;
  9628. case BA_DISSONANCE: /* 不協和音 */
  9629. case BA_FROSTJOKE: /* 寒いジョ?ク */
  9630. case BA_WHISTLE: /* 口笛 */
  9631. case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
  9632. case BA_POEMBRAGI: /* ブラギの詩 */
  9633. case BA_APPLEIDUN: /* イドゥンの林檎 */
  9634. case DC_UGLYDANCE: /* 自分勝手なダンス */
  9635. case DC_SCREAM: /* スクリ?ム */
  9636. case DC_HUMMING: /* ハミング */
  9637. case DC_DONTFORGETME: /* 私を忘れないで… */
  9638. case DC_FORTUNEKISS: /* 幸運のキス */
  9639. case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
  9640. i=1;
  9641. break;
  9642. default:
  9643. i=0;
  9644. }
  9645. return i;
  9646. }
  9647. /*==========================================
  9648. * 演奏/ダンスをやめる
  9649. * flag 1で合奏中なら相方にユニットを任せる
  9650. *
  9651. *------------------------------------------
  9652. */
  9653. void skill_stop_dancing(struct block_list *src, int flag)
  9654. {
  9655. struct status_change* sc_data;
  9656. struct skill_unit_group* group;
  9657. nullpo_retv(src);
  9658. nullpo_retv(sc_data = battle_get_sc_data(src));
  9659. if(sc_data[SC_DANCING].timer != -1) {
  9660. group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる
  9661. if(group && src->type==BL_PC && sc_data && sc_data[SC_DANCING].val4){ //合奏中?
  9662. struct map_session_data* dsd=map_id2sd(sc_data[SC_DANCING].val4); //相方のsd取得
  9663. if(flag){ //ログアウトなど片方が落ちても演奏が??される
  9664. if(dsd && src->id == group->src_id){ //グル?プを持ってるPCが落ちる
  9665. group->src_id=sc_data[SC_DANCING].val4; //相方にグル?プを任せる
  9666. if(flag&1) //ログアウト
  9667. dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス?態
  9668. if(flag&2) //ハエ飛びなど
  9669. return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
  9670. }else if(dsd && dsd->bl.id == group->src_id){ //相方がグル?プを持っているPCが落ちる(自分はグル?プを持っていない)
  9671. if(flag&1) //ログアウト
  9672. dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス?態
  9673. if(flag&2) //ハエ飛びなど
  9674. return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
  9675. }
  9676. skill_status_change_end(src,SC_DANCING,-1);//自分のステ?タスを終了させる
  9677. //そしてグル?プは消さない&消さないのでステ?タス計算もいらない?
  9678. return;
  9679. }else{
  9680. if(dsd && src->id == group->src_id){ //グル?プを持ってるPCが止める
  9681. skill_status_change_end((struct block_list *)dsd,SC_DANCING,-1);//相手のステ?タスを終了させる
  9682. }
  9683. if(dsd && dsd->bl.id == group->src_id){ //相方がグル?プを持っているPCが止める(自分はグル?プを持っていない)
  9684. skill_status_change_end(src,SC_DANCING,-1);//自分のステ?タスを終了させる
  9685. }
  9686. }
  9687. }
  9688. if(flag&2 && group && src->type==BL_PC){ //ハエで飛んだときとかはユニットも飛ぶ
  9689. struct map_session_data *sd = (struct map_session_data *)src;
  9690. skill_unit_move_unit_group(group, sd->bl.m,(sd->to_x - sd->bl.x),(sd->to_y - sd->bl.y));
  9691. return;
  9692. }
  9693. skill_delunitgroup(group);
  9694. if(src->type==BL_PC)
  9695. pc_calcstatus((struct map_session_data *)src,0);
  9696. }
  9697. }
  9698. /*==========================================
  9699. * スキルユニット初期化
  9700. *------------------------------------------
  9701. */
  9702. struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,int y)
  9703. {
  9704. struct skill_unit *unit;
  9705. nullpo_retr(NULL, group);
  9706. nullpo_retr(NULL, unit=&group->unit[idx]);
  9707. if(!unit->alive)
  9708. group->alive_count++;
  9709. unit->bl.id=map_addobject(&unit->bl);
  9710. unit->bl.type=BL_SKILL;
  9711. unit->bl.m=group->map;
  9712. unit->bl.x=x;
  9713. unit->bl.y=y;
  9714. unit->group=group;
  9715. unit->val1=unit->val2=0;
  9716. unit->alive=1;
  9717. map_addblock(&unit->bl);
  9718. clif_skill_setunit(unit);
  9719. return unit;
  9720. }
  9721. int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
  9722. /*==========================================
  9723. * スキルユニット削除
  9724. *------------------------------------------
  9725. */
  9726. int skill_delunit(struct skill_unit *unit)
  9727. {
  9728. struct skill_unit_group *group;
  9729. int range;
  9730. nullpo_retr(0, unit);
  9731. if(!unit->alive)
  9732. return 0;
  9733. nullpo_retr(0, group=unit->group);
  9734. /* onlimitイベント呼び出し */
  9735. skill_unit_onlimit( unit,gettick() );
  9736. /* ondeleteイベント呼び出し */
  9737. range=group->range;
  9738. map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m,
  9739. unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
  9740. &unit->bl,gettick() );
  9741. clif_skill_delunit(unit);
  9742. unit->group=NULL;
  9743. unit->alive=0;
  9744. map_delobjectnofree(unit->bl.id);
  9745. if(group->alive_count>0 && (--group->alive_count)<=0)
  9746. skill_delunitgroup(group);
  9747. return 0;
  9748. }
  9749. /*==========================================
  9750. * スキルユニットグル?プ初期化
  9751. *------------------------------------------
  9752. */
  9753. static int skill_unit_group_newid=10;
  9754. struct skill_unit_group *skill_initunitgroup(struct block_list *src,
  9755. int count,int skillid,int skilllv,int unit_id)
  9756. {
  9757. int i;
  9758. struct skill_unit_group *group=NULL, *list=NULL;
  9759. int maxsug=0;
  9760. if(skilllv <= 0) return 0;
  9761. nullpo_retr(NULL, src);
  9762. if(src->type==BL_PC){
  9763. list=((struct map_session_data *)src)->skillunit;
  9764. maxsug=MAX_SKILLUNITGROUP;
  9765. }else if(src->type==BL_MOB){
  9766. list=((struct mob_data *)src)->skillunit;
  9767. maxsug=MAX_MOBSKILLUNITGROUP;
  9768. }else if(src->type==BL_PET){
  9769. list=((struct pet_data *)src)->skillunit;
  9770. maxsug=MAX_MOBSKILLUNITGROUP;
  9771. }
  9772. if(list){
  9773. for(i=0;i<maxsug;i++) /* 空いているもの?索 */
  9774. if(list[i].group_id==0){
  9775. group=&list[i];
  9776. break;
  9777. }
  9778. if(group==NULL){ /* 空いてないので古いもの?索 */
  9779. int j=0;
  9780. unsigned maxdiff=0,x,tick=gettick();
  9781. for(i=0;i<maxsug;i++)
  9782. if((x=DIFF_TICK(tick,list[i].tick))>maxdiff){
  9783. maxdiff=x;
  9784. j=i;
  9785. }
  9786. skill_delunitgroup(&list[j]);
  9787. group=&list[j];
  9788. }
  9789. }
  9790. if(group==NULL){
  9791. printf("skill_initunitgroup: error unit group !\n");
  9792. exit(1);
  9793. }
  9794. group->src_id=src->id;
  9795. group->party_id=battle_get_party_id(src);
  9796. group->guild_id=battle_get_guild_id(src);
  9797. group->group_id=skill_unit_group_newid++;
  9798. if(skill_unit_group_newid<=0)
  9799. skill_unit_group_newid=10;
  9800. group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
  9801. group->unit_count=count;
  9802. group->val1=group->val2=0;
  9803. group->skill_id=skillid;
  9804. group->skill_lv=skilllv;
  9805. group->unit_id=unit_id;
  9806. group->map=src->m;
  9807. group->range=0;
  9808. group->limit=10000;
  9809. group->interval=1000;
  9810. group->tick=gettick();
  9811. group->valstr=NULL;
  9812. if( skill_is_danceskill(skillid) ){
  9813. struct map_session_data *sd = NULL;
  9814. if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){
  9815. sd->skillid_dance=skillid;
  9816. sd->skilllv_dance=skilllv;
  9817. }
  9818. skill_status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
  9819. switch(skillid){ //合奏スキルは相方をダンス?態にする
  9820. case BD_LULLABY: /* 子守歌 */
  9821. case BD_RICHMANKIM: /* ニヨルドの宴 */
  9822. case BD_ETERNALCHAOS: /* 永遠の混沌 */
  9823. case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
  9824. case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
  9825. case BD_ROKISWEIL: /* ロキの叫び */
  9826. case BD_INTOABYSS: /* 深淵の中に */
  9827. case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
  9828. case BD_RAGNAROK: /* 神?の?昏 */
  9829. case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
  9830. {
  9831. int range=1;
  9832. int c=0;
  9833. if(sd){
  9834. map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
  9835. sd->bl.x-range,sd->bl.y-range,
  9836. sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
  9837. }
  9838. }
  9839. }
  9840. }
  9841. return group;
  9842. }
  9843. /*==========================================
  9844. * スキルユニットグル?プ削除
  9845. *------------------------------------------
  9846. */
  9847. int skill_delunitgroup(struct skill_unit_group *group)
  9848. {
  9849. struct block_list *src;
  9850. int i;
  9851. nullpo_retr(0, group);
  9852. if(group->unit_count<=0)
  9853. return 0;
  9854. src=map_id2bl(group->src_id);
  9855. if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス?態を解除する
  9856. if(src)
  9857. skill_status_change_end(src,SC_DANCING,-1);
  9858. }
  9859. group->alive_count=0;
  9860. if(group->unit!=NULL){
  9861. for(i=0;i<group->unit_count;i++)
  9862. if(group->unit[i].alive)
  9863. skill_delunit(&group->unit[i]);
  9864. }
  9865. if(group->valstr!=NULL){
  9866. map_freeblock(group->valstr);
  9867. group->valstr=NULL;
  9868. }
  9869. map_freeblock(group->unit); /* free()の替わり */
  9870. group->unit=NULL;
  9871. group->src_id=0;
  9872. group->group_id=0;
  9873. group->unit_count=0;
  9874. return 0;
  9875. }
  9876. /*==========================================
  9877. * スキルユニットグル?プ全削除
  9878. *------------------------------------------
  9879. */
  9880. int skill_clear_unitgroup(struct block_list *src)
  9881. {
  9882. struct skill_unit_group *group=NULL;
  9883. int maxsug=0;
  9884. nullpo_retr(0, src);
  9885. if(src->type==BL_PC){
  9886. group=((struct map_session_data *)src)->skillunit;
  9887. maxsug=MAX_SKILLUNITGROUP;
  9888. }else if(src->type==BL_MOB){
  9889. group=((struct mob_data *)src)->skillunit;
  9890. maxsug=MAX_MOBSKILLUNITGROUP;
  9891. }else if(src->type==BL_PET){ // [Valaris]
  9892. group=((struct pet_data *)src)->skillunit;
  9893. maxsug=MAX_MOBSKILLUNITGROUP;
  9894. }
  9895. if(group){
  9896. int i;
  9897. for(i=0;i<maxsug;i++)
  9898. if(group[i].group_id>0 && group[i].src_id == src->id)
  9899. skill_delunitgroup(&group[i]);
  9900. }
  9901. return 0;
  9902. }
  9903. /*==========================================
  9904. * スキルユニットグル?プの被影響tick?索
  9905. *------------------------------------------
  9906. */
  9907. struct skill_unit_group_tickset *skill_unitgrouptickset_search(
  9908. struct block_list *bl,int group_id)
  9909. {
  9910. int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET;
  9911. struct skill_unit_group_tickset *set=NULL;
  9912. nullpo_retr(0, bl);
  9913. if(bl->type==BL_PC){
  9914. set=((struct map_session_data *)bl)->skillunittick;
  9915. }else{
  9916. set=((struct mob_data *)bl)->skillunittick;
  9917. }
  9918. if(set==NULL)
  9919. return 0;
  9920. for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
  9921. if( set[(k=(i+s)%MAX_SKILLUNITGROUPTICKSET)].group_id == group_id )
  9922. return &set[k];
  9923. else if( set[k].group_id==0 )
  9924. j=k;
  9925. return &set[j];
  9926. }
  9927. /*==========================================
  9928. * スキルユニットグル?プの被影響tick削除
  9929. *------------------------------------------
  9930. */
  9931. int skill_unitgrouptickset_delete(struct block_list *bl,int group_id)
  9932. {
  9933. int i,s=group_id%MAX_SKILLUNITGROUPTICKSET;
  9934. struct skill_unit_group_tickset *set=NULL,*ts;
  9935. nullpo_retr(0, bl);
  9936. if(bl->type==BL_PC){
  9937. set=((struct map_session_data *)bl)->skillunittick;
  9938. }else{
  9939. set=((struct mob_data *)bl)->skillunittick;
  9940. }
  9941. if(set!=NULL){
  9942. for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
  9943. if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id )
  9944. ts->group_id=0;
  9945. }
  9946. return 0;
  9947. }
  9948. /*==========================================
  9949. * スキルユニットタイマ??動?理用(foreachinarea)
  9950. *------------------------------------------
  9951. */
  9952. int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap )
  9953. {
  9954. struct block_list *src;
  9955. struct skill_unit *su;
  9956. unsigned int tick;
  9957. nullpo_retr(0, bl);
  9958. nullpo_retr(0, ap);
  9959. src=va_arg(ap,struct block_list*);
  9960. tick=va_arg(ap,unsigned int);
  9961. su = (struct skill_unit *)src;
  9962. if( su && su->alive ) {
  9963. struct skill_unit_group *sg;
  9964. sg = su->group;
  9965. if(sg && battle_check_target(src,bl,sg->target_flag )>0)
  9966. skill_unit_onplace( su, bl, tick );
  9967. }
  9968. return 0;
  9969. }
  9970. /*==========================================
  9971. * スキルユニットタイマ?削除?理用(foreachinarea)
  9972. *------------------------------------------
  9973. */
  9974. int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap )
  9975. {
  9976. struct block_list *src;
  9977. struct skill_unit *su;
  9978. unsigned int tick;
  9979. nullpo_retr(0, bl);
  9980. nullpo_retr(0, ap);
  9981. src=va_arg(ap,struct block_list*);
  9982. tick=va_arg(ap,unsigned int);
  9983. su = (struct skill_unit *)src;
  9984. if( su && su->alive ){
  9985. struct skill_unit_group *sg;
  9986. sg = su->group;
  9987. if( sg && battle_check_target(src,bl,sg->target_flag )>0 )
  9988. skill_unit_ondelete( su, bl, tick );
  9989. }
  9990. return 0;
  9991. }
  9992. /*==========================================
  9993. * スキルユニットタイマ??理用(foreachobject)
  9994. *------------------------------------------
  9995. */
  9996. int skill_unit_timer_sub( struct block_list *bl, va_list ap )
  9997. {
  9998. struct skill_unit *unit;
  9999. struct skill_unit_group *group;
  10000. int range;
  10001. unsigned int tick;
  10002. nullpo_retr(0, bl);
  10003. nullpo_retr(0, ap);
  10004. nullpo_retr(0, unit=(struct skill_unit *)bl);
  10005. nullpo_retr(0, group=unit->group);
  10006. tick=va_arg(ap,unsigned int);
  10007. if(!unit->alive)
  10008. return 0;
  10009. range=(unit->range!=0)?unit->range:group->range;
  10010. /* onplaceイベント呼び出し */
  10011. if(unit->alive && unit->range>=0){
  10012. map_foreachinarea( skill_unit_timer_sub_onplace, bl->m,
  10013. bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,
  10014. bl,tick);
  10015. if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){
  10016. map_foreachinarea( skill_idun_heal, bl->m,
  10017. bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit);
  10018. group->val2++;
  10019. }
  10020. }
  10021. /* 時間切れ削除 */
  10022. if(unit->alive &&
  10023. (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){
  10024. switch(group->unit_id){
  10025. case 0x8f: /* ブラストマイン */
  10026. group->unit_id = 0x8c;
  10027. clif_changelook(bl,LOOK_BASE,group->unit_id);
  10028. group->limit=DIFF_TICK(tick+1500,group->tick);
  10029. unit->limit=DIFF_TICK(tick+1500,group->tick);
  10030. break;
  10031. case 0x90: /* スキッドトラップ */
  10032. case 0x91: /* アンクルスネア */
  10033. case 0x93: /* ランドマイン */
  10034. case 0x94: /* ショックウェ?ブトラップ */
  10035. case 0x95: /* サンドマン */
  10036. case 0x96: /* フラッシャ? */
  10037. case 0x97: /* フリ?ジングトラップ */
  10038. case 0x98: /* クレイモア?トラップ */
  10039. case 0x99: /* ト?キ?ボックス */
  10040. {
  10041. struct block_list *src=map_id2bl(group->src_id);
  10042. if(group->unit_id == 0x91 && group->val2);
  10043. else{
  10044. if(src && src->type==BL_PC){
  10045. struct item item_tmp;
  10046. memset(&item_tmp,0,sizeof(item_tmp));
  10047. item_tmp.nameid=1065;
  10048. item_tmp.identify=1;
  10049. map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // ?返還
  10050. }
  10051. }
  10052. skill_delunit(unit);
  10053. }
  10054. break;
  10055. case 0xc1:
  10056. case 0xc2:
  10057. case 0xc3:
  10058. case 0xc4:
  10059. {
  10060. struct block_list *src=map_id2bl(group->src_id);
  10061. if (src)
  10062. group->tick = tick;
  10063. }
  10064. break;
  10065. default:
  10066. skill_delunit(unit);
  10067. }
  10068. }
  10069. if(group->unit_id == 0x8d) {
  10070. unit->val1 -= 5;
  10071. if(unit->val1 <= 0 && unit->limit + group->tick > tick + 700)
  10072. unit->limit = DIFF_TICK(tick+700,group->tick);
  10073. }
  10074. return 0;
  10075. }
  10076. /*==========================================
  10077. * スキルユニットタイマ??理
  10078. *------------------------------------------
  10079. */
  10080. int skill_unit_timer( int tid,unsigned int tick,int id,int data)
  10081. {
  10082. map_freeblock_lock();
  10083. map_foreachobject( skill_unit_timer_sub, BL_SKILL, tick );
  10084. map_freeblock_unlock();
  10085. return 0;
  10086. }
  10087. /*==========================================
  10088. * スキルユニット移動時?理用(foreachinarea)
  10089. *------------------------------------------
  10090. */
  10091. int skill_unit_out_all_sub( struct block_list *bl, va_list ap )
  10092. {
  10093. struct skill_unit *unit;
  10094. struct skill_unit_group *group;
  10095. struct block_list *src;
  10096. int range;
  10097. unsigned int tick;
  10098. nullpo_retr(0, bl);
  10099. nullpo_retr(0, ap);
  10100. nullpo_retr(0, src=va_arg(ap,struct block_list*));
  10101. nullpo_retr(0, unit=(struct skill_unit *)bl);
  10102. nullpo_retr(0, group=unit->group);
  10103. tick=va_arg(ap,unsigned int);
  10104. if(!unit->alive || src->prev==NULL)
  10105. return 0;
  10106. range=(unit->range!=0)?unit->range:group->range;
  10107. if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
  10108. return 0;
  10109. if( src->x >= bl->x-range && src->x <= bl->x+range &&
  10110. src->y >= bl->y-range && src->y <= bl->y+range )
  10111. skill_unit_onout( unit, src, tick );
  10112. return 0;
  10113. }
  10114. /*==========================================
  10115. * スキルユニット移動時?理
  10116. *------------------------------------------
  10117. */
  10118. int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range)
  10119. {
  10120. nullpo_retr(0, bl);
  10121. if( bl->prev==NULL )
  10122. return 0;
  10123. if(range<7)
  10124. range=7;
  10125. map_foreachinarea( skill_unit_out_all_sub,
  10126. bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
  10127. bl,tick );
  10128. return 0;
  10129. }
  10130. /*==========================================
  10131. * スキルユニット移動時?理用(foreachinarea)
  10132. *------------------------------------------
  10133. */
  10134. int skill_unit_move_sub( struct block_list *bl, va_list ap )
  10135. {
  10136. struct skill_unit *unit;
  10137. struct skill_unit_group *group;
  10138. struct block_list *src;
  10139. int range;
  10140. unsigned int tick;
  10141. nullpo_retr(0, bl);
  10142. nullpo_retr(0, ap);
  10143. nullpo_retr(0, unit=(struct skill_unit *)bl);
  10144. nullpo_retr(0, src=va_arg(ap,struct block_list*));
  10145. tick=va_arg(ap,unsigned int);
  10146. if(!unit->alive || src->prev==NULL)
  10147. return 0;
  10148. if((group=unit->group) == NULL)
  10149. return 0;
  10150. range=(unit->range!=0)?unit->range:group->range;
  10151. if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
  10152. return 0;
  10153. if( src->x >= bl->x-range && src->x <= bl->x+range &&
  10154. src->y >= bl->y-range && src->y <= bl->y+range )
  10155. skill_unit_onplace( unit, src, tick );
  10156. else
  10157. skill_unit_onout( unit, src, tick );
  10158. return 0;
  10159. }
  10160. /*==========================================
  10161. * スキルユニット移動時?理
  10162. *------------------------------------------
  10163. */
  10164. int skill_unit_move( struct block_list *bl,unsigned int tick,int range)
  10165. {
  10166. nullpo_retr(0, bl);
  10167. if( bl->prev==NULL )
  10168. return 0;
  10169. if(range<7)
  10170. range=7;
  10171. map_foreachinarea( skill_unit_move_sub,
  10172. bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
  10173. bl,tick );
  10174. return 0;
  10175. }
  10176. /*==========================================
  10177. * スキルユニット自?の移動時?理(foreachinarea)
  10178. *------------------------------------------
  10179. */
  10180. int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap )
  10181. {
  10182. struct skill_unit *unit;
  10183. struct skill_unit_group *group;
  10184. struct block_list *src;
  10185. int range;
  10186. unsigned int tick;
  10187. nullpo_retr(0, bl);
  10188. nullpo_retr(0, ap);
  10189. nullpo_retr(0, src=va_arg(ap,struct block_list*));
  10190. nullpo_retr(0, unit=(struct skill_unit *)src);
  10191. nullpo_retr(0, group=unit->group);
  10192. tick=va_arg(ap,unsigned int);
  10193. if(!unit->alive || bl->prev==NULL)
  10194. return 0;
  10195. range=(unit->range!=0)?unit->range:group->range;
  10196. if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 )
  10197. return 0;
  10198. if( bl->x >= src->x-range && bl->x <= src->x+range &&
  10199. bl->y >= src->y-range && bl->y <= src->y+range )
  10200. skill_unit_onplace( unit, bl, tick );
  10201. else
  10202. skill_unit_onout( unit, bl, tick );
  10203. return 0;
  10204. }
  10205. /*==========================================
  10206. * スキルユニット自?の移動時?理
  10207. * 引?はグル?プと移動量
  10208. *------------------------------------------
  10209. */
  10210. int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy)
  10211. {
  10212. nullpo_retr(0, group);
  10213. if( group->unit_count<=0)
  10214. return 0;
  10215. if(group->unit!=NULL){
  10216. if(!battle_config.unit_movement_type){
  10217. int i;
  10218. for(i=0;i<group->unit_count;i++){
  10219. struct skill_unit *unit=&group->unit[i];
  10220. if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){
  10221. int range=unit->range;
  10222. map_delblock(&unit->bl);
  10223. unit->bl.m = m;
  10224. unit->bl.x += dx;
  10225. unit->bl.y += dy;
  10226. map_addblock(&unit->bl);
  10227. clif_skill_setunit(unit);
  10228. if(range>0){
  10229. if(range<7)
  10230. range=7;
  10231. map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m,
  10232. unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
  10233. &unit->bl,gettick() );
  10234. }
  10235. }
  10236. }
  10237. }else{
  10238. int i,j, *r_flag, *s_flag, *m_flag;
  10239. struct skill_unit *unit1;
  10240. struct skill_unit *unit2;
  10241. r_flag = (int *) malloc(sizeof(int) * group->unit_count);
  10242. s_flag = (int *) malloc(sizeof(int) * group->unit_count);
  10243. m_flag = (int *) malloc(sizeof(int) * group->unit_count);
  10244. memset(r_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
  10245. memset(s_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
  10246. memset(m_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
  10247. //先にフラグを全部決める
  10248. for(i=0;i<group->unit_count;i++){
  10249. int move_check=0;// かぶりフラグ
  10250. unit1=&group->unit[i];
  10251. for(j=0;j<group->unit_count;j++){
  10252. unit2=&group->unit[j];
  10253. if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
  10254. //移動先にユニットがかぶってたら
  10255. s_flag[i]=1;// 移動前のユニットナンバ?の?承フラグon
  10256. r_flag[j]=1;// かぶるユニットナンバ?の?留フラグon
  10257. move_check=1;//ユニットがかぶった。
  10258. break;
  10259. }
  10260. }
  10261. if(!move_check)// ユニットがかぶってなかったら
  10262. m_flag[i]=1;// 移動前ユニットナンバ?の移動フラグon
  10263. }
  10264. //フラグに基づいてユニット移動
  10265. for(i=0;i<group->unit_count;i++){
  10266. unit1=&group->unit[i];
  10267. if(m_flag[i]){// 移動フラグがonで
  10268. if(!r_flag[i]){// ?留フラグがoffなら
  10269. //?純移動(rangeも?承の必要無し)
  10270. int range=unit1->range;
  10271. map_delblock(&unit1->bl);
  10272. unit1->bl.m = m;
  10273. unit1->bl.x += dx;
  10274. unit1->bl.y += dy;
  10275. map_addblock(&unit1->bl);
  10276. clif_skill_setunit(unit1);
  10277. if(range > 0){
  10278. if(range < 7)
  10279. range = 7;
  10280. map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m,
  10281. unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0,
  10282. &unit1->bl,gettick() );
  10283. }
  10284. }else{// ?留フラグがonなら
  10285. //空ユニットになるので、?承可能なユニットを探す
  10286. for(j=0;j<group->unit_count;j++){
  10287. unit2=&group->unit[j];
  10288. if(s_flag[j] && !r_flag[j]){
  10289. // ?承移動(range?承付き)
  10290. int range=unit1->range;
  10291. map_delblock(&unit2->bl);
  10292. unit2->bl.m = m;
  10293. unit2->bl.x = unit1->bl.x + dx;
  10294. unit2->bl.y = unit1->bl.y + dy;
  10295. unit2->range = unit1->range;
  10296. map_addblock(&unit2->bl);
  10297. clif_skill_setunit(unit2);
  10298. if(range > 0){
  10299. if(range < 7)
  10300. range = 7;
  10301. map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m,
  10302. unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0,
  10303. &unit2->bl,gettick() );
  10304. }
  10305. s_flag[j]=0;// ?承完了したのでoff
  10306. break;
  10307. }
  10308. }
  10309. }
  10310. }
  10311. }
  10312. free(r_flag);
  10313. free(s_flag);
  10314. free(m_flag);
  10315. }
  10316. }
  10317. return 0;
  10318. }
  10319. /*----------------------------------------------------------------------------
  10320. * アイテム合成
  10321. *----------------------------------------------------------------------------
  10322. */
  10323. /*==========================================
  10324. * アイテム合成可能判定
  10325. *------------------------------------------
  10326. */
  10327. int skill_can_produce_mix( struct map_session_data *sd, int nameid, int trigger )
  10328. {
  10329. int i,j;
  10330. nullpo_retr(0, sd);
  10331. if(nameid<=0)
  10332. return 0;
  10333. for(i=0;i<MAX_SKILL_PRODUCE_DB;i++){
  10334. if(skill_produce_db[i].nameid == nameid )
  10335. break;
  10336. }
  10337. if( i >= MAX_SKILL_PRODUCE_DB ) /* デ?タベ?スにない */
  10338. return 0;
  10339. if(trigger>=0){
  10340. if(trigger == 32 || trigger == 16 || trigger==64 || trigger == 256) {
  10341. if(skill_produce_db[i].itemlv!=trigger) /* ファ?マシ?*ポ?ション類と溶??*?石以外はだめ */
  10342. return 0;
  10343. }else{
  10344. if(skill_produce_db[i].itemlv>=16) /* 武器以外はだめ */
  10345. return 0;
  10346. if( itemdb_wlv(nameid)>trigger ) /* 武器Lv判定 */
  10347. return 0;
  10348. }
  10349. }
  10350. if( (j=skill_produce_db[i].req_skill)>0 && pc_checkskill(sd,j)<=0 )
  10351. return 0; /* スキルが足りない */
  10352. for(j=0;j<MAX_PRODUCE_RESOURCE;j++){
  10353. int id,x,y;
  10354. if( (id=skill_produce_db[i].mat_id[j]) <= 0 ) /* これ以上は材料要らない */
  10355. continue;
  10356. if(skill_produce_db[i].mat_amount[j] <= 0) {
  10357. if(pc_search_inventory(sd,id) < 0)
  10358. return 0;
  10359. }
  10360. else {
  10361. for(y=0,x=0;y<MAX_INVENTORY;y++)
  10362. if( sd->status.inventory[y].nameid == id )
  10363. x+=sd->status.inventory[y].amount;
  10364. if(x<skill_produce_db[i].mat_amount[j]) /* アイテムが足りない */
  10365. return 0;
  10366. }
  10367. }
  10368. return i+1;
  10369. }
  10370. /*==========================================
  10371. * アイテム合成可能判定
  10372. *------------------------------------------
  10373. */
  10374. int skill_produce_mix( struct map_session_data *sd,
  10375. int nameid, int slot1, int slot2, int slot3 )
  10376. {
  10377. int slot[3];
  10378. int i,sc,ele,idx,equip,wlv,make_per,flag;
  10379. nullpo_retr(0, sd);
  10380. if( !(idx=skill_can_produce_mix(sd,nameid,-1)) ) /* ?件不足 */
  10381. return 0;
  10382. idx--;
  10383. slot[0]=slot1;
  10384. slot[1]=slot2;
  10385. slot[2]=slot3;
  10386. /* 埋め?み?理 */
  10387. for(i=0,sc=0,ele=0;i<3;i++){
  10388. int j;
  10389. if( slot[i]<=0 )
  10390. continue;
  10391. j = pc_search_inventory(sd,slot[i]);
  10392. if(j < 0) /* 不正パケット(アイテム存在)チェック */
  10393. continue;
  10394. if(slot[i]==1000){ /* 星のかけら */
  10395. pc_delitem(sd,j,1,1);
  10396. sc++;
  10397. }
  10398. if(slot[i]>=994 && slot[i]<=997 && ele==0){ /* ?性石 */
  10399. static const int ele_table[4]={3,1,4,2};
  10400. pc_delitem(sd,j,1,1);
  10401. ele=ele_table[slot[i]-994];
  10402. }
  10403. }
  10404. /* 材料消費 */
  10405. for(i=0;i<MAX_PRODUCE_RESOURCE;i++){
  10406. int j,id,x;
  10407. if( (id=skill_produce_db[idx].mat_id[i]) <= 0 )
  10408. continue;
  10409. x=skill_produce_db[idx].mat_amount[i]; /* 必要な個? */
  10410. do{ /* 2つ以上のインデックスにまたがっているかもしれない */
  10411. int y=0;
  10412. j = pc_search_inventory(sd,id);
  10413. if(j >= 0){
  10414. y = sd->status.inventory[j].amount;
  10415. if(y>x)y=x; /* 足りている */
  10416. pc_delitem(sd,j,y,0);
  10417. }else {
  10418. if(battle_config.error_log)
  10419. printf("skill_produce_mix: material item error\n");
  10420. }
  10421. x-=y; /* まだ足りない個?を計算 */
  10422. }while( j>=0 && x>0 ); /* 材料を消費するか、エラ?になるまで繰り返す */
  10423. }
  10424. /* 確率判定 */
  10425. equip = itemdb_isequip(nameid);
  10426. if(!equip) {
  10427. if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
  10428. if((nameid >= 501 && nameid <= 506) || (nameid >= 545 && nameid <= 547) || nameid == 525)
  10429. make_per = 2000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
  10430. else if(nameid == 970)
  10431. make_per = 1500 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
  10432. else if(nameid == 7135)
  10433. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
  10434. else if(nameid == 7136)
  10435. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100;
  10436. else if(nameid == 7137)
  10437. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
  10438. else if(nameid == 7138)
  10439. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100;
  10440. else if(nameid == 7139)
  10441. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 +
  10442. pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
  10443. else
  10444. make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
  10445. } else if (skill_produce_db[idx].req_skill == ASC_CDP) {
  10446. make_per = 2000 + 40*sd->paramc[4] + 20*sd->paramc[5];
  10447. //make_per = 20 + (20*sd->paramc[4])/50 + (20*sd->paramc[5])/100;
  10448. } else {
  10449. if(nameid == 998)
  10450. make_per = 2000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
  10451. else if(nameid == 985)
  10452. make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + (pc_checkskill(sd,skill_produce_db[idx].req_skill)-1)*500;
  10453. else
  10454. make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
  10455. }
  10456. }
  10457. else {
  10458. int add_per;
  10459. if(pc_search_inventory(sd,989) >= 0) add_per = 750;
  10460. else if(pc_search_inventory(sd,988) >= 0) add_per = 500;
  10461. else if(pc_search_inventory(sd,987) >= 0) add_per = 250;
  10462. else if(pc_search_inventory(sd,986) >= 0) add_per = 0;
  10463. else add_per = -500;
  10464. if(ele) add_per -= 500;
  10465. add_per -= sc*500;
  10466. wlv = itemdb_wlv(nameid);
  10467. make_per = ((250 + sd->status.base_level*15 + sd->paramc[4]*10 + sd->paramc[5]*5 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500 +
  10468. add_per) * (100 - (wlv - 1)*20))/100 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0);
  10469. }
  10470. if(make_per < 1) make_per = 1;
  10471. if(skill_produce_db[idx].req_skill==AM_PHARMACY ||
  10472. skill_produce_db[idx].req_skill==ASC_CDP) {
  10473. if( battle_config.pp_rate!=100 )
  10474. make_per=make_per*battle_config.pp_rate/100;
  10475. }
  10476. else {
  10477. if( battle_config.wp_rate!=100 ) /* 確率補正 */
  10478. make_per=make_per*battle_config.wp_rate/100;
  10479. }
  10480. // if(battle_config.etc_log)
  10481. // printf("make rate = %d\n",make_per);
  10482. if(rand()%10000 < make_per){
  10483. /* 成功 */
  10484. struct item tmp_item;
  10485. memset(&tmp_item,0,sizeof(tmp_item));
  10486. tmp_item.nameid=nameid;
  10487. tmp_item.amount=1;
  10488. tmp_item.identify=1;
  10489. if(equip){ /* 武器の場合 */
  10490. tmp_item.card[0]=0x00ff; /* 製造武器フラグ */
  10491. tmp_item.card[1]=((sc*5)<<8)+ele; /* ?性とつよさ */
  10492. *((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* キャラID */
  10493. }
  10494. else if((battle_config.produce_item_name_input && skill_produce_db[idx].req_skill!=AM_PHARMACY) ||
  10495. (battle_config.produce_potion_name_input && skill_produce_db[idx].req_skill==AM_PHARMACY)) {
  10496. tmp_item.card[0]=0x00fe;
  10497. tmp_item.card[1]=0;
  10498. *((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* キャラID */
  10499. }
  10500. #ifndef TXT_ONLY
  10501. if(log_config.produce > 0)
  10502. log_produce(sd,nameid,slot1,slot2,slot3,1);
  10503. #endif //USE_SQL
  10504. switch (skill_produce_db[idx].req_skill) {
  10505. case AM_PHARMACY:
  10506. clif_produceeffect(sd,2,nameid);/* 製?エフェクト */
  10507. clif_misceffect(&sd->bl,5); /* 他人にも成功を通知 */
  10508. break;
  10509. case ASC_CDP:
  10510. clif_produceeffect(sd,2,nameid);/* 暫定で製?エフェクト */
  10511. clif_misceffect(&sd->bl,5);
  10512. break;
  10513. default: /* 武器製造、コイン製造 */
  10514. clif_produceeffect(sd,0,nameid); /* 武器製造エフェクト */
  10515. clif_misceffect(&sd->bl,3);
  10516. break;
  10517. }
  10518. if((flag = pc_additem(sd,&tmp_item,1))) {
  10519. clif_additem(sd,0,0,flag);
  10520. map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  10521. }
  10522. }
  10523. else {
  10524. #ifndef TXT_ONLY
  10525. if(log_config.produce > 0)
  10526. log_produce(sd,nameid,slot1,slot2,slot3,0);
  10527. #endif //USE_SQL
  10528. switch (skill_produce_db[idx].req_skill) {
  10529. case AM_PHARMACY:
  10530. clif_produceeffect(sd,3,nameid);/* 製?失敗エフェクト */
  10531. clif_misceffect(&sd->bl,6); /* 他人にも失敗を通知 */
  10532. break;
  10533. case ASC_CDP:
  10534. {
  10535. clif_produceeffect(sd,3,nameid); /* 暫定で製?エフェクト */
  10536. clif_misceffect(&sd->bl,6); /* 他人にも失敗を通知 */
  10537. pc_heal(sd, -(sd->status.max_hp>>2), 0);
  10538. }
  10539. break;
  10540. default:
  10541. clif_produceeffect(sd,1,nameid);/* 武器製造失敗エフェクト */
  10542. clif_misceffect(&sd->bl,2); /* 他人にも失敗を通知 */
  10543. break;
  10544. }
  10545. }
  10546. return 0;
  10547. }
  10548. int skill_arrow_create( struct map_session_data *sd,int nameid)
  10549. {
  10550. int i,j,flag,index=-1;
  10551. struct item tmp_item;
  10552. nullpo_retr(0, sd);
  10553. if(nameid <= 0)
  10554. return 1;
  10555. for(i=0;i<MAX_SKILL_ARROW_DB;i++)
  10556. if(nameid == skill_arrow_db[i].nameid) {
  10557. index = i;
  10558. break;
  10559. }
  10560. if(index < 0 || (j = pc_search_inventory(sd,nameid)) < 0)
  10561. return 1;
  10562. pc_delitem(sd,j,1,0);
  10563. for(i=0;i<5;i++) {
  10564. memset(&tmp_item,0,sizeof(tmp_item));
  10565. tmp_item.identify = 1;
  10566. tmp_item.nameid = skill_arrow_db[index].cre_id[i];
  10567. tmp_item.amount = skill_arrow_db[index].cre_amount[i];
  10568. if(battle_config.making_arrow_name_input) {
  10569. tmp_item.card[0]=0x00fe;
  10570. tmp_item.card[1]=0;
  10571. *((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* キャラID */
  10572. }
  10573. if(tmp_item.nameid <= 0 || tmp_item.amount <= 0)
  10574. continue;
  10575. if((flag = pc_additem(sd,&tmp_item,tmp_item.amount))) {
  10576. clif_additem(sd,0,0,flag);
  10577. map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
  10578. }
  10579. }
  10580. return 0;
  10581. }
  10582. /*----------------------------------------------------------------------------
  10583. * 初期化系
  10584. */
  10585. /*==========================================
  10586. * スキル?係ファイル?み?み
  10587. * skill_db.txt スキルデ?タ
  10588. * skill_cast_db.txt スキルの詠唱時間とディレイデ?タ
  10589. * produce_db.txt アイテム作成スキル用デ?タ
  10590. * create_arrow_db.txt 矢作成スキル用デ?タ
  10591. * abra_db.txt アブラカダブラ?動スキルデ?タ
  10592. *------------------------------------------
  10593. */
  10594. int skill_readdb(void)
  10595. {
  10596. int i,j,k,l,m;
  10597. FILE *fp;
  10598. char line[1024],*p;
  10599. char *filename[]={"db/produce_db.txt","db/produce_db2.txt"};
  10600. /* スキルデ?タベ?ス */
  10601. memset(skill_db,0,sizeof(skill_db));
  10602. fp=fopen("db/skill_db.txt","r");
  10603. if(fp==NULL){
  10604. printf("can't read db/skill_db.txt\n");
  10605. return 1;
  10606. }
  10607. while(fgets(line,1020,fp)){
  10608. char *split[50], *split2[MAX_SKILL_LEVEL];
  10609. if(line[0]=='/' && line[1]=='/')
  10610. continue;
  10611. for(j=0,p=line;j<14 && p;j++){
  10612. split[j]=p;
  10613. p=strchr(p,',');
  10614. if(p) *p++=0;
  10615. }
  10616. if(split[13]==NULL || j<14)
  10617. continue;
  10618. i=atoi(split[0]);
  10619. if (i>=10000 && i<10015) // for guild skills [Celest]
  10620. i -= 9500;
  10621. else if(i<0 || i>MAX_SKILL_DB)
  10622. continue;
  10623. /* printf("skill id=%d\n",i); */
  10624. memset(split2,0,sizeof(split2));
  10625. for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
  10626. split2[j]=p;
  10627. p=strchr(p,':');
  10628. if(p) *p++=0;
  10629. }
  10630. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10631. skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10632. skill_db[i].hit=atoi(split[2]);
  10633. skill_db[i].inf=atoi(split[3]);
  10634. skill_db[i].pl=atoi(split[4]);
  10635. skill_db[i].nk=atoi(split[5]);
  10636. skill_db[i].max=atoi(split[6]);
  10637. memset(split2,0,sizeof(split2));
  10638. for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){
  10639. split2[j]=p;
  10640. p=strchr(p,':');
  10641. if(p) *p++=0;
  10642. }
  10643. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10644. skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10645. if(strcmpi(split[8],"yes") == 0)
  10646. skill_db[i].castcancel=1;
  10647. else
  10648. skill_db[i].castcancel=0;
  10649. skill_db[i].cast_def_rate=atoi(split[9]);
  10650. skill_db[i].inf2=atoi(split[10]);
  10651. skill_db[i].maxcount=atoi(split[11]);
  10652. if(strcmpi(split[12],"weapon") == 0)
  10653. skill_db[i].skill_type=BF_WEAPON;
  10654. else if(strcmpi(split[12],"magic") == 0)
  10655. skill_db[i].skill_type=BF_MAGIC;
  10656. else if(strcmpi(split[12],"misc") == 0)
  10657. skill_db[i].skill_type=BF_MISC;
  10658. else
  10659. skill_db[i].skill_type=0;
  10660. memset(split2,0,sizeof(split2));
  10661. for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){
  10662. split2[j]=p;
  10663. p=strchr(p,':');
  10664. if(p) *p++=0;
  10665. }
  10666. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10667. skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10668. }
  10669. fclose(fp);
  10670. sprintf(tmp_output,"Done reading '\033[1;29m%s\033[0;0m'.\n","db/skill_db.txt");
  10671. ShowStatus(tmp_output);
  10672. fp=fopen("db/skill_require_db.txt","r");
  10673. if(fp==NULL){
  10674. printf("can't read db/skill_require_db.txt\n");
  10675. return 1;
  10676. }
  10677. while(fgets(line,1020,fp)){
  10678. char *split[51], *split2[MAX_SKILL_LEVEL];
  10679. if(line[0]=='/' && line[1]=='/')
  10680. continue;
  10681. for(j=0,p=line;j<30 && p;j++){
  10682. split[j]=p;
  10683. p=strchr(p,',');
  10684. if(p) *p++=0;
  10685. }
  10686. if(split[29]==NULL || j<30)
  10687. continue;
  10688. i=atoi(split[0]);
  10689. if (i>=10000 && i<10015) // for guild skills [Celest]
  10690. i -= 9500;
  10691. else if(i<0 || i>MAX_SKILL_DB)
  10692. continue;
  10693. memset(split2,0,sizeof(split2));
  10694. for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
  10695. split2[j]=p;
  10696. p=strchr(p,':');
  10697. if(p) *p++=0;
  10698. }
  10699. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10700. skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10701. memset(split2,0,sizeof(split2));
  10702. for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
  10703. split2[j]=p;
  10704. p=strchr(p,':');
  10705. if(p) *p++=0;
  10706. }
  10707. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10708. skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10709. memset(split2,0,sizeof(split2));
  10710. for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
  10711. split2[j]=p;
  10712. p=strchr(p,':');
  10713. if(p) *p++=0;
  10714. }
  10715. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10716. skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10717. memset(split2,0,sizeof(split2));
  10718. for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
  10719. split2[j]=p;
  10720. p=strchr(p,':');
  10721. if(p) *p++=0;
  10722. }
  10723. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10724. skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10725. memset(split2,0,sizeof(split2));
  10726. for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){
  10727. split2[j]=p;
  10728. p=strchr(p,':');
  10729. if(p) *p++=0;
  10730. }
  10731. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10732. skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10733. memset(split2,0,sizeof(split2));
  10734. for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){
  10735. split2[j]=p;
  10736. p=strchr(p,':');
  10737. if(p) *p++=0;
  10738. }
  10739. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10740. skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10741. memset(split2,0,sizeof(split2));
  10742. for(j=0,p=split[7];j<32 && p;j++){
  10743. split2[j]=p;
  10744. p=strchr(p,':');
  10745. if(p) *p++=0;
  10746. }
  10747. for(k=0;k<32 && split2[k];k++) {
  10748. l = atoi(split2[k]);
  10749. if(l == 99) {
  10750. skill_db[i].weapon = 0xffffffff;
  10751. break;
  10752. }
  10753. else
  10754. skill_db[i].weapon |= 1<<l;
  10755. }
  10756. if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING;
  10757. else if( strcmpi(split[8],"cloaking")==0 ) skill_db[i].state=ST_CLOAKING;
  10758. else if( strcmpi(split[8],"hidden")==0 ) skill_db[i].state=ST_HIDDEN;
  10759. else if( strcmpi(split[8],"riding")==0 ) skill_db[i].state=ST_RIDING;
  10760. else if( strcmpi(split[8],"falcon")==0 ) skill_db[i].state=ST_FALCON;
  10761. else if( strcmpi(split[8],"cart")==0 ) skill_db[i].state=ST_CART;
  10762. else if( strcmpi(split[8],"shield")==0 ) skill_db[i].state=ST_SHIELD;
  10763. else if( strcmpi(split[8],"sight")==0 ) skill_db[i].state=ST_SIGHT;
  10764. else if( strcmpi(split[8],"explosionspirits")==0 ) skill_db[i].state=ST_EXPLOSIONSPIRITS;
  10765. else if( strcmpi(split[8],"recover_weight_rate")==0 ) skill_db[i].state=ST_RECOV_WEIGHT_RATE;
  10766. else if( strcmpi(split[8],"move_enable")==0 ) skill_db[i].state=ST_MOVE_ENABLE;
  10767. else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER;
  10768. else skill_db[i].state=ST_NONE;
  10769. memset(split2,0,sizeof(split2));
  10770. for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){
  10771. split2[j]=p;
  10772. p=strchr(p,':');
  10773. if(p) *p++=0;
  10774. }
  10775. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10776. skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10777. skill_db[i].itemid[0]=atoi(split[10]);
  10778. skill_db[i].amount[0]=atoi(split[11]);
  10779. skill_db[i].itemid[1]=atoi(split[12]);
  10780. skill_db[i].amount[1]=atoi(split[13]);
  10781. skill_db[i].itemid[2]=atoi(split[14]);
  10782. skill_db[i].amount[2]=atoi(split[15]);
  10783. skill_db[i].itemid[3]=atoi(split[16]);
  10784. skill_db[i].amount[3]=atoi(split[17]);
  10785. skill_db[i].itemid[4]=atoi(split[18]);
  10786. skill_db[i].amount[4]=atoi(split[19]);
  10787. skill_db[i].itemid[5]=atoi(split[20]);
  10788. skill_db[i].amount[5]=atoi(split[21]);
  10789. skill_db[i].itemid[6]=atoi(split[22]);
  10790. skill_db[i].amount[6]=atoi(split[23]);
  10791. skill_db[i].itemid[7]=atoi(split[24]);
  10792. skill_db[i].amount[7]=atoi(split[25]);
  10793. skill_db[i].itemid[8]=atoi(split[26]);
  10794. skill_db[i].amount[8]=atoi(split[27]);
  10795. skill_db[i].itemid[9]=atoi(split[28]);
  10796. skill_db[i].amount[9]=atoi(split[29]);
  10797. }
  10798. fclose(fp);
  10799. sprintf(tmp_output,"Done reading '\033[1;29m%s\033[0;0m'.\n","db/skill_cast_db.txt");
  10800. ShowStatus(tmp_output);
  10801. /* キャスティングデ?タベ?ス */
  10802. fp=fopen("db/skill_cast_db.txt","r");
  10803. if(fp==NULL){
  10804. printf("can't read db/skill_cast_db.txt\n");
  10805. return 1;
  10806. }
  10807. while(fgets(line,1020,fp)){
  10808. char *split[50], *split2[MAX_SKILL_LEVEL];
  10809. memset(split,0,sizeof(split)); // [Valaris] thanks to fov
  10810. if(line[0]=='/' && line[1]=='/')
  10811. continue;
  10812. for(j=0,p=line;j<5 && p;j++){
  10813. split[j]=p;
  10814. p=strchr(p,',');
  10815. if(p) *p++=0;
  10816. }
  10817. if(split[4]==NULL || j<5)
  10818. continue;
  10819. i=atoi(split[0]);
  10820. if (i>=10000 && i<10015) // for guild skills [Celest]
  10821. i -= 9500;
  10822. else if(i<0 || i>MAX_SKILL_DB)
  10823. continue;
  10824. memset(split2,0,sizeof(split2));
  10825. for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
  10826. split2[j]=p;
  10827. p=strchr(p,':');
  10828. if(p) *p++=0;
  10829. }
  10830. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10831. skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10832. memset(split2,0,sizeof(split2));
  10833. for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
  10834. split2[j]=p;
  10835. p=strchr(p,':');
  10836. if(p) *p++=0;
  10837. }
  10838. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10839. skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10840. memset(split2,0,sizeof(split2));
  10841. for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
  10842. split2[j]=p;
  10843. p=strchr(p,':');
  10844. if(p) *p++=0;
  10845. }
  10846. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10847. skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10848. memset(split2,0,sizeof(split2));
  10849. for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
  10850. split2[j]=p;
  10851. p=strchr(p,':');
  10852. if(p) *p++=0;
  10853. }
  10854. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10855. skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10856. }
  10857. fclose(fp);
  10858. sprintf(tmp_output,"Done reading '\033[1;29m%s\033[0;0m'.\n","db/skill_cast_db.txt");
  10859. ShowStatus(tmp_output);
  10860. /* 製造系スキルデ?タベ?ス */
  10861. memset(skill_produce_db,0,sizeof(skill_produce_db));
  10862. for(m=0;m<2;m++){
  10863. fp=fopen(filename[m],"r");
  10864. if(fp==NULL){
  10865. if(m>0)
  10866. continue;
  10867. printf("can't read %s\n",filename[m]);
  10868. return 1;
  10869. }
  10870. k=0;
  10871. while(fgets(line,1020,fp)){
  10872. char *split[6 + MAX_PRODUCE_RESOURCE * 2];
  10873. int x,y;
  10874. if(line[0]=='/' && line[1]=='/')
  10875. continue;
  10876. memset(split,0,sizeof(split));
  10877. for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){
  10878. split[j]=p;
  10879. p=strchr(p,',');
  10880. if(p) *p++=0;
  10881. }
  10882. if(split[0]==NULL)
  10883. continue;
  10884. i=atoi(split[0]);
  10885. if(i<=0)
  10886. continue;
  10887. skill_produce_db[k].nameid=i;
  10888. skill_produce_db[k].itemlv=atoi(split[1]);
  10889. skill_produce_db[k].req_skill=atoi(split[2]);
  10890. for(x=3,y=0; split[x] && split[x+1] && y<MAX_PRODUCE_RESOURCE; x+=2,y++){
  10891. skill_produce_db[k].mat_id[y]=atoi(split[x]);
  10892. skill_produce_db[k].mat_amount[y]=atoi(split[x+1]);
  10893. }
  10894. k++;
  10895. if(k >= MAX_SKILL_PRODUCE_DB)
  10896. break;
  10897. }
  10898. fclose(fp);
  10899. sprintf(tmp_output,"Done reading '\033[1;29m%d\033[0;0m' entries in '\033[1;29m%s\033[0;0m'.\n",k,filename[m]);
  10900. ShowStatus(tmp_output);
  10901. }
  10902. memset(skill_arrow_db,0,sizeof(skill_arrow_db));
  10903. fp=fopen("db/create_arrow_db.txt","r");
  10904. if(fp==NULL){
  10905. printf("can't read db/create_arrow_db.txt\n");
  10906. return 1;
  10907. }
  10908. k=0;
  10909. while(fgets(line,1020,fp)){
  10910. char *split[16];
  10911. int x,y;
  10912. if(line[0]=='/' && line[1]=='/')
  10913. continue;
  10914. memset(split,0,sizeof(split));
  10915. for(j=0,p=line;j<13 && p;j++){
  10916. split[j]=p;
  10917. p=strchr(p,',');
  10918. if(p) *p++=0;
  10919. }
  10920. if(split[0]==NULL)
  10921. continue;
  10922. i=atoi(split[0]);
  10923. if(i<=0)
  10924. continue;
  10925. skill_arrow_db[k].nameid=i;
  10926. for(x=1,y=0;split[x] && split[x+1] && y<5;x+=2,y++){
  10927. skill_arrow_db[k].cre_id[y]=atoi(split[x]);
  10928. skill_arrow_db[k].cre_amount[y]=atoi(split[x+1]);
  10929. }
  10930. k++;
  10931. if(k >= MAX_SKILL_ARROW_DB)
  10932. break;
  10933. }
  10934. fclose(fp);
  10935. sprintf(tmp_output,"Done reading '\033[1;29m%d\033[0;0m' entries in '\033[1;29m%s\033[0;0m'.\n",k,"db/create_arrow_db.txt");
  10936. ShowStatus(tmp_output);
  10937. memset(skill_abra_db,0,sizeof(skill_abra_db));
  10938. fp=fopen("db/abra_db.txt","r");
  10939. if(fp==NULL){
  10940. printf("can't read db/abra_db.txt\n");
  10941. return 1;
  10942. }
  10943. k=0;
  10944. while(fgets(line,1020,fp)){
  10945. char *split[16];
  10946. if(line[0]=='/' && line[1]=='/')
  10947. continue;
  10948. memset(split,0,sizeof(split));
  10949. for(j=0,p=line;j<13 && p;j++){
  10950. split[j]=p;
  10951. p=strchr(p,',');
  10952. if(p) *p++=0;
  10953. }
  10954. if(split[0]==NULL)
  10955. continue;
  10956. i=atoi(split[0]);
  10957. if(i<=0)
  10958. continue;
  10959. skill_abra_db[i].req_lv=atoi(split[2]);
  10960. skill_abra_db[i].per=atoi(split[3]);
  10961. k++;
  10962. if(k >= MAX_SKILL_ABRA_DB)
  10963. break;
  10964. }
  10965. fclose(fp);
  10966. sprintf(tmp_output,"Done reading '\033[1;29m%d\033[0;0m' entries in '\033[1;29m%s\033[0;0m'.\n",k,"db/abra_db.txt");
  10967. ShowStatus(tmp_output);
  10968. fp=fopen("db/skill_castnodex_db.txt","r");
  10969. if(fp==NULL){
  10970. printf("can't read db/skill_castnodex_db.txt\n");
  10971. return 1;
  10972. }
  10973. while(fgets(line,1020,fp)){
  10974. char *split[50], *split2[MAX_SKILL_LEVEL];
  10975. memset(split,0,sizeof(split));
  10976. if(line[0]=='/' && line[1]=='/')
  10977. continue;
  10978. for(j=0,p=line;j<2 && p;j++){
  10979. split[j]=p;
  10980. p=strchr(p,',');
  10981. if(p) *p++=0;
  10982. }
  10983. i=atoi(split[0]);
  10984. if (i>=10000 && i<10015) // for guild skills [Celest]
  10985. i -= 9500;
  10986. else if(i<0 || i>MAX_SKILL_DB)
  10987. continue;
  10988. memset(split2,0,sizeof(split2));
  10989. for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
  10990. split2[j]=p;
  10991. p=strchr(p,':');
  10992. if(p) *p++=0;
  10993. }
  10994. for(k=0;k<MAX_SKILL_LEVEL;k++)
  10995. skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
  10996. }
  10997. fclose(fp);
  10998. sprintf(tmp_output,"Done reading '\033[1;29m%s\033[0;0m'.\n","db/skill_castnodex_db.txt");
  10999. ShowStatus(tmp_output);
  11000. fp=fopen("db/skill_nocast_db.txt","r");
  11001. if(fp==NULL){
  11002. printf("can't read db/skill_nocast_db.txt\n");
  11003. return 1;
  11004. }
  11005. k=0;
  11006. while(fgets(line,1020,fp)){
  11007. char *split[16];
  11008. if(line[0]=='/' && line[1]=='/')
  11009. continue;
  11010. memset(split,0,sizeof(split));
  11011. for(j=0,p=line;j<2 && p;j++){
  11012. split[j]=p;
  11013. p=strchr(p,',');
  11014. if(p) *p++=0;
  11015. }
  11016. if(split[0]==NULL)
  11017. continue;
  11018. i=atoi(split[0]);
  11019. if (i>=10000 && i<10015) // for guild skills [Celest]
  11020. i -= 9500;
  11021. else if(i<0 || i>MAX_SKILL_DB)
  11022. continue;
  11023. skill_db[i].nocast=atoi(split[1]);
  11024. k++;
  11025. }
  11026. fclose(fp);
  11027. sprintf(tmp_output,"Done reading '\033[1;29m%s\033[0;0m'.\n","db/skill_nocast_db");
  11028. ShowStatus(tmp_output);
  11029. return 0;
  11030. }
  11031. void skill_reload(void)
  11032. {
  11033. /*
  11034. <empty skill database>
  11035. <?>
  11036. */
  11037. do_init_skill();
  11038. }
  11039. /*==========================================
  11040. * スキル?係初期化?理
  11041. *------------------------------------------
  11042. */
  11043. int do_init_skill(void)
  11044. {
  11045. skill_readdb();
  11046. add_timer_func_list(skill_unit_timer,"skill_unit_timer");
  11047. add_timer_func_list(skill_castend_id,"skill_castend_id");
  11048. add_timer_func_list(skill_castend_pos,"skill_castend_pos");
  11049. add_timer_func_list(skill_timerskill,"skill_timerskill");
  11050. add_timer_func_list(skill_status_change_timer,"skill_status_change_timer");
  11051. add_timer_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL);
  11052. return 0;
  11053. }