Entity.cpp 130 KB

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