Entity.cpp 135 KB

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