Entity.cpp 148 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. /*
  24. ===============================================================================
  25. idEntity
  26. ===============================================================================
  27. */
  28. // overridable events
  29. const idEventDef EV_PostSpawn( "<postspawn>", NULL );
  30. const idEventDef EV_FindTargets( "<findTargets>", NULL );
  31. const idEventDef EV_Touch( "<touch>", "et" );
  32. const idEventDef EV_GetName( "getName", NULL, 's' );
  33. const idEventDef EV_SetName( "setName", "s" );
  34. const idEventDef EV_Activate( "activate", "e" );
  35. const idEventDef EV_ActivateTargets( "activateTargets", "e" );
  36. const idEventDef EV_NumTargets( "numTargets", NULL, 'f' );
  37. const idEventDef EV_GetTarget( "getTarget", "f", 'e' );
  38. const idEventDef EV_RandomTarget( "randomTarget", "s", 'e' );
  39. const idEventDef EV_Bind( "bind", "e" );
  40. const idEventDef EV_BindPosition( "bindPosition", "e" );
  41. const idEventDef EV_BindToJoint( "bindToJoint", "esf" );
  42. const idEventDef EV_Unbind( "unbind", NULL );
  43. const idEventDef EV_RemoveBinds( "removeBinds" );
  44. const idEventDef EV_SpawnBind( "<spawnbind>", NULL );
  45. const idEventDef EV_SetOwner( "setOwner", "e" );
  46. const idEventDef EV_SetModel( "setModel", "s" );
  47. const idEventDef EV_SetSkin( "setSkin", "s" );
  48. const idEventDef EV_GetWorldOrigin( "getWorldOrigin", NULL, 'v' );
  49. const idEventDef EV_SetWorldOrigin( "setWorldOrigin", "v" );
  50. const idEventDef EV_GetOrigin( "getOrigin", NULL, 'v' );
  51. const idEventDef EV_SetOrigin( "setOrigin", "v" );
  52. const idEventDef EV_GetAngles( "getAngles", NULL, 'v' );
  53. const idEventDef EV_SetAngles( "setAngles", "v" );
  54. const idEventDef EV_GetLinearVelocity( "getLinearVelocity", NULL, 'v' );
  55. const idEventDef EV_SetLinearVelocity( "setLinearVelocity", "v" );
  56. const idEventDef EV_GetAngularVelocity( "getAngularVelocity", NULL, 'v' );
  57. const idEventDef EV_SetAngularVelocity( "setAngularVelocity", "v" );
  58. const idEventDef EV_GetSize( "getSize", NULL, 'v' );
  59. const idEventDef EV_SetSize( "setSize", "vv" );
  60. const idEventDef EV_GetMins( "getMins", NULL, 'v' );
  61. const idEventDef EV_GetMaxs( "getMaxs", NULL, 'v' );
  62. const idEventDef EV_IsHidden( "isHidden", NULL, 'd' );
  63. const idEventDef EV_Hide( "hide", NULL );
  64. const idEventDef EV_Show( "show", NULL );
  65. const idEventDef EV_Touches( "touches", "E", 'd' );
  66. const idEventDef EV_ClearSignal( "clearSignal", "d" );
  67. const idEventDef EV_GetShaderParm( "getShaderParm", "d", 'f' );
  68. const idEventDef EV_SetShaderParm( "setShaderParm", "df" );
  69. const idEventDef EV_SetShaderParms( "setShaderParms", "ffff" );
  70. const idEventDef EV_SetColor( "setColor", "fff" );
  71. const idEventDef EV_GetColor( "getColor", NULL, 'v' );
  72. const idEventDef EV_CacheSoundShader( "cacheSoundShader", "s" );
  73. const idEventDef EV_StartSoundShader( "startSoundShader", "sd", 'f' );
  74. const idEventDef EV_StartSound( "startSound", "sdd", 'f' );
  75. const idEventDef EV_StopSound( "stopSound", "dd" );
  76. const idEventDef EV_FadeSound( "fadeSound", "dff" );
  77. const idEventDef EV_SetGuiParm( "setGuiParm", "ss" );
  78. const idEventDef EV_SetGuiFloat( "setGuiFloat", "sf" );
  79. const idEventDef EV_GetNextKey( "getNextKey", "ss", 's' );
  80. const idEventDef EV_SetKey( "setKey", "ss" );
  81. const idEventDef EV_GetKey( "getKey", "s", 's' );
  82. const idEventDef EV_GetIntKey( "getIntKey", "s", 'f' );
  83. const idEventDef EV_GetFloatKey( "getFloatKey", "s", 'f' );
  84. const idEventDef EV_GetVectorKey( "getVectorKey", "s", 'v' );
  85. const idEventDef EV_GetEntityKey( "getEntityKey", "s", 'e' );
  86. const idEventDef EV_RestorePosition( "restorePosition" );
  87. const idEventDef EV_UpdateCameraTarget( "<updateCameraTarget>", NULL );
  88. const idEventDef EV_DistanceTo( "distanceTo", "E", 'f' );
  89. const idEventDef EV_DistanceToPoint( "distanceToPoint", "v", 'f' );
  90. const idEventDef EV_StartFx( "startFx", "s" );
  91. const idEventDef EV_HasFunction( "hasFunction", "s", 'd' );
  92. const idEventDef EV_CallFunction( "callFunction", "s" );
  93. const idEventDef EV_CallFunctionArg( "callFunctionArg", "sd" );
  94. const idEventDef EV_SetNeverDormant( "setNeverDormant", "d" );
  95. const idEventDef EV_SetFrobbable( "setFrobbable", "d" ); //bc
  96. const idEventDef EV_deck_print( "deck_print", "s" );
  97. const idEventDef EV_deck_printline( "deck_printline", "s" );
  98. const idEventDef EV_deck_cls( "deck_cls" );
  99. const idEventDef EV_SetCameraTarget( "setCameraTarget", "e" );
  100. const idEventDef EV_ClearCameraTarget( "clearCameraTarget", NULL );
  101. const idEventDef EV_getNearestEnemy( "getNearestEnemy", NULL, 'e' );
  102. const idEventDef EV_canSeeEntity( "canSeeEntity", "e", 'd' );
  103. const idEventDef EV_GetIndex( "getIndex", NULL, 'd' );
  104. const idEventDef EV_SetSolid( "setSolid", "d" );
  105. const idEventDef EV_SetClipModel( "setClipModel", "s" );
  106. //bc flite
  107. //const idEventDef EV_flitespeech( "flitespeech", "s", 'd' );
  108. #ifdef _D3XP
  109. const idEventDef EV_SetGui ( "setGui", "ds" );
  110. const idEventDef EV_PrecacheGui ( "precacheGui", "s" );
  111. const idEventDef EV_GetGuiParm ( "getGuiParm", "ds", 's' );
  112. const idEventDef EV_GetGuiParmFloat ( "getGuiParmFloat", "ds", 'f' );
  113. const idEventDef EV_MotionBlurOn( "motionBlurOn" );
  114. const idEventDef EV_MotionBlurOff( "motionBlurOff" );
  115. const idEventDef EV_GuiNamedEvent ( "guiNamedEvent", "ds" );
  116. #endif
  117. ABSTRACT_DECLARATION( idClass, idEntity )
  118. EVENT( EV_GetName, idEntity::Event_GetName )
  119. EVENT( EV_SetName, idEntity::Event_SetName )
  120. EVENT( EV_FindTargets, idEntity::Event_FindTargets )
  121. EVENT( EV_ActivateTargets, idEntity::Event_ActivateTargets )
  122. EVENT( EV_NumTargets, idEntity::Event_NumTargets )
  123. EVENT( EV_GetTarget, idEntity::Event_GetTarget )
  124. EVENT( EV_RandomTarget, idEntity::Event_RandomTarget )
  125. EVENT( EV_BindToJoint, idEntity::Event_BindToJoint )
  126. EVENT( EV_RemoveBinds, idEntity::Event_RemoveBinds )
  127. EVENT( EV_Bind, idEntity::Event_Bind )
  128. EVENT( EV_BindPosition, idEntity::Event_BindPosition )
  129. EVENT( EV_Unbind, idEntity::Event_Unbind )
  130. EVENT( EV_SpawnBind, idEntity::Event_SpawnBind )
  131. EVENT( EV_SetOwner, idEntity::Event_SetOwner )
  132. EVENT( EV_SetModel, idEntity::Event_SetModel )
  133. EVENT( EV_SetSkin, idEntity::Event_SetSkin )
  134. EVENT( EV_GetShaderParm, idEntity::Event_GetShaderParm )
  135. EVENT( EV_SetShaderParm, idEntity::Event_SetShaderParm )
  136. EVENT( EV_SetShaderParms, idEntity::Event_SetShaderParms )
  137. EVENT( EV_SetColor, idEntity::Event_SetColor )
  138. EVENT( EV_GetColor, idEntity::Event_GetColor )
  139. EVENT( EV_IsHidden, idEntity::Event_IsHidden )
  140. EVENT( EV_Hide, idEntity::Event_Hide )
  141. EVENT( EV_Show, idEntity::Event_Show )
  142. EVENT( EV_CacheSoundShader, idEntity::Event_CacheSoundShader )
  143. EVENT( EV_StartSoundShader, idEntity::Event_StartSoundShader )
  144. EVENT( EV_StartSound, idEntity::Event_StartSound )
  145. EVENT( EV_StopSound, idEntity::Event_StopSound )
  146. EVENT( EV_FadeSound, idEntity::Event_FadeSound )
  147. EVENT( EV_GetWorldOrigin, idEntity::Event_GetWorldOrigin )
  148. EVENT( EV_SetWorldOrigin, idEntity::Event_SetWorldOrigin )
  149. EVENT( EV_GetOrigin, idEntity::Event_GetOrigin )
  150. EVENT( EV_SetOrigin, idEntity::Event_SetOrigin )
  151. EVENT( EV_GetAngles, idEntity::Event_GetAngles )
  152. EVENT( EV_SetAngles, idEntity::Event_SetAngles )
  153. EVENT( EV_GetLinearVelocity, idEntity::Event_GetLinearVelocity )
  154. EVENT( EV_SetLinearVelocity, idEntity::Event_SetLinearVelocity )
  155. EVENT( EV_GetAngularVelocity, idEntity::Event_GetAngularVelocity )
  156. EVENT( EV_SetAngularVelocity, idEntity::Event_SetAngularVelocity )
  157. EVENT( EV_GetSize, idEntity::Event_GetSize )
  158. EVENT( EV_SetSize, idEntity::Event_SetSize )
  159. EVENT( EV_GetMins, idEntity::Event_GetMins)
  160. EVENT( EV_GetMaxs, idEntity::Event_GetMaxs )
  161. EVENT( EV_Touches, idEntity::Event_Touches )
  162. EVENT( EV_SetGuiParm, idEntity::Event_SetGuiParm )
  163. EVENT( EV_SetGuiFloat, idEntity::Event_SetGuiFloat )
  164. EVENT( EV_GetNextKey, idEntity::Event_GetNextKey )
  165. EVENT( EV_SetKey, idEntity::Event_SetKey )
  166. EVENT( EV_GetKey, idEntity::Event_GetKey )
  167. EVENT( EV_GetIntKey, idEntity::Event_GetIntKey )
  168. EVENT( EV_GetFloatKey, idEntity::Event_GetFloatKey )
  169. EVENT( EV_GetVectorKey, idEntity::Event_GetVectorKey )
  170. EVENT( EV_GetEntityKey, idEntity::Event_GetEntityKey )
  171. EVENT( EV_RestorePosition, idEntity::Event_RestorePosition )
  172. EVENT( EV_UpdateCameraTarget, idEntity::Event_UpdateCameraTarget )
  173. EVENT( EV_DistanceTo, idEntity::Event_DistanceTo )
  174. EVENT( EV_DistanceToPoint, idEntity::Event_DistanceToPoint )
  175. EVENT( EV_StartFx, idEntity::Event_StartFx )
  176. EVENT( EV_Thread_WaitFrame, idEntity::Event_WaitFrame )
  177. EVENT( EV_Thread_Wait, idEntity::Event_Wait )
  178. EVENT( EV_HasFunction, idEntity::Event_HasFunction )
  179. EVENT( EV_CallFunction, idEntity::Event_CallFunction )
  180. EVENT( EV_CallFunctionArg, idEntity::Event_CallFunctionArg )
  181. EVENT( EV_SetNeverDormant, idEntity::Event_SetNeverDormant )
  182. EVENT( EV_SetFrobbable, idEntity::Event_SetFrobbable ) //bc
  183. EVENT( EV_deck_print, idEntity::Event_deck_print)
  184. EVENT( EV_deck_printline, idEntity::Event_deck_printline)
  185. EVENT( EV_SetSolid, idEntity::Event_SetSolid) //bc
  186. EVENT( EV_SetClipModel, idEntity::Event_SetClipModel) //bc
  187. //bc flite
  188. //EVENT( EV_flitespeech, idEntity::Event_flitespeech) //bc
  189. EVENT( EV_deck_cls, idEntity::Event_deck_cls)
  190. EVENT( EV_SetCameraTarget, idEntity::Event_SetCameraTarget)
  191. EVENT( EV_ClearCameraTarget, idEntity::Event_ClearCameraTarget)
  192. EVENT( EV_getNearestEnemy, idEntity::Event_getNearestEnemy)
  193. EVENT( EV_canSeeEntity, idEntity::Event_canSeeEntity)
  194. EVENT( EV_GetIndex, idEntity::Event_GetIndex)
  195. #ifdef _D3XP
  196. EVENT( EV_SetGui, idEntity::Event_SetGui )
  197. EVENT( EV_PrecacheGui, idEntity::Event_PrecacheGui )
  198. EVENT( EV_GetGuiParm, idEntity::Event_GetGuiParm )
  199. EVENT( EV_GetGuiParmFloat, idEntity::Event_GetGuiParmFloat )
  200. EVENT( EV_GuiNamedEvent, idEntity::Event_GuiNamedEvent )
  201. #endif
  202. END_CLASS
  203. /*
  204. ================
  205. UpdateGuiParms
  206. ================
  207. */
  208. void UpdateGuiParms( idUserInterface *gui, const idDict *args ) {
  209. if ( gui == NULL || args == NULL ) {
  210. return;
  211. }
  212. const idKeyValue *kv = args->MatchPrefix( "gui_parm", NULL );
  213. while( kv ) {
  214. gui->SetStateString( kv->GetKey(), kv->GetValue() );
  215. kv = args->MatchPrefix( "gui_parm", kv );
  216. }
  217. gui->SetStateBool( "noninteractive", args->GetBool( "gui_noninteractive" ) ) ;
  218. gui->StateChanged( gameLocal.time );
  219. }
  220. /*
  221. ================
  222. AddRenderGui
  223. ================
  224. */
  225. void AddRenderGui( const char *name, idUserInterface **gui, const idDict *args ) {
  226. const idKeyValue *kv = args->MatchPrefix( "gui_parm", NULL );
  227. *gui = uiManager->FindGui( name, true, ( kv != NULL ) );
  228. UpdateGuiParms( *gui, args );
  229. }
  230. /*
  231. ================
  232. idGameEdit::ParseSpawnArgsToRenderEntity
  233. parse the static model parameters
  234. this is the canonical renderEntity parm parsing,
  235. which should be used by dmap and the editor
  236. ================
  237. */
  238. void idGameEdit::ParseSpawnArgsToRenderEntity( const idDict *args, renderEntity_t *renderEntity ) {
  239. int i;
  240. const char *temp;
  241. idVec3 color;
  242. float angle;
  243. const idDeclModelDef *modelDef;
  244. memset( renderEntity, 0, sizeof( *renderEntity ) );
  245. temp = args->GetString( "model" );
  246. modelDef = NULL;
  247. if ( temp[0] != '\0' ) {
  248. modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, temp, false ) );
  249. if ( modelDef ) {
  250. renderEntity->hModel = modelDef->ModelHandle();
  251. }
  252. if ( !renderEntity->hModel ) {
  253. renderEntity->hModel = renderModelManager->FindModel( temp );
  254. }
  255. }
  256. if ( renderEntity->hModel ) {
  257. renderEntity->bounds = renderEntity->hModel->Bounds( renderEntity );
  258. } else {
  259. renderEntity->bounds.Zero();
  260. }
  261. temp = args->GetString( "skin" );
  262. if ( temp[0] != '\0' ) {
  263. renderEntity->customSkin = declManager->FindSkin( temp );
  264. } else if ( modelDef ) {
  265. renderEntity->customSkin = modelDef->GetDefaultSkin();
  266. }
  267. temp = args->GetString( "shader" );
  268. if ( temp[0] != '\0' ) {
  269. renderEntity->customShader = declManager->FindMaterial( temp );
  270. }
  271. args->GetVector( "origin", "0 0 0", renderEntity->origin );
  272. // get the rotation matrix in either full form, or single angle form
  273. if ( !args->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", renderEntity->axis ) ) {
  274. angle = args->GetFloat( "angle" );
  275. if ( angle != 0.0f ) {
  276. renderEntity->axis = idAngles( 0.0f, angle, 0.0f ).ToMat3();
  277. } else {
  278. renderEntity->axis.Identity();
  279. }
  280. }
  281. renderEntity->referenceSound = NULL;
  282. // get shader parms
  283. args->GetVector( "_color", "1 1 1", color );
  284. renderEntity->shaderParms[ SHADERPARM_RED ] = color[0];
  285. renderEntity->shaderParms[ SHADERPARM_GREEN ] = color[1];
  286. renderEntity->shaderParms[ SHADERPARM_BLUE ] = color[2];
  287. renderEntity->shaderParms[ 3 ] = args->GetFloat( "shaderParm3", "1" );
  288. renderEntity->shaderParms[ 4 ] = args->GetFloat( "shaderParm4", "0" );
  289. renderEntity->shaderParms[ 5 ] = args->GetFloat( "shaderParm5", "0" );
  290. renderEntity->shaderParms[ 6 ] = args->GetFloat( "shaderParm6", "0" );
  291. renderEntity->shaderParms[ 7 ] = args->GetFloat( "shaderParm7", "0" );
  292. renderEntity->shaderParms[ 8 ] = args->GetFloat( "shaderParm8", "0" );
  293. renderEntity->shaderParms[ 9 ] = args->GetFloat( "shaderParm9", "0" );
  294. renderEntity->shaderParms[ 10 ] = args->GetFloat( "shaderParm10", "0" );
  295. renderEntity->shaderParms[ 11 ] = args->GetFloat( "shaderParm11", "0" );
  296. // check noDynamicInteractions flag
  297. renderEntity->noDynamicInteractions = args->GetBool( "noDynamicInteractions" );
  298. // check noshadows flag
  299. renderEntity->noShadow = args->GetBool( "noshadows" );
  300. // check noselfshadows flag
  301. renderEntity->noSelfShadow = args->GetBool( "noselfshadows" );
  302. // init any guis, including entity-specific states
  303. for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  304. temp = args->GetString( i == 0 ? "gui" : va( "gui%d", i + 1 ) );
  305. if ( temp[ 0 ] != '\0' ) {
  306. AddRenderGui( temp, &renderEntity->gui[ i ], args );
  307. }
  308. }
  309. }
  310. /*
  311. ================
  312. idGameEdit::ParseSpawnArgsToRefSound
  313. parse the sound parameters
  314. this is the canonical refSound parm parsing,
  315. which should be used by dmap and the editor
  316. ================
  317. */
  318. void idGameEdit::ParseSpawnArgsToRefSound( const idDict *args, refSound_t *refSound ) {
  319. const char *temp;
  320. memset( refSound, 0, sizeof( *refSound ) );
  321. refSound->parms.minDistance = args->GetFloat( "s_mindistance" );
  322. refSound->parms.maxDistance = args->GetFloat( "s_maxdistance" );
  323. refSound->parms.volume = args->GetFloat( "s_volume" );
  324. refSound->parms.shakes = args->GetFloat( "s_shakes" );
  325. args->GetVector( "origin", "0 0 0", refSound->origin );
  326. refSound->referenceSound = NULL;
  327. // if a diversity is not specified, every sound start will make
  328. // a random one. Specifying diversity is usefull to make multiple
  329. // lights all share the same buzz sound offset, for instance.
  330. refSound->diversity = args->GetFloat( "s_diversity", "-1" );
  331. refSound->waitfortrigger = args->GetBool( "s_waitfortrigger" );
  332. if ( args->GetBool( "s_omni" ) ) {
  333. refSound->parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL;
  334. }
  335. if ( args->GetBool( "s_looping" ) ) {
  336. refSound->parms.soundShaderFlags |= SSF_LOOPING;
  337. }
  338. if ( args->GetBool( "s_occlusion" ) ) {
  339. refSound->parms.soundShaderFlags |= SSF_NO_OCCLUSION;
  340. }
  341. if ( args->GetBool( "s_global" ) ) {
  342. refSound->parms.soundShaderFlags |= SSF_GLOBAL;
  343. }
  344. if ( args->GetBool( "s_unclamped" ) ) {
  345. refSound->parms.soundShaderFlags |= SSF_UNCLAMPED;
  346. }
  347. refSound->parms.soundClass = args->GetInt( "s_soundClass" );
  348. temp = args->GetString( "s_shader" );
  349. if ( temp[0] != '\0' ) {
  350. refSound->shader = declManager->FindSound( temp );
  351. }
  352. }
  353. /*
  354. ===============
  355. idEntity::UpdateChangeableSpawnArgs
  356. Any key val pair that might change during the course of the game ( via a gui or whatever )
  357. should be initialize here so a gui or other trigger can change something and have it updated
  358. properly. An optional source may be provided if the values reside in an outside dictionary and
  359. first need copied over to spawnArgs
  360. ===============
  361. */
  362. void idEntity::UpdateChangeableSpawnArgs( const idDict *source ) {
  363. int i;
  364. const char *target;
  365. if ( !source ) {
  366. source = &spawnArgs;
  367. }
  368. cameraTarget = NULL;
  369. target = source->GetString( "cameraTarget" );
  370. if ( target && target[0] ) {
  371. // update the camera taget
  372. PostEventMS( &EV_UpdateCameraTarget, 0 );
  373. }
  374. for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  375. UpdateGuiParms( renderEntity.gui[ i ], source );
  376. }
  377. }
  378. /*
  379. ================
  380. idEntity::idEntity
  381. ================
  382. */
  383. idEntity::idEntity() {
  384. entityNumber = ENTITYNUM_NONE;
  385. entityDefNumber = -1;
  386. spawnNode.SetOwner( this );
  387. activeNode.SetOwner( this );
  388. snapshotNode.SetOwner( this );
  389. snapshotSequence = -1;
  390. snapshotBits = 0;
  391. thinkFlags = 0;
  392. dormantStart = 0;
  393. cinematic = false;
  394. renderView = NULL;
  395. cameraTarget = NULL;
  396. health = 0;
  397. physics = NULL;
  398. bindMaster = NULL;
  399. bindJoint = INVALID_JOINT;
  400. bindBody = -1;
  401. teamMaster = NULL;
  402. teamChain = NULL;
  403. signals = NULL;
  404. memset( PVSAreas, 0, sizeof( PVSAreas ) );
  405. numPVSAreas = -1;
  406. memset( &fl, 0, sizeof( fl ) );
  407. fl.neverDormant = true; // most entities never go dormant
  408. memset( &renderEntity, 0, sizeof( renderEntity ) );
  409. modelDefHandle = -1;
  410. memset( &refSound, 0, sizeof( refSound ) );
  411. mpGUIState = -1;
  412. #ifdef _D3XP
  413. memset( &xrayEntity, 0, sizeof( xrayEntity ) );
  414. timeGroup = TIME_GROUP1;
  415. xrayEntityHandle = -1;
  416. xraySkin = NULL;
  417. noGrab = false;
  418. #endif
  419. }
  420. /*
  421. ================
  422. idEntity::FixupLocalizedStrings
  423. ================
  424. */
  425. void idEntity::FixupLocalizedStrings() {
  426. for ( int i = 0; i < spawnArgs.GetNumKeyVals(); i++ ) {
  427. const idKeyValue *kv = spawnArgs.GetKeyVal( i );
  428. if ( idStr::Cmpn( kv->GetValue(), STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ){
  429. spawnArgs.Set( kv->GetKey(), common->GetLanguageDict()->GetString( kv->GetValue() ) );
  430. }
  431. }
  432. }
  433. /*
  434. ================
  435. idEntity::Spawn
  436. ================
  437. */
  438. void idEntity::Spawn( void ) {
  439. int i;
  440. const char *temp;
  441. idVec3 origin;
  442. idMat3 axis;
  443. const idKeyValue *networkSync;
  444. const char *classname;
  445. const char *scriptObjectName;
  446. gameLocal.RegisterEntity( this );
  447. spawnArgs.GetString( "classname", NULL, &classname );
  448. const idDeclEntityDef *def = gameLocal.FindEntityDef( classname, false );
  449. if ( def ) {
  450. entityDefNumber = def->Index();
  451. }
  452. FixupLocalizedStrings();
  453. // parse static models the same way the editor display does
  454. gameEdit->ParseSpawnArgsToRenderEntity( &spawnArgs, &renderEntity );
  455. renderEntity.entityNum = entityNumber;
  456. #ifdef _D3XP
  457. noGrab = spawnArgs.GetBool( "noGrab", "0" );
  458. isFrobbable = spawnArgs.GetBool( "frobbable", "1" );
  459. lastThrowTime = 0;
  460. xraySkin = NULL;
  461. renderEntity.xrayIndex = 1;
  462. idStr str;
  463. if ( spawnArgs.GetString( "skin_xray", "", str ) ) {
  464. xraySkin = declManager->FindSkin( str.c_str() );
  465. }
  466. #endif
  467. // go dormant within 5 frames so that when the map starts most monsters are dormant
  468. dormantStart = gameLocal.time - DELAY_DORMANT_TIME + gameLocal.msec * 5;
  469. origin = renderEntity.origin;
  470. axis = renderEntity.axis;
  471. // do the audio parsing the same way dmap and the editor do
  472. gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
  473. // only play SCHANNEL_PRIVATE when sndworld->PlaceListener() is called with this listenerId
  474. // don't spatialize sounds from the same entity
  475. refSound.listenerId = entityNumber + 1;
  476. cameraTarget = NULL;
  477. temp = spawnArgs.GetString( "cameraTarget" );
  478. if ( temp && temp[0] ) {
  479. // update the camera taget
  480. PostEventMS( &EV_UpdateCameraTarget, 0 );
  481. }
  482. for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  483. UpdateGuiParms( renderEntity.gui[ i ], &spawnArgs );
  484. }
  485. fl.solidForTeam = spawnArgs.GetBool( "solidForTeam", "0" );
  486. fl.neverDormant = spawnArgs.GetBool( "neverDormant", "0" );
  487. fl.hidden = spawnArgs.GetBool( "hide", "0" );
  488. if ( fl.hidden ) {
  489. // make sure we're hidden, since a spawn function might not set it up right
  490. PostEventMS( &EV_Hide, 0 );
  491. }
  492. cinematic = spawnArgs.GetBool( "cinematic", "0" );
  493. networkSync = spawnArgs.FindKey( "networkSync" );
  494. if ( networkSync ) {
  495. fl.networkSync = ( atoi( networkSync->GetValue() ) != 0 );
  496. }
  497. #if 0
  498. if ( !gameLocal.isClient ) {
  499. // common->DPrintf( "NET: DBG %s - %s is synced: %s\n", spawnArgs.GetString( "classname", "" ), GetType()->classname, fl.networkSync ? "true" : "false" );
  500. if ( spawnArgs.GetString( "classname", "" )[ 0 ] == '\0' && !fl.networkSync ) {
  501. common->DPrintf( "NET: WRN %s entity, no classname, and no networkSync?\n", GetType()->classname );
  502. }
  503. }
  504. #endif
  505. // every object will have a unique name
  506. temp = spawnArgs.GetString( "name", va( "%s_%s_%d", GetClassname(), spawnArgs.GetString( "classname" ), entityNumber ) );
  507. SetName( temp );
  508. // if we have targets, wait until all entities are spawned to get them
  509. if ( spawnArgs.MatchPrefix( "target" ) || spawnArgs.MatchPrefix( "guiTarget" ) ) {
  510. if ( gameLocal.GameState() == GAMESTATE_STARTUP ) {
  511. PostEventMS( &EV_FindTargets, 0 );
  512. } else {
  513. // not during spawn, so it's ok to get the targets
  514. FindTargets();
  515. }
  516. }
  517. health = spawnArgs.GetInt( "health" );
  518. InitDefaultPhysics( origin, axis );
  519. SetOrigin( origin );
  520. SetAxis( axis );
  521. temp = spawnArgs.GetString( "model" );
  522. if ( temp && *temp ) {
  523. SetModel( temp );
  524. }
  525. if ( spawnArgs.GetString( "bind", "", &temp ) ) {
  526. PostEventMS( &EV_SpawnBind, 0 );
  527. }
  528. // auto-start a sound on the entity
  529. if ( refSound.shader && !refSound.waitfortrigger ) {
  530. StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  531. }
  532. // setup script object
  533. if ( ShouldConstructScriptObjectAtSpawn() && spawnArgs.GetString( "scriptobject", NULL, &scriptObjectName ) ) {
  534. if ( !scriptObject.SetType( scriptObjectName ) ) {
  535. gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
  536. }
  537. ConstructScriptObject();
  538. }
  539. #ifdef _D3XP
  540. // determine time group
  541. DetermineTimeGroup( spawnArgs.GetBool( "slowmo", "1" ) );
  542. #endif
  543. //bc
  544. uiAlarmTimer = 0;
  545. uiHackTimer = 0;
  546. }
  547. /*
  548. ================
  549. idEntity::~idEntity
  550. ================
  551. */
  552. idEntity::~idEntity( void ) {
  553. if ( gameLocal.GameState() != GAMESTATE_SHUTDOWN && !gameLocal.isClient && fl.networkSync && entityNumber >= MAX_CLIENTS ) {
  554. idBitMsg msg;
  555. byte msgBuf[ MAX_GAME_MESSAGE_SIZE ];
  556. msg.Init( msgBuf, sizeof( msgBuf ) );
  557. msg.WriteByte( GAME_RELIABLE_MESSAGE_DELETE_ENT );
  558. msg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  559. networkSystem->ServerSendReliableMessage( -1, msg );
  560. }
  561. DeconstructScriptObject();
  562. scriptObject.Free();
  563. if ( thinkFlags ) {
  564. BecomeInactive( thinkFlags );
  565. }
  566. activeNode.Remove();
  567. Signal( SIG_REMOVED );
  568. // we have to set back the default physics object before unbinding because the entity
  569. // specific physics object might be an entity variable and as such could already be destroyed.
  570. SetPhysics( NULL );
  571. // remove any entities that are bound to me
  572. RemoveBinds();
  573. // unbind from master
  574. Unbind();
  575. QuitTeam();
  576. gameLocal.RemoveEntityFromHash( name.c_str(), this );
  577. delete renderView;
  578. renderView = NULL;
  579. delete signals;
  580. signals = NULL;
  581. FreeModelDef();
  582. FreeSoundEmitter( false );
  583. #ifdef _D3XP
  584. if ( xrayEntityHandle != -1) {
  585. gameRenderWorld->FreeEntityDef( xrayEntityHandle );
  586. xrayEntityHandle = -1;
  587. }
  588. #endif
  589. gameLocal.UnregisterEntity( this );
  590. }
  591. /*
  592. ================
  593. idEntity::Save
  594. ================
  595. */
  596. void idEntity::Save( idSaveGame *savefile ) const {
  597. int i, j;
  598. savefile->WriteInt( entityNumber );
  599. savefile->WriteInt( entityDefNumber );
  600. // spawnNode and activeNode are restored by gameLocal
  601. savefile->WriteInt( snapshotSequence );
  602. savefile->WriteInt( snapshotBits );
  603. savefile->WriteDict( &spawnArgs );
  604. savefile->WriteString( name );
  605. scriptObject.Save( savefile );
  606. savefile->WriteInt( thinkFlags );
  607. savefile->WriteInt( dormantStart );
  608. savefile->WriteBool( cinematic );
  609. savefile->WriteObject( cameraTarget );
  610. savefile->WriteInt( health );
  611. savefile->WriteInt( targets.Num() );
  612. for( i = 0; i < targets.Num(); i++ ) {
  613. targets[ i ].Save( savefile );
  614. }
  615. entityFlags_s flags = fl;
  616. LittleBitField( &flags, sizeof( flags ) );
  617. savefile->Write( &flags, sizeof( flags ) );
  618. #ifdef _D3XP
  619. savefile->WriteInt( timeGroup );
  620. savefile->WriteBool( noGrab );
  621. savefile->WriteRenderEntity( xrayEntity );
  622. savefile->WriteInt( xrayEntityHandle );
  623. savefile->WriteSkin( xraySkin );
  624. #endif
  625. savefile->WriteRenderEntity( renderEntity );
  626. savefile->WriteInt( modelDefHandle );
  627. savefile->WriteRefSound( refSound );
  628. savefile->WriteObject( bindMaster );
  629. savefile->WriteJoint( bindJoint );
  630. savefile->WriteInt( bindBody );
  631. savefile->WriteObject( teamMaster );
  632. savefile->WriteObject( teamChain );
  633. savefile->WriteStaticObject( defaultPhysicsObj );
  634. savefile->WriteInt( numPVSAreas );
  635. for( i = 0; i < MAX_PVS_AREAS; i++ ) {
  636. savefile->WriteInt( PVSAreas[ i ] );
  637. }
  638. if ( !signals ) {
  639. savefile->WriteBool( false );
  640. } else {
  641. savefile->WriteBool( true );
  642. for( i = 0; i < NUM_SIGNALS; i++ ) {
  643. savefile->WriteInt( signals->signal[ i ].Num() );
  644. for( j = 0; j < signals->signal[ i ].Num(); j++ ) {
  645. savefile->WriteInt( signals->signal[ i ][ j ].threadnum );
  646. savefile->WriteString( signals->signal[ i ][ j ].function->Name() );
  647. }
  648. }
  649. }
  650. savefile->WriteInt( mpGUIState );
  651. //BC
  652. savefile->WriteBool(noGrab);
  653. savefile->WriteBool(isFrobbable);
  654. savefile->WriteInt(uiAlarmTimer);
  655. savefile->WriteInt(uiHackTimer);
  656. savefile->WriteInt(lastThrowTime);
  657. }
  658. /*
  659. ================
  660. idEntity::Restore
  661. ================
  662. */
  663. void idEntity::Restore( idRestoreGame *savefile ) {
  664. int i, j;
  665. int num;
  666. idStr funcname;
  667. savefile->ReadInt( entityNumber );
  668. savefile->ReadInt( entityDefNumber );
  669. // spawnNode and activeNode are restored by gameLocal
  670. savefile->ReadInt( snapshotSequence );
  671. savefile->ReadInt( snapshotBits );
  672. savefile->ReadDict( &spawnArgs );
  673. savefile->ReadString( name );
  674. SetName( name );
  675. scriptObject.Restore( savefile );
  676. savefile->ReadInt( thinkFlags );
  677. savefile->ReadInt( dormantStart );
  678. savefile->ReadBool( cinematic );
  679. savefile->ReadObject( reinterpret_cast<idClass *&>( cameraTarget ) );
  680. savefile->ReadInt( health );
  681. targets.Clear();
  682. savefile->ReadInt( num );
  683. targets.SetNum( num );
  684. for( i = 0; i < num; i++ ) {
  685. targets[ i ].Restore( savefile );
  686. }
  687. savefile->Read( &fl, sizeof( fl ) );
  688. LittleBitField( &fl, sizeof( fl ) );
  689. #ifdef _D3XP
  690. savefile->ReadInt( timeGroup );
  691. savefile->ReadBool( noGrab );
  692. savefile->ReadRenderEntity( xrayEntity );
  693. savefile->ReadInt( xrayEntityHandle );
  694. if ( xrayEntityHandle != -1 ) {
  695. xrayEntityHandle = gameRenderWorld->AddEntityDef( &xrayEntity );
  696. }
  697. savefile->ReadSkin( xraySkin );
  698. #endif
  699. savefile->ReadRenderEntity( renderEntity );
  700. savefile->ReadInt( modelDefHandle );
  701. savefile->ReadRefSound( refSound );
  702. savefile->ReadObject( reinterpret_cast<idClass *&>( bindMaster ) );
  703. savefile->ReadJoint( bindJoint );
  704. savefile->ReadInt( bindBody );
  705. savefile->ReadObject( reinterpret_cast<idClass *&>( teamMaster ) );
  706. savefile->ReadObject( reinterpret_cast<idClass *&>( teamChain ) );
  707. savefile->ReadStaticObject( defaultPhysicsObj );
  708. RestorePhysics( &defaultPhysicsObj );
  709. savefile->ReadInt( numPVSAreas );
  710. for( i = 0; i < MAX_PVS_AREAS; i++ ) {
  711. savefile->ReadInt( PVSAreas[ i ] );
  712. }
  713. bool readsignals;
  714. savefile->ReadBool( readsignals );
  715. if ( readsignals ) {
  716. signals = new signalList_t;
  717. for( i = 0; i < NUM_SIGNALS; i++ ) {
  718. savefile->ReadInt( num );
  719. signals->signal[ i ].SetNum( num );
  720. for( j = 0; j < num; j++ ) {
  721. savefile->ReadInt( signals->signal[ i ][ j ].threadnum );
  722. savefile->ReadString( funcname );
  723. signals->signal[ i ][ j ].function = gameLocal.program.FindFunction( funcname );
  724. if ( !signals->signal[ i ][ j ].function ) {
  725. savefile->Error( "Function '%s' not found", funcname.c_str() );
  726. }
  727. }
  728. }
  729. }
  730. savefile->ReadInt( mpGUIState );
  731. // restore must retrieve modelDefHandle from the renderer
  732. if ( modelDefHandle != -1 ) {
  733. modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  734. }
  735. //BC
  736. savefile->ReadBool(noGrab);
  737. savefile->ReadBool(isFrobbable);
  738. savefile->ReadInt(uiAlarmTimer);
  739. savefile->ReadInt(uiHackTimer);
  740. savefile->ReadInt(lastThrowTime);
  741. }
  742. /*
  743. ================
  744. idEntity::GetEntityDefName
  745. ================
  746. */
  747. const char * idEntity::GetEntityDefName( void ) const {
  748. if ( entityDefNumber < 0 ) {
  749. return "*unknown*";
  750. }
  751. return declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  752. }
  753. /*
  754. ================
  755. idEntity::SetName
  756. ================
  757. */
  758. void idEntity::SetName( const char *newname ) {
  759. if ( name.Length() ) {
  760. gameLocal.RemoveEntityFromHash( name.c_str(), this );
  761. gameLocal.program.SetEntity( name, NULL );
  762. }
  763. name = newname;
  764. if ( name.Length() ) {
  765. if ( ( name == "NULL" ) || ( name == "null_entity" ) ) {
  766. gameLocal.Error( "Cannot name entity '%s'. '%s' is reserved for script.", name.c_str(), name.c_str() );
  767. }
  768. gameLocal.AddEntityToHash( name.c_str(), this );
  769. gameLocal.program.SetEntity( name, this );
  770. }
  771. }
  772. /*
  773. ================
  774. idEntity::GetName
  775. ================
  776. */
  777. const char * idEntity::GetName( void ) const {
  778. return name.c_str();
  779. }
  780. /***********************************************************************
  781. Thinking
  782. ***********************************************************************/
  783. /*
  784. ================
  785. idEntity::Think
  786. ================
  787. */
  788. void idEntity::Think( void ) {
  789. RunPhysics();
  790. Present();
  791. }
  792. /*
  793. ================
  794. idEntity::DoDormantTests
  795. Monsters and other expensive entities that are completely closed
  796. off from the player can skip all of their work
  797. ================
  798. */
  799. bool idEntity::DoDormantTests( void ) {
  800. if ( fl.neverDormant ) {
  801. return false;
  802. }
  803. // if the monster area is not topologically connected to a player
  804. if ( !gameLocal.InPlayerConnectedArea( this ) ) {
  805. if ( dormantStart == 0 ) {
  806. dormantStart = gameLocal.time;
  807. }
  808. if ( gameLocal.time - dormantStart < DELAY_DORMANT_TIME ) {
  809. // just got closed off, don't go dormant yet
  810. return false;
  811. }
  812. return true;
  813. } else {
  814. // the monster area is topologically connected to a player, but if
  815. // the monster hasn't been woken up before, do the more precise PVS check
  816. if ( !fl.hasAwakened ) {
  817. if ( !gameLocal.InPlayerPVS( this ) ) {
  818. return true; // stay dormant
  819. }
  820. }
  821. // wake up
  822. dormantStart = 0;
  823. fl.hasAwakened = true; // only go dormant when area closed off now, not just out of PVS
  824. return false;
  825. }
  826. return false;
  827. }
  828. /*
  829. ================
  830. idEntity::CheckDormant
  831. Monsters and other expensive entities that are completely closed
  832. off from the player can skip all of their work
  833. ================
  834. */
  835. bool idEntity::CheckDormant( void ) {
  836. bool dormant;
  837. dormant = DoDormantTests();
  838. if ( dormant && !fl.isDormant ) {
  839. fl.isDormant = true;
  840. DormantBegin();
  841. } else if ( !dormant && fl.isDormant ) {
  842. fl.isDormant = false;
  843. DormantEnd();
  844. }
  845. return dormant;
  846. }
  847. /*
  848. ================
  849. idEntity::DormantBegin
  850. called when entity becomes dormant
  851. ================
  852. */
  853. void idEntity::DormantBegin( void ) {
  854. }
  855. /*
  856. ================
  857. idEntity::DormantEnd
  858. called when entity wakes from being dormant
  859. ================
  860. */
  861. void idEntity::DormantEnd( void ) {
  862. }
  863. /*
  864. ================
  865. idEntity::IsActive
  866. ================
  867. */
  868. bool idEntity::IsActive( void ) const {
  869. return activeNode.InList();
  870. }
  871. /*
  872. ================
  873. idEntity::BecomeActive
  874. ================
  875. */
  876. void idEntity::BecomeActive( int flags ) {
  877. if ( ( flags & TH_PHYSICS ) ) {
  878. // enable the team master if this entity is part of a physics team
  879. if ( teamMaster && teamMaster != this ) {
  880. teamMaster->BecomeActive( TH_PHYSICS );
  881. } else if ( !( thinkFlags & TH_PHYSICS ) ) {
  882. // if this is a pusher
  883. if ( physics->IsType( idPhysics_Parametric::Type ) || physics->IsType( idPhysics_Actor::Type ) ) {
  884. gameLocal.sortPushers = true;
  885. }
  886. }
  887. }
  888. int oldFlags = thinkFlags;
  889. thinkFlags |= flags;
  890. if ( thinkFlags ) {
  891. if ( !IsActive() ) {
  892. activeNode.AddToEnd( gameLocal.activeEntities );
  893. } else if ( !oldFlags ) {
  894. // we became inactive this frame, so we have to decrease the count of entities to deactivate
  895. gameLocal.numEntitiesToDeactivate--;
  896. }
  897. }
  898. }
  899. /*
  900. ================
  901. idEntity::BecomeInactive
  902. ================
  903. */
  904. void idEntity::BecomeInactive( int flags ) {
  905. if ( ( flags & TH_PHYSICS ) ) {
  906. // may only disable physics on a team master if no team members are running physics or bound to a joints
  907. if ( teamMaster == this ) {
  908. for ( idEntity *ent = teamMaster->teamChain; ent; ent = ent->teamChain ) {
  909. if ( ( ent->thinkFlags & TH_PHYSICS ) || ( ( ent->bindMaster == this ) && ( ent->bindJoint != INVALID_JOINT ) ) ) {
  910. flags &= ~TH_PHYSICS;
  911. break;
  912. }
  913. }
  914. }
  915. }
  916. if ( thinkFlags ) {
  917. thinkFlags &= ~flags;
  918. if ( !thinkFlags && IsActive() ) {
  919. gameLocal.numEntitiesToDeactivate++;
  920. }
  921. }
  922. if ( ( flags & TH_PHYSICS ) ) {
  923. // if this entity has a team master
  924. if ( teamMaster && teamMaster != this ) {
  925. // if the team master is at rest
  926. if ( teamMaster->IsAtRest() ) {
  927. teamMaster->BecomeInactive( TH_PHYSICS );
  928. }
  929. }
  930. }
  931. }
  932. /***********************************************************************
  933. Visuals
  934. ***********************************************************************/
  935. /*
  936. ================
  937. idEntity::SetShaderParm
  938. ================
  939. */
  940. void idEntity::SetShaderParm( int parmnum, float value ) {
  941. if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  942. gameLocal.Warning( "shader parm index (%d) out of range", parmnum );
  943. return;
  944. }
  945. renderEntity.shaderParms[ parmnum ] = value;
  946. UpdateVisuals();
  947. }
  948. /*
  949. ================
  950. idEntity::SetColor
  951. ================
  952. */
  953. void idEntity::SetColor( float red, float green, float blue ) {
  954. renderEntity.shaderParms[ SHADERPARM_RED ] = red;
  955. renderEntity.shaderParms[ SHADERPARM_GREEN ] = green;
  956. renderEntity.shaderParms[ SHADERPARM_BLUE ] = blue;
  957. UpdateVisuals();
  958. }
  959. /*
  960. ================
  961. idEntity::SetColor
  962. ================
  963. */
  964. void idEntity::SetColor( const idVec3 &color ) {
  965. SetColor( color[ 0 ], color[ 1 ], color[ 2 ] );
  966. UpdateVisuals();
  967. }
  968. /*
  969. ================
  970. idEntity::GetColor
  971. ================
  972. */
  973. void idEntity::GetColor( idVec3 &out ) const {
  974. out[ 0 ] = renderEntity.shaderParms[ SHADERPARM_RED ];
  975. out[ 1 ] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  976. out[ 2 ] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  977. }
  978. /*
  979. ================
  980. idEntity::SetColor
  981. ================
  982. */
  983. void idEntity::SetColor( const idVec4 &color ) {
  984. renderEntity.shaderParms[ SHADERPARM_RED ] = color[ 0 ];
  985. renderEntity.shaderParms[ SHADERPARM_GREEN ] = color[ 1 ];
  986. renderEntity.shaderParms[ SHADERPARM_BLUE ] = color[ 2 ];
  987. renderEntity.shaderParms[ SHADERPARM_ALPHA ] = color[ 3 ];
  988. UpdateVisuals();
  989. }
  990. /*
  991. ================
  992. idEntity::GetColor
  993. ================
  994. */
  995. void idEntity::GetColor( idVec4 &out ) const {
  996. out[ 0 ] = renderEntity.shaderParms[ SHADERPARM_RED ];
  997. out[ 1 ] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  998. out[ 2 ] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  999. out[ 3 ] = renderEntity.shaderParms[ SHADERPARM_ALPHA ];
  1000. }
  1001. /*
  1002. ================
  1003. idEntity::UpdateAnimationControllers
  1004. ================
  1005. */
  1006. bool idEntity::UpdateAnimationControllers( void ) {
  1007. // any ragdoll and IK animation controllers should be updated here
  1008. return false;
  1009. }
  1010. /*
  1011. ================
  1012. idEntity::SetModel
  1013. ================
  1014. */
  1015. void idEntity::SetModel( const char *modelname ) {
  1016. assert( modelname );
  1017. FreeModelDef();
  1018. renderEntity.hModel = renderModelManager->FindModel( modelname );
  1019. if ( renderEntity.hModel ) {
  1020. renderEntity.hModel->Reset();
  1021. }
  1022. renderEntity.callback = NULL;
  1023. renderEntity.numJoints = 0;
  1024. renderEntity.joints = NULL;
  1025. if ( renderEntity.hModel ) {
  1026. renderEntity.bounds = renderEntity.hModel->Bounds( &renderEntity );
  1027. } else {
  1028. renderEntity.bounds.Zero();
  1029. }
  1030. UpdateVisuals();
  1031. }
  1032. /*
  1033. ================
  1034. idEntity::SetSkin
  1035. ================
  1036. */
  1037. void idEntity::SetSkin( const idDeclSkin *skin ) {
  1038. renderEntity.customSkin = skin;
  1039. UpdateVisuals();
  1040. }
  1041. /*
  1042. ================
  1043. idEntity::GetSkin
  1044. ================
  1045. */
  1046. const idDeclSkin *idEntity::GetSkin( void ) const {
  1047. return renderEntity.customSkin;
  1048. }
  1049. /*
  1050. ================
  1051. idEntity::FreeModelDef
  1052. ================
  1053. */
  1054. void idEntity::FreeModelDef( void ) {
  1055. if ( modelDefHandle != -1 ) {
  1056. gameRenderWorld->FreeEntityDef( modelDefHandle );
  1057. modelDefHandle = -1;
  1058. }
  1059. }
  1060. /*
  1061. ================
  1062. idEntity::FreeLightDef
  1063. ================
  1064. */
  1065. void idEntity::FreeLightDef( void ) {
  1066. }
  1067. /*
  1068. ================
  1069. idEntity::IsHidden
  1070. ================
  1071. */
  1072. bool idEntity::IsHidden( void ) const {
  1073. return fl.hidden;
  1074. }
  1075. /*
  1076. ================
  1077. idEntity::Hide
  1078. ================
  1079. */
  1080. void idEntity::Hide( void ) {
  1081. if ( !IsHidden() ) {
  1082. fl.hidden = true;
  1083. FreeModelDef();
  1084. UpdateVisuals();
  1085. }
  1086. }
  1087. /*
  1088. ================
  1089. idEntity::Show
  1090. ================
  1091. */
  1092. void idEntity::Show( void ) {
  1093. if ( IsHidden() ) {
  1094. fl.hidden = false;
  1095. UpdateVisuals();
  1096. }
  1097. }
  1098. /*
  1099. ================
  1100. idEntity::UpdateModelTransform
  1101. ================
  1102. */
  1103. void idEntity::UpdateModelTransform( void ) {
  1104. idVec3 origin;
  1105. idMat3 axis;
  1106. if ( GetPhysicsToVisualTransform( origin, axis ) ) {
  1107. renderEntity.axis = axis * GetPhysics()->GetAxis();
  1108. renderEntity.origin = GetPhysics()->GetOrigin() + origin * renderEntity.axis;
  1109. } else {
  1110. renderEntity.axis = GetPhysics()->GetAxis();
  1111. renderEntity.origin = GetPhysics()->GetOrigin();
  1112. }
  1113. }
  1114. /*
  1115. ================
  1116. idEntity::UpdateModel
  1117. ================
  1118. */
  1119. void idEntity::UpdateModel( void ) {
  1120. #ifdef _D3XP
  1121. renderEntity.timeGroup = timeGroup;
  1122. #endif
  1123. UpdateModelTransform();
  1124. // check if the entity has an MD5 model
  1125. idAnimator *animator = GetAnimator();
  1126. if ( animator && animator->ModelHandle() ) {
  1127. // set the callback to update the joints
  1128. renderEntity.callback = idEntity::ModelCallback;
  1129. }
  1130. // set to invalid number to force an update the next time the PVS areas are retrieved
  1131. ClearPVSAreas();
  1132. // ensure that we call Present this frame
  1133. BecomeActive( TH_UPDATEVISUALS );
  1134. #ifdef _D3XP
  1135. // If the entity has an xray skin, go ahead and add it
  1136. if ( xraySkin != NULL ) {
  1137. xrayEntity = renderEntity;
  1138. xrayEntity.xrayIndex = 2;
  1139. xrayEntity.customSkin = xraySkin;
  1140. if ( xrayEntityHandle == -1 ) {
  1141. xrayEntityHandle = gameRenderWorld->AddEntityDef( &xrayEntity );
  1142. } else {
  1143. gameRenderWorld->UpdateEntityDef( xrayEntityHandle, &xrayEntity );
  1144. }
  1145. }
  1146. #endif
  1147. }
  1148. /*
  1149. ================
  1150. idEntity::UpdateVisuals
  1151. ================
  1152. */
  1153. void idEntity::UpdateVisuals( void ) {
  1154. UpdateModel();
  1155. UpdateSound();
  1156. }
  1157. /*
  1158. ================
  1159. idEntity::UpdatePVSAreas
  1160. ================
  1161. */
  1162. void idEntity::UpdatePVSAreas( void ) {
  1163. int localNumPVSAreas, localPVSAreas[32];
  1164. idBounds modelAbsBounds;
  1165. int i;
  1166. modelAbsBounds.FromTransformedBounds( renderEntity.bounds, renderEntity.origin, renderEntity.axis );
  1167. localNumPVSAreas = gameLocal.pvs.GetPVSAreas( modelAbsBounds, localPVSAreas, sizeof( localPVSAreas ) / sizeof( localPVSAreas[0] ) );
  1168. // FIXME: some particle systems may have huge bounds and end up in many PVS areas
  1169. // the first MAX_PVS_AREAS may not be visible to a network client and as a result the particle system may not show up when it should
  1170. if ( localNumPVSAreas > MAX_PVS_AREAS ) {
  1171. localNumPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( renderEntity.origin ).Expand( 64.0f ), localPVSAreas, sizeof( localPVSAreas ) / sizeof( localPVSAreas[0] ) );
  1172. }
  1173. for ( numPVSAreas = 0; numPVSAreas < MAX_PVS_AREAS && numPVSAreas < localNumPVSAreas; numPVSAreas++ ) {
  1174. PVSAreas[numPVSAreas] = localPVSAreas[numPVSAreas];
  1175. }
  1176. for( i = numPVSAreas; i < MAX_PVS_AREAS; i++ ) {
  1177. PVSAreas[ i ] = 0;
  1178. }
  1179. }
  1180. /*
  1181. ================
  1182. idEntity::UpdatePVSAreas
  1183. ================
  1184. */
  1185. void idEntity::UpdatePVSAreas( const idVec3 &pos ) {
  1186. int i;
  1187. numPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( pos ), PVSAreas, MAX_PVS_AREAS );
  1188. i = numPVSAreas;
  1189. while ( i < MAX_PVS_AREAS ) {
  1190. PVSAreas[ i++ ] = 0;
  1191. }
  1192. }
  1193. /*
  1194. ================
  1195. idEntity::GetNumPVSAreas
  1196. ================
  1197. */
  1198. int idEntity::GetNumPVSAreas( void ) {
  1199. if ( numPVSAreas < 0 ) {
  1200. UpdatePVSAreas();
  1201. }
  1202. return numPVSAreas;
  1203. }
  1204. /*
  1205. ================
  1206. idEntity::GetPVSAreas
  1207. ================
  1208. */
  1209. const int *idEntity::GetPVSAreas( void ) {
  1210. if ( numPVSAreas < 0 ) {
  1211. UpdatePVSAreas();
  1212. }
  1213. return PVSAreas;
  1214. }
  1215. /*
  1216. ================
  1217. idEntity::ClearPVSAreas
  1218. ================
  1219. */
  1220. void idEntity::ClearPVSAreas( void ) {
  1221. numPVSAreas = -1;
  1222. }
  1223. /*
  1224. ================
  1225. idEntity::PhysicsTeamInPVS
  1226. FIXME: for networking also return true if any of the entity shadows is in the PVS
  1227. ================
  1228. */
  1229. bool idEntity::PhysicsTeamInPVS( pvsHandle_t pvsHandle ) {
  1230. idEntity *part;
  1231. if ( teamMaster ) {
  1232. for ( part = teamMaster; part; part = part->teamChain ) {
  1233. if ( gameLocal.pvs.InCurrentPVS( pvsHandle, part->GetPVSAreas(), part->GetNumPVSAreas() ) ) {
  1234. return true;
  1235. }
  1236. }
  1237. } else {
  1238. return gameLocal.pvs.InCurrentPVS( pvsHandle, GetPVSAreas(), GetNumPVSAreas() );
  1239. }
  1240. return false;
  1241. }
  1242. /*
  1243. ==============
  1244. idEntity::ProjectOverlay
  1245. ==============
  1246. */
  1247. void idEntity::ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ) {
  1248. float s, c;
  1249. idMat3 axis, axistemp;
  1250. idVec3 localOrigin, localAxis[2];
  1251. idPlane localPlane[2];
  1252. // make sure the entity has a valid model handle
  1253. if ( modelDefHandle < 0 ) {
  1254. return;
  1255. }
  1256. // only do this on dynamic md5 models
  1257. if ( renderEntity.hModel->IsDynamicModel() != DM_CACHED ) {
  1258. return;
  1259. }
  1260. idMath::SinCos16( gameLocal.random.RandomFloat() * idMath::TWO_PI, s, c );
  1261. axis[2] = -dir;
  1262. axis[2].NormalVectors( axistemp[0], axistemp[1] );
  1263. axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * -s;
  1264. axis[1] = axistemp[ 0 ] * -s + axistemp[ 1 ] * -c;
  1265. renderEntity.axis.ProjectVector( origin - renderEntity.origin, localOrigin );
  1266. renderEntity.axis.ProjectVector( axis[0], localAxis[0] );
  1267. renderEntity.axis.ProjectVector( axis[1], localAxis[1] );
  1268. size = 1.0f / size;
  1269. localAxis[0] *= size;
  1270. localAxis[1] *= size;
  1271. localPlane[0] = localAxis[0];
  1272. localPlane[0][3] = -( localOrigin * localAxis[0] ) + 0.5f;
  1273. localPlane[1] = localAxis[1];
  1274. localPlane[1][3] = -( localOrigin * localAxis[1] ) + 0.5f;
  1275. const idMaterial *mtr = declManager->FindMaterial( material );
  1276. // project an overlay onto the model
  1277. gameRenderWorld->ProjectOverlay( modelDefHandle, localPlane, mtr );
  1278. // make sure non-animating models update their overlay
  1279. UpdateVisuals();
  1280. }
  1281. /*
  1282. ================
  1283. idEntity::Present
  1284. Present is called to allow entities to generate refEntities, lights, etc for the renderer.
  1285. ================
  1286. */
  1287. void idEntity::Present( void ) {
  1288. if ( !gameLocal.isNewFrame ) {
  1289. return;
  1290. }
  1291. // don't present to the renderer if the entity hasn't changed
  1292. if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  1293. return;
  1294. }
  1295. BecomeInactive( TH_UPDATEVISUALS );
  1296. // camera target for remote render views
  1297. if ( cameraTarget && gameLocal.InPlayerPVS( this ) ) {
  1298. renderEntity.remoteRenderView = cameraTarget->GetRenderView();
  1299. if ( spawnArgs.GetBool( "isfreezeframe", "0" ))
  1300. {
  1301. renderEntity.isFreezeFrame = 1;
  1302. }
  1303. }
  1304. // if set to invisible, skip
  1305. if ( !renderEntity.hModel || IsHidden() ) {
  1306. return;
  1307. }
  1308. // add to refresh list
  1309. if ( modelDefHandle == -1 ) {
  1310. modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  1311. } else {
  1312. gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  1313. }
  1314. }
  1315. /*
  1316. ================
  1317. idEntity::GetRenderEntity
  1318. ================
  1319. */
  1320. renderEntity_t *idEntity::GetRenderEntity( void ) {
  1321. return &renderEntity;
  1322. }
  1323. /*
  1324. ================
  1325. idEntity::GetModelDefHandle
  1326. ================
  1327. */
  1328. int idEntity::GetModelDefHandle( void ) {
  1329. return modelDefHandle;
  1330. }
  1331. /*
  1332. ================
  1333. idEntity::UpdateRenderEntity
  1334. ================
  1335. */
  1336. bool idEntity::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) {
  1337. if ( gameLocal.inCinematic && gameLocal.skipCinematic ) {
  1338. return false;
  1339. }
  1340. idAnimator *animator = GetAnimator();
  1341. if ( animator ) {
  1342. #ifdef _D3XP
  1343. SetTimeState ts( timeGroup );
  1344. #endif
  1345. return animator->CreateFrame( gameLocal.time, false );
  1346. }
  1347. return false;
  1348. }
  1349. /*
  1350. ================
  1351. idEntity::ModelCallback
  1352. NOTE: may not change the game state whatsoever!
  1353. ================
  1354. */
  1355. bool idEntity::ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) {
  1356. idEntity *ent;
  1357. ent = gameLocal.entities[ renderEntity->entityNum ];
  1358. if ( !ent ) {
  1359. gameLocal.Error( "idEntity::ModelCallback: callback with NULL game entity" );
  1360. }
  1361. return ent->UpdateRenderEntity( renderEntity, renderView );
  1362. }
  1363. /*
  1364. ================
  1365. idEntity::GetAnimator
  1366. Subclasses will be responsible for allocating animator.
  1367. ================
  1368. */
  1369. idAnimator *idEntity::GetAnimator( void ) {
  1370. return NULL;
  1371. }
  1372. /*
  1373. =============
  1374. idEntity::GetRenderView
  1375. This is used by remote camera views to look from an entity
  1376. =============
  1377. */
  1378. renderView_t *idEntity::GetRenderView( void ) {
  1379. if ( !renderView ) {
  1380. renderView = new renderView_t;
  1381. }
  1382. memset( renderView, 0, sizeof( *renderView ) );
  1383. renderView->vieworg = GetPhysics()->GetOrigin();
  1384. renderView->fov_x = 120;
  1385. renderView->fov_y = 120;
  1386. renderView->viewaxis = GetPhysics()->GetAxis();
  1387. // copy global shader parms
  1388. for( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  1389. renderView->shaderParms[ i ] = gameLocal.globalShaderParms[ i ];
  1390. }
  1391. renderView->globalMaterial = gameLocal.GetGlobalMaterial();
  1392. renderView->time = gameLocal.time;
  1393. return renderView;
  1394. }
  1395. /***********************************************************************
  1396. Sound
  1397. ***********************************************************************/
  1398. /*
  1399. ================
  1400. idEntity::CanPlayChatterSounds
  1401. Used for playing chatter sounds on monsters.
  1402. ================
  1403. */
  1404. bool idEntity::CanPlayChatterSounds( void ) const {
  1405. return true;
  1406. }
  1407. /*
  1408. ================
  1409. idEntity::StartSound
  1410. ================
  1411. */
  1412. bool idEntity::StartSound( const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length ) {
  1413. const idSoundShader *shader;
  1414. const char *sound;
  1415. if ( length ) {
  1416. *length = 0;
  1417. }
  1418. // we should ALWAYS be playing sounds from the def.
  1419. // hardcoded sounds MUST be avoided at all times because they won't get precached.
  1420. assert( idStr::Icmpn( soundName, "snd_", 4 ) == 0 );
  1421. if ( !spawnArgs.GetString( soundName, "", &sound ) ) {
  1422. return false;
  1423. }
  1424. if ( sound[0] == '\0' ) {
  1425. return false;
  1426. }
  1427. if ( !gameLocal.isNewFrame ) {
  1428. // don't play the sound, but don't report an error
  1429. return true;
  1430. }
  1431. shader = declManager->FindSound( sound );
  1432. return StartSoundShader( shader, channel, soundShaderFlags, broadcast, length );
  1433. }
  1434. /*
  1435. ================
  1436. idEntity::StartSoundShader
  1437. ================
  1438. */
  1439. bool idEntity::StartSoundShader( const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length ) {
  1440. float diversity;
  1441. int len;
  1442. if ( length ) {
  1443. *length = 0;
  1444. }
  1445. if ( !shader ) {
  1446. return false;
  1447. }
  1448. if ( !gameLocal.isNewFrame ) {
  1449. return true;
  1450. }
  1451. if ( gameLocal.isServer && broadcast ) {
  1452. idBitMsg msg;
  1453. byte msgBuf[MAX_EVENT_PARAM_SIZE];
  1454. msg.Init( msgBuf, sizeof( msgBuf ) );
  1455. msg.BeginWriting();
  1456. msg.WriteLong( gameLocal.ServerRemapDecl( -1, DECL_SOUND, shader->Index() ) );
  1457. msg.WriteByte( channel );
  1458. ServerSendEvent( EVENT_STARTSOUNDSHADER, &msg, false, -1 );
  1459. }
  1460. // set a random value for diversity unless one was parsed from the entity
  1461. if ( refSound.diversity < 0.0f ) {
  1462. diversity = gameLocal.random.RandomFloat();
  1463. } else {
  1464. diversity = refSound.diversity;
  1465. }
  1466. // if we don't have a soundEmitter allocated yet, get one now
  1467. if ( !refSound.referenceSound ) {
  1468. refSound.referenceSound = gameSoundWorld->AllocSoundEmitter();
  1469. }
  1470. UpdateSound();
  1471. len = refSound.referenceSound->StartSound( shader, channel, diversity, soundShaderFlags, !timeGroup /*_D3XP*/ );
  1472. if ( length ) {
  1473. *length = len;
  1474. }
  1475. // set reference to the sound for shader synced effects
  1476. renderEntity.referenceSound = refSound.referenceSound;
  1477. return true;
  1478. }
  1479. /*
  1480. ================
  1481. idEntity::StopSound
  1482. ================
  1483. */
  1484. void idEntity::StopSound( const s_channelType channel, bool broadcast ) {
  1485. if ( !gameLocal.isNewFrame ) {
  1486. return;
  1487. }
  1488. if ( gameLocal.isServer && broadcast ) {
  1489. idBitMsg msg;
  1490. byte msgBuf[MAX_EVENT_PARAM_SIZE];
  1491. msg.Init( msgBuf, sizeof( msgBuf ) );
  1492. msg.BeginWriting();
  1493. msg.WriteByte( channel );
  1494. ServerSendEvent( EVENT_STOPSOUNDSHADER, &msg, false, -1 );
  1495. }
  1496. if ( refSound.referenceSound ) {
  1497. refSound.referenceSound->StopSound( channel );
  1498. }
  1499. }
  1500. /*
  1501. ================
  1502. idEntity::SetSoundVolume
  1503. Must be called before starting a new sound.
  1504. ================
  1505. */
  1506. void idEntity::SetSoundVolume( float volume ) {
  1507. refSound.parms.volume = volume;
  1508. }
  1509. /*
  1510. ================
  1511. idEntity::UpdateSound
  1512. ================
  1513. */
  1514. void idEntity::UpdateSound( void ) {
  1515. if ( refSound.referenceSound ) {
  1516. idVec3 origin;
  1517. idMat3 axis;
  1518. if ( GetPhysicsToSoundTransform( origin, axis ) ) {
  1519. refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
  1520. } else {
  1521. refSound.origin = GetPhysics()->GetOrigin();
  1522. }
  1523. refSound.referenceSound->UpdateEmitter( refSound.origin, refSound.listenerId, &refSound.parms );
  1524. }
  1525. }
  1526. /*
  1527. ================
  1528. idEntity::GetListenerId
  1529. ================
  1530. */
  1531. int idEntity::GetListenerId( void ) const {
  1532. return refSound.listenerId;
  1533. }
  1534. /*
  1535. ================
  1536. idEntity::GetSoundEmitter
  1537. ================
  1538. */
  1539. idSoundEmitter *idEntity::GetSoundEmitter( void ) const {
  1540. return refSound.referenceSound;
  1541. }
  1542. /*
  1543. ================
  1544. idEntity::FreeSoundEmitter
  1545. ================
  1546. */
  1547. void idEntity::FreeSoundEmitter( bool immediate ) {
  1548. if ( refSound.referenceSound ) {
  1549. refSound.referenceSound->Free( immediate );
  1550. refSound.referenceSound = NULL;
  1551. }
  1552. }
  1553. /***********************************************************************
  1554. entity binding
  1555. ***********************************************************************/
  1556. /*
  1557. ================
  1558. idEntity::PreBind
  1559. ================
  1560. */
  1561. void idEntity::PreBind( void ) {
  1562. }
  1563. /*
  1564. ================
  1565. idEntity::PostBind
  1566. ================
  1567. */
  1568. void idEntity::PostBind( void ) {
  1569. }
  1570. /*
  1571. ================
  1572. idEntity::PreUnbind
  1573. ================
  1574. */
  1575. void idEntity::PreUnbind( void ) {
  1576. }
  1577. /*
  1578. ================
  1579. idEntity::PostUnbind
  1580. ================
  1581. */
  1582. void idEntity::PostUnbind( void ) {
  1583. }
  1584. /*
  1585. ================
  1586. idEntity::InitBind
  1587. ================
  1588. */
  1589. bool idEntity::InitBind( idEntity *master ) {
  1590. if ( master == this ) {
  1591. gameLocal.Error( "Tried to bind an object to itself." );
  1592. return false;
  1593. }
  1594. if ( this == gameLocal.world ) {
  1595. gameLocal.Error( "Tried to bind world to another entity" );
  1596. return false;
  1597. }
  1598. // unbind myself from my master
  1599. Unbind();
  1600. // add any bind constraints to an articulated figure
  1601. if ( master && IsType( idAFEntity_Base::Type ) ) {
  1602. static_cast<idAFEntity_Base *>(this)->AddBindConstraints();
  1603. }
  1604. if ( !master || master == gameLocal.world ) {
  1605. // this can happen in scripts, so safely exit out.
  1606. return false;
  1607. }
  1608. return true;
  1609. }
  1610. /*
  1611. ================
  1612. idEntity::FinishBind
  1613. ================
  1614. */
  1615. void idEntity::FinishBind( void ) {
  1616. // set the master on the physics object
  1617. physics->SetMaster( bindMaster, fl.bindOrientated );
  1618. // We are now separated from our previous team and are either
  1619. // an individual, or have a team of our own. Now we can join
  1620. // the new bindMaster's team. Bindmaster must be set before
  1621. // joining the team, or we will be placed in the wrong position
  1622. // on the team.
  1623. JoinTeam( bindMaster );
  1624. // if our bindMaster is enabled during a cinematic, we must be, too
  1625. cinematic = bindMaster->cinematic;
  1626. // make sure the team master is active so that physics get run
  1627. teamMaster->BecomeActive( TH_PHYSICS );
  1628. }
  1629. /*
  1630. ================
  1631. idEntity::Bind
  1632. bind relative to the visual position of the master
  1633. ================
  1634. */
  1635. void idEntity::Bind( idEntity *master, bool orientated ) {
  1636. if ( !InitBind( master ) ) {
  1637. return;
  1638. }
  1639. PreBind();
  1640. bindJoint = INVALID_JOINT;
  1641. bindBody = -1;
  1642. bindMaster = master;
  1643. fl.bindOrientated = orientated;
  1644. FinishBind();
  1645. PostBind( );
  1646. }
  1647. /*
  1648. ================
  1649. idEntity::BindToJoint
  1650. bind relative to a joint of the md5 model used by the master
  1651. ================
  1652. */
  1653. void idEntity::BindToJoint( idEntity *master, const char *jointname, bool orientated ) {
  1654. jointHandle_t jointnum;
  1655. idAnimator *masterAnimator;
  1656. if ( !InitBind( master ) ) {
  1657. return;
  1658. }
  1659. masterAnimator = master->GetAnimator();
  1660. if ( !masterAnimator ) {
  1661. gameLocal.Warning( "idEntity::BindToJoint: entity '%s' cannot support skeletal models.", master->GetName() );
  1662. return;
  1663. }
  1664. jointnum = masterAnimator->GetJointHandle( jointname );
  1665. if ( jointnum == INVALID_JOINT ) {
  1666. gameLocal.Warning( "idEntity::BindToJoint: joint '%s' not found on entity '%s'.", jointname, master->GetName() );
  1667. }
  1668. PreBind();
  1669. bindJoint = jointnum;
  1670. bindBody = -1;
  1671. bindMaster = master;
  1672. fl.bindOrientated = orientated;
  1673. FinishBind();
  1674. PostBind();
  1675. }
  1676. /*
  1677. ================
  1678. idEntity::BindToJoint
  1679. bind relative to a joint of the md5 model used by the master
  1680. ================
  1681. */
  1682. void idEntity::BindToJoint( idEntity *master, jointHandle_t jointnum, bool orientated ) {
  1683. if ( !InitBind( master ) ) {
  1684. return;
  1685. }
  1686. PreBind();
  1687. bindJoint = jointnum;
  1688. bindBody = -1;
  1689. bindMaster = master;
  1690. fl.bindOrientated = orientated;
  1691. FinishBind();
  1692. PostBind();
  1693. }
  1694. /*
  1695. ================
  1696. idEntity::BindToBody
  1697. bind relative to a collision model used by the physics of the master
  1698. ================
  1699. */
  1700. void idEntity::BindToBody( idEntity *master, int bodyId, bool orientated ) {
  1701. if ( !InitBind( master ) ) {
  1702. return;
  1703. }
  1704. if ( bodyId < 0 ) {
  1705. gameLocal.Warning( "idEntity::BindToBody: body '%d' not found.", bodyId );
  1706. }
  1707. PreBind();
  1708. bindJoint = INVALID_JOINT;
  1709. bindBody = bodyId;
  1710. bindMaster = master;
  1711. fl.bindOrientated = orientated;
  1712. FinishBind();
  1713. PostBind();
  1714. }
  1715. /*
  1716. ================
  1717. idEntity::Unbind
  1718. ================
  1719. */
  1720. void idEntity::Unbind( void ) {
  1721. idEntity * prev;
  1722. idEntity * next;
  1723. idEntity * last;
  1724. idEntity * ent;
  1725. // remove any bind constraints from an articulated figure
  1726. if ( IsType( idAFEntity_Base::Type ) ) {
  1727. static_cast<idAFEntity_Base *>(this)->RemoveBindConstraints();
  1728. }
  1729. if ( !bindMaster ) {
  1730. return;
  1731. }
  1732. if ( !teamMaster ) {
  1733. // Teammaster already has been freed
  1734. bindMaster = NULL;
  1735. return;
  1736. }
  1737. PreUnbind();
  1738. if ( physics ) {
  1739. physics->SetMaster( NULL, fl.bindOrientated );
  1740. }
  1741. // We're still part of a team, so that means I have to extricate myself
  1742. // and any entities that are bound to me from the old team.
  1743. // Find the node previous to me in the team
  1744. prev = teamMaster;
  1745. for( ent = teamMaster->teamChain; ent && ( ent != this ); ent = ent->teamChain ) {
  1746. prev = ent;
  1747. }
  1748. assert( ent == this ); // If ent is not pointing to this, then something is very wrong.
  1749. // Find the last node in my team that is bound to me.
  1750. // Also find the first node not bound to me, if one exists.
  1751. last = this;
  1752. for( next = teamChain; next != NULL; next = next->teamChain ) {
  1753. if ( !next->IsBoundTo( this ) ) {
  1754. break;
  1755. }
  1756. // Tell them I'm now the teamMaster
  1757. next->teamMaster = this;
  1758. last = next;
  1759. }
  1760. // disconnect the last member of our team from the old team
  1761. last->teamChain = NULL;
  1762. // connect up the previous member of the old team to the node that
  1763. // follow the last node bound to me (if one exists).
  1764. if ( teamMaster != this ) {
  1765. prev->teamChain = next;
  1766. if ( !next && ( teamMaster == prev ) ) {
  1767. prev->teamMaster = NULL;
  1768. }
  1769. } else if ( next ) {
  1770. // If we were the teamMaster, then the nodes that were not bound to me are now
  1771. // a disconnected chain. Make them into their own team.
  1772. for( ent = next; ent->teamChain != NULL; ent = ent->teamChain ) {
  1773. ent->teamMaster = next;
  1774. }
  1775. next->teamMaster = next;
  1776. }
  1777. // If we don't have anyone on our team, then clear the team variables.
  1778. if ( teamChain ) {
  1779. // make myself my own team
  1780. teamMaster = this;
  1781. } else {
  1782. // no longer a team
  1783. teamMaster = NULL;
  1784. }
  1785. bindJoint = INVALID_JOINT;
  1786. bindBody = -1;
  1787. bindMaster = NULL;
  1788. PostUnbind();
  1789. }
  1790. /*
  1791. ================
  1792. idEntity::RemoveBinds
  1793. ================
  1794. */
  1795. void idEntity::RemoveBinds( void ) {
  1796. idEntity *ent;
  1797. idEntity *next;
  1798. for( ent = teamChain; ent != NULL; ent = next ) {
  1799. next = ent->teamChain;
  1800. if ( ent->bindMaster == this ) {
  1801. ent->Unbind();
  1802. ent->PostEventMS( &EV_Remove, 0 );
  1803. next = teamChain;
  1804. }
  1805. }
  1806. }
  1807. /*
  1808. ================
  1809. idEntity::IsBound
  1810. ================
  1811. */
  1812. bool idEntity::IsBound( void ) const {
  1813. if ( bindMaster ) {
  1814. return true;
  1815. }
  1816. return false;
  1817. }
  1818. /*
  1819. ================
  1820. idEntity::IsBoundTo
  1821. ================
  1822. */
  1823. bool idEntity::IsBoundTo( idEntity *master ) const {
  1824. idEntity *ent;
  1825. if ( !bindMaster ) {
  1826. return false;
  1827. }
  1828. for ( ent = bindMaster; ent != NULL; ent = ent->bindMaster ) {
  1829. if ( ent == master ) {
  1830. return true;
  1831. }
  1832. }
  1833. return false;
  1834. }
  1835. /*
  1836. ================
  1837. idEntity::GetBindMaster
  1838. ================
  1839. */
  1840. idEntity *idEntity::GetBindMaster( void ) const {
  1841. return bindMaster;
  1842. }
  1843. /*
  1844. ================
  1845. idEntity::GetBindJoint
  1846. ================
  1847. */
  1848. jointHandle_t idEntity::GetBindJoint( void ) const {
  1849. return bindJoint;
  1850. }
  1851. /*
  1852. ================
  1853. idEntity::GetBindBody
  1854. ================
  1855. */
  1856. int idEntity::GetBindBody( void ) const {
  1857. return bindBody;
  1858. }
  1859. /*
  1860. ================
  1861. idEntity::GetTeamMaster
  1862. ================
  1863. */
  1864. idEntity *idEntity::GetTeamMaster( void ) const {
  1865. return teamMaster;
  1866. }
  1867. /*
  1868. ================
  1869. idEntity::GetNextTeamEntity
  1870. ================
  1871. */
  1872. idEntity *idEntity::GetNextTeamEntity( void ) const {
  1873. return teamChain;
  1874. }
  1875. /*
  1876. =====================
  1877. idEntity::ConvertLocalToWorldTransform
  1878. =====================
  1879. */
  1880. void idEntity::ConvertLocalToWorldTransform( idVec3 &offset, idMat3 &axis ) {
  1881. UpdateModelTransform();
  1882. offset = renderEntity.origin + offset * renderEntity.axis;
  1883. axis *= renderEntity.axis;
  1884. }
  1885. /*
  1886. ================
  1887. idEntity::GetLocalVector
  1888. Takes a vector in worldspace and transforms it into the parent
  1889. object's localspace.
  1890. Note: Does not take origin into acount. Use getLocalCoordinate to
  1891. convert coordinates.
  1892. ================
  1893. */
  1894. idVec3 idEntity::GetLocalVector( const idVec3 &vec ) const {
  1895. idVec3 pos;
  1896. if ( !bindMaster ) {
  1897. return vec;
  1898. }
  1899. idVec3 masterOrigin;
  1900. idMat3 masterAxis;
  1901. GetMasterPosition( masterOrigin, masterAxis );
  1902. masterAxis.ProjectVector( vec, pos );
  1903. return pos;
  1904. }
  1905. /*
  1906. ================
  1907. idEntity::GetLocalCoordinates
  1908. Takes a vector in world coordinates and transforms it into the parent
  1909. object's local coordinates.
  1910. ================
  1911. */
  1912. idVec3 idEntity::GetLocalCoordinates( const idVec3 &vec ) const {
  1913. idVec3 pos;
  1914. if ( !bindMaster ) {
  1915. return vec;
  1916. }
  1917. idVec3 masterOrigin;
  1918. idMat3 masterAxis;
  1919. GetMasterPosition( masterOrigin, masterAxis );
  1920. masterAxis.ProjectVector( vec - masterOrigin, pos );
  1921. return pos;
  1922. }
  1923. /*
  1924. ================
  1925. idEntity::GetWorldVector
  1926. Takes a vector in the parent object's local coordinates and transforms
  1927. it into world coordinates.
  1928. Note: Does not take origin into acount. Use getWorldCoordinate to
  1929. convert coordinates.
  1930. ================
  1931. */
  1932. idVec3 idEntity::GetWorldVector( const idVec3 &vec ) const {
  1933. idVec3 pos;
  1934. if ( !bindMaster ) {
  1935. return vec;
  1936. }
  1937. idVec3 masterOrigin;
  1938. idMat3 masterAxis;
  1939. GetMasterPosition( masterOrigin, masterAxis );
  1940. masterAxis.UnprojectVector( vec, pos );
  1941. return pos;
  1942. }
  1943. /*
  1944. ================
  1945. idEntity::GetWorldCoordinates
  1946. Takes a vector in the parent object's local coordinates and transforms
  1947. it into world coordinates.
  1948. ================
  1949. */
  1950. idVec3 idEntity::GetWorldCoordinates( const idVec3 &vec ) const {
  1951. idVec3 pos;
  1952. if ( !bindMaster ) {
  1953. return vec;
  1954. }
  1955. idVec3 masterOrigin;
  1956. idMat3 masterAxis;
  1957. GetMasterPosition( masterOrigin, masterAxis );
  1958. masterAxis.UnprojectVector( vec, pos );
  1959. pos += masterOrigin;
  1960. return pos;
  1961. }
  1962. /*
  1963. ================
  1964. idEntity::GetMasterPosition
  1965. ================
  1966. */
  1967. bool idEntity::GetMasterPosition( idVec3 &masterOrigin, idMat3 &masterAxis ) const {
  1968. idVec3 localOrigin;
  1969. idMat3 localAxis;
  1970. idAnimator *masterAnimator;
  1971. if ( bindMaster ) {
  1972. // if bound to a joint of an animated model
  1973. if ( bindJoint != INVALID_JOINT ) {
  1974. masterAnimator = bindMaster->GetAnimator();
  1975. if ( !masterAnimator ) {
  1976. masterOrigin = vec3_origin;
  1977. masterAxis = mat3_identity;
  1978. return false;
  1979. } else {
  1980. masterAnimator->GetJointTransform( bindJoint, gameLocal.time, masterOrigin, masterAxis );
  1981. masterAxis *= bindMaster->renderEntity.axis;
  1982. masterOrigin = bindMaster->renderEntity.origin + masterOrigin * bindMaster->renderEntity.axis;
  1983. }
  1984. } else if ( bindBody >= 0 && bindMaster->GetPhysics() ) {
  1985. masterOrigin = bindMaster->GetPhysics()->GetOrigin( bindBody );
  1986. masterAxis = bindMaster->GetPhysics()->GetAxis( bindBody );
  1987. } else {
  1988. masterOrigin = bindMaster->renderEntity.origin;
  1989. masterAxis = bindMaster->renderEntity.axis;
  1990. }
  1991. return true;
  1992. } else {
  1993. masterOrigin = vec3_origin;
  1994. masterAxis = mat3_identity;
  1995. return false;
  1996. }
  1997. }
  1998. /*
  1999. ================
  2000. idEntity::GetWorldVelocities
  2001. ================
  2002. */
  2003. void idEntity::GetWorldVelocities( idVec3 &linearVelocity, idVec3 &angularVelocity ) const {
  2004. linearVelocity = physics->GetLinearVelocity();
  2005. angularVelocity = physics->GetAngularVelocity();
  2006. if ( bindMaster ) {
  2007. idVec3 masterOrigin, masterLinearVelocity, masterAngularVelocity;
  2008. idMat3 masterAxis;
  2009. // get position of master
  2010. GetMasterPosition( masterOrigin, masterAxis );
  2011. // get master velocities
  2012. bindMaster->GetWorldVelocities( masterLinearVelocity, masterAngularVelocity );
  2013. // linear velocity relative to master plus master linear and angular velocity
  2014. linearVelocity = linearVelocity * masterAxis + masterLinearVelocity +
  2015. masterAngularVelocity.Cross( GetPhysics()->GetOrigin() - masterOrigin );
  2016. }
  2017. }
  2018. /*
  2019. ================
  2020. idEntity::JoinTeam
  2021. ================
  2022. */
  2023. void idEntity::JoinTeam( idEntity *teammember ) {
  2024. idEntity *ent;
  2025. idEntity *master;
  2026. idEntity *prev;
  2027. idEntity *next;
  2028. // if we're already on a team, quit it so we can join this one
  2029. if ( teamMaster && ( teamMaster != this ) ) {
  2030. QuitTeam();
  2031. }
  2032. assert( teammember );
  2033. if ( teammember == this ) {
  2034. teamMaster = this;
  2035. return;
  2036. }
  2037. // check if our new team mate is already on a team
  2038. master = teammember->teamMaster;
  2039. if ( !master ) {
  2040. // he's not on a team, so he's the new teamMaster
  2041. master = teammember;
  2042. teammember->teamMaster = teammember;
  2043. teammember->teamChain = this;
  2044. // make anyone who's bound to me part of the new team
  2045. for( ent = teamChain; ent != NULL; ent = ent->teamChain ) {
  2046. ent->teamMaster = master;
  2047. }
  2048. } else {
  2049. // skip past the chain members bound to the entity we're teaming up with
  2050. prev = teammember;
  2051. next = teammember->teamChain;
  2052. if ( bindMaster ) {
  2053. // if we have a bindMaster, join after any entities bound to the entity
  2054. // we're joining
  2055. while( next && next->IsBoundTo( teammember ) ) {
  2056. prev = next;
  2057. next = next->teamChain;
  2058. }
  2059. } else {
  2060. // if we're not bound to someone, then put us at the end of the team
  2061. while( next ) {
  2062. prev = next;
  2063. next = next->teamChain;
  2064. }
  2065. }
  2066. // make anyone who's bound to me part of the new team and
  2067. // also find the last member of my team
  2068. for( ent = this; ent->teamChain != NULL; ent = ent->teamChain ) {
  2069. ent->teamChain->teamMaster = master;
  2070. }
  2071. prev->teamChain = this;
  2072. ent->teamChain = next;
  2073. }
  2074. teamMaster = master;
  2075. // reorder the active entity list
  2076. gameLocal.sortTeamMasters = true;
  2077. }
  2078. /*
  2079. ================
  2080. idEntity::QuitTeam
  2081. ================
  2082. */
  2083. void idEntity::QuitTeam( void ) {
  2084. idEntity *ent;
  2085. if ( !teamMaster ) {
  2086. return;
  2087. }
  2088. // check if I'm the teamMaster
  2089. if ( teamMaster == this ) {
  2090. // do we have more than one teammate?
  2091. if ( !teamChain->teamChain ) {
  2092. // no, break up the team
  2093. teamChain->teamMaster = NULL;
  2094. } else {
  2095. // yes, so make the first teammate the teamMaster
  2096. for( ent = teamChain; ent; ent = ent->teamChain ) {
  2097. ent->teamMaster = teamChain;
  2098. }
  2099. }
  2100. } else {
  2101. assert( teamMaster );
  2102. assert( teamMaster->teamChain );
  2103. // find the previous member of the teamChain
  2104. ent = teamMaster;
  2105. while( ent->teamChain != this ) {
  2106. assert( ent->teamChain ); // this should never happen
  2107. ent = ent->teamChain;
  2108. }
  2109. // remove this from the teamChain
  2110. ent->teamChain = teamChain;
  2111. // if no one is left on the team, break it up
  2112. if ( !teamMaster->teamChain ) {
  2113. teamMaster->teamMaster = NULL;
  2114. }
  2115. }
  2116. teamMaster = NULL;
  2117. teamChain = NULL;
  2118. }
  2119. /***********************************************************************
  2120. Physics.
  2121. ***********************************************************************/
  2122. /*
  2123. ================
  2124. idEntity::InitDefaultPhysics
  2125. ================
  2126. */
  2127. void idEntity::InitDefaultPhysics( const idVec3 &origin, const idMat3 &axis ) {
  2128. const char *temp;
  2129. idClipModel *clipModel = NULL;
  2130. // check if a clipmodel key/value pair is set
  2131. if ( spawnArgs.GetString( "clipmodel", "", &temp ) ) {
  2132. if ( idClipModel::CheckModel( temp ) ) {
  2133. clipModel = new idClipModel( temp );
  2134. }
  2135. }
  2136. if ( !spawnArgs.GetBool( "noclipmodel", "0" ) ) {
  2137. // check if mins/maxs or size key/value pairs are set
  2138. if ( !clipModel ) {
  2139. idVec3 size;
  2140. idBounds bounds;
  2141. bool setClipModel = false;
  2142. if ( spawnArgs.GetVector( "mins", NULL, bounds[0] ) &&
  2143. spawnArgs.GetVector( "maxs", NULL, bounds[1] ) ) {
  2144. setClipModel = true;
  2145. if ( bounds[0][0] > bounds[1][0] || bounds[0][1] > bounds[1][1] || bounds[0][2] > bounds[1][2] ) {
  2146. gameLocal.Error( "Invalid bounds '%s'-'%s' on entity '%s'", bounds[0].ToString(), bounds[1].ToString(), name.c_str() );
  2147. }
  2148. } else if ( spawnArgs.GetVector( "size", NULL, size ) ) {
  2149. if ( ( size.x < 0.0f ) || ( size.y < 0.0f ) || ( size.z < 0.0f ) ) {
  2150. gameLocal.Error( "Invalid size '%s' on entity '%s'", size.ToString(), name.c_str() );
  2151. }
  2152. bounds[0].Set( size.x * -0.5f, size.y * -0.5f, 0.0f );
  2153. bounds[1].Set( size.x * 0.5f, size.y * 0.5f, size.z );
  2154. setClipModel = true;
  2155. }
  2156. if ( setClipModel ) {
  2157. int numSides;
  2158. idTraceModel trm;
  2159. if ( spawnArgs.GetInt( "cylinder", "0", numSides ) && numSides > 0 ) {
  2160. trm.SetupCylinder( bounds, numSides < 3 ? 3 : numSides );
  2161. } else if ( spawnArgs.GetInt( "cone", "0", numSides ) && numSides > 0 ) {
  2162. trm.SetupCone( bounds, numSides < 3 ? 3 : numSides );
  2163. } else {
  2164. trm.SetupBox( bounds );
  2165. }
  2166. clipModel = new idClipModel( trm );
  2167. }
  2168. }
  2169. // check if the visual model can be used as collision model
  2170. if ( !clipModel ) {
  2171. temp = spawnArgs.GetString( "model" );
  2172. if ( ( temp != NULL ) && ( *temp != 0 ) ) {
  2173. if ( idClipModel::CheckModel( temp ) ) {
  2174. clipModel = new idClipModel( temp );
  2175. }
  2176. }
  2177. }
  2178. }
  2179. defaultPhysicsObj.SetSelf( this );
  2180. defaultPhysicsObj.SetClipModel( clipModel, 1.0f );
  2181. defaultPhysicsObj.SetOrigin( origin );
  2182. defaultPhysicsObj.SetAxis( axis );
  2183. physics = &defaultPhysicsObj;
  2184. }
  2185. /*
  2186. ================
  2187. idEntity::SetPhysics
  2188. ================
  2189. */
  2190. void idEntity::SetPhysics( idPhysics *phys ) {
  2191. // clear any contacts the current physics object has
  2192. if ( physics ) {
  2193. physics->ClearContacts();
  2194. }
  2195. // set new physics object or set the default physics if NULL
  2196. if ( phys != NULL ) {
  2197. defaultPhysicsObj.SetClipModel( NULL, 1.0f );
  2198. physics = phys;
  2199. physics->Activate();
  2200. } else {
  2201. physics = &defaultPhysicsObj;
  2202. }
  2203. physics->UpdateTime( gameLocal.time );
  2204. physics->SetMaster( bindMaster, fl.bindOrientated );
  2205. }
  2206. /*
  2207. ================
  2208. idEntity::RestorePhysics
  2209. ================
  2210. */
  2211. void idEntity::RestorePhysics( idPhysics *phys ) {
  2212. assert( phys != NULL );
  2213. // restore physics pointer
  2214. physics = phys;
  2215. }
  2216. /*
  2217. ================
  2218. idEntity::GetPhysics
  2219. ================
  2220. */
  2221. idPhysics *idEntity::GetPhysics( void ) const {
  2222. return physics;
  2223. }
  2224. /*
  2225. ================
  2226. idEntity::RunPhysics
  2227. ================
  2228. */
  2229. bool idEntity::RunPhysics( void ) {
  2230. int i, reachedTime, startTime, endTime;
  2231. idEntity * part, *blockedPart, *blockingEntity;
  2232. trace_t results;
  2233. bool moved;
  2234. // don't run physics if not enabled
  2235. if ( !( thinkFlags & TH_PHYSICS ) ) {
  2236. // however do update any animation controllers
  2237. if ( UpdateAnimationControllers() ) {
  2238. BecomeActive( TH_ANIMATE );
  2239. }
  2240. return false;
  2241. }
  2242. // if this entity is a team slave don't do anything because the team master will handle everything
  2243. if ( teamMaster && teamMaster != this ) {
  2244. return false;
  2245. }
  2246. startTime = gameLocal.previousTime;
  2247. endTime = gameLocal.time;
  2248. gameLocal.push.InitSavingPushedEntityPositions();
  2249. blockedPart = NULL;
  2250. // save the physics state of the whole team and disable the team for collision detection
  2251. for ( part = this; part != NULL; part = part->teamChain ) {
  2252. if ( part->physics ) {
  2253. if ( !part->fl.solidForTeam ) {
  2254. part->physics->DisableClip();
  2255. }
  2256. part->physics->SaveState();
  2257. }
  2258. }
  2259. // move the whole team
  2260. for ( part = this; part != NULL; part = part->teamChain ) {
  2261. if ( part->physics ) {
  2262. // run physics
  2263. moved = part->physics->Evaluate( endTime - startTime, endTime );
  2264. // check if the object is blocked
  2265. blockingEntity = part->physics->GetBlockingEntity();
  2266. if ( blockingEntity ) {
  2267. blockedPart = part;
  2268. break;
  2269. }
  2270. // if moved or forced to update the visual position and orientation from the physics
  2271. if ( moved || part->fl.forcePhysicsUpdate ) {
  2272. part->UpdateFromPhysics( false );
  2273. }
  2274. // update any animation controllers here so an entity bound
  2275. // to a joint of this entity gets the correct position
  2276. if ( part->UpdateAnimationControllers() ) {
  2277. part->BecomeActive( TH_ANIMATE );
  2278. }
  2279. }
  2280. }
  2281. // enable the whole team for collision detection
  2282. for ( part = this; part != NULL; part = part->teamChain ) {
  2283. if ( part->physics ) {
  2284. if ( !part->fl.solidForTeam ) {
  2285. part->physics->EnableClip();
  2286. }
  2287. }
  2288. }
  2289. // if one of the team entities is a pusher and blocked
  2290. if ( blockedPart ) {
  2291. // move the parts back to the previous position
  2292. for ( part = this; part != blockedPart; part = part->teamChain ) {
  2293. if ( part->physics ) {
  2294. // restore the physics state
  2295. part->physics->RestoreState();
  2296. // move back the visual position and orientation
  2297. part->UpdateFromPhysics( true );
  2298. }
  2299. }
  2300. for ( part = this; part != NULL; part = part->teamChain ) {
  2301. if ( part->physics ) {
  2302. // update the physics time without moving
  2303. part->physics->UpdateTime( endTime );
  2304. }
  2305. }
  2306. // restore the positions of any pushed entities
  2307. gameLocal.push.RestorePushedEntityPositions();
  2308. if ( gameLocal.isClient ) {
  2309. return false;
  2310. }
  2311. // if the master pusher has a "blocked" function, call it
  2312. Signal( SIG_BLOCKED );
  2313. ProcessEvent( &EV_TeamBlocked, blockedPart, blockingEntity );
  2314. // call the blocked function on the blocked part
  2315. blockedPart->ProcessEvent( &EV_PartBlocked, blockingEntity );
  2316. return false;
  2317. }
  2318. // set pushed
  2319. for ( i = 0; i < gameLocal.push.GetNumPushedEntities(); i++ ) {
  2320. idEntity *ent = gameLocal.push.GetPushedEntity( i );
  2321. ent->physics->SetPushed( endTime - startTime );
  2322. }
  2323. //BC commenting this out might break everything.
  2324. //if ( gameLocal.isClient )
  2325. {
  2326. //return true;
  2327. }
  2328. // post reached event if the current time is at or past the end point of the motion
  2329. for ( part = this; part != NULL; part = part->teamChain ) {
  2330. if ( part->physics )
  2331. {
  2332. reachedTime = part->physics->GetLinearEndTime();
  2333. //gameLocal.Printf(" Starttime: %d reachedTime: %d endTime: %d\n", startTime, reachedTime, endTime);
  2334. if ( startTime < reachedTime && endTime >= reachedTime ) {
  2335. part->ProcessEvent( &EV_ReachedPos );
  2336. }
  2337. reachedTime = part->physics->GetAngularEndTime();
  2338. if ( startTime < reachedTime && endTime >= reachedTime ) {
  2339. part->ProcessEvent( &EV_ReachedAng );
  2340. }
  2341. }
  2342. }
  2343. return true;
  2344. }
  2345. /*
  2346. ================
  2347. idEntity::UpdateFromPhysics
  2348. ================
  2349. */
  2350. void idEntity::UpdateFromPhysics( bool moveBack ) {
  2351. if ( IsType( idActor::Type ) ) {
  2352. idActor *actor = static_cast<idActor *>( this );
  2353. // set master delta angles for actors
  2354. if ( GetBindMaster() ) {
  2355. idAngles delta = actor->GetDeltaViewAngles();
  2356. if ( moveBack ) {
  2357. delta.yaw -= static_cast<idPhysics_Actor *>(physics)->GetMasterDeltaYaw();
  2358. } else {
  2359. delta.yaw += static_cast<idPhysics_Actor *>(physics)->GetMasterDeltaYaw();
  2360. }
  2361. actor->SetDeltaViewAngles( delta );
  2362. }
  2363. }
  2364. UpdateVisuals();
  2365. }
  2366. /*
  2367. ================
  2368. idEntity::SetOrigin
  2369. ================
  2370. */
  2371. void idEntity::SetOrigin( const idVec3 &org ) {
  2372. GetPhysics()->SetOrigin( org );
  2373. UpdateVisuals();
  2374. }
  2375. /*
  2376. ================
  2377. idEntity::SetAxis
  2378. ================
  2379. */
  2380. void idEntity::SetAxis( const idMat3 &axis ) {
  2381. if ( GetPhysics()->IsType( idPhysics_Actor::Type ) ) {
  2382. static_cast<idActor *>(this)->viewAxis = axis;
  2383. } else {
  2384. GetPhysics()->SetAxis( axis );
  2385. }
  2386. UpdateVisuals();
  2387. }
  2388. /*
  2389. ================
  2390. idEntity::SetAngles
  2391. ================
  2392. */
  2393. void idEntity::SetAngles( const idAngles &ang ) {
  2394. SetAxis( ang.ToMat3() );
  2395. }
  2396. /*
  2397. ================
  2398. idEntity::GetFloorPos
  2399. ================
  2400. */
  2401. bool idEntity::GetFloorPos( float max_dist, idVec3 &floorpos ) const {
  2402. trace_t result;
  2403. if ( !GetPhysics()->HasGroundContacts() ) {
  2404. GetPhysics()->ClipTranslation( result, GetPhysics()->GetGravityNormal() * max_dist, NULL );
  2405. if ( result.fraction < 1.0f ) {
  2406. floorpos = result.endpos;
  2407. return true;
  2408. } else {
  2409. floorpos = GetPhysics()->GetOrigin();
  2410. return false;
  2411. }
  2412. } else {
  2413. floorpos = GetPhysics()->GetOrigin();
  2414. return true;
  2415. }
  2416. }
  2417. /*
  2418. ================
  2419. idEntity::GetPhysicsToVisualTransform
  2420. ================
  2421. */
  2422. bool idEntity::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
  2423. return false;
  2424. }
  2425. /*
  2426. ================
  2427. idEntity::GetPhysicsToSoundTransform
  2428. ================
  2429. */
  2430. bool idEntity::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  2431. // by default play the sound at the center of the bounding box of the first clip model
  2432. if ( GetPhysics()->GetNumClipModels() > 0 ) {
  2433. origin = GetPhysics()->GetBounds().GetCenter();
  2434. axis.Identity();
  2435. return true;
  2436. }
  2437. return false;
  2438. }
  2439. /*
  2440. ================
  2441. idEntity::Collide
  2442. ================
  2443. */
  2444. bool idEntity::Collide( const trace_t &collision, const idVec3 &velocity ) {
  2445. // this entity collides with collision.c.entityNum
  2446. return false;
  2447. }
  2448. /*
  2449. ================
  2450. idEntity::GetImpactInfo
  2451. ================
  2452. */
  2453. void idEntity::GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info ) {
  2454. GetPhysics()->GetImpactInfo( id, point, info );
  2455. }
  2456. /*
  2457. ================
  2458. idEntity::ApplyImpulse
  2459. ================
  2460. */
  2461. void idEntity::ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse ) {
  2462. GetPhysics()->ApplyImpulse( id, point, impulse );
  2463. }
  2464. /*
  2465. ================
  2466. idEntity::AddForce
  2467. ================
  2468. */
  2469. void idEntity::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force ) {
  2470. GetPhysics()->AddForce( id, point, force );
  2471. }
  2472. /*
  2473. ================
  2474. idEntity::ActivatePhysics
  2475. ================
  2476. */
  2477. void idEntity::ActivatePhysics( idEntity *ent ) {
  2478. GetPhysics()->Activate();
  2479. }
  2480. /*
  2481. ================
  2482. idEntity::IsAtRest
  2483. ================
  2484. */
  2485. bool idEntity::IsAtRest( void ) const {
  2486. return GetPhysics()->IsAtRest();
  2487. }
  2488. /*
  2489. ================
  2490. idEntity::GetRestStartTime
  2491. ================
  2492. */
  2493. int idEntity::GetRestStartTime( void ) const {
  2494. return GetPhysics()->GetRestStartTime();
  2495. }
  2496. /*
  2497. ================
  2498. idEntity::AddContactEntity
  2499. ================
  2500. */
  2501. void idEntity::AddContactEntity( idEntity *ent ) {
  2502. GetPhysics()->AddContactEntity( ent );
  2503. }
  2504. /*
  2505. ================
  2506. idEntity::RemoveContactEntity
  2507. ================
  2508. */
  2509. void idEntity::RemoveContactEntity( idEntity *ent ) {
  2510. GetPhysics()->RemoveContactEntity( ent );
  2511. }
  2512. /***********************************************************************
  2513. Damage
  2514. ***********************************************************************/
  2515. /*
  2516. ============
  2517. idEntity::CanDamage
  2518. Returns true if the inflictor can directly damage the target. Used for
  2519. explosions and melee attacks.
  2520. ============
  2521. */
  2522. bool idEntity::CanDamage( const idVec3 &origin, idVec3 &damagePoint ) const {
  2523. idVec3 dest;
  2524. trace_t tr;
  2525. idVec3 midpoint;
  2526. // use the midpoint of the bounds instead of the origin, because
  2527. // bmodels may have their origin at 0,0,0
  2528. midpoint = ( GetPhysics()->GetAbsBounds()[0] + GetPhysics()->GetAbsBounds()[1] ) * 0.5;
  2529. dest = midpoint;
  2530. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2531. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2532. damagePoint = tr.endpos;
  2533. return true;
  2534. }
  2535. // this should probably check in the plane of projection, rather than in world coordinate
  2536. dest = midpoint;
  2537. dest[0] += 15.0;
  2538. dest[1] += 15.0;
  2539. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2540. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2541. damagePoint = tr.endpos;
  2542. return true;
  2543. }
  2544. dest = midpoint;
  2545. dest[0] += 15.0;
  2546. dest[1] -= 15.0;
  2547. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2548. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2549. damagePoint = tr.endpos;
  2550. return true;
  2551. }
  2552. dest = midpoint;
  2553. dest[0] -= 15.0;
  2554. dest[1] += 15.0;
  2555. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2556. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2557. damagePoint = tr.endpos;
  2558. return true;
  2559. }
  2560. dest = midpoint;
  2561. dest[0] -= 15.0;
  2562. dest[1] -= 15.0;
  2563. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2564. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2565. damagePoint = tr.endpos;
  2566. return true;
  2567. }
  2568. dest = midpoint;
  2569. dest[2] += 15.0;
  2570. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2571. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2572. damagePoint = tr.endpos;
  2573. return true;
  2574. }
  2575. dest = midpoint;
  2576. dest[2] -= 15.0;
  2577. gameLocal.clip.TracePoint( tr, origin, dest, MASK_SOLID, NULL );
  2578. if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  2579. damagePoint = tr.endpos;
  2580. return true;
  2581. }
  2582. return false;
  2583. }
  2584. /*
  2585. ================
  2586. idEntity::DamageFeedback
  2587. callback function for when another entity received damage from this entity. damage can be adjusted and returned to the caller.
  2588. ================
  2589. */
  2590. void idEntity::DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage ) {
  2591. // implemented in subclasses
  2592. }
  2593. /*
  2594. ============
  2595. Damage
  2596. this entity that is being damaged
  2597. inflictor entity that is causing the damage
  2598. attacker entity that caused the inflictor to damage targ
  2599. example: this=monster, inflictor=rocket, attacker=player
  2600. dir direction of the attack for knockback in global space
  2601. point point at which the damage is being inflicted, used for headshots
  2602. damage amount of damage being inflicted
  2603. inflictor, attacker, dir, and point can be NULL for environmental effects
  2604. ============
  2605. */
  2606. void idEntity::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
  2607. const char *damageDefName, const float damageScale, const int location ) {
  2608. if ( !fl.takedamage ) {
  2609. return;
  2610. }
  2611. #ifdef _D3XP
  2612. SetTimeState ts( timeGroup );
  2613. #endif
  2614. if ( !inflictor ) {
  2615. inflictor = gameLocal.world;
  2616. }
  2617. if ( !attacker ) {
  2618. attacker = gameLocal.world;
  2619. }
  2620. const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
  2621. if ( !damageDef ) {
  2622. gameLocal.Error( "Unknown damageDef '%s'\n", damageDefName );
  2623. }
  2624. int damage = damageDef->GetInt( "damage" );
  2625. // inform the attacker that they hit someone
  2626. if (damage > 0)
  2627. attacker->DamageFeedback( this, inflictor, damage ); //bc
  2628. if ( damage ) {
  2629. // do the damage
  2630. health -= damage;
  2631. if ( health <= 0 ) {
  2632. if ( health < -999 ) {
  2633. health = -999;
  2634. }
  2635. Killed( inflictor, attacker, damage, dir, location );
  2636. } else {
  2637. Pain( inflictor, attacker, damage, dir, location );
  2638. }
  2639. }
  2640. }
  2641. /*
  2642. ================
  2643. idEntity::AddDamageEffect
  2644. ================
  2645. */
  2646. void idEntity::AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName ) {
  2647. const char *sound, *decal, *key;
  2648. const idDeclEntityDef *def = gameLocal.FindEntityDef( damageDefName, false );
  2649. if ( def == NULL ) {
  2650. return;
  2651. }
  2652. const char *materialType = gameLocal.sufaceTypeNames[ collision.c.material->GetSurfaceType() ];
  2653. // start impact sound based on material type
  2654. key = va( "snd_%s", materialType );
  2655. sound = spawnArgs.GetString( key );
  2656. if ( *sound == '\0' ) {
  2657. sound = def->dict.GetString( key );
  2658. }
  2659. if ( *sound != '\0' ) {
  2660. StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
  2661. }
  2662. if ( g_decals.GetBool() ) {
  2663. // place a wound overlay on the model
  2664. key = va( "mtr_wound_%s", materialType );
  2665. decal = spawnArgs.RandomPrefix( key, gameLocal.random );
  2666. if ( *decal == '\0' ) {
  2667. decal = def->dict.RandomPrefix( key, gameLocal.random );
  2668. }
  2669. if ( *decal != '\0' ) {
  2670. idVec3 dir = velocity;
  2671. dir.Normalize();
  2672. ProjectOverlay( collision.c.point, dir, 20.0f, decal );
  2673. }
  2674. }
  2675. }
  2676. /*
  2677. ============
  2678. idEntity::Pain
  2679. Called whenever an entity recieves damage. Returns whether the entity responds to the pain.
  2680. This is a virtual function that subclasses are expected to implement.
  2681. ============
  2682. */
  2683. bool idEntity::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  2684. return false;
  2685. }
  2686. /*
  2687. ============
  2688. idEntity::Killed
  2689. Called whenever an entity's health is reduced to 0 or less.
  2690. This is a virtual function that subclasses are expected to implement.
  2691. ============
  2692. */
  2693. void idEntity::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  2694. }
  2695. /***********************************************************************
  2696. Script functions
  2697. ***********************************************************************/
  2698. /*
  2699. ================
  2700. idEntity::ShouldConstructScriptObjectAtSpawn
  2701. Called during idEntity::Spawn to see if it should construct the script object or not.
  2702. Overridden by subclasses that need to spawn the script object themselves.
  2703. ================
  2704. */
  2705. bool idEntity::ShouldConstructScriptObjectAtSpawn( void ) const {
  2706. return true;
  2707. }
  2708. /*
  2709. ================
  2710. idEntity::ConstructScriptObject
  2711. Called during idEntity::Spawn. Calls the constructor on the script object.
  2712. Can be overridden by subclasses when a thread doesn't need to be allocated.
  2713. ================
  2714. */
  2715. idThread *idEntity::ConstructScriptObject( void ) {
  2716. idThread *thread;
  2717. const function_t *constructor;
  2718. // init the script object's data
  2719. scriptObject.ClearObject();
  2720. // call script object's constructor
  2721. constructor = scriptObject.GetConstructor();
  2722. if ( constructor ) {
  2723. // start a thread that will initialize after Spawn is done being called
  2724. thread = new idThread();
  2725. thread->SetThreadName( name.c_str() );
  2726. thread->CallFunction( this, constructor, true );
  2727. thread->DelayedStart( 0 );
  2728. } else {
  2729. thread = NULL;
  2730. }
  2731. // clear out the object's memory
  2732. scriptObject.ClearObject();
  2733. return thread;
  2734. }
  2735. /*
  2736. ================
  2737. idEntity::DeconstructScriptObject
  2738. Called during idEntity::~idEntity. Calls the destructor on the script object.
  2739. Can be overridden by subclasses when a thread doesn't need to be allocated.
  2740. Not called during idGameLocal::MapShutdown.
  2741. ================
  2742. */
  2743. void idEntity::DeconstructScriptObject( void ) {
  2744. idThread *thread;
  2745. const function_t *destructor;
  2746. // don't bother calling the script object's destructor on map shutdown
  2747. if ( gameLocal.GameState() == GAMESTATE_SHUTDOWN ) {
  2748. return;
  2749. }
  2750. // call script object's destructor
  2751. destructor = scriptObject.GetDestructor();
  2752. if ( destructor ) {
  2753. // start a thread that will run immediately and be destroyed
  2754. thread = new idThread();
  2755. thread->SetThreadName( name.c_str() );
  2756. thread->CallFunction( this, destructor, true );
  2757. thread->Execute();
  2758. delete thread;
  2759. }
  2760. }
  2761. /*
  2762. ================
  2763. idEntity::HasSignal
  2764. ================
  2765. */
  2766. bool idEntity::HasSignal( signalNum_t signalnum ) const {
  2767. if ( !signals ) {
  2768. return false;
  2769. }
  2770. assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  2771. return ( signals->signal[ signalnum ].Num() > 0 );
  2772. }
  2773. /*
  2774. ================
  2775. idEntity::SetSignal
  2776. ================
  2777. */
  2778. void idEntity::SetSignal( signalNum_t signalnum, idThread *thread, const function_t *function ) {
  2779. int i;
  2780. int num;
  2781. signal_t sig;
  2782. int threadnum;
  2783. assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  2784. if ( !signals ) {
  2785. signals = new signalList_t;
  2786. }
  2787. assert( thread );
  2788. threadnum = thread->GetThreadNum();
  2789. num = signals->signal[ signalnum ].Num();
  2790. for( i = 0; i < num; i++ ) {
  2791. if ( signals->signal[ signalnum ][ i ].threadnum == threadnum ) {
  2792. signals->signal[ signalnum ][ i ].function = function;
  2793. return;
  2794. }
  2795. }
  2796. if ( num >= MAX_SIGNAL_THREADS ) {
  2797. thread->Error( "Exceeded maximum number of signals per object" );
  2798. }
  2799. sig.threadnum = threadnum;
  2800. sig.function = function;
  2801. signals->signal[ signalnum ].Append( sig );
  2802. }
  2803. /*
  2804. ================
  2805. idEntity::ClearSignal
  2806. ================
  2807. */
  2808. void idEntity::ClearSignal( idThread *thread, signalNum_t signalnum ) {
  2809. assert( thread );
  2810. if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  2811. gameLocal.Error( "Signal out of range" );
  2812. }
  2813. if ( !signals ) {
  2814. return;
  2815. }
  2816. signals->signal[ signalnum ].Clear();
  2817. }
  2818. /*
  2819. ================
  2820. idEntity::ClearSignalThread
  2821. ================
  2822. */
  2823. void idEntity::ClearSignalThread( signalNum_t signalnum, idThread *thread ) {
  2824. int i;
  2825. int num;
  2826. int threadnum;
  2827. assert( thread );
  2828. if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  2829. gameLocal.Error( "Signal out of range" );
  2830. }
  2831. if ( !signals ) {
  2832. return;
  2833. }
  2834. threadnum = thread->GetThreadNum();
  2835. num = signals->signal[ signalnum ].Num();
  2836. for( i = 0; i < num; i++ ) {
  2837. if ( signals->signal[ signalnum ][ i ].threadnum == threadnum ) {
  2838. signals->signal[ signalnum ].RemoveIndex( i );
  2839. return;
  2840. }
  2841. }
  2842. }
  2843. /*
  2844. ================
  2845. idEntity::Signal
  2846. ================
  2847. */
  2848. void idEntity::Signal( signalNum_t signalnum ) {
  2849. int i;
  2850. int num;
  2851. signal_t sigs[ MAX_SIGNAL_THREADS ];
  2852. idThread *thread;
  2853. assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  2854. if ( !signals ) {
  2855. return;
  2856. }
  2857. // we copy the signal list since each thread has the potential
  2858. // to end any of the threads in the list. By copying the list
  2859. // we don't have to worry about the list changing as we're
  2860. // processing it.
  2861. num = signals->signal[ signalnum ].Num();
  2862. for( i = 0; i < num; i++ ) {
  2863. sigs[ i ] = signals->signal[ signalnum ][ i ];
  2864. }
  2865. // clear out the signal list so that we don't get into an infinite loop
  2866. signals->signal[ signalnum ].Clear();
  2867. for( i = 0; i < num; i++ ) {
  2868. thread = idThread::GetThread( sigs[ i ].threadnum );
  2869. if ( thread ) {
  2870. thread->CallFunction( this, sigs[ i ].function, true );
  2871. thread->Execute();
  2872. }
  2873. }
  2874. }
  2875. /*
  2876. ================
  2877. idEntity::SignalEvent
  2878. ================
  2879. */
  2880. void idEntity::SignalEvent( idThread *thread, signalNum_t signalnum ) {
  2881. if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  2882. gameLocal.Error( "Signal out of range" );
  2883. }
  2884. if ( !signals ) {
  2885. return;
  2886. }
  2887. Signal( signalnum );
  2888. }
  2889. /***********************************************************************
  2890. Guis.
  2891. ***********************************************************************/
  2892. /*
  2893. ================
  2894. idEntity::TriggerGuis
  2895. ================
  2896. */
  2897. void idEntity::TriggerGuis( void ) {
  2898. int i;
  2899. for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  2900. if ( renderEntity.gui[ i ] ) {
  2901. renderEntity.gui[ i ]->Trigger( gameLocal.time );
  2902. }
  2903. }
  2904. }
  2905. /*
  2906. ================
  2907. idEntity::HandleGuiCommands
  2908. ================
  2909. */
  2910. bool idEntity::HandleGuiCommands( idEntity *entityGui, const char *cmds ) {
  2911. idEntity *targetEnt;
  2912. bool ret = false;
  2913. if ( entityGui && cmds && *cmds ) {
  2914. idLexer src;
  2915. idToken token, token2, token3, token4;
  2916. src.LoadMemory( cmds, strlen( cmds ), "guiCommands" );
  2917. while( 1 ) {
  2918. if ( !src.ReadToken( &token ) ) {
  2919. return ret;
  2920. }
  2921. if ( token == ";" ) {
  2922. continue;
  2923. }
  2924. if ( token.Icmp( "activate" ) == 0 ) {
  2925. bool targets = true;
  2926. if ( src.ReadToken( &token2 ) ) {
  2927. if ( token2 == ";" ) {
  2928. src.UnreadToken( &token2 );
  2929. } else {
  2930. targets = false;
  2931. }
  2932. }
  2933. if ( targets ) {
  2934. entityGui->ActivateTargets( this );
  2935. } else {
  2936. idEntity *ent = gameLocal.FindEntity( token2 );
  2937. if ( ent ) {
  2938. ent->Signal( SIG_TRIGGER );
  2939. ent->PostEventMS( &EV_Activate, 0, this );
  2940. }
  2941. }
  2942. entityGui->renderEntity.shaderParms[ SHADERPARM_MODE ] = 1.0f;
  2943. continue;
  2944. }
  2945. if ( token.Icmp( "runScript" ) == 0 ) {
  2946. if ( src.ReadToken( &token2 ) ) {
  2947. while( src.CheckTokenString( "::" ) ) {
  2948. idToken token3;
  2949. if ( !src.ReadToken( &token3 ) ) {
  2950. gameLocal.Error( "Expecting function name following '::' in gui for entity '%s'", entityGui->name.c_str() );
  2951. }
  2952. token2 += "::" + token3;
  2953. }
  2954. const function_t *func = gameLocal.program.FindFunction( token2 );
  2955. if ( !func ) {
  2956. gameLocal.Error( "Can't find function '%s' for gui in entity '%s'", token2.c_str(), entityGui->name.c_str() );
  2957. } else {
  2958. idThread *thread = new idThread( func );
  2959. thread->DelayedStart( 0 );
  2960. }
  2961. }
  2962. continue;
  2963. }
  2964. if ( token.Icmp("play") == 0 ) {
  2965. if ( src.ReadToken( &token2 ) ) {
  2966. const idSoundShader *shader = declManager->FindSound(token2);
  2967. entityGui->StartSoundShader( shader, SND_CHANNEL_ANY, 0, false, NULL );
  2968. }
  2969. continue;
  2970. }
  2971. if ( token.Icmp( "setkeyval" ) == 0 ) {
  2972. if ( src.ReadToken( &token2 ) && src.ReadToken(&token3) && src.ReadToken( &token4 ) ) {
  2973. idEntity *ent = gameLocal.FindEntity( token2 );
  2974. if ( ent ) {
  2975. ent->spawnArgs.Set( token3, token4 );
  2976. ent->UpdateChangeableSpawnArgs( NULL );
  2977. ent->UpdateVisuals();
  2978. }
  2979. }
  2980. continue;
  2981. }
  2982. if ( token.Icmp( "setshaderparm" ) == 0 ) {
  2983. if ( src.ReadToken( &token2 ) && src.ReadToken(&token3) ) {
  2984. entityGui->SetShaderParm( atoi( token2 ), atof( token3 ) );
  2985. entityGui->UpdateVisuals();
  2986. }
  2987. continue;
  2988. }
  2989. if ( token.Icmp("close") == 0 ) {
  2990. ret = true;
  2991. continue;
  2992. }
  2993. if ( !token.Icmp( "turkeyscore" ) ) {
  2994. if ( src.ReadToken( &token2 ) && entityGui->renderEntity.gui[0] ) {
  2995. int score = entityGui->renderEntity.gui[0]->State().GetInt( "score" );
  2996. score += atoi( token2 );
  2997. entityGui->renderEntity.gui[0]->SetStateInt( "score", score );
  2998. if ( gameLocal.GetLocalPlayer() && score >= 25000 && !gameLocal.GetLocalPlayer()->inventory.turkeyScore ) {
  2999. gameLocal.GetLocalPlayer()->GiveEmail( "highScore" );
  3000. gameLocal.GetLocalPlayer()->inventory.turkeyScore = true;
  3001. }
  3002. }
  3003. continue;
  3004. }
  3005. #ifdef _D3XP
  3006. if ( !token.Icmp( "martianbuddycomplete" ) ) {
  3007. gameLocal.GetLocalPlayer()->GiveEmail( "MartianBuddyGameComplete" );
  3008. continue;
  3009. }
  3010. #endif
  3011. // handy for debugging GUI stuff
  3012. if ( !token.Icmp( "print" ) ) {
  3013. idStr msg;
  3014. while ( src.ReadToken( &token2 ) ) {
  3015. if ( token2 == ";" ) {
  3016. src.UnreadToken( &token2 );
  3017. break;
  3018. }
  3019. msg += token2.c_str();
  3020. }
  3021. common->Printf( "ent gui 0x%x '%s': %s\n", entityNumber, name.c_str(), msg.c_str() );
  3022. continue;
  3023. }
  3024. // if we get to this point we don't know how to handle it
  3025. src.UnreadToken(&token);
  3026. if ( !HandleSingleGuiCommand( entityGui, &src ) ) {
  3027. // not handled there see if entity or any of its targets can handle it
  3028. // this will only work for one target atm
  3029. if ( entityGui->HandleSingleGuiCommand( entityGui, &src ) ) {
  3030. continue;
  3031. }
  3032. int c = entityGui->targets.Num();
  3033. int i;
  3034. for ( i = 0; i < c; i++) {
  3035. targetEnt = entityGui->targets[ i ].GetEntity();
  3036. if ( targetEnt && targetEnt->HandleSingleGuiCommand( entityGui, &src ) ) {
  3037. break;
  3038. }
  3039. }
  3040. if ( i == c ) {
  3041. // not handled
  3042. common->DPrintf( "idEntity::HandleGuiCommands: '%s' not handled\n", token.c_str() );
  3043. src.ReadToken( &token );
  3044. }
  3045. }
  3046. }
  3047. }
  3048. return ret;
  3049. }
  3050. /*
  3051. ================
  3052. idEntity::HandleSingleGuiCommand
  3053. ================
  3054. */
  3055. bool idEntity::HandleSingleGuiCommand( idEntity *entityGui, idLexer *src ) {
  3056. return false;
  3057. }
  3058. /***********************************************************************
  3059. Targets
  3060. ***********************************************************************/
  3061. /*
  3062. ===============
  3063. idEntity::FindTargets
  3064. We have to wait until all entities are spawned
  3065. Used to build lists of targets after the entity is spawned. Since not all entities
  3066. have been spawned when the entity is created at map load time, we have to wait
  3067. ===============
  3068. */
  3069. void idEntity::FindTargets( void ) {
  3070. int i;
  3071. // targets can be a list of multiple names
  3072. gameLocal.GetTargets( spawnArgs, targets, "target" );
  3073. // ensure that we don't target ourselves since that could cause an infinite loop when activating entities
  3074. for( i = 0; i < targets.Num(); i++ ) {
  3075. if ( targets[ i ].GetEntity() == this ) {
  3076. gameLocal.Error( "Entity '%s' is targeting itself", name.c_str() );
  3077. }
  3078. }
  3079. }
  3080. /*
  3081. ================
  3082. idEntity::RemoveNullTargets
  3083. ================
  3084. */
  3085. void idEntity::RemoveNullTargets( void ) {
  3086. int i;
  3087. for( i = targets.Num() - 1; i >= 0; i-- ) {
  3088. if ( !targets[ i ].GetEntity() ) {
  3089. targets.RemoveIndex( i );
  3090. }
  3091. }
  3092. }
  3093. /*
  3094. ==============================
  3095. idEntity::ActivateTargets
  3096. "activator" should be set to the entity that initiated the firing.
  3097. ==============================
  3098. */
  3099. void idEntity::ActivateTargets( idEntity *activator ) const {
  3100. idEntity *ent;
  3101. int i, j;
  3102. for( i = 0; i < targets.Num(); i++ ) {
  3103. ent = targets[ i ].GetEntity();
  3104. if ( !ent ) {
  3105. continue;
  3106. }
  3107. if ( ent->RespondsTo( EV_Activate ) || ent->HasSignal( SIG_TRIGGER ) ) {
  3108. ent->Signal( SIG_TRIGGER );
  3109. ent->ProcessEvent( &EV_Activate, activator );
  3110. }
  3111. for ( j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
  3112. if ( ent->renderEntity.gui[ j ] ) {
  3113. ent->renderEntity.gui[ j ]->Trigger( gameLocal.time );
  3114. }
  3115. }
  3116. }
  3117. }
  3118. /***********************************************************************
  3119. Misc.
  3120. ***********************************************************************/
  3121. /*
  3122. ================
  3123. idEntity::Teleport
  3124. ================
  3125. */
  3126. void idEntity::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
  3127. GetPhysics()->SetOrigin( origin );
  3128. GetPhysics()->SetAxis( angles.ToMat3() );
  3129. UpdateVisuals();
  3130. }
  3131. /*
  3132. ============
  3133. idEntity::TouchTriggers
  3134. Activate all trigger entities touched at the current position.
  3135. ============
  3136. */
  3137. bool idEntity::TouchTriggers( void ) const {
  3138. int i, numClipModels, numEntities;
  3139. idClipModel * cm;
  3140. idClipModel * clipModels[ MAX_GENTITIES ];
  3141. idEntity * ent;
  3142. trace_t trace;
  3143. memset( &trace, 0, sizeof( trace ) );
  3144. trace.endpos = GetPhysics()->GetOrigin();
  3145. trace.endAxis = GetPhysics()->GetAxis();
  3146. numClipModels = gameLocal.clip.ClipModelsTouchingBounds( GetPhysics()->GetAbsBounds(), CONTENTS_TRIGGER, clipModels, MAX_GENTITIES );
  3147. numEntities = 0;
  3148. for ( i = 0; i < numClipModels; i++ ) {
  3149. cm = clipModels[ i ];
  3150. // don't touch it if we're the owner
  3151. if ( cm->GetOwner() == this ) {
  3152. continue;
  3153. }
  3154. ent = cm->GetEntity();
  3155. if ( !ent->RespondsTo( EV_Touch ) && !ent->HasSignal( SIG_TOUCH ) ) {
  3156. continue;
  3157. }
  3158. if ( !GetPhysics()->ClipContents( cm ) ) {
  3159. continue;
  3160. }
  3161. #ifdef _D3XP
  3162. SetTimeState ts( ent->timeGroup );
  3163. #endif
  3164. numEntities++;
  3165. trace.c.contents = cm->GetContents();
  3166. trace.c.entityNum = cm->GetEntity()->entityNumber;
  3167. trace.c.id = cm->GetId();
  3168. ent->Signal( SIG_TOUCH );
  3169. ent->ProcessEvent( &EV_Touch, this, &trace );
  3170. if ( !gameLocal.entities[ entityNumber ] ) {
  3171. gameLocal.Printf( "entity was removed while touching triggers\n" );
  3172. return true;
  3173. }
  3174. }
  3175. return ( numEntities != 0 );
  3176. }
  3177. /*
  3178. ================
  3179. idEntity::GetSpline
  3180. ================
  3181. */
  3182. idCurve_Spline<idVec3> *idEntity::GetSpline( void ) const {
  3183. int i, numPoints, t;
  3184. const idKeyValue *kv;
  3185. idLexer lex;
  3186. idVec3 v;
  3187. idCurve_Spline<idVec3> *spline;
  3188. const char *curveTag = "curve_";
  3189. kv = spawnArgs.MatchPrefix( curveTag );
  3190. if ( !kv ) {
  3191. return NULL;
  3192. }
  3193. idStr str = kv->GetKey().Right( kv->GetKey().Length() - strlen( curveTag ) );
  3194. if ( str.Icmp( "CatmullRomSpline" ) == 0 ) {
  3195. spline = new idCurve_CatmullRomSpline<idVec3>();
  3196. } else if ( str.Icmp( "nubs" ) == 0 ) {
  3197. spline = new idCurve_NonUniformBSpline<idVec3>();
  3198. } else if ( str.Icmp( "nurbs" ) == 0 ) {
  3199. spline = new idCurve_NURBS<idVec3>();
  3200. } else {
  3201. spline = new idCurve_BSpline<idVec3>();
  3202. }
  3203. spline->SetBoundaryType( idCurve_Spline<idVec3>::BT_CLAMPED );
  3204. lex.LoadMemory( kv->GetValue(), kv->GetValue().Length(), curveTag );
  3205. numPoints = lex.ParseInt();
  3206. lex.ExpectTokenString( "(" );
  3207. for ( t = i = 0; i < numPoints; i++, t += 100 ) {
  3208. v.x = lex.ParseFloat();
  3209. v.y = lex.ParseFloat();
  3210. v.z = lex.ParseFloat();
  3211. spline->AddValue( t, v );
  3212. }
  3213. lex.ExpectTokenString( ")" );
  3214. return spline;
  3215. }
  3216. /*
  3217. ===============
  3218. idEntity::ShowEditingDialog
  3219. ===============
  3220. */
  3221. void idEntity::ShowEditingDialog( void ) {
  3222. }
  3223. /***********************************************************************
  3224. Events
  3225. ***********************************************************************/
  3226. /*
  3227. ================
  3228. idEntity::Event_GetName
  3229. ================
  3230. */
  3231. void idEntity::Event_GetName( void ) {
  3232. idThread::ReturnString( name.c_str() );
  3233. }
  3234. void idEntity::Event_GetIndex( void )
  3235. {
  3236. idThread::ReturnInt( this->entityNumber);
  3237. }
  3238. /*
  3239. ================
  3240. idEntity::Event_SetName
  3241. ================
  3242. */
  3243. void idEntity::Event_SetName( const char *newname ) {
  3244. SetName( newname );
  3245. }
  3246. /*
  3247. ===============
  3248. idEntity::Event_FindTargets
  3249. ===============
  3250. */
  3251. void idEntity::Event_FindTargets( void ) {
  3252. FindTargets();
  3253. }
  3254. /*
  3255. ============
  3256. idEntity::Event_ActivateTargets
  3257. Activates any entities targeted by this entity. Mainly used as an
  3258. event to delay activating targets.
  3259. ============
  3260. */
  3261. void idEntity::Event_ActivateTargets( idEntity *activator ) {
  3262. ActivateTargets( activator );
  3263. }
  3264. /*
  3265. ================
  3266. idEntity::Event_NumTargets
  3267. ================
  3268. */
  3269. void idEntity::Event_NumTargets( void ) {
  3270. idThread::ReturnFloat( targets.Num() );
  3271. }
  3272. /*
  3273. ================
  3274. idEntity::Event_GetTarget
  3275. ================
  3276. */
  3277. void idEntity::Event_GetTarget( float index ) {
  3278. int i;
  3279. i = ( int )index;
  3280. if ( ( i < 0 ) || i >= targets.Num() ) {
  3281. idThread::ReturnEntity( NULL );
  3282. } else {
  3283. idThread::ReturnEntity( targets[ i ].GetEntity() );
  3284. }
  3285. }
  3286. /*
  3287. ================
  3288. idEntity::Event_RandomTarget
  3289. ================
  3290. */
  3291. void idEntity::Event_RandomTarget( const char *ignore ) {
  3292. int num;
  3293. idEntity *ent;
  3294. int i;
  3295. int ignoreNum;
  3296. RemoveNullTargets();
  3297. if ( !targets.Num() ) {
  3298. idThread::ReturnEntity( NULL );
  3299. return;
  3300. }
  3301. ignoreNum = -1;
  3302. if ( ignore && ( ignore[ 0 ] != 0 ) && ( targets.Num() > 1 ) ) {
  3303. for( i = 0; i < targets.Num(); i++ ) {
  3304. ent = targets[ i ].GetEntity();
  3305. if ( ent && ( ent->name == ignore ) ) {
  3306. ignoreNum = i;
  3307. break;
  3308. }
  3309. }
  3310. }
  3311. if ( ignoreNum >= 0 ) {
  3312. num = gameLocal.random.RandomInt( targets.Num() - 1 );
  3313. if ( num >= ignoreNum ) {
  3314. num++;
  3315. }
  3316. } else {
  3317. num = gameLocal.random.RandomInt( targets.Num() );
  3318. }
  3319. ent = targets[ num ].GetEntity();
  3320. idThread::ReturnEntity( ent );
  3321. }
  3322. /*
  3323. ================
  3324. idEntity::Event_BindToJoint
  3325. ================
  3326. */
  3327. void idEntity::Event_BindToJoint( idEntity *master, const char *jointname, float orientated ) {
  3328. BindToJoint( master, jointname, ( orientated != 0.0f ) );
  3329. }
  3330. /*
  3331. ================
  3332. idEntity::Event_RemoveBinds
  3333. ================
  3334. */
  3335. void idEntity::Event_RemoveBinds( void ) {
  3336. RemoveBinds();
  3337. }
  3338. /*
  3339. ================
  3340. idEntity::Event_Bind
  3341. ================
  3342. */
  3343. void idEntity::Event_Bind( idEntity *master ) {
  3344. Bind( master, true );
  3345. }
  3346. /*
  3347. ================
  3348. idEntity::Event_BindPosition
  3349. ================
  3350. */
  3351. void idEntity::Event_BindPosition( idEntity *master ) {
  3352. Bind( master, false );
  3353. }
  3354. /*
  3355. ================
  3356. idEntity::Event_Unbind
  3357. ================
  3358. */
  3359. void idEntity::Event_Unbind( void ) {
  3360. Unbind();
  3361. }
  3362. /*
  3363. ================
  3364. idEntity::Event_SpawnBind
  3365. ================
  3366. */
  3367. void idEntity::Event_SpawnBind( void ) {
  3368. idEntity *parent;
  3369. const char *bind, *joint, *bindanim;
  3370. jointHandle_t bindJoint;
  3371. bool bindOrientated;
  3372. int id;
  3373. const idAnim *anim;
  3374. int animNum;
  3375. idAnimator *parentAnimator;
  3376. if ( spawnArgs.GetString( "bind", "", &bind ) ) {
  3377. if ( idStr::Icmp( bind, "worldspawn" ) == 0 ) {
  3378. //FIXME: Completely unneccessary since the worldspawn is called "world"
  3379. parent = gameLocal.world;
  3380. } else {
  3381. parent = gameLocal.FindEntity( bind );
  3382. }
  3383. bindOrientated = spawnArgs.GetBool( "bindOrientated", "1" );
  3384. if ( parent ) {
  3385. // bind to a joint of the skeletal model of the parent
  3386. if ( spawnArgs.GetString( "bindToJoint", "", &joint ) && *joint ) {
  3387. parentAnimator = parent->GetAnimator();
  3388. if ( !parentAnimator ) {
  3389. gameLocal.Error( "Cannot bind to joint '%s' on '%s'. Entity does not support skeletal models.", joint, name.c_str() );
  3390. }
  3391. bindJoint = parentAnimator->GetJointHandle( joint );
  3392. if ( bindJoint == INVALID_JOINT ) {
  3393. gameLocal.Error( "Joint '%s' not found for bind on '%s'", joint, name.c_str() );
  3394. }
  3395. // bind it relative to a specific anim
  3396. if ( ( parent->spawnArgs.GetString( "bindanim", "", &bindanim ) || parent->spawnArgs.GetString( "anim", "", &bindanim ) ) && *bindanim ) {
  3397. animNum = parentAnimator->GetAnim( bindanim );
  3398. if ( !animNum ) {
  3399. gameLocal.Error( "Anim '%s' not found for bind on '%s'", bindanim, name.c_str() );
  3400. }
  3401. anim = parentAnimator->GetAnim( animNum );
  3402. if ( !anim ) {
  3403. gameLocal.Error( "Anim '%s' not found for bind on '%s'", bindanim, name.c_str() );
  3404. }
  3405. // make sure parent's render origin has been set
  3406. parent->UpdateModelTransform();
  3407. //FIXME: need a BindToJoint that accepts a joint position
  3408. parentAnimator->CreateFrame( gameLocal.time, true );
  3409. idJointMat *frame = parent->renderEntity.joints;
  3410. gameEdit->ANIM_CreateAnimFrame( parentAnimator->ModelHandle(), anim->MD5Anim( 0 ), parent->renderEntity.numJoints, frame, 0, parentAnimator->ModelDef()->GetVisualOffset(), parentAnimator->RemoveOrigin() );
  3411. BindToJoint( parent, joint, bindOrientated );
  3412. parentAnimator->ForceUpdate();
  3413. } else {
  3414. BindToJoint( parent, joint, bindOrientated );
  3415. }
  3416. }
  3417. // bind to a body of the physics object of the parent
  3418. else if ( spawnArgs.GetInt( "bindToBody", "0", id ) ) {
  3419. BindToBody( parent, id, bindOrientated );
  3420. }
  3421. // bind to the parent
  3422. else {
  3423. Bind( parent, bindOrientated );
  3424. }
  3425. }
  3426. }
  3427. }
  3428. /*
  3429. ================
  3430. idEntity::Event_SetOwner
  3431. ================
  3432. */
  3433. void idEntity::Event_SetOwner( idEntity *owner ) {
  3434. int i;
  3435. for ( i = 0; i < GetPhysics()->GetNumClipModels(); i++ ) {
  3436. GetPhysics()->GetClipModel( i )->SetOwner( owner );
  3437. }
  3438. }
  3439. /*
  3440. ================
  3441. idEntity::Event_SetModel
  3442. ================
  3443. */
  3444. void idEntity::Event_SetModel( const char *modelname ) {
  3445. SetModel( modelname );
  3446. }
  3447. /*
  3448. ================
  3449. idEntity::Event_SetSkin
  3450. ================
  3451. */
  3452. void idEntity::Event_SetSkin( const char *skinname ) {
  3453. renderEntity.customSkin = declManager->FindSkin( skinname );
  3454. UpdateVisuals();
  3455. }
  3456. /*
  3457. ================
  3458. idEntity::Event_GetShaderParm
  3459. ================
  3460. */
  3461. void idEntity::Event_GetShaderParm( int parmnum ) {
  3462. if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  3463. gameLocal.Error( "shader parm index (%d) out of range", parmnum );
  3464. }
  3465. idThread::ReturnFloat( renderEntity.shaderParms[ parmnum ] );
  3466. }
  3467. /*
  3468. ================
  3469. idEntity::Event_SetShaderParm
  3470. ================
  3471. */
  3472. void idEntity::Event_SetShaderParm( int parmnum, float value ) {
  3473. SetShaderParm( parmnum, value );
  3474. }
  3475. /*
  3476. ================
  3477. idEntity::Event_SetShaderParms
  3478. ================
  3479. */
  3480. void idEntity::Event_SetShaderParms( float parm0, float parm1, float parm2, float parm3 ) {
  3481. renderEntity.shaderParms[ SHADERPARM_RED ] = parm0;
  3482. renderEntity.shaderParms[ SHADERPARM_GREEN ] = parm1;
  3483. renderEntity.shaderParms[ SHADERPARM_BLUE ] = parm2;
  3484. renderEntity.shaderParms[ SHADERPARM_ALPHA ] = parm3;
  3485. UpdateVisuals();
  3486. }
  3487. /*
  3488. ================
  3489. idEntity::Event_SetColor
  3490. ================
  3491. */
  3492. void idEntity::Event_SetColor( float red, float green, float blue ) {
  3493. SetColor( red, green, blue );
  3494. }
  3495. /*
  3496. ================
  3497. idEntity::Event_GetColor
  3498. ================
  3499. */
  3500. void idEntity::Event_GetColor( void ) {
  3501. idVec3 out;
  3502. GetColor( out );
  3503. idThread::ReturnVector( out );
  3504. }
  3505. /*
  3506. ================
  3507. idEntity::Event_IsHidden
  3508. ================
  3509. */
  3510. void idEntity::Event_IsHidden( void ) {
  3511. idThread::ReturnInt( fl.hidden );
  3512. }
  3513. /*
  3514. ================
  3515. idEntity::Event_Hide
  3516. ================
  3517. */
  3518. void idEntity::Event_Hide( void ) {
  3519. Hide();
  3520. }
  3521. /*
  3522. ================
  3523. idEntity::Event_Show
  3524. ================
  3525. */
  3526. void idEntity::Event_Show( void ) {
  3527. Show();
  3528. }
  3529. /*
  3530. ================
  3531. idEntity::Event_CacheSoundShader
  3532. ================
  3533. */
  3534. void idEntity::Event_CacheSoundShader( const char *soundName ) {
  3535. declManager->FindSound( soundName );
  3536. }
  3537. /*
  3538. ================
  3539. idEntity::Event_StartSoundShader
  3540. ================
  3541. */
  3542. void idEntity::Event_StartSoundShader( const char *soundName, int channel ) {
  3543. int length;
  3544. StartSoundShader( declManager->FindSound( soundName ), (s_channelType)channel, 0, false, &length );
  3545. idThread::ReturnFloat( MS2SEC( length ) );
  3546. }
  3547. /*
  3548. ================
  3549. idEntity::Event_StopSound
  3550. ================
  3551. */
  3552. void idEntity::Event_StopSound( int channel, int netSync ) {
  3553. StopSound( channel, ( netSync != 0 ) );
  3554. }
  3555. /*
  3556. ================
  3557. idEntity::Event_StartSound
  3558. ================
  3559. */
  3560. void idEntity::Event_StartSound( const char *soundName, int channel, int netSync ) {
  3561. int time;
  3562. StartSound( soundName, ( s_channelType )channel, 0, ( netSync != 0 ), &time );
  3563. idThread::ReturnFloat( MS2SEC( time ) );
  3564. }
  3565. /*
  3566. ================
  3567. idEntity::Event_FadeSound
  3568. ================
  3569. */
  3570. void idEntity::Event_FadeSound( int channel, float to, float over ) {
  3571. if ( refSound.referenceSound ) {
  3572. refSound.referenceSound->FadeSound( channel, to, over );
  3573. }
  3574. }
  3575. /*
  3576. ================
  3577. idEntity::Event_GetWorldOrigin
  3578. ================
  3579. */
  3580. void idEntity::Event_GetWorldOrigin( void ) {
  3581. idThread::ReturnVector( GetPhysics()->GetOrigin() );
  3582. }
  3583. /*
  3584. ================
  3585. idEntity::Event_SetWorldOrigin
  3586. ================
  3587. */
  3588. void idEntity::Event_SetWorldOrigin( idVec3 const &org ) {
  3589. idVec3 neworg = GetLocalCoordinates( org );
  3590. SetOrigin( neworg );
  3591. }
  3592. /*
  3593. ================
  3594. idEntity::Event_SetOrigin
  3595. ================
  3596. */
  3597. void idEntity::Event_SetOrigin( idVec3 const &org ) {
  3598. SetOrigin( org );
  3599. }
  3600. /*
  3601. ================
  3602. idEntity::Event_GetOrigin
  3603. ================
  3604. */
  3605. void idEntity::Event_GetOrigin( void ) {
  3606. idThread::ReturnVector( GetLocalCoordinates( GetPhysics()->GetOrigin() ) );
  3607. }
  3608. /*
  3609. ================
  3610. idEntity::Event_SetAngles
  3611. ================
  3612. */
  3613. void idEntity::Event_SetAngles( idAngles const &ang ) {
  3614. SetAngles( ang );
  3615. }
  3616. /*
  3617. ================
  3618. idEntity::Event_GetAngles
  3619. ================
  3620. */
  3621. void idEntity::Event_GetAngles( void ) {
  3622. idAngles ang = GetPhysics()->GetAxis().ToAngles();
  3623. idThread::ReturnVector( idVec3( ang[0], ang[1], ang[2] ) );
  3624. }
  3625. /*
  3626. ================
  3627. idEntity::Event_SetLinearVelocity
  3628. ================
  3629. */
  3630. void idEntity::Event_SetLinearVelocity( const idVec3 &velocity ) {
  3631. GetPhysics()->SetLinearVelocity( velocity );
  3632. }
  3633. /*
  3634. ================
  3635. idEntity::Event_GetLinearVelocity
  3636. ================
  3637. */
  3638. void idEntity::Event_GetLinearVelocity( void ) {
  3639. idThread::ReturnVector( GetPhysics()->GetLinearVelocity() );
  3640. }
  3641. /*
  3642. ================
  3643. idEntity::Event_SetAngularVelocity
  3644. ================
  3645. */
  3646. void idEntity::Event_SetAngularVelocity( const idVec3 &velocity ) {
  3647. GetPhysics()->SetAngularVelocity( velocity );
  3648. }
  3649. /*
  3650. ================
  3651. idEntity::Event_GetAngularVelocity
  3652. ================
  3653. */
  3654. void idEntity::Event_GetAngularVelocity( void ) {
  3655. idThread::ReturnVector( GetPhysics()->GetAngularVelocity() );
  3656. }
  3657. /*
  3658. ================
  3659. idEntity::Event_SetSize
  3660. ================
  3661. */
  3662. void idEntity::Event_SetSize( idVec3 const &mins, idVec3 const &maxs ) {
  3663. GetPhysics()->SetClipBox( idBounds( mins, maxs ), 1.0f );
  3664. }
  3665. /*
  3666. ================
  3667. idEntity::Event_GetSize
  3668. ================
  3669. */
  3670. void idEntity::Event_GetSize( void ) {
  3671. idBounds bounds;
  3672. bounds = GetPhysics()->GetBounds();
  3673. idThread::ReturnVector( bounds[1] - bounds[0] );
  3674. }
  3675. /*
  3676. ================
  3677. idEntity::Event_GetMins
  3678. ================
  3679. */
  3680. void idEntity::Event_GetMins( void ) {
  3681. idThread::ReturnVector( GetPhysics()->GetBounds()[0] );
  3682. }
  3683. /*
  3684. ================
  3685. idEntity::Event_GetMaxs
  3686. ================
  3687. */
  3688. void idEntity::Event_GetMaxs( void ) {
  3689. idThread::ReturnVector( GetPhysics()->GetBounds()[1] );
  3690. }
  3691. /*
  3692. ================
  3693. idEntity::Event_Touches
  3694. ================
  3695. */
  3696. void idEntity::Event_Touches( idEntity *ent ) {
  3697. if ( !ent ) {
  3698. idThread::ReturnInt( false );
  3699. return;
  3700. }
  3701. const idBounds &myBounds = GetPhysics()->GetAbsBounds();
  3702. const idBounds &entBounds = ent->GetPhysics()->GetAbsBounds();
  3703. idThread::ReturnInt( myBounds.IntersectsBounds( entBounds ) );
  3704. }
  3705. /*
  3706. ================
  3707. idEntity::Event_SetGuiParm
  3708. ================
  3709. */
  3710. void idEntity::Event_SetGuiParm( const char *key, const char *val ) {
  3711. for ( int i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  3712. if ( renderEntity.gui[ i ] ) {
  3713. if ( idStr::Icmpn( key, "gui_", 4 ) == 0 ) {
  3714. spawnArgs.Set( key, val );
  3715. }
  3716. renderEntity.gui[ i ]->SetStateString( key, val );
  3717. renderEntity.gui[ i ]->StateChanged( gameLocal.time );
  3718. }
  3719. }
  3720. }
  3721. /*
  3722. ================
  3723. idEntity::Event_SetGuiParm
  3724. ================
  3725. */
  3726. void idEntity::Event_SetGuiFloat( const char *key, float f ) {
  3727. for ( int i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  3728. if ( renderEntity.gui[ i ] ) {
  3729. renderEntity.gui[ i ]->SetStateString( key, va( "%f", f ) );
  3730. renderEntity.gui[ i ]->StateChanged( gameLocal.time );
  3731. }
  3732. }
  3733. }
  3734. /*
  3735. ================
  3736. idEntity::Event_GetNextKey
  3737. ================
  3738. */
  3739. void idEntity::Event_GetNextKey( const char *prefix, const char *lastMatch ) {
  3740. const idKeyValue *kv;
  3741. const idKeyValue *previous;
  3742. if ( *lastMatch ) {
  3743. previous = spawnArgs.FindKey( lastMatch );
  3744. } else {
  3745. previous = NULL;
  3746. }
  3747. kv = spawnArgs.MatchPrefix( prefix, previous );
  3748. if ( !kv ) {
  3749. idThread::ReturnString( "" );
  3750. } else {
  3751. idThread::ReturnString( kv->GetKey() );
  3752. }
  3753. }
  3754. /*
  3755. ================
  3756. idEntity::Event_SetKey
  3757. ================
  3758. */
  3759. void idEntity::Event_SetKey( const char *key, const char *value ) {
  3760. spawnArgs.Set( key, value );
  3761. #ifdef _D3XP
  3762. UpdateChangeableSpawnArgs( NULL );
  3763. #endif
  3764. }
  3765. /*
  3766. ================
  3767. idEntity::Event_GetKey
  3768. ================
  3769. */
  3770. void idEntity::Event_GetKey( const char *key ) {
  3771. const char *value;
  3772. spawnArgs.GetString( key, "", &value );
  3773. idThread::ReturnString( value );
  3774. }
  3775. /*
  3776. ================
  3777. idEntity::Event_GetIntKey
  3778. ================
  3779. */
  3780. void idEntity::Event_GetIntKey( const char *key ) {
  3781. int value;
  3782. spawnArgs.GetInt( key, "0", value );
  3783. // scripts only support floats
  3784. idThread::ReturnFloat( value );
  3785. }
  3786. /*
  3787. ================
  3788. idEntity::Event_GetFloatKey
  3789. ================
  3790. */
  3791. void idEntity::Event_GetFloatKey( const char *key ) {
  3792. float value;
  3793. spawnArgs.GetFloat( key, "0", value );
  3794. idThread::ReturnFloat( value );
  3795. }
  3796. /*
  3797. ================
  3798. idEntity::Event_GetVectorKey
  3799. ================
  3800. */
  3801. void idEntity::Event_GetVectorKey( const char *key ) {
  3802. idVec3 value;
  3803. spawnArgs.GetVector( key, "0 0 0", value );
  3804. idThread::ReturnVector( value );
  3805. }
  3806. /*
  3807. ================
  3808. idEntity::Event_GetEntityKey
  3809. ================
  3810. */
  3811. void idEntity::Event_GetEntityKey( const char *key ) {
  3812. idEntity *ent;
  3813. const char *entname;
  3814. if ( !spawnArgs.GetString( key, NULL, &entname ) ) {
  3815. idThread::ReturnEntity( NULL );
  3816. return;
  3817. }
  3818. ent = gameLocal.FindEntity( entname );
  3819. if ( !ent ) {
  3820. gameLocal.Warning( "Couldn't find entity '%s' specified in '%s' key in entity '%s'", entname, key, name.c_str() );
  3821. }
  3822. idThread::ReturnEntity( ent );
  3823. }
  3824. /*
  3825. ================
  3826. idEntity::Event_RestorePosition
  3827. ================
  3828. */
  3829. void idEntity::Event_RestorePosition( void ) {
  3830. idVec3 org;
  3831. idAngles angles;
  3832. idMat3 axis;
  3833. idEntity * part;
  3834. spawnArgs.GetVector( "origin", "0 0 0", org );
  3835. // get the rotation matrix in either full form, or single angle form
  3836. if ( spawnArgs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) {
  3837. angles = axis.ToAngles();
  3838. } else {
  3839. angles[ 0 ] = 0;
  3840. angles[ 1 ] = spawnArgs.GetFloat( "angle" );
  3841. angles[ 2 ] = 0;
  3842. }
  3843. Teleport( org, angles, NULL );
  3844. for ( part = teamChain; part != NULL; part = part->teamChain ) {
  3845. if ( part->bindMaster != this ) {
  3846. continue;
  3847. }
  3848. if ( part->GetPhysics()->IsType( idPhysics_Parametric::Type ) ) {
  3849. if ( static_cast<idPhysics_Parametric *>(part->GetPhysics())->IsPusher() ) {
  3850. gameLocal.Warning( "teleported '%s' which has the pushing mover '%s' bound to it\n", GetName(), part->GetName() );
  3851. }
  3852. } else if ( part->GetPhysics()->IsType( idPhysics_AF::Type ) ) {
  3853. gameLocal.Warning( "teleported '%s' which has the articulated figure '%s' bound to it\n", GetName(), part->GetName() );
  3854. }
  3855. }
  3856. }
  3857. /*
  3858. ================
  3859. idEntity::Event_UpdateCameraTarget
  3860. ================
  3861. */
  3862. void idEntity::Event_UpdateCameraTarget( void ) {
  3863. const char *target;
  3864. const idKeyValue *kv;
  3865. idVec3 dir;
  3866. target = spawnArgs.GetString( "cameraTarget" );
  3867. cameraTarget = gameLocal.FindEntity( target );
  3868. if ( cameraTarget ) {
  3869. kv = cameraTarget->spawnArgs.MatchPrefix( "target", NULL );
  3870. while( kv ) {
  3871. idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
  3872. if ( ent && idStr::Icmp( ent->GetEntityDefName(), "target_null" ) == 0) {
  3873. dir = ent->GetPhysics()->GetOrigin() - cameraTarget->GetPhysics()->GetOrigin();
  3874. dir.Normalize();
  3875. cameraTarget->SetAxis( dir.ToMat3() );
  3876. SetAxis(dir.ToMat3());
  3877. break;
  3878. }
  3879. kv = cameraTarget->spawnArgs.MatchPrefix( "target", kv );
  3880. }
  3881. }
  3882. UpdateVisuals();
  3883. }
  3884. /*
  3885. ================
  3886. idEntity::Event_DistanceTo
  3887. ================
  3888. */
  3889. void idEntity::Event_DistanceTo( idEntity *ent ) {
  3890. if ( !ent ) {
  3891. // just say it's really far away
  3892. idThread::ReturnFloat( MAX_WORLD_SIZE );
  3893. } else {
  3894. float dist = ( GetPhysics()->GetOrigin() - ent->GetPhysics()->GetOrigin() ).LengthFast();
  3895. idThread::ReturnFloat( dist );
  3896. }
  3897. }
  3898. /*
  3899. ================
  3900. idEntity::Event_DistanceToPoint
  3901. ================
  3902. */
  3903. void idEntity::Event_DistanceToPoint( const idVec3 &point ) {
  3904. float dist = ( GetPhysics()->GetOrigin() - point ).LengthFast();
  3905. idThread::ReturnFloat( dist );
  3906. }
  3907. /*
  3908. ================
  3909. idEntity::Event_StartFx
  3910. ================
  3911. */
  3912. void idEntity::Event_StartFx( const char *fx ) {
  3913. idEntityFx::StartFx( fx, NULL, NULL, this, true );
  3914. }
  3915. /*
  3916. ================
  3917. idEntity::Event_WaitFrame
  3918. ================
  3919. */
  3920. void idEntity::Event_WaitFrame( void ) {
  3921. idThread *thread;
  3922. thread = idThread::CurrentThread();
  3923. if ( thread ) {
  3924. thread->WaitFrame();
  3925. }
  3926. }
  3927. /*
  3928. =====================
  3929. idEntity::Event_Wait
  3930. =====================
  3931. */
  3932. void idEntity::Event_Wait( float time ) {
  3933. idThread *thread = idThread::CurrentThread();
  3934. if ( !thread ) {
  3935. gameLocal.Error( "Event 'wait' called from outside thread" );
  3936. }
  3937. thread->WaitSec( time );
  3938. }
  3939. /*
  3940. =====================
  3941. idEntity::Event_HasFunction
  3942. =====================
  3943. */
  3944. void idEntity::Event_HasFunction( const char *name ) {
  3945. const function_t *func;
  3946. func = scriptObject.GetFunction( name );
  3947. if ( func ) {
  3948. idThread::ReturnInt( true );
  3949. } else {
  3950. idThread::ReturnInt( false );
  3951. }
  3952. }
  3953. void idEntity::Event_CallFunctionArg( const char *funcname, int arg )
  3954. {
  3955. idThread* thread;
  3956. const function_t *funcCall;
  3957. funcCall = this->scriptObject.GetFunction( funcname );
  3958. if (!funcCall)
  3959. {
  3960. common->Printf("CallFunctionArg: cannot find function '%s', arg '%d'\n", funcname, arg);
  3961. return;
  3962. }
  3963. // start a thread that will run immediately and be destroyed
  3964. thread = new idThread( funcCall );
  3965. thread->CallFunctionArgs(funcCall, true, "ef", this, (float)arg);
  3966. thread->Execute();
  3967. delete thread;
  3968. }
  3969. /*
  3970. =====================
  3971. idEntity::Event_CallFunction
  3972. =====================
  3973. */
  3974. void idEntity::Event_CallFunction( const char *funcname ) {
  3975. const function_t *func;
  3976. idThread *thread;
  3977. thread = idThread::CurrentThread();
  3978. if ( !thread ) {
  3979. gameLocal.Error( "Event 'callFunction' called from outside thread" );
  3980. }
  3981. func = scriptObject.GetFunction( funcname );
  3982. if ( !func ) {
  3983. gameLocal.Error( "Unknown function '%s' in '%s'", funcname, scriptObject.GetTypeName() );
  3984. }
  3985. if ( func->type->NumParameters() != 1 ) {
  3986. gameLocal.Error( "Function '%s' has the wrong number of parameters for 'callFunction'", funcname );
  3987. }
  3988. if ( !scriptObject.GetTypeDef()->Inherits( func->type->GetParmType( 0 ) ) ) {
  3989. gameLocal.Error( "Function '%s' is the wrong type for 'callFunction'", funcname );
  3990. }
  3991. // function args will be invalid after this call
  3992. thread->CallFunction( this, func, false );
  3993. }
  3994. void idEntity::Event_getNearestEnemy( )
  3995. {
  3996. idEntity *ent;
  3997. idActor *actor;
  3998. float bestDist;
  3999. float dist;
  4000. pvsHandle_t pvs;
  4001. idVec3 delta;
  4002. idActor *bestEnemy;
  4003. pvs = gameLocal.pvs.SetupCurrentPVS( GetPVSAreas(), GetNumPVSAreas() );
  4004. bestDist = idMath::INFINITY;
  4005. bestEnemy = NULL;
  4006. for ( ent = gameLocal.activeEntities.Next(); ent != NULL; ent = ent->activeNode.Next() )
  4007. {
  4008. if (!ent || ent->fl.hidden || ent->fl.isDormant || !ent->IsType(idActor::Type) || ent->IsType(idPlayer::Type))
  4009. continue;
  4010. actor = static_cast<idActor *>(ent);
  4011. if (actor->health <= 0)
  4012. continue;
  4013. if ( !gameLocal.pvs.InCurrentPVS( pvs, actor->GetPVSAreas(), actor->GetNumPVSAreas() ) )
  4014. continue;
  4015. delta = this->GetPhysics()->GetOrigin() - actor->GetPhysics()->GetOrigin();
  4016. dist = delta.LengthSqr();
  4017. if ( ( dist < bestDist ) && CanSeeEntity( actor ))
  4018. {
  4019. bestDist = dist;
  4020. bestEnemy = actor;
  4021. }
  4022. }
  4023. gameLocal.pvs.FreeCurrentPVS( pvs );
  4024. idThread::ReturnEntity( bestEnemy );
  4025. }
  4026. void idEntity::Event_canSeeEntity( idEntity *ent )
  4027. {
  4028. if ( !ent )
  4029. {
  4030. idThread::ReturnInt( false );
  4031. return;
  4032. }
  4033. idThread::ReturnInt( CanSeeEntity(ent) );
  4034. }
  4035. bool idEntity::CanSeeEntity( idEntity *other )
  4036. {
  4037. trace_t tr;
  4038. idVec3 selfPos;
  4039. idVec3 otherPos;
  4040. selfPos = this->GetPhysics()->GetOrigin();
  4041. otherPos = this->GetPhysics()->GetOrigin();
  4042. //aim for center of mass.
  4043. selfPos.z += this->GetPhysics()->GetBounds().GetCenter().z;
  4044. otherPos.z += other->GetPhysics()->GetBounds().GetCenter().z;
  4045. gameLocal.clip.TracePoint( tr, selfPos, otherPos, MASK_OPAQUE, this );
  4046. if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == other) )
  4047. return true;
  4048. return false;
  4049. }
  4050. void idEntity::Event_SetCameraTarget( idEntity *ent )
  4051. {
  4052. ent->cameraTarget = ent; //assign the cameraTarget of the cameraTarget (yup)
  4053. this->cameraTarget = ent; //assign the cameraTarget of this entity.
  4054. UpdateVisuals(); //force camera update.
  4055. }
  4056. void idEntity::Event_ClearCameraTarget( )
  4057. {
  4058. this->cameraTarget = NULL; //assign the cameraTarget of this entity.
  4059. this->renderEntity.remoteRenderView = NULL;
  4060. UpdateVisuals(); //force camera update.
  4061. }
  4062. //bc
  4063. void idEntity::Event_SetFrobbable( int enable )
  4064. {
  4065. this->isFrobbable = enable;
  4066. }
  4067. /*bc flite
  4068. void idEntity::Event_flitespeech( const char *text )
  4069. {
  4070. soundSystem->SynthesizeSpeech( text );
  4071. int length;
  4072. this->StartSoundShader( declManager->FindSound( "flite" ), SCHANNEL_ANY, 0, false, &length );
  4073. idThread::ReturnInt(length);
  4074. }
  4075. */
  4076. void idEntity::Event_SetClipModel( const char *clipModelName )
  4077. {
  4078. idTraceModel trm;
  4079. if ( !collisionModelManager->TrmFromModel( clipModelName, trm ) )
  4080. {
  4081. gameLocal.Error( "SetClipModel '%s': cannot load collision model %s", name.c_str(), clipModelName );
  4082. return;
  4083. }
  4084. else
  4085. {
  4086. this->GetPhysics()->SetClipModel( new idClipModel( trm ), 0.5f );
  4087. }
  4088. }
  4089. void idEntity::Event_SetSolid( int enable )
  4090. {
  4091. if ( enable > 0 )
  4092. {
  4093. GetPhysics()->SetContents( CONTENTS_SOLID );
  4094. }
  4095. else
  4096. {
  4097. GetPhysics()->SetContents( 0 );
  4098. }
  4099. }
  4100. //print string to user deck GUI.
  4101. void idEntity::Event_deck_print( const char* text )
  4102. {
  4103. if ( gameLocal.GetLocalPlayer()->deckList == NULL)
  4104. return;
  4105. //BC 7-22-2016 fixed possible deck gui crash when loading savegame.
  4106. if (!gameLocal.GetLocalPlayer()->deckList->IsConfigured())
  4107. return;
  4108. gameLocal.GetLocalPlayer()->deckList->Push( text );
  4109. }
  4110. void idEntity::Event_deck_printline( const char* text )
  4111. {
  4112. if ( gameLocal.GetLocalPlayer()->deckList == NULL)
  4113. return;
  4114. if (!gameLocal.GetLocalPlayer()->deckList->IsConfigured())
  4115. return;
  4116. int totalCount = gameLocal.GetLocalPlayer()->deckList->Num();
  4117. gameLocal.GetLocalPlayer()->deckList->Add(totalCount - 1, text);
  4118. }
  4119. void idEntity::Event_deck_cls( void )
  4120. {
  4121. if ( gameLocal.GetLocalPlayer()->deckList == NULL)
  4122. return;
  4123. if (!gameLocal.GetLocalPlayer()->deckList->IsConfigured())
  4124. return;
  4125. gameLocal.GetLocalPlayer()->deckList->Clear();
  4126. }
  4127. /*
  4128. ================
  4129. idEntity::Event_SetNeverDormant
  4130. ================
  4131. */
  4132. void idEntity::Event_SetNeverDormant( int enable ) {
  4133. fl.neverDormant = ( enable != 0 );
  4134. dormantStart = 0;
  4135. }
  4136. #ifdef _D3XP
  4137. /*
  4138. ================
  4139. idEntity::Event_SetGui
  4140. ================
  4141. * BSM Nerve: Allows guis to be changed at runtime. Guis that are
  4142. * loaded after the level loads should be precahced using PrecacheGui.
  4143. */
  4144. void idEntity::Event_SetGui( int guiNum, const char *guiName) {
  4145. idUserInterface** gui = NULL;
  4146. if ( guiNum >= 1 && guiNum <= MAX_RENDERENTITY_GUI ) {
  4147. gui = &renderEntity.gui[ guiNum-1 ];
  4148. }
  4149. if( gui ) {
  4150. *gui = uiManager->FindGui( guiName, true, false );
  4151. UpdateGuiParms( *gui, &spawnArgs );
  4152. UpdateChangeableSpawnArgs( NULL );
  4153. gameRenderWorld->UpdateEntityDef(modelDefHandle, &renderEntity);
  4154. } else {
  4155. gameLocal.Error( "Entity '%s' doesn't have a GUI %d", name.c_str(), guiNum );
  4156. }
  4157. }
  4158. /*
  4159. ================
  4160. idEntity::Event_PrecacheGui
  4161. ================
  4162. * BSM Nerve: Forces the engine to initialize a gui even if it is not specified as used in a level.
  4163. * This is useful for preventing load hitches when switching guis during the game using "setGui"
  4164. */
  4165. void idEntity::Event_PrecacheGui( const char *guiName ) {
  4166. uiManager->FindGui( guiName, true, true );
  4167. }
  4168. void idEntity::Event_GetGuiParm(int guiNum, const char *key) {
  4169. if(renderEntity.gui[guiNum-1]) {
  4170. idThread::ReturnString(renderEntity.gui[guiNum-1]->GetStateString(key));
  4171. return;
  4172. }
  4173. idThread::ReturnString("");
  4174. }
  4175. void idEntity::Event_GetGuiParmFloat(int guiNum, const char *key) {
  4176. if(renderEntity.gui[guiNum-1]) {
  4177. idThread::ReturnFloat(renderEntity.gui[guiNum-1]->GetStateFloat(key));
  4178. return;
  4179. }
  4180. idThread::ReturnFloat(0.0f);
  4181. }
  4182. void idEntity::Event_GuiNamedEvent(int guiNum, const char *event) {
  4183. if(renderEntity.gui[guiNum-1]) {
  4184. renderEntity.gui[guiNum-1]->HandleNamedEvent(event);
  4185. }
  4186. }
  4187. #endif
  4188. /***********************************************************************
  4189. Network
  4190. ***********************************************************************/
  4191. /*
  4192. ================
  4193. idEntity::ClientPredictionThink
  4194. ================
  4195. */
  4196. void idEntity::ClientPredictionThink( void ) {
  4197. RunPhysics();
  4198. Present();
  4199. }
  4200. /*
  4201. ================
  4202. idEntity::WriteBindToSnapshot
  4203. ================
  4204. */
  4205. void idEntity::WriteBindToSnapshot( idBitMsgDelta &msg ) const {
  4206. int bindInfo;
  4207. if ( bindMaster ) {
  4208. bindInfo = bindMaster->entityNumber;
  4209. bindInfo |= ( fl.bindOrientated & 1 ) << GENTITYNUM_BITS;
  4210. if ( bindJoint != INVALID_JOINT ) {
  4211. bindInfo |= 1 << ( GENTITYNUM_BITS + 1 );
  4212. bindInfo |= bindJoint << ( 3 + GENTITYNUM_BITS );
  4213. } else if ( bindBody != -1 ) {
  4214. bindInfo |= 2 << ( GENTITYNUM_BITS + 1 );
  4215. bindInfo |= bindBody << ( 3 + GENTITYNUM_BITS );
  4216. }
  4217. } else {
  4218. bindInfo = ENTITYNUM_NONE;
  4219. }
  4220. msg.WriteBits( bindInfo, GENTITYNUM_BITS + 3 + 9 );
  4221. }
  4222. /*
  4223. ================
  4224. idEntity::ReadBindFromSnapshot
  4225. ================
  4226. */
  4227. void idEntity::ReadBindFromSnapshot( const idBitMsgDelta &msg ) {
  4228. int bindInfo, bindEntityNum, bindPos;
  4229. bool bindOrientated;
  4230. idEntity *master;
  4231. bindInfo = msg.ReadBits( GENTITYNUM_BITS + 3 + 9 );
  4232. bindEntityNum = bindInfo & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  4233. if ( bindEntityNum != ENTITYNUM_NONE ) {
  4234. master = gameLocal.entities[ bindEntityNum ];
  4235. bindOrientated = ( bindInfo >> GENTITYNUM_BITS ) & 1;
  4236. bindPos = ( bindInfo >> ( GENTITYNUM_BITS + 3 ) );
  4237. switch( ( bindInfo >> ( GENTITYNUM_BITS + 1 ) ) & 3 ) {
  4238. case 1: {
  4239. BindToJoint( master, (jointHandle_t) bindPos, bindOrientated );
  4240. break;
  4241. }
  4242. case 2: {
  4243. BindToBody( master, bindPos, bindOrientated );
  4244. break;
  4245. }
  4246. default: {
  4247. Bind( master, bindOrientated );
  4248. break;
  4249. }
  4250. }
  4251. } else if ( bindMaster ) {
  4252. Unbind();
  4253. }
  4254. }
  4255. /*
  4256. ================
  4257. idEntity::WriteColorToSnapshot
  4258. ================
  4259. */
  4260. void idEntity::WriteColorToSnapshot( idBitMsgDelta &msg ) const {
  4261. idVec4 color;
  4262. color[0] = renderEntity.shaderParms[ SHADERPARM_RED ];
  4263. color[1] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  4264. color[2] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  4265. color[3] = renderEntity.shaderParms[ SHADERPARM_ALPHA ];
  4266. msg.WriteLong( PackColor( color ) );
  4267. }
  4268. /*
  4269. ================
  4270. idEntity::ReadColorFromSnapshot
  4271. ================
  4272. */
  4273. void idEntity::ReadColorFromSnapshot( const idBitMsgDelta &msg ) {
  4274. idVec4 color;
  4275. UnpackColor( msg.ReadLong(), color );
  4276. renderEntity.shaderParms[ SHADERPARM_RED ] = color[0];
  4277. renderEntity.shaderParms[ SHADERPARM_GREEN ] = color[1];
  4278. renderEntity.shaderParms[ SHADERPARM_BLUE ] = color[2];
  4279. renderEntity.shaderParms[ SHADERPARM_ALPHA ] = color[3];
  4280. }
  4281. /*
  4282. ================
  4283. idEntity::WriteGUIToSnapshot
  4284. ================
  4285. */
  4286. void idEntity::WriteGUIToSnapshot( idBitMsgDelta &msg ) const {
  4287. // no need to loop over MAX_RENDERENTITY_GUI at this time
  4288. if ( renderEntity.gui[ 0 ] ) {
  4289. msg.WriteByte( renderEntity.gui[ 0 ]->State().GetInt( "networkState" ) );
  4290. } else {
  4291. msg.WriteByte( 0 );
  4292. }
  4293. }
  4294. /*
  4295. ================
  4296. idEntity::ReadGUIFromSnapshot
  4297. ================
  4298. */
  4299. void idEntity::ReadGUIFromSnapshot( const idBitMsgDelta &msg ) {
  4300. int state;
  4301. idUserInterface *gui;
  4302. state = msg.ReadByte( );
  4303. gui = renderEntity.gui[ 0 ];
  4304. if ( gui && state != mpGUIState ) {
  4305. mpGUIState = state;
  4306. gui->SetStateInt( "networkState", state );
  4307. gui->HandleNamedEvent( "networkState" );
  4308. }
  4309. }
  4310. /*
  4311. ================
  4312. idEntity::WriteToSnapshot
  4313. ================
  4314. */
  4315. void idEntity::WriteToSnapshot( idBitMsgDelta &msg ) const {
  4316. }
  4317. /*
  4318. ================
  4319. idEntity::ReadFromSnapshot
  4320. ================
  4321. */
  4322. void idEntity::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  4323. }
  4324. /*
  4325. ================
  4326. idEntity::ServerSendEvent
  4327. Saved events are also sent to any client that connects late so all clients
  4328. always receive the events nomatter what time they join the game.
  4329. ================
  4330. */
  4331. void idEntity::ServerSendEvent( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) const {
  4332. idBitMsg outMsg;
  4333. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  4334. if ( !gameLocal.isServer ) {
  4335. return;
  4336. }
  4337. // prevent dupe events caused by frame re-runs
  4338. if ( !gameLocal.isNewFrame ) {
  4339. return;
  4340. }
  4341. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  4342. outMsg.BeginWriting();
  4343. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );
  4344. outMsg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  4345. outMsg.WriteByte( eventId );
  4346. outMsg.WriteLong( gameLocal.time );
  4347. if ( msg ) {
  4348. outMsg.WriteBits( msg->GetSize(), idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  4349. outMsg.WriteData( msg->GetData(), msg->GetSize() );
  4350. } else {
  4351. outMsg.WriteBits( 0, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  4352. }
  4353. if ( excludeClient != -1 ) {
  4354. networkSystem->ServerSendReliableMessageExcluding( excludeClient, outMsg );
  4355. } else {
  4356. networkSystem->ServerSendReliableMessage( -1, outMsg );
  4357. }
  4358. if ( saveEvent ) {
  4359. gameLocal.SaveEntityNetworkEvent( this, eventId, msg );
  4360. }
  4361. }
  4362. /*
  4363. ================
  4364. idEntity::ClientSendEvent
  4365. ================
  4366. */
  4367. void idEntity::ClientSendEvent( int eventId, const idBitMsg *msg ) const {
  4368. idBitMsg outMsg;
  4369. byte msgBuf[MAX_GAME_MESSAGE_SIZE];
  4370. if ( !gameLocal.isClient ) {
  4371. return;
  4372. }
  4373. // prevent dupe events caused by frame re-runs
  4374. if ( !gameLocal.isNewFrame ) {
  4375. return;
  4376. }
  4377. outMsg.Init( msgBuf, sizeof( msgBuf ) );
  4378. outMsg.BeginWriting();
  4379. outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );
  4380. outMsg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  4381. outMsg.WriteByte( eventId );
  4382. outMsg.WriteLong( gameLocal.time );
  4383. if ( msg ) {
  4384. outMsg.WriteBits( msg->GetSize(), idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  4385. outMsg.WriteData( msg->GetData(), msg->GetSize() );
  4386. } else {
  4387. outMsg.WriteBits( 0, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  4388. }
  4389. networkSystem->ClientSendReliableMessage( outMsg );
  4390. }
  4391. /*
  4392. ================
  4393. idEntity::ServerReceiveEvent
  4394. ================
  4395. */
  4396. bool idEntity::ServerReceiveEvent( int event, int time, const idBitMsg &msg ) {
  4397. switch( event ) {
  4398. case 0: {
  4399. }
  4400. default: {
  4401. return false;
  4402. }
  4403. }
  4404. }
  4405. /*
  4406. ================
  4407. idEntity::ClientReceiveEvent
  4408. ================
  4409. */
  4410. bool idEntity::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  4411. int index;
  4412. const idSoundShader *shader;
  4413. s_channelType channel;
  4414. switch( event ) {
  4415. case EVENT_STARTSOUNDSHADER: {
  4416. // the sound stuff would early out
  4417. assert( gameLocal.isNewFrame );
  4418. if ( time < gameLocal.realClientTime - 1000 ) {
  4419. // too old, skip it ( reliable messages don't need to be parsed in full )
  4420. common->DPrintf( "ent 0x%x: start sound shader too old (%d ms)\n", entityNumber, gameLocal.realClientTime - time );
  4421. return true;
  4422. }
  4423. index = gameLocal.ClientRemapDecl( DECL_SOUND, msg.ReadLong() );
  4424. if ( index >= 0 && index < declManager->GetNumDecls( DECL_SOUND ) ) {
  4425. shader = declManager->SoundByIndex( index, false );
  4426. channel = (s_channelType)msg.ReadByte();
  4427. StartSoundShader( shader, channel, 0, false, NULL );
  4428. }
  4429. return true;
  4430. }
  4431. case EVENT_STOPSOUNDSHADER: {
  4432. // the sound stuff would early out
  4433. assert( gameLocal.isNewFrame );
  4434. channel = (s_channelType)msg.ReadByte();
  4435. StopSound( channel, false );
  4436. return true;
  4437. }
  4438. default: {
  4439. return false;
  4440. }
  4441. }
  4442. return false;
  4443. }
  4444. #ifdef _D3XP
  4445. /*
  4446. ================
  4447. idEntity::DetermineTimeGroup
  4448. ================
  4449. */
  4450. void idEntity::DetermineTimeGroup( bool slowmo ) {
  4451. if ( slowmo || gameLocal.isMultiplayer ) {
  4452. timeGroup = TIME_GROUP1;
  4453. }
  4454. else {
  4455. timeGroup = TIME_GROUP2;
  4456. }
  4457. }
  4458. /*
  4459. ================
  4460. idEntity::SetGrabbedState
  4461. ================
  4462. */
  4463. void idEntity::SetGrabbedState( bool grabbed ) {
  4464. fl.grabbed = grabbed;
  4465. }
  4466. /*
  4467. ================
  4468. idEntity::IsGrabbed
  4469. ================
  4470. */
  4471. bool idEntity::IsGrabbed() {
  4472. return fl.grabbed;
  4473. }
  4474. #endif
  4475. /*
  4476. ===============================================================================
  4477. idAnimatedEntity
  4478. ===============================================================================
  4479. */
  4480. const idEventDef EV_GetJointHandle( "getJointHandle", "s", 'd' );
  4481. const idEventDef EV_ClearAllJoints( "clearAllJoints" );
  4482. const idEventDef EV_ClearJoint( "clearJoint", "d" );
  4483. const idEventDef EV_SetJointPos( "setJointPos", "ddv" );
  4484. const idEventDef EV_SetJointAngle( "setJointAngle", "ddv" );
  4485. const idEventDef EV_GetJointPos( "getJointPos", "d", 'v' );
  4486. const idEventDef EV_GetJointAngle( "getJointAngle", "d", 'v' );
  4487. CLASS_DECLARATION( idEntity, idAnimatedEntity )
  4488. EVENT( EV_GetJointHandle, idAnimatedEntity::Event_GetJointHandle )
  4489. EVENT( EV_ClearAllJoints, idAnimatedEntity::Event_ClearAllJoints )
  4490. EVENT( EV_ClearJoint, idAnimatedEntity::Event_ClearJoint )
  4491. EVENT( EV_SetJointPos, idAnimatedEntity::Event_SetJointPos )
  4492. EVENT( EV_SetJointAngle, idAnimatedEntity::Event_SetJointAngle )
  4493. EVENT( EV_GetJointPos, idAnimatedEntity::Event_GetJointPos )
  4494. EVENT( EV_GetJointAngle, idAnimatedEntity::Event_GetJointAngle )
  4495. END_CLASS
  4496. /*
  4497. ================
  4498. idAnimatedEntity::idAnimatedEntity
  4499. ================
  4500. */
  4501. idAnimatedEntity::idAnimatedEntity() {
  4502. animator.SetEntity( this );
  4503. damageEffects = NULL;
  4504. }
  4505. /*
  4506. ================
  4507. idAnimatedEntity::~idAnimatedEntity
  4508. ================
  4509. */
  4510. idAnimatedEntity::~idAnimatedEntity() {
  4511. damageEffect_t *de;
  4512. for ( de = damageEffects; de; de = damageEffects ) {
  4513. damageEffects = de->next;
  4514. delete de;
  4515. }
  4516. }
  4517. /*
  4518. ================
  4519. idAnimatedEntity::Save
  4520. archives object for save game file
  4521. ================
  4522. */
  4523. void idAnimatedEntity::Save( idSaveGame *savefile ) const {
  4524. animator.Save( savefile );
  4525. // Wounds are very temporary, ignored at this time
  4526. //damageEffect_t *damageEffects;
  4527. }
  4528. /*
  4529. ================
  4530. idAnimatedEntity::Restore
  4531. unarchives object from save game file
  4532. ================
  4533. */
  4534. void idAnimatedEntity::Restore( idRestoreGame *savefile ) {
  4535. animator.Restore( savefile );
  4536. // check if the entity has an MD5 model
  4537. if ( animator.ModelHandle() ) {
  4538. // set the callback to update the joints
  4539. renderEntity.callback = idEntity::ModelCallback;
  4540. animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
  4541. animator.GetBounds( gameLocal.time, renderEntity.bounds );
  4542. if ( modelDefHandle != -1 ) {
  4543. gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  4544. }
  4545. }
  4546. }
  4547. /*
  4548. ================
  4549. idAnimatedEntity::ClientPredictionThink
  4550. ================
  4551. */
  4552. void idAnimatedEntity::ClientPredictionThink( void ) {
  4553. RunPhysics();
  4554. UpdateAnimation();
  4555. Present();
  4556. }
  4557. /*
  4558. ================
  4559. idAnimatedEntity::Think
  4560. ================
  4561. */
  4562. void idAnimatedEntity::Think( void ) {
  4563. RunPhysics();
  4564. UpdateAnimation();
  4565. Present();
  4566. UpdateDamageEffects();
  4567. }
  4568. /*
  4569. ================
  4570. idAnimatedEntity::UpdateAnimation
  4571. ================
  4572. */
  4573. void idAnimatedEntity::UpdateAnimation( void ) {
  4574. // don't do animations if they're not enabled
  4575. if ( !( thinkFlags & TH_ANIMATE ) ) {
  4576. return;
  4577. }
  4578. // is the model an MD5?
  4579. if ( !animator.ModelHandle() ) {
  4580. // no, so nothing to do
  4581. return;
  4582. }
  4583. // call any frame commands that have happened in the past frame
  4584. if ( !fl.hidden ) {
  4585. animator.ServiceAnims( gameLocal.previousTime, gameLocal.time );
  4586. }
  4587. // if the model is animating then we have to update it
  4588. if ( !animator.FrameHasChanged( gameLocal.time ) ) {
  4589. // still fine the way it was
  4590. return;
  4591. }
  4592. // get the latest frame bounds
  4593. animator.GetBounds( gameLocal.time, renderEntity.bounds );
  4594. if ( renderEntity.bounds.IsCleared() && !fl.hidden ) {
  4595. gameLocal.DPrintf( "%d: inside out bounds\n", gameLocal.time );
  4596. }
  4597. // update the renderEntity
  4598. UpdateVisuals();
  4599. // the animation is updated
  4600. animator.ClearForceUpdate();
  4601. }
  4602. /*
  4603. ================
  4604. idAnimatedEntity::GetAnimator
  4605. ================
  4606. */
  4607. idAnimator *idAnimatedEntity::GetAnimator( void ) {
  4608. return &animator;
  4609. }
  4610. /*
  4611. ================
  4612. idAnimatedEntity::SetModel
  4613. ================
  4614. */
  4615. void idAnimatedEntity::SetModel( const char *modelname ) {
  4616. FreeModelDef();
  4617. renderEntity.hModel = animator.SetModel( modelname );
  4618. if ( !renderEntity.hModel ) {
  4619. idEntity::SetModel( modelname );
  4620. return;
  4621. }
  4622. if ( !renderEntity.customSkin ) {
  4623. renderEntity.customSkin = animator.ModelDef()->GetDefaultSkin();
  4624. }
  4625. // set the callback to update the joints
  4626. renderEntity.callback = idEntity::ModelCallback;
  4627. animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
  4628. animator.GetBounds( gameLocal.time, renderEntity.bounds );
  4629. UpdateVisuals();
  4630. }
  4631. /*
  4632. =====================
  4633. idAnimatedEntity::GetJointWorldTransform
  4634. =====================
  4635. */
  4636. bool idAnimatedEntity::GetJointWorldTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
  4637. if ( !animator.GetJointTransform( jointHandle, currentTime, offset, axis ) ) {
  4638. return false;
  4639. }
  4640. ConvertLocalToWorldTransform( offset, axis );
  4641. return true;
  4642. }
  4643. /*
  4644. ==============
  4645. idAnimatedEntity::GetJointTransformForAnim
  4646. ==============
  4647. */
  4648. bool idAnimatedEntity::GetJointTransformForAnim( jointHandle_t jointHandle, int animNum, int frameTime, idVec3 &offset, idMat3 &axis ) const {
  4649. const idAnim *anim;
  4650. int numJoints;
  4651. idJointMat *frame;
  4652. anim = animator.GetAnim( animNum );
  4653. if ( !anim ) {
  4654. assert( 0 );
  4655. return false;
  4656. }
  4657. numJoints = animator.NumJoints();
  4658. if ( ( jointHandle < 0 ) || ( jointHandle >= numJoints ) ) {
  4659. assert( 0 );
  4660. return false;
  4661. }
  4662. frame = ( idJointMat * )_alloca16( numJoints * sizeof( idJointMat ) );
  4663. gameEdit->ANIM_CreateAnimFrame( animator.ModelHandle(), anim->MD5Anim( 0 ), renderEntity.numJoints, frame, frameTime, animator.ModelDef()->GetVisualOffset(), animator.RemoveOrigin() );
  4664. offset = frame[ jointHandle ].ToVec3();
  4665. axis = frame[ jointHandle ].ToMat3();
  4666. return true;
  4667. }
  4668. /*
  4669. ==============
  4670. idAnimatedEntity::AddDamageEffect
  4671. Dammage effects track the animating impact position, spitting out particles.
  4672. ==============
  4673. */
  4674. void idAnimatedEntity::AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName ) {
  4675. jointHandle_t jointNum;
  4676. idVec3 origin, dir, localDir, localOrigin, localNormal;
  4677. idMat3 axis;
  4678. if ( !g_bloodEffects.GetBool() || renderEntity.joints == NULL ) {
  4679. return;
  4680. }
  4681. const idDeclEntityDef *def = gameLocal.FindEntityDef( damageDefName, false );
  4682. if ( def == NULL ) {
  4683. return;
  4684. }
  4685. jointNum = CLIPMODEL_ID_TO_JOINT_HANDLE( collision.c.id );
  4686. if ( jointNum == INVALID_JOINT ) {
  4687. return;
  4688. }
  4689. dir = velocity;
  4690. dir.Normalize();
  4691. axis = renderEntity.joints[jointNum].ToMat3() * renderEntity.axis;
  4692. origin = renderEntity.origin + renderEntity.joints[jointNum].ToVec3() * renderEntity.axis;
  4693. localOrigin = ( collision.c.point - origin ) * axis.Transpose();
  4694. localNormal = collision.c.normal * axis.Transpose();
  4695. localDir = dir * axis.Transpose();
  4696. AddLocalDamageEffect( jointNum, localOrigin, localNormal, localDir, def, collision.c.material );
  4697. if ( gameLocal.isServer ) {
  4698. idBitMsg msg;
  4699. byte msgBuf[MAX_EVENT_PARAM_SIZE];
  4700. msg.Init( msgBuf, sizeof( msgBuf ) );
  4701. msg.BeginWriting();
  4702. msg.WriteShort( (int)jointNum );
  4703. msg.WriteFloat( localOrigin[0] );
  4704. msg.WriteFloat( localOrigin[1] );
  4705. msg.WriteFloat( localOrigin[2] );
  4706. msg.WriteDir( localNormal, 24 );
  4707. msg.WriteDir( localDir, 24 );
  4708. msg.WriteLong( gameLocal.ServerRemapDecl( -1, DECL_ENTITYDEF, def->Index() ) );
  4709. msg.WriteLong( gameLocal.ServerRemapDecl( -1, DECL_MATERIAL, collision.c.material->Index() ) );
  4710. ServerSendEvent( EVENT_ADD_DAMAGE_EFFECT, &msg, false, -1 );
  4711. }
  4712. }
  4713. /*
  4714. ==============
  4715. idAnimatedEntity::GetDefaultSurfaceType
  4716. ==============
  4717. */
  4718. int idAnimatedEntity::GetDefaultSurfaceType( void ) const {
  4719. return SURFTYPE_METAL;
  4720. }
  4721. /*
  4722. ==============
  4723. idAnimatedEntity::AddLocalDamageEffect
  4724. ==============
  4725. */
  4726. void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec3 &localOrigin, const idVec3 &localNormal, const idVec3 &localDir, const idDeclEntityDef *def, const idMaterial *collisionMaterial ) {
  4727. const char *sound, *splat, *decal, *bleed, *key;
  4728. damageEffect_t *de;
  4729. idVec3 origin, dir;
  4730. idMat3 axis;
  4731. #ifdef _D3XP
  4732. SetTimeState ts( timeGroup );
  4733. #endif
  4734. axis = renderEntity.joints[jointNum].ToMat3() * renderEntity.axis;
  4735. origin = renderEntity.origin + renderEntity.joints[jointNum].ToVec3() * renderEntity.axis;
  4736. origin = origin + localOrigin * axis;
  4737. dir = localDir * axis;
  4738. int type = collisionMaterial->GetSurfaceType();
  4739. if ( type == SURFTYPE_NONE ) {
  4740. type = GetDefaultSurfaceType();
  4741. }
  4742. const char *materialType = gameLocal.sufaceTypeNames[ type ];
  4743. // start impact sound based on material type
  4744. key = va( "snd_%s", materialType );
  4745. sound = spawnArgs.GetString( key );
  4746. if ( *sound == '\0' ) {
  4747. sound = def->dict.GetString( key );
  4748. }
  4749. if ( *sound != '\0' ) {
  4750. StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
  4751. }
  4752. // blood splats are thrown onto nearby surfaces
  4753. key = va( "mtr_splat_%s", materialType );
  4754. splat = spawnArgs.RandomPrefix( key, gameLocal.random );
  4755. if ( *splat == '\0' ) {
  4756. splat = def->dict.RandomPrefix( key, gameLocal.random );
  4757. }
  4758. if ( *splat != '\0' ) {
  4759. gameLocal.BloodSplat( origin, dir, 64.0f, splat );
  4760. }
  4761. // can't see wounds on the player model in single player mode
  4762. if ( !( IsType( idPlayer::Type ) && !gameLocal.isMultiplayer ) ) {
  4763. // place a wound overlay on the model
  4764. key = va( "mtr_wound_%s", materialType );
  4765. decal = spawnArgs.RandomPrefix( key, gameLocal.random );
  4766. if ( *decal == '\0' ) {
  4767. decal = def->dict.RandomPrefix( key, gameLocal.random );
  4768. }
  4769. if ( *decal != '\0' ) {
  4770. ProjectOverlay( origin, dir, 20.0f, decal );
  4771. }
  4772. }
  4773. // a blood spurting wound is added
  4774. key = va( "smoke_wound_%s", materialType );
  4775. bleed = spawnArgs.GetString( key );
  4776. if ( *bleed == '\0' ) {
  4777. bleed = def->dict.GetString( key );
  4778. }
  4779. if ( *bleed != '\0' ) {
  4780. de = new damageEffect_t;
  4781. de->next = this->damageEffects;
  4782. this->damageEffects = de;
  4783. de->jointNum = jointNum;
  4784. de->localOrigin = localOrigin;
  4785. de->localNormal = localNormal;
  4786. de->type = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, bleed ) );
  4787. de->time = gameLocal.time;
  4788. }
  4789. }
  4790. /*
  4791. ==============
  4792. idAnimatedEntity::UpdateDamageEffects
  4793. ==============
  4794. */
  4795. void idAnimatedEntity::UpdateDamageEffects( void ) {
  4796. damageEffect_t *de, **prev;
  4797. // free any that have timed out
  4798. prev = &this->damageEffects;
  4799. while ( *prev ) {
  4800. de = *prev;
  4801. if ( de->time == 0 ) { // FIXME:SMOKE
  4802. *prev = de->next;
  4803. delete de;
  4804. } else {
  4805. prev = &de->next;
  4806. }
  4807. }
  4808. if ( !g_bloodEffects.GetBool() ) {
  4809. return;
  4810. }
  4811. // emit a particle for each bleeding wound
  4812. for ( de = this->damageEffects; de; de = de->next ) {
  4813. idVec3 origin, start;
  4814. idMat3 axis;
  4815. animator.GetJointTransform( de->jointNum, gameLocal.time, origin, axis );
  4816. axis *= renderEntity.axis;
  4817. origin = renderEntity.origin + origin * renderEntity.axis;
  4818. start = origin + de->localOrigin * axis;
  4819. if ( !gameLocal.smokeParticles->EmitSmoke( de->type, de->time, gameLocal.random.CRandomFloat(), start, axis, timeGroup /*_D3XP*/ ) ) {
  4820. de->time = 0;
  4821. }
  4822. }
  4823. }
  4824. /*
  4825. ================
  4826. idAnimatedEntity::ClientReceiveEvent
  4827. ================
  4828. */
  4829. bool idAnimatedEntity::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  4830. int damageDefIndex;
  4831. int materialIndex;
  4832. jointHandle_t jointNum;
  4833. idVec3 localOrigin, localNormal, localDir;
  4834. switch( event ) {
  4835. case EVENT_ADD_DAMAGE_EFFECT: {
  4836. jointNum = (jointHandle_t) msg.ReadShort();
  4837. localOrigin[0] = msg.ReadFloat();
  4838. localOrigin[1] = msg.ReadFloat();
  4839. localOrigin[2] = msg.ReadFloat();
  4840. localNormal = msg.ReadDir( 24 );
  4841. localDir = msg.ReadDir( 24 );
  4842. damageDefIndex = gameLocal.ClientRemapDecl( DECL_ENTITYDEF, msg.ReadLong() );
  4843. materialIndex = gameLocal.ClientRemapDecl( DECL_MATERIAL, msg.ReadLong() );
  4844. const idDeclEntityDef *damageDef = static_cast<const idDeclEntityDef *>( declManager->DeclByIndex( DECL_ENTITYDEF, damageDefIndex ) );
  4845. const idMaterial *collisionMaterial = static_cast<const idMaterial *>( declManager->DeclByIndex( DECL_MATERIAL, materialIndex ) );
  4846. AddLocalDamageEffect( jointNum, localOrigin, localNormal, localDir, damageDef, collisionMaterial );
  4847. return true;
  4848. }
  4849. default: {
  4850. return idEntity::ClientReceiveEvent( event, time, msg );
  4851. }
  4852. }
  4853. return false;
  4854. }
  4855. /*
  4856. ================
  4857. idAnimatedEntity::Event_GetJointHandle
  4858. looks up the number of the specified joint. returns INVALID_JOINT if the joint is not found.
  4859. ================
  4860. */
  4861. void idAnimatedEntity::Event_GetJointHandle( const char *jointname ) {
  4862. jointHandle_t joint;
  4863. joint = animator.GetJointHandle( jointname );
  4864. idThread::ReturnInt( joint );
  4865. }
  4866. /*
  4867. ================
  4868. idAnimatedEntity::Event_ClearAllJoints
  4869. removes any custom transforms on all joints
  4870. ================
  4871. */
  4872. void idAnimatedEntity::Event_ClearAllJoints( void ) {
  4873. animator.ClearAllJoints();
  4874. }
  4875. /*
  4876. ================
  4877. idAnimatedEntity::Event_ClearJoint
  4878. removes any custom transforms on the specified joint
  4879. ================
  4880. */
  4881. void idAnimatedEntity::Event_ClearJoint( jointHandle_t jointnum ) {
  4882. animator.ClearJoint( jointnum );
  4883. }
  4884. /*
  4885. ================
  4886. idAnimatedEntity::Event_SetJointPos
  4887. modifies the position of the joint based on the transform type
  4888. ================
  4889. */
  4890. void idAnimatedEntity::Event_SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ) {
  4891. animator.SetJointPos( jointnum, transform_type, pos );
  4892. }
  4893. /*
  4894. ================
  4895. idAnimatedEntity::Event_SetJointAngle
  4896. modifies the orientation of the joint based on the transform type
  4897. ================
  4898. */
  4899. void idAnimatedEntity::Event_SetJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &angles ) {
  4900. idMat3 mat;
  4901. mat = angles.ToMat3();
  4902. animator.SetJointAxis( jointnum, transform_type, mat );
  4903. }
  4904. /*
  4905. ================
  4906. idAnimatedEntity::Event_GetJointPos
  4907. returns the position of the joint in worldspace
  4908. ================
  4909. */
  4910. void idAnimatedEntity::Event_GetJointPos( jointHandle_t jointnum ) {
  4911. idVec3 offset;
  4912. idMat3 axis;
  4913. if ( !GetJointWorldTransform( jointnum, gameLocal.time, offset, axis ) ) {
  4914. gameLocal.Warning( "Joint # %d out of range on entity '%s'", jointnum, name.c_str() );
  4915. }
  4916. idThread::ReturnVector( offset );
  4917. }
  4918. /*
  4919. ================
  4920. idAnimatedEntity::Event_GetJointAngle
  4921. returns the orientation of the joint in worldspace
  4922. ================
  4923. */
  4924. void idAnimatedEntity::Event_GetJointAngle( jointHandle_t jointnum ) {
  4925. idVec3 offset;
  4926. idMat3 axis;
  4927. if ( !GetJointWorldTransform( jointnum, gameLocal.time, offset, axis ) ) {
  4928. gameLocal.Warning( "Joint # %d out of range on entity '%s'", jointnum, name.c_str() );
  4929. }
  4930. idAngles ang = axis.ToAngles();
  4931. idVec3 vec( ang[ 0 ], ang[ 1 ], ang[ 2 ] );
  4932. idThread::ReturnVector( vec );
  4933. }
  4934. int idAnimatedEntity::Event_PlayAnim( const char* animname, int animBlendFrames)
  4935. {
  4936. int anim;
  4937. int channel = 0;
  4938. int animDoneTime = 0;
  4939. //idAnimator *animator = GetAnimator();
  4940. anim = animator.GetAnim( animname );
  4941. if ( !anim )
  4942. {
  4943. gameLocal.Warning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
  4944. animator.Clear( channel, gameLocal.time, FRAME2MS( animBlendFrames ) );
  4945. animDoneTime = 0;
  4946. }
  4947. else
  4948. {
  4949. animator.PlayAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
  4950. animDoneTime = animator.CurrentAnim( channel )->GetEndTime();
  4951. }
  4952. animBlendFrames = 0;
  4953. return animDoneTime;
  4954. }