1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- // a mover will update any gui entities in it's target list with
- // a key/val pair of "mover" "state" from below.. guis can represent
- // realtime info like this
- // binary only
- static const char *guiBinaryMoverStates[] = {
- "1", // pos 1
- "2", // pos 2
- "3", // moving 1 to 2
- "4" // moving 2 to 1
- };
- /*
- ===============================================================================
- idMover
- ===============================================================================
- */
- const idEventDef EV_FindGuiTargets( "<FindGuiTargets>", NULL );
- const idEventDef EV_TeamBlocked( "<teamblocked>", "ee" );
- const idEventDef EV_PartBlocked( "<partblocked>", "e" );
- const idEventDef EV_ReachedPos( "<reachedpos>", NULL );
- const idEventDef EV_ReachedAng( "<reachedang>", NULL );
- const idEventDef EV_PostRestore( "<postrestore>", "ddddd" );
- const idEventDef EV_StopMoving( "stopMoving", NULL );
- const idEventDef EV_StopRotating( "stopRotating", NULL );
- const idEventDef EV_Speed( "speed", "f" );
- const idEventDef EV_Time( "time", "f" );
- const idEventDef EV_AccelTime( "accelTime", "f" );
- const idEventDef EV_DecelTime( "decelTime", "f" );
- const idEventDef EV_MoveTo( "moveTo", "e" );
- const idEventDef EV_MoveToPos( "moveToPos", "v" );
- const idEventDef EV_Move( "move", "ff" );
- const idEventDef EV_MoveAccelerateTo( "accelTo", "ff" );
- const idEventDef EV_MoveDecelerateTo( "decelTo", "ff" );
- const idEventDef EV_RotateDownTo( "rotateDownTo", "df" );
- const idEventDef EV_RotateUpTo( "rotateUpTo", "df" );
- const idEventDef EV_RotateTo( "rotateTo", "v" );
- const idEventDef EV_Rotate( "rotate", "v" );
- const idEventDef EV_RotateOnce( "rotateOnce", "v" );
- const idEventDef EV_Bob( "bob", "ffv" );
- const idEventDef EV_Sway( "sway", "ffv" );
- const idEventDef EV_Mover_OpenPortal( "openPortal" );
- const idEventDef EV_Mover_ClosePortal( "closePortal" );
- const idEventDef EV_AccelSound( "accelSound", "s" );
- const idEventDef EV_DecelSound( "decelSound", "s" );
- const idEventDef EV_MoveSound( "moveSound", "s" );
- const idEventDef EV_Mover_InitGuiTargets( "<initguitargets>", NULL );
- const idEventDef EV_EnableSplineAngles( "enableSplineAngles", NULL );
- const idEventDef EV_DisableSplineAngles( "disableSplineAngles", NULL );
- const idEventDef EV_RemoveInitialSplineAngles( "removeInitialSplineAngles", NULL );
- const idEventDef EV_StartSpline( "startSpline", "e" );
- const idEventDef EV_StopSpline( "stopSpline", NULL );
- const idEventDef EV_IsMoving( "isMoving", NULL, 'd' );
- const idEventDef EV_IsRotating( "isRotating", NULL, 'd' );
- CLASS_DECLARATION( idEntity, idMover )
- EVENT( EV_FindGuiTargets, idMover::Event_FindGuiTargets )
- EVENT( EV_Thread_SetCallback, idMover::Event_SetCallback )
- EVENT( EV_TeamBlocked, idMover::Event_TeamBlocked )
- EVENT( EV_PartBlocked, idMover::Event_PartBlocked )
- EVENT( EV_ReachedPos, idMover::Event_UpdateMove )
- EVENT( EV_ReachedAng, idMover::Event_UpdateRotation )
- EVENT( EV_PostRestore, idMover::Event_PostRestore )
- EVENT( EV_StopMoving, idMover::Event_StopMoving )
- EVENT( EV_StopRotating, idMover::Event_StopRotating )
- EVENT( EV_Speed, idMover::Event_SetMoveSpeed )
- EVENT( EV_Time, idMover::Event_SetMoveTime )
- EVENT( EV_AccelTime, idMover::Event_SetAccellerationTime )
- EVENT( EV_DecelTime, idMover::Event_SetDecelerationTime )
- EVENT( EV_MoveTo, idMover::Event_MoveTo )
- EVENT( EV_MoveToPos, idMover::Event_MoveToPos )
- EVENT( EV_Move, idMover::Event_MoveDir )
- EVENT( EV_MoveAccelerateTo, idMover::Event_MoveAccelerateTo )
- EVENT( EV_MoveDecelerateTo, idMover::Event_MoveDecelerateTo )
- EVENT( EV_RotateDownTo, idMover::Event_RotateDownTo )
- EVENT( EV_RotateUpTo, idMover::Event_RotateUpTo )
- EVENT( EV_RotateTo, idMover::Event_RotateTo )
- EVENT( EV_Rotate, idMover::Event_Rotate )
- EVENT( EV_RotateOnce, idMover::Event_RotateOnce )
- EVENT( EV_Bob, idMover::Event_Bob )
- EVENT( EV_Sway, idMover::Event_Sway )
- EVENT( EV_Mover_OpenPortal, idMover::Event_OpenPortal )
- EVENT( EV_Mover_ClosePortal, idMover::Event_ClosePortal )
- EVENT( EV_AccelSound, idMover::Event_SetAccelSound )
- EVENT( EV_DecelSound, idMover::Event_SetDecelSound )
- EVENT( EV_MoveSound, idMover::Event_SetMoveSound )
- EVENT( EV_Mover_InitGuiTargets, idMover::Event_InitGuiTargets )
- EVENT( EV_EnableSplineAngles, idMover::Event_EnableSplineAngles )
- EVENT( EV_DisableSplineAngles, idMover::Event_DisableSplineAngles )
- EVENT( EV_RemoveInitialSplineAngles, idMover::Event_RemoveInitialSplineAngles )
- EVENT( EV_StartSpline, idMover::Event_StartSpline )
- EVENT( EV_StopSpline, idMover::Event_StopSpline )
- EVENT( EV_Activate, idMover::Event_Activate )
- EVENT( EV_IsMoving, idMover::Event_IsMoving )
- EVENT( EV_IsRotating, idMover::Event_IsRotating )
- END_CLASS
- /*
- ================
- idMover::idMover
- ================
- */
- idMover::idMover( void ) {
- memset( &move, 0, sizeof( move ) );
- memset( &rot, 0, sizeof( rot ) );
- move_thread = 0;
- rotate_thread = 0;
- dest_angles.Zero();
- angle_delta.Zero();
- dest_position.Zero();
- move_delta.Zero();
- move_speed = 0.0f;
- move_time = 0;
- deceltime = 0;
- acceltime = 0;
- stopRotation = false;
- useSplineAngles = true;
- lastCommand = MOVER_NONE;
- damage = 0.0f;
- areaPortal = 0;
- fl.networkSync = true;
- }
- /*
- ================
- idMover::Save
- ================
- */
- void idMover::Save( idSaveGame *savefile ) const {
- int i;
- savefile->WriteStaticObject( physicsObj );
- savefile->WriteInt( move.stage );
- savefile->WriteInt( move.acceleration );
- savefile->WriteInt( move.movetime );
- savefile->WriteInt( move.deceleration );
- savefile->WriteVec3( move.dir );
-
- savefile->WriteInt( rot.stage );
- savefile->WriteInt( rot.acceleration );
- savefile->WriteInt( rot.movetime );
- savefile->WriteInt( rot.deceleration );
- savefile->WriteFloat( rot.rot.pitch );
- savefile->WriteFloat( rot.rot.yaw );
- savefile->WriteFloat( rot.rot.roll );
-
- savefile->WriteInt( move_thread );
- savefile->WriteInt( rotate_thread );
- savefile->WriteAngles( dest_angles );
- savefile->WriteAngles( angle_delta );
- savefile->WriteVec3( dest_position );
- savefile->WriteVec3( move_delta );
- savefile->WriteFloat( move_speed );
- savefile->WriteInt( move_time );
- savefile->WriteInt( deceltime );
- savefile->WriteInt( acceltime );
- savefile->WriteBool( stopRotation );
- savefile->WriteBool( useSplineAngles );
- savefile->WriteInt( lastCommand );
- savefile->WriteFloat( damage );
- savefile->WriteInt( areaPortal );
- if ( areaPortal > 0 ) {
- savefile->WriteInt( gameRenderWorld->GetPortalState( areaPortal ) );
- }
- savefile->WriteInt( guiTargets.Num() );
- for( i = 0; i < guiTargets.Num(); i++ ) {
- guiTargets[ i ].Save( savefile );
- }
- if ( splineEnt.GetEntity() && splineEnt.GetEntity()->GetSpline() ) {
- idCurve_Spline<idVec3> *spline = physicsObj.GetSpline();
- savefile->WriteBool( true );
- splineEnt.Save( savefile );
- savefile->WriteInt( spline->GetTime( 0 ) );
- savefile->WriteInt( spline->GetTime( spline->GetNumValues() - 1 ) - spline->GetTime( 0 ) );
- savefile->WriteInt( physicsObj.GetSplineAcceleration() );
- savefile->WriteInt( physicsObj.GetSplineDeceleration() );
- savefile->WriteInt( (int)physicsObj.UsingSplineAngles() );
- } else {
- savefile->WriteBool( false );
- }
- }
- /*
- ================
- idMover::Restore
- ================
- */
- void idMover::Restore( idRestoreGame *savefile ) {
- int i, num;
- bool hasSpline = false;
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- savefile->ReadInt( (int&)move.stage );
- savefile->ReadInt( move.acceleration );
- savefile->ReadInt( move.movetime );
- savefile->ReadInt( move.deceleration );
- savefile->ReadVec3( move.dir );
-
- savefile->ReadInt( (int&)rot.stage );
- savefile->ReadInt( rot.acceleration );
- savefile->ReadInt( rot.movetime );
- savefile->ReadInt( rot.deceleration );
- savefile->ReadFloat( rot.rot.pitch );
- savefile->ReadFloat( rot.rot.yaw );
- savefile->ReadFloat( rot.rot.roll );
-
- savefile->ReadInt( move_thread );
- savefile->ReadInt( rotate_thread );
- savefile->ReadAngles( dest_angles );
- savefile->ReadAngles( angle_delta );
- savefile->ReadVec3( dest_position );
- savefile->ReadVec3( move_delta );
- savefile->ReadFloat( move_speed );
- savefile->ReadInt( move_time );
- savefile->ReadInt( deceltime );
- savefile->ReadInt( acceltime );
- savefile->ReadBool( stopRotation );
- savefile->ReadBool( useSplineAngles );
- savefile->ReadInt( (int &)lastCommand );
- savefile->ReadFloat( damage );
- savefile->ReadInt( areaPortal );
- if ( areaPortal > 0 ) {
- int portalState = 0;
- savefile->ReadInt( portalState );
- gameLocal.SetPortalState( areaPortal, portalState );
- }
- guiTargets.Clear();
- savefile->ReadInt( num );
- guiTargets.SetNum( num );
- for( i = 0; i < num; i++ ) {
- guiTargets[ i ].Restore( savefile );
- }
- savefile->ReadBool( hasSpline );
- if ( hasSpline ) {
- int starttime;
- int totaltime;
- int accel;
- int decel;
- int useAngles;
- splineEnt.Restore( savefile );
- savefile->ReadInt( starttime );
- savefile->ReadInt( totaltime );
- savefile->ReadInt( accel );
- savefile->ReadInt( decel );
- savefile->ReadInt( useAngles );
- PostEventMS( &EV_PostRestore, 0, starttime, totaltime, accel, decel, useAngles );
- }
- }
- /*
- ================
- idMover::Event_PostRestore
- ================
- */
- void idMover::Event_PostRestore( int start, int total, int accel, int decel, int useSplineAng ) {
- idCurve_Spline<idVec3> *spline;
- idEntity *splineEntity = splineEnt.GetEntity();
- if ( !splineEntity ) {
- // We should never get this event if splineEnt is invalid
- common->Warning( "Invalid spline entity during restore\n" );
- return;
- }
- spline = splineEntity->GetSpline();
- spline->MakeUniform( total );
- spline->ShiftTime( start - spline->GetTime( 0 ) );
- physicsObj.SetSpline( spline, accel, decel, ( useSplineAng != 0 ) );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_position, vec3_origin, vec3_origin );
- }
- /*
- ================
- idMover::Spawn
- ================
- */
- void idMover::Spawn( void ) {
- move_thread = 0;
- rotate_thread = 0;
- stopRotation = false;
- lastCommand = MOVER_NONE;
- acceltime = 1000.0f * spawnArgs.GetFloat( "accel_time", "0" );
- deceltime = 1000.0f * spawnArgs.GetFloat( "decel_time", "0" );
- move_time = 1000.0f * spawnArgs.GetFloat( "move_time", "1" ); // safe default value
- move_speed = spawnArgs.GetFloat( "move_speed", "0" );
- spawnArgs.GetFloat( "damage" , "0", damage );
- dest_position = GetPhysics()->GetOrigin();
- dest_angles = GetPhysics()->GetAxis().ToAngles();
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "solid", "1" ) ) {
- physicsObj.SetContents( 0 );
- }
- if ( !renderEntity.hModel || !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_position, vec3_origin, vec3_origin );
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_angles, ang_zero, ang_zero );
- SetPhysics( &physicsObj );
- // see if we are on an areaportal
- areaPortal = gameRenderWorld->FindPortal( GetPhysics()->GetAbsBounds() );
- if ( spawnArgs.MatchPrefix( "guiTarget" ) ) {
- if ( gameLocal.GameState() == GAMESTATE_STARTUP ) {
- PostEventMS( &EV_FindGuiTargets, 0 );
- } else {
- // not during spawn, so it's ok to get the targets
- FindGuiTargets();
- }
- }
- health = spawnArgs.GetInt( "health" );
- if ( health ) {
- fl.takedamage = true;
- }
- }
- /*
- ================
- idMover::Hide
- ================
- */
- void idMover::Hide( void ) {
- idEntity::Hide();
- physicsObj.SetContents( 0 );
- }
- /*
- ================
- idMover::Show
- ================
- */
- void idMover::Show( void ) {
- idEntity::Show();
- if ( spawnArgs.GetBool( "solid", "1" ) ) {
- physicsObj.SetContents( CONTENTS_SOLID );
- }
- SetPhysics( &physicsObj );
- }
- /*
- ============
- idMover::Killed
- ============
- */
- void idMover::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
- fl.takedamage = false;
- ActivateTargets( this );
- }
- /*
- ================
- idMover::Event_SetCallback
- ================
- */
- void idMover::Event_SetCallback( void ) {
- if ( ( lastCommand == MOVER_ROTATING ) && !rotate_thread ) {
- lastCommand = MOVER_NONE;
- rotate_thread = idThread::CurrentThreadNum();
- idThread::ReturnInt( true );
- } else if ( ( lastCommand == MOVER_MOVING || lastCommand == MOVER_SPLINE ) && !move_thread ) {
- lastCommand = MOVER_NONE;
- move_thread = idThread::CurrentThreadNum();
- idThread::ReturnInt( true );
- } else {
- idThread::ReturnInt( false );
- }
- }
- /*
- ================
- idMover::VectorForDir
- ================
- */
- void idMover::VectorForDir( float angle, idVec3 &vec ) {
- idAngles ang;
- switch( ( int )angle ) {
- case DIR_UP :
- vec.Set( 0, 0, 1 );
- break;
- case DIR_DOWN :
- vec.Set( 0, 0, -1 );
- break;
- case DIR_LEFT :
- physicsObj.GetLocalAngles( ang );
- ang.pitch = 0;
- ang.roll = 0;
- ang.yaw += 90;
- vec = ang.ToForward();
- break;
- case DIR_RIGHT :
- physicsObj.GetLocalAngles( ang );
- ang.pitch = 0;
- ang.roll = 0;
- ang.yaw -= 90;
- vec = ang.ToForward();
- break;
- case DIR_FORWARD :
- physicsObj.GetLocalAngles( ang );
- ang.pitch = 0;
- ang.roll = 0;
- vec = ang.ToForward();
- break;
- case DIR_BACK :
- physicsObj.GetLocalAngles( ang );
- ang.pitch = 0;
- ang.roll = 0;
- ang.yaw += 180;
- vec = ang.ToForward();
- break;
- case DIR_REL_UP :
- vec.Set( 0, 0, 1 );
- break;
- case DIR_REL_DOWN :
- vec.Set( 0, 0, -1 );
- break;
- case DIR_REL_LEFT :
- physicsObj.GetLocalAngles( ang );
- ang.ToVectors( NULL, &vec );
- vec *= -1;
- break;
- case DIR_REL_RIGHT :
- physicsObj.GetLocalAngles( ang );
- ang.ToVectors( NULL, &vec );
- break;
- case DIR_REL_FORWARD :
- physicsObj.GetLocalAngles( ang );
- vec = ang.ToForward();
- break;
- case DIR_REL_BACK :
- physicsObj.GetLocalAngles( ang );
- vec = ang.ToForward() * -1;
- break;
- default:
- ang.Set( 0, angle, 0 );
- vec = GetWorldVector( ang.ToForward() );
- break;
- }
- }
- /*
- ================
- idMover::FindGuiTargets
- ================
- */
- void idMover::FindGuiTargets( void ) {
- gameLocal.GetTargets( spawnArgs, guiTargets, "guiTarget" );
- }
- /*
- ==============================
- idMover::SetGuiState
- key/val will be set to any renderEntity->gui's on the list
- ==============================
- */
- void idMover::SetGuiState( const char *key, const char *val ) const {
- gameLocal.Printf( "Setting %s to %s\n", key, val );
- for( int i = 0; i < guiTargets.Num(); i++ ) {
- idEntity *ent = guiTargets[ i ].GetEntity();
- if ( ent ) {
- for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
- if ( ent->GetRenderEntity() && ent->GetRenderEntity()->gui[ j ] ) {
- ent->GetRenderEntity()->gui[ j ]->SetStateString( key, val );
- ent->GetRenderEntity()->gui[ j ]->StateChanged( gameLocal.time, true );
- }
- }
- ent->UpdateVisuals();
- }
- }
- }
- /*
- ================
- idMover::Event_InitGuiTargets
- ================
- */
- void idMover::Event_FindGuiTargets( void ) {
- FindGuiTargets();
- }
- /*
- ================
- idMover::SetGuiStates
- ================
- */
- void idMover::SetGuiStates( const char *state ) {
- int i;
- if ( guiTargets.Num() ) {
- SetGuiState( "movestate", state );
- }
- for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
- if ( renderEntity.gui[ i ] ) {
- renderEntity.gui[ i ]->SetStateString( "movestate", state );
- renderEntity.gui[ i ]->StateChanged( gameLocal.time, true );
- }
- }
- }
- /*
- ================
- idMover::Event_InitGuiTargets
- ================
- */
- void idMover::Event_InitGuiTargets( void ) {
- SetGuiStates( guiBinaryMoverStates[MOVER_POS1] );
- }
- /***********************************************************************
- Translation control functions
-
- ***********************************************************************/
- /*
- ================
- idMover::Event_StopMoving
- ================
- */
- void idMover::Event_StopMoving( void ) {
- physicsObj.GetLocalOrigin( dest_position );
- DoneMoving();
- }
- /*
- ================
- idMover::DoneMoving
- ================
- */
- void idMover::DoneMoving( void ) {
- if ( lastCommand != MOVER_SPLINE ) {
- // set our final position so that we get rid of any numerical inaccuracy
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_position, vec3_origin, vec3_origin );
- }
- lastCommand = MOVER_NONE;
- idThread::ObjectMoveDone( move_thread, this );
- move_thread = 0;
- StopSound( SND_CHANNEL_BODY, false );
- }
- /*
- ================
- idMover::UpdateMoveSound
- ================
- */
- void idMover::UpdateMoveSound( moveStage_t stage ) {
- switch( stage ) {
- case ACCELERATION_STAGE: {
- StartSound( "snd_accel", SND_CHANNEL_BODY2, 0, false, NULL );
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- break;
- }
- case LINEAR_STAGE: {
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- break;
- }
- case DECELERATION_STAGE: {
- StopSound( SND_CHANNEL_BODY, false );
- StartSound( "snd_decel", SND_CHANNEL_BODY2, 0, false, NULL );
- break;
- }
- case FINISHED_STAGE: {
- StopSound( SND_CHANNEL_BODY, false );
- break;
- }
- }
- }
- /*
- ================
- idMover::Event_UpdateMove
- ================
- */
- void idMover::Event_UpdateMove( void ) {
- idVec3 org;
- physicsObj.GetLocalOrigin( org );
- UpdateMoveSound( move.stage );
- switch( move.stage ) {
- case ACCELERATION_STAGE: {
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_ACCELLINEAR, gameLocal.time, move.acceleration, org, move.dir, vec3_origin );
- if ( move.movetime > 0 ) {
- move.stage = LINEAR_STAGE;
- } else if ( move.deceleration > 0 ) {
- move.stage = DECELERATION_STAGE;
- } else {
- move.stage = FINISHED_STAGE;
- }
- break;
- }
- case LINEAR_STAGE: {
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_LINEAR, gameLocal.time, move.movetime, org, move.dir, vec3_origin );
- if ( move.deceleration ) {
- move.stage = DECELERATION_STAGE;
- } else {
- move.stage = FINISHED_STAGE;
- }
- break;
- }
- case DECELERATION_STAGE: {
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_DECELLINEAR, gameLocal.time, move.deceleration, org, move.dir, vec3_origin );
- move.stage = FINISHED_STAGE;
- break;
- }
- case FINISHED_STAGE: {
- if ( g_debugMover.GetBool() ) {
- gameLocal.Printf( "%d: '%s' move done\n", gameLocal.time, name.c_str() );
- }
- DoneMoving();
- break;
- }
- }
- }
- /*
- ================
- idMover::BeginMove
- ================
- */
- void idMover::BeginMove( idThread *thread ) {
- moveStage_t stage;
- idVec3 org;
- float dist;
- float acceldist;
- int totalacceltime;
- int at;
- int dt;
- lastCommand = MOVER_MOVING;
- move_thread = 0;
- physicsObj.GetLocalOrigin( org );
- move_delta = dest_position - org;
- if ( move_delta.Compare( vec3_zero ) ) {
- DoneMoving();
- return;
- }
- // scale times up to whole physics frames
- at = idPhysics::SnapTimeToPhysicsFrame( acceltime );
- move_time += at - acceltime;
- acceltime = at;
- dt = idPhysics::SnapTimeToPhysicsFrame( deceltime );
- move_time += dt - deceltime;
- deceltime = dt;
- // if we're moving at a specific speed, we need to calculate the move time
- if ( move_speed ) {
- dist = move_delta.Length();
- totalacceltime = acceltime + deceltime;
- // calculate the distance we'll move during acceleration and deceleration
- acceldist = totalacceltime * 0.5f * 0.001f * move_speed;
- if ( acceldist >= dist ) {
- // going too slow for this distance to move at a constant speed
- move_time = totalacceltime;
- } else {
- // calculate move time taking acceleration into account
- move_time = totalacceltime + 1000.0f * ( dist - acceldist ) / move_speed;
- }
- }
- // scale time up to a whole physics frames
- move_time = idPhysics::SnapTimeToPhysicsFrame( move_time );
- if ( acceltime ) {
- stage = ACCELERATION_STAGE;
- } else if ( move_time <= deceltime ) {
- stage = DECELERATION_STAGE;
- } else {
- stage = LINEAR_STAGE;
- }
- at = acceltime;
- dt = deceltime;
- if ( at + dt > move_time ) {
- // there's no real correct way to handle this, so we just scale
- // the times to fit into the move time in the same proportions
- at = idPhysics::SnapTimeToPhysicsFrame( at * move_time / ( at + dt ) );
- dt = move_time - at;
- }
- move_delta = move_delta * ( 1000.0f / ( (float) move_time - ( at + dt ) * 0.5f ) );
- move.stage = stage;
- move.acceleration = at;
- move.movetime = move_time - at - dt;
- move.deceleration = dt;
- move.dir = move_delta;
- ProcessEvent( &EV_ReachedPos );
- }
- /***********************************************************************
- Rotation control functions
-
- ***********************************************************************/
- /*
- ================
- idMover::Event_StopRotating
- ================
- */
- void idMover::Event_StopRotating( void ) {
- physicsObj.GetLocalAngles( dest_angles );
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_angles, ang_zero, ang_zero );
- DoneRotating();
- }
- /*
- ================
- idMover::DoneRotating
- ================
- */
- void idMover::DoneRotating( void ) {
- lastCommand = MOVER_NONE;
- idThread::ObjectMoveDone( rotate_thread, this );
- rotate_thread = 0;
- StopSound( SND_CHANNEL_BODY, false );
- }
- /*
- ================
- idMover::UpdateRotationSound
- ================
- */
- void idMover::UpdateRotationSound( moveStage_t stage ) {
- switch( stage ) {
- case ACCELERATION_STAGE: {
- StartSound( "snd_accel", SND_CHANNEL_BODY2, 0, false, NULL );
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- break;
- }
- case LINEAR_STAGE: {
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- break;
- }
- case DECELERATION_STAGE: {
- StopSound( SND_CHANNEL_BODY, false );
- StartSound( "snd_decel", SND_CHANNEL_BODY2, 0, false, NULL );
- break;
- }
- case FINISHED_STAGE: {
- StopSound( SND_CHANNEL_BODY, false );
- break;
- }
- }
- }
- /*
- ================
- idMover::Event_UpdateRotation
- ================
- */
- void idMover::Event_UpdateRotation( void ) {
- idAngles ang;
- physicsObj.GetLocalAngles( ang );
- UpdateRotationSound( rot.stage );
- switch( rot.stage ) {
- case ACCELERATION_STAGE: {
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_ACCELLINEAR, gameLocal.time, rot.acceleration, ang, rot.rot, ang_zero );
- if ( rot.movetime > 0 ) {
- rot.stage = LINEAR_STAGE;
- } else if ( rot.deceleration > 0 ) {
- rot.stage = DECELERATION_STAGE;
- } else {
- rot.stage = FINISHED_STAGE;
- }
- break;
- }
- case LINEAR_STAGE: {
- if ( !stopRotation && !rot.deceleration ) {
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, rot.movetime, ang, rot.rot, ang_zero );
- } else {
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_LINEAR, gameLocal.time, rot.movetime, ang, rot.rot, ang_zero );
- }
- if ( rot.deceleration ) {
- rot.stage = DECELERATION_STAGE;
- } else {
- rot.stage = FINISHED_STAGE;
- }
- break;
- }
- case DECELERATION_STAGE: {
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_DECELLINEAR, gameLocal.time, rot.deceleration, ang, rot.rot, ang_zero );
- rot.stage = FINISHED_STAGE;
- break;
- }
- case FINISHED_STAGE: {
- lastCommand = MOVER_NONE;
- if ( stopRotation ) {
- // set our final angles so that we get rid of any numerical inaccuracy
- dest_angles.Normalize360();
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_angles, ang_zero, ang_zero );
- stopRotation = false;
- } else if ( physicsObj.GetAngularExtrapolationType() == EXTRAPOLATION_ACCELLINEAR ) {
- // keep our angular velocity constant
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, ang, rot.rot, ang_zero );
- }
- if ( g_debugMover.GetBool() ) {
- gameLocal.Printf( "%d: '%s' rotation done\n", gameLocal.time, name.c_str() );
- }
- DoneRotating();
- break;
- }
- }
- }
- /*
- ================
- idMover::BeginRotation
- ================
- */
- void idMover::BeginRotation( idThread *thread, bool stopwhendone ) {
- moveStage_t stage;
- idAngles ang;
- int at;
- int dt;
- lastCommand = MOVER_ROTATING;
- rotate_thread = 0;
- // rotation always uses move_time so that if a move was started before the rotation,
- // the rotation will take the same amount of time as the move. If no move has been
- // started and no time is set, the rotation takes 1 second.
- if ( !move_time ) {
- move_time = 1;
- }
- physicsObj.GetLocalAngles( ang );
- angle_delta = dest_angles - ang;
- if ( angle_delta == ang_zero ) {
- // set our final angles so that we get rid of any numerical inaccuracy
- dest_angles.Normalize360();
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_angles, ang_zero, ang_zero );
- stopRotation = false;
- DoneRotating();
- return;
- }
- // scale times up to whole physics frames
- at = idPhysics::SnapTimeToPhysicsFrame( acceltime );
- move_time += at - acceltime;
- acceltime = at;
- dt = idPhysics::SnapTimeToPhysicsFrame( deceltime );
- move_time += dt - deceltime;
- deceltime = dt;
- move_time = idPhysics::SnapTimeToPhysicsFrame( move_time );
- if ( acceltime ) {
- stage = ACCELERATION_STAGE;
- } else if ( move_time <= deceltime ) {
- stage = DECELERATION_STAGE;
- } else {
- stage = LINEAR_STAGE;
- }
- at = acceltime;
- dt = deceltime;
- if ( at + dt > move_time ) {
- // there's no real correct way to handle this, so we just scale
- // the times to fit into the move time in the same proportions
- at = idPhysics::SnapTimeToPhysicsFrame( at * move_time / ( at + dt ) );
- dt = move_time - at;
- }
- angle_delta = angle_delta * ( 1000.0f / ( (float) move_time - ( at + dt ) * 0.5f ) );
- stopRotation = stopwhendone || ( dt != 0 );
- rot.stage = stage;
- rot.acceleration = at;
- rot.movetime = move_time - at - dt;
- rot.deceleration = dt;
- rot.rot = angle_delta;
- ProcessEvent( &EV_ReachedAng );
- }
- /***********************************************************************
- Script callable routines
-
- ***********************************************************************/
- /*
- ===============
- idMover::Event_TeamBlocked
- ===============
- */
- void idMover::Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity ) {
- if ( g_debugMover.GetBool() ) {
- gameLocal.Printf( "%d: '%s' stopped due to team member '%s' blocked by '%s'\n", gameLocal.time, name.c_str(), blockedEntity->name.c_str(), blockingEntity->name.c_str() );
- }
- }
- /*
- ===============
- idMover::Event_PartBlocked
- ===============
- */
- void idMover::Event_PartBlocked( idEntity *blockingEntity ) {
- if ( damage > 0.0f ) {
- blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
- }
- if ( g_debugMover.GetBool() ) {
- gameLocal.Printf( "%d: '%s' blocked by '%s'\n", gameLocal.time, name.c_str(), blockingEntity->name.c_str() );
- }
- }
- /*
- ================
- idMover::Event_SetMoveSpeed
- ================
- */
- void idMover::Event_SetMoveSpeed( float speed ) {
- if ( speed <= 0 ) {
- gameLocal.Error( "Cannot set speed less than or equal to 0." );
- }
- move_speed = speed;
- move_time = 0; // move_time is calculated for each move when move_speed is non-0
- }
- /*
- ================
- idMover::Event_SetMoveTime
- ================
- */
- void idMover::Event_SetMoveTime( float time ) {
- if ( time <= 0 ) {
- gameLocal.Error( "Cannot set time less than or equal to 0." );
- }
- move_speed = 0;
- move_time = SEC2MS( time );
- }
- /*
- ================
- idMover::Event_SetAccellerationTime
- ================
- */
- void idMover::Event_SetAccellerationTime( float time ) {
- if ( time < 0 ) {
- gameLocal.Error( "Cannot set acceleration time less than 0." );
- }
- acceltime = SEC2MS( time );
- }
- /*
- ================
- idMover::Event_SetDecelerationTime
- ================
- */
- void idMover::Event_SetDecelerationTime( float time ) {
- if ( time < 0 ) {
- gameLocal.Error( "Cannot set deceleration time less than 0." );
- }
- deceltime = SEC2MS( time );
- }
- /*
- ================
- idMover::Event_MoveTo
- ================
- */
- void idMover::Event_MoveTo( idEntity *ent ) {
- if ( !ent ) {
- gameLocal.Warning( "Entity not found" );
- }
- dest_position = GetLocalCoordinates( ent->GetPhysics()->GetOrigin() );
- BeginMove( idThread::CurrentThread() );
- }
- /*
- ================
- idMover::MoveToPos
- ================
- */
- void idMover::MoveToPos( const idVec3 &pos ) {
- dest_position = GetLocalCoordinates( pos );
- BeginMove( NULL );
- }
- /*
- ================
- idMover::Event_MoveToPos
- ================
- */
- void idMover::Event_MoveToPos( idVec3 &pos ) {
- MoveToPos( pos );
- }
- /*
- ================
- idMover::Event_MoveDir
- ================
- */
- void idMover::Event_MoveDir( float angle, float distance ) {
- idVec3 dir;
- idVec3 org;
- physicsObj.GetLocalOrigin( org );
- VectorForDir( angle, dir );
- dest_position = org + dir * distance;
- BeginMove( idThread::CurrentThread() );
- }
- /*
- ================
- idMover::Event_MoveAccelerateTo
- ================
- */
- void idMover::Event_MoveAccelerateTo( float speed, float time ) {
- float v;
- idVec3 org, dir;
- int at;
- if ( time < 0 ) {
- gameLocal.Error( "idMover::Event_MoveAccelerateTo: cannot set acceleration time less than 0." );
- }
- dir = physicsObj.GetLinearVelocity();
- v = dir.Normalize();
- // if not moving already
- if ( v == 0.0f ) {
- gameLocal.Error( "idMover::Event_MoveAccelerateTo: not moving." );
- }
- // if already moving faster than the desired speed
- if ( v >= speed ) {
- return;
- }
- at = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( time ) );
- lastCommand = MOVER_MOVING;
- physicsObj.GetLocalOrigin( org );
- move.stage = ACCELERATION_STAGE;
- move.acceleration = at;
- move.movetime = 0;
- move.deceleration = 0;
- StartSound( "snd_accel", SND_CHANNEL_BODY2, 0, false, NULL );
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_ACCELLINEAR, gameLocal.time, move.acceleration, org, dir * ( speed - v ), dir * v );
- }
- /*
- ================
- idMover::Event_MoveDecelerateTo
- ================
- */
- void idMover::Event_MoveDecelerateTo( float speed, float time ) {
- float v;
- idVec3 org, dir;
- int dt;
- if ( time < 0 ) {
- gameLocal.Error( "idMover::Event_MoveDecelerateTo: cannot set deceleration time less than 0." );
- }
- dir = physicsObj.GetLinearVelocity();
- v = dir.Normalize();
- // if not moving already
- if ( v == 0.0f ) {
- gameLocal.Error( "idMover::Event_MoveDecelerateTo: not moving." );
- }
- // if already moving slower than the desired speed
- if ( v <= speed ) {
- return;
- }
- dt = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( time ) );
- lastCommand = MOVER_MOVING;
- physicsObj.GetLocalOrigin( org );
- move.stage = DECELERATION_STAGE;
- move.acceleration = 0;
- move.movetime = 0;
- move.deceleration = dt;
- StartSound( "snd_decel", SND_CHANNEL_BODY2, 0, false, NULL );
- StartSound( "snd_move", SND_CHANNEL_BODY, 0, false, NULL );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_DECELLINEAR, gameLocal.time, move.deceleration, org, dir * ( v - speed ), dir * speed );
- }
- /*
- ================
- idMover::Event_RotateDownTo
- ================
- */
- void idMover::Event_RotateDownTo( int axis, float angle ) {
- idAngles ang;
- if ( ( axis < 0 ) || ( axis > 2 ) ) {
- gameLocal.Error( "Invalid axis" );
- }
- physicsObj.GetLocalAngles( ang );
- dest_angles[ axis ] = angle;
- if ( dest_angles[ axis ] > ang[ axis ] ) {
- dest_angles[ axis ] -= 360;
- }
- BeginRotation( idThread::CurrentThread(), true );
- }
- /*
- ================
- idMover::Event_RotateUpTo
- ================
- */
- void idMover::Event_RotateUpTo( int axis, float angle ) {
- idAngles ang;
- if ( ( axis < 0 ) || ( axis > 2 ) ) {
- gameLocal.Error( "Invalid axis" );
- }
- physicsObj.GetLocalAngles( ang );
- dest_angles[ axis ] = angle;
- if ( dest_angles[ axis ] < ang[ axis ] ) {
- dest_angles[ axis ] += 360;
- }
- BeginRotation( idThread::CurrentThread(), true );
- }
- /*
- ================
- idMover::Event_RotateTo
- ================
- */
- void idMover::Event_RotateTo( idAngles &angles ) {
- dest_angles = angles;
- BeginRotation( idThread::CurrentThread(), true );
- }
- /*
- ================
- idMover::Event_Rotate
- ================
- */
- void idMover::Event_Rotate( idAngles &angles ) {
- idAngles ang;
- if ( rotate_thread ) {
- DoneRotating();
- }
- physicsObj.GetLocalAngles( ang );
- dest_angles = ang + angles * ( move_time - ( acceltime + deceltime ) / 2 ) * 0.001f;
- BeginRotation( idThread::CurrentThread(), false );
- }
- /*
- ================
- idMover::Event_RotateOnce
- ================
- */
- void idMover::Event_RotateOnce( idAngles &angles ) {
- idAngles ang;
- if ( rotate_thread ) {
- DoneRotating();
- }
- physicsObj.GetLocalAngles( ang );
- dest_angles = ang + angles;
- BeginRotation( idThread::CurrentThread(), true );
- }
- /*
- ================
- idMover::Event_Bob
- ================
- */
- void idMover::Event_Bob( float speed, float phase, idVec3 &depth ) {
- idVec3 org;
- physicsObj.GetLocalOrigin( org );
- physicsObj.SetLinearExtrapolation( extrapolation_t(EXTRAPOLATION_DECELSINE|EXTRAPOLATION_NOSTOP), speed * 1000 * phase, speed * 500, org, depth * 2.0f, vec3_origin );
- }
- /*
- ================
- idMover::Event_Sway
- ================
- */
- void idMover::Event_Sway( float speed, float phase, idAngles &depth ) {
- idAngles ang, angSpeed;
- float duration;
- physicsObj.GetLocalAngles( ang );
- assert ( speed > 0.0f );
- duration = idMath::Sqrt( depth[0] * depth[0] + depth[1] * depth[1] + depth[2] * depth[2] ) / speed;
- angSpeed = depth / ( duration * idMath::SQRT_1OVER2 );
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_DECELSINE|EXTRAPOLATION_NOSTOP), duration * 1000.0f * phase, duration * 1000.0f, ang, angSpeed, ang_zero );
- }
- /*
- ================
- idMover::Event_OpenPortal
- Sets the portal associtated with this mover to be open
- ================
- */
- void idMover::Event_OpenPortal( void ) {
- if ( areaPortal ) {
- SetPortalState( true );
- }
- }
- /*
- ================
- idMover::Event_ClosePortal
- Sets the portal associtated with this mover to be closed
- ================
- */
- void idMover::Event_ClosePortal( void ) {
- if ( areaPortal ) {
- SetPortalState( false );
- }
- }
- /*
- ================
- idMover::Event_SetAccelSound
- ================
- */
- void idMover::Event_SetAccelSound( const char *sound ) {
- // refSound.SetSound( "accel", sound );
- }
- /*
- ================
- idMover::Event_SetDecelSound
- ================
- */
- void idMover::Event_SetDecelSound( const char *sound ) {
- // refSound.SetSound( "decel", sound );
- }
- /*
- ================
- idMover::Event_SetMoveSound
- ================
- */
- void idMover::Event_SetMoveSound( const char *sound ) {
- // refSound.SetSound( "move", sound );
- }
- /*
- ================
- idMover::Event_EnableSplineAngles
- ================
- */
- void idMover::Event_EnableSplineAngles( void ) {
- useSplineAngles = true;
- }
- /*
- ================
- idMover::Event_DisableSplineAngles
- ================
- */
- void idMover::Event_DisableSplineAngles( void ) {
- useSplineAngles = false;
- }
- /*
- ================
- idMover::Event_RemoveInitialSplineAngles
- ================
- */
- void idMover::Event_RemoveInitialSplineAngles( void ) {
- idCurve_Spline<idVec3> *spline;
- idAngles ang;
- spline = physicsObj.GetSpline();
- if ( !spline ) {
- return;
- }
- ang = spline->GetCurrentFirstDerivative( 0 ).ToAngles();
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, -ang, ang_zero, ang_zero );
- }
- /*
- ================
- idMover::Event_StartSpline
- ================
- */
- void idMover::Event_StartSpline( idEntity *splineEntity ) {
- idCurve_Spline<idVec3> *spline;
- if ( !splineEntity ) {
- return;
- }
- // Needed for savegames
- splineEnt = splineEntity;
- spline = splineEntity->GetSpline();
- if ( !spline ) {
- return;
- }
- lastCommand = MOVER_SPLINE;
- move_thread = 0;
- if ( acceltime + deceltime > move_time ) {
- acceltime = move_time / 2;
- deceltime = move_time - acceltime;
- }
- move.stage = FINISHED_STAGE;
- move.acceleration = acceltime;
- move.movetime = move_time;
- move.deceleration = deceltime;
- spline->MakeUniform( move_time );
- spline->ShiftTime( gameLocal.time - spline->GetTime( 0 ) );
- physicsObj.SetSpline( spline, move.acceleration, move.deceleration, useSplineAngles );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, dest_position, vec3_origin, vec3_origin );
- }
- /*
- ================
- idMover::Event_StopSpline
- ================
- */
- void idMover::Event_StopSpline( void ) {
- physicsObj.SetSpline( NULL, 0, 0, useSplineAngles );
- splineEnt = NULL;
- }
- /*
- ================
- idMover::Event_Activate
- ================
- */
- void idMover::Event_Activate( idEntity *activator ) {
- Show();
- Event_StartSpline( this );
- }
- /*
- ================
- idMover::Event_IsMoving
- ================
- */
- void idMover::Event_IsMoving( void ) {
- if ( physicsObj.GetLinearExtrapolationType() == EXTRAPOLATION_NONE ) {
- idThread::ReturnInt( false );
- } else {
- idThread::ReturnInt( true );
- }
- }
- /*
- ================
- idMover::Event_IsRotating
- ================
- */
- void idMover::Event_IsRotating( void ) {
- if ( physicsObj.GetAngularExtrapolationType() == EXTRAPOLATION_NONE ) {
- idThread::ReturnInt( false );
- } else {
- idThread::ReturnInt( true );
- }
- }
- /*
- ================
- idMover::WriteToSnapshot
- ================
- */
- void idMover::WriteToSnapshot( idBitMsgDelta &msg ) const {
- physicsObj.WriteToSnapshot( msg );
- msg.WriteBits( move.stage, 3 );
- msg.WriteBits( rot.stage, 3 );
- WriteBindToSnapshot( msg );
- WriteGUIToSnapshot( msg );
- }
- /*
- ================
- idMover::ReadFromSnapshot
- ================
- */
- void idMover::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- moveStage_t oldMoveStage = move.stage;
- moveStage_t oldRotStage = rot.stage;
- physicsObj.ReadFromSnapshot( msg );
- move.stage = (moveStage_t) msg.ReadBits( 3 );
- rot.stage = (moveStage_t) msg.ReadBits( 3 );
- ReadBindFromSnapshot( msg );
- ReadGUIFromSnapshot( msg );
- if ( msg.HasChanged() ) {
- if ( move.stage != oldMoveStage ) {
- UpdateMoveSound( oldMoveStage );
- }
- if ( rot.stage != oldRotStage ) {
- UpdateRotationSound( oldRotStage );
- }
- UpdateVisuals();
- }
- }
- /*
- ================
- idMover::SetPortalState
- ================
- */
- void idMover::SetPortalState( bool open ) {
- assert( areaPortal );
- gameLocal.SetPortalState( areaPortal, open ? PS_BLOCK_NONE : PS_BLOCK_ALL );
- }
- /*
- ===============================================================================
- idSplinePath, holds a spline path to be used by an idMover
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idSplinePath )
- END_CLASS
- /*
- ================
- idSplinePath::idSplinePath
- ================
- */
- idSplinePath::idSplinePath() {
- }
- /*
- ================
- idSplinePath::Spawn
- ================
- */
- void idSplinePath::Spawn( void ) {
- }
- /*
- ===============================================================================
- idElevator
- ===============================================================================
- */
- const idEventDef EV_PostArrival( "postArrival", NULL );
- const idEventDef EV_GotoFloor( "gotoFloor", "d" );
- CLASS_DECLARATION( idMover, idElevator )
- EVENT( EV_Activate, idElevator::Event_Activate )
- EVENT( EV_TeamBlocked, idElevator::Event_TeamBlocked )
- EVENT( EV_PartBlocked, idElevator::Event_PartBlocked )
- EVENT( EV_PostArrival, idElevator::Event_PostFloorArrival )
- EVENT( EV_GotoFloor, idElevator::Event_GotoFloor )
- EVENT( EV_Touch, idElevator::Event_Touch )
- END_CLASS
- /*
- ================
- idElevator::idElevator
- ================
- */
- idElevator::idElevator( void ) {
- state = INIT;
- floorInfo.Clear();
- currentFloor = 0;
- pendingFloor = 0;
- lastFloor = 0;
- controlsDisabled = false;
- lastTouchTime = 0;
- returnFloor = 0;
- returnTime = 0;
- }
- /*
- ================
- idElevator::Save
- ================
- */
- void idElevator::Save( idSaveGame *savefile ) const {
- int i;
- savefile->WriteInt( (int)state );
- savefile->WriteInt( floorInfo.Num() );
- for ( i = 0; i < floorInfo.Num(); i++ ) {
- savefile->WriteVec3( floorInfo[ i ].pos );
- savefile->WriteString( floorInfo[ i ].door );
- savefile->WriteInt( floorInfo[ i ].floor );
- }
- savefile->WriteInt( currentFloor );
- savefile->WriteInt( pendingFloor );
- savefile->WriteInt( lastFloor );
- savefile->WriteBool( controlsDisabled );
- savefile->WriteFloat( returnTime );
- savefile->WriteInt( returnFloor );
- savefile->WriteInt( lastTouchTime );
- }
- /*
- ================
- idElevator::Restore
- ================
- */
- void idElevator::Restore( idRestoreGame *savefile ) {
- int i, num;
- savefile->ReadInt( (int &)state );
- savefile->ReadInt( num );
- for ( i = 0; i < num; i++ ) {
- floorInfo_s floor;
- savefile->ReadVec3( floor.pos );
- savefile->ReadString( floor.door );
- savefile->ReadInt( floor.floor );
- floorInfo.Append( floor );
- }
- savefile->ReadInt( currentFloor );
- savefile->ReadInt( pendingFloor );
- savefile->ReadInt( lastFloor );
- savefile->ReadBool( controlsDisabled );
- savefile->ReadFloat( returnTime );
- savefile->ReadInt( returnFloor );
- savefile->ReadInt( lastTouchTime );
- }
- /*
- ================
- idElevator::Spawn
- ================
- */
- void idElevator::Spawn( void ) {
- idStr str;
- int len1;
- lastFloor = 0;
- currentFloor = 0;
- pendingFloor = spawnArgs.GetInt( "floor", "1" );
- SetGuiStates( ( pendingFloor == 1 ) ? guiBinaryMoverStates[0] : guiBinaryMoverStates[1]);
- returnTime = spawnArgs.GetFloat( "returnTime" );
- returnFloor = spawnArgs.GetInt( "returnFloor" );
- len1 = strlen( "floorPos_" );
- const idKeyValue *kv = spawnArgs.MatchPrefix( "floorPos_", NULL );
- while( kv ) {
- str = kv->GetKey().Right( kv->GetKey().Length() - len1 );
- floorInfo_s fi;
- fi.floor = atoi( str );
- fi.door = spawnArgs.GetString( va( "floorDoor_%i", fi.floor ) );
- fi.pos = spawnArgs.GetVector( kv->GetKey() );
- floorInfo.Append( fi );
- kv = spawnArgs.MatchPrefix( "floorPos_", kv );
- }
- lastTouchTime = 0;
- state = INIT;
- BecomeActive( TH_THINK | TH_PHYSICS );
- PostEventMS( &EV_Mover_InitGuiTargets, 0 );
- controlsDisabled = false;
- }
- /*
- ==============
- idElevator::Event_Touch
- ===============
- */
- void idElevator::Event_Touch( idEntity *other, trace_t *trace ) {
-
- if ( gameLocal.time < lastTouchTime + 2000 ) {
- return;
- }
- if ( !other->IsType( idPlayer::Type ) ) {
- return;
- }
- lastTouchTime = gameLocal.time;
- if ( thinkFlags & TH_PHYSICS ) {
- return;
- }
- int triggerFloor = spawnArgs.GetInt( "triggerFloor" );
- if ( spawnArgs.GetBool( "trigger" ) && triggerFloor != currentFloor ) {
- PostEventSec( &EV_GotoFloor, 0.25f, triggerFloor );
- }
- }
- /*
- ================
- idElevator::Think
- ================
- */
- void idElevator::Think( void ) {
- idVec3 masterOrigin;
- idMat3 masterAxis;
- idDoor *doorent = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( state == INIT ) {
- state = IDLE;
- if ( doorent ) {
- doorent->BindTeam( this );
- doorent->spawnArgs.Set( "snd_open", "" );
- doorent->spawnArgs.Set( "snd_close", "" );
- doorent->spawnArgs.Set( "snd_opened", "" );
- }
- for ( int i = 0; i < floorInfo.Num(); i++ ) {
- idDoor *door = GetDoor( floorInfo[i].door );
- if ( door ) {
- door->SetCompanion( doorent );
- }
- }
- Event_GotoFloor( pendingFloor );
- DisableAllDoors();
- SetGuiStates( ( pendingFloor == 1 ) ? guiBinaryMoverStates[0] : guiBinaryMoverStates[1] );
- } else if ( state == WAITING_ON_DOORS ) {
- if ( doorent ) {
- state = doorent->IsOpen() ? WAITING_ON_DOORS : IDLE;
- } else {
- state = IDLE;
- }
- if ( state == IDLE ) {
- lastFloor = currentFloor;
- currentFloor = pendingFloor;
- floorInfo_s *fi = GetFloorInfo( currentFloor );
- if ( fi ) {
- MoveToPos( fi->pos );
- }
- }
- }
- RunPhysics();
- Present();
- }
- /*
- ================
- idElevator::Event_Activate
- ================
- */
- void idElevator::Event_Activate( idEntity *activator ) {
- int triggerFloor = spawnArgs.GetInt( "triggerFloor" );
- if ( spawnArgs.GetBool( "trigger" ) && triggerFloor != currentFloor ) {
- Event_GotoFloor( triggerFloor );
- }
- }
- /*
- ================
- idElevator::Event_TeamBlocked
- ================
- */
- void idElevator::Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity ) {
- if ( blockedEntity == this ) {
- Event_GotoFloor( lastFloor );
- } else if ( blockedEntity && blockedEntity->IsType( idDoor::Type ) ) {
- // open the inner doors if one is blocked
- idDoor *blocked = static_cast<idDoor *>( blockedEntity );
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door && blocked->GetMoveMaster() == door->GetMoveMaster() ) {
- door->SetBlocked(true);
- OpenInnerDoor();
- OpenFloorDoor( currentFloor );
- }
- }
- }
- /*
- ===============
- idElevator::HandleSingleGuiCommand
- ===============
- */
- bool idElevator::HandleSingleGuiCommand( idEntity *entityGui, idLexer *src ) {
- idToken token;
- if ( controlsDisabled ) {
- return false;
- }
- if ( !src->ReadToken( &token ) ) {
- return false;
- }
- if ( token == ";" ) {
- return false;
- }
- if ( token.Icmp( "changefloor" ) == 0 ) {
- if ( src->ReadToken( &token ) ) {
- int newFloor = atoi( token );
- if ( newFloor == currentFloor ) {
- // open currentFloor and interior doors
- OpenInnerDoor();
- OpenFloorDoor( currentFloor );
- } else {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door && door->IsOpen() ) {
- PostEventSec( &EV_GotoFloor, 0.5f, newFloor );
- } else {
- ProcessEvent( &EV_GotoFloor, newFloor );
- }
- }
- return true;
- }
- }
- src->UnreadToken( &token );
- return false;
- }
- /*
- ================
- idElevator::OpenFloorDoor
- ================
- */
- void idElevator::OpenFloorDoor( int floor ) {
- floorInfo_s *fi = GetFloorInfo( floor );
- if ( fi ) {
- idDoor *door = GetDoor( fi->door );
- if ( door ) {
- door->Open();
- }
- }
- }
- /*
- ================
- idElevator::OpenInnerDoor
- ================
- */
- void idElevator::OpenInnerDoor( void ) {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door ) {
- door->Open();
- }
- }
- /*
- ================
- idElevator::GetFloorInfo
- ================
- */
- floorInfo_s *idElevator::GetFloorInfo( int floor ) {
- for ( int i = 0; i < floorInfo.Num(); i++ ) {
- if ( floorInfo[i].floor == floor ) {
- return &floorInfo[i];
- }
- }
- return NULL;
- }
- /*
- ================
- idElevator::Event_GotoFloor
- ================
- */
- void idElevator::Event_GotoFloor( int floor ) {
- floorInfo_s *fi = GetFloorInfo( floor );
- if ( fi ) {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door ) {
- if ( door->IsBlocked() || door->IsOpen() ) {
- PostEventSec( &EV_GotoFloor, 0.5f, floor );
- return;
- }
- }
- DisableAllDoors();
- CloseAllDoors();
- state = WAITING_ON_DOORS;
- pendingFloor = floor;
- }
- }
- /*
- ================
- idElevator::BeginMove
- ================
- */
- void idElevator::BeginMove( idThread *thread ) {
- controlsDisabled = true;
- CloseAllDoors();
- DisableAllDoors();
- const idKeyValue *kv = spawnArgs.MatchPrefix( "statusGui" );
- while( kv ) {
- idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
- if ( ent ) {
- for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
- if ( ent->GetRenderEntity() && ent->GetRenderEntity()->gui[ j ] ) {
- ent->GetRenderEntity()->gui[ j ]->SetStateString( "floor", "" );
- ent->GetRenderEntity()->gui[ j ]->StateChanged( gameLocal.time, true );
- }
- }
- ent->UpdateVisuals();
- }
- kv = spawnArgs.MatchPrefix( "statusGui", kv );
- }
- SetGuiStates( ( pendingFloor == 1 ) ? guiBinaryMoverStates[3] : guiBinaryMoverStates[2] );
- idMover::BeginMove( thread );
- }
- /*
- ================
- idElevator::GetDoor
- ================
- */
- idDoor *idElevator::GetDoor( const char *name ) {
- idEntity *ent;
- idEntity *master;
- idDoor *doorEnt;
- doorEnt = NULL;
- if ( name && *name ) {
- ent = gameLocal.FindEntity( name );
- if ( ent && ent->IsType( idDoor::Type ) ) {
- doorEnt = static_cast<idDoor*>( ent );
- master = doorEnt->GetMoveMaster();
- if ( master != doorEnt ) {
- if ( master->IsType( idDoor::Type ) ) {
- doorEnt = static_cast<idDoor*>( master );
- } else {
- doorEnt = NULL;
- }
- }
- }
- }
- return doorEnt;
- }
- /*
- ================
- idElevator::Event_PostFloorArrival
- ================
- */
- void idElevator::Event_PostFloorArrival() {
- OpenFloorDoor( currentFloor );
- OpenInnerDoor();
- SetGuiStates( ( currentFloor == 1 ) ? guiBinaryMoverStates[0] : guiBinaryMoverStates[1] );
- controlsDisabled = false;
- if ( returnTime > 0.0f && returnFloor != currentFloor ) {
- PostEventSec( &EV_GotoFloor, returnTime, returnFloor );
- }
- }
- /*
- ================
- idElevator::DoneMoving
- ================
- */
- void idElevator::DoneMoving( void ) {
- idMover::DoneMoving();
- EnableProperDoors();
- const idKeyValue *kv = spawnArgs.MatchPrefix( "statusGui" );
- while( kv ) {
- idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
- if ( ent ) {
- for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
- if ( ent->GetRenderEntity() && ent->GetRenderEntity()->gui[ j ] ) {
- ent->GetRenderEntity()->gui[ j ]->SetStateString( "floor", va( "%i", currentFloor ) );
- ent->GetRenderEntity()->gui[ j ]->StateChanged( gameLocal.time, true );
- }
- }
- ent->UpdateVisuals();
- }
- kv = spawnArgs.MatchPrefix( "statusGui", kv );
- }
- if ( spawnArgs.GetInt( "pauseOnFloor", "-1" ) == currentFloor ) {
- PostEventSec( &EV_PostArrival, spawnArgs.GetFloat( "pauseTime" ) );
- } else {
- Event_PostFloorArrival();
- }
- }
- /*
- ================
- idElevator::CloseAllDoors
- ================
- */
- void idElevator::CloseAllDoors( void ) {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door ) {
- door->Close();
- }
- for ( int i = 0; i < floorInfo.Num(); i++ ) {
- door = GetDoor( floorInfo[i].door );
- if ( door ) {
- door->Close();
- }
- }
- }
- /*
- ================
- idElevator::DisableAllDoors
- ================
- */
- void idElevator::DisableAllDoors( void ) {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door ) {
- door->Enable( false );
- }
- for ( int i = 0; i < floorInfo.Num(); i++ ) {
- door = GetDoor( floorInfo[i].door );
- if ( door ) {
- door->Enable( false );
- }
- }
- }
- /*
- ================
- idElevator::EnableProperDoors
- ================
- */
- void idElevator::EnableProperDoors( void ) {
- idDoor *door = GetDoor( spawnArgs.GetString( "innerdoor" ) );
- if ( door ) {
- door->Enable( true );
- }
- for ( int i = 0; i < floorInfo.Num(); i++ ) {
- if ( floorInfo[i].floor == currentFloor ) {
- door = GetDoor( floorInfo[i].door );
- if ( door ) {
- door->Enable( true );
- break;
- }
- }
- }
- }
- /*
- ===============================================================================
- idMover_Binary
- Doors, plats, and buttons are all binary (two position) movers
- Pos1 is "at rest", pos2 is "activated"
- ===============================================================================
- */
- const idEventDef EV_Mover_ReturnToPos1( "<returntopos1>", NULL );
- const idEventDef EV_Mover_MatchTeam( "<matchteam>", "dd" );
- const idEventDef EV_Mover_Enable( "enable", NULL );
- const idEventDef EV_Mover_Disable( "disable", NULL );
- CLASS_DECLARATION( idEntity, idMover_Binary )
- EVENT( EV_FindGuiTargets, idMover_Binary::Event_FindGuiTargets )
- EVENT( EV_Thread_SetCallback, idMover_Binary::Event_SetCallback )
- EVENT( EV_Mover_ReturnToPos1, idMover_Binary::Event_ReturnToPos1 )
- EVENT( EV_Activate, idMover_Binary::Event_Use_BinaryMover )
- EVENT( EV_ReachedPos, idMover_Binary::Event_Reached_BinaryMover )
- EVENT( EV_Mover_MatchTeam, idMover_Binary::Event_MatchActivateTeam )
- EVENT( EV_Mover_Enable, idMover_Binary::Event_Enable )
- EVENT( EV_Mover_Disable, idMover_Binary::Event_Disable )
- EVENT( EV_Mover_OpenPortal, idMover_Binary::Event_OpenPortal )
- EVENT( EV_Mover_ClosePortal, idMover_Binary::Event_ClosePortal )
- EVENT( EV_Mover_InitGuiTargets, idMover_Binary::Event_InitGuiTargets )
- END_CLASS
- /*
- ================
- idMover_Binary::idMover_Binary()
- ================
- */
- idMover_Binary::idMover_Binary() {
- pos1.Zero();
- pos2.Zero();
- moverState = MOVER_POS1;
- moveMaster = NULL;
- activateChain = NULL;
- soundPos1 = 0;
- sound1to2 = 0;
- sound2to1 = 0;
- soundPos2 = 0;
- soundLoop = 0;
- wait = 0.0f;
- damage = 0.0f;
- duration = 0;
- accelTime = 0;
- decelTime = 0;
- activatedBy = this;
- stateStartTime = 0;
- team.Clear();
- enabled = false;
- move_thread = 0;
- updateStatus = 0;
- areaPortal = 0;
- blocked = false;
- fl.networkSync = true;
- }
- /*
- ================
- idMover_Binary::~idMover_Binary
- ================
- */
- idMover_Binary::~idMover_Binary() {
- idMover_Binary *mover;
- // if this is the mover master
- if ( this == moveMaster ) {
- // make the next mover in the chain the move master
- for ( mover = moveMaster; mover; mover = mover->activateChain ) {
- mover->moveMaster = this->activateChain;
- }
- }
- else {
- // remove mover from the activate chain
- for ( mover = moveMaster; mover; mover = mover->activateChain ) {
- if ( mover->activateChain == this ) {
- mover->activateChain = this->activateChain;
- break;
- }
- }
- }
- }
- /*
- ================
- idMover_Binary::Save
- ================
- */
- void idMover_Binary::Save( idSaveGame *savefile ) const {
- int i;
- savefile->WriteVec3( pos1 );
- savefile->WriteVec3( pos2 );
- savefile->WriteInt( (moverState_t)moverState );
- savefile->WriteObject( moveMaster );
- savefile->WriteObject( activateChain );
- savefile->WriteInt( soundPos1 );
- savefile->WriteInt( sound1to2 );
- savefile->WriteInt( sound2to1 );
- savefile->WriteInt( soundPos2 );
- savefile->WriteInt( soundLoop );
- savefile->WriteFloat( wait );
- savefile->WriteFloat( damage );
- savefile->WriteInt( duration );
- savefile->WriteInt( accelTime );
- savefile->WriteInt( decelTime );
- activatedBy.Save( savefile );
- savefile->WriteInt( stateStartTime );
- savefile->WriteString( team );
- savefile->WriteBool( enabled );
- savefile->WriteInt( move_thread );
- savefile->WriteInt( updateStatus );
- savefile->WriteInt( buddies.Num() );
- for ( i = 0; i < buddies.Num(); i++ ) {
- savefile->WriteString( buddies[ i ] );
- }
- savefile->WriteStaticObject( physicsObj );
- savefile->WriteInt( areaPortal );
- if ( areaPortal ) {
- savefile->WriteInt( gameRenderWorld->GetPortalState( areaPortal ) );
- }
- savefile->WriteBool( blocked );
- savefile->WriteInt( guiTargets.Num() );
- for( i = 0; i < guiTargets.Num(); i++ ) {
- guiTargets[ i ].Save( savefile );
- }
- }
- /*
- ================
- idMover_Binary::Restore
- ================
- */
- void idMover_Binary::Restore( idRestoreGame *savefile ) {
- int i, num, portalState;
- idStr temp;
- savefile->ReadVec3( pos1 );
- savefile->ReadVec3( pos2 );
- savefile->ReadInt( (int &)moverState );
- savefile->ReadObject( reinterpret_cast<idClass *&>( moveMaster ) );
- savefile->ReadObject( reinterpret_cast<idClass *&>( activateChain ) );
- savefile->ReadInt( soundPos1 );
- savefile->ReadInt( sound1to2 );
- savefile->ReadInt( sound2to1 );
- savefile->ReadInt( soundPos2 );
- savefile->ReadInt( soundLoop );
- savefile->ReadFloat( wait );
- savefile->ReadFloat( damage );
- savefile->ReadInt( duration );
- savefile->ReadInt( accelTime );
- savefile->ReadInt( decelTime );
- activatedBy.Restore( savefile );
- savefile->ReadInt( stateStartTime );
- savefile->ReadString( team );
- savefile->ReadBool( enabled );
- savefile->ReadInt( move_thread );
- savefile->ReadInt( updateStatus );
- savefile->ReadInt( num );
- for ( i = 0; i < num; i++ ) {
- savefile->ReadString( temp );
- buddies.Append( temp );
- }
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- savefile->ReadInt( areaPortal );
- if ( areaPortal ) {
- savefile->ReadInt( portalState );
- gameLocal.SetPortalState( areaPortal, portalState );
- }
- savefile->ReadBool( blocked );
- guiTargets.Clear();
- savefile->ReadInt( num );
- guiTargets.SetNum( num );
- for( i = 0; i < num; i++ ) {
- guiTargets[ i ].Restore( savefile );
- }
- }
- /*
- ================
- idMover_Binary::Spawn
- Base class for all movers.
- "wait" wait before returning (3 default, -1 = never return)
- "speed" movement speed
- ================
- */
- void idMover_Binary::Spawn( void ) {
- idEntity *ent;
- const char *temp;
- move_thread = 0;
- enabled = true;
- areaPortal = 0;
- activateChain = NULL;
- spawnArgs.GetFloat( "wait", "0", wait );
- spawnArgs.GetInt( "updateStatus", "0", updateStatus );
- const idKeyValue *kv = spawnArgs.MatchPrefix( "buddy", NULL );
- while( kv ) {
- buddies.Append( kv->GetValue() );
- kv = spawnArgs.MatchPrefix( "buddy", kv );
- }
- spawnArgs.GetString( "team", "", &temp );
- team = temp;
- if ( !team.Length() ) {
- ent = this;
- } else {
- // find the first entity spawned on this team (which could be us)
- for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
- if ( ent->IsType( idMover_Binary::Type ) && !idStr::Icmp( static_cast<idMover_Binary *>(ent)->team.c_str(), temp ) ) {
- break;
- }
- }
- if ( !ent ) {
- ent = this;
- }
- }
- moveMaster = static_cast<idMover_Binary *>(ent);
- // create a physics team for the binary mover parts
- if ( ent != this ) {
- JoinTeam( ent );
- }
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "solid", "1" ) ) {
- physicsObj.SetContents( 0 );
- }
- if ( !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, GetPhysics()->GetOrigin(), vec3_origin, vec3_origin );
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, GetPhysics()->GetAxis().ToAngles(), ang_zero, ang_zero );
- SetPhysics( &physicsObj );
- if ( moveMaster != this ) {
- JoinActivateTeam( moveMaster );
- }
- idBounds soundOrigin;
- idMover_Binary *slave;
- soundOrigin.Clear();
- for ( slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- soundOrigin += slave->GetPhysics()->GetAbsBounds();
- }
- moveMaster->refSound.origin = soundOrigin.GetCenter();
- if ( spawnArgs.MatchPrefix( "guiTarget" ) ) {
- if ( gameLocal.GameState() == GAMESTATE_STARTUP ) {
- PostEventMS( &EV_FindGuiTargets, 0 );
- } else {
- // not during spawn, so it's ok to get the targets
- FindGuiTargets();
- }
- }
- }
- /*
- ===============
- idMover_Binary::GetMovedir
- The editor only specifies a single value for angles (yaw),
- but we have special constants to generate an up or down direction.
- Angles will be cleared, because it is being used to represent a direction
- instead of an orientation.
- ===============
- */
- void idMover_Binary::GetMovedir( float angle, idVec3 &movedir ) {
- if ( angle == -1 ) {
- movedir.Set( 0, 0, 1 );
- } else if ( angle == -2 ) {
- movedir.Set( 0, 0, -1 );
- } else {
- movedir = idAngles( 0, angle, 0 ).ToForward();
- }
- }
- /*
- ================
- idMover_Binary::Event_SetCallback
- ================
- */
- void idMover_Binary::Event_SetCallback( void ) {
- if ( ( moverState == MOVER_1TO2 ) || ( moverState == MOVER_2TO1 ) ) {
- move_thread = idThread::CurrentThreadNum();
- idThread::ReturnInt( true );
- } else {
- idThread::ReturnInt( false );
- }
- }
- /*
- ===============
- idMover_Binary::UpdateMoverSound
- ===============
- */
- void idMover_Binary::UpdateMoverSound( moverState_t state ) {
- if ( moveMaster == this ) {
- switch( state ) {
- case MOVER_POS1:
- break;
- case MOVER_POS2:
- break;
- case MOVER_1TO2:
- StartSound( "snd_open", SND_CHANNEL_ANY, 0, false, NULL );
- break;
- case MOVER_2TO1:
- StartSound( "snd_close", SND_CHANNEL_ANY, 0, false, NULL );
- break;
- }
- }
- }
- /*
- ===============
- idMover_Binary::SetMoverState
- ===============
- */
- void idMover_Binary::SetMoverState( moverState_t newstate, int time ) {
- idVec3 delta;
- moverState = newstate;
- move_thread = 0;
- UpdateMoverSound( newstate );
- stateStartTime = time;
- switch( moverState ) {
- case MOVER_POS1: {
- Signal( SIG_MOVER_POS1 );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, time, 0, pos1, vec3_origin, vec3_origin );
- break;
- }
- case MOVER_POS2: {
- Signal( SIG_MOVER_POS2 );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, time, 0, pos2, vec3_origin, vec3_origin );
- break;
- }
- case MOVER_1TO2: {
- Signal( SIG_MOVER_1TO2 );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_LINEAR, time, duration, pos1, ( pos2 - pos1 ) * 1000.0f / duration, vec3_origin );
- if ( accelTime != 0 || decelTime != 0 ) {
- physicsObj.SetLinearInterpolation( time, accelTime, decelTime, duration, pos1, pos2 );
- } else {
- physicsObj.SetLinearInterpolation( 0, 0, 0, 0, pos1, pos2 );
- }
- break;
- }
- case MOVER_2TO1: {
- Signal( SIG_MOVER_2TO1 );
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_LINEAR, time, duration, pos2, ( pos1 - pos2 ) * 1000.0f / duration, vec3_origin );
- if ( accelTime != 0 || decelTime != 0 ) {
- physicsObj.SetLinearInterpolation( time, accelTime, decelTime, duration, pos2, pos1 );
- } else {
- physicsObj.SetLinearInterpolation( 0, 0, 0, 0, pos1, pos2 );
- }
- break;
- }
- }
- }
- /*
- ================
- idMover_Binary::MatchActivateTeam
- All entities in a mover team will move from pos1 to pos2
- in the same amount of time
- ================
- */
- void idMover_Binary::MatchActivateTeam( moverState_t newstate, int time ) {
- idMover_Binary *slave;
- for ( slave = this; slave != NULL; slave = slave->activateChain ) {
- slave->SetMoverState( newstate, time );
- }
- }
- /*
- ================
- idMover_Binary::Enable
- ================
- */
- void idMover_Binary::Enable( bool b ) {
- enabled = b;
- }
- /*
- ================
- idMover_Binary::Event_MatchActivateTeam
- ================
- */
- void idMover_Binary::Event_MatchActivateTeam( moverState_t newstate, int time ) {
- MatchActivateTeam( newstate, time );
- }
- /*
- ================
- idMover_Binary::BindTeam
- All entities in a mover team will be bound
- ================
- */
- void idMover_Binary::BindTeam( idEntity *bindTo ) {
- idMover_Binary *slave;
- for ( slave = this; slave != NULL; slave = slave->activateChain ) {
- slave->Bind( bindTo, true );
- }
- }
- /*
- ================
- idMover_Binary::JoinActivateTeam
- Set all entities in a mover team to be enabled
- ================
- */
- void idMover_Binary::JoinActivateTeam( idMover_Binary *master ) {
- this->activateChain = master->activateChain;
- master->activateChain = this;
- }
- /*
- ================
- idMover_Binary::Event_Enable
- Set all entities in a mover team to be enabled
- ================
- */
- void idMover_Binary::Event_Enable( void ) {
- idMover_Binary *slave;
- for ( slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- slave->Enable( false );
- }
- }
- /*
- ================
- idMover_Binary::Event_Disable
- Set all entities in a mover team to be disabled
- ================
- */
- void idMover_Binary::Event_Disable( void ) {
- idMover_Binary *slave;
- for ( slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- slave->Enable( false );
- }
- }
- /*
- ================
- idMover_Binary::Event_OpenPortal
- Sets the portal associtated with this mover to be open
- ================
- */
- void idMover_Binary::Event_OpenPortal( void ) {
- idMover_Binary *slave;
- for ( slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- if ( slave->areaPortal ) {
- slave->SetPortalState( true );
- }
- }
- }
- /*
- ================
- idMover_Binary::Event_ClosePortal
- Sets the portal associtated with this mover to be closed
- ================
- */
- void idMover_Binary::Event_ClosePortal( void ) {
- idMover_Binary *slave;
- for ( slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- if ( !slave->IsHidden() ) {
- if ( slave->areaPortal ) {
- slave->SetPortalState( false );
- }
- }
- }
- }
- /*
- ================
- idMover_Binary::Event_ReturnToPos1
- ================
- */
- void idMover_Binary::Event_ReturnToPos1( void ) {
- MatchActivateTeam( MOVER_2TO1, gameLocal.time );
- }
- /*
- ================
- idMover_Binary::Event_Reached_BinaryMover
- ================
- */
- void idMover_Binary::Event_Reached_BinaryMover( void ) {
- if ( moverState == MOVER_1TO2 ) {
- // reached pos2
- idThread::ObjectMoveDone( move_thread, this );
- move_thread = 0;
- if ( moveMaster == this ) {
- StartSound( "snd_opened", SND_CHANNEL_ANY, 0, false, NULL );
- }
- SetMoverState( MOVER_POS2, gameLocal.time );
- SetGuiStates( guiBinaryMoverStates[MOVER_POS2] );
- UpdateBuddies( 1 );
- if ( enabled && wait >= 0 && !spawnArgs.GetBool( "toggle" ) ) {
- // return to pos1 after a delay
- PostEventSec( &EV_Mover_ReturnToPos1, wait );
- }
-
- // fire targets
- ActivateTargets( moveMaster->GetActivator() );
- SetBlocked(false);
- } else if ( moverState == MOVER_2TO1 ) {
- // reached pos1
- idThread::ObjectMoveDone( move_thread, this );
- move_thread = 0;
- SetMoverState( MOVER_POS1, gameLocal.time );
- SetGuiStates( guiBinaryMoverStates[MOVER_POS1] );
- UpdateBuddies( 0 );
- // close areaportals
- if ( moveMaster == this ) {
- ProcessEvent( &EV_Mover_ClosePortal );
- }
- if ( enabled && wait >= 0 && spawnArgs.GetBool( "continuous" ) ) {
- PostEventSec( &EV_Activate, wait, this );
- }
- SetBlocked(false);
- } else {
- gameLocal.Error( "Event_Reached_BinaryMover: bad moverState" );
- }
- }
- /*
- ================
- idMover_Binary::GotoPosition1
- ================
- */
- void idMover_Binary::GotoPosition1( void ) {
- idMover_Binary *slave;
- int partial;
- // only the master should control this
- if ( moveMaster != this ) {
- moveMaster->GotoPosition1();
- return;
- }
- SetGuiStates( guiBinaryMoverStates[MOVER_2TO1] );
- if ( ( moverState == MOVER_POS1 ) || ( moverState == MOVER_2TO1 ) ) {
- // already there, or on the way
- return;
- }
- if ( moverState == MOVER_POS2 ) {
- for ( slave = this; slave != NULL; slave = slave->activateChain ) {
- slave->CancelEvents( &EV_Mover_ReturnToPos1 );
- }
- if ( !spawnArgs.GetBool( "toggle" ) ) {
- ProcessEvent( &EV_Mover_ReturnToPos1 );
- }
- return;
- }
- // only partway up before reversing
- if ( moverState == MOVER_1TO2 ) {
- // use the physics times because this might be executed during the physics simulation
- partial = physicsObj.GetLinearEndTime() - physicsObj.GetTime();
- assert( partial >= 0 );
- if ( partial < 0 ) {
- partial = 0;
- }
- MatchActivateTeam( MOVER_2TO1, physicsObj.GetTime() - partial );
- // if already at at position 1 (partial == duration) execute the reached event
- if ( partial >= duration ) {
- Event_Reached_BinaryMover();
- }
- }
- }
- /*
- ================
- idMover_Binary::GotoPosition2
- ================
- */
- void idMover_Binary::GotoPosition2( void ) {
- int partial;
- // only the master should control this
- if ( moveMaster != this ) {
- moveMaster->GotoPosition2();
- return;
- }
- SetGuiStates( guiBinaryMoverStates[MOVER_1TO2] );
- if ( ( moverState == MOVER_POS2 ) || ( moverState == MOVER_1TO2 ) ) {
- // already there, or on the way
- return;
- }
- if ( moverState == MOVER_POS1 ) {
- MatchActivateTeam( MOVER_1TO2, gameLocal.time );
- // open areaportal
- ProcessEvent( &EV_Mover_OpenPortal );
- return;
- }
- // only partway up before reversing
- if ( moverState == MOVER_2TO1 ) {
- // use the physics times because this might be executed during the physics simulation
- partial = physicsObj.GetLinearEndTime() - physicsObj.GetTime();
- assert( partial >= 0 );
- if ( partial < 0 ) {
- partial = 0;
- }
- MatchActivateTeam( MOVER_1TO2, physicsObj.GetTime() - partial );
- // if already at at position 2 (partial == duration) execute the reached event
- if ( partial >= duration ) {
- Event_Reached_BinaryMover();
- }
- }
- }
- /*
- ================
- idMover_Binary::UpdateBuddies
- ================
- */
- void idMover_Binary::UpdateBuddies( int val ) {
- int i, c;
- if ( updateStatus == 2 ) {
- c = buddies.Num();
- for ( i = 0; i < c; i++ ) {
- idEntity *buddy = gameLocal.FindEntity( buddies[i] );
- if ( buddy ) {
- buddy->SetShaderParm( SHADERPARM_MODE, val );
- buddy->UpdateVisuals();
- }
- }
- }
- }
- /*
- ================
- idMover_Binary::SetGuiStates
- ================
- */
- void idMover_Binary::SetGuiStates( const char *state ) {
- if ( guiTargets.Num() ) {
- SetGuiState( "movestate", state );
- }
- idMover_Binary *mb = activateChain;
- while( mb ) {
- if ( mb->guiTargets.Num() ) {
- mb->SetGuiState( "movestate", state );
- }
- mb = mb->activateChain;
- }
- }
- /*
- ================
- idMover_Binary::Use_BinaryMover
- ================
- */
- void idMover_Binary::Use_BinaryMover( idEntity *activator ) {
- // only the master should be used
- if ( moveMaster != this ) {
- moveMaster->Use_BinaryMover( activator );
- return;
- }
- if ( !enabled ) {
- return;
- }
- activatedBy = activator;
- if ( moverState == MOVER_POS1 ) {
- // FIXME: start moving USERCMD_MSEC later, because if this was player
- // triggered, gameLocal.time hasn't been advanced yet
- MatchActivateTeam( MOVER_1TO2, gameLocal.time + USERCMD_MSEC );
- SetGuiStates( guiBinaryMoverStates[MOVER_1TO2] );
- // open areaportal
- ProcessEvent( &EV_Mover_OpenPortal );
- return;
- }
- // if all the way up, just delay before coming down
- if ( moverState == MOVER_POS2 ) {
- idMover_Binary *slave;
- if ( wait == -1 ) {
- return;
- }
- SetGuiStates( guiBinaryMoverStates[MOVER_2TO1] );
- for ( slave = this; slave != NULL; slave = slave->activateChain ) {
- slave->CancelEvents( &EV_Mover_ReturnToPos1 );
- slave->PostEventSec( &EV_Mover_ReturnToPos1, spawnArgs.GetBool( "toggle" ) ? 0 : wait );
- }
- return;
- }
- // only partway down before reversing
- if ( moverState == MOVER_2TO1 ) {
- GotoPosition2();
- return;
- }
- // only partway up before reversing
- if ( moverState == MOVER_1TO2 ) {
- GotoPosition1();
- return;
- }
- }
- /*
- ================
- idMover_Binary::Event_Use_BinaryMover
- ================
- */
- void idMover_Binary::Event_Use_BinaryMover( idEntity *activator ) {
- Use_BinaryMover( activator );
- }
- /*
- ================
- idMover_Binary::PreBind
- ================
- */
- void idMover_Binary::PreBind( void ) {
- pos1 = GetWorldCoordinates( pos1 );
- pos2 = GetWorldCoordinates( pos2 );
- }
- /*
- ================
- idMover_Binary::PostBind
- ================
- */
- void idMover_Binary::PostBind( void ) {
- pos1 = GetLocalCoordinates( pos1 );
- pos2 = GetLocalCoordinates( pos2 );
- }
- /*
- ================
- idMover_Binary::FindGuiTargets
- ================
- */
- void idMover_Binary::FindGuiTargets( void ) {
- gameLocal.GetTargets( spawnArgs, guiTargets, "guiTarget" );
- }
- /*
- ==============================
- idMover_Binary::SetGuiState
- key/val will be set to any renderEntity->gui's on the list
- ==============================
- */
- void idMover_Binary::SetGuiState( const char *key, const char *val ) const {
- int i;
- for( i = 0; i < guiTargets.Num(); i++ ) {
- idEntity *ent = guiTargets[ i ].GetEntity();
- if ( ent ) {
- for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
- if ( ent->GetRenderEntity() && ent->GetRenderEntity()->gui[ j ] ) {
- ent->GetRenderEntity()->gui[ j ]->SetStateString( key, val );
- ent->GetRenderEntity()->gui[ j ]->StateChanged( gameLocal.time, true );
- }
- }
- ent->UpdateVisuals();
- }
- }
- }
- /*
- ================
- idMover_Binary::Event_InitGuiTargets
- ================
- */
- void idMover_Binary::Event_FindGuiTargets( void ) {
- FindGuiTargets();
- }
- /*
- ================
- idMover_Binary::Event_InitGuiTargets
- ================
- */
- void idMover_Binary::Event_InitGuiTargets( void ) {
- if ( guiTargets.Num() ) {
- SetGuiState( "movestate", guiBinaryMoverStates[MOVER_POS1] );
- }
- }
- /*
- ================
- idMover_Binary::InitSpeed
- pos1, pos2, and speed are passed in so the movement delta can be calculated
- ================
- */
- void idMover_Binary::InitSpeed( idVec3 &mpos1, idVec3 &mpos2, float mspeed, float maccelTime, float mdecelTime ) {
- idVec3 move;
- float distance;
- float speed;
- pos1 = mpos1;
- pos2 = mpos2;
- accelTime = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( maccelTime ) );
- decelTime = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( mdecelTime ) );
- speed = mspeed ? mspeed : 100;
- // calculate time to reach second position from speed
- move = pos2 - pos1;
- distance = move.Length();
- duration = idPhysics::SnapTimeToPhysicsFrame( distance * 1000 / speed );
- if ( duration <= 0 ) {
- duration = 1;
- }
- moverState = MOVER_POS1;
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, pos1, vec3_origin, vec3_origin );
- physicsObj.SetLinearInterpolation( 0, 0, 0, 0, vec3_origin, vec3_origin );
- SetOrigin( pos1 );
- PostEventMS( &EV_Mover_InitGuiTargets, 0 );
- }
- /*
- ================
- idMover_Binary::InitTime
- pos1, pos2, and time are passed in so the movement delta can be calculated
- ================
- */
- void idMover_Binary::InitTime( idVec3 &mpos1, idVec3 &mpos2, float mtime, float maccelTime, float mdecelTime ) {
- pos1 = mpos1;
- pos2 = mpos2;
- accelTime = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( maccelTime ) );
- decelTime = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( mdecelTime ) );
- duration = idPhysics::SnapTimeToPhysicsFrame( SEC2MS( mtime ) );
- if ( duration <= 0 ) {
- duration = 1;
- }
- moverState = MOVER_POS1;
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, pos1, vec3_origin, vec3_origin );
- physicsObj.SetLinearInterpolation( 0, 0, 0, 0, vec3_origin, vec3_origin );
- SetOrigin( pos1 );
- PostEventMS( &EV_Mover_InitGuiTargets, 0 );
- }
- /*
- ================
- idMover_Binary::SetBlocked
- ================
- */
- void idMover_Binary::SetBlocked( bool b ) {
- for ( idMover_Binary *slave = moveMaster; slave != NULL; slave = slave->activateChain ) {
- slave->blocked = b;
- if ( b ) {
- const idKeyValue *kv = slave->spawnArgs.MatchPrefix( "triggerBlocked" );
- while( kv ) {
- idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
- if ( ent ) {
- ent->PostEventMS( &EV_Activate, 0, moveMaster->GetActivator() );
- }
- kv = slave->spawnArgs.MatchPrefix( "triggerBlocked", kv );
- }
- }
- }
- }
- /*
- ================
- idMover_Binary::IsBlocked
- ================
- */
- bool idMover_Binary::IsBlocked( void ) {
- return blocked;
- }
- /*
- ================
- idMover_Binary::GetActivator
- ================
- */
- idEntity *idMover_Binary::GetActivator( void ) const {
- return activatedBy.GetEntity();
- }
- /*
- ================
- idMover_Binary::WriteToSnapshot
- ================
- */
- void idMover_Binary::WriteToSnapshot( idBitMsgDelta &msg ) const {
- physicsObj.WriteToSnapshot( msg );
- msg.WriteBits( moverState, 3 );
- WriteBindToSnapshot( msg );
- }
- /*
- ================
- idMover_Binary::ReadFromSnapshot
- ================
- */
- void idMover_Binary::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- moverState_t oldMoverState = moverState;
- physicsObj.ReadFromSnapshot( msg );
- moverState = (moverState_t) msg.ReadBits( 3 );
- ReadBindFromSnapshot( msg );
- if ( msg.HasChanged() ) {
- if ( moverState != oldMoverState ) {
- UpdateMoverSound( moverState );
- }
- UpdateVisuals();
- }
- }
- /*
- ================
- idMover_Binary::SetPortalState
- ================
- */
- void idMover_Binary::SetPortalState( bool open ) {
- assert( areaPortal );
- gameLocal.SetPortalState( areaPortal, open ? PS_BLOCK_NONE : PS_BLOCK_ALL );
- }
- /*
- ===============================================================================
- idDoor
- A use can be triggered either by a touch function, by being shot, or by being
- targeted by another entity.
- ===============================================================================
- */
- const idEventDef EV_Door_StartOpen( "<startOpen>", NULL );
- const idEventDef EV_Door_SpawnDoorTrigger( "<spawnDoorTrigger>", NULL );
- const idEventDef EV_Door_SpawnSoundTrigger( "<spawnSoundTrigger>", NULL );
- const idEventDef EV_Door_Open( "open", NULL );
- const idEventDef EV_Door_Close( "close", NULL );
- const idEventDef EV_Door_Lock( "lock", "d" );
- const idEventDef EV_Door_IsOpen( "isOpen", NULL, 'f' );
- const idEventDef EV_Door_IsLocked( "isLocked", NULL, 'f' );
- CLASS_DECLARATION( idMover_Binary, idDoor )
- EVENT( EV_TeamBlocked, idDoor::Event_TeamBlocked )
- EVENT( EV_PartBlocked, idDoor::Event_PartBlocked )
- EVENT( EV_Touch, idDoor::Event_Touch )
- EVENT( EV_Activate, idDoor::Event_Activate )
- EVENT( EV_Door_StartOpen, idDoor::Event_StartOpen )
- EVENT( EV_Door_SpawnDoorTrigger, idDoor::Event_SpawnDoorTrigger )
- EVENT( EV_Door_SpawnSoundTrigger, idDoor::Event_SpawnSoundTrigger )
- EVENT( EV_Door_Open, idDoor::Event_Open )
- EVENT( EV_Door_Close, idDoor::Event_Close )
- EVENT( EV_Door_Lock, idDoor::Event_Lock )
- EVENT( EV_Door_IsOpen, idDoor::Event_IsOpen )
- EVENT( EV_Door_IsLocked, idDoor::Event_Locked )
- EVENT( EV_ReachedPos, idDoor::Event_Reached_BinaryMover )
- EVENT( EV_SpectatorTouch, idDoor::Event_SpectatorTouch )
- EVENT( EV_Mover_OpenPortal, idDoor::Event_OpenPortal )
- EVENT( EV_Mover_ClosePortal, idDoor::Event_ClosePortal )
- END_CLASS
- /*
- ================
- idDoor::idDoor
- ================
- */
- idDoor::idDoor( void ) {
- triggersize = 1.0f;
- crusher = false;
- noTouch = false;
- aas_area_closed = false;
- buddyStr.Clear();
- trigger = NULL;
- sndTrigger = NULL;
- nextSndTriggerTime = 0;
- localTriggerOrigin.Zero();
- localTriggerAxis.Identity();
- requires.Clear();
- removeItem = 0;
- syncLock.Clear();
- companionDoor = NULL;
- normalAxisIndex = 0;
- }
- /*
- ================
- idDoor::~idDoor
- ================
- */
- idDoor::~idDoor( void ) {
- if ( trigger ) {
- delete trigger;
- }
- if ( sndTrigger ) {
- delete sndTrigger;
- }
- }
- /*
- ================
- idDoor::Save
- ================
- */
- void idDoor::Save( idSaveGame *savefile ) const {
- savefile->WriteFloat( triggersize );
- savefile->WriteBool( crusher );
- savefile->WriteBool( noTouch );
- savefile->WriteBool( aas_area_closed );
- savefile->WriteString( buddyStr );
- savefile->WriteInt( nextSndTriggerTime );
- savefile->WriteVec3( localTriggerOrigin );
- savefile->WriteMat3( localTriggerAxis );
- savefile->WriteString( requires );
- savefile->WriteInt( removeItem );
- savefile->WriteString( syncLock );
- savefile->WriteInt( normalAxisIndex );
- savefile->WriteClipModel( trigger );
- savefile->WriteClipModel( sndTrigger );
- savefile->WriteObject( companionDoor );
- }
- /*
- ================
- idDoor::Restore
- ================
- */
- void idDoor::Restore( idRestoreGame *savefile ) {
- savefile->ReadFloat( triggersize );
- savefile->ReadBool( crusher );
- savefile->ReadBool( noTouch );
- savefile->ReadBool( aas_area_closed );
- SetAASAreaState( aas_area_closed );
- savefile->ReadString( buddyStr );
- savefile->ReadInt( nextSndTriggerTime );
- savefile->ReadVec3( localTriggerOrigin );
- savefile->ReadMat3( localTriggerAxis );
- savefile->ReadString( requires );
- savefile->ReadInt( removeItem );
- savefile->ReadString( syncLock );
- savefile->ReadInt( normalAxisIndex );
- savefile->ReadClipModel( trigger );
- savefile->ReadClipModel( sndTrigger );
- savefile->ReadObject( reinterpret_cast<idClass *&>( companionDoor ) );
- }
- /*
- ================
- idDoor::Spawn
- ================
- */
- void idDoor::Spawn( void ) {
- idVec3 abs_movedir;
- float distance;
- idVec3 size;
- idVec3 movedir;
- float dir;
- float lip;
- bool start_open;
- float time;
- float speed;
- // get the direction to move
- if ( !spawnArgs.GetFloat( "movedir", "0", dir ) ) {
- // no movedir, so angle defines movement direction and not orientation,
- // a la oldschool Quake
- SetAngles( ang_zero );
- spawnArgs.GetFloat( "angle", "0", dir );
- }
- GetMovedir( dir, movedir );
- // default speed of 400
- spawnArgs.GetFloat( "speed", "400", speed );
- // default wait of 2 seconds
- spawnArgs.GetFloat( "wait", "3", wait );
- // default lip of 8 units
- spawnArgs.GetFloat( "lip", "8", lip );
- // by default no damage
- spawnArgs.GetFloat( "damage", "0", damage );
- // trigger size
- spawnArgs.GetFloat( "triggersize", "120", triggersize );
- spawnArgs.GetBool( "crusher", "0", crusher );
- spawnArgs.GetBool( "start_open", "0", start_open );
- spawnArgs.GetBool( "no_touch", "0", noTouch );
- // expects syncLock to be a door that must be closed before this door will open
- spawnArgs.GetString( "syncLock", "", syncLock );
- spawnArgs.GetString( "buddy", "", buddyStr );
- spawnArgs.GetString( "requires", "", requires );
- spawnArgs.GetInt( "removeItem", "0", removeItem );
- // ever separate piece of a door is considered solid when other team mates push entities
- fl.solidForTeam = true;
- // first position at start
- pos1 = GetPhysics()->GetOrigin();
- // calculate second position
- abs_movedir[0] = idMath::Fabs( movedir[ 0 ] );
- abs_movedir[1] = idMath::Fabs( movedir[ 1 ] );
- abs_movedir[2] = idMath::Fabs( movedir[ 2 ] );
- size = GetPhysics()->GetAbsBounds()[1] - GetPhysics()->GetAbsBounds()[0];
- distance = ( abs_movedir * size ) - lip;
- pos2 = pos1 + distance * movedir;
- // if "start_open", reverse position 1 and 2
- if ( start_open ) {
- // post it after EV_SpawnBind
- PostEventMS( &EV_Door_StartOpen, 1 );
- }
- if ( spawnArgs.GetFloat( "time", "1", time ) ) {
- InitTime( pos1, pos2, time, 0, 0 );
- } else {
- InitSpeed( pos1, pos2, speed, 0, 0 );
- }
- if ( moveMaster == this ) {
- if ( health ) {
- fl.takedamage = true;
- }
- if ( noTouch || health ) {
- // non touch/shoot doors
- PostEventMS( &EV_Mover_MatchTeam, 0, moverState, gameLocal.time );
- const char *sndtemp = spawnArgs.GetString( "snd_locked" );
- if ( spawnArgs.GetInt( "locked" ) && sndtemp && *sndtemp ) {
- PostEventMS( &EV_Door_SpawnSoundTrigger, 0 );
- }
- } else {
- // spawn trigger
- PostEventMS( &EV_Door_SpawnDoorTrigger, 0 );
- }
- }
- // see if we are on an areaportal
- areaPortal = gameRenderWorld->FindPortal( GetPhysics()->GetAbsBounds() );
- if ( !start_open ) {
- // start closed
- ProcessEvent( &EV_Mover_ClosePortal );
- }
- int locked = spawnArgs.GetInt( "locked" );
- if ( locked ) {
- // make sure all members of the team get locked
- PostEventMS( &EV_Door_Lock, 0, locked );
- }
- if ( spawnArgs.GetBool( "continuous" ) ) {
- PostEventSec( &EV_Activate, spawnArgs.GetFloat( "delay" ), this );
- }
- // sounds have a habit of stuttering when portals close, so make them unoccluded
- refSound.parms.soundShaderFlags |= SSF_NO_OCCLUSION;
- companionDoor = NULL;
- enabled = true;
- blocked = false;
- }
- /*
- ================
- idDoor::Think
- ================
- */
- void idDoor::Think( void ) {
- idVec3 masterOrigin;
- idMat3 masterAxis;
- idMover_Binary::Think();
- if ( thinkFlags & TH_PHYSICS ) {
- // update trigger position
- if ( GetMasterPosition( masterOrigin, masterAxis ) ) {
- if ( trigger ) {
- trigger->Link( gameLocal.clip, this, 0, masterOrigin + localTriggerOrigin * masterAxis, localTriggerAxis * masterAxis );
- }
- if ( sndTrigger ) {
- sndTrigger->Link( gameLocal.clip, this, 0, masterOrigin + localTriggerOrigin * masterAxis, localTriggerAxis * masterAxis );
- }
- }
- }
- }
- /*
- ================
- idDoor::PreBind
- ================
- */
- void idDoor::PreBind( void ) {
- idMover_Binary::PreBind();
- }
- /*
- ================
- idDoor::PostBind
- ================
- */
- void idDoor::PostBind( void ) {
- idMover_Binary::PostBind();
- GetLocalTriggerPosition( trigger ? trigger : sndTrigger );
- }
- /*
- ================
- idDoor::SetAASAreaState
- ================
- */
- void idDoor::SetAASAreaState( bool closed ) {
- aas_area_closed = closed;
- gameLocal.SetAASAreaState( physicsObj.GetAbsBounds(), AREACONTENTS_CLUSTERPORTAL|AREACONTENTS_OBSTACLE, closed );
- }
- /*
- ================
- idDoor::Hide
- ================
- */
- void idDoor::Hide( void ) {
- idMover_Binary *slave;
- idMover_Binary *master;
- idDoor *slaveDoor;
- idDoor *companion;
- master = GetMoveMaster();
- if ( this != master ) {
- master->Hide();
- } else {
- for ( slave = this; slave != NULL; slave = slave->GetActivateChain() ) {
- if ( slave->IsType( idDoor::Type ) ) {
- slaveDoor = static_cast<idDoor *>( slave );
- companion = slaveDoor->companionDoor;
- if ( companion && ( companion != master ) && ( companion->GetMoveMaster() != master ) ) {
- companion->Hide();
- }
- if ( slaveDoor->trigger ) {
- slaveDoor->trigger->Disable();
- }
- if ( slaveDoor->sndTrigger ) {
- slaveDoor->sndTrigger->Disable();
- }
- if ( slaveDoor->areaPortal ) {
- slaveDoor->SetPortalState( true );
- }
- slaveDoor->SetAASAreaState( false );
- }
- slave->GetPhysics()->GetClipModel()->Disable();
- slave->idMover_Binary::Hide();
- }
- }
- }
- /*
- ================
- idDoor::Show
- ================
- */
- void idDoor::Show( void ) {
- idMover_Binary *slave;
- idMover_Binary *master;
- idDoor *slaveDoor;
- idDoor *companion;
- master = GetMoveMaster();
- if ( this != master ) {
- master->Show();
- } else {
- for ( slave = this; slave != NULL; slave = slave->GetActivateChain() ) {
- if ( slave->IsType( idDoor::Type ) ) {
- slaveDoor = static_cast<idDoor *>( slave );
- companion = slaveDoor->companionDoor;
- if ( companion && ( companion != master ) && ( companion->GetMoveMaster() != master ) ) {
- companion->Show();
- }
- if ( slaveDoor->trigger ) {
- slaveDoor->trigger->Enable();
- }
- if ( slaveDoor->sndTrigger ) {
- slaveDoor->sndTrigger->Enable();
- }
- if ( slaveDoor->areaPortal && ( slaveDoor->moverState == MOVER_POS1 ) ) {
- slaveDoor->SetPortalState( false );
- }
- slaveDoor->SetAASAreaState( IsLocked() || IsNoTouch() );
- }
- slave->GetPhysics()->GetClipModel()->Enable();
- slave->idMover_Binary::Show();
- }
- }
- }
- /*
- ================
- idDoor::GetLocalTriggerPosition
- ================
- */
- void idDoor::GetLocalTriggerPosition( const idClipModel *trigger ) {
- idVec3 origin;
- idMat3 axis;
- if ( !trigger ) {
- return;
- }
- GetMasterPosition( origin, axis );
- localTriggerOrigin = ( trigger->GetOrigin() - origin ) * axis.Transpose();
- localTriggerAxis = trigger->GetAxis() * axis.Transpose();
- }
- /*
- ================
- idDoor::Use
- ================
- */
- void idDoor::Use( idEntity *other, idEntity *activator ) {
- if ( gameLocal.RequirementMet( activator, requires, removeItem ) ) {
- if ( syncLock.Length() ) {
- idEntity *sync = gameLocal.FindEntity( syncLock );
- if ( sync && sync->IsType( idDoor::Type ) ) {
- if ( static_cast<idDoor *>( sync )->IsOpen() ) {
- return;
- }
- }
- }
- ActivateTargets( activator );
- Use_BinaryMover( activator );
- }
- }
- /*
- ================
- idDoor::Open
- ================
- */
- void idDoor::Open( void ) {
- GotoPosition2();
- }
- /*
- ================
- idDoor::Close
- ================
- */
- void idDoor::Close( void ) {
- GotoPosition1();
- }
- /*
- ================
- idDoor::Lock
- ================
- */
- void idDoor::Lock( int f ) {
- idMover_Binary *other;
- // lock all the doors on the team
- for( other = moveMaster; other != NULL; other = other->GetActivateChain() ) {
- if ( other->IsType( idDoor::Type ) ) {
- idDoor *door = static_cast<idDoor *>( other );
- if ( other == moveMaster ) {
- if ( door->sndTrigger == NULL ) {
- // in this case the sound trigger never got spawned
- const char *sndtemp = door->spawnArgs.GetString( "snd_locked" );
- if ( sndtemp && *sndtemp ) {
- door->PostEventMS( &EV_Door_SpawnSoundTrigger, 0 );
- }
- }
- if ( !f && ( door->spawnArgs.GetInt( "locked" ) != 0 ) ) {
- door->StartSound( "snd_unlocked", SND_CHANNEL_ANY, 0, false, NULL );
- }
- }
- door->spawnArgs.SetInt( "locked", f );
- if ( ( f == 0 ) || ( !IsHidden() && ( door->moverState == MOVER_POS1 ) ) ) {
- door->SetAASAreaState( f != 0 );
- }
- }
- }
- if ( f ) {
- Close();
- }
- }
- /*
- ================
- idDoor::IsLocked
- ================
- */
- int idDoor::IsLocked( void ) {
- return spawnArgs.GetInt( "locked" );
- }
- /*
- ================
- idDoor::IsOpen
- ================
- */
- bool idDoor::IsOpen( void ) {
- return ( moverState != MOVER_POS1 );
- }
- /*
- ================
- idDoor::IsNoTouch
- ================
- */
- bool idDoor::IsNoTouch( void ) {
- return noTouch;
- }
- /*
- ======================
- idDoor::CalcTriggerBounds
- Calcs bounds for a trigger.
- ======================
- */
- void idDoor::CalcTriggerBounds( float size, idBounds &bounds ) {
- idMover_Binary *other;
- int i;
- int best;
- // find the bounds of everything on the team
- bounds = GetPhysics()->GetAbsBounds();
-
- fl.takedamage = true;
- for( other = activateChain; other != NULL; other = other->GetActivateChain() ) {
- if ( other->IsType( idDoor::Type ) ) {
- // find the bounds of everything on the team
- bounds.AddBounds( other->GetPhysics()->GetAbsBounds() );
- // set all of the slaves as shootable
- other->fl.takedamage = true;
- }
- }
- // find the thinnest axis, which will be the one we expand
- best = 0;
- for ( i = 1 ; i < 3 ; i++ ) {
- if ( bounds[1][ i ] - bounds[0][ i ] < bounds[1][ best ] - bounds[0][ best ] ) {
- best = i;
- }
- }
- normalAxisIndex = best;
- bounds[0][ best ] -= size;
- bounds[1][ best ] += size;
- bounds[0] -= GetPhysics()->GetOrigin();
- bounds[1] -= GetPhysics()->GetOrigin();
- }
- /*
- ======================
- idDoor::Event_StartOpen
- if "start_open", reverse position 1 and 2
- ======================
- */
- void idDoor::Event_StartOpen( void ) {
- float time;
- float speed;
- // if "start_open", reverse position 1 and 2
- pos1 = pos2;
- pos2 = GetPhysics()->GetOrigin();
- spawnArgs.GetFloat( "speed", "400", speed );
- if ( spawnArgs.GetFloat( "time", "1", time ) ) {
- InitTime( pos1, pos2, time, 0, 0 );
- } else {
- InitSpeed( pos1, pos2, speed, 0, 0 );
- }
- }
- /*
- ======================
- idDoor::Event_SpawnDoorTrigger
- All of the parts of a door have been spawned, so create
- a trigger that encloses all of them.
- ======================
- */
- void idDoor::Event_SpawnDoorTrigger( void ) {
- idBounds bounds;
- idMover_Binary *other;
- bool toggle;
- if ( trigger ) {
- // already have a trigger, so don't spawn a new one.
- return;
- }
- // check if any of the doors are marked as toggled
- toggle = false;
- for( other = moveMaster; other != NULL; other = other->GetActivateChain() ) {
- if ( other->IsType( idDoor::Type ) && other->spawnArgs.GetBool( "toggle" ) ) {
- toggle = true;
- break;
- }
- }
- if ( toggle ) {
- // mark them all as toggled
- for( other = moveMaster; other != NULL; other = other->GetActivateChain() ) {
- if ( other->IsType( idDoor::Type ) ) {
- other->spawnArgs.Set( "toggle", "1" );
- }
- }
- // don't spawn trigger
- return;
- }
- const char *sndtemp = spawnArgs.GetString( "snd_locked" );
- if ( spawnArgs.GetInt( "locked" ) && sndtemp && *sndtemp ) {
- PostEventMS( &EV_Door_SpawnSoundTrigger, 0 );
- }
- CalcTriggerBounds( triggersize, bounds );
- // create a trigger clip model
- trigger = new idClipModel( idTraceModel( bounds ) );
- trigger->Link( gameLocal.clip, this, 255, GetPhysics()->GetOrigin(), mat3_identity );
- trigger->SetContents( CONTENTS_TRIGGER );
- GetLocalTriggerPosition( trigger );
- MatchActivateTeam( moverState, gameLocal.time );
- }
- /*
- ======================
- idDoor::Event_SpawnSoundTrigger
- Spawn a sound trigger to activate locked sound if it exists.
- ======================
- */
- void idDoor::Event_SpawnSoundTrigger( void ) {
- idBounds bounds;
- if ( sndTrigger ) {
- return;
- }
- CalcTriggerBounds( triggersize * 0.5f, bounds );
- // create a trigger clip model
- sndTrigger = new idClipModel( idTraceModel( bounds ) );
- sndTrigger->Link( gameLocal.clip, this, 254, GetPhysics()->GetOrigin(), mat3_identity );
- sndTrigger->SetContents( CONTENTS_TRIGGER );
- GetLocalTriggerPosition( sndTrigger );
- }
- /*
- ================
- idDoor::Event_Reached_BinaryMover
- ================
- */
- void idDoor::Event_Reached_BinaryMover( void ) {
- if ( moverState == MOVER_2TO1 ) {
- SetBlocked( false );
- const idKeyValue *kv = spawnArgs.MatchPrefix( "triggerClosed" );
- while( kv ) {
- idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
- if ( ent ) {
- ent->PostEventMS( &EV_Activate, 0, moveMaster->GetActivator() );
- }
- kv = spawnArgs.MatchPrefix( "triggerClosed", kv );
- }
- } else if ( moverState == MOVER_1TO2 ) {
- const idKeyValue *kv = spawnArgs.MatchPrefix( "triggerOpened" );
- while( kv ) {
- idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
- if ( ent ) {
- ent->PostEventMS( &EV_Activate, 0, moveMaster->GetActivator() );
- }
- kv = spawnArgs.MatchPrefix( "triggerOpened", kv );
- }
- }
- idMover_Binary::Event_Reached_BinaryMover();
- }
- /*
- ================
- idDoor::Blocked_Door
- ================
- */
- void idDoor::Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity ) {
- SetBlocked( true );
- if ( crusher ) {
- return; // crushers don't reverse
- }
- // reverse direction
- Use_BinaryMover( moveMaster->GetActivator() );
- if ( companionDoor ) {
- companionDoor->ProcessEvent( &EV_TeamBlocked, blockedEntity, blockingEntity );
- }
- }
- /*
- ===============
- idDoor::SetCompanion
- ===============
- */
- void idDoor::SetCompanion( idDoor *door ) {
- companionDoor = door;
- }
- /*
- ===============
- idDoor::Event_PartBlocked
- ===============
- */
- void idDoor::Event_PartBlocked( idEntity *blockingEntity ) {
- if ( damage > 0.0f ) {
- blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
- }
- }
- /*
- ================
- idDoor::Event_Touch
- ================
- */
- void idDoor::Event_Touch( idEntity *other, trace_t *trace ) {
- idVec3 contact, translate;
- idVec3 planeaxis1, planeaxis2, normal;
- idBounds bounds;
- if ( !enabled ) {
- return;
- }
- if ( trigger && trace->c.id == trigger->GetId() ) {
- if ( !IsNoTouch() && !IsLocked() && GetMoverState() != MOVER_1TO2 ) {
- Use( this, other );
- }
- } else if ( sndTrigger && trace->c.id == sndTrigger->GetId() ) {
- if ( other && other->IsType( idPlayer::Type ) && IsLocked() && gameLocal.time > nextSndTriggerTime ) {
- StartSound( "snd_locked", SND_CHANNEL_ANY, 0, false, NULL );
- nextSndTriggerTime = gameLocal.time + 10000;
- }
- }
- }
- /*
- ================
- idDoor::Event_SpectatorTouch
- ================
- */
- void idDoor::Event_SpectatorTouch( idEntity *other, trace_t *trace ) {
- idVec3 contact, translate, normal;
- idBounds bounds;
- idPlayer *p;
- assert( other && other->IsType( idPlayer::Type ) && static_cast< idPlayer * >( other )->spectating );
- p = static_cast< idPlayer * >( other );
- // avoid flicker when stopping right at clip box boundaries
- if ( p->lastSpectateTeleport > gameLocal.time - 1000 ) {
- return;
- }
- if ( trigger && !IsOpen() ) {
- // teleport to the other side, center to the middle of the trigger brush
- bounds = trigger->GetAbsBounds();
- contact = trace->endpos - bounds.GetCenter();
- translate = bounds.GetCenter();
- normal.Zero();
- normal[ normalAxisIndex ] = 1.0f;
- if ( normal * contact > 0 ) {
- translate[ normalAxisIndex ] += ( bounds[ 0 ][ normalAxisIndex ] - translate[ normalAxisIndex ] ) * 0.5f;
- } else {
- translate[ normalAxisIndex ] += ( bounds[ 1 ][ normalAxisIndex ] - translate[ normalAxisIndex ] ) * 0.5f;
- }
- p->SetOrigin( translate );
- p->lastSpectateTeleport = gameLocal.time;
- }
- }
- /*
- ================
- idDoor::Event_Activate
- ================
- */
- void idDoor::Event_Activate( idEntity *activator ) {
- int old_lock;
- if ( spawnArgs.GetInt( "locked" ) ) {
- if ( !trigger ) {
- PostEventMS( &EV_Door_SpawnDoorTrigger, 0 );
- }
- if ( buddyStr.Length() ) {
- idEntity *buddy = gameLocal.FindEntity( buddyStr );
- if ( buddy ) {
- buddy->SetShaderParm( SHADERPARM_MODE, 1 );
- buddy->UpdateVisuals();
- }
- }
- old_lock = spawnArgs.GetInt( "locked" );
- Lock( 0 );
- if ( old_lock == 2 ) {
- return;
- }
- }
- if ( syncLock.Length() ) {
- idEntity *sync = gameLocal.FindEntity( syncLock );
- if ( sync && sync->IsType( idDoor::Type ) ) {
- if ( static_cast<idDoor *>( sync )->IsOpen() ) {
- return;
- }
- }
- }
- ActivateTargets( activator );
- renderEntity.shaderParms[ SHADERPARM_MODE ] = 1;
- UpdateVisuals();
- Use_BinaryMover( activator );
- }
- /*
- ================
- idDoor::Event_Open
- ================
- */
- void idDoor::Event_Open( void ) {
- Open();
- }
- /*
- ================
- idDoor::Event_Close
- ================
- */
- void idDoor::Event_Close( void ) {
- Close();
- }
- /*
- ================
- idDoor::Event_Lock
- ================
- */
- void idDoor::Event_Lock( int f ) {
- Lock( f );
- }
- /*
- ================
- idDoor::Event_IsOpen
- ================
- */
- void idDoor::Event_IsOpen( void ) {
- bool state;
- state = IsOpen();
- idThread::ReturnFloat( state );
- }
- /*
- ================
- idDoor::Event_Locked
- ================
- */
- void idDoor::Event_Locked( void ) {
- idThread::ReturnFloat( spawnArgs.GetInt("locked") );
- }
- /*
- ================
- idDoor::Event_OpenPortal
- Sets the portal associtated with this door to be open
- ================
- */
- void idDoor::Event_OpenPortal( void ) {
- idMover_Binary *slave;
- idDoor *slaveDoor;
- for ( slave = this; slave != NULL; slave = slave->GetActivateChain() ) {
- if ( slave->IsType( idDoor::Type ) ) {
- slaveDoor = static_cast<idDoor *>( slave );
- if ( slaveDoor->areaPortal ) {
- slaveDoor->SetPortalState( true );
- }
- slaveDoor->SetAASAreaState( false );
- }
- }
- }
- /*
- ================
- idDoor::Event_ClosePortal
- Sets the portal associtated with this door to be closed
- ================
- */
- void idDoor::Event_ClosePortal( void ) {
- idMover_Binary *slave;
- idDoor *slaveDoor;
- for ( slave = this; slave != NULL; slave = slave->GetActivateChain() ) {
- if ( !slave->IsHidden() ) {
- if ( slave->IsType( idDoor::Type ) ) {
- slaveDoor = static_cast<idDoor *>( slave );
- if ( slaveDoor->areaPortal ) {
- slaveDoor->SetPortalState( false );
- }
- slaveDoor->SetAASAreaState( IsLocked() || IsNoTouch() );
- }
- }
- }
- }
- /*
- ===============================================================================
- idPlat
- ===============================================================================
- */
- CLASS_DECLARATION( idMover_Binary, idPlat )
- EVENT( EV_Touch, idPlat::Event_Touch )
- EVENT( EV_TeamBlocked, idPlat::Event_TeamBlocked )
- EVENT( EV_PartBlocked, idPlat::Event_PartBlocked )
- END_CLASS
- /*
- ===============
- idPlat::idPlat
- ===============
- */
- idPlat::idPlat( void ) {
- trigger = NULL;
- localTriggerOrigin.Zero();
- localTriggerAxis.Identity();
- }
- /*
- ===============
- idPlat::~idPlat
- ===============
- */
- idPlat::~idPlat( void ) {
- if ( trigger ) {
- delete trigger;
- }
- }
- /*
- ===============
- idPlat::Save
- ===============
- */
- void idPlat::Save( idSaveGame *savefile ) const {
- savefile->WriteClipModel( trigger );
- savefile->WriteVec3( localTriggerOrigin );
- savefile->WriteMat3( localTriggerAxis );
- }
- /*
- ===============
- idPlat::Restore
- ===============
- */
- void idPlat::Restore( idRestoreGame *savefile ) {
- savefile->ReadClipModel( trigger );
- savefile->ReadVec3( localTriggerOrigin );
- savefile->ReadMat3( localTriggerAxis );
- }
- /*
- ===============
- idPlat::Spawn
- ===============
- */
- void idPlat::Spawn( void ) {
- float lip;
- float height;
- float time;
- float speed;
- float accel;
- float decel;
- bool noTouch;
- spawnArgs.GetFloat( "speed", "100", speed );
- spawnArgs.GetFloat( "damage", "0", damage );
- spawnArgs.GetFloat( "wait", "1", wait );
- spawnArgs.GetFloat( "lip", "8", lip );
- spawnArgs.GetFloat( "accel_time", "0.25", accel );
- spawnArgs.GetFloat( "decel_time", "0.25", decel );
- // create second position
- if ( !spawnArgs.GetFloat( "height", "0", height ) ) {
- height = ( GetPhysics()->GetBounds()[1][2] - GetPhysics()->GetBounds()[0][2] ) - lip;
- }
- spawnArgs.GetBool( "no_touch", "0", noTouch );
- // pos1 is the rest (bottom) position, pos2 is the top
- pos2 = GetPhysics()->GetOrigin();
- pos1 = pos2;
- pos1[2] -= height;
- if ( spawnArgs.GetFloat( "time", "1", time ) ) {
- InitTime( pos1, pos2, time, accel, decel );
- } else {
- InitSpeed( pos1, pos2, speed, accel, decel );
- }
- SetMoverState( MOVER_POS1, gameLocal.time );
- UpdateVisuals();
- // spawn the trigger if one hasn't been custom made
- if ( !noTouch ) {
- // spawn trigger
- SpawnPlatTrigger( pos1 );
- }
- }
- /*
- ================
- idPlat::Think
- ================
- */
- void idPlat::Think( void ) {
- idVec3 masterOrigin;
- idMat3 masterAxis;
- idMover_Binary::Think();
- if ( thinkFlags & TH_PHYSICS ) {
- // update trigger position
- if ( GetMasterPosition( masterOrigin, masterAxis ) ) {
- if ( trigger ) {
- trigger->Link( gameLocal.clip, this, 0, masterOrigin + localTriggerOrigin * masterAxis, localTriggerAxis * masterAxis );
- }
- }
- }
- }
- /*
- ================
- idPlat::PreBind
- ================
- */
- void idPlat::PreBind( void ) {
- idMover_Binary::PreBind();
- }
- /*
- ================
- idPlat::PostBind
- ================
- */
- void idPlat::PostBind( void ) {
- idMover_Binary::PostBind();
- GetLocalTriggerPosition( trigger );
- }
- /*
- ================
- idPlat::GetLocalTriggerPosition
- ================
- */
- void idPlat::GetLocalTriggerPosition( const idClipModel *trigger ) {
- idVec3 origin;
- idMat3 axis;
- if ( !trigger ) {
- return;
- }
- GetMasterPosition( origin, axis );
- localTriggerOrigin = ( trigger->GetOrigin() - origin ) * axis.Transpose();
- localTriggerAxis = trigger->GetAxis() * axis.Transpose();
- }
- /*
- ==============
- idPlat::SpawnPlatTrigger
- ===============
- */
- void idPlat::SpawnPlatTrigger( idVec3 &pos ) {
- idBounds bounds;
- idVec3 tmin;
- idVec3 tmax;
- // the middle trigger will be a thin trigger just
- // above the starting position
- bounds = GetPhysics()->GetBounds();
- tmin[0] = bounds[0][0] + 33;
- tmin[1] = bounds[0][1] + 33;
- tmin[2] = bounds[0][2];
- tmax[0] = bounds[1][0] - 33;
- tmax[1] = bounds[1][1] - 33;
- tmax[2] = bounds[1][2] + 8;
- if ( tmax[0] <= tmin[0] ) {
- tmin[0] = ( bounds[0][0] + bounds[1][0] ) * 0.5f;
- tmax[0] = tmin[0] + 1;
- }
- if ( tmax[1] <= tmin[1] ) {
- tmin[1] = ( bounds[0][1] + bounds[1][1] ) * 0.5f;
- tmax[1] = tmin[1] + 1;
- }
-
- trigger = new idClipModel( idTraceModel( idBounds( tmin, tmax ) ) );
- trigger->Link( gameLocal.clip, this, 255, GetPhysics()->GetOrigin(), mat3_identity );
- trigger->SetContents( CONTENTS_TRIGGER );
- }
- /*
- ==============
- idPlat::Event_Touch
- ===============
- */
- void idPlat::Event_Touch( idEntity *other, trace_t *trace ) {
- if ( !other->IsType( idPlayer::Type ) ) {
- return;
- }
- if ( ( GetMoverState() == MOVER_POS1 ) && trigger && ( trace->c.id == trigger->GetId() ) && ( other->health > 0 ) ) {
- Use_BinaryMover( other );
- }
- }
- /*
- ================
- idPlat::Event_TeamBlocked
- ================
- */
- void idPlat::Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity ) {
- // reverse direction
- Use_BinaryMover( activatedBy.GetEntity() );
- }
- /*
- ===============
- idPlat::Event_PartBlocked
- ===============
- */
- void idPlat::Event_PartBlocked( idEntity *blockingEntity ) {
- if ( damage > 0.0f ) {
- blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
- }
- }
- /*
- ===============================================================================
- idMover_Periodic
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idMover_Periodic )
- EVENT( EV_TeamBlocked, idMover_Periodic::Event_TeamBlocked )
- EVENT( EV_PartBlocked, idMover_Periodic::Event_PartBlocked )
- END_CLASS
- /*
- ===============
- idMover_Periodic::idMover_Periodic
- ===============
- */
- idMover_Periodic::idMover_Periodic( void ) {
- damage = 0.0f;
- fl.neverDormant = false;
- }
- /*
- ===============
- idMover_Periodic::Spawn
- ===============
- */
- void idMover_Periodic::Spawn( void ) {
- spawnArgs.GetFloat( "damage", "0", damage );
- if ( !spawnArgs.GetBool( "solid", "1" ) ) {
- GetPhysics()->SetContents( 0 );
- }
- }
- /*
- ===============
- idMover_Periodic::Save
- ===============
- */
- void idMover_Periodic::Save( idSaveGame *savefile ) const {
- savefile->WriteFloat( damage );
- savefile->WriteStaticObject( physicsObj );
- }
- /*
- ===============
- idMover_Periodic::Restore
- ===============
- */
- void idMover_Periodic::Restore( idRestoreGame *savefile ) {
- savefile->ReadFloat( damage );
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- }
- /*
- ================
- idMover_Periodic::Think
- ================
- */
- void idMover_Periodic::Think( void ) {
- // if we are completely closed off from the player, don't do anything at all
- if ( CheckDormant() ) {
- return;
- }
- RunPhysics();
- Present();
- }
- /*
- ===============
- idMover_Periodic::Event_TeamBlocked
- ===============
- */
- void idMover_Periodic::Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity ) {
- }
- /*
- ===============
- idMover_Periodic::Event_PartBlocked
- ===============
- */
- void idMover_Periodic::Event_PartBlocked( idEntity *blockingEntity ) {
- if ( damage > 0.0f ) {
- blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
- }
- }
- /*
- ================
- idMover_Periodic::WriteToSnapshot
- ================
- */
- void idMover_Periodic::WriteToSnapshot( idBitMsgDelta &msg ) const {
- physicsObj.WriteToSnapshot( msg );
- WriteBindToSnapshot( msg );
- }
- /*
- ================
- idMover_Periodic::ReadFromSnapshot
- ================
- */
- void idMover_Periodic::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- physicsObj.ReadFromSnapshot( msg );
- ReadBindFromSnapshot( msg );
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- /*
- ===============================================================================
- idRotater
- ===============================================================================
- */
- CLASS_DECLARATION( idMover_Periodic, idRotater )
- EVENT( EV_Activate, idRotater::Event_Activate )
- END_CLASS
- /*
- ===============
- idRotater::idRotater
- ===============
- */
- idRotater::idRotater( void ) {
- activatedBy = this;
- }
- /*
- ===============
- idRotater::Spawn
- ===============
- */
- void idRotater::Spawn( void ) {
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, gameLocal.time, 0, GetPhysics()->GetOrigin(), vec3_origin, vec3_origin );
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, GetPhysics()->GetAxis().ToAngles(), ang_zero, ang_zero );
- SetPhysics( &physicsObj );
- if ( spawnArgs.GetBool( "start_on" ) ) {
- ProcessEvent( &EV_Activate, this );
- }
- }
- /*
- ===============
- idRotater::Save
- ===============
- */
- void idRotater::Save( idSaveGame *savefile ) const {
- activatedBy.Save( savefile );
- }
- /*
- ===============
- idRotater::Restore
- ===============
- */
- void idRotater::Restore( idRestoreGame *savefile ) {
- activatedBy.Restore( savefile );
- }
- /*
- ===============
- idRotater::Event_Activate
- ===============
- */
- void idRotater::Event_Activate( idEntity *activator ) {
- float speed;
- bool x_axis;
- bool y_axis;
- idAngles delta;
- activatedBy = activator;
- delta.Zero();
- if ( !spawnArgs.GetBool( "rotate" ) ) {
- spawnArgs.Set( "rotate", "1" );
- spawnArgs.GetFloat( "speed", "100", speed );
- spawnArgs.GetBool( "x_axis", "0", x_axis );
- spawnArgs.GetBool( "y_axis", "0", y_axis );
-
- // set the axis of rotation
- if ( x_axis ) {
- delta[2] = speed;
- } else if ( y_axis ) {
- delta[0] = speed;
- } else {
- delta[1] = speed;
- }
- } else {
- spawnArgs.Set( "rotate", "0" );
- }
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, physicsObj.GetAxis().ToAngles(), delta, ang_zero );
- }
- /*
- ===============================================================================
- idBobber
- ===============================================================================
- */
- CLASS_DECLARATION( idMover_Periodic, idBobber )
- END_CLASS
- /*
- ===============
- idBobber::idBobber
- ===============
- */
- idBobber::idBobber( void ) {
- }
- /*
- ===============
- idBobber::Spawn
- ===============
- */
- void idBobber::Spawn( void ) {
- float speed;
- float height;
- float phase;
- bool x_axis;
- bool y_axis;
- idVec3 delta;
- spawnArgs.GetFloat( "speed", "4", speed );
- spawnArgs.GetFloat( "height", "32", height );
- spawnArgs.GetFloat( "phase", "0", phase );
- spawnArgs.GetBool( "x_axis", "0", x_axis );
- spawnArgs.GetBool( "y_axis", "0", y_axis );
- // set the axis of bobbing
- delta = vec3_origin;
- if ( x_axis ) {
- delta[ 0 ] = height;
- } else if ( y_axis ) {
- delta[ 1 ] = height;
- } else {
- delta[ 2 ] = height;
- }
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( extrapolation_t(EXTRAPOLATION_DECELSINE|EXTRAPOLATION_NOSTOP), phase * 1000, speed * 500, GetPhysics()->GetOrigin(), delta * 2.0f, vec3_origin );
- SetPhysics( &physicsObj );
- }
- /*
- ===============================================================================
- idPendulum
- ===============================================================================
- */
- CLASS_DECLARATION( idMover_Periodic, idPendulum )
- END_CLASS
- /*
- ===============
- idPendulum::idPendulum
- ===============
- */
- idPendulum::idPendulum( void ) {
- }
- /*
- ===============
- idPendulum::Spawn
- ===============
- */
- void idPendulum::Spawn( void ) {
- float speed;
- float freq;
- float length;
- float phase;
- spawnArgs.GetFloat( "speed", "30", speed );
- spawnArgs.GetFloat( "phase", "0", phase );
- if ( spawnArgs.GetFloat( "freq", "", freq ) ) {
- if ( freq <= 0.0f ) {
- gameLocal.Error( "Invalid frequency on entity '%s'", GetName() );
- }
- } else {
- // find pendulum length
- length = idMath::Fabs( GetPhysics()->GetBounds()[0][2] );
- if ( length < 8 ) {
- length = 8;
- }
- freq = 1 / ( idMath::TWO_PI ) * idMath::Sqrt( g_gravity.GetFloat() / ( 3 * length ) );
- }
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, GetPhysics()->GetOrigin(), vec3_origin, vec3_origin );
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_DECELSINE|EXTRAPOLATION_NOSTOP), phase * 1000, 500/freq, GetPhysics()->GetAxis().ToAngles(), idAngles( 0, 0, speed * 2.0f ), ang_zero );
- SetPhysics( &physicsObj );
- }
- /*
- ===============================================================================
- idBobber
- ===============================================================================
- */
- CLASS_DECLARATION( idMover_Periodic, idRiser )
- EVENT( EV_Activate, idRiser::Event_Activate )
- END_CLASS
- /*
- ===============
- idRiser::idRiser
- ===============
- */
- idRiser::idRiser( void ) {
- }
- /*
- ===============
- idRiser::Spawn
- ===============
- */
- void idRiser::Spawn( void ) {
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- if ( !spawnArgs.GetBool( "solid", "1" ) ) {
- physicsObj.SetContents( 0 );
- }
- if ( !spawnArgs.GetBool( "nopush" ) ) {
- physicsObj.SetPusher( 0 );
- }
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_NONE, 0, 0, GetPhysics()->GetOrigin(), vec3_origin, vec3_origin );
- SetPhysics( &physicsObj );
- }
- /*
- ================
- idRiser::Event_Activate
- ================
- */
- void idRiser::Event_Activate( idEntity *activator ) {
- if ( !IsHidden() && spawnArgs.GetBool("hide") ) {
- Hide();
- } else {
- Show();
- float time;
- float height;
- idVec3 delta;
- spawnArgs.GetFloat( "time", "4", time );
- spawnArgs.GetFloat( "height", "32", height );
- delta = vec3_origin;
- delta[ 2 ] = height;
- physicsObj.SetLinearExtrapolation( EXTRAPOLATION_LINEAR, gameLocal.time, time * 1000, physicsObj.GetOrigin(), delta, vec3_origin );
- }
- }
|