Actor.cpp 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401
  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. FinishSetup();
  539. }
  540. /*
  541. ================
  542. idActor::FinishSetup
  543. ================
  544. */
  545. void idActor::FinishSetup( void ) {
  546. const char *scriptObjectName;
  547. // setup script object
  548. if ( spawnArgs.GetString( "scriptobject", NULL, &scriptObjectName ) ) {
  549. if ( !scriptObject.SetType( scriptObjectName ) ) {
  550. gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
  551. }
  552. ConstructScriptObject();
  553. }
  554. SetupBody();
  555. }
  556. /*
  557. ================
  558. idActor::SetupHead
  559. ================
  560. */
  561. void idActor::SetupHead( void ) {
  562. idAFAttachment *headEnt;
  563. idStr jointName;
  564. const char *headModel;
  565. jointHandle_t joint;
  566. jointHandle_t damageJoint;
  567. int i;
  568. const idKeyValue *sndKV;
  569. if ( gameLocal.isClient ) {
  570. return;
  571. }
  572. headModel = spawnArgs.GetString( "def_head", "" );
  573. if ( headModel[ 0 ] ) {
  574. jointName = spawnArgs.GetString( "head_joint" );
  575. joint = animator.GetJointHandle( jointName );
  576. if ( joint == INVALID_JOINT ) {
  577. gameLocal.Error( "Joint '%s' not found for 'head_joint' on '%s'", jointName.c_str(), name.c_str() );
  578. }
  579. // set the damage joint to be part of the head damage group
  580. damageJoint = joint;
  581. for( i = 0; i < damageGroups.Num(); i++ ) {
  582. if ( damageGroups[ i ] == "head" ) {
  583. damageJoint = static_cast<jointHandle_t>( i );
  584. break;
  585. }
  586. }
  587. // copy any sounds in case we have frame commands on the head
  588. idDict args;
  589. sndKV = spawnArgs.MatchPrefix( "snd_", NULL );
  590. while( sndKV ) {
  591. args.Set( sndKV->GetKey(), sndKV->GetValue() );
  592. sndKV = spawnArgs.MatchPrefix( "snd_", sndKV );
  593. }
  594. #ifdef _D3XP
  595. // copy slowmo param to the head
  596. args.SetBool( "slowmo", spawnArgs.GetBool("slowmo", "1") );
  597. #endif
  598. headEnt = static_cast<idAFAttachment *>( gameLocal.SpawnEntityType( idAFAttachment::Type, &args ) );
  599. headEnt->SetName( va( "%s_head", name.c_str() ) );
  600. headEnt->SetBody( this, headModel, damageJoint );
  601. head = headEnt;
  602. #ifdef _D3XP
  603. idStr xSkin;
  604. if ( spawnArgs.GetString( "skin_head_xray", "", xSkin ) ) {
  605. headEnt->xraySkin = declManager->FindSkin( xSkin.c_str() );
  606. headEnt->UpdateModel();
  607. }
  608. #endif
  609. idVec3 origin;
  610. idMat3 axis;
  611. idAttachInfo &attach = attachments.Alloc();
  612. attach.channel = animator.GetChannelForJoint( joint );
  613. animator.GetJointTransform( joint, gameLocal.time, origin, axis );
  614. origin = renderEntity.origin + ( origin + modelOffset ) * renderEntity.axis;
  615. attach.ent = headEnt;
  616. headEnt->SetOrigin( origin );
  617. headEnt->SetAxis( renderEntity.axis );
  618. headEnt->BindToJoint( this, joint, true );
  619. }
  620. }
  621. /*
  622. ================
  623. idActor::CopyJointsFromBodyToHead
  624. ================
  625. */
  626. void idActor::CopyJointsFromBodyToHead( void ) {
  627. idEntity *headEnt = head.GetEntity();
  628. idAnimator *headAnimator;
  629. int i;
  630. idMat3 mat;
  631. idMat3 axis;
  632. idVec3 pos;
  633. if ( !headEnt ) {
  634. return;
  635. }
  636. headAnimator = headEnt->GetAnimator();
  637. // copy the animation from the body to the head
  638. for( i = 0; i < copyJoints.Num(); i++ ) {
  639. if ( copyJoints[ i ].mod == JOINTMOD_WORLD_OVERRIDE ) {
  640. mat = headEnt->GetPhysics()->GetAxis().Transpose();
  641. GetJointWorldTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
  642. pos -= headEnt->GetPhysics()->GetOrigin();
  643. headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos * mat );
  644. headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis * mat );
  645. } else {
  646. animator.GetJointLocalTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
  647. headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos );
  648. headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis );
  649. }
  650. }
  651. }
  652. /*
  653. ================
  654. idActor::Restart
  655. ================
  656. */
  657. void idActor::Restart( void ) {
  658. assert( !head.GetEntity() );
  659. SetupHead();
  660. FinishSetup();
  661. }
  662. /*
  663. ================
  664. idActor::Save
  665. archive object for savegame file
  666. ================
  667. */
  668. void idActor::Save( idSaveGame *savefile ) const {
  669. idActor *ent;
  670. int i;
  671. savefile->WriteInt( team );
  672. savefile->WriteInt( rank );
  673. savefile->WriteMat3( viewAxis );
  674. savefile->WriteInt( enemyList.Num() );
  675. for ( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  676. savefile->WriteObject( ent );
  677. }
  678. savefile->WriteFloat( fovDot );
  679. savefile->WriteVec3( eyeOffset );
  680. savefile->WriteVec3( modelOffset );
  681. savefile->WriteAngles( deltaViewAngles );
  682. savefile->WriteInt( pain_debounce_time );
  683. savefile->WriteInt( pain_delay );
  684. savefile->WriteInt( pain_threshold );
  685. savefile->WriteInt( damageGroups.Num() );
  686. for( i = 0; i < damageGroups.Num(); i++ ) {
  687. savefile->WriteString( damageGroups[ i ] );
  688. }
  689. savefile->WriteInt( damageScale.Num() );
  690. for( i = 0; i < damageScale.Num(); i++ ) {
  691. savefile->WriteFloat( damageScale[ i ] );
  692. }
  693. savefile->WriteBool( use_combat_bbox );
  694. head.Save( savefile );
  695. savefile->WriteInt( copyJoints.Num() );
  696. for( i = 0; i < copyJoints.Num(); i++ ) {
  697. savefile->WriteInt( copyJoints[i].mod );
  698. savefile->WriteJoint( copyJoints[i].from );
  699. savefile->WriteJoint( copyJoints[i].to );
  700. }
  701. savefile->WriteJoint( leftEyeJoint );
  702. savefile->WriteJoint( rightEyeJoint );
  703. savefile->WriteJoint( soundJoint );
  704. walkIK.Save( savefile );
  705. savefile->WriteString( animPrefix );
  706. savefile->WriteString( painAnim );
  707. savefile->WriteInt( blink_anim );
  708. savefile->WriteInt( blink_time );
  709. savefile->WriteInt( blink_min );
  710. savefile->WriteInt( blink_max );
  711. // script variables
  712. savefile->WriteObject( scriptThread );
  713. savefile->WriteString( waitState );
  714. headAnim.Save( savefile );
  715. torsoAnim.Save( savefile );
  716. legsAnim.Save( savefile );
  717. savefile->WriteBool( allowPain );
  718. savefile->WriteBool( allowEyeFocus );
  719. savefile->WriteInt( painTime );
  720. savefile->WriteInt( attachments.Num() );
  721. for ( i = 0; i < attachments.Num(); i++ ) {
  722. attachments[i].ent.Save( savefile );
  723. savefile->WriteInt( attachments[i].channel );
  724. }
  725. savefile->WriteBool( finalBoss );
  726. idToken token;
  727. //FIXME: this is unneccesary
  728. if ( state ) {
  729. idLexer src( state->Name(), idStr::Length( state->Name() ), "idAI::Save" );
  730. src.ReadTokenOnLine( &token );
  731. src.ExpectTokenString( "::" );
  732. src.ReadTokenOnLine( &token );
  733. savefile->WriteString( token );
  734. } else {
  735. savefile->WriteString( "" );
  736. }
  737. if ( idealState ) {
  738. idLexer src( idealState->Name(), idStr::Length( idealState->Name() ), "idAI::Save" );
  739. src.ReadTokenOnLine( &token );
  740. src.ExpectTokenString( "::" );
  741. src.ReadTokenOnLine( &token );
  742. savefile->WriteString( token );
  743. } else {
  744. savefile->WriteString( "" );
  745. }
  746. #ifdef _D3XP
  747. savefile->WriteInt(damageCap);
  748. #endif
  749. }
  750. /*
  751. ================
  752. idActor::Restore
  753. unarchives object from save game file
  754. ================
  755. */
  756. void idActor::Restore( idRestoreGame *savefile ) {
  757. int i, num;
  758. idActor *ent;
  759. savefile->ReadInt( team );
  760. savefile->ReadInt( rank );
  761. savefile->ReadMat3( viewAxis );
  762. savefile->ReadInt( num );
  763. for ( i = 0; i < num; i++ ) {
  764. savefile->ReadObject( reinterpret_cast<idClass *&>( ent ) );
  765. assert( ent );
  766. if ( ent ) {
  767. ent->enemyNode.AddToEnd( enemyList );
  768. }
  769. }
  770. savefile->ReadFloat( fovDot );
  771. savefile->ReadVec3( eyeOffset );
  772. savefile->ReadVec3( modelOffset );
  773. savefile->ReadAngles( deltaViewAngles );
  774. savefile->ReadInt( pain_debounce_time );
  775. savefile->ReadInt( pain_delay );
  776. savefile->ReadInt( pain_threshold );
  777. savefile->ReadInt( num );
  778. damageGroups.SetGranularity( 1 );
  779. damageGroups.SetNum( num );
  780. for( i = 0; i < num; i++ ) {
  781. savefile->ReadString( damageGroups[ i ] );
  782. }
  783. savefile->ReadInt( num );
  784. damageScale.SetNum( num );
  785. for( i = 0; i < num; i++ ) {
  786. savefile->ReadFloat( damageScale[ i ] );
  787. }
  788. savefile->ReadBool( use_combat_bbox );
  789. head.Restore( savefile );
  790. savefile->ReadInt( num );
  791. copyJoints.SetNum( num );
  792. for( i = 0; i < num; i++ ) {
  793. int val;
  794. savefile->ReadInt( val );
  795. copyJoints[i].mod = static_cast<jointModTransform_t>( val );
  796. savefile->ReadJoint( copyJoints[i].from );
  797. savefile->ReadJoint( copyJoints[i].to );
  798. }
  799. savefile->ReadJoint( leftEyeJoint );
  800. savefile->ReadJoint( rightEyeJoint );
  801. savefile->ReadJoint( soundJoint );
  802. walkIK.Restore( savefile );
  803. savefile->ReadString( animPrefix );
  804. savefile->ReadString( painAnim );
  805. savefile->ReadInt( blink_anim );
  806. savefile->ReadInt( blink_time );
  807. savefile->ReadInt( blink_min );
  808. savefile->ReadInt( blink_max );
  809. savefile->ReadObject( reinterpret_cast<idClass *&>( scriptThread ) );
  810. savefile->ReadString( waitState );
  811. headAnim.Restore( savefile );
  812. torsoAnim.Restore( savefile );
  813. legsAnim.Restore( savefile );
  814. savefile->ReadBool( allowPain );
  815. savefile->ReadBool( allowEyeFocus );
  816. savefile->ReadInt( painTime );
  817. savefile->ReadInt( num );
  818. for ( i = 0; i < num; i++ ) {
  819. idAttachInfo &attach = attachments.Alloc();
  820. attach.ent.Restore( savefile );
  821. savefile->ReadInt( attach.channel );
  822. }
  823. savefile->ReadBool( finalBoss );
  824. idStr statename;
  825. savefile->ReadString( statename );
  826. if ( statename.Length() > 0 ) {
  827. state = GetScriptFunction( statename );
  828. }
  829. savefile->ReadString( statename );
  830. if ( statename.Length() > 0 ) {
  831. idealState = GetScriptFunction( statename );
  832. }
  833. #ifdef _D3XP
  834. savefile->ReadInt(damageCap);
  835. #endif
  836. }
  837. /*
  838. ================
  839. idActor::Hide
  840. ================
  841. */
  842. void idActor::Hide( void ) {
  843. idEntity *ent;
  844. idEntity *next;
  845. idAFEntity_Base::Hide();
  846. if ( head.GetEntity() ) {
  847. head.GetEntity()->Hide();
  848. }
  849. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  850. next = ent->GetNextTeamEntity();
  851. if ( ent->GetBindMaster() == this ) {
  852. ent->Hide();
  853. if ( ent->IsType( idLight::Type ) ) {
  854. static_cast<idLight *>( ent )->Off();
  855. }
  856. }
  857. }
  858. UnlinkCombat();
  859. }
  860. /*
  861. ================
  862. idActor::Show
  863. ================
  864. */
  865. void idActor::Show( void ) {
  866. idEntity *ent;
  867. idEntity *next;
  868. idAFEntity_Base::Show();
  869. if ( head.GetEntity() ) {
  870. head.GetEntity()->Show();
  871. }
  872. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  873. next = ent->GetNextTeamEntity();
  874. if ( ent->GetBindMaster() == this ) {
  875. ent->Show();
  876. if ( ent->IsType( idLight::Type ) ) {
  877. #ifdef _D3XP
  878. if(!spawnArgs.GetBool("lights_off", "0")) {
  879. static_cast<idLight *>( ent )->On();
  880. }
  881. #endif
  882. }
  883. }
  884. }
  885. LinkCombat();
  886. }
  887. /*
  888. ==============
  889. idActor::GetDefaultSurfaceType
  890. ==============
  891. */
  892. int idActor::GetDefaultSurfaceType( void ) const {
  893. return SURFTYPE_FLESH;
  894. }
  895. /*
  896. ================
  897. idActor::ProjectOverlay
  898. ================
  899. */
  900. void idActor::ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ) {
  901. idEntity *ent;
  902. idEntity *next;
  903. idEntity::ProjectOverlay( origin, dir, size, material );
  904. for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
  905. next = ent->GetNextTeamEntity();
  906. if ( ent->GetBindMaster() == this ) {
  907. if ( ent->fl.takedamage && ent->spawnArgs.GetBool( "bleed" ) ) {
  908. ent->ProjectOverlay( origin, dir, size, material );
  909. }
  910. }
  911. }
  912. }
  913. /*
  914. ================
  915. idActor::LoadAF
  916. ================
  917. */
  918. bool idActor::LoadAF( void ) {
  919. idStr fileName;
  920. if ( !spawnArgs.GetString( "ragdoll", "*unknown*", fileName ) || !fileName.Length() ) {
  921. return false;
  922. }
  923. af.SetAnimator( GetAnimator() );
  924. return af.Load( this, fileName );
  925. }
  926. /*
  927. =====================
  928. idActor::SetupBody
  929. =====================
  930. */
  931. void idActor::SetupBody( void ) {
  932. const char *jointname;
  933. animator.ClearAllAnims( gameLocal.time, 0 );
  934. animator.ClearAllJoints();
  935. idEntity *headEnt = head.GetEntity();
  936. if ( headEnt ) {
  937. jointname = spawnArgs.GetString( "bone_leftEye" );
  938. leftEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
  939. jointname = spawnArgs.GetString( "bone_rightEye" );
  940. rightEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
  941. // set up the eye height. check if it's specified in the def.
  942. if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
  943. // if not in the def, then try to base it off the idle animation
  944. int anim = headEnt->GetAnimator()->GetAnim( "idle" );
  945. if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
  946. idVec3 pos;
  947. idMat3 axis;
  948. headEnt->GetAnimator()->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, 0 );
  949. headEnt->GetAnimator()->GetJointTransform( leftEyeJoint, gameLocal.time, pos, axis );
  950. headEnt->GetAnimator()->ClearAllAnims( gameLocal.time, 0 );
  951. headEnt->GetAnimator()->ForceUpdate();
  952. pos += headEnt->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  953. eyeOffset = pos + modelOffset;
  954. } else {
  955. // just base it off the bounding box size
  956. eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
  957. }
  958. }
  959. headAnim.Init( this, headEnt->GetAnimator(), ANIMCHANNEL_ALL );
  960. } else {
  961. jointname = spawnArgs.GetString( "bone_leftEye" );
  962. leftEyeJoint = animator.GetJointHandle( jointname );
  963. jointname = spawnArgs.GetString( "bone_rightEye" );
  964. rightEyeJoint = animator.GetJointHandle( jointname );
  965. // set up the eye height. check if it's specified in the def.
  966. if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
  967. // if not in the def, then try to base it off the idle animation
  968. int anim = animator.GetAnim( "idle" );
  969. if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
  970. idVec3 pos;
  971. idMat3 axis;
  972. animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, 0 );
  973. animator.GetJointTransform( leftEyeJoint, gameLocal.time, pos, axis );
  974. animator.ClearAllAnims( gameLocal.time, 0 );
  975. animator.ForceUpdate();
  976. eyeOffset = pos + modelOffset;
  977. } else {
  978. // just base it off the bounding box size
  979. eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
  980. }
  981. }
  982. headAnim.Init( this, &animator, ANIMCHANNEL_HEAD );
  983. }
  984. waitState = "";
  985. torsoAnim.Init( this, &animator, ANIMCHANNEL_TORSO );
  986. legsAnim.Init( this, &animator, ANIMCHANNEL_LEGS );
  987. }
  988. /*
  989. =====================
  990. idActor::CheckBlink
  991. =====================
  992. */
  993. void idActor::CheckBlink( void ) {
  994. // check if it's time to blink
  995. if ( !blink_anim || ( health <= 0 ) || !allowEyeFocus || ( blink_time > gameLocal.time ) ) {
  996. return;
  997. }
  998. idEntity *headEnt = head.GetEntity();
  999. if ( headEnt ) {
  1000. headEnt->GetAnimator()->PlayAnim( ANIMCHANNEL_EYELIDS, blink_anim, gameLocal.time, 1 );
  1001. } else {
  1002. animator.PlayAnim( ANIMCHANNEL_EYELIDS, blink_anim, gameLocal.time, 1 );
  1003. }
  1004. // set the next blink time
  1005. blink_time = gameLocal.time + blink_min + gameLocal.random.RandomFloat() * ( blink_max - blink_min );
  1006. }
  1007. /*
  1008. ================
  1009. idActor::GetPhysicsToVisualTransform
  1010. ================
  1011. */
  1012. bool idActor::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
  1013. if ( af.IsActive() ) {
  1014. af.GetPhysicsToVisualTransform( origin, axis );
  1015. return true;
  1016. }
  1017. origin = modelOffset;
  1018. axis = viewAxis;
  1019. return true;
  1020. }
  1021. /*
  1022. ================
  1023. idActor::GetPhysicsToSoundTransform
  1024. ================
  1025. */
  1026. bool idActor::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  1027. if ( soundJoint != INVALID_JOINT ) {
  1028. animator.GetJointTransform( soundJoint, gameLocal.time, origin, axis );
  1029. origin += modelOffset;
  1030. axis = viewAxis;
  1031. } else {
  1032. origin = GetPhysics()->GetGravityNormal() * -eyeOffset.z;
  1033. axis.Identity();
  1034. }
  1035. return true;
  1036. }
  1037. /***********************************************************************
  1038. script state management
  1039. ***********************************************************************/
  1040. /*
  1041. ================
  1042. idActor::ShutdownThreads
  1043. ================
  1044. */
  1045. void idActor::ShutdownThreads( void ) {
  1046. headAnim.Shutdown();
  1047. torsoAnim.Shutdown();
  1048. legsAnim.Shutdown();
  1049. if ( scriptThread ) {
  1050. scriptThread->EndThread();
  1051. scriptThread->PostEventMS( &EV_Remove, 0 );
  1052. delete scriptThread;
  1053. scriptThread = NULL;
  1054. }
  1055. }
  1056. /*
  1057. ================
  1058. idActor::ShouldConstructScriptObjectAtSpawn
  1059. Called during idEntity::Spawn to see if it should construct the script object or not.
  1060. Overridden by subclasses that need to spawn the script object themselves.
  1061. ================
  1062. */
  1063. bool idActor::ShouldConstructScriptObjectAtSpawn( void ) const {
  1064. return false;
  1065. }
  1066. /*
  1067. ================
  1068. idActor::ConstructScriptObject
  1069. Called during idEntity::Spawn. Calls the constructor on the script object.
  1070. Can be overridden by subclasses when a thread doesn't need to be allocated.
  1071. ================
  1072. */
  1073. idThread *idActor::ConstructScriptObject( void ) {
  1074. const function_t *constructor;
  1075. // make sure we have a scriptObject
  1076. if ( !scriptObject.HasObject() ) {
  1077. gameLocal.Error( "No scriptobject set on '%s'. Check the '%s' entityDef.", name.c_str(), GetEntityDefName() );
  1078. }
  1079. if ( !scriptThread ) {
  1080. // create script thread
  1081. scriptThread = new idThread();
  1082. scriptThread->ManualDelete();
  1083. scriptThread->ManualControl();
  1084. scriptThread->SetThreadName( name.c_str() );
  1085. } else {
  1086. scriptThread->EndThread();
  1087. }
  1088. // call script object's constructor
  1089. constructor = scriptObject.GetConstructor();
  1090. if ( !constructor ) {
  1091. gameLocal.Error( "Missing constructor on '%s' for entity '%s'", scriptObject.GetTypeName(), name.c_str() );
  1092. }
  1093. // init the script object's data
  1094. scriptObject.ClearObject();
  1095. // just set the current function on the script. we'll execute in the subclasses.
  1096. scriptThread->CallFunction( this, constructor, true );
  1097. return scriptThread;
  1098. }
  1099. /*
  1100. =====================
  1101. idActor::GetScriptFunction
  1102. =====================
  1103. */
  1104. const function_t *idActor::GetScriptFunction( const char *funcname ) {
  1105. const function_t *func;
  1106. func = scriptObject.GetFunction( funcname );
  1107. if ( !func ) {
  1108. scriptThread->Error( "Unknown function '%s' in '%s'", funcname, scriptObject.GetTypeName() );
  1109. }
  1110. return func;
  1111. }
  1112. /*
  1113. =====================
  1114. idActor::SetState
  1115. =====================
  1116. */
  1117. void idActor::SetState( const function_t *newState ) {
  1118. if ( !newState ) {
  1119. gameLocal.Error( "idActor::SetState: Null state" );
  1120. }
  1121. if ( ai_debugScript.GetInteger() == entityNumber ) {
  1122. gameLocal.Printf( "%d: %s: State: %s\n", gameLocal.time, name.c_str(), newState->Name() );
  1123. }
  1124. state = newState;
  1125. idealState = state;
  1126. scriptThread->CallFunction( this, state, true );
  1127. }
  1128. /*
  1129. =====================
  1130. idActor::SetState
  1131. =====================
  1132. */
  1133. void idActor::SetState( const char *statename ) {
  1134. const function_t *newState;
  1135. newState = GetScriptFunction( statename );
  1136. SetState( newState );
  1137. }
  1138. /*
  1139. =====================
  1140. idActor::UpdateScript
  1141. =====================
  1142. */
  1143. void idActor::UpdateScript( void ) {
  1144. int i;
  1145. if ( ai_debugScript.GetInteger() == entityNumber ) {
  1146. scriptThread->EnableDebugInfo();
  1147. } else {
  1148. scriptThread->DisableDebugInfo();
  1149. }
  1150. // a series of state changes can happen in a single frame.
  1151. // this loop limits them in case we've entered an infinite loop.
  1152. for( i = 0; i < 20; i++ ) {
  1153. if ( idealState != state ) {
  1154. SetState( idealState );
  1155. }
  1156. // don't call script until it's done waiting
  1157. if ( scriptThread->IsWaiting() ) {
  1158. break;
  1159. }
  1160. scriptThread->Execute();
  1161. if ( idealState == state ) {
  1162. break;
  1163. }
  1164. }
  1165. if ( i == 20 ) {
  1166. scriptThread->Warning( "idActor::UpdateScript: exited loop to prevent lockup" );
  1167. }
  1168. }
  1169. /***********************************************************************
  1170. vision
  1171. ***********************************************************************/
  1172. /*
  1173. =====================
  1174. idActor::setFov
  1175. =====================
  1176. */
  1177. void idActor::SetFOV( float fov ) {
  1178. fovDot = (float)cos( DEG2RAD( fov * 0.5f ) );
  1179. }
  1180. /*
  1181. =====================
  1182. idActor::SetEyeHeight
  1183. =====================
  1184. */
  1185. void idActor::SetEyeHeight( float height ) {
  1186. eyeOffset.z = height;
  1187. }
  1188. /*
  1189. =====================
  1190. idActor::EyeHeight
  1191. =====================
  1192. */
  1193. float idActor::EyeHeight( void ) const {
  1194. return eyeOffset.z;
  1195. }
  1196. /*
  1197. =====================
  1198. idActor::EyeOffset
  1199. =====================
  1200. */
  1201. idVec3 idActor::EyeOffset( void ) const {
  1202. return GetPhysics()->GetGravityNormal() * -eyeOffset.z;
  1203. }
  1204. /*
  1205. =====================
  1206. idActor::GetEyePosition
  1207. =====================
  1208. */
  1209. idVec3 idActor::GetEyePosition( void ) const {
  1210. return GetPhysics()->GetOrigin() + ( GetPhysics()->GetGravityNormal() * -eyeOffset.z );
  1211. }
  1212. /*
  1213. =====================
  1214. idActor::GetViewPos
  1215. =====================
  1216. */
  1217. void idActor::GetViewPos( idVec3 &origin, idMat3 &axis ) const {
  1218. origin = GetEyePosition();
  1219. axis = viewAxis;
  1220. }
  1221. /*
  1222. =====================
  1223. idActor::CheckFOV
  1224. =====================
  1225. */
  1226. bool idActor::CheckFOV( const idVec3 &pos ) const {
  1227. if ( fovDot == 1.0f ) {
  1228. return true;
  1229. }
  1230. float dot;
  1231. idVec3 delta;
  1232. delta = pos - GetEyePosition();
  1233. // get our gravity normal
  1234. const idVec3 &gravityDir = GetPhysics()->GetGravityNormal();
  1235. // infinite vertical vision, so project it onto our orientation plane
  1236. delta -= gravityDir * ( gravityDir * delta );
  1237. delta.Normalize();
  1238. dot = viewAxis[ 0 ] * delta;
  1239. return ( dot >= fovDot );
  1240. }
  1241. /*
  1242. =====================
  1243. idActor::CanSee
  1244. =====================
  1245. */
  1246. bool idActor::CanSee( idEntity *ent, bool useFov ) const {
  1247. trace_t tr;
  1248. idVec3 eye;
  1249. idVec3 toPos;
  1250. if ( ent->IsHidden() ) {
  1251. return false;
  1252. }
  1253. if ( ent->IsType( idActor::Type ) ) {
  1254. toPos = ( ( idActor * )ent )->GetEyePosition();
  1255. } else {
  1256. toPos = ent->GetPhysics()->GetOrigin();
  1257. }
  1258. if ( useFov && !CheckFOV( toPos ) ) {
  1259. return false;
  1260. }
  1261. eye = GetEyePosition();
  1262. gameLocal.clip.TracePoint( tr, eye, toPos, MASK_OPAQUE, this );
  1263. if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
  1264. return true;
  1265. }
  1266. return false;
  1267. }
  1268. /*
  1269. =====================
  1270. idActor::PointVisible
  1271. =====================
  1272. */
  1273. bool idActor::PointVisible( const idVec3 &point ) const {
  1274. trace_t results;
  1275. idVec3 start, end;
  1276. start = GetEyePosition();
  1277. end = point;
  1278. end[2] += 1.0f;
  1279. gameLocal.clip.TracePoint( results, start, end, MASK_OPAQUE, this );
  1280. return ( results.fraction >= 1.0f );
  1281. }
  1282. /*
  1283. =====================
  1284. idActor::GetAIAimTargets
  1285. Returns positions for the AI to aim at.
  1286. =====================
  1287. */
  1288. void idActor::GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos ) {
  1289. headPos = lastSightPos + EyeOffset();
  1290. chestPos = ( headPos + lastSightPos + GetPhysics()->GetBounds().GetCenter() ) * 0.5f;
  1291. }
  1292. /*
  1293. =====================
  1294. idActor::GetRenderView
  1295. =====================
  1296. */
  1297. renderView_t *idActor::GetRenderView() {
  1298. renderView_t *rv = idEntity::GetRenderView();
  1299. rv->viewaxis = viewAxis;
  1300. rv->vieworg = GetEyePosition();
  1301. return rv;
  1302. }
  1303. /***********************************************************************
  1304. Model/Ragdoll
  1305. ***********************************************************************/
  1306. /*
  1307. ================
  1308. idActor::SetCombatModel
  1309. ================
  1310. */
  1311. void idActor::SetCombatModel( void ) {
  1312. idAFAttachment *headEnt;
  1313. if ( !use_combat_bbox ) {
  1314. if ( combatModel ) {
  1315. combatModel->Unlink();
  1316. combatModel->LoadModel( modelDefHandle );
  1317. } else {
  1318. combatModel = new idClipModel( modelDefHandle );
  1319. }
  1320. headEnt = head.GetEntity();
  1321. if ( headEnt ) {
  1322. headEnt->SetCombatModel();
  1323. }
  1324. }
  1325. }
  1326. /*
  1327. ================
  1328. idActor::GetCombatModel
  1329. ================
  1330. */
  1331. idClipModel *idActor::GetCombatModel( void ) const {
  1332. return combatModel;
  1333. }
  1334. /*
  1335. ================
  1336. idActor::LinkCombat
  1337. ================
  1338. */
  1339. void idActor::LinkCombat( void ) {
  1340. idAFAttachment *headEnt;
  1341. if ( fl.hidden || use_combat_bbox ) {
  1342. return;
  1343. }
  1344. if ( combatModel ) {
  1345. combatModel->Link( gameLocal.clip, this, 0, renderEntity.origin, renderEntity.axis, modelDefHandle );
  1346. }
  1347. headEnt = head.GetEntity();
  1348. if ( headEnt ) {
  1349. headEnt->LinkCombat();
  1350. }
  1351. }
  1352. /*
  1353. ================
  1354. idActor::UnlinkCombat
  1355. ================
  1356. */
  1357. void idActor::UnlinkCombat( void ) {
  1358. idAFAttachment *headEnt;
  1359. if ( combatModel ) {
  1360. combatModel->Unlink();
  1361. }
  1362. headEnt = head.GetEntity();
  1363. if ( headEnt ) {
  1364. headEnt->UnlinkCombat();
  1365. }
  1366. }
  1367. /*
  1368. ================
  1369. idActor::StartRagdoll
  1370. ================
  1371. */
  1372. bool idActor::StartRagdoll( void ) {
  1373. float slomoStart, slomoEnd;
  1374. float jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd;
  1375. float contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd;
  1376. // if no AF loaded
  1377. if ( !af.IsLoaded() ) {
  1378. return false;
  1379. }
  1380. // if the AF is already active
  1381. if ( af.IsActive() ) {
  1382. return true;
  1383. }
  1384. // disable the monster bounding box
  1385. GetPhysics()->DisableClip();
  1386. // start using the AF
  1387. af.StartFromCurrentPose( spawnArgs.GetInt( "velocityTime", "0" ) );
  1388. slomoStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoStart", "-1.6" );
  1389. slomoEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoEnd", "0.8" );
  1390. // do the first part of the death in slow motion
  1391. af.GetPhysics()->SetTimeScaleRamp( slomoStart, slomoEnd );
  1392. jointFrictionDent = spawnArgs.GetFloat( "ragdoll_jointFrictionDent", "0.1" );
  1393. jointFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionStart", "0.2" );
  1394. jointFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionEnd", "1.2" );
  1395. // set joint friction dent
  1396. af.GetPhysics()->SetJointFrictionDent( jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd );
  1397. contactFrictionDent = spawnArgs.GetFloat( "ragdoll_contactFrictionDent", "0.1" );
  1398. contactFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionStart", "1.0" );
  1399. contactFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionEnd", "2.0" );
  1400. // set contact friction dent
  1401. af.GetPhysics()->SetContactFrictionDent( contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd );
  1402. // drop any items the actor is holding
  1403. idMoveableItem::DropItems( this, "death", NULL );
  1404. // drop any articulated figures the actor is holding
  1405. idAFEntity_Base::DropAFs( this, "death", NULL );
  1406. RemoveAttachments();
  1407. return true;
  1408. }
  1409. /*
  1410. ================
  1411. idActor::StopRagdoll
  1412. ================
  1413. */
  1414. void idActor::StopRagdoll( void ) {
  1415. if ( af.IsActive() ) {
  1416. af.Stop();
  1417. }
  1418. }
  1419. /*
  1420. ================
  1421. idActor::UpdateAnimationControllers
  1422. ================
  1423. */
  1424. bool idActor::UpdateAnimationControllers( void ) {
  1425. if ( af.IsActive() ) {
  1426. return idAFEntity_Base::UpdateAnimationControllers();
  1427. } else {
  1428. animator.ClearAFPose();
  1429. }
  1430. if ( walkIK.IsInitialized() ) {
  1431. walkIK.Evaluate();
  1432. return true;
  1433. }
  1434. return false;
  1435. }
  1436. /*
  1437. ================
  1438. idActor::RemoveAttachments
  1439. ================
  1440. */
  1441. void idActor::RemoveAttachments( void ) {
  1442. int i;
  1443. idEntity *ent;
  1444. // remove any attached entities
  1445. for( i = 0; i < attachments.Num(); i++ ) {
  1446. ent = attachments[ i ].ent.GetEntity();
  1447. if ( ent && ent->spawnArgs.GetBool( "remove" ) ) {
  1448. ent->PostEventMS( &EV_Remove, 0 );
  1449. }
  1450. }
  1451. }
  1452. /*
  1453. ================
  1454. idActor::Attach
  1455. ================
  1456. */
  1457. void idActor::Attach( idEntity *ent ) {
  1458. idVec3 origin;
  1459. idMat3 axis;
  1460. jointHandle_t joint;
  1461. idStr jointName;
  1462. idAttachInfo &attach = attachments.Alloc();
  1463. idAngles angleOffset;
  1464. idVec3 originOffset;
  1465. jointName = ent->spawnArgs.GetString( "joint" );
  1466. joint = animator.GetJointHandle( jointName );
  1467. if ( joint == INVALID_JOINT ) {
  1468. gameLocal.Error( "Joint '%s' not found for attaching '%s' on '%s'", jointName.c_str(), ent->GetClassname(), name.c_str() );
  1469. }
  1470. angleOffset = ent->spawnArgs.GetAngles( "angles" );
  1471. originOffset = ent->spawnArgs.GetVector( "origin" );
  1472. attach.channel = animator.GetChannelForJoint( joint );
  1473. GetJointWorldTransform( joint, gameLocal.time, origin, axis );
  1474. attach.ent = ent;
  1475. ent->SetOrigin( origin + originOffset * renderEntity.axis );
  1476. idMat3 rotate = angleOffset.ToMat3();
  1477. idMat3 newAxis = rotate * axis;
  1478. ent->SetAxis( newAxis );
  1479. ent->BindToJoint( this, joint, true );
  1480. ent->cinematic = cinematic;
  1481. }
  1482. /*
  1483. ================
  1484. idActor::Teleport
  1485. ================
  1486. */
  1487. void idActor::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
  1488. GetPhysics()->SetOrigin( origin + idVec3( 0, 0, CM_CLIP_EPSILON ) );
  1489. GetPhysics()->SetLinearVelocity( vec3_origin );
  1490. viewAxis = angles.ToMat3();
  1491. UpdateVisuals();
  1492. if ( !IsHidden() ) {
  1493. // kill anything at the new position
  1494. gameLocal.KillBox( this );
  1495. }
  1496. }
  1497. /*
  1498. ================
  1499. idActor::GetDeltaViewAngles
  1500. ================
  1501. */
  1502. const idAngles &idActor::GetDeltaViewAngles( void ) const {
  1503. return deltaViewAngles;
  1504. }
  1505. /*
  1506. ================
  1507. idActor::SetDeltaViewAngles
  1508. ================
  1509. */
  1510. void idActor::SetDeltaViewAngles( const idAngles &delta ) {
  1511. deltaViewAngles = delta;
  1512. }
  1513. /*
  1514. ================
  1515. idActor::HasEnemies
  1516. ================
  1517. */
  1518. bool idActor::HasEnemies( void ) const {
  1519. idActor *ent;
  1520. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1521. if ( !ent->fl.hidden ) {
  1522. return true;
  1523. }
  1524. }
  1525. return false;
  1526. }
  1527. /*
  1528. ================
  1529. idActor::ClosestEnemyToPoint
  1530. ================
  1531. */
  1532. idActor *idActor::ClosestEnemyToPoint( const idVec3 &pos ) {
  1533. idActor *ent;
  1534. idActor *bestEnt;
  1535. float bestDistSquared;
  1536. float distSquared;
  1537. idVec3 delta;
  1538. bestDistSquared = idMath::INFINITY;
  1539. bestEnt = NULL;
  1540. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1541. if ( ent->fl.hidden ) {
  1542. continue;
  1543. }
  1544. delta = ent->GetPhysics()->GetOrigin() - pos;
  1545. distSquared = delta.LengthSqr();
  1546. if ( distSquared < bestDistSquared ) {
  1547. bestEnt = ent;
  1548. bestDistSquared = distSquared;
  1549. }
  1550. }
  1551. return bestEnt;
  1552. }
  1553. /*
  1554. ================
  1555. idActor::EnemyWithMostHealth
  1556. ================
  1557. */
  1558. idActor *idActor::EnemyWithMostHealth() {
  1559. idActor *ent;
  1560. idActor *bestEnt;
  1561. int most = -9999;
  1562. bestEnt = NULL;
  1563. for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  1564. if ( !ent->fl.hidden && ( ent->health > most ) ) {
  1565. bestEnt = ent;
  1566. most = ent->health;
  1567. }
  1568. }
  1569. return bestEnt;
  1570. }
  1571. /*
  1572. ================
  1573. idActor::OnLadder
  1574. ================
  1575. */
  1576. bool idActor::OnLadder( void ) const {
  1577. return false;
  1578. }
  1579. /*
  1580. ==============
  1581. idActor::GetAASLocation
  1582. ==============
  1583. */
  1584. void idActor::GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const {
  1585. idVec3 size;
  1586. idBounds bounds;
  1587. GetFloorPos( 64.0f, pos );
  1588. if ( !aas ) {
  1589. areaNum = 0;
  1590. return;
  1591. }
  1592. size = aas->GetSettings()->boundingBoxes[0][1];
  1593. bounds[0] = -size;
  1594. size.z = 32.0f;
  1595. bounds[1] = size;
  1596. areaNum = aas->PointReachableAreaNum( pos, bounds, AREA_REACHABLE_WALK );
  1597. if ( areaNum ) {
  1598. aas->PushPointIntoAreaNum( areaNum, pos );
  1599. }
  1600. }
  1601. /***********************************************************************
  1602. animation state
  1603. ***********************************************************************/
  1604. /*
  1605. =====================
  1606. idActor::SetAnimState
  1607. =====================
  1608. */
  1609. void idActor::SetAnimState( int channel, const char *statename, int blendFrames ) {
  1610. const function_t *func;
  1611. func = scriptObject.GetFunction( statename );
  1612. if ( !func ) {
  1613. assert( 0 );
  1614. gameLocal.Error( "Can't find function '%s' in object '%s'", statename, scriptObject.GetTypeName() );
  1615. }
  1616. switch( channel ) {
  1617. case ANIMCHANNEL_HEAD :
  1618. headAnim.SetState( statename, blendFrames );
  1619. allowEyeFocus = true;
  1620. break;
  1621. case ANIMCHANNEL_TORSO :
  1622. torsoAnim.SetState( statename, blendFrames );
  1623. legsAnim.Enable( blendFrames );
  1624. allowPain = true;
  1625. allowEyeFocus = true;
  1626. break;
  1627. case ANIMCHANNEL_LEGS :
  1628. legsAnim.SetState( statename, blendFrames );
  1629. torsoAnim.Enable( blendFrames );
  1630. allowPain = true;
  1631. allowEyeFocus = true;
  1632. break;
  1633. default:
  1634. gameLocal.Error( "idActor::SetAnimState: Unknown anim group" );
  1635. break;
  1636. }
  1637. }
  1638. /*
  1639. =====================
  1640. idActor::GetAnimState
  1641. =====================
  1642. */
  1643. const char *idActor::GetAnimState( int channel ) const {
  1644. switch( channel ) {
  1645. case ANIMCHANNEL_HEAD :
  1646. return headAnim.state;
  1647. break;
  1648. case ANIMCHANNEL_TORSO :
  1649. return torsoAnim.state;
  1650. break;
  1651. case ANIMCHANNEL_LEGS :
  1652. return legsAnim.state;
  1653. break;
  1654. default:
  1655. gameLocal.Error( "idActor::GetAnimState: Unknown anim group" );
  1656. return NULL;
  1657. break;
  1658. }
  1659. }
  1660. /*
  1661. =====================
  1662. idActor::InAnimState
  1663. =====================
  1664. */
  1665. bool idActor::InAnimState( int channel, const char *statename ) const {
  1666. switch( channel ) {
  1667. case ANIMCHANNEL_HEAD :
  1668. if ( headAnim.state == statename ) {
  1669. return true;
  1670. }
  1671. break;
  1672. case ANIMCHANNEL_TORSO :
  1673. if ( torsoAnim.state == statename ) {
  1674. return true;
  1675. }
  1676. break;
  1677. case ANIMCHANNEL_LEGS :
  1678. if ( legsAnim.state == statename ) {
  1679. return true;
  1680. }
  1681. break;
  1682. default:
  1683. gameLocal.Error( "idActor::InAnimState: Unknown anim group" );
  1684. break;
  1685. }
  1686. return false;
  1687. }
  1688. /*
  1689. =====================
  1690. idActor::WaitState
  1691. =====================
  1692. */
  1693. const char *idActor::WaitState( void ) const {
  1694. if ( waitState.Length() ) {
  1695. return waitState;
  1696. } else {
  1697. return NULL;
  1698. }
  1699. }
  1700. /*
  1701. =====================
  1702. idActor::SetWaitState
  1703. =====================
  1704. */
  1705. void idActor::SetWaitState( const char *_waitstate ) {
  1706. waitState = _waitstate;
  1707. }
  1708. /*
  1709. =====================
  1710. idActor::UpdateAnimState
  1711. =====================
  1712. */
  1713. void idActor::UpdateAnimState( void ) {
  1714. headAnim.UpdateState();
  1715. torsoAnim.UpdateState();
  1716. legsAnim.UpdateState();
  1717. }
  1718. /*
  1719. =====================
  1720. idActor::GetAnim
  1721. =====================
  1722. */
  1723. int idActor::GetAnim( int channel, const char *animname ) {
  1724. int anim;
  1725. const char *temp;
  1726. idAnimator *animatorPtr;
  1727. if ( channel == ANIMCHANNEL_HEAD ) {
  1728. if ( !head.GetEntity() ) {
  1729. return 0;
  1730. }
  1731. animatorPtr = head.GetEntity()->GetAnimator();
  1732. } else {
  1733. animatorPtr = &animator;
  1734. }
  1735. if ( animPrefix.Length() ) {
  1736. temp = va( "%s_%s", animPrefix.c_str(), animname );
  1737. anim = animatorPtr->GetAnim( temp );
  1738. if ( anim ) {
  1739. return anim;
  1740. }
  1741. }
  1742. anim = animatorPtr->GetAnim( animname );
  1743. return anim;
  1744. }
  1745. /*
  1746. ===============
  1747. idActor::SyncAnimChannels
  1748. ===============
  1749. */
  1750. void idActor::SyncAnimChannels( int channel, int syncToChannel, int blendFrames ) {
  1751. idAnimator *headAnimator;
  1752. idAFAttachment *headEnt;
  1753. int anim;
  1754. idAnimBlend *syncAnim;
  1755. int starttime;
  1756. int blendTime;
  1757. int cycle;
  1758. blendTime = FRAME2MS( blendFrames );
  1759. if ( channel == ANIMCHANNEL_HEAD ) {
  1760. headEnt = head.GetEntity();
  1761. if ( headEnt ) {
  1762. headAnimator = headEnt->GetAnimator();
  1763. syncAnim = animator.CurrentAnim( syncToChannel );
  1764. if ( syncAnim ) {
  1765. anim = headAnimator->GetAnim( syncAnim->AnimFullName() );
  1766. if ( !anim ) {
  1767. anim = headAnimator->GetAnim( syncAnim->AnimName() );
  1768. }
  1769. if ( anim ) {
  1770. cycle = animator.CurrentAnim( syncToChannel )->GetCycleCount();
  1771. starttime = animator.CurrentAnim( syncToChannel )->GetStartTime();
  1772. headAnimator->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, blendTime );
  1773. headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( cycle );
  1774. headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetStartTime( starttime );
  1775. } else {
  1776. headEnt->PlayIdleAnim( blendTime );
  1777. }
  1778. }
  1779. }
  1780. } else if ( syncToChannel == ANIMCHANNEL_HEAD ) {
  1781. headEnt = head.GetEntity();
  1782. if ( headEnt ) {
  1783. headAnimator = headEnt->GetAnimator();
  1784. syncAnim = headAnimator->CurrentAnim( ANIMCHANNEL_ALL );
  1785. if ( syncAnim ) {
  1786. anim = GetAnim( channel, syncAnim->AnimFullName() );
  1787. if ( !anim ) {
  1788. anim = GetAnim( channel, syncAnim->AnimName() );
  1789. }
  1790. if ( anim ) {
  1791. cycle = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetCycleCount();
  1792. starttime = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime();
  1793. animator.PlayAnim( channel, anim, gameLocal.time, blendTime );
  1794. animator.CurrentAnim( channel )->SetCycleCount( cycle );
  1795. animator.CurrentAnim( channel )->SetStartTime( starttime );
  1796. }
  1797. }
  1798. }
  1799. } else {
  1800. animator.SyncAnimChannels( channel, syncToChannel, gameLocal.time, blendTime );
  1801. }
  1802. }
  1803. /***********************************************************************
  1804. Damage
  1805. ***********************************************************************/
  1806. /*
  1807. ============
  1808. idActor::Gib
  1809. ============
  1810. */
  1811. void idActor::Gib( const idVec3 &dir, const char *damageDefName ) {
  1812. // no gibbing in multiplayer - by self damage or by moving objects
  1813. if ( gameLocal.isMultiplayer ) {
  1814. return;
  1815. }
  1816. // only gib once
  1817. if ( gibbed ) {
  1818. return;
  1819. }
  1820. idAFEntity_Gibbable::Gib( dir, damageDefName );
  1821. if ( head.GetEntity() ) {
  1822. head.GetEntity()->Hide();
  1823. }
  1824. StopSound( SND_CHANNEL_VOICE, false );
  1825. }
  1826. /*
  1827. ============
  1828. idActor::Damage
  1829. this entity that is being damaged
  1830. inflictor entity that is causing the damage
  1831. attacker entity that caused the inflictor to damage targ
  1832. example: this=monster, inflictor=rocket, attacker=player
  1833. dir direction of the attack for knockback in global space
  1834. point point at which the damage is being inflicted, used for headshots
  1835. damage amount of damage being inflicted
  1836. inflictor, attacker, dir, and point can be NULL for environmental effects
  1837. Bleeding wounds and surface overlays are applied in the collision code that
  1838. calls Damage()
  1839. ============
  1840. */
  1841. void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
  1842. const char *damageDefName, const float damageScale, const int location ) {
  1843. if ( !fl.takedamage ) {
  1844. return;
  1845. }
  1846. if ( !inflictor ) {
  1847. inflictor = gameLocal.world;
  1848. }
  1849. if ( !attacker ) {
  1850. attacker = gameLocal.world;
  1851. }
  1852. #ifdef _D3XP
  1853. SetTimeState ts( timeGroup );
  1854. // Helltime boss is immune to all projectiles except the helltime killer
  1855. if ( finalBoss && idStr::Icmp(inflictor->GetEntityDefName(), "projectile_helltime_killer") ) {
  1856. return;
  1857. }
  1858. // Maledict is immume to the falling asteroids
  1859. if ( !idStr::Icmp( GetEntityDefName(), "monster_boss_d3xp_maledict" ) &&
  1860. (!idStr::Icmp( damageDefName, "damage_maledict_asteroid" ) || !idStr::Icmp( damageDefName, "damage_maledict_asteroid_splash" ) ) ) {
  1861. return;
  1862. }
  1863. #else
  1864. if ( finalBoss && !inflictor->IsType( idSoulCubeMissile::Type ) ) {
  1865. return;
  1866. }
  1867. #endif
  1868. const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
  1869. if ( !damageDef ) {
  1870. gameLocal.Error( "Unknown damageDef '%s'", damageDefName );
  1871. }
  1872. int damage = damageDef->GetInt( "damage" ) * damageScale;
  1873. damage = GetDamageForLocation( damage, location );
  1874. // inform the attacker that they hit someone
  1875. attacker->DamageFeedback( this, inflictor, damage );
  1876. if ( damage > 0 ) {
  1877. health -= damage;
  1878. #ifdef _D3XP
  1879. //Check the health against any damage cap that is currently set
  1880. if(damageCap >= 0 && health < damageCap) {
  1881. health = damageCap;
  1882. }
  1883. #endif
  1884. if ( health <= 0 ) {
  1885. if ( health < -999 ) {
  1886. health = -999;
  1887. }
  1888. Killed( inflictor, attacker, damage, dir, location );
  1889. if ( ( health < -20 ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) {
  1890. Gib( dir, damageDefName );
  1891. }
  1892. } else {
  1893. Pain( inflictor, attacker, damage, dir, location );
  1894. }
  1895. } else {
  1896. // don't accumulate knockback
  1897. if ( af.IsLoaded() ) {
  1898. // clear impacts
  1899. af.Rest();
  1900. // physics is turned off by calling af.Rest()
  1901. BecomeActive( TH_PHYSICS );
  1902. }
  1903. }
  1904. }
  1905. /*
  1906. =====================
  1907. idActor::ClearPain
  1908. =====================
  1909. */
  1910. void idActor::ClearPain( void ) {
  1911. pain_debounce_time = 0;
  1912. }
  1913. /*
  1914. =====================
  1915. idActor::Pain
  1916. =====================
  1917. */
  1918. bool idActor::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  1919. if ( af.IsLoaded() ) {
  1920. // clear impacts
  1921. af.Rest();
  1922. // physics is turned off by calling af.Rest()
  1923. BecomeActive( TH_PHYSICS );
  1924. }
  1925. if ( gameLocal.time < pain_debounce_time ) {
  1926. return false;
  1927. }
  1928. // don't play pain sounds more than necessary
  1929. pain_debounce_time = gameLocal.time + pain_delay;
  1930. if ( health > 75 ) {
  1931. StartSound( "snd_pain_small", SND_CHANNEL_VOICE, 0, false, NULL );
  1932. } else if ( health > 50 ) {
  1933. StartSound( "snd_pain_medium", SND_CHANNEL_VOICE, 0, false, NULL );
  1934. } else if ( health > 25 ) {
  1935. StartSound( "snd_pain_large", SND_CHANNEL_VOICE, 0, false, NULL );
  1936. } else {
  1937. StartSound( "snd_pain_huge", SND_CHANNEL_VOICE, 0, false, NULL );
  1938. }
  1939. if ( !allowPain || ( gameLocal.time < painTime ) ) {
  1940. // don't play a pain anim
  1941. return false;
  1942. }
  1943. if ( pain_threshold && ( damage < pain_threshold ) ) {
  1944. return false;
  1945. }
  1946. // set the pain anim
  1947. idStr damageGroup = GetDamageGroup( location );
  1948. painAnim = "";
  1949. if ( animPrefix.Length() ) {
  1950. if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
  1951. sprintf( painAnim, "%s_pain_%s", animPrefix.c_str(), damageGroup.c_str() );
  1952. if ( !animator.HasAnim( painAnim ) ) {
  1953. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1954. if ( !animator.HasAnim( painAnim ) ) {
  1955. painAnim = "";
  1956. }
  1957. }
  1958. }
  1959. if ( !painAnim.Length() ) {
  1960. sprintf( painAnim, "%s_pain", animPrefix.c_str() );
  1961. if ( !animator.HasAnim( painAnim ) ) {
  1962. painAnim = "";
  1963. }
  1964. }
  1965. } else if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
  1966. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1967. if ( !animator.HasAnim( painAnim ) ) {
  1968. sprintf( painAnim, "pain_%s", damageGroup.c_str() );
  1969. if ( !animator.HasAnim( painAnim ) ) {
  1970. painAnim = "";
  1971. }
  1972. }
  1973. }
  1974. if ( !painAnim.Length() ) {
  1975. painAnim = "pain";
  1976. }
  1977. if ( g_debugDamage.GetBool() ) {
  1978. gameLocal.Printf( "Damage: joint: '%s', zone '%s', anim '%s'\n", animator.GetJointName( ( jointHandle_t )location ),
  1979. damageGroup.c_str(), painAnim.c_str() );
  1980. }
  1981. return true;
  1982. }
  1983. /*
  1984. =====================
  1985. idActor::SpawnGibs
  1986. =====================
  1987. */
  1988. void idActor::SpawnGibs( const idVec3 &dir, const char *damageDefName ) {
  1989. idAFEntity_Gibbable::SpawnGibs( dir, damageDefName );
  1990. RemoveAttachments();
  1991. }
  1992. /*
  1993. =====================
  1994. idActor::SetupDamageGroups
  1995. FIXME: only store group names once and store an index for each joint
  1996. =====================
  1997. */
  1998. void idActor::SetupDamageGroups( void ) {
  1999. int i;
  2000. const idKeyValue *arg;
  2001. idStr groupname;
  2002. idList<jointHandle_t> jointList;
  2003. int jointnum;
  2004. float scale;
  2005. // create damage zones
  2006. damageGroups.SetNum( animator.NumJoints() );
  2007. arg = spawnArgs.MatchPrefix( "damage_zone ", NULL );
  2008. while ( arg ) {
  2009. groupname = arg->GetKey();
  2010. groupname.Strip( "damage_zone " );
  2011. animator.GetJointList( arg->GetValue(), jointList );
  2012. for( i = 0; i < jointList.Num(); i++ ) {
  2013. jointnum = jointList[ i ];
  2014. damageGroups[ jointnum ] = groupname;
  2015. }
  2016. jointList.Clear();
  2017. arg = spawnArgs.MatchPrefix( "damage_zone ", arg );
  2018. }
  2019. // initilize the damage zones to normal damage
  2020. damageScale.SetNum( animator.NumJoints() );
  2021. for( i = 0; i < damageScale.Num(); i++ ) {
  2022. damageScale[ i ] = 1.0f;
  2023. }
  2024. // set the percentage on damage zones
  2025. arg = spawnArgs.MatchPrefix( "damage_scale ", NULL );
  2026. while ( arg ) {
  2027. scale = atof( arg->GetValue() );
  2028. groupname = arg->GetKey();
  2029. groupname.Strip( "damage_scale " );
  2030. for( i = 0; i < damageScale.Num(); i++ ) {
  2031. if ( damageGroups[ i ] == groupname ) {
  2032. damageScale[ i ] = scale;
  2033. }
  2034. }
  2035. arg = spawnArgs.MatchPrefix( "damage_scale ", arg );
  2036. }
  2037. }
  2038. /*
  2039. =====================
  2040. idActor::GetDamageForLocation
  2041. =====================
  2042. */
  2043. int idActor::GetDamageForLocation( int damage, int location ) {
  2044. if ( ( location < 0 ) || ( location >= damageScale.Num() ) ) {
  2045. return damage;
  2046. }
  2047. return (int)ceil( damage * damageScale[ location ] );
  2048. }
  2049. /*
  2050. =====================
  2051. idActor::GetDamageGroup
  2052. =====================
  2053. */
  2054. const char *idActor::GetDamageGroup( int location ) {
  2055. if ( ( location < 0 ) || ( location >= damageGroups.Num() ) ) {
  2056. return "";
  2057. }
  2058. return damageGroups[ location ];
  2059. }
  2060. /***********************************************************************
  2061. Events
  2062. ***********************************************************************/
  2063. /*
  2064. =====================
  2065. idActor::Event_EnableEyeFocus
  2066. =====================
  2067. */
  2068. void idActor::PlayFootStepSound( void ) {
  2069. const char *sound = NULL;
  2070. const idMaterial *material;
  2071. if ( !GetPhysics()->HasGroundContacts() ) {
  2072. return;
  2073. }
  2074. // start footstep sound based on material type
  2075. material = GetPhysics()->GetContact( 0 ).material;
  2076. if ( material != NULL ) {
  2077. sound = spawnArgs.GetString( va( "snd_footstep_%s", gameLocal.sufaceTypeNames[ material->GetSurfaceType() ] ) );
  2078. }
  2079. if ( *sound == '\0' ) {
  2080. sound = spawnArgs.GetString( "snd_footstep" );
  2081. }
  2082. if ( *sound != '\0' ) {
  2083. StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
  2084. }
  2085. }
  2086. /*
  2087. =====================
  2088. idActor::Event_EnableEyeFocus
  2089. =====================
  2090. */
  2091. void idActor::Event_EnableEyeFocus( void ) {
  2092. allowEyeFocus = true;
  2093. blink_time = gameLocal.time + blink_min + gameLocal.random.RandomFloat() * ( blink_max - blink_min );
  2094. }
  2095. /*
  2096. =====================
  2097. idActor::Event_DisableEyeFocus
  2098. =====================
  2099. */
  2100. void idActor::Event_DisableEyeFocus( void ) {
  2101. allowEyeFocus = false;
  2102. idEntity *headEnt = head.GetEntity();
  2103. if ( headEnt ) {
  2104. headEnt->GetAnimator()->Clear( ANIMCHANNEL_EYELIDS, gameLocal.time, FRAME2MS( 2 ) );
  2105. } else {
  2106. animator.Clear( ANIMCHANNEL_EYELIDS, gameLocal.time, FRAME2MS( 2 ) );
  2107. }
  2108. }
  2109. /*
  2110. ===============
  2111. idActor::Event_Footstep
  2112. ===============
  2113. */
  2114. void idActor::Event_Footstep( void ) {
  2115. PlayFootStepSound();
  2116. }
  2117. /*
  2118. =====================
  2119. idActor::Event_EnableWalkIK
  2120. =====================
  2121. */
  2122. void idActor::Event_EnableWalkIK( void ) {
  2123. walkIK.EnableAll();
  2124. }
  2125. /*
  2126. =====================
  2127. idActor::Event_DisableWalkIK
  2128. =====================
  2129. */
  2130. void idActor::Event_DisableWalkIK( void ) {
  2131. walkIK.DisableAll();
  2132. }
  2133. /*
  2134. =====================
  2135. idActor::Event_EnableLegIK
  2136. =====================
  2137. */
  2138. void idActor::Event_EnableLegIK( int num ) {
  2139. walkIK.EnableLeg( num );
  2140. }
  2141. /*
  2142. =====================
  2143. idActor::Event_DisableLegIK
  2144. =====================
  2145. */
  2146. void idActor::Event_DisableLegIK( int num ) {
  2147. walkIK.DisableLeg( num );
  2148. }
  2149. /*
  2150. =====================
  2151. idActor::Event_PreventPain
  2152. =====================
  2153. */
  2154. void idActor::Event_PreventPain( float duration ) {
  2155. painTime = gameLocal.time + SEC2MS( duration );
  2156. }
  2157. /*
  2158. ===============
  2159. idActor::Event_DisablePain
  2160. ===============
  2161. */
  2162. void idActor::Event_DisablePain( void ) {
  2163. allowPain = false;
  2164. }
  2165. /*
  2166. ===============
  2167. idActor::Event_EnablePain
  2168. ===============
  2169. */
  2170. void idActor::Event_EnablePain( void ) {
  2171. allowPain = true;
  2172. }
  2173. /*
  2174. =====================
  2175. idActor::Event_GetPainAnim
  2176. =====================
  2177. */
  2178. void idActor::Event_GetPainAnim( void ) {
  2179. if ( !painAnim.Length() ) {
  2180. idThread::ReturnString( "pain" );
  2181. } else {
  2182. idThread::ReturnString( painAnim );
  2183. }
  2184. }
  2185. /*
  2186. =====================
  2187. idActor::Event_SetAnimPrefix
  2188. =====================
  2189. */
  2190. void idActor::Event_SetAnimPrefix( const char *prefix ) {
  2191. animPrefix = prefix;
  2192. }
  2193. /*
  2194. ===============
  2195. idActor::Event_StopAnim
  2196. ===============
  2197. */
  2198. void idActor::Event_StopAnim( int channel, int frames ) {
  2199. switch( channel ) {
  2200. case ANIMCHANNEL_HEAD :
  2201. headAnim.StopAnim( frames );
  2202. break;
  2203. case ANIMCHANNEL_TORSO :
  2204. torsoAnim.StopAnim( frames );
  2205. break;
  2206. case ANIMCHANNEL_LEGS :
  2207. legsAnim.StopAnim( frames );
  2208. break;
  2209. default:
  2210. gameLocal.Error( "Unknown anim group" );
  2211. break;
  2212. }
  2213. }
  2214. /*
  2215. ===============
  2216. idActor::Event_PlayAnim
  2217. ===============
  2218. */
  2219. void idActor::Event_PlayAnim( int channel, const char *animname ) {
  2220. animFlags_t flags;
  2221. idEntity *headEnt;
  2222. int anim;
  2223. anim = GetAnim( channel, animname );
  2224. if ( !anim ) {
  2225. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2226. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2227. } else {
  2228. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2229. }
  2230. idThread::ReturnInt( 0 );
  2231. return;
  2232. }
  2233. switch( channel ) {
  2234. case ANIMCHANNEL_HEAD :
  2235. headEnt = head.GetEntity();
  2236. if ( headEnt ) {
  2237. headAnim.idleAnim = false;
  2238. headAnim.PlayAnim( anim );
  2239. flags = headAnim.GetAnimFlags();
  2240. if ( !flags.prevent_idle_override ) {
  2241. if ( torsoAnim.IsIdle() ) {
  2242. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2243. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2244. if ( legsAnim.IsIdle() ) {
  2245. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2246. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2247. }
  2248. }
  2249. }
  2250. }
  2251. break;
  2252. case ANIMCHANNEL_TORSO :
  2253. torsoAnim.idleAnim = false;
  2254. torsoAnim.PlayAnim( anim );
  2255. flags = torsoAnim.GetAnimFlags();
  2256. if ( !flags.prevent_idle_override ) {
  2257. if ( headAnim.IsIdle() ) {
  2258. headAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2259. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2260. }
  2261. if ( legsAnim.IsIdle() ) {
  2262. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2263. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2264. }
  2265. }
  2266. break;
  2267. case ANIMCHANNEL_LEGS :
  2268. legsAnim.idleAnim = false;
  2269. legsAnim.PlayAnim( anim );
  2270. flags = legsAnim.GetAnimFlags();
  2271. if ( !flags.prevent_idle_override ) {
  2272. if ( torsoAnim.IsIdle() ) {
  2273. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2274. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2275. if ( headAnim.IsIdle() ) {
  2276. headAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2277. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2278. }
  2279. }
  2280. }
  2281. break;
  2282. default :
  2283. gameLocal.Error( "Unknown anim group" );
  2284. break;
  2285. }
  2286. idThread::ReturnInt( 1 );
  2287. }
  2288. /*
  2289. ===============
  2290. idActor::Event_PlayCycle
  2291. ===============
  2292. */
  2293. void idActor::Event_PlayCycle( int channel, const char *animname ) {
  2294. animFlags_t flags;
  2295. int anim;
  2296. anim = GetAnim( channel, animname );
  2297. if ( !anim ) {
  2298. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2299. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2300. } else {
  2301. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2302. }
  2303. idThread::ReturnInt( false );
  2304. return;
  2305. }
  2306. switch( channel ) {
  2307. case ANIMCHANNEL_HEAD :
  2308. headAnim.idleAnim = false;
  2309. headAnim.CycleAnim( anim );
  2310. flags = headAnim.GetAnimFlags();
  2311. if ( !flags.prevent_idle_override ) {
  2312. if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
  2313. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2314. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2315. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2316. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2317. }
  2318. }
  2319. break;
  2320. case ANIMCHANNEL_TORSO :
  2321. torsoAnim.idleAnim = false;
  2322. torsoAnim.CycleAnim( anim );
  2323. flags = torsoAnim.GetAnimFlags();
  2324. if ( !flags.prevent_idle_override ) {
  2325. if ( headAnim.IsIdle() ) {
  2326. headAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2327. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2328. }
  2329. if ( legsAnim.IsIdle() ) {
  2330. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2331. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2332. }
  2333. }
  2334. break;
  2335. case ANIMCHANNEL_LEGS :
  2336. legsAnim.idleAnim = false;
  2337. legsAnim.CycleAnim( anim );
  2338. flags = legsAnim.GetAnimFlags();
  2339. if ( !flags.prevent_idle_override ) {
  2340. if ( torsoAnim.IsIdle() ) {
  2341. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2342. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2343. if ( headAnim.IsIdle() ) {
  2344. headAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2345. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2346. }
  2347. }
  2348. }
  2349. break;
  2350. default:
  2351. gameLocal.Error( "Unknown anim group" );
  2352. }
  2353. idThread::ReturnInt( true );
  2354. }
  2355. /*
  2356. ===============
  2357. idActor::Event_IdleAnim
  2358. ===============
  2359. */
  2360. void idActor::Event_IdleAnim( int channel, const char *animname ) {
  2361. int anim;
  2362. anim = GetAnim( channel, animname );
  2363. if ( !anim ) {
  2364. if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
  2365. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
  2366. } else {
  2367. gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
  2368. }
  2369. switch( channel ) {
  2370. case ANIMCHANNEL_HEAD :
  2371. headAnim.BecomeIdle();
  2372. break;
  2373. case ANIMCHANNEL_TORSO :
  2374. torsoAnim.BecomeIdle();
  2375. break;
  2376. case ANIMCHANNEL_LEGS :
  2377. legsAnim.BecomeIdle();
  2378. break;
  2379. default:
  2380. gameLocal.Error( "Unknown anim group" );
  2381. }
  2382. idThread::ReturnInt( false );
  2383. return;
  2384. }
  2385. switch( channel ) {
  2386. case ANIMCHANNEL_HEAD :
  2387. headAnim.BecomeIdle();
  2388. if ( torsoAnim.GetAnimFlags().prevent_idle_override ) {
  2389. // don't sync to torso body if it doesn't override idle anims
  2390. headAnim.CycleAnim( anim );
  2391. } else if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
  2392. // everything is idle, so play the anim on the head and copy it to the torso and legs
  2393. headAnim.CycleAnim( anim );
  2394. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2395. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2396. legsAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2397. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_HEAD, headAnim.lastAnimBlendFrames );
  2398. } else if ( torsoAnim.IsIdle() ) {
  2399. // sync the head and torso to the legs
  2400. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, headAnim.animBlendFrames );
  2401. torsoAnim.animBlendFrames = headAnim.lastAnimBlendFrames;
  2402. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, torsoAnim.animBlendFrames );
  2403. } else {
  2404. // sync the head to the torso
  2405. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, headAnim.animBlendFrames );
  2406. }
  2407. break;
  2408. case ANIMCHANNEL_TORSO :
  2409. torsoAnim.BecomeIdle();
  2410. if ( legsAnim.GetAnimFlags().prevent_idle_override ) {
  2411. // don't sync to legs if legs anim doesn't override idle anims
  2412. torsoAnim.CycleAnim( anim );
  2413. } else if ( legsAnim.IsIdle() ) {
  2414. // play the anim in both legs and torso
  2415. torsoAnim.CycleAnim( anim );
  2416. legsAnim.animBlendFrames = torsoAnim.lastAnimBlendFrames;
  2417. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2418. } else {
  2419. // sync the anim to the legs
  2420. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, torsoAnim.animBlendFrames );
  2421. }
  2422. if ( headAnim.IsIdle() ) {
  2423. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2424. }
  2425. break;
  2426. case ANIMCHANNEL_LEGS :
  2427. legsAnim.BecomeIdle();
  2428. if ( torsoAnim.GetAnimFlags().prevent_idle_override ) {
  2429. // don't sync to torso if torso anim doesn't override idle anims
  2430. legsAnim.CycleAnim( anim );
  2431. } else if ( torsoAnim.IsIdle() ) {
  2432. // play the anim in both legs and torso
  2433. legsAnim.CycleAnim( anim );
  2434. torsoAnim.animBlendFrames = legsAnim.lastAnimBlendFrames;
  2435. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2436. if ( headAnim.IsIdle() ) {
  2437. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2438. }
  2439. } else {
  2440. // sync the anim to the torso
  2441. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, legsAnim.animBlendFrames );
  2442. }
  2443. break;
  2444. default:
  2445. gameLocal.Error( "Unknown anim group" );
  2446. }
  2447. idThread::ReturnInt( true );
  2448. }
  2449. /*
  2450. ================
  2451. idActor::Event_SetSyncedAnimWeight
  2452. ================
  2453. */
  2454. void idActor::Event_SetSyncedAnimWeight( int channel, int anim, float weight ) {
  2455. idEntity *headEnt;
  2456. headEnt = head.GetEntity();
  2457. switch( channel ) {
  2458. case ANIMCHANNEL_HEAD :
  2459. if ( headEnt ) {
  2460. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2461. } else {
  2462. animator.CurrentAnim( ANIMCHANNEL_HEAD )->SetSyncedAnimWeight( anim, weight );
  2463. }
  2464. if ( torsoAnim.IsIdle() ) {
  2465. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2466. if ( legsAnim.IsIdle() ) {
  2467. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2468. }
  2469. }
  2470. break;
  2471. case ANIMCHANNEL_TORSO :
  2472. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2473. if ( legsAnim.IsIdle() ) {
  2474. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2475. }
  2476. if ( headEnt && headAnim.IsIdle() ) {
  2477. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2478. }
  2479. break;
  2480. case ANIMCHANNEL_LEGS :
  2481. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( anim, weight );
  2482. if ( torsoAnim.IsIdle() ) {
  2483. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( anim, weight );
  2484. if ( headEnt && headAnim.IsIdle() ) {
  2485. animator.CurrentAnim( ANIMCHANNEL_ALL )->SetSyncedAnimWeight( anim, weight );
  2486. }
  2487. }
  2488. break;
  2489. default:
  2490. gameLocal.Error( "Unknown anim group" );
  2491. }
  2492. }
  2493. /*
  2494. ===============
  2495. idActor::Event_OverrideAnim
  2496. ===============
  2497. */
  2498. void idActor::Event_OverrideAnim( int channel ) {
  2499. switch( channel ) {
  2500. case ANIMCHANNEL_HEAD :
  2501. headAnim.Disable();
  2502. if ( !torsoAnim.IsIdle() ) {
  2503. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2504. } else {
  2505. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2506. }
  2507. break;
  2508. case ANIMCHANNEL_TORSO :
  2509. torsoAnim.Disable();
  2510. SyncAnimChannels( ANIMCHANNEL_TORSO, ANIMCHANNEL_LEGS, legsAnim.lastAnimBlendFrames );
  2511. if ( headAnim.IsIdle() ) {
  2512. SyncAnimChannels( ANIMCHANNEL_HEAD, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2513. }
  2514. break;
  2515. case ANIMCHANNEL_LEGS :
  2516. legsAnim.Disable();
  2517. SyncAnimChannels( ANIMCHANNEL_LEGS, ANIMCHANNEL_TORSO, torsoAnim.lastAnimBlendFrames );
  2518. break;
  2519. default:
  2520. gameLocal.Error( "Unknown anim group" );
  2521. break;
  2522. }
  2523. }
  2524. /*
  2525. ===============
  2526. idActor::Event_EnableAnim
  2527. ===============
  2528. */
  2529. void idActor::Event_EnableAnim( int channel, int blendFrames ) {
  2530. switch( channel ) {
  2531. case ANIMCHANNEL_HEAD :
  2532. headAnim.Enable( blendFrames );
  2533. break;
  2534. case ANIMCHANNEL_TORSO :
  2535. torsoAnim.Enable( blendFrames );
  2536. break;
  2537. case ANIMCHANNEL_LEGS :
  2538. legsAnim.Enable( blendFrames );
  2539. break;
  2540. default:
  2541. gameLocal.Error( "Unknown anim group" );
  2542. break;
  2543. }
  2544. }
  2545. /*
  2546. ===============
  2547. idActor::Event_SetBlendFrames
  2548. ===============
  2549. */
  2550. void idActor::Event_SetBlendFrames( int channel, int blendFrames ) {
  2551. switch( channel ) {
  2552. case ANIMCHANNEL_HEAD :
  2553. headAnim.animBlendFrames = blendFrames;
  2554. headAnim.lastAnimBlendFrames = blendFrames;
  2555. break;
  2556. case ANIMCHANNEL_TORSO :
  2557. torsoAnim.animBlendFrames = blendFrames;
  2558. torsoAnim.lastAnimBlendFrames = blendFrames;
  2559. break;
  2560. case ANIMCHANNEL_LEGS :
  2561. legsAnim.animBlendFrames = blendFrames;
  2562. legsAnim.lastAnimBlendFrames = blendFrames;
  2563. break;
  2564. default:
  2565. gameLocal.Error( "Unknown anim group" );
  2566. break;
  2567. }
  2568. }
  2569. /*
  2570. ===============
  2571. idActor::Event_GetBlendFrames
  2572. ===============
  2573. */
  2574. void idActor::Event_GetBlendFrames( int channel ) {
  2575. switch( channel ) {
  2576. case ANIMCHANNEL_HEAD :
  2577. idThread::ReturnInt( headAnim.animBlendFrames );
  2578. break;
  2579. case ANIMCHANNEL_TORSO :
  2580. idThread::ReturnInt( torsoAnim.animBlendFrames );
  2581. break;
  2582. case ANIMCHANNEL_LEGS :
  2583. idThread::ReturnInt( legsAnim.animBlendFrames );
  2584. break;
  2585. default:
  2586. gameLocal.Error( "Unknown anim group" );
  2587. break;
  2588. }
  2589. }
  2590. /*
  2591. ===============
  2592. idActor::Event_AnimState
  2593. ===============
  2594. */
  2595. void idActor::Event_AnimState( int channel, const char *statename, int blendFrames ) {
  2596. SetAnimState( channel, statename, blendFrames );
  2597. }
  2598. /*
  2599. ===============
  2600. idActor::Event_GetAnimState
  2601. ===============
  2602. */
  2603. void idActor::Event_GetAnimState( int channel ) {
  2604. const char *state;
  2605. state = GetAnimState( channel );
  2606. idThread::ReturnString( state );
  2607. }
  2608. /*
  2609. ===============
  2610. idActor::Event_InAnimState
  2611. ===============
  2612. */
  2613. void idActor::Event_InAnimState( int channel, const char *statename ) {
  2614. bool instate;
  2615. instate = InAnimState( channel, statename );
  2616. idThread::ReturnInt( instate );
  2617. }
  2618. /*
  2619. ===============
  2620. idActor::Event_FinishAction
  2621. ===============
  2622. */
  2623. void idActor::Event_FinishAction( const char *actionname ) {
  2624. if ( waitState == actionname ) {
  2625. SetWaitState( "" );
  2626. }
  2627. }
  2628. /*
  2629. ===============
  2630. idActor::Event_AnimDone
  2631. ===============
  2632. */
  2633. void idActor::Event_AnimDone( int channel, int blendFrames ) {
  2634. bool result;
  2635. switch( channel ) {
  2636. case ANIMCHANNEL_HEAD :
  2637. result = headAnim.AnimDone( blendFrames );
  2638. idThread::ReturnInt( result );
  2639. break;
  2640. case ANIMCHANNEL_TORSO :
  2641. result = torsoAnim.AnimDone( blendFrames );
  2642. idThread::ReturnInt( result );
  2643. break;
  2644. case ANIMCHANNEL_LEGS :
  2645. result = legsAnim.AnimDone( blendFrames );
  2646. idThread::ReturnInt( result );
  2647. break;
  2648. default:
  2649. gameLocal.Error( "Unknown anim group" );
  2650. }
  2651. }
  2652. /*
  2653. ================
  2654. idActor::Event_HasAnim
  2655. ================
  2656. */
  2657. void idActor::Event_HasAnim( int channel, const char *animname ) {
  2658. if ( GetAnim( channel, animname ) != NULL ) {
  2659. idThread::ReturnFloat( 1.0f );
  2660. } else {
  2661. idThread::ReturnFloat( 0.0f );
  2662. }
  2663. }
  2664. /*
  2665. ================
  2666. idActor::Event_CheckAnim
  2667. ================
  2668. */
  2669. void idActor::Event_CheckAnim( int channel, const char *animname ) {
  2670. if ( !GetAnim( channel, animname ) ) {
  2671. if ( animPrefix.Length() ) {
  2672. gameLocal.Error( "Can't find anim '%s_%s' for '%s'", animPrefix.c_str(), animname, name.c_str() );
  2673. } else {
  2674. gameLocal.Error( "Can't find anim '%s' for '%s'", animname, name.c_str() );
  2675. }
  2676. }
  2677. }
  2678. /*
  2679. ================
  2680. idActor::Event_ChooseAnim
  2681. ================
  2682. */
  2683. void idActor::Event_ChooseAnim( int channel, const char *animname ) {
  2684. int anim;
  2685. anim = GetAnim( channel, animname );
  2686. if ( anim ) {
  2687. if ( channel == ANIMCHANNEL_HEAD ) {
  2688. if ( head.GetEntity() ) {
  2689. idThread::ReturnString( head.GetEntity()->GetAnimator()->AnimFullName( anim ) );
  2690. return;
  2691. }
  2692. } else {
  2693. idThread::ReturnString( animator.AnimFullName( anim ) );
  2694. return;
  2695. }
  2696. }
  2697. idThread::ReturnString( "" );
  2698. }
  2699. /*
  2700. ================
  2701. idActor::Event_AnimLength
  2702. ================
  2703. */
  2704. void idActor::Event_AnimLength( int channel, const char *animname ) {
  2705. int anim;
  2706. anim = GetAnim( channel, animname );
  2707. if ( anim ) {
  2708. if ( channel == ANIMCHANNEL_HEAD ) {
  2709. if ( head.GetEntity() ) {
  2710. idThread::ReturnFloat( MS2SEC( head.GetEntity()->GetAnimator()->AnimLength( anim ) ) );
  2711. return;
  2712. }
  2713. } else {
  2714. idThread::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
  2715. return;
  2716. }
  2717. }
  2718. idThread::ReturnFloat( 0.0f );
  2719. }
  2720. /*
  2721. ================
  2722. idActor::Event_AnimDistance
  2723. ================
  2724. */
  2725. void idActor::Event_AnimDistance( int channel, const char *animname ) {
  2726. int anim;
  2727. anim = GetAnim( channel, animname );
  2728. if ( anim ) {
  2729. if ( channel == ANIMCHANNEL_HEAD ) {
  2730. if ( head.GetEntity() ) {
  2731. idThread::ReturnFloat( head.GetEntity()->GetAnimator()->TotalMovementDelta( anim ).Length() );
  2732. return;
  2733. }
  2734. } else {
  2735. idThread::ReturnFloat( animator.TotalMovementDelta( anim ).Length() );
  2736. return;
  2737. }
  2738. }
  2739. idThread::ReturnFloat( 0.0f );
  2740. }
  2741. /*
  2742. ================
  2743. idActor::Event_HasEnemies
  2744. ================
  2745. */
  2746. void idActor::Event_HasEnemies( void ) {
  2747. bool hasEnemy;
  2748. hasEnemy = HasEnemies();
  2749. idThread::ReturnInt( hasEnemy );
  2750. }
  2751. /*
  2752. ================
  2753. idActor::Event_NextEnemy
  2754. ================
  2755. */
  2756. void idActor::Event_NextEnemy( idEntity *ent ) {
  2757. idActor *actor;
  2758. if ( !ent || ( ent == this ) ) {
  2759. actor = enemyList.Next();
  2760. } else {
  2761. if ( !ent->IsType( idActor::Type ) ) {
  2762. gameLocal.Error( "'%s' cannot be an enemy", ent->name.c_str() );
  2763. }
  2764. actor = static_cast<idActor *>( ent );
  2765. if ( actor->enemyNode.ListHead() != &enemyList ) {
  2766. gameLocal.Error( "'%s' is not in '%s' enemy list", actor->name.c_str(), name.c_str() );
  2767. }
  2768. }
  2769. for( ; actor != NULL; actor = actor->enemyNode.Next() ) {
  2770. if ( !actor->fl.hidden ) {
  2771. idThread::ReturnEntity( actor );
  2772. return;
  2773. }
  2774. }
  2775. idThread::ReturnEntity( NULL );
  2776. }
  2777. /*
  2778. ================
  2779. idActor::Event_ClosestEnemyToPoint
  2780. ================
  2781. */
  2782. void idActor::Event_ClosestEnemyToPoint( const idVec3 &pos ) {
  2783. idActor *bestEnt = ClosestEnemyToPoint( pos );
  2784. idThread::ReturnEntity( bestEnt );
  2785. }
  2786. /*
  2787. ================
  2788. idActor::Event_StopSound
  2789. ================
  2790. */
  2791. void idActor::Event_StopSound( int channel, int netSync ) {
  2792. if ( channel == SND_CHANNEL_VOICE ) {
  2793. idEntity *headEnt = head.GetEntity();
  2794. if ( headEnt ) {
  2795. headEnt->StopSound( channel, ( netSync != 0 ) );
  2796. }
  2797. }
  2798. StopSound( channel, ( netSync != 0 ) );
  2799. }
  2800. /*
  2801. =====================
  2802. idActor::Event_SetNextState
  2803. =====================
  2804. */
  2805. void idActor::Event_SetNextState( const char *name ) {
  2806. idealState = GetScriptFunction( name );
  2807. if ( idealState == state ) {
  2808. state = NULL;
  2809. }
  2810. }
  2811. /*
  2812. =====================
  2813. idActor::Event_SetState
  2814. =====================
  2815. */
  2816. void idActor::Event_SetState( const char *name ) {
  2817. idealState = GetScriptFunction( name );
  2818. if ( idealState == state ) {
  2819. state = NULL;
  2820. }
  2821. scriptThread->DoneProcessing();
  2822. }
  2823. /*
  2824. =====================
  2825. idActor::Event_GetState
  2826. =====================
  2827. */
  2828. void idActor::Event_GetState( void ) {
  2829. if ( state ) {
  2830. idThread::ReturnString( state->Name() );
  2831. } else {
  2832. idThread::ReturnString( "" );
  2833. }
  2834. }
  2835. /*
  2836. =====================
  2837. idActor::Event_GetHead
  2838. =====================
  2839. */
  2840. void idActor::Event_GetHead( void ) {
  2841. idThread::ReturnEntity( head.GetEntity() );
  2842. }
  2843. #ifdef _D3XP
  2844. /*
  2845. ================
  2846. idActor::Event_SetDamageGroupScale
  2847. ================
  2848. */
  2849. void idActor::Event_SetDamageGroupScale( const char* groupName, float scale) {
  2850. for( int i = 0; i < damageScale.Num(); i++ ) {
  2851. if ( damageGroups[ i ] == groupName ) {
  2852. damageScale[ i ] = scale;
  2853. }
  2854. }
  2855. }
  2856. /*
  2857. ================
  2858. idActor::Event_SetDamageGroupScaleAll
  2859. ================
  2860. */
  2861. void idActor::Event_SetDamageGroupScaleAll( float scale ) {
  2862. for( int i = 0; i < damageScale.Num(); i++ ) {
  2863. damageScale[ i ] = scale;
  2864. }
  2865. }
  2866. void idActor::Event_GetDamageGroupScale( const char* groupName ) {
  2867. for( int i = 0; i < damageScale.Num(); i++ ) {
  2868. if ( damageGroups[ i ] == groupName ) {
  2869. idThread::ReturnFloat(damageScale[i]);
  2870. return;
  2871. }
  2872. }
  2873. idThread::ReturnFloat(0);
  2874. }
  2875. void idActor::Event_SetDamageCap( float _damageCap ) {
  2876. damageCap = _damageCap;
  2877. }
  2878. void idActor::Event_SetWaitState( const char* waitState) {
  2879. SetWaitState(waitState);
  2880. }
  2881. void idActor::Event_GetWaitState() {
  2882. if(WaitState()) {
  2883. idThread::ReturnString(WaitState());
  2884. } else {
  2885. idThread::ReturnString("");
  2886. }
  2887. }
  2888. #endif