Actor.cpp 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. /***********************************************************************
  24. idAnimState
  25. ***********************************************************************/
  26. /*
  27. =====================
  28. idAnimState::idAnimState
  29. =====================
  30. */
  31. idAnimState::idAnimState() {
  32. self = NULL;
  33. animator = NULL;
  34. thread = NULL;
  35. idleAnim = true;
  36. disabled = true;
  37. channel = ANIMCHANNEL_ALL;
  38. animBlendFrames = 0;
  39. lastAnimBlendFrames = 0;
  40. }
  41. /*
  42. =====================
  43. idAnimState::~idAnimState
  44. =====================
  45. */
  46. idAnimState::~idAnimState() {
  47. delete thread;
  48. }
  49. /*
  50. =====================
  51. idAnimState::Save
  52. =====================
  53. */
  54. void idAnimState::Save( idSaveGame *savefile ) const {
  55. savefile->WriteObject( self );
  56. // Save the entity owner of the animator
  57. savefile->WriteObject( animator->GetEntity() );
  58. savefile->WriteObject( thread );
  59. savefile->WriteString( state );
  60. savefile->WriteInt( animBlendFrames );
  61. savefile->WriteInt( lastAnimBlendFrames );
  62. savefile->WriteInt( channel );
  63. savefile->WriteBool( idleAnim );
  64. savefile->WriteBool( disabled );
  65. }
  66. /*
  67. =====================
  68. idAnimState::Restore
  69. =====================
  70. */
  71. void idAnimState::Restore( idRestoreGame *savefile ) {
  72. savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
  73. idEntity *animowner;
  74. savefile->ReadObject( reinterpret_cast<idClass *&>( animowner ) );
  75. if ( animowner ) {
  76. animator = animowner->GetAnimator();
  77. }
  78. savefile->ReadObject( reinterpret_cast<idClass *&>( thread ) );
  79. savefile->ReadString( state );
  80. savefile->ReadInt( animBlendFrames );
  81. savefile->ReadInt( lastAnimBlendFrames );
  82. savefile->ReadInt( channel );
  83. savefile->ReadBool( idleAnim );
  84. savefile->ReadBool( disabled );
  85. }
  86. /*
  87. =====================
  88. idAnimState::Init
  89. =====================
  90. */
  91. void idAnimState::Init( idActor *owner, idAnimator *_animator, int animchannel ) {
  92. assert( owner );
  93. assert( _animator );
  94. self = owner;
  95. animator = _animator;
  96. channel = animchannel;
  97. if ( !thread ) {
  98. thread = new idThread();
  99. thread->ManualDelete();
  100. }
  101. thread->EndThread();
  102. thread->ManualControl();
  103. }
  104. /*
  105. =====================
  106. idAnimState::Shutdown
  107. =====================
  108. */
  109. void idAnimState::Shutdown( void ) {
  110. delete thread;
  111. thread = NULL;
  112. }
  113. /*
  114. =====================
  115. idAnimState::SetState
  116. =====================
  117. */
  118. void idAnimState::SetState( const char *statename, int blendFrames ) {
  119. const function_t *func;
  120. func = self->scriptObject.GetFunction( statename );
  121. if ( !func ) {
  122. assert( 0 );
  123. gameLocal.Error( "Can't find function '%s' in object '%s'", statename, self->scriptObject.GetTypeName() );
  124. }
  125. state = statename;
  126. disabled = false;
  127. animBlendFrames = blendFrames;
  128. lastAnimBlendFrames = blendFrames;
  129. thread->CallFunction( self, func, true );
  130. animBlendFrames = blendFrames;
  131. lastAnimBlendFrames = blendFrames;
  132. disabled = false;
  133. idleAnim = false;
  134. if ( ai_debugScript.GetInteger() == self->entityNumber ) {
  135. gameLocal.Printf( "%d: %s: Animstate: %s\n", gameLocal.time, self->name.c_str(), state.c_str() );
  136. }
  137. }
  138. /*
  139. =====================
  140. idAnimState::StopAnim
  141. =====================
  142. */
  143. void idAnimState::StopAnim( int frames ) {
  144. animBlendFrames = 0;
  145. animator->Clear( channel, gameLocal.time, FRAME2MS( frames ) );
  146. }
  147. /*
  148. =====================
  149. idAnimState::PlayAnim
  150. =====================
  151. */
  152. void idAnimState::PlayAnim( int anim ) {
  153. if ( anim ) {
  154. animator->PlayAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
  155. }
  156. animBlendFrames = 0;
  157. }
  158. /*
  159. =====================
  160. idAnimState::CycleAnim
  161. =====================
  162. */
  163. void idAnimState::CycleAnim( int anim ) {
  164. if ( anim ) {
  165. animator->CycleAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
  166. }
  167. animBlendFrames = 0;
  168. }
  169. /*
  170. =====================
  171. idAnimState::BecomeIdle
  172. =====================
  173. */
  174. void idAnimState::BecomeIdle( void ) {
  175. idleAnim = true;
  176. }
  177. /*
  178. =====================
  179. idAnimState::Disabled
  180. =====================
  181. */
  182. bool idAnimState::Disabled( void ) const {
  183. return disabled;
  184. }
  185. /*
  186. =====================
  187. idAnimState::AnimDone
  188. =====================
  189. */
  190. bool idAnimState::AnimDone( int blendFrames ) const {
  191. int animDoneTime;
  192. animDoneTime = animator->CurrentAnim( channel )->GetEndTime();
  193. if ( animDoneTime < 0 ) {
  194. // playing a cycle
  195. return false;
  196. } else if ( animDoneTime - FRAME2MS( blendFrames ) <= gameLocal.time ) {
  197. return true;
  198. } else {
  199. return false;
  200. }
  201. }
  202. /*
  203. =====================
  204. idAnimState::IsIdle
  205. =====================
  206. */
  207. bool idAnimState::IsIdle( void ) const {
  208. return disabled || idleAnim;
  209. }
  210. /*
  211. =====================
  212. idAnimState::GetAnimFlags
  213. =====================
  214. */
  215. animFlags_t idAnimState::GetAnimFlags( void ) const {
  216. animFlags_t flags;
  217. memset( &flags, 0, sizeof( flags ) );
  218. if ( !disabled && !AnimDone( 0 ) ) {
  219. flags = animator->GetAnimFlags( animator->CurrentAnim( channel )->AnimNum() );
  220. }
  221. return flags;
  222. }
  223. /*
  224. =====================
  225. idAnimState::Enable
  226. =====================
  227. */
  228. void idAnimState::Enable( int blendFrames ) {
  229. if ( disabled ) {
  230. disabled = false;
  231. animBlendFrames = blendFrames;
  232. lastAnimBlendFrames = blendFrames;
  233. if ( state.Length() ) {
  234. SetState( state.c_str(), blendFrames );
  235. }
  236. }
  237. }
  238. /*
  239. =====================
  240. idAnimState::Disable
  241. =====================
  242. */
  243. void idAnimState::Disable( void ) {
  244. disabled = true;
  245. idleAnim = false;
  246. }
  247. /*
  248. =====================
  249. idAnimState::UpdateState
  250. =====================
  251. */
  252. bool idAnimState::UpdateState( void ) {
  253. if ( disabled ) {
  254. return false;
  255. }
  256. if ( ai_debugScript.GetInteger() == self->entityNumber ) {
  257. thread->EnableDebugInfo();
  258. } else {
  259. thread->DisableDebugInfo();
  260. }
  261. thread->Execute();
  262. return true;
  263. }
  264. /***********************************************************************
  265. idActor
  266. ***********************************************************************/
  267. const idEventDef AI_EnableEyeFocus( "enableEyeFocus" );
  268. const idEventDef AI_DisableEyeFocus( "disableEyeFocus" );
  269. const idEventDef EV_Footstep( "footstep" );
  270. const idEventDef EV_FootstepLeft( "leftFoot" );
  271. const idEventDef EV_FootstepRight( "rightFoot" );
  272. const idEventDef EV_EnableWalkIK( "EnableWalkIK" );
  273. const idEventDef EV_DisableWalkIK( "DisableWalkIK" );
  274. const idEventDef EV_EnableLegIK( "EnableLegIK", "d" );
  275. const idEventDef EV_DisableLegIK( "DisableLegIK", "d" );
  276. const idEventDef AI_StopAnim( "stopAnim", "dd" );
  277. const idEventDef AI_PlayAnim( "playAnim", "ds", 'd' );
  278. const idEventDef AI_PlayCycle( "playCycle", "ds", 'd' );
  279. const idEventDef AI_IdleAnim( "idleAnim", "ds", 'd' );
  280. const idEventDef AI_SetSyncedAnimWeight( "setSyncedAnimWeight", "ddf" );
  281. const idEventDef AI_SetBlendFrames( "setBlendFrames", "dd" );
  282. const idEventDef AI_GetBlendFrames( "getBlendFrames", "d", 'd' );
  283. const idEventDef AI_AnimState( "animState", "dsd" );
  284. const idEventDef AI_GetAnimState( "getAnimState", "d", 's' );
  285. const idEventDef AI_InAnimState( "inAnimState", "ds", 'd' );
  286. const idEventDef AI_FinishAction( "finishAction", "s" );
  287. const idEventDef AI_AnimDone( "animDone", "dd", 'd' );
  288. const idEventDef AI_OverrideAnim( "overrideAnim", "d" );
  289. const idEventDef AI_EnableAnim( "enableAnim", "dd" );
  290. const idEventDef AI_PreventPain( "preventPain", "f" );
  291. const idEventDef AI_DisablePain( "disablePain" );
  292. const idEventDef AI_EnablePain( "enablePain" );
  293. const idEventDef AI_GetPainAnim( "getPainAnim", NULL, 's' );
  294. const idEventDef AI_SetAnimPrefix( "setAnimPrefix", "s" );
  295. const idEventDef AI_HasAnim( "hasAnim", "ds", 'f' );
  296. const idEventDef AI_CheckAnim( "checkAnim", "ds" );
  297. const idEventDef AI_ChooseAnim( "chooseAnim", "ds", 's' );
  298. const idEventDef AI_AnimLength( "animLength", "ds", 'f' );
  299. const idEventDef AI_AnimDistance( "animDistance", "ds", 'f' );
  300. const idEventDef AI_HasEnemies( "hasEnemies", NULL, 'd' );
  301. const idEventDef AI_NextEnemy( "nextEnemy", "E", 'e' );
  302. const idEventDef AI_ClosestEnemyToPoint( "closestEnemyToPoint", "v", 'e' );
  303. const idEventDef AI_SetNextState( "setNextState", "s" );
  304. const idEventDef AI_SetState( "setState", "s" );
  305. const idEventDef AI_GetState( "getState", NULL, 's' );
  306. const idEventDef AI_GetHead( "getHead", NULL, 'e' );
  307. #ifdef _D3XP
  308. const idEventDef EV_SetDamageGroupScale( "setDamageGroupScale", "sf" );
  309. const idEventDef EV_SetDamageGroupScaleAll( "setDamageGroupScaleAll", "f" );
  310. const idEventDef EV_GetDamageGroupScale( "getDamageGroupScale", "s", 'f' );
  311. const idEventDef EV_SetDamageCap( "setDamageCap", "f" );
  312. const idEventDef EV_SetWaitState( "setWaitState" , "s" );
  313. const idEventDef EV_GetWaitState( "getWaitState", NULL, 's' );
  314. #endif
  315. CLASS_DECLARATION( idAFEntity_Gibbable, idActor )
  316. EVENT( AI_EnableEyeFocus, idActor::Event_EnableEyeFocus )
  317. EVENT( AI_DisableEyeFocus, idActor::Event_DisableEyeFocus )
  318. EVENT( EV_Footstep, idActor::Event_Footstep )
  319. EVENT( EV_FootstepLeft, idActor::Event_Footstep )
  320. EVENT( EV_FootstepRight, idActor::Event_Footstep )
  321. EVENT( EV_EnableWalkIK, idActor::Event_EnableWalkIK )
  322. EVENT( EV_DisableWalkIK, idActor::Event_DisableWalkIK )
  323. EVENT( EV_EnableLegIK, idActor::Event_EnableLegIK )
  324. EVENT( EV_DisableLegIK, idActor::Event_DisableLegIK )
  325. EVENT( AI_PreventPain, idActor::Event_PreventPain )
  326. EVENT( AI_DisablePain, idActor::Event_DisablePain )
  327. EVENT( AI_EnablePain, idActor::Event_EnablePain )
  328. EVENT( AI_GetPainAnim, idActor::Event_GetPainAnim )
  329. EVENT( AI_SetAnimPrefix, idActor::Event_SetAnimPrefix )
  330. EVENT( AI_StopAnim, idActor::Event_StopAnim )
  331. EVENT( AI_PlayAnim, idActor::Event_PlayAnim )
  332. EVENT( AI_PlayCycle, idActor::Event_PlayCycle )
  333. EVENT( AI_IdleAnim, idActor::Event_IdleAnim )
  334. EVENT( AI_SetSyncedAnimWeight, idActor::Event_SetSyncedAnimWeight )
  335. EVENT( AI_SetBlendFrames, idActor::Event_SetBlendFrames )
  336. EVENT( AI_GetBlendFrames, idActor::Event_GetBlendFrames )
  337. EVENT( AI_AnimState, idActor::Event_AnimState )
  338. EVENT( AI_GetAnimState, idActor::Event_GetAnimState )
  339. EVENT( AI_InAnimState, idActor::Event_InAnimState )
  340. EVENT( AI_FinishAction, idActor::Event_FinishAction )
  341. EVENT( AI_AnimDone, idActor::Event_AnimDone )
  342. EVENT( AI_OverrideAnim, idActor::Event_OverrideAnim )
  343. EVENT( AI_EnableAnim, idActor::Event_EnableAnim )
  344. EVENT( AI_HasAnim, idActor::Event_HasAnim )
  345. EVENT( AI_CheckAnim, idActor::Event_CheckAnim )
  346. EVENT( AI_ChooseAnim, idActor::Event_ChooseAnim )
  347. EVENT( AI_AnimLength, idActor::Event_AnimLength )
  348. EVENT( AI_AnimDistance, idActor::Event_AnimDistance )
  349. EVENT( AI_HasEnemies, idActor::Event_HasEnemies )
  350. EVENT( AI_NextEnemy, idActor::Event_NextEnemy )
  351. EVENT( AI_ClosestEnemyToPoint, idActor::Event_ClosestEnemyToPoint )
  352. EVENT( EV_StopSound, idActor::Event_StopSound )
  353. EVENT( AI_SetNextState, idActor::Event_SetNextState )
  354. EVENT( AI_SetState, idActor::Event_SetState )
  355. EVENT( AI_GetState, idActor::Event_GetState )
  356. EVENT( AI_GetHead, idActor::Event_GetHead )
  357. #ifdef _D3XP
  358. EVENT( EV_SetDamageGroupScale, idActor::Event_SetDamageGroupScale )
  359. EVENT( EV_SetDamageGroupScaleAll, idActor::Event_SetDamageGroupScaleAll )
  360. EVENT( EV_GetDamageGroupScale, idActor::Event_GetDamageGroupScale )
  361. EVENT( EV_SetDamageCap, idActor::Event_SetDamageCap )
  362. EVENT( EV_SetWaitState, idActor::Event_SetWaitState )
  363. EVENT( EV_GetWaitState, idActor::Event_GetWaitState )
  364. #endif
  365. END_CLASS
  366. /*
  367. =====================
  368. idActor::idActor
  369. =====================
  370. */
  371. idActor::idActor( void ) {
  372. viewAxis.Identity();
  373. scriptThread = NULL; // initialized by ConstructScriptObject, which is called by idEntity::Spawn
  374. use_combat_bbox = false;
  375. head = NULL;
  376. team = 0;
  377. rank = 0;
  378. fovDot = 0.0f;
  379. eyeOffset.Zero();
  380. pain_debounce_time = 0;
  381. pain_delay = 0;
  382. pain_threshold = 0;
  383. state = NULL;
  384. idealState = NULL;
  385. leftEyeJoint = INVALID_JOINT;
  386. rightEyeJoint = INVALID_JOINT;
  387. soundJoint = INVALID_JOINT;
  388. modelOffset.Zero();
  389. deltaViewAngles.Zero();
  390. painTime = 0;
  391. allowPain = false;
  392. allowEyeFocus = false;
  393. waitState = "";
  394. blink_anim = NULL;
  395. blink_time = 0;
  396. blink_min = 0;
  397. blink_max = 0;
  398. finalBoss = false;
  399. attachments.SetGranularity( 1 );
  400. enemyNode.SetOwner( this );
  401. enemyList.SetOwner( this );
  402. #ifdef _D3XP
  403. damageCap = -1;
  404. #endif
  405. }
  406. /*
  407. =====================
  408. idActor::~idActor
  409. =====================
  410. */
  411. idActor::~idActor( void ) {
  412. int i;
  413. idEntity *ent;
  414. DeconstructScriptObject();
  415. scriptObject.Free();
  416. StopSound( SND_CHANNEL_ANY, false );
  417. delete combatModel;
  418. combatModel = NULL;
  419. if ( head.GetEntity() ) {
  420. head.GetEntity()->ClearBody();
  421. head.GetEntity()->PostEventMS( &EV_Remove, 0 );
  422. }
  423. // remove any attached entities
  424. for( i = 0; i < attachments.Num(); i++ ) {
  425. ent = attachments[ i ].ent.GetEntity();
  426. if ( ent ) {
  427. ent->PostEventMS( &EV_Remove, 0 );
  428. }
  429. }
  430. ShutdownThreads();
  431. }
  432. /*
  433. =====================
  434. idActor::Spawn
  435. =====================
  436. */
  437. void idActor::Spawn( void ) {
  438. idEntity *ent;
  439. idStr jointName;
  440. float fovDegrees;
  441. copyJoints_t copyJoint;
  442. animPrefix = "";
  443. state = NULL;
  444. idealState = NULL;
  445. spawnArgs.GetInt( "rank", "0", rank );
  446. spawnArgs.GetInt( "team", "0", team );
  447. spawnArgs.GetVector( "offsetModel", "0 0 0", modelOffset );
  448. spawnArgs.GetBool( "use_combat_bbox", "0", use_combat_bbox );
  449. viewAxis = GetPhysics()->GetAxis();
  450. spawnArgs.GetFloat( "fov", "90", fovDegrees );
  451. SetFOV( fovDegrees );
  452. pain_debounce_time = 0;
  453. pain_delay = SEC2MS( spawnArgs.GetFloat( "pain_delay" ) );
  454. pain_threshold = spawnArgs.GetInt( "pain_threshold" );
  455. LoadAF();
  456. walkIK.Init( this, IK_ANIM, modelOffset );
  457. // the animation used to be set to the IK_ANIM at this point, but that was fixed, resulting in
  458. // attachments not binding correctly, so we're stuck setting the IK_ANIM before attaching things.
  459. animator.ClearAllAnims( gameLocal.time, 0 );
  460. animator.SetFrame( ANIMCHANNEL_ALL, animator.GetAnim( IK_ANIM ), 0, 0, 0 );
  461. // spawn any attachments we might have
  462. const idKeyValue *kv = spawnArgs.MatchPrefix( "def_attach", NULL );
  463. while ( kv ) {
  464. idDict args;
  465. args.Set( "classname", kv->GetValue().c_str() );
  466. // make items non-touchable so the player can't take them out of the character's hands
  467. args.Set( "no_touch", "1" );
  468. // don't let them drop to the floor
  469. args.Set( "dropToFloor", "0" );
  470. gameLocal.SpawnEntityDef( args, &ent );
  471. if ( !ent ) {
  472. gameLocal.Error( "Couldn't spawn '%s' to attach to entity '%s'", kv->GetValue().c_str(), name.c_str() );
  473. } else {
  474. Attach( ent );
  475. }
  476. kv = spawnArgs.MatchPrefix( "def_attach", kv );
  477. }
  478. SetupDamageGroups();
  479. SetupHead();
  480. // clear the bind anim
  481. animator.ClearAllAnims( gameLocal.time, 0 );
  482. idEntity *headEnt = head.GetEntity();
  483. idAnimator *headAnimator;
  484. if ( headEnt ) {
  485. headAnimator = headEnt->GetAnimator();
  486. } else {
  487. headAnimator = &animator;
  488. }
  489. if ( headEnt ) {
  490. // set up the list of joints to copy to the head
  491. for( kv = spawnArgs.MatchPrefix( "copy_joint", NULL ); kv != NULL; kv = spawnArgs.MatchPrefix( "copy_joint", kv ) ) {
  492. if ( kv->GetValue() == "" ) {
  493. // probably clearing out inherited key, so skip it
  494. continue;
  495. }
  496. jointName = kv->GetKey();
  497. if ( jointName.StripLeadingOnce( "copy_joint_world " ) ) {
  498. copyJoint.mod = JOINTMOD_WORLD_OVERRIDE;
  499. } else {
  500. jointName.StripLeadingOnce( "copy_joint " );
  501. copyJoint.mod = JOINTMOD_LOCAL_OVERRIDE;
  502. }
  503. copyJoint.from = animator.GetJointHandle( jointName );
  504. if ( copyJoint.from == INVALID_JOINT ) {
  505. gameLocal.Warning( "Unknown copy_joint '%s' on entity %s", jointName.c_str(), name.c_str() );
  506. continue;
  507. }
  508. jointName = kv->GetValue();
  509. copyJoint.to = headAnimator->GetJointHandle( jointName );
  510. if ( copyJoint.to == INVALID_JOINT ) {
  511. gameLocal.Warning( "Unknown copy_joint '%s' on head of entity %s", jointName.c_str(), name.c_str() );
  512. continue;
  513. }
  514. copyJoints.Append( copyJoint );
  515. }
  516. }
  517. // set up blinking
  518. blink_anim = headAnimator->GetAnim( "blink" );
  519. blink_time = 0; // it's ok to blink right away
  520. blink_min = SEC2MS( spawnArgs.GetFloat( "blink_min", "0.5" ) );
  521. blink_max = SEC2MS( spawnArgs.GetFloat( "blink_max", "8" ) );
  522. // set up the head anim if necessary
  523. int headAnim = headAnimator->GetAnim( "def_head" );
  524. if ( headAnim ) {
  525. if ( headEnt ) {
  526. headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, 0 );
  527. } else {
  528. headAnimator->CycleAnim( ANIMCHANNEL_HEAD, headAnim, gameLocal.time, 0 );
  529. }
  530. }
  531. if ( spawnArgs.GetString( "sound_bone", "", jointName ) ) {
  532. soundJoint = animator.GetJointHandle( jointName );
  533. if ( soundJoint == INVALID_JOINT ) {
  534. gameLocal.Warning( "idAnimated '%s' at (%s): cannot find joint '%s' for sound playback", name.c_str(), GetPhysics()->GetOrigin().ToString(0), jointName.c_str() );
  535. }
  536. }
  537. finalBoss = spawnArgs.GetBool( "finalBoss" );
  538. //BC 8-24-2015
  539. StartSound( "snd_idle", SND_CHANNEL_HEART, 0, false, NULL );
  540. FinishSetup();
  541. }
  542. /*
  543. ================
  544. idActor::FinishSetup
  545. ================
  546. */
  547. void idActor::FinishSetup( void ) {
  548. const char *scriptObjectName;
  549. // setup script object
  550. if ( spawnArgs.GetString( "scriptobject", NULL, &scriptObjectName ) ) {
  551. if ( !scriptObject.SetType( scriptObjectName ) ) {
  552. gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
  553. }
  554. ConstructScriptObject();
  555. }
  556. SetupBody();
  557. }
  558. /*
  559. ================
  560. idActor::SetupHead
  561. ================
  562. */
  563. void idActor::SetupHead( void ) {
  564. idAFAttachment *headEnt;
  565. idStr jointName;
  566. const char *headModel;
  567. jointHandle_t joint;
  568. jointHandle_t damageJoint;
  569. int i;
  570. const idKeyValue *sndKV;
  571. if ( gameLocal.isClient ) {
  572. return;
  573. }
  574. headModel = spawnArgs.GetString( "def_head", "" );
  575. if ( headModel[ 0 ] ) {
  576. jointName = spawnArgs.GetString( "head_joint" );
  577. joint = animator.GetJointHandle( jointName );
  578. if ( joint == INVALID_JOINT ) {
  579. gameLocal.Error( "Joint '%s' not found for 'head_joint' on '%s'", jointName.c_str(), name.c_str() );
  580. }
  581. // set the damage joint to be part of the head damage group
  582. damageJoint = joint;
  583. for( i = 0; i < damageGroups.Num(); i++ ) {
  584. if ( damageGroups[ i ] == "head" ) {
  585. damageJoint = static_cast<jointHandle_t>( i );
  586. break;
  587. }
  588. }
  589. // copy any sounds in case we have frame commands on the head
  590. idDict args;
  591. sndKV = spawnArgs.MatchPrefix( "snd_", NULL );
  592. while( sndKV ) {
  593. args.Set( sndKV->GetKey(), sndKV->GetValue() );
  594. sndKV = spawnArgs.MatchPrefix( "snd_", sndKV );
  595. }
  596. #ifdef _D3XP
  597. // copy slowmo param to the head
  598. args.SetBool( "slowmo", spawnArgs.GetBool("slowmo", "1") );
  599. #endif
  600. headEnt = static_cast<idAFAttachment *>( gameLocal.SpawnEntityType( idAFAttachment::Type, &args ) );
  601. headEnt->SetName( va( "%s_head", name.c_str() ) );
  602. headEnt->SetBody( this, headModel, damageJoint );
  603. head = headEnt;
  604. #ifdef _D3XP
  605. idStr xSkin;
  606. if ( spawnArgs.GetString( "skin_head_xray", "", xSkin ) ) {
  607. headEnt->xraySkin = declManager->FindSkin( xSkin.c_str() );
  608. headEnt->UpdateModel();
  609. }
  610. #endif
  611. idVec3 origin;
  612. idMat3 axis;
  613. idAttachInfo &attach = attachments.Alloc();
  614. attach.channel = animator.GetChannelForJoint( joint );
  615. animator.GetJointTransform( joint, gameLocal.time, origin, axis );
  616. origin = renderEntity.origin + ( origin + modelOffset ) * renderEntity.axis;
  617. attach.ent = headEnt;
  618. headEnt->SetOrigin( origin );
  619. headEnt->SetAxis( renderEntity.axis );
  620. headEnt->BindToJoint( this, joint, true );
  621. }
  622. }
  623. /*
  624. ================
  625. idActor::CopyJointsFromBodyToHead
  626. ================
  627. */
  628. void idActor::CopyJointsFromBodyToHead( void ) {
  629. idEntity *headEnt = head.GetEntity();
  630. idAnimator *headAnimator;
  631. int i;
  632. idMat3 mat;
  633. idMat3 axis;
  634. idVec3 pos;
  635. if ( !headEnt ) {
  636. return;
  637. }
  638. headAnimator = headEnt->GetAnimator();
  639. // copy the animation from the body to the head
  640. for( i = 0; i < copyJoints.Num(); i++ ) {
  641. if ( copyJoints[ i ].mod == JOINTMOD_WORLD_OVERRIDE ) {
  642. mat = headEnt->GetPhysics()->GetAxis().Transpose();
  643. GetJointWorldTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
  644. pos -= headEnt->GetPhysics()->GetOrigin();
  645. headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos * mat );
  646. headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis * mat );
  647. } else {
  648. animator.GetJointLocalTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
  649. headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos );
  650. headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis );
  651. }
  652. }
  653. }
  654. /*
  655. ================
  656. idActor::Restart
  657. ================
  658. */
  659. void idActor::Restart( void ) {
  660. assert( !head.GetEntity() );
  661. SetupHead();
  662. FinishSetup();
  663. }
  664. /*
  665. ================
  666. idActor::Save
  667. archive object for savegame file
  668. ================
  669. */
  670. void idActor::Save( idSaveGame *savefile ) const {
  671. idActor *ent;
  672. int i;
  673. savefile->WriteInt( team );
  674. savefile->WriteInt( rank );
  675. savefile->WriteMat3( viewAxis );
  676. savefile->WriteInt( enemyList.Num() );
  677. for ( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  678. savefile->WriteObject( ent );
  679. }
  680. savefile->WriteFloat( fovDot );
  681. savefile->WriteVec3( eyeOffset );
  682. savefile->WriteVec3( modelOffset );
  683. savefile->WriteAngles( deltaViewAngles );
  684. savefile->WriteInt( pain_debounce_time );
  685. savefile->WriteInt( pain_delay );
  686. savefile->WriteInt( pain_threshold );
  687. savefile->WriteInt( damageGroups.Num() );
  688. for( i = 0; i < damageGroups.Num(); i++ ) {
  689. savefile->WriteString( damageGroups[ i ] );
  690. }
  691. savefile->WriteInt( damageScale.Num() );
  692. for( i = 0; i < damageScale.Num(); i++ ) {
  693. savefile->WriteFloat( damageScale[ i ] );
  694. }
  695. savefile->WriteBool( use_combat_bbox );
  696. head.Save( savefile );
  697. savefile->WriteInt( copyJoints.Num() );
  698. for( i = 0; i < copyJoints.Num(); i++ ) {
  699. savefile->WriteInt( copyJoints[i].mod );
  700. savefile->WriteJoint( copyJoints[i].from );
  701. savefile->WriteJoint( copyJoints[i].to );
  702. }
  703. savefile->WriteJoint( leftEyeJoint );
  704. savefile->WriteJoint( rightEyeJoint );
  705. savefile->WriteJoint( soundJoint );
  706. walkIK.Save( savefile );
  707. savefile->WriteString( animPrefix );
  708. savefile->WriteString( painAnim );
  709. savefile->WriteInt( blink_anim );
  710. savefile->WriteInt( blink_time );
  711. savefile->WriteInt( blink_min );
  712. savefile->WriteInt( blink_max );
  713. // script variables
  714. savefile->WriteObject( scriptThread );
  715. savefile->WriteString( waitState );
  716. headAnim.Save( savefile );
  717. torsoAnim.Save( savefile );
  718. legsAnim.Save( savefile );
  719. savefile->WriteBool( allowPain );
  720. savefile->WriteBool( allowEyeFocus );
  721. savefile->WriteInt( painTime );
  722. savefile->WriteInt( attachments.Num() );
  723. for ( i = 0; i < attachments.Num(); i++ ) {
  724. attachments[i].ent.Save( savefile );
  725. savefile->WriteInt( attachments[i].channel );
  726. }
  727. savefile->WriteBool( finalBoss );
  728. idToken token;
  729. //FIXME: this is unneccesary
  730. if ( state ) {
  731. idLexer src( state->Name(), idStr::Length( state->Name() ), "idAI::Save" );
  732. src.ReadTokenOnLine( &token );
  733. src.ExpectTokenString( "::" );
  734. src.ReadTokenOnLine( &token );
  735. savefile->WriteString( token );
  736. } else {
  737. savefile->WriteString( "" );
  738. }
  739. if ( idealState ) {
  740. idLexer src( idealState->Name(), idStr::Length( idealState->Name() ), "idAI::Save" );
  741. src.ReadTokenOnLine( &token );
  742. src.ExpectTokenString( "::" );
  743. src.ReadTokenOnLine( &token );
  744. savefile->WriteString( token );
  745. } else {
  746. savefile->WriteString( "" );
  747. }
  748. #ifdef _D3XP
  749. savefile->WriteInt(damageCap);
  750. #endif
  751. }
  752. /*
  753. ================
  754. idActor::Restore
  755. unarchives object from save game file
  756. ================
  757. */
  758. void idActor::Restore( idRestoreGame *savefile ) {
  759. int i, num;
  760. idActor *ent;
  761. savefile->ReadInt( team );
  762. savefile->ReadInt( rank );
  763. savefile->ReadMat3( viewAxis );
  764. savefile->ReadInt( num );
  765. for ( i = 0; i < num; i++ ) {
  766. savefile->ReadObject( reinterpret_cast<idClass *&>( ent ) );
  767. assert( ent );
  768. if ( ent ) {
  769. ent->enemyNode.AddToEnd( enemyList );
  770. }
  771. }
  772. savefile->ReadFloat( fovDot );
  773. savefile->ReadVec3( eyeOffset );
  774. savefile->ReadVec3( modelOffset );
  775. savefile->ReadAngles( deltaViewAngles );
  776. savefile->ReadInt( pain_debounce_time );
  777. savefile->ReadInt( pain_delay );
  778. savefile->ReadInt( pain_threshold );
  779. savefile->ReadInt( num );
  780. damageGroups.SetGranularity( 1 );
  781. damageGroups.SetNum( num );
  782. for( i = 0; i < num; i++ ) {
  783. savefile->ReadString( damageGroups[ i ] );
  784. }
  785. savefile->ReadInt( num );
  786. damageScale.SetNum( num );
  787. for( i = 0; i < num; i++ ) {
  788. savefile->ReadFloat( damageScale[ i ] );
  789. }
  790. savefile->ReadBool( use_combat_bbox );
  791. head.Restore( savefile );
  792. savefile->ReadInt( num );
  793. copyJoints.SetNum( num );
  794. for( i = 0; i < num; i++ ) {
  795. int val;
  796. savefile->ReadInt( val );
  797. copyJoints[i].mod = static_cast<jointModTransform_t>( val );
  798. savefile->ReadJoint( copyJoints[i].from );
  799. savefile->ReadJoint( copyJoints[i].to );
  800. }
  801. savefile->ReadJoint( leftEyeJoint );
  802. savefile->ReadJoint( rightEyeJoint );
  803. savefile->ReadJoint( soundJoint );
  804. walkIK.Restore( savefile );
  805. savefile->ReadString( animPrefix );
  806. savefile->ReadString( painAnim );
  807. savefile->ReadInt( blink_anim );
  808. savefile->ReadInt( blink_time );
  809. savefile->ReadInt( blink_min );
  810. savefile->ReadInt( blink_max );
  811. savefile->ReadObject( reinterpret_cast<idClass *&>( scriptThread ) );
  812. savefile->ReadString( waitState );
  813. headAnim.Restore( savefile );
  814. torsoAnim.Restore( savefile );
  815. legsAnim.Restore( savefile );
  816. savefile->ReadBool( allowPain );
  817. savefile->ReadBool( allowEyeFocus );
  818. savefile->ReadInt( painTime );
  819. savefile->ReadInt( num );
  820. for ( i = 0; i < num; i++ ) {
  821. idAttachInfo &attach = attachments.Alloc();
  822. attach.ent.Restore( savefile );
  823. savefile->ReadInt( attach.channel );
  824. }
  825. savefile->ReadBool( finalBoss );
  826. idStr statename;
  827. savefile->ReadString( statename );
  828. if ( statename.Length() > 0 ) {
  829. state = GetScriptFunction( statename );
  830. }
  831. savefile->ReadString( statename );
  832. if ( statename.Length() > 0 ) {
  833. idealState = GetScriptFunction( statename );
  834. }
  835. #ifdef _D3XP
  836. savefile->ReadInt(damageCap);
  837. #endif
  838. }
  839. /*
  840. ================
  841. idActor::Hide
  842. ================
  843. */
  844. void idActor::Hide( void ) {
  845. idEntity *ent;
  846. idEntity *next;
  847. idAFEntity_Base::Hide();
  848. if ( head.GetEntity() ) {
  849. head.GetEntity()->Hide();
  850. }
  851. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  852. next = ent->GetNextTeamEntity();
  853. if ( ent->GetBindMaster() == this ) {
  854. ent->Hide();
  855. if ( ent->IsType( idLight::Type ) ) {
  856. static_cast<idLight *>( ent )->Off();
  857. }
  858. }
  859. }
  860. UnlinkCombat();
  861. }
  862. /*
  863. ================
  864. idActor::Show
  865. ================
  866. */
  867. void idActor::Show( void ) {
  868. idEntity *ent;
  869. idEntity *next;
  870. idAFEntity_Base::Show();
  871. if ( head.GetEntity() ) {
  872. head.GetEntity()->Show();
  873. }
  874. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  875. next = ent->GetNextTeamEntity();
  876. if ( ent->GetBindMaster() == this ) {
  877. ent->Show();
  878. if ( ent->IsType( idLight::Type ) ) {
  879. #ifdef _D3XP
  880. if(!spawnArgs.GetBool("lights_off", "0")) {
  881. static_cast<idLight *>( ent )->On();
  882. }
  883. #endif
  884. }
  885. }
  886. }
  887. LinkCombat();
  888. }
  889. /*
  890. ==============
  891. idActor::GetDefaultSurfaceType
  892. ==============
  893. */
  894. int idActor::GetDefaultSurfaceType( void ) const {
  895. return SURFTYPE_FLESH;
  896. }
  897. /*
  898. ================
  899. idActor::ProjectOverlay
  900. ================
  901. */
  902. void idActor::ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ) {
  903. idEntity *ent;
  904. idEntity *next;
  905. idEntity::ProjectOverlay( origin, dir, size, material );
  906. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  907. next = ent->GetNextTeamEntity();
  908. if ( ent->GetBindMaster() == this ) {
  909. if ( ent->fl.takedamage && ent->spawnArgs.GetBool( "bleed" ) ) {
  910. ent->ProjectOverlay( origin, dir, size, material );
  911. }
  912. }
  913. }
  914. }
  915. /*
  916. ================
  917. idActor::LoadAF
  918. ================
  919. */
  920. bool idActor::LoadAF( void ) {
  921. idStr fileName;
  922. if ( !spawnArgs.GetString( "ragdoll", "*unknown*", fileName ) || !fileName.Length() ) {
  923. return false;
  924. }
  925. af.SetAnimator( GetAnimator() );
  926. return af.Load( this, fileName );
  927. }
  928. /*
  929. =====================
  930. idActor::SetupBody
  931. =====================
  932. */
  933. void idActor::SetupBody( void ) {
  934. const char *jointname;
  935. animator.ClearAllAnims( gameLocal.time, 0 );
  936. animator.ClearAllJoints();
  937. idEntity *headEnt = head.GetEntity();
  938. if ( headEnt ) {
  939. jointname = spawnArgs.GetString( "bone_leftEye" );
  940. leftEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
  941. jointname = spawnArgs.GetString( "bone_rightEye" );
  942. rightEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
  943. // set up the eye height. check if it's specified in the def.
  944. if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
  945. // if not in the def, then try to base it off the idle animation
  946. int anim = headEnt->GetAnimator()->GetAnim( "idle" );
  947. if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
  948. idVec3 pos;
  949. idMat3 axis;
  950. headEnt->GetAnimator()->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, 0 );
  951. headEnt->GetAnimator()->GetJointTransform( leftEyeJoint, gameLocal.time, pos, axis );
  952. headEnt->GetAnimator()->ClearAllAnims( gameLocal.time, 0 );
  953. headEnt->GetAnimator()->ForceUpdate();
  954. pos += headEnt->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  955. eyeOffset = pos + modelOffset;
  956. } else {
  957. // just base it off the bounding box size
  958. eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
  959. }
  960. }
  961. headAnim.Init( this, headEnt->GetAnimator(), ANIMCHANNEL_ALL );
  962. } else {
  963. jointname = spawnArgs.GetString( "bone_leftEye" );
  964. leftEyeJoint = animator.GetJointHandle( jointname );
  965. jointname = spawnArgs.GetString( "bone_rightEye" );
  966. rightEyeJoint = animator.GetJointHandle( jointname );
  967. // set up the eye height. check if it's specified in the def.
  968. if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
  969. // if not in the def, then try to base it off the idle animation
  970. int anim = animator.GetAnim( "idle" );
  971. if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
  972. idVec3 pos;
  973. idMat3 axis;
  974. animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, 0 );
  975. animator.GetJointTransform( leftEyeJoint, gameLocal.time, pos, axis );
  976. animator.ClearAllAnims( gameLocal.time, 0 );
  977. animator.ForceUpdate();
  978. eyeOffset = pos + modelOffset;
  979. } else {
  980. // just base it off the bounding box size
  981. eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
  982. }
  983. }
  984. headAnim.Init( this, &animator, ANIMCHANNEL_HEAD );
  985. }
  986. waitState = "";
  987. torsoAnim.Init( this, &animator, ANIMCHANNEL_TORSO );
  988. legsAnim.Init( this, &animator, ANIMCHANNEL_LEGS );
  989. }
  990. /*
  991. =====================
  992. idActor::CheckBlink
  993. =====================
  994. */
  995. void idActor::CheckBlink( void ) {
  996. // check if it's time to blink
  997. if ( !blink_anim || ( health <= 0 ) || !allowEyeFocus || ( blink_time > gameLocal.time ) ) {
  998. return;
  999. }
  1000. idEntity *headEnt = head.GetEntity();
  1001. if ( headEnt ) {
  1002. headEnt->GetAnimator()->PlayAnim( ANIMCHANNEL_EYELIDS, blink_anim, gameLocal.time, 1 );
  1003. } else {
  1004. animator.PlayAnim( ANIMCHANNEL_EYELIDS, blink_anim, gameLocal.time, 1 );
  1005. }
  1006. // set the next blink time
  1007. blink_time = gameLocal.time + blink_min + gameLocal.random.RandomFloat() * ( blink_max - blink_min );
  1008. }
  1009. /*
  1010. ================
  1011. idActor::GetPhysicsToVisualTransform
  1012. ================
  1013. */
  1014. bool idActor::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
  1015. if ( af.IsActive() ) {
  1016. af.GetPhysicsToVisualTransform( origin, axis );
  1017. return true;
  1018. }
  1019. origin = modelOffset;
  1020. axis = viewAxis;
  1021. return true;
  1022. }
  1023. /*
  1024. ================
  1025. idActor::GetPhysicsToSoundTransform
  1026. ================
  1027. */
  1028. bool idActor::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  1029. if ( soundJoint != INVALID_JOINT ) {
  1030. animator.GetJointTransform( soundJoint, gameLocal.time, origin, axis );
  1031. origin += modelOffset;
  1032. axis = viewAxis;
  1033. } else {
  1034. origin = GetPhysics()->GetGravityNormal() * -eyeOffset.z;
  1035. axis.Identity();
  1036. }
  1037. return true;
  1038. }
  1039. /***********************************************************************
  1040. script state management
  1041. ***********************************************************************/
  1042. /*
  1043. ================
  1044. idActor::ShutdownThreads
  1045. ================
  1046. */
  1047. void idActor::ShutdownThreads( void ) {
  1048. headAnim.Shutdown();
  1049. torsoAnim.Shutdown();
  1050. legsAnim.Shutdown();
  1051. if ( scriptThread ) {
  1052. scriptThread->EndThread();
  1053. scriptThread->PostEventMS( &EV_Remove, 0 );
  1054. delete scriptThread;
  1055. scriptThread = NULL;
  1056. }
  1057. }
  1058. /*
  1059. ================
  1060. idActor::ShouldConstructScriptObjectAtSpawn
  1061. Called during idEntity::Spawn to see if it should construct the script object or not.
  1062. Overridden by subclasses that need to spawn the script object themselves.
  1063. ================
  1064. */
  1065. bool idActor::ShouldConstructScriptObjectAtSpawn( void ) const {
  1066. return false;
  1067. }
  1068. /*
  1069. ================
  1070. idActor::ConstructScriptObject
  1071. Called during idEntity::Spawn. Calls the constructor on the script object.
  1072. Can be overridden by subclasses when a thread doesn't need to be allocated.
  1073. ================
  1074. */
  1075. idThread *idActor::ConstructScriptObject( void ) {
  1076. const function_t *constructor;
  1077. // make sure we have a scriptObject
  1078. if ( !scriptObject.HasObject() ) {
  1079. gameLocal.Error( "No scriptobject set on '%s'. Check the '%s' entityDef.", name.c_str(), GetEntityDefName() );
  1080. }
  1081. if ( !scriptThread ) {
  1082. // create script thread
  1083. scriptThread = new idThread();
  1084. scriptThread->ManualDelete();
  1085. scriptThread->ManualControl();
  1086. scriptThread->SetThreadName( name.c_str() );
  1087. } else {
  1088. scriptThread->EndThread();
  1089. }
  1090. // call script object's constructor
  1091. constructor = scriptObject.GetConstructor();
  1092. if ( !constructor ) {
  1093. gameLocal.Error( "Missing constructor on '%s' for entity '%s'", scriptObject.GetTypeName(), name.c_str() );
  1094. }
  1095. // init the script object's data
  1096. scriptObject.ClearObject();
  1097. // just set the current function on the script. we'll execute in the subclasses.
  1098. scriptThread->CallFunction( this, constructor, true );
  1099. return scriptThread;
  1100. }
  1101. /*
  1102. =====================
  1103. idActor::GetScriptFunction
  1104. =====================
  1105. */
  1106. const function_t *idActor::GetScriptFunction( const char *funcname ) {
  1107. const function_t *func;
  1108. func = scriptObject.GetFunction( funcname );
  1109. if ( !func ) {
  1110. scriptThread->Error( "Unknown function '%s' in '%s'", funcname, scriptObject.GetTypeName() );
  1111. }
  1112. return func;
  1113. }
  1114. /*
  1115. =====================
  1116. idActor::SetState
  1117. =====================
  1118. */
  1119. void idActor::SetState( const function_t *newState ) {
  1120. if ( !newState ) {
  1121. gameLocal.Error( "idActor::SetState: Null state" );
  1122. }
  1123. if ( ai_debugScript.GetInteger() == entityNumber ) {
  1124. gameLocal.Printf( "%d: %s: State: %s\n", gameLocal.time, name.c_str(), newState->Name() );
  1125. }
  1126. state = newState;
  1127. idealState = state;
  1128. scriptThread->CallFunction( this, state, true );
  1129. }
  1130. /*
  1131. =====================
  1132. idActor::SetState
  1133. =====================
  1134. */
  1135. void idActor::SetState( const char *statename ) {
  1136. const function_t *newState;
  1137. newState = GetScriptFunction( statename );
  1138. SetState( newState );
  1139. }
  1140. /*
  1141. =====================
  1142. idActor::UpdateScript
  1143. =====================
  1144. */
  1145. void idActor::UpdateScript( void ) {
  1146. int i;
  1147. if ( ai_debugScript.GetInteger() == entityNumber ) {
  1148. scriptThread->EnableDebugInfo();
  1149. } else {
  1150. scriptThread->DisableDebugInfo();
  1151. }
  1152. // a series of state changes can happen in a single frame.
  1153. // this loop limits them in case we've entered an infinite loop.
  1154. for( i = 0; i < 20; i++ ) {
  1155. if ( idealState != state ) {
  1156. SetState( idealState );
  1157. }
  1158. // don't call script until it's done waiting
  1159. if ( scriptThread->IsWaiting() ) {
  1160. break;
  1161. }
  1162. scriptThread->Execute();
  1163. if ( idealState == state ) {
  1164. break;
  1165. }
  1166. }
  1167. if ( i == 20 ) {
  1168. scriptThread->Warning( "idActor::UpdateScript: exited loop to prevent lockup" );
  1169. }
  1170. }
  1171. /***********************************************************************
  1172. vision
  1173. ***********************************************************************/
  1174. /*
  1175. =====================
  1176. idActor::setFov
  1177. =====================
  1178. */
  1179. void idActor::SetFOV( float fov ) {
  1180. fovDot = (float)cos( DEG2RAD( fov * 0.5f ) );
  1181. }
  1182. /*
  1183. =====================
  1184. idActor::SetEyeHeight
  1185. =====================
  1186. */
  1187. void idActor::SetEyeHeight( float height ) {
  1188. eyeOffset.z = height;
  1189. }
  1190. /*
  1191. =====================
  1192. idActor::EyeHeight
  1193. =====================
  1194. */
  1195. float idActor::EyeHeight( void ) const {
  1196. return eyeOffset.z;
  1197. }
  1198. /*
  1199. =====================
  1200. idActor::EyeOffset
  1201. =====================
  1202. */
  1203. idVec3 idActor::EyeOffset( void ) const {
  1204. return GetPhysics()->GetGravityNormal() * -eyeOffset.z;
  1205. }
  1206. /*
  1207. =====================
  1208. idActor::GetEyePosition
  1209. =====================
  1210. */
  1211. idVec3 idActor::GetEyePosition( void ) const {
  1212. return GetPhysics()->GetOrigin() + ( GetPhysics()->GetGravityNormal() * -eyeOffset.z );
  1213. }
  1214. /*
  1215. =====================
  1216. idActor::GetViewPos
  1217. =====================
  1218. */
  1219. void idActor::GetViewPos( idVec3 &origin, idMat3 &axis ) const {
  1220. origin = GetEyePosition();
  1221. axis = viewAxis;
  1222. }
  1223. /*
  1224. =====================
  1225. idActor::CheckFOV
  1226. =====================
  1227. */
  1228. bool idActor::CheckFOV( const idVec3 &pos ) const {
  1229. if ( fovDot == 1.0f ) {
  1230. return true;
  1231. }
  1232. float dot;
  1233. idVec3 delta;
  1234. delta = pos - GetEyePosition();
  1235. // get our gravity normal
  1236. const idVec3 &gravityDir = GetPhysics()->GetGravityNormal();
  1237. // infinite vertical vision, so project it onto our orientation plane
  1238. delta -= gravityDir * ( gravityDir * delta );
  1239. delta.Normalize();
  1240. dot = viewAxis[ 0 ] * delta;
  1241. return ( dot >= fovDot );
  1242. }
  1243. /*
  1244. =====================
  1245. idActor::CanSee
  1246. =====================
  1247. */
  1248. bool idActor::CanSee( idEntity *ent, bool useFov ) const {
  1249. trace_t tr;
  1250. idVec3 eye;
  1251. idVec3 toPos;
  1252. if ( ent->IsHidden() ) {
  1253. return false;
  1254. }
  1255. if ( ent->IsType( idActor::Type ) ) {
  1256. toPos = ( ( idActor * )ent )->GetEyePosition();
  1257. } else {
  1258. toPos = ent->GetPhysics()->GetOrigin();
  1259. }
  1260. if ( useFov && !CheckFOV( toPos ) ) {
  1261. return false;
  1262. }
  1263. eye = GetEyePosition();
  1264. gameLocal.clip.TracePoint( tr, eye, toPos, MASK_OPAQUE, this );
  1265. if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
  1266. return true;
  1267. }
  1268. return false;
  1269. }
  1270. /*
  1271. =====================
  1272. idActor::PointVisible
  1273. =====================
  1274. */
  1275. bool idActor::PointVisible( const idVec3 &point ) const {
  1276. trace_t results;
  1277. idVec3 start, end;
  1278. start = GetEyePosition();
  1279. end = point;
  1280. end[2] += 1.0f;
  1281. gameLocal.clip.TracePoint( results, start, end, MASK_OPAQUE, this );
  1282. return ( results.fraction >= 1.0f );
  1283. }
  1284. /*
  1285. =====================
  1286. idActor::GetAIAimTargets
  1287. Returns positions for the AI to aim at.
  1288. =====================
  1289. */
  1290. void idActor::GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos ) {
  1291. headPos = lastSightPos + EyeOffset();
  1292. chestPos = ( headPos + lastSightPos + GetPhysics()->GetBounds().GetCenter() ) * 0.5f;
  1293. }
  1294. /*
  1295. =====================
  1296. idActor::GetRenderView
  1297. =====================
  1298. */
  1299. renderView_t *idActor::GetRenderView() {
  1300. renderView_t *rv = idEntity::GetRenderView();
  1301. rv->viewaxis = viewAxis;
  1302. rv->vieworg = GetEyePosition();
  1303. return rv;
  1304. }
  1305. /***********************************************************************
  1306. Model/Ragdoll
  1307. ***********************************************************************/
  1308. /*
  1309. ================
  1310. idActor::SetCombatModel
  1311. ================
  1312. */
  1313. void idActor::SetCombatModel( void ) {
  1314. idAFAttachment *headEnt;
  1315. if ( !use_combat_bbox ) {
  1316. if ( combatModel ) {
  1317. combatModel->Unlink();
  1318. combatModel->LoadModel( modelDefHandle );
  1319. } else {
  1320. combatModel = new idClipModel( modelDefHandle );
  1321. }
  1322. headEnt = head.GetEntity();
  1323. if ( headEnt ) {
  1324. headEnt->SetCombatModel();
  1325. }
  1326. }
  1327. }
  1328. /*
  1329. ================
  1330. idActor::GetCombatModel
  1331. ================
  1332. */
  1333. idClipModel *idActor::GetCombatModel( void ) const {
  1334. return combatModel;
  1335. }
  1336. /*
  1337. ================
  1338. idActor::LinkCombat
  1339. ================
  1340. */
  1341. void idActor::LinkCombat( void ) {
  1342. idAFAttachment *headEnt;
  1343. if ( fl.hidden || use_combat_bbox ) {
  1344. return;
  1345. }
  1346. if ( combatModel ) {
  1347. combatModel->Link( gameLocal.clip, this, 0, renderEntity.origin, renderEntity.axis, modelDefHandle );
  1348. }
  1349. headEnt = head.GetEntity();
  1350. if ( headEnt ) {
  1351. headEnt->LinkCombat();
  1352. }
  1353. }
  1354. /*
  1355. ================
  1356. idActor::UnlinkCombat
  1357. ================
  1358. */
  1359. void idActor::UnlinkCombat( void ) {
  1360. idAFAttachment *headEnt;
  1361. if ( combatModel ) {
  1362. combatModel->Unlink();
  1363. }
  1364. headEnt = head.GetEntity();
  1365. if ( headEnt ) {
  1366. headEnt->UnlinkCombat();
  1367. }
  1368. }
  1369. /*
  1370. ================
  1371. idActor::StartRagdoll
  1372. ================
  1373. */
  1374. bool idActor::StartRagdoll( void ) {
  1375. float slomoStart, slomoEnd;
  1376. float jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd;
  1377. float contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd;
  1378. // if no AF loaded
  1379. if ( !af.IsLoaded() ) {
  1380. return false;
  1381. }
  1382. // if the AF is already active
  1383. if ( af.IsActive() ) {
  1384. return true;
  1385. }
  1386. // disable the monster bounding box
  1387. GetPhysics()->DisableClip();
  1388. // start using the AF
  1389. af.StartFromCurrentPose( spawnArgs.GetInt( "velocityTime", "0" ) );
  1390. slomoStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoStart", "-1.6" );
  1391. slomoEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoEnd", "0.8" );
  1392. // do the first part of the death in slow motion
  1393. af.GetPhysics()->SetTimeScaleRamp( slomoStart, slomoEnd );
  1394. jointFrictionDent = spawnArgs.GetFloat( "ragdoll_jointFrictionDent", "0.1" );
  1395. jointFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionStart", "0.2" );
  1396. jointFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionEnd", "1.2" );
  1397. // set joint friction dent
  1398. af.GetPhysics()->SetJointFrictionDent( jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd );
  1399. contactFrictionDent = spawnArgs.GetFloat( "ragdoll_contactFrictionDent", "0.1" );
  1400. contactFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionStart", "1.0" );
  1401. contactFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionEnd", "2.0" );
  1402. // set contact friction dent
  1403. af.GetPhysics()->SetContactFrictionDent( contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd );
  1404. // drop any items the actor is holding
  1405. idMoveableItem::DropItems( this, "death", NULL );
  1406. // drop any articulated figures the actor is holding
  1407. idAFEntity_Base::DropAFs( this, "death", NULL );
  1408. RemoveAttachments();
  1409. return true;
  1410. }
  1411. /*
  1412. ================
  1413. idActor::StopRagdoll
  1414. ================
  1415. */
  1416. void idActor::StopRagdoll( void ) {
  1417. if ( af.IsActive() ) {
  1418. af.Stop();
  1419. }
  1420. }
  1421. /*
  1422. ================
  1423. idActor::UpdateAnimationControllers
  1424. ================
  1425. */
  1426. bool idActor::UpdateAnimationControllers( void ) {
  1427. if ( af.IsActive() ) {
  1428. return idAFEntity_Base::UpdateAnimationControllers();
  1429. } else {
  1430. animator.ClearAFPose();
  1431. }
  1432. if ( walkIK.IsInitialized() ) {
  1433. walkIK.Evaluate();
  1434. return true;
  1435. }
  1436. return false;
  1437. }
  1438. /*
  1439. ================
  1440. idActor::RemoveAttachments
  1441. ================
  1442. */
  1443. void idActor::RemoveAttachments( void ) {
  1444. int i;
  1445. idEntity *ent;
  1446. // remove any attached entities
  1447. for( i = 0; i < attachments.Num(); i++ ) {
  1448. ent = attachments[ i ].ent.GetEntity();
  1449. if ( ent && ent->spawnArgs.GetBool( "remove" ) ) {
  1450. ent->PostEventMS( &EV_Remove, 0 );
  1451. }
  1452. }
  1453. }
  1454. /*
  1455. ================
  1456. idActor::Attach
  1457. ================
  1458. */
  1459. void idActor::Attach( idEntity *ent ) {
  1460. idVec3 origin;
  1461. idMat3 axis;
  1462. jointHandle_t joint;
  1463. idStr jointName;
  1464. idAttachInfo &attach = attachments.Alloc();
  1465. idAngles angleOffset;
  1466. idVec3 originOffset;
  1467. jointName = ent->spawnArgs.GetString( "joint" );
  1468. joint = animator.GetJointHandle( jointName );
  1469. if ( joint == INVALID_JOINT ) {
  1470. gameLocal.Error( "Joint '%s' not found for attaching '%s' on '%s'", jointName.c_str(), ent->GetClassname(), name.c_str() );
  1471. }
  1472. angleOffset = ent->spawnArgs.GetAngles( "angles" );
  1473. originOffset = ent->spawnArgs.GetVector( "origin" );
  1474. attach.channel = animator.GetChannelForJoint( joint );
  1475. GetJointWorldTransform( joint, gameLocal.time, origin, axis );
  1476. attach.ent = ent;
  1477. ent->SetOrigin( origin + originOffset * renderEntity.axis );
  1478. idMat3 rotate = angleOffset.ToMat3();
  1479. idMat3 newAxis = rotate * axis;
  1480. ent->SetAxis( newAxis );
  1481. ent->BindToJoint( this, joint, true );
  1482. ent->cinematic = cinematic;
  1483. }
  1484. /*
  1485. ================
  1486. idActor::Teleport
  1487. ================
  1488. */
  1489. void idActor::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
  1490. GetPhysics()->SetOrigin( origin + idVec3( 0, 0, CM_CLIP_EPSILON ) );
  1491. GetPhysics()->SetLinearVelocity( vec3_origin );
  1492. viewAxis = angles.ToMat3();
  1493. UpdateVisuals();
  1494. if ( !IsHidden() ) {
  1495. // kill anything at the new position
  1496. gameLocal.KillBox( this );
  1497. }
  1498. }
  1499. /*
  1500. ================
  1501. idActor::GetDeltaViewAngles
  1502. ================
  1503. */
  1504. const idAngles &idActor::GetDeltaViewAngles( void ) const {
  1505. return deltaViewAngles;
  1506. }
  1507. /*
  1508. ================
  1509. idActor::SetDeltaViewAngles
  1510. ================
  1511. */
  1512. void idActor::SetDeltaViewAngles( const idAngles &delta ) {
  1513. deltaViewAngles = delta;
  1514. }
  1515. /*
  1516. ================
  1517. idActor::HasEnemies
  1518. ================
  1519. */
  1520. bool idActor::HasEnemies( void ) const {
  1521. idActor *ent;
  1522. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1523. if ( !ent->fl.hidden ) {
  1524. return true;
  1525. }
  1526. }
  1527. return false;
  1528. }
  1529. /*
  1530. ================
  1531. idActor::ClosestEnemyToPoint
  1532. ================
  1533. */
  1534. idActor *idActor::ClosestEnemyToPoint( const idVec3 &pos ) {
  1535. idActor *ent;
  1536. idActor *bestEnt;
  1537. float bestDistSquared;
  1538. float distSquared;
  1539. idVec3 delta;
  1540. bestDistSquared = idMath::INFINITY;
  1541. bestEnt = NULL;
  1542. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1543. if ( ent->fl.hidden ) {
  1544. continue;
  1545. }
  1546. delta = ent->GetPhysics()->GetOrigin() - pos;
  1547. distSquared = delta.LengthSqr();
  1548. if ( distSquared < bestDistSquared ) {
  1549. bestEnt = ent;
  1550. bestDistSquared = distSquared;
  1551. }
  1552. }
  1553. return bestEnt;
  1554. }
  1555. /*
  1556. ================
  1557. idActor::EnemyWithMostHealth
  1558. ================
  1559. */
  1560. idActor *idActor::EnemyWithMostHealth() {
  1561. idActor *ent;
  1562. idActor *bestEnt;
  1563. int most = -9999;
  1564. bestEnt = NULL;
  1565. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1566. if ( !ent->fl.hidden && ( ent->health > most ) ) {
  1567. bestEnt = ent;
  1568. most = ent->health;
  1569. }
  1570. }
  1571. return bestEnt;
  1572. }
  1573. /*
  1574. ================
  1575. idActor::OnLadder
  1576. ================
  1577. */
  1578. bool idActor::OnLadder( void ) const {
  1579. return false;
  1580. }
  1581. /*
  1582. ==============
  1583. idActor::GetAASLocation
  1584. ==============
  1585. */
  1586. void idActor::GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const {
  1587. idVec3 size;
  1588. idBounds bounds;
  1589. GetFloorPos( 64.0f, pos );
  1590. if ( !aas ) {
  1591. areaNum = 0;
  1592. return;
  1593. }
  1594. size = aas->GetSettings()->boundingBoxes[0][1];
  1595. bounds[0] = -size;
  1596. size.z = 32.0f;
  1597. bounds[1] = size;
  1598. areaNum = aas->PointReachableAreaNum( pos, bounds, AREA_REACHABLE_WALK );
  1599. if ( areaNum ) {
  1600. aas->PushPointIntoAreaNum( areaNum, pos );
  1601. }
  1602. }
  1603. /***********************************************************************
  1604. animation state
  1605. ***********************************************************************/
  1606. /*
  1607. =====================
  1608. idActor::SetAnimState
  1609. =====================
  1610. */
  1611. void idActor::SetAnimState( int channel, const char *statename, int blendFrames ) {
  1612. const function_t *func;
  1613. func = scriptObject.GetFunction( statename );
  1614. if ( !func ) {
  1615. assert( 0 );
  1616. gameLocal.Error( "Can't find function '%s' in object '%s'", statename, scriptObject.GetTypeName() );
  1617. }
  1618. switch( channel ) {
  1619. case ANIMCHANNEL_HEAD :
  1620. headAnim.SetState( statename, blendFrames );
  1621. allowEyeFocus = true;
  1622. break;
  1623. case ANIMCHANNEL_TORSO :
  1624. torsoAnim.SetState( statename, blendFrames );
  1625. legsAnim.Enable( blendFrames );
  1626. allowPain = true;
  1627. allowEyeFocus = true;
  1628. break;
  1629. case ANIMCHANNEL_LEGS :
  1630. legsAnim.SetState( statename, blendFrames );
  1631. torsoAnim.Enable( blendFrames );
  1632. allowPain = true;
  1633. allowEyeFocus = true;
  1634. break;
  1635. default:
  1636. gameLocal.Error( "idActor::SetAnimState: Unknown anim group" );
  1637. break;
  1638. }
  1639. }
  1640. /*
  1641. =====================
  1642. idActor::GetAnimState
  1643. =====================
  1644. */
  1645. const char *idActor::GetAnimState( int channel ) const {
  1646. switch( channel ) {
  1647. case ANIMCHANNEL_HEAD :
  1648. return headAnim.state;
  1649. break;
  1650. case ANIMCHANNEL_TORSO :
  1651. return torsoAnim.state;
  1652. break;
  1653. case ANIMCHANNEL_LEGS :
  1654. return legsAnim.state;
  1655. break;
  1656. default:
  1657. gameLocal.Error( "idActor::GetAnimState: Unknown anim group" );
  1658. return NULL;
  1659. break;
  1660. }
  1661. }
  1662. /*
  1663. =====================
  1664. idActor::InAnimState
  1665. =====================
  1666. */
  1667. bool idActor::InAnimState( int channel, const char *statename ) const {
  1668. switch( channel ) {
  1669. case ANIMCHANNEL_HEAD :
  1670. if ( headAnim.state == statename ) {
  1671. return true;
  1672. }
  1673. break;
  1674. case ANIMCHANNEL_TORSO :
  1675. if ( torsoAnim.state == statename ) {
  1676. return true;
  1677. }
  1678. break;
  1679. case ANIMCHANNEL_LEGS :
  1680. if ( legsAnim.state == statename ) {
  1681. return true;
  1682. }
  1683. break;
  1684. default:
  1685. gameLocal.Error( "idActor::InAnimState: Unknown anim group" );
  1686. break;
  1687. }
  1688. return false;
  1689. }
  1690. /*
  1691. =====================
  1692. idActor::WaitState
  1693. =====================
  1694. */
  1695. const char *idActor::WaitState( void ) const {
  1696. if ( waitState.Length() ) {
  1697. return waitState;
  1698. } else {
  1699. return NULL;
  1700. }
  1701. }
  1702. /*
  1703. =====================
  1704. idActor::SetWaitState
  1705. =====================
  1706. */
  1707. void idActor::SetWaitState( const char *_waitstate ) {
  1708. waitState = _waitstate;
  1709. }
  1710. /*
  1711. =====================
  1712. idActor::UpdateAnimState
  1713. =====================
  1714. */
  1715. void idActor::UpdateAnimState( void ) {
  1716. headAnim.UpdateState();
  1717. torsoAnim.UpdateState();
  1718. legsAnim.UpdateState();
  1719. }
  1720. /*
  1721. =====================
  1722. idActor::GetAnim
  1723. =====================
  1724. */
  1725. int idActor::GetAnim( int channel, const char *animname ) {
  1726. int anim;
  1727. const char *temp;
  1728. idAnimator *animatorPtr;
  1729. if ( channel == ANIMCHANNEL_HEAD ) {
  1730. if ( !head.GetEntity() ) {
  1731. return 0;
  1732. }
  1733. animatorPtr = head.GetEntity()->GetAnimator();
  1734. } else {
  1735. animatorPtr = &animator;
  1736. }
  1737. if ( animPrefix.Length() ) {
  1738. temp = va( "%s_%s", animPrefix.c_str(), animname );
  1739. anim = animatorPtr->GetAnim( temp );
  1740. if ( anim ) {
  1741. return anim;
  1742. }
  1743. }
  1744. anim = animatorPtr->GetAnim( animname );
  1745. return anim;
  1746. }
  1747. /*
  1748. ===============
  1749. idActor::SyncAnimChannels
  1750. ===============
  1751. */
  1752. void idActor::SyncAnimChannels( int channel, int syncToChannel, int blendFrames ) {
  1753. idAnimator *headAnimator;
  1754. idAFAttachment *headEnt;
  1755. int anim;
  1756. idAnimBlend *syncAnim;
  1757. int starttime;
  1758. int blendTime;
  1759. int cycle;
  1760. blendTime = FRAME2MS( blendFrames );
  1761. if ( channel == ANIMCHANNEL_HEAD ) {
  1762. headEnt = head.GetEntity();
  1763. if ( headEnt ) {
  1764. headAnimator = headEnt->GetAnimator();
  1765. syncAnim = animator.CurrentAnim( syncToChannel );
  1766. if ( syncAnim ) {
  1767. anim = headAnimator->GetAnim( syncAnim->AnimFullName() );
  1768. if ( !anim ) {
  1769. anim = headAnimator->GetAnim( syncAnim->AnimName() );
  1770. }
  1771. if ( anim ) {
  1772. cycle = animator.CurrentAnim( syncToChannel )->GetCycleCount();
  1773. starttime = animator.CurrentAnim( syncToChannel )->GetStartTime();
  1774. headAnimator->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, blendTime );
  1775. headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( cycle );
  1776. headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetStartTime( starttime );
  1777. } else {
  1778. headEnt->PlayIdleAnim( blendTime );
  1779. }
  1780. }
  1781. }
  1782. } else if ( syncToChannel == ANIMCHANNEL_HEAD ) {
  1783. headEnt = head.GetEntity();
  1784. if ( headEnt ) {
  1785. headAnimator = headEnt->GetAnimator();
  1786. syncAnim = headAnimator->CurrentAnim( ANIMCHANNEL_ALL );
  1787. if ( syncAnim ) {
  1788. anim = GetAnim( channel, syncAnim->AnimFullName() );
  1789. if ( !anim ) {
  1790. anim = GetAnim( channel, syncAnim->AnimName() );
  1791. }
  1792. if ( anim ) {
  1793. cycle = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetCycleCount();
  1794. starttime = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime();
  1795. animator.PlayAnim( channel, anim, gameLocal.time, blendTime );
  1796. animator.CurrentAnim( channel )->SetCycleCount( cycle );
  1797. animator.CurrentAnim( channel )->SetStartTime( starttime );
  1798. }
  1799. }
  1800. }
  1801. } else {
  1802. animator.SyncAnimChannels( channel, syncToChannel, gameLocal.time, blendTime );
  1803. }
  1804. }
  1805. /***********************************************************************
  1806. Damage
  1807. ***********************************************************************/
  1808. /*
  1809. ============
  1810. idActor::Gib
  1811. ============
  1812. */
  1813. void idActor::Gib( const idVec3 &dir, const char *damageDefName ) {
  1814. // no gibbing in multiplayer - by self damage or by moving objects
  1815. if ( gameLocal.isMultiplayer ) {
  1816. return;
  1817. }
  1818. // only gib once
  1819. if ( gibbed ) {
  1820. return;
  1821. }
  1822. idAFEntity_Gibbable::Gib( dir, damageDefName );
  1823. if ( head.GetEntity() ) {
  1824. head.GetEntity()->Hide();
  1825. }
  1826. StopSound( SND_CHANNEL_VOICE, false );
  1827. }
  1828. /*
  1829. ============
  1830. idActor::Damage
  1831. this entity that is being damaged
  1832. inflictor entity that is causing the damage
  1833. attacker entity that caused the inflictor to damage targ
  1834. example: this=monster, inflictor=rocket, attacker=player
  1835. dir direction of the attack for knockback in global space
  1836. point point at which the damage is being inflicted, used for headshots
  1837. damage amount of damage being inflicted
  1838. inflictor, attacker, dir, and point can be NULL for environmental effects
  1839. Bleeding wounds and surface overlays are applied in the collision code that
  1840. calls Damage()
  1841. ============
  1842. */
  1843. void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
  1844. const char *damageDefName, const float damageScale, const int location ) {
  1845. if ( !fl.takedamage ) {
  1846. return;
  1847. }
  1848. if ( !inflictor ) {
  1849. inflictor = gameLocal.world;
  1850. }
  1851. if ( !attacker ) {
  1852. attacker = gameLocal.world;
  1853. }
  1854. #ifdef _D3XP
  1855. SetTimeState ts( timeGroup );
  1856. // Helltime boss is immune to all projectiles except the helltime killer
  1857. if ( finalBoss && idStr::Icmp(inflictor->GetEntityDefName(), "projectile_helltime_killer") ) {
  1858. return;
  1859. }
  1860. // Maledict is immume to the falling asteroids
  1861. if ( !idStr::Icmp( GetEntityDefName(), "monster_boss_d3xp_maledict" ) &&
  1862. (!idStr::Icmp( damageDefName, "damage_maledict_asteroid" ) || !idStr::Icmp( damageDefName, "damage_maledict_asteroid_splash" ) ) ) {
  1863. return;
  1864. }
  1865. #else
  1866. if ( finalBoss && !inflictor->IsType( idSoulCubeMissile::Type ) ) {
  1867. return;
  1868. }
  1869. #endif
  1870. const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
  1871. if ( !damageDef ) {
  1872. gameLocal.Error( "Unknown damageDef '%s'", damageDefName );
  1873. }
  1874. int damage = damageDef->GetInt( "damage" ) * damageScale;
  1875. damage = GetDamageForLocation( damage, location );
  1876. // inform the attacker that they hit someone
  1877. if (attacker != inflictor)
  1878. attacker->DamageFeedback( this, inflictor, damage );
  1879. if ( damage > 0 )
  1880. {
  1881. health -= damage;
  1882. #ifdef _D3XP
  1883. //Check the health against any damage cap that is currently set
  1884. if(damageCap >= 0 && health < damageCap) {
  1885. health = damageCap;
  1886. }
  1887. #endif
  1888. if ( health <= 0 ) {
  1889. if ( health < -999 ) {
  1890. health = -999;
  1891. }
  1892. Killed( inflictor, attacker, damage, dir, location );
  1893. if ( ( health < -20 ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) {
  1894. Gib( dir, damageDefName );
  1895. }
  1896. } else {
  1897. Pain( inflictor, attacker, damage, dir, location );
  1898. }
  1899. } else {
  1900. // don't accumulate knockback
  1901. if ( af.IsLoaded() ) {
  1902. // clear impacts
  1903. af.Rest();
  1904. // physics is turned off by calling af.Rest()
  1905. BecomeActive( TH_PHYSICS );
  1906. }
  1907. }
  1908. }
  1909. /*
  1910. =====================
  1911. idActor::ClearPain
  1912. =====================
  1913. */
  1914. void idActor::ClearPain( void ) {
  1915. pain_debounce_time = 0;
  1916. }
  1917. /*
  1918. =====================
  1919. idActor::Pain
  1920. =====================
  1921. */
  1922. bool idActor::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  1923. if ( af.IsLoaded() ) {
  1924. // clear impacts
  1925. af.Rest();
  1926. // physics is turned off by calling af.Rest()
  1927. BecomeActive( TH_PHYSICS );
  1928. }
  1929. if ( gameLocal.time < pain_debounce_time ) {
  1930. return false;
  1931. }
  1932. // don't play pain sounds more than necessary
  1933. pain_debounce_time = gameLocal.time + pain_delay;
  1934. if ( health > 75 ) {
  1935. StartSound( "snd_pain_small", SND_CHANNEL_VOICE, 0, false, NULL );
  1936. } else if ( health > 50 ) {
  1937. StartSound( "snd_pain_medium", SND_CHANNEL_VOICE, 0, false, NULL );
  1938. } else if ( health > 25 ) {
  1939. StartSound( "snd_pain_large", SND_CHANNEL_VOICE, 0, false, NULL );
  1940. } else {
  1941. StartSound( "snd_pain_huge", SND_CHANNEL_VOICE, 0, false, NULL );
  1942. }
  1943. if ( !allowPain || ( gameLocal.time < painTime ) ) {
  1944. // don't play a pain anim
  1945. return false;
  1946. }
  1947. if ( pain_threshold && ( damage < pain_threshold ) ) {
  1948. return false;
  1949. }
  1950. // set the pain anim
  1951. idStr damageGroup = GetDamageGroup( location );
  1952. painAnim = "";
  1953. if ( animPrefix.Length() ) {
  1954. if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
  1955. sprintf( painAnim, "%s_pain_%s", animPrefix.c_str(), damageGroup.c_str() );
  1956. if ( !animator.HasAnim( painAnim ) ) {
  1957. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1958. if ( !animator.HasAnim( painAnim ) ) {
  1959. painAnim = "";
  1960. }
  1961. }
  1962. }
  1963. if ( !painAnim.Length() ) {
  1964. sprintf( painAnim, "%s_pain", animPrefix.c_str() );
  1965. if ( !animator.HasAnim( painAnim ) ) {
  1966. painAnim = "";
  1967. }
  1968. }
  1969. } else if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
  1970. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1971. if ( !animator.HasAnim( painAnim ) ) {
  1972. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1973. if ( !animator.HasAnim( painAnim ) ) {
  1974. painAnim = "";
  1975. }
  1976. }
  1977. }
  1978. if ( !painAnim.Length() ) {
  1979. painAnim = "pain";
  1980. }
  1981. if ( g_debugDamage.GetBool() ) {
  1982. gameLocal.Printf( "Damage: joint: '%s', zone '%s', anim '%s'\n", animator.GetJointName( ( jointHandle_t )location ),
  1983. damageGroup.c_str(), painAnim.c_str() );
  1984. }
  1985. return true;
  1986. }
  1987. /*
  1988. =====================
  1989. idActor::SpawnGibs
  1990. =====================
  1991. */
  1992. void idActor::SpawnGibs( const idVec3 &dir, const char *damageDefName ) {
  1993. idAFEntity_Gibbable::SpawnGibs( dir, damageDefName );
  1994. RemoveAttachments();
  1995. }
  1996. /*
  1997. =====================
  1998. idActor::SetupDamageGroups
  1999. FIXME: only store group names once and store an index for each joint
  2000. =====================
  2001. */
  2002. void idActor::SetupDamageGroups( void ) {
  2003. int i;
  2004. const idKeyValue *arg;
  2005. idStr groupname;
  2006. idList<jointHandle_t> jointList;
  2007. int jointnum;
  2008. float scale;
  2009. // create damage zones
  2010. damageGroups.SetNum( animator.NumJoints() );
  2011. arg = spawnArgs.MatchPrefix( "damage_zone ", NULL );
  2012. while ( arg ) {
  2013. groupname = arg->GetKey();
  2014. groupname.Strip( "damage_zone " );
  2015. animator.GetJointList( arg->GetValue(), jointList );
  2016. for( i = 0; i < jointList.Num(); i++ ) {
  2017. jointnum = jointList[ i ];
  2018. damageGroups[ jointnum ] = groupname;
  2019. }
  2020. jointList.Clear();
  2021. arg = spawnArgs.MatchPrefix( "damage_zone ", arg );
  2022. }
  2023. // initilize the damage zones to normal damage
  2024. damageScale.SetNum( animator.NumJoints() );
  2025. for( i = 0; i < damageScale.Num(); i++ ) {
  2026. damageScale[ i ] = 1.0f;
  2027. }
  2028. // set the percentage on damage zones
  2029. arg = spawnArgs.MatchPrefix( "damage_scale ", NULL );
  2030. while ( arg ) {
  2031. scale = atof( arg->GetValue() );
  2032. groupname = arg->GetKey();
  2033. groupname.Strip( "damage_scale " );
  2034. for( i = 0; i < damageScale.Num(); i++ ) {
  2035. if ( damageGroups[ i ] == groupname ) {
  2036. damageScale[ i ] = scale;
  2037. }
  2038. }
  2039. arg = spawnArgs.MatchPrefix( "damage_scale ", arg );
  2040. }
  2041. }
  2042. /*
  2043. =====================
  2044. idActor::GetDamageForLocation
  2045. =====================
  2046. */
  2047. int idActor::GetDamageForLocation( int damage, int location ) {
  2048. if ( ( location < 0 ) || ( location >= damageScale.Num() ) ) {
  2049. return damage;
  2050. }
  2051. return (int)ceil( damage * damageScale[ location ] );
  2052. }
  2053. /*
  2054. =====================
  2055. idActor::GetDamageGroup
  2056. =====================
  2057. */
  2058. const char *idActor::GetDamageGroup( int location ) {
  2059. if ( ( location < 0 ) || ( location >= damageGroups.Num() ) ) {
  2060. return "";
  2061. }
  2062. return damageGroups[ location ];
  2063. }
  2064. /***********************************************************************
  2065. Events
  2066. ***********************************************************************/
  2067. /*
  2068. =====================
  2069. idActor::Event_EnableEyeFocus
  2070. =====================
  2071. */
  2072. void idActor::PlayFootStepSound( void ) {
  2073. const char *sound = NULL;
  2074. //const idMaterial *material;
  2075. if ( !GetPhysics()->HasGroundContacts() ) {
  2076. return;
  2077. }
  2078. idEntity *recordEnt;
  2079. recordEnt = gameLocal.FindEntity( "world1" );
  2080. if (recordEnt)
  2081. {
  2082. int currentRole = static_cast<idWorldManager *>( recordEnt )->index;
  2083. if (currentRole >= 0)
  2084. {
  2085. const char *sound = NULL;
  2086. sound = spawnArgs.GetString( va( "snd_footstep_role%d", currentRole ) );
  2087. if ( *sound != '\0' )
  2088. {
  2089. StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_ANY, 0, false, NULL );
  2090. }
  2091. }
  2092. //common->Printf("%d\n", currentRole);
  2093. }
  2094. /*
  2095. // start footstep sound based on material type
  2096. material = GetPhysics()->GetContact( 0 ).material;
  2097. if ( material != NULL ) {
  2098. sound = spawnArgs.GetString( va( "snd_footstep_%s", gameLocal.sufaceTypeNames[ material->GetSurfaceType() ] ) );
  2099. }
  2100. if ( *sound == '\0' ) {
  2101. sound = spawnArgs.GetString( "snd_footstep" );
  2102. }
  2103. if ( *sound != '\0' ) {
  2104. StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
  2105. }
  2106. */
  2107. }
  2108. /*
  2109. =====================
  2110. idActor::Event_EnableEyeFocus
  2111. =====================
  2112. */
  2113. void idActor::Event_EnableEyeFocus( void ) {
  2114. allowEyeFocus = true;
  2115. blink_time = gameLocal.time + blink_min + gameLocal.random.RandomFloat() * ( blink_max - blink_min );
  2116. }
  2117. /*
  2118. =====================
  2119. idActor::Event_DisableEyeFocus
  2120. =====================
  2121. */
  2122. void idActor::Event_DisableEyeFocus( void ) {
  2123. allowEyeFocus = false;
  2124. idEntity *headEnt = head.GetEntity();
  2125. if ( headEnt ) {
  2126. headEnt->GetAnimator()->Clear( ANIMCHANNEL_EYELIDS, gameLocal.time, FRAME2MS( 2 ) );
  2127. } else {
  2128. animator.Clear( ANIMCHANNEL_EYELIDS, gameLocal.time, FRAME2MS( 2 ) );
  2129. }
  2130. }
  2131. /*
  2132. ===============
  2133. idActor::Event_Footstep
  2134. ===============
  2135. */
  2136. void idActor::Event_Footstep( void ) {
  2137. PlayFootStepSound();
  2138. }
  2139. /*
  2140. =====================
  2141. idActor::Event_EnableWalkIK
  2142. =====================
  2143. */
  2144. void idActor::Event_EnableWalkIK( void ) {
  2145. walkIK.EnableAll();
  2146. }
  2147. /*
  2148. =====================
  2149. idActor::Event_DisableWalkIK
  2150. =====================
  2151. */
  2152. void idActor::Event_DisableWalkIK( void ) {
  2153. walkIK.DisableAll();
  2154. }
  2155. /*
  2156. =====================
  2157. idActor::Event_EnableLegIK
  2158. =====================
  2159. */
  2160. void idActor::Event_EnableLegIK( int num ) {
  2161. walkIK.EnableLeg( num );
  2162. }
  2163. /*
  2164. =====================
  2165. idActor::Event_DisableLegIK
  2166. =====================
  2167. */
  2168. void idActor::Event_DisableLegIK( int num ) {
  2169. walkIK.DisableLeg( num );
  2170. }
  2171. /*
  2172. =====================
  2173. idActor::Event_PreventPain
  2174. =====================
  2175. */
  2176. void idActor::Event_PreventPain( float duration ) {
  2177. painTime = gameLocal.time + SEC2MS( duration );
  2178. }
  2179. /*
  2180. ===============
  2181. idActor::Event_DisablePain
  2182. ===============
  2183. */
  2184. void idActor::Event_DisablePain( void ) {
  2185. allowPain = false;
  2186. }
  2187. /*
  2188. ===============
  2189. idActor::Event_EnablePain
  2190. ===============
  2191. */
  2192. void idActor::Event_EnablePain( void ) {
  2193. allowPain = true;
  2194. }
  2195. /*
  2196. =====================
  2197. idActor::Event_GetPainAnim
  2198. =====================
  2199. */
  2200. void idActor::Event_GetPainAnim( void ) {
  2201. if ( !painAnim.Length() ) {
  2202. idThread::ReturnString( "pain" );
  2203. } else {
  2204. idThread::ReturnString( painAnim );
  2205. }
  2206. }
  2207. /*
  2208. =====================
  2209. idActor::Event_SetAnimPrefix
  2210. =====================
  2211. */
  2212. void idActor::Event_SetAnimPrefix( const char *prefix ) {
  2213. animPrefix = prefix;
  2214. }
  2215. /*
  2216. ===============
  2217. idActor::Event_StopAnim
  2218. ===============
  2219. */
  2220. void idActor::Event_StopAnim( int channel, int frames ) {
  2221. switch( channel ) {
  2222. case ANIMCHANNEL_HEAD :
  2223. headAnim.StopAnim( frames );
  2224. break;
  2225. case ANIMCHANNEL_TORSO :
  2226. torsoAnim.StopAnim( frames );
  2227. break;
  2228. case ANIMCHANNEL_LEGS :
  2229. legsAnim.StopAnim( frames );
  2230. break;
  2231. default:
  2232. gameLocal.Error( "Unknown anim group" );
  2233. break;
  2234. }
  2235. }
  2236. /*
  2237. ===============
  2238. idActor::Event_PlayAnim
  2239. ===============
  2240. */
  2241. void idActor::Event_PlayAnim( int channel, const char *animname ) {
  2242. animFlags_t flags;
  2243. idEntity *headEnt;
  2244. int anim;
  2245. anim = GetAnim( channel, animname );
  2246. if ( !anim ) {
  2247. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2248. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2249. } else {
  2250. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2251. }
  2252. idThread::ReturnInt( 0 );
  2253. return;
  2254. }
  2255. switch( channel ) {
  2256. case ANIMCHANNEL_HEAD :
  2257. headEnt = head.GetEntity();
  2258. if ( headEnt ) {
  2259. headAnim.idleAnim = false;
  2260. headAnim.PlayAnim( anim );
  2261. flags = headAnim.GetAnimFlags();
  2262. if ( !flags.prevent_idle_override ) {
  2263. if ( torsoAnim.IsIdle() ) {
  2264. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2265. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2266. if ( legsAnim.IsIdle() ) {
  2267. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2268. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2269. }
  2270. }
  2271. }
  2272. }
  2273. break;
  2274. case ANIMCHANNEL_TORSO :
  2275. torsoAnim.idleAnim = false;
  2276. torsoAnim.PlayAnim( anim );
  2277. flags = torsoAnim.GetAnimFlags();
  2278. if ( !flags.prevent_idle_override ) {
  2279. if ( headAnim.IsIdle() ) {
  2280. headAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2281. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2282. }
  2283. if ( legsAnim.IsIdle() ) {
  2284. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2285. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2286. }
  2287. }
  2288. break;
  2289. case ANIMCHANNEL_LEGS :
  2290. legsAnim.idleAnim = false;
  2291. legsAnim.PlayAnim( anim );
  2292. flags = legsAnim.GetAnimFlags();
  2293. if ( !flags.prevent_idle_override ) {
  2294. if ( torsoAnim.IsIdle() ) {
  2295. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2296. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2297. if ( headAnim.IsIdle() ) {
  2298. headAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2299. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2300. }
  2301. }
  2302. }
  2303. break;
  2304. default :
  2305. gameLocal.Error( "Unknown anim group" );
  2306. break;
  2307. }
  2308. idThread::ReturnInt( 1 );
  2309. }
  2310. /*
  2311. ===============
  2312. idActor::Event_PlayCycle
  2313. ===============
  2314. */
  2315. void idActor::Event_PlayCycle( int channel, const char *animname ) {
  2316. animFlags_t flags;
  2317. int anim;
  2318. anim = GetAnim( channel, animname );
  2319. if ( !anim ) {
  2320. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2321. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2322. } else {
  2323. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2324. }
  2325. idThread::ReturnInt( false );
  2326. return;
  2327. }
  2328. switch( channel ) {
  2329. case ANIMCHANNEL_HEAD :
  2330. headAnim.idleAnim = false;
  2331. headAnim.CycleAnim( anim );
  2332. flags = headAnim.GetAnimFlags();
  2333. if ( !flags.prevent_idle_override ) {
  2334. if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
  2335. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2336. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2337. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2338. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2339. }
  2340. }
  2341. break;
  2342. case ANIMCHANNEL_TORSO :
  2343. torsoAnim.idleAnim = false;
  2344. torsoAnim.CycleAnim( anim );
  2345. flags = torsoAnim.GetAnimFlags();
  2346. if ( !flags.prevent_idle_override ) {
  2347. if ( headAnim.IsIdle() ) {
  2348. headAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2349. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2350. }
  2351. if ( legsAnim.IsIdle() ) {
  2352. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2353. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2354. }
  2355. }
  2356. break;
  2357. case ANIMCHANNEL_LEGS :
  2358. legsAnim.idleAnim = false;
  2359. legsAnim.CycleAnim( anim );
  2360. flags = legsAnim.GetAnimFlags();
  2361. if ( !flags.prevent_idle_override ) {
  2362. if ( torsoAnim.IsIdle() ) {
  2363. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2364. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2365. if ( headAnim.IsIdle() ) {
  2366. headAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2367. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2368. }
  2369. }
  2370. }
  2371. break;
  2372. default:
  2373. gameLocal.Error( "Unknown anim group" );
  2374. }
  2375. idThread::ReturnInt( true );
  2376. }
  2377. /*
  2378. ===============
  2379. idActor::Event_IdleAnim
  2380. ===============
  2381. */
  2382. void idActor::Event_IdleAnim( int channel, const char *animname ) {
  2383. int anim;
  2384. anim = GetAnim( channel, animname );
  2385. if ( !anim ) {
  2386. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2387. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2388. } else {
  2389. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2390. }
  2391. switch( channel ) {
  2392. case ANIMCHANNEL_HEAD :
  2393. headAnim.BecomeIdle();
  2394. break;
  2395. case ANIMCHANNEL_TORSO :
  2396. torsoAnim.BecomeIdle();
  2397. break;
  2398. case ANIMCHANNEL_LEGS :
  2399. legsAnim.BecomeIdle();
  2400. break;
  2401. default:
  2402. gameLocal.Error( "Unknown anim group" );
  2403. }
  2404. idThread::ReturnInt( false );
  2405. return;
  2406. }
  2407. switch( channel ) {
  2408. case ANIMCHANNEL_HEAD :
  2409. headAnim.BecomeIdle();
  2410. if ( torsoAnim.GetAnimFlags().prevent_idle_override ) {
  2411. // don't sync to torso body if it doesn't override idle anims
  2412. headAnim.CycleAnim( anim );
  2413. } else if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
  2414. // everything is idle, so play the anim on the head and copy it to the torso and legs
  2415. headAnim.CycleAnim( anim );
  2416. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2417. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2418. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2419. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2420. } else if ( torsoAnim.IsIdle() ) {
  2421. // sync the head and torso to the legs
  2422. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, headAnim.animBlendFrames );
  2423. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2424. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, torsoAnim.animBlendFrames );
  2425. } else {
  2426. // sync the head to the torso
  2427. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, headAnim.animBlendFrames );
  2428. }
  2429. break;
  2430. case ANIMCHANNEL_TORSO :
  2431. torsoAnim.BecomeIdle();
  2432. if ( legsAnim.GetAnimFlags().prevent_idle_override ) {
  2433. // don't sync to legs if legs anim doesn't override idle anims
  2434. torsoAnim.CycleAnim( anim );
  2435. } else if ( legsAnim.IsIdle() ) {
  2436. // play the anim in both legs and torso
  2437. torsoAnim.CycleAnim( anim );
  2438. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2439. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2440. } else {
  2441. // sync the anim to the legs
  2442. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, torsoAnim.animBlendFrames );
  2443. }
  2444. if ( headAnim.IsIdle() ) {
  2445. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2446. }
  2447. break;
  2448. case ANIMCHANNEL_LEGS :
  2449. legsAnim.BecomeIdle();
  2450. if ( torsoAnim.GetAnimFlags().prevent_idle_override ) {
  2451. // don't sync to torso if torso anim doesn't override idle anims
  2452. legsAnim.CycleAnim( anim );
  2453. } else if ( torsoAnim.IsIdle() ) {
  2454. // play the anim in both legs and torso
  2455. legsAnim.CycleAnim( anim );
  2456. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2457. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2458. if ( headAnim.IsIdle() ) {
  2459. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2460. }
  2461. } else {
  2462. // sync the anim to the torso
  2463. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, legsAnim.animBlendFrames );
  2464. }
  2465. break;
  2466. default:
  2467. gameLocal.Error( "Unknown anim group" );
  2468. }
  2469. idThread::ReturnInt( true );
  2470. }
  2471. /*
  2472. ================
  2473. idActor::Event_SetSyncedAnimWeight
  2474. ================
  2475. */
  2476. void idActor::Event_SetSyncedAnimWeight( int channel, int anim, float weight ) {
  2477. idEntity *headEnt;
  2478. headEnt = head.GetEntity();
  2479. switch( channel ) {
  2480. case ANIMCHANNEL_HEAD :
  2481. if ( headEnt ) {
  2482. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2483. } else {
  2484. animator.CurrentAnim( ANIMCHANNEL_HEAD )->SetSyncedAnimWeight( anim, weight );
  2485. }
  2486. if ( torsoAnim.IsIdle() ) {
  2487. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2488. if ( legsAnim.IsIdle() ) {
  2489. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2490. }
  2491. }
  2492. break;
  2493. case ANIMCHANNEL_TORSO :
  2494. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2495. if ( legsAnim.IsIdle() ) {
  2496. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2497. }
  2498. if ( headEnt && headAnim.IsIdle() ) {
  2499. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2500. }
  2501. break;
  2502. case ANIMCHANNEL_LEGS :
  2503. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2504. if ( torsoAnim.IsIdle() ) {
  2505. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2506. if ( headEnt && headAnim.IsIdle() ) {
  2507. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2508. }
  2509. }
  2510. break;
  2511. default:
  2512. gameLocal.Error( "Unknown anim group" );
  2513. }
  2514. }
  2515. /*
  2516. ===============
  2517. idActor::Event_OverrideAnim
  2518. ===============
  2519. */
  2520. void idActor::Event_OverrideAnim( int channel ) {
  2521. switch( channel ) {
  2522. case ANIMCHANNEL_HEAD :
  2523. headAnim.Disable();
  2524. if ( !torsoAnim.IsIdle() ) {
  2525. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2526. } else {
  2527. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2528. }
  2529. break;
  2530. case ANIMCHANNEL_TORSO :
  2531. torsoAnim.Disable();
  2532. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2533. if ( headAnim.IsIdle() ) {
  2534. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2535. }
  2536. break;
  2537. case ANIMCHANNEL_LEGS :
  2538. legsAnim.Disable();
  2539. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2540. break;
  2541. default:
  2542. gameLocal.Error( "Unknown anim group" );
  2543. break;
  2544. }
  2545. }
  2546. /*
  2547. ===============
  2548. idActor::Event_EnableAnim
  2549. ===============
  2550. */
  2551. void idActor::Event_EnableAnim( int channel, int blendFrames ) {
  2552. switch( channel ) {
  2553. case ANIMCHANNEL_HEAD :
  2554. headAnim.Enable( blendFrames );
  2555. break;
  2556. case ANIMCHANNEL_TORSO :
  2557. torsoAnim.Enable( blendFrames );
  2558. break;
  2559. case ANIMCHANNEL_LEGS :
  2560. legsAnim.Enable( blendFrames );
  2561. break;
  2562. default:
  2563. gameLocal.Error( "Unknown anim group" );
  2564. break;
  2565. }
  2566. }
  2567. /*
  2568. ===============
  2569. idActor::Event_SetBlendFrames
  2570. ===============
  2571. */
  2572. void idActor::Event_SetBlendFrames( int channel, int blendFrames ) {
  2573. switch( channel ) {
  2574. case ANIMCHANNEL_HEAD :
  2575. headAnim.animBlendFrames = blendFrames;
  2576. headAnim.lastAnimBlendFrames = blendFrames;
  2577. break;
  2578. case ANIMCHANNEL_TORSO :
  2579. torsoAnim.animBlendFrames = blendFrames;
  2580. torsoAnim.lastAnimBlendFrames = blendFrames;
  2581. break;
  2582. case ANIMCHANNEL_LEGS :
  2583. legsAnim.animBlendFrames = blendFrames;
  2584. legsAnim.lastAnimBlendFrames = blendFrames;
  2585. break;
  2586. default:
  2587. gameLocal.Error( "Unknown anim group" );
  2588. break;
  2589. }
  2590. }
  2591. /*
  2592. ===============
  2593. idActor::Event_GetBlendFrames
  2594. ===============
  2595. */
  2596. void idActor::Event_GetBlendFrames( int channel ) {
  2597. switch( channel ) {
  2598. case ANIMCHANNEL_HEAD :
  2599. idThread::ReturnInt( headAnim.animBlendFrames );
  2600. break;
  2601. case ANIMCHANNEL_TORSO :
  2602. idThread::ReturnInt( torsoAnim.animBlendFrames );
  2603. break;
  2604. case ANIMCHANNEL_LEGS :
  2605. idThread::ReturnInt( legsAnim.animBlendFrames );
  2606. break;
  2607. default:
  2608. gameLocal.Error( "Unknown anim group" );
  2609. break;
  2610. }
  2611. }
  2612. /*
  2613. ===============
  2614. idActor::Event_AnimState
  2615. ===============
  2616. */
  2617. void idActor::Event_AnimState( int channel, const char *statename, int blendFrames ) {
  2618. SetAnimState( channel, statename, blendFrames );
  2619. }
  2620. /*
  2621. ===============
  2622. idActor::Event_GetAnimState
  2623. ===============
  2624. */
  2625. void idActor::Event_GetAnimState( int channel ) {
  2626. const char *state;
  2627. state = GetAnimState( channel );
  2628. idThread::ReturnString( state );
  2629. }
  2630. /*
  2631. ===============
  2632. idActor::Event_InAnimState
  2633. ===============
  2634. */
  2635. void idActor::Event_InAnimState( int channel, const char *statename ) {
  2636. bool instate;
  2637. instate = InAnimState( channel, statename );
  2638. idThread::ReturnInt( instate );
  2639. }
  2640. /*
  2641. ===============
  2642. idActor::Event_FinishAction
  2643. ===============
  2644. */
  2645. void idActor::Event_FinishAction( const char *actionname ) {
  2646. if ( waitState == actionname ) {
  2647. SetWaitState( "" );
  2648. }
  2649. }
  2650. /*
  2651. ===============
  2652. idActor::Event_AnimDone
  2653. ===============
  2654. */
  2655. void idActor::Event_AnimDone( int channel, int blendFrames ) {
  2656. bool result;
  2657. switch( channel ) {
  2658. case ANIMCHANNEL_HEAD :
  2659. result = headAnim.AnimDone( blendFrames );
  2660. idThread::ReturnInt( result );
  2661. break;
  2662. case ANIMCHANNEL_TORSO :
  2663. result = torsoAnim.AnimDone( blendFrames );
  2664. idThread::ReturnInt( result );
  2665. break;
  2666. case ANIMCHANNEL_LEGS :
  2667. result = legsAnim.AnimDone( blendFrames );
  2668. idThread::ReturnInt( result );
  2669. break;
  2670. default:
  2671. gameLocal.Error( "Unknown anim group" );
  2672. }
  2673. }
  2674. /*
  2675. ================
  2676. idActor::Event_HasAnim
  2677. ================
  2678. */
  2679. void idActor::Event_HasAnim( int channel, const char *animname ) {
  2680. if ( GetAnim( channel, animname ) != NULL ) {
  2681. idThread::ReturnFloat( 1.0f );
  2682. } else {
  2683. idThread::ReturnFloat( 0.0f );
  2684. }
  2685. }
  2686. /*
  2687. ================
  2688. idActor::Event_CheckAnim
  2689. ================
  2690. */
  2691. void idActor::Event_CheckAnim( int channel, const char *animname ) {
  2692. if ( !GetAnim( channel, animname ) ) {
  2693. if ( animPrefix.Length() ) {
  2694. gameLocal.Error( "Can't find anim '%s_%s' for '%s'", animPrefix.c_str(), animname, name.c_str() );
  2695. } else {
  2696. gameLocal.Error( "Can't find anim '%s' for '%s'", animname, name.c_str() );
  2697. }
  2698. }
  2699. }
  2700. /*
  2701. ================
  2702. idActor::Event_ChooseAnim
  2703. ================
  2704. */
  2705. void idActor::Event_ChooseAnim( int channel, const char *animname ) {
  2706. int anim;
  2707. anim = GetAnim( channel, animname );
  2708. if ( anim ) {
  2709. if ( channel == ANIMCHANNEL_HEAD ) {
  2710. if ( head.GetEntity() ) {
  2711. idThread::ReturnString( head.GetEntity()->GetAnimator()->AnimFullName( anim ) );
  2712. return;
  2713. }
  2714. } else {
  2715. idThread::ReturnString( animator.AnimFullName( anim ) );
  2716. return;
  2717. }
  2718. }
  2719. idThread::ReturnString( "" );
  2720. }
  2721. /*
  2722. ================
  2723. idActor::Event_AnimLength
  2724. ================
  2725. */
  2726. void idActor::Event_AnimLength( int channel, const char *animname ) {
  2727. int anim;
  2728. anim = GetAnim( channel, animname );
  2729. if ( anim ) {
  2730. if ( channel == ANIMCHANNEL_HEAD ) {
  2731. if ( head.GetEntity() ) {
  2732. idThread::ReturnFloat( MS2SEC( head.GetEntity()->GetAnimator()->AnimLength( anim ) ) );
  2733. return;
  2734. }
  2735. } else {
  2736. idThread::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
  2737. return;
  2738. }
  2739. }
  2740. idThread::ReturnFloat( 0.0f );
  2741. }
  2742. /*
  2743. ================
  2744. idActor::Event_AnimDistance
  2745. ================
  2746. */
  2747. void idActor::Event_AnimDistance( int channel, const char *animname ) {
  2748. int anim;
  2749. anim = GetAnim( channel, animname );
  2750. if ( anim ) {
  2751. if ( channel == ANIMCHANNEL_HEAD ) {
  2752. if ( head.GetEntity() ) {
  2753. idThread::ReturnFloat( head.GetEntity()->GetAnimator()->TotalMovementDelta( anim ).Length() );
  2754. return;
  2755. }
  2756. } else {
  2757. idThread::ReturnFloat( animator.TotalMovementDelta( anim ).Length() );
  2758. return;
  2759. }
  2760. }
  2761. idThread::ReturnFloat( 0.0f );
  2762. }
  2763. /*
  2764. ================
  2765. idActor::Event_HasEnemies
  2766. ================
  2767. */
  2768. void idActor::Event_HasEnemies( void ) {
  2769. bool hasEnemy;
  2770. hasEnemy = HasEnemies();
  2771. idThread::ReturnInt( hasEnemy );
  2772. }
  2773. /*
  2774. ================
  2775. idActor::Event_NextEnemy
  2776. ================
  2777. */
  2778. void idActor::Event_NextEnemy( idEntity *ent ) {
  2779. idActor *actor;
  2780. if ( !ent || ( ent == this ) ) {
  2781. actor = enemyList.Next();
  2782. } else {
  2783. if ( !ent->IsType( idActor::Type ) ) {
  2784. gameLocal.Error( "'%s' cannot be an enemy", ent->name.c_str() );
  2785. }
  2786. actor = static_cast<idActor *>( ent );
  2787. if ( actor->enemyNode.ListHead() != &enemyList ) {
  2788. gameLocal.Error( "'%s' is not in '%s' enemy list", actor->name.c_str(), name.c_str() );
  2789. }
  2790. }
  2791. for( ; actor != NULL; actor = actor->enemyNode.Next() ) {
  2792. if ( !actor->fl.hidden ) {
  2793. idThread::ReturnEntity( actor );
  2794. return;
  2795. }
  2796. }
  2797. idThread::ReturnEntity( NULL );
  2798. }
  2799. /*
  2800. ================
  2801. idActor::Event_ClosestEnemyToPoint
  2802. ================
  2803. */
  2804. void idActor::Event_ClosestEnemyToPoint( const idVec3 &pos ) {
  2805. idActor *bestEnt = ClosestEnemyToPoint( pos );
  2806. idThread::ReturnEntity( bestEnt );
  2807. }
  2808. /*
  2809. ================
  2810. idActor::Event_StopSound
  2811. ================
  2812. */
  2813. void idActor::Event_StopSound( int channel, int netSync ) {
  2814. if ( channel == SND_CHANNEL_VOICE ) {
  2815. idEntity *headEnt = head.GetEntity();
  2816. if ( headEnt ) {
  2817. headEnt->StopSound( channel, ( netSync != 0 ) );
  2818. }
  2819. }
  2820. StopSound( channel, ( netSync != 0 ) );
  2821. }
  2822. /*
  2823. =====================
  2824. idActor::Event_SetNextState
  2825. =====================
  2826. */
  2827. void idActor::Event_SetNextState( const char *name ) {
  2828. idealState = GetScriptFunction( name );
  2829. if ( idealState == state ) {
  2830. state = NULL;
  2831. }
  2832. }
  2833. /*
  2834. =====================
  2835. idActor::Event_SetState
  2836. =====================
  2837. */
  2838. void idActor::Event_SetState( const char *name ) {
  2839. idealState = GetScriptFunction( name );
  2840. if ( idealState == state ) {
  2841. state = NULL;
  2842. }
  2843. scriptThread->DoneProcessing();
  2844. }
  2845. /*
  2846. =====================
  2847. idActor::Event_GetState
  2848. =====================
  2849. */
  2850. void idActor::Event_GetState( void ) {
  2851. if ( state ) {
  2852. idThread::ReturnString( state->Name() );
  2853. } else {
  2854. idThread::ReturnString( "" );
  2855. }
  2856. }
  2857. /*
  2858. =====================
  2859. idActor::Event_GetHead
  2860. =====================
  2861. */
  2862. void idActor::Event_GetHead( void ) {
  2863. idThread::ReturnEntity( head.GetEntity() );
  2864. }
  2865. #ifdef _D3XP
  2866. /*
  2867. ================
  2868. idActor::Event_SetDamageGroupScale
  2869. ================
  2870. */
  2871. void idActor::Event_SetDamageGroupScale( const char* groupName, float scale) {
  2872. for( int i = 0; i < damageScale.Num(); i++ ) {
  2873. if ( damageGroups[ i ] == groupName ) {
  2874. damageScale[ i ] = scale;
  2875. }
  2876. }
  2877. }
  2878. /*
  2879. ================
  2880. idActor::Event_SetDamageGroupScaleAll
  2881. ================
  2882. */
  2883. void idActor::Event_SetDamageGroupScaleAll( float scale ) {
  2884. for( int i = 0; i < damageScale.Num(); i++ ) {
  2885. damageScale[ i ] = scale;
  2886. }
  2887. }
  2888. void idActor::Event_GetDamageGroupScale( const char* groupName ) {
  2889. for( int i = 0; i < damageScale.Num(); i++ ) {
  2890. if ( damageGroups[ i ] == groupName ) {
  2891. idThread::ReturnFloat(damageScale[i]);
  2892. return;
  2893. }
  2894. }
  2895. idThread::ReturnFloat(0);
  2896. }
  2897. void idActor::Event_SetDamageCap( float _damageCap ) {
  2898. damageCap = _damageCap;
  2899. }
  2900. void idActor::Event_SetWaitState( const char* waitState) {
  2901. SetWaitState(waitState);
  2902. }
  2903. void idActor::Event_GetWaitState() {
  2904. if(WaitState()) {
  2905. idThread::ReturnString(WaitState());
  2906. } else {
  2907. idThread::ReturnString("");
  2908. }
  2909. }
  2910. #endif