AI_events.cpp 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913
  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. AI Events
  25. ***********************************************************************/
  26. const idEventDef AI_FindEnemy( "findEnemy", "d", 'e' );
  27. const idEventDef AI_FindEnemyAI( "findEnemyAI", "d", 'e' );
  28. const idEventDef AI_FindEnemyInCombatNodes( "findEnemyInCombatNodes", NULL, 'e' );
  29. const idEventDef AI_ClosestReachableEnemyOfEntity( "closestReachableEnemyOfEntity", "E", 'e' );
  30. const idEventDef AI_HeardSound( "heardSound", "d", 'e' );
  31. const idEventDef AI_SetEnemy( "setEnemy", "E" );
  32. const idEventDef AI_ClearEnemy( "clearEnemy" );
  33. const idEventDef AI_MuzzleFlash( "muzzleFlash", "s" );
  34. const idEventDef AI_CreateMissile( "createMissile", "s", 'e' );
  35. const idEventDef AI_AttackMissile( "attackMissile", "s", 'e' );
  36. const idEventDef AI_FireMissileAtTarget( "fireMissileAtTarget", "ss", 'e' );
  37. const idEventDef AI_LaunchMissile( "launchMissile", "vv", 'e' );
  38. #ifdef _D3XP
  39. const idEventDef AI_LaunchProjectile( "launchProjectile", "s" );
  40. #endif
  41. const idEventDef AI_AttackMelee( "attackMelee", "s", 'd' );
  42. const idEventDef AI_DirectDamage( "directDamage", "es" );
  43. const idEventDef AI_RadiusDamageFromJoint( "radiusDamageFromJoint", "ss" );
  44. const idEventDef AI_BeginAttack( "attackBegin", "s" );
  45. const idEventDef AI_EndAttack( "attackEnd" );
  46. const idEventDef AI_MeleeAttackToJoint( "meleeAttackToJoint", "ss", 'd' );
  47. const idEventDef AI_RandomPath( "randomPath", NULL, 'e' );
  48. const idEventDef AI_CanBecomeSolid( "canBecomeSolid", NULL, 'f' );
  49. const idEventDef AI_BecomeSolid( "becomeSolid" );
  50. const idEventDef AI_BecomeRagdoll( "becomeRagdoll", NULL, 'd' );
  51. const idEventDef AI_StopRagdoll( "stopRagdoll" );
  52. const idEventDef AI_SetHealth( "setHealth", "f" );
  53. const idEventDef AI_GetHealth( "getHealth", NULL, 'f' );
  54. const idEventDef AI_AllowDamage( "allowDamage" );
  55. const idEventDef AI_IgnoreDamage( "ignoreDamage" );
  56. const idEventDef AI_GetCurrentYaw( "getCurrentYaw", NULL, 'f' );
  57. const idEventDef AI_TurnTo( "turnTo", "f" );
  58. const idEventDef AI_TurnToPos( "turnToPos", "v" );
  59. const idEventDef AI_TurnToEntity( "turnToEntity", "E" );
  60. const idEventDef AI_MoveStatus( "moveStatus", NULL, 'd' );
  61. const idEventDef AI_StopMove( "stopMove" );
  62. const idEventDef AI_MoveToCover( "moveToCover" );
  63. const idEventDef AI_MoveToEnemy( "moveToEnemy" );
  64. const idEventDef AI_MoveToEnemyHeight( "moveToEnemyHeight" );
  65. const idEventDef AI_MoveOutOfRange( "moveOutOfRange", "ef" );
  66. const idEventDef AI_MoveToAttackPosition( "moveToAttackPosition", "es" );
  67. const idEventDef AI_Wander( "wander" );
  68. const idEventDef AI_MoveToEntity( "moveToEntity", "e" );
  69. const idEventDef AI_MoveToPosition( "moveToPosition", "v" );
  70. const idEventDef AI_SlideTo( "slideTo", "vf" );
  71. const idEventDef AI_FacingIdeal( "facingIdeal", NULL, 'd' );
  72. const idEventDef AI_FaceEnemy( "faceEnemy" );
  73. const idEventDef AI_FaceEntity( "faceEntity", "E" );
  74. const idEventDef AI_GetCombatNode( "getCombatNode", NULL, 'e' );
  75. const idEventDef AI_EnemyInCombatCone( "enemyInCombatCone", "Ed", 'd' );
  76. const idEventDef AI_WaitMove( "waitMove" );
  77. const idEventDef AI_GetJumpVelocity( "getJumpVelocity", "vff", 'v' );
  78. const idEventDef AI_EntityInAttackCone( "entityInAttackCone", "E", 'd' );
  79. const idEventDef AI_CanSeeEntity( "canSee", "E", 'd' );
  80. const idEventDef AI_SetTalkTarget( "setTalkTarget", "E" );
  81. const idEventDef AI_GetTalkTarget( "getTalkTarget", NULL, 'e' );
  82. const idEventDef AI_SetTalkState( "setTalkState", "d" );
  83. const idEventDef AI_EnemyRange( "enemyRange", NULL, 'f' );
  84. const idEventDef AI_EnemyRange2D( "enemyRange2D", NULL, 'f' );
  85. const idEventDef AI_GetEnemy( "getEnemy", NULL, 'e' );
  86. const idEventDef AI_GetEnemyPos( "getEnemyPos", NULL, 'v' );
  87. const idEventDef AI_GetEnemyEyePos( "getEnemyEyePos", NULL, 'v' );
  88. const idEventDef AI_PredictEnemyPos( "predictEnemyPos", "f", 'v' );
  89. const idEventDef AI_CanHitEnemy( "canHitEnemy", NULL, 'd' );
  90. const idEventDef AI_CanHitEnemyFromAnim( "canHitEnemyFromAnim", "s", 'd' );
  91. const idEventDef AI_CanHitEnemyFromJoint( "canHitEnemyFromJoint", "s", 'd' );
  92. const idEventDef AI_EnemyPositionValid( "enemyPositionValid", NULL, 'd' );
  93. const idEventDef AI_ChargeAttack( "chargeAttack", "s" );
  94. const idEventDef AI_TestChargeAttack( "testChargeAttack", NULL, 'f' );
  95. const idEventDef AI_TestMoveToPosition( "testMoveToPosition", "v", 'd' );
  96. const idEventDef AI_TestAnimMoveTowardEnemy( "testAnimMoveTowardEnemy", "s", 'd' );
  97. const idEventDef AI_TestAnimMove( "testAnimMove", "s", 'd' );
  98. const idEventDef AI_TestMeleeAttack( "testMeleeAttack", NULL, 'd' );
  99. const idEventDef AI_TestAnimAttack( "testAnimAttack", "s", 'd' );
  100. const idEventDef AI_Shrivel( "shrivel", "f" );
  101. const idEventDef AI_Burn( "burn" );
  102. const idEventDef AI_ClearBurn( "clearBurn" );
  103. const idEventDef AI_PreBurn( "preBurn" );
  104. const idEventDef AI_SetSmokeVisibility( "setSmokeVisibility", "dd" );
  105. const idEventDef AI_NumSmokeEmitters( "numSmokeEmitters", NULL, 'd' );
  106. const idEventDef AI_WaitAction( "waitAction", "s" );
  107. const idEventDef AI_StopThinking( "stopThinking" );
  108. const idEventDef AI_GetTurnDelta( "getTurnDelta", NULL, 'f' );
  109. const idEventDef AI_GetMoveType( "getMoveType", NULL, 'd' );
  110. const idEventDef AI_SetMoveType( "setMoveType", "d" );
  111. const idEventDef AI_SaveMove( "saveMove" );
  112. const idEventDef AI_RestoreMove( "restoreMove" );
  113. const idEventDef AI_AllowMovement( "allowMovement", "f" );
  114. const idEventDef AI_JumpFrame( "<jumpframe>" );
  115. const idEventDef AI_EnableClip( "enableClip" );
  116. const idEventDef AI_DisableClip( "disableClip" );
  117. const idEventDef AI_EnableGravity( "enableGravity" );
  118. const idEventDef AI_DisableGravity( "disableGravity" );
  119. const idEventDef AI_EnableAFPush( "enableAFPush" );
  120. const idEventDef AI_DisableAFPush( "disableAFPush" );
  121. const idEventDef AI_SetFlySpeed( "setFlySpeed", "f" );
  122. const idEventDef AI_SetFlyOffset( "setFlyOffset", "d" );
  123. const idEventDef AI_ClearFlyOffset( "clearFlyOffset" );
  124. const idEventDef AI_GetClosestHiddenTarget( "getClosestHiddenTarget", "s", 'e' );
  125. const idEventDef AI_GetRandomTarget( "getRandomTarget", "s", 'e' );
  126. const idEventDef AI_TravelDistanceToPoint( "travelDistanceToPoint", "v", 'f' );
  127. const idEventDef AI_TravelDistanceToEntity( "travelDistanceToEntity", "e", 'f' );
  128. const idEventDef AI_TravelDistanceBetweenPoints( "travelDistanceBetweenPoints", "vv", 'f' );
  129. const idEventDef AI_TravelDistanceBetweenEntities( "travelDistanceBetweenEntities", "ee", 'f' );
  130. const idEventDef AI_LookAtEntity( "lookAt", "Ef" );
  131. const idEventDef AI_LookAtEnemy( "lookAtEnemy", "f" );
  132. const idEventDef AI_SetJointMod( "setBoneMod", "d" );
  133. const idEventDef AI_ThrowMoveable( "throwMoveable" );
  134. const idEventDef AI_ThrowAF( "throwAF" );
  135. const idEventDef AI_RealKill( "<kill>" );
  136. const idEventDef AI_Kill( "kill" );
  137. const idEventDef AI_WakeOnFlashlight( "wakeOnFlashlight", "d" );
  138. const idEventDef AI_LocateEnemy( "locateEnemy" );
  139. const idEventDef AI_KickObstacles( "kickObstacles", "Ef" );
  140. const idEventDef AI_GetObstacle( "getObstacle", NULL, 'e' );
  141. const idEventDef AI_PushPointIntoAAS( "pushPointIntoAAS", "v", 'v' );
  142. const idEventDef AI_GetTurnRate( "getTurnRate", NULL, 'f' );
  143. const idEventDef AI_SetTurnRate( "setTurnRate", "f" );
  144. const idEventDef AI_AnimTurn( "animTurn", "f" );
  145. const idEventDef AI_AllowHiddenMovement( "allowHiddenMovement", "d" );
  146. const idEventDef AI_TriggerParticles( "triggerParticles", "s" );
  147. const idEventDef AI_FindActorsInBounds( "findActorsInBounds", "vv", 'e' );
  148. const idEventDef AI_CanReachPosition( "canReachPosition", "v", 'd' );
  149. const idEventDef AI_CanReachEntity( "canReachEntity", "E", 'd' );
  150. const idEventDef AI_CanReachEnemy( "canReachEnemy", NULL, 'd' );
  151. const idEventDef AI_GetReachableEntityPosition( "getReachableEntityPosition", "e", 'v' );
  152. #ifdef _D3XP
  153. const idEventDef AI_MoveToPositionDirect( "moveToPositionDirect", "v" );
  154. const idEventDef AI_AvoidObstacles( "avoidObstacles", "d" );
  155. const idEventDef AI_TriggerFX( "triggerFX", "ss" );
  156. const idEventDef AI_StartEmitter( "startEmitter", "sss", 'e' );
  157. const idEventDef AI_GetEmitter( "getEmitter", "s", 'e' );
  158. const idEventDef AI_StopEmitter( "stopEmitter", "s" );
  159. #endif
  160. CLASS_DECLARATION( idActor, idAI )
  161. EVENT( EV_Activate, idAI::Event_Activate )
  162. EVENT( EV_Touch, idAI::Event_Touch )
  163. EVENT( AI_FindEnemy, idAI::Event_FindEnemy )
  164. EVENT( AI_FindEnemyAI, idAI::Event_FindEnemyAI )
  165. EVENT( AI_FindEnemyInCombatNodes, idAI::Event_FindEnemyInCombatNodes )
  166. EVENT( AI_ClosestReachableEnemyOfEntity, idAI::Event_ClosestReachableEnemyOfEntity )
  167. EVENT( AI_HeardSound, idAI::Event_HeardSound )
  168. EVENT( AI_SetEnemy, idAI::Event_SetEnemy )
  169. EVENT( AI_ClearEnemy, idAI::Event_ClearEnemy )
  170. EVENT( AI_MuzzleFlash, idAI::Event_MuzzleFlash )
  171. EVENT( AI_CreateMissile, idAI::Event_CreateMissile )
  172. EVENT( AI_AttackMissile, idAI::Event_AttackMissile )
  173. EVENT( AI_FireMissileAtTarget, idAI::Event_FireMissileAtTarget )
  174. EVENT( AI_LaunchMissile, idAI::Event_LaunchMissile )
  175. #ifdef _D3XP
  176. EVENT( AI_LaunchProjectile, idAI::Event_LaunchProjectile )
  177. #endif
  178. EVENT( AI_AttackMelee, idAI::Event_AttackMelee )
  179. EVENT( AI_DirectDamage, idAI::Event_DirectDamage )
  180. EVENT( AI_RadiusDamageFromJoint, idAI::Event_RadiusDamageFromJoint )
  181. EVENT( AI_BeginAttack, idAI::Event_BeginAttack )
  182. EVENT( AI_EndAttack, idAI::Event_EndAttack )
  183. EVENT( AI_MeleeAttackToJoint, idAI::Event_MeleeAttackToJoint )
  184. EVENT( AI_RandomPath, idAI::Event_RandomPath )
  185. EVENT( AI_CanBecomeSolid, idAI::Event_CanBecomeSolid )
  186. EVENT( AI_BecomeSolid, idAI::Event_BecomeSolid )
  187. EVENT( EV_BecomeNonSolid, idAI::Event_BecomeNonSolid )
  188. EVENT( AI_BecomeRagdoll, idAI::Event_BecomeRagdoll )
  189. EVENT( AI_StopRagdoll, idAI::Event_StopRagdoll )
  190. EVENT( AI_SetHealth, idAI::Event_SetHealth )
  191. EVENT( AI_GetHealth, idAI::Event_GetHealth )
  192. EVENT( AI_AllowDamage, idAI::Event_AllowDamage )
  193. EVENT( AI_IgnoreDamage, idAI::Event_IgnoreDamage )
  194. EVENT( AI_GetCurrentYaw, idAI::Event_GetCurrentYaw )
  195. EVENT( AI_TurnTo, idAI::Event_TurnTo )
  196. EVENT( AI_TurnToPos, idAI::Event_TurnToPos )
  197. EVENT( AI_TurnToEntity, idAI::Event_TurnToEntity )
  198. EVENT( AI_MoveStatus, idAI::Event_MoveStatus )
  199. EVENT( AI_StopMove, idAI::Event_StopMove )
  200. EVENT( AI_MoveToCover, idAI::Event_MoveToCover )
  201. EVENT( AI_MoveToEnemy, idAI::Event_MoveToEnemy )
  202. EVENT( AI_MoveToEnemyHeight, idAI::Event_MoveToEnemyHeight )
  203. EVENT( AI_MoveOutOfRange, idAI::Event_MoveOutOfRange )
  204. EVENT( AI_MoveToAttackPosition, idAI::Event_MoveToAttackPosition )
  205. EVENT( AI_Wander, idAI::Event_Wander )
  206. EVENT( AI_MoveToEntity, idAI::Event_MoveToEntity )
  207. EVENT( AI_MoveToPosition, idAI::Event_MoveToPosition )
  208. EVENT( AI_SlideTo, idAI::Event_SlideTo )
  209. EVENT( AI_FacingIdeal, idAI::Event_FacingIdeal )
  210. EVENT( AI_FaceEnemy, idAI::Event_FaceEnemy )
  211. EVENT( AI_FaceEntity, idAI::Event_FaceEntity )
  212. EVENT( AI_WaitAction, idAI::Event_WaitAction )
  213. EVENT( AI_GetCombatNode, idAI::Event_GetCombatNode )
  214. EVENT( AI_EnemyInCombatCone, idAI::Event_EnemyInCombatCone )
  215. EVENT( AI_WaitMove, idAI::Event_WaitMove )
  216. EVENT( AI_GetJumpVelocity, idAI::Event_GetJumpVelocity )
  217. EVENT( AI_EntityInAttackCone, idAI::Event_EntityInAttackCone )
  218. EVENT( AI_CanSeeEntity, idAI::Event_CanSeeEntity )
  219. EVENT( AI_SetTalkTarget, idAI::Event_SetTalkTarget )
  220. EVENT( AI_GetTalkTarget, idAI::Event_GetTalkTarget )
  221. EVENT( AI_SetTalkState, idAI::Event_SetTalkState )
  222. EVENT( AI_EnemyRange, idAI::Event_EnemyRange )
  223. EVENT( AI_EnemyRange2D, idAI::Event_EnemyRange2D )
  224. EVENT( AI_GetEnemy, idAI::Event_GetEnemy )
  225. EVENT( AI_GetEnemyPos, idAI::Event_GetEnemyPos )
  226. EVENT( AI_GetEnemyEyePos, idAI::Event_GetEnemyEyePos )
  227. EVENT( AI_PredictEnemyPos, idAI::Event_PredictEnemyPos )
  228. EVENT( AI_CanHitEnemy, idAI::Event_CanHitEnemy )
  229. EVENT( AI_CanHitEnemyFromAnim, idAI::Event_CanHitEnemyFromAnim )
  230. EVENT( AI_CanHitEnemyFromJoint, idAI::Event_CanHitEnemyFromJoint )
  231. EVENT( AI_EnemyPositionValid, idAI::Event_EnemyPositionValid )
  232. EVENT( AI_ChargeAttack, idAI::Event_ChargeAttack )
  233. EVENT( AI_TestChargeAttack, idAI::Event_TestChargeAttack )
  234. EVENT( AI_TestAnimMoveTowardEnemy, idAI::Event_TestAnimMoveTowardEnemy )
  235. EVENT( AI_TestAnimMove, idAI::Event_TestAnimMove )
  236. EVENT( AI_TestMoveToPosition, idAI::Event_TestMoveToPosition )
  237. EVENT( AI_TestMeleeAttack, idAI::Event_TestMeleeAttack )
  238. EVENT( AI_TestAnimAttack, idAI::Event_TestAnimAttack )
  239. EVENT( AI_Shrivel, idAI::Event_Shrivel )
  240. EVENT( AI_Burn, idAI::Event_Burn )
  241. EVENT( AI_PreBurn, idAI::Event_PreBurn )
  242. EVENT( AI_SetSmokeVisibility, idAI::Event_SetSmokeVisibility )
  243. EVENT( AI_NumSmokeEmitters, idAI::Event_NumSmokeEmitters )
  244. EVENT( AI_ClearBurn, idAI::Event_ClearBurn )
  245. EVENT( AI_StopThinking, idAI::Event_StopThinking )
  246. EVENT( AI_GetTurnDelta, idAI::Event_GetTurnDelta )
  247. EVENT( AI_GetMoveType, idAI::Event_GetMoveType )
  248. EVENT( AI_SetMoveType, idAI::Event_SetMoveType )
  249. EVENT( AI_SaveMove, idAI::Event_SaveMove )
  250. EVENT( AI_RestoreMove, idAI::Event_RestoreMove )
  251. EVENT( AI_AllowMovement, idAI::Event_AllowMovement )
  252. EVENT( AI_JumpFrame, idAI::Event_JumpFrame )
  253. EVENT( AI_EnableClip, idAI::Event_EnableClip )
  254. EVENT( AI_DisableClip, idAI::Event_DisableClip )
  255. EVENT( AI_EnableGravity, idAI::Event_EnableGravity )
  256. EVENT( AI_DisableGravity, idAI::Event_DisableGravity )
  257. EVENT( AI_EnableAFPush, idAI::Event_EnableAFPush )
  258. EVENT( AI_DisableAFPush, idAI::Event_DisableAFPush )
  259. EVENT( AI_SetFlySpeed, idAI::Event_SetFlySpeed )
  260. EVENT( AI_SetFlyOffset, idAI::Event_SetFlyOffset )
  261. EVENT( AI_ClearFlyOffset, idAI::Event_ClearFlyOffset )
  262. EVENT( AI_GetClosestHiddenTarget, idAI::Event_GetClosestHiddenTarget )
  263. EVENT( AI_GetRandomTarget, idAI::Event_GetRandomTarget )
  264. EVENT( AI_TravelDistanceToPoint, idAI::Event_TravelDistanceToPoint )
  265. EVENT( AI_TravelDistanceToEntity, idAI::Event_TravelDistanceToEntity )
  266. EVENT( AI_TravelDistanceBetweenPoints, idAI::Event_TravelDistanceBetweenPoints )
  267. EVENT( AI_TravelDistanceBetweenEntities, idAI::Event_TravelDistanceBetweenEntities )
  268. EVENT( AI_LookAtEntity, idAI::Event_LookAtEntity )
  269. EVENT( AI_LookAtEnemy, idAI::Event_LookAtEnemy )
  270. EVENT( AI_SetJointMod, idAI::Event_SetJointMod )
  271. EVENT( AI_ThrowMoveable, idAI::Event_ThrowMoveable )
  272. EVENT( AI_ThrowAF, idAI::Event_ThrowAF )
  273. EVENT( EV_GetAngles, idAI::Event_GetAngles )
  274. EVENT( EV_SetAngles, idAI::Event_SetAngles )
  275. EVENT( AI_RealKill, idAI::Event_RealKill )
  276. EVENT( AI_Kill, idAI::Event_Kill )
  277. EVENT( AI_WakeOnFlashlight, idAI::Event_WakeOnFlashlight )
  278. EVENT( AI_LocateEnemy, idAI::Event_LocateEnemy )
  279. EVENT( AI_KickObstacles, idAI::Event_KickObstacles )
  280. EVENT( AI_GetObstacle, idAI::Event_GetObstacle )
  281. EVENT( AI_PushPointIntoAAS, idAI::Event_PushPointIntoAAS )
  282. EVENT( AI_GetTurnRate, idAI::Event_GetTurnRate )
  283. EVENT( AI_SetTurnRate, idAI::Event_SetTurnRate )
  284. EVENT( AI_AnimTurn, idAI::Event_AnimTurn )
  285. EVENT( AI_AllowHiddenMovement, idAI::Event_AllowHiddenMovement )
  286. EVENT( AI_TriggerParticles, idAI::Event_TriggerParticles )
  287. EVENT( AI_FindActorsInBounds, idAI::Event_FindActorsInBounds )
  288. EVENT( AI_CanReachPosition, idAI::Event_CanReachPosition )
  289. EVENT( AI_CanReachEntity, idAI::Event_CanReachEntity )
  290. EVENT( AI_CanReachEnemy, idAI::Event_CanReachEnemy )
  291. EVENT( AI_GetReachableEntityPosition, idAI::Event_GetReachableEntityPosition )
  292. #ifdef _D3XP
  293. EVENT( AI_MoveToPositionDirect, idAI::Event_MoveToPositionDirect )
  294. EVENT( AI_AvoidObstacles, idAI::Event_AvoidObstacles )
  295. EVENT( AI_TriggerFX, idAI::Event_TriggerFX )
  296. EVENT( AI_StartEmitter, idAI::Event_StartEmitter )
  297. EVENT( AI_GetEmitter, idAI::Event_GetEmitter )
  298. EVENT( AI_StopEmitter, idAI::Event_StopEmitter )
  299. #endif
  300. END_CLASS
  301. /*
  302. =====================
  303. idAI::Event_Activate
  304. =====================
  305. */
  306. void idAI::Event_Activate( idEntity *activator ) {
  307. Activate( activator );
  308. }
  309. /*
  310. =====================
  311. idAI::Event_Touch
  312. =====================
  313. */
  314. void idAI::Event_Touch( idEntity *other, trace_t *trace ) {
  315. if ( !enemy.GetEntity() && !other->fl.notarget && ( ReactionTo( other ) & ATTACK_ON_ACTIVATE ) ) {
  316. Activate( other );
  317. }
  318. AI_PUSHED = true;
  319. }
  320. /*
  321. =====================
  322. idAI::Event_FindEnemy
  323. =====================
  324. */
  325. void idAI::Event_FindEnemy( int useFOV ) {
  326. int i;
  327. idEntity *ent;
  328. idActor *actor;
  329. if ( gameLocal.InPlayerPVS( this ) ) {
  330. for ( i = 0; i < gameLocal.numClients ; i++ ) {
  331. ent = gameLocal.entities[ i ];
  332. if ( !ent || !ent->IsType( idActor::Type ) ) {
  333. continue;
  334. }
  335. actor = static_cast<idActor *>( ent );
  336. if ( ( actor->health <= 0 ) || !( ReactionTo( actor ) & ATTACK_ON_SIGHT ) ) {
  337. continue;
  338. }
  339. if ( CanSee( actor, useFOV != 0 ) ) {
  340. idThread::ReturnEntity( actor );
  341. return;
  342. }
  343. }
  344. }
  345. idThread::ReturnEntity( NULL );
  346. }
  347. /*
  348. =====================
  349. idAI::Event_FindEnemyAI
  350. =====================
  351. */
  352. void idAI::Event_FindEnemyAI( int useFOV ) {
  353. idEntity *ent;
  354. idActor *actor;
  355. idActor *bestEnemy;
  356. float bestDist;
  357. float dist;
  358. idVec3 delta;
  359. pvsHandle_t pvs;
  360. pvs = gameLocal.pvs.SetupCurrentPVS( GetPVSAreas(), GetNumPVSAreas() );
  361. bestDist = idMath::INFINITY;
  362. bestEnemy = NULL;
  363. for ( ent = gameLocal.activeEntities.Next(); ent != NULL; ent = ent->activeNode.Next() ) {
  364. if ( ent->fl.hidden || ent->fl.isDormant || !ent->IsType( idActor::Type ) ) {
  365. continue;
  366. }
  367. //bc ignore players.
  368. if ( ent->IsType( idPlayer::Type ) )
  369. {
  370. continue;
  371. }
  372. actor = static_cast<idActor *>( ent );
  373. if ( ( actor->health <= 0 ) || !( ReactionTo( actor ) & ATTACK_ON_SIGHT ) ) {
  374. continue;
  375. }
  376. if ( !gameLocal.pvs.InCurrentPVS( pvs, actor->GetPVSAreas(), actor->GetNumPVSAreas() ) ) {
  377. continue;
  378. }
  379. delta = physicsObj.GetOrigin() - actor->GetPhysics()->GetOrigin();
  380. dist = delta.LengthSqr();
  381. if ( ( dist < bestDist ) && CanSee( actor, useFOV != 0 ) ) {
  382. bestDist = dist;
  383. bestEnemy = actor;
  384. }
  385. }
  386. gameLocal.pvs.FreeCurrentPVS( pvs );
  387. idThread::ReturnEntity( bestEnemy );
  388. }
  389. /*
  390. =====================
  391. idAI::Event_FindEnemyInCombatNodes
  392. =====================
  393. */
  394. void idAI::Event_FindEnemyInCombatNodes( void ) {
  395. int i, j;
  396. idCombatNode *node;
  397. idEntity *ent;
  398. idEntity *targetEnt;
  399. idActor *actor;
  400. if ( !gameLocal.InPlayerPVS( this ) ) {
  401. // don't locate the player when we're not in his PVS
  402. idThread::ReturnEntity( NULL );
  403. return;
  404. }
  405. for ( i = 0; i < gameLocal.numClients ; i++ ) {
  406. ent = gameLocal.entities[ i ];
  407. if ( !ent || !ent->IsType( idActor::Type ) ) {
  408. continue;
  409. }
  410. actor = static_cast<idActor *>( ent );
  411. if ( ( actor->health <= 0 ) || !( ReactionTo( actor ) & ATTACK_ON_SIGHT ) ) {
  412. continue;
  413. }
  414. for( j = 0; j < targets.Num(); j++ ) {
  415. targetEnt = targets[ j ].GetEntity();
  416. if ( !targetEnt || !targetEnt->IsType( idCombatNode::Type ) ) {
  417. continue;
  418. }
  419. node = static_cast<idCombatNode *>( targetEnt );
  420. if ( !node->IsDisabled() && node->EntityInView( actor, actor->GetPhysics()->GetOrigin() ) ) {
  421. idThread::ReturnEntity( actor );
  422. return;
  423. }
  424. }
  425. }
  426. idThread::ReturnEntity( NULL );
  427. }
  428. /*
  429. =====================
  430. idAI::Event_ClosestReachableEnemyOfEntity
  431. =====================
  432. */
  433. void idAI::Event_ClosestReachableEnemyOfEntity( idEntity *team_mate ) {
  434. idActor *actor;
  435. idActor *ent;
  436. idActor *bestEnt;
  437. float bestDistSquared;
  438. float distSquared;
  439. idVec3 delta;
  440. int areaNum;
  441. int enemyAreaNum;
  442. aasPath_t path;
  443. if ( !team_mate->IsType( idActor::Type ) ) {
  444. gameLocal.Error( "Entity '%s' is not an AI character or player", team_mate->GetName() );
  445. }
  446. actor = static_cast<idActor *>( team_mate );
  447. const idVec3 &origin = physicsObj.GetOrigin();
  448. areaNum = PointReachableAreaNum( origin );
  449. bestDistSquared = idMath::INFINITY;
  450. bestEnt = NULL;
  451. for( ent = actor->enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
  452. if ( ent->fl.hidden ) {
  453. continue;
  454. }
  455. delta = ent->GetPhysics()->GetOrigin() - origin;
  456. distSquared = delta.LengthSqr();
  457. if ( distSquared < bestDistSquared ) {
  458. const idVec3 &enemyPos = ent->GetPhysics()->GetOrigin();
  459. enemyAreaNum = PointReachableAreaNum( enemyPos );
  460. if ( ( areaNum != 0 ) && PathToGoal( path, areaNum, origin, enemyAreaNum, enemyPos ) ) {
  461. bestEnt = ent;
  462. bestDistSquared = distSquared;
  463. }
  464. }
  465. }
  466. idThread::ReturnEntity( bestEnt );
  467. }
  468. /*
  469. =====================
  470. idAI::Event_HeardSound
  471. =====================
  472. */
  473. void idAI::Event_HeardSound( int ignore_team ) {
  474. // check if we heard any sounds in the last frame
  475. idActor *actor = gameLocal.GetAlertEntity();
  476. if ( actor && ( !ignore_team || ( ReactionTo( actor ) & ATTACK_ON_SIGHT ) ) && gameLocal.InPlayerPVS( this ) ) {
  477. idVec3 pos = actor->GetPhysics()->GetOrigin();
  478. idVec3 org = physicsObj.GetOrigin();
  479. float dist = ( pos - org ).LengthSqr();
  480. if ( dist < Square( AI_HEARING_RANGE ) ) {
  481. idThread::ReturnEntity( actor );
  482. return;
  483. }
  484. }
  485. idThread::ReturnEntity( NULL );
  486. }
  487. /*
  488. =====================
  489. idAI::Event_SetEnemy
  490. =====================
  491. */
  492. void idAI::Event_SetEnemy( idEntity *ent ) {
  493. if ( !ent ) {
  494. ClearEnemy();
  495. } else if ( !ent->IsType( idActor::Type ) ) {
  496. gameLocal.Error( "'%s' is not an idActor (player or ai controlled character)", ent->name.c_str() );
  497. } else {
  498. SetEnemy( static_cast<idActor *>( ent ) );
  499. }
  500. }
  501. /*
  502. =====================
  503. idAI::Event_ClearEnemy
  504. =====================
  505. */
  506. void idAI::Event_ClearEnemy( void ) {
  507. ClearEnemy();
  508. }
  509. /*
  510. =====================
  511. idAI::Event_MuzzleFlash
  512. =====================
  513. */
  514. void idAI::Event_MuzzleFlash( const char *jointname ) {
  515. idVec3 muzzle;
  516. idMat3 axis;
  517. GetMuzzle( jointname, muzzle, axis );
  518. TriggerWeaponEffects( muzzle );
  519. }
  520. /*
  521. =====================
  522. idAI::Event_CreateMissile
  523. =====================
  524. */
  525. void idAI::Event_CreateMissile( const char *jointname ) {
  526. idVec3 muzzle;
  527. idMat3 axis;
  528. if ( !projectileDef ) {
  529. gameLocal.Warning( "%s (%s) doesn't have a projectile specified", name.c_str(), GetEntityDefName() );
  530. return idThread::ReturnEntity( NULL );
  531. }
  532. GetMuzzle( jointname, muzzle, axis );
  533. CreateProjectile( muzzle, viewAxis[ 0 ] * physicsObj.GetGravityAxis() );
  534. if ( projectile.GetEntity() ) {
  535. if ( !jointname || !jointname[ 0 ] ) {
  536. projectile.GetEntity()->Bind( this, true );
  537. } else {
  538. projectile.GetEntity()->BindToJoint( this, jointname, true );
  539. }
  540. }
  541. idThread::ReturnEntity( projectile.GetEntity() );
  542. }
  543. /*
  544. =====================
  545. idAI::Event_AttackMissile
  546. =====================
  547. */
  548. void idAI::Event_AttackMissile( const char *jointname ) {
  549. idProjectile *proj;
  550. proj = LaunchProjectile( jointname, enemy.GetEntity(), true );
  551. idThread::ReturnEntity( proj );
  552. }
  553. /*
  554. =====================
  555. idAI::Event_FireMissileAtTarget
  556. =====================
  557. */
  558. void idAI::Event_FireMissileAtTarget( const char *jointname, const char *targetname ) {
  559. idEntity *aent;
  560. idProjectile *proj;
  561. aent = gameLocal.FindEntity( targetname );
  562. if ( !aent ) {
  563. gameLocal.Warning( "Entity '%s' not found for 'fireMissileAtTarget'", targetname );
  564. }
  565. proj = LaunchProjectile( jointname, aent, false );
  566. idThread::ReturnEntity( proj );
  567. }
  568. /*
  569. =====================
  570. idAI::Event_LaunchMissile
  571. =====================
  572. */
  573. void idAI::Event_LaunchMissile( const idVec3 &org, const idAngles &ang ) {
  574. idVec3 start;
  575. trace_t tr;
  576. idBounds projBounds;
  577. const idClipModel *projClip;
  578. idMat3 axis;
  579. float distance;
  580. if ( !projectileDef ) {
  581. gameLocal.Warning( "%s (%s) doesn't have a projectile specified", name.c_str(), GetEntityDefName() );
  582. idThread::ReturnEntity( NULL );
  583. return;
  584. }
  585. axis = ang.ToMat3();
  586. if ( !projectile.GetEntity() ) {
  587. CreateProjectile( org, axis[ 0 ] );
  588. }
  589. // make sure the projectile starts inside the monster bounding box
  590. const idBounds &ownerBounds = physicsObj.GetAbsBounds();
  591. projClip = projectile.GetEntity()->GetPhysics()->GetClipModel();
  592. projBounds = projClip->GetBounds().Rotate( projClip->GetAxis() );
  593. // check if the owner bounds is bigger than the projectile bounds
  594. if ( ( ( ownerBounds[1][0] - ownerBounds[0][0] ) > ( projBounds[1][0] - projBounds[0][0] ) ) &&
  595. ( ( ownerBounds[1][1] - ownerBounds[0][1] ) > ( projBounds[1][1] - projBounds[0][1] ) ) &&
  596. ( ( ownerBounds[1][2] - ownerBounds[0][2] ) > ( projBounds[1][2] - projBounds[0][2] ) ) ) {
  597. if ( (ownerBounds - projBounds).RayIntersection( org, viewAxis[ 0 ], distance ) ) {
  598. start = org + distance * viewAxis[ 0 ];
  599. } else {
  600. start = ownerBounds.GetCenter();
  601. }
  602. } else {
  603. // projectile bounds bigger than the owner bounds, so just start it from the center
  604. start = ownerBounds.GetCenter();
  605. }
  606. gameLocal.clip.Translation( tr, start, org, projClip, projClip->GetAxis(), MASK_SHOT_RENDERMODEL, this );
  607. // launch the projectile
  608. idThread::ReturnEntity( projectile.GetEntity() );
  609. projectile.GetEntity()->Launch( tr.endpos, axis[ 0 ], vec3_origin );
  610. projectile = NULL;
  611. TriggerWeaponEffects( tr.endpos );
  612. lastAttackTime = gameLocal.time;
  613. }
  614. #ifdef _D3XP
  615. /*
  616. =====================
  617. idAI::Event_LaunchProjectile
  618. =====================
  619. */
  620. void idAI::Event_LaunchProjectile( const char *entityDefName ) {
  621. idVec3 muzzle, start, dir;
  622. const idDict *projDef;
  623. idMat3 axis;
  624. const idClipModel *projClip;
  625. idBounds projBounds;
  626. trace_t tr;
  627. idEntity *ent;
  628. const char *clsname;
  629. float distance;
  630. idProjectile *proj = NULL;
  631. projDef = gameLocal.FindEntityDefDict( entityDefName );
  632. gameLocal.SpawnEntityDef( *projDef, &ent, false );
  633. if ( !ent ) {
  634. clsname = projectileDef->GetString( "classname" );
  635. gameLocal.Error( "Could not spawn entityDef '%s'", clsname );
  636. }
  637. if ( !ent->IsType( idProjectile::Type ) ) {
  638. clsname = ent->GetClassname();
  639. gameLocal.Error( "'%s' is not an idProjectile", clsname );
  640. }
  641. proj = ( idProjectile * )ent;
  642. GetMuzzle( "pistol", muzzle, axis );
  643. proj->Create( this, muzzle, axis[0] );
  644. // make sure the projectile starts inside the monster bounding box
  645. const idBounds &ownerBounds = physicsObj.GetAbsBounds();
  646. projClip = proj->GetPhysics()->GetClipModel();
  647. projBounds = projClip->GetBounds().Rotate( projClip->GetAxis() );
  648. if ( (ownerBounds - projBounds).RayIntersection( muzzle, viewAxis[ 0 ], distance ) ) {
  649. start = muzzle + distance * viewAxis[ 0 ];
  650. } else {
  651. start = ownerBounds.GetCenter();
  652. }
  653. gameLocal.clip.Translation( tr, start, muzzle, projClip, projClip->GetAxis(), MASK_SHOT_RENDERMODEL, this );
  654. muzzle = tr.endpos;
  655. GetAimDir( muzzle, enemy.GetEntity(), this, dir );
  656. proj->Launch( muzzle, dir, vec3_origin );
  657. TriggerWeaponEffects( muzzle );
  658. }
  659. #endif
  660. /*
  661. =====================
  662. idAI::Event_AttackMelee
  663. =====================
  664. */
  665. void idAI::Event_AttackMelee( const char *meleeDefName ) {
  666. bool hit;
  667. hit = AttackMelee( meleeDefName );
  668. idThread::ReturnInt( hit );
  669. }
  670. /*
  671. =====================
  672. idAI::Event_DirectDamage
  673. =====================
  674. */
  675. void idAI::Event_DirectDamage( idEntity *damageTarget, const char *damageDefName ) {
  676. DirectDamage( damageDefName, damageTarget );
  677. }
  678. /*
  679. =====================
  680. idAI::Event_RadiusDamageFromJoint
  681. =====================
  682. */
  683. void idAI::Event_RadiusDamageFromJoint( const char *jointname, const char *damageDefName ) {
  684. jointHandle_t joint;
  685. idVec3 org;
  686. idMat3 axis;
  687. if ( !jointname || !jointname[ 0 ] ) {
  688. org = physicsObj.GetOrigin();
  689. } else {
  690. joint = animator.GetJointHandle( jointname );
  691. if ( joint == INVALID_JOINT ) {
  692. gameLocal.Error( "Unknown joint '%s' on %s", jointname, GetEntityDefName() );
  693. }
  694. GetJointWorldTransform( joint, gameLocal.time, org, axis );
  695. }
  696. gameLocal.RadiusDamage( org, this, this, this, this, damageDefName );
  697. }
  698. /*
  699. =====================
  700. idAI::Event_RandomPath
  701. =====================
  702. */
  703. void idAI::Event_RandomPath( void ) {
  704. idPathCorner *path;
  705. path = idPathCorner::RandomPath( this, NULL );
  706. idThread::ReturnEntity( path );
  707. }
  708. /*
  709. =====================
  710. idAI::Event_BeginAttack
  711. =====================
  712. */
  713. void idAI::Event_BeginAttack( const char *name ) {
  714. BeginAttack( name );
  715. }
  716. /*
  717. =====================
  718. idAI::Event_EndAttack
  719. =====================
  720. */
  721. void idAI::Event_EndAttack( void ) {
  722. EndAttack();
  723. }
  724. /*
  725. =====================
  726. idAI::Event_MeleeAttackToJoint
  727. =====================
  728. */
  729. void idAI::Event_MeleeAttackToJoint( const char *jointname, const char *meleeDefName ) {
  730. jointHandle_t joint;
  731. idVec3 start;
  732. idVec3 end;
  733. idMat3 axis;
  734. trace_t trace;
  735. idEntity *hitEnt;
  736. joint = animator.GetJointHandle( jointname );
  737. if ( joint == INVALID_JOINT ) {
  738. gameLocal.Error( "Unknown joint '%s' on %s", jointname, GetEntityDefName() );
  739. }
  740. animator.GetJointTransform( joint, gameLocal.time, end, axis );
  741. end = physicsObj.GetOrigin() + ( end + modelOffset ) * viewAxis * physicsObj.GetGravityAxis();
  742. start = GetEyePosition();
  743. if ( ai_debugMove.GetBool() ) {
  744. gameRenderWorld->DebugLine( colorYellow, start, end, gameLocal.msec );
  745. }
  746. gameLocal.clip.TranslationEntities( trace, start, end, NULL, mat3_identity, MASK_SHOT_BOUNDINGBOX, this );
  747. if ( trace.fraction < 1.0f ) {
  748. hitEnt = gameLocal.GetTraceEntity( trace );
  749. if ( hitEnt && hitEnt->IsType( idActor::Type ) ) {
  750. DirectDamage( meleeDefName, hitEnt );
  751. idThread::ReturnInt( true );
  752. return;
  753. }
  754. }
  755. idThread::ReturnInt( false );
  756. }
  757. /*
  758. =====================
  759. idAI::Event_CanBecomeSolid
  760. =====================
  761. */
  762. void idAI::Event_CanBecomeSolid( void ) {
  763. int i;
  764. int num;
  765. #ifdef _D3XP
  766. bool returnValue = true;
  767. #endif
  768. idEntity * hit;
  769. idClipModel *cm;
  770. idClipModel *clipModels[ MAX_GENTITIES ];
  771. num = gameLocal.clip.ClipModelsTouchingBounds( physicsObj.GetAbsBounds(), MASK_MONSTERSOLID, clipModels, MAX_GENTITIES );
  772. for ( i = 0; i < num; i++ ) {
  773. cm = clipModels[ i ];
  774. // don't check render entities
  775. if ( cm->IsRenderModel() ) {
  776. continue;
  777. }
  778. hit = cm->GetEntity();
  779. if ( ( hit == this ) || !hit->fl.takedamage ) {
  780. continue;
  781. }
  782. #ifdef _D3XP
  783. if ( spawnClearMoveables && hit->IsType( idMoveable::Type ) || hit->IsType( idBarrel::Type ) || hit->IsType( idExplodingBarrel::Type ) ) {
  784. idVec3 push;
  785. push = hit->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  786. push.z = 30.f;
  787. push.NormalizeFast();
  788. if ( (idMath::Fabs(push.x) < 0.15f) && (idMath::Fabs(push.y) < 0.15f) ) {
  789. push.x = 10.f; push.y = 10.f; push.z = 15.f;
  790. push.NormalizeFast();
  791. }
  792. push *= 300.f;
  793. hit->GetPhysics()->SetLinearVelocity( push );
  794. }
  795. #endif
  796. if ( physicsObj.ClipContents( cm ) ) {
  797. #ifdef _D3XP
  798. returnValue = false;
  799. #else
  800. idThread::ReturnFloat( false );
  801. return;
  802. #endif
  803. }
  804. }
  805. #ifdef _D3XP
  806. idThread::ReturnFloat( returnValue );
  807. #else
  808. idThread::ReturnFloat( true );
  809. #endif
  810. }
  811. /*
  812. =====================
  813. idAI::Event_BecomeSolid
  814. =====================
  815. */
  816. void idAI::Event_BecomeSolid( void ) {
  817. physicsObj.EnableClip();
  818. if ( spawnArgs.GetBool( "big_monster" ) ) {
  819. physicsObj.SetContents( 0 );
  820. } else if ( use_combat_bbox ) {
  821. physicsObj.SetContents( CONTENTS_BODY|CONTENTS_SOLID );
  822. } else {
  823. physicsObj.SetContents( CONTENTS_BODY );
  824. }
  825. physicsObj.GetClipModel()->Link( gameLocal.clip );
  826. fl.takedamage = !spawnArgs.GetBool( "noDamage" );
  827. }
  828. /*
  829. =====================
  830. idAI::Event_BecomeNonSolid
  831. =====================
  832. */
  833. void idAI::Event_BecomeNonSolid( void ) {
  834. fl.takedamage = false;
  835. physicsObj.SetContents( 0 );
  836. physicsObj.GetClipModel()->Unlink();
  837. }
  838. /*
  839. =====================
  840. idAI::Event_BecomeRagdoll
  841. =====================
  842. */
  843. void idAI::Event_BecomeRagdoll( void ) {
  844. bool result;
  845. result = StartRagdoll();
  846. idThread::ReturnInt( result );
  847. }
  848. /*
  849. =====================
  850. idAI::Event_StopRagdoll
  851. =====================
  852. */
  853. void idAI::Event_StopRagdoll( void ) {
  854. StopRagdoll();
  855. // set back the monster physics
  856. SetPhysics( &physicsObj );
  857. }
  858. /*
  859. =====================
  860. idAI::Event_SetHealth
  861. =====================
  862. */
  863. void idAI::Event_SetHealth( float newHealth ) {
  864. health = newHealth;
  865. fl.takedamage = true;
  866. if ( health > 0 ) {
  867. AI_DEAD = false;
  868. } else {
  869. AI_DEAD = true;
  870. }
  871. }
  872. /*
  873. =====================
  874. idAI::Event_GetHealth
  875. =====================
  876. */
  877. void idAI::Event_GetHealth( void ) {
  878. idThread::ReturnFloat( health );
  879. }
  880. /*
  881. =====================
  882. idAI::Event_AllowDamage
  883. =====================
  884. */
  885. void idAI::Event_AllowDamage( void ) {
  886. fl.takedamage = true;
  887. }
  888. /*
  889. =====================
  890. idAI::Event_IgnoreDamage
  891. =====================
  892. */
  893. void idAI::Event_IgnoreDamage( void ) {
  894. fl.takedamage = false;
  895. }
  896. /*
  897. =====================
  898. idAI::Event_GetCurrentYaw
  899. =====================
  900. */
  901. void idAI::Event_GetCurrentYaw( void ) {
  902. idThread::ReturnFloat( current_yaw );
  903. }
  904. /*
  905. =====================
  906. idAI::Event_TurnTo
  907. =====================
  908. */
  909. void idAI::Event_TurnTo( float angle ) {
  910. TurnToward( angle );
  911. }
  912. /*
  913. =====================
  914. idAI::Event_TurnToPos
  915. =====================
  916. */
  917. void idAI::Event_TurnToPos( const idVec3 &pos ) {
  918. TurnToward( pos );
  919. }
  920. /*
  921. =====================
  922. idAI::Event_TurnToEntity
  923. =====================
  924. */
  925. void idAI::Event_TurnToEntity( idEntity *ent ) {
  926. if ( ent ) {
  927. TurnToward( ent->GetPhysics()->GetOrigin() );
  928. }
  929. }
  930. /*
  931. =====================
  932. idAI::Event_MoveStatus
  933. =====================
  934. */
  935. void idAI::Event_MoveStatus( void ) {
  936. idThread::ReturnInt( move.moveStatus );
  937. }
  938. /*
  939. =====================
  940. idAI::Event_StopMove
  941. =====================
  942. */
  943. void idAI::Event_StopMove( void ) {
  944. StopMove( MOVE_STATUS_DONE );
  945. }
  946. /*
  947. =====================
  948. idAI::Event_MoveToCover
  949. =====================
  950. */
  951. void idAI::Event_MoveToCover( void ) {
  952. idActor *enemyEnt = enemy.GetEntity();
  953. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  954. if ( !enemyEnt || !MoveToCover( enemyEnt, lastVisibleEnemyPos ) ) {
  955. return;
  956. }
  957. }
  958. /*
  959. =====================
  960. idAI::Event_MoveToEnemy
  961. =====================
  962. */
  963. void idAI::Event_MoveToEnemy( void ) {
  964. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  965. if ( !enemy.GetEntity() || !MoveToEnemy() ) {
  966. return;
  967. }
  968. }
  969. /*
  970. =====================
  971. idAI::Event_MoveToEnemyHeight
  972. =====================
  973. */
  974. void idAI::Event_MoveToEnemyHeight( void ) {
  975. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  976. MoveToEnemyHeight();
  977. }
  978. /*
  979. =====================
  980. idAI::Event_MoveOutOfRange
  981. =====================
  982. */
  983. void idAI::Event_MoveOutOfRange( idEntity *entity, float range ) {
  984. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  985. MoveOutOfRange( entity, range );
  986. }
  987. /*
  988. =====================
  989. idAI::Event_MoveToAttackPosition
  990. =====================
  991. */
  992. void idAI::Event_MoveToAttackPosition( idEntity *entity, const char *attack_anim ) {
  993. int anim;
  994. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  995. anim = GetAnim( ANIMCHANNEL_LEGS, attack_anim );
  996. if ( !anim ) {
  997. gameLocal.Error( "Unknown anim '%s'", attack_anim );
  998. }
  999. MoveToAttackPosition( entity, anim );
  1000. }
  1001. /*
  1002. =====================
  1003. idAI::Event_MoveToEntity
  1004. =====================
  1005. */
  1006. void idAI::Event_MoveToEntity( idEntity *ent ) {
  1007. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  1008. if ( ent ) {
  1009. MoveToEntity( ent );
  1010. }
  1011. }
  1012. /*
  1013. =====================
  1014. idAI::Event_MoveToPosition
  1015. =====================
  1016. */
  1017. void idAI::Event_MoveToPosition( const idVec3 &pos ) {
  1018. StopMove( MOVE_STATUS_DONE );
  1019. MoveToPosition( pos );
  1020. }
  1021. /*
  1022. =====================
  1023. idAI::Event_SlideTo
  1024. =====================
  1025. */
  1026. void idAI::Event_SlideTo( const idVec3 &pos, float time ) {
  1027. SlideToPosition( pos, time );
  1028. }
  1029. /*
  1030. =====================
  1031. idAI::Event_Wander
  1032. =====================
  1033. */
  1034. void idAI::Event_Wander( void ) {
  1035. WanderAround();
  1036. }
  1037. /*
  1038. =====================
  1039. idAI::Event_FacingIdeal
  1040. =====================
  1041. */
  1042. void idAI::Event_FacingIdeal( void ) {
  1043. bool facing = FacingIdeal();
  1044. idThread::ReturnInt( facing );
  1045. }
  1046. /*
  1047. =====================
  1048. idAI::Event_FaceEnemy
  1049. =====================
  1050. */
  1051. void idAI::Event_FaceEnemy( void ) {
  1052. FaceEnemy();
  1053. }
  1054. /*
  1055. =====================
  1056. idAI::Event_FaceEntity
  1057. =====================
  1058. */
  1059. void idAI::Event_FaceEntity( idEntity *ent ) {
  1060. FaceEntity( ent );
  1061. }
  1062. /*
  1063. =====================
  1064. idAI::Event_WaitAction
  1065. =====================
  1066. */
  1067. void idAI::Event_WaitAction( const char *waitForState ) {
  1068. if ( idThread::BeginMultiFrameEvent( this, &AI_WaitAction ) ) {
  1069. SetWaitState( waitForState );
  1070. }
  1071. if ( !WaitState() ) {
  1072. idThread::EndMultiFrameEvent( this, &AI_WaitAction );
  1073. }
  1074. }
  1075. /*
  1076. =====================
  1077. idAI::Event_GetCombatNode
  1078. =====================
  1079. */
  1080. void idAI::Event_GetCombatNode( void ) {
  1081. int i;
  1082. float dist;
  1083. idEntity *targetEnt;
  1084. idCombatNode *node;
  1085. float bestDist;
  1086. idCombatNode *bestNode;
  1087. idActor *enemyEnt = enemy.GetEntity();
  1088. if ( !targets.Num() ) {
  1089. // no combat nodes
  1090. idThread::ReturnEntity( NULL );
  1091. return;
  1092. }
  1093. if ( !enemyEnt || !EnemyPositionValid() ) {
  1094. // don't return a combat node if we don't have an enemy or
  1095. // if we can see he's not in the last place we saw him
  1096. #ifdef _D3XP
  1097. if ( team == 0 ) {
  1098. // find the closest attack node to the player
  1099. bestNode = NULL;
  1100. const idVec3 &myPos = physicsObj.GetOrigin();
  1101. const idVec3 &playerPos = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();
  1102. bestDist = ( myPos - playerPos ).LengthSqr();
  1103. for( i = 0; i < targets.Num(); i++ ) {
  1104. targetEnt = targets[ i ].GetEntity();
  1105. if ( !targetEnt || !targetEnt->IsType( idCombatNode::Type ) ) {
  1106. continue;
  1107. }
  1108. node = static_cast<idCombatNode *>( targetEnt );
  1109. if ( !node->IsDisabled() ) {
  1110. idVec3 org = node->GetPhysics()->GetOrigin();
  1111. dist = ( playerPos - org ).LengthSqr();
  1112. if ( dist < bestDist ) {
  1113. bestNode = node;
  1114. bestDist = dist;
  1115. }
  1116. }
  1117. }
  1118. idThread::ReturnEntity( bestNode );
  1119. return;
  1120. }
  1121. #endif
  1122. idThread::ReturnEntity( NULL );
  1123. return;
  1124. }
  1125. // find the closest attack node that can see our enemy and is closer than our enemy
  1126. bestNode = NULL;
  1127. const idVec3 &myPos = physicsObj.GetOrigin();
  1128. bestDist = ( myPos - lastVisibleEnemyPos ).LengthSqr();
  1129. for( i = 0; i < targets.Num(); i++ ) {
  1130. targetEnt = targets[ i ].GetEntity();
  1131. if ( !targetEnt || !targetEnt->IsType( idCombatNode::Type ) ) {
  1132. continue;
  1133. }
  1134. node = static_cast<idCombatNode *>( targetEnt );
  1135. if ( !node->IsDisabled() && node->EntityInView( enemyEnt, lastVisibleEnemyPos ) ) {
  1136. idVec3 org = node->GetPhysics()->GetOrigin();
  1137. dist = ( myPos - org ).LengthSqr();
  1138. if ( dist < bestDist ) {
  1139. bestNode = node;
  1140. bestDist = dist;
  1141. }
  1142. }
  1143. }
  1144. idThread::ReturnEntity( bestNode );
  1145. }
  1146. /*
  1147. =====================
  1148. idAI::Event_EnemyInCombatCone
  1149. =====================
  1150. */
  1151. void idAI::Event_EnemyInCombatCone( idEntity *ent, int use_current_enemy_location ) {
  1152. idCombatNode *node;
  1153. bool result;
  1154. idActor *enemyEnt = enemy.GetEntity();
  1155. if ( !targets.Num() ) {
  1156. // no combat nodes
  1157. idThread::ReturnInt( false );
  1158. return;
  1159. }
  1160. if ( !enemyEnt ) {
  1161. // have to have an enemy
  1162. idThread::ReturnInt( false );
  1163. return;
  1164. }
  1165. if ( !ent || !ent->IsType( idCombatNode::Type ) ) {
  1166. // not a combat node
  1167. idThread::ReturnInt( false );
  1168. return;
  1169. }
  1170. #ifdef _D3XP
  1171. //Allow the level designers define attack nodes that the enemy should never leave.
  1172. //This is different that the turrent type combat nodes because they can play an animation
  1173. if(ent->spawnArgs.GetBool("neverLeave", "0")) {
  1174. idThread::ReturnInt( true );
  1175. return;
  1176. }
  1177. #endif
  1178. node = static_cast<idCombatNode *>( ent );
  1179. if ( use_current_enemy_location ) {
  1180. const idVec3 &pos = enemyEnt->GetPhysics()->GetOrigin();
  1181. result = node->EntityInView( enemyEnt, pos );
  1182. } else {
  1183. result = node->EntityInView( enemyEnt, lastVisibleEnemyPos );
  1184. }
  1185. idThread::ReturnInt( result );
  1186. }
  1187. /*
  1188. =====================
  1189. idAI::Event_WaitMove
  1190. =====================
  1191. */
  1192. void idAI::Event_WaitMove( void ) {
  1193. idThread::BeginMultiFrameEvent( this, &AI_WaitMove );
  1194. if ( MoveDone() ) {
  1195. idThread::EndMultiFrameEvent( this, &AI_WaitMove );
  1196. }
  1197. }
  1198. /*
  1199. =====================
  1200. idAI::Event_GetJumpVelocity
  1201. =====================
  1202. */
  1203. void idAI::Event_GetJumpVelocity( const idVec3 &pos, float speed, float max_height ) {
  1204. idVec3 start;
  1205. idVec3 end;
  1206. idVec3 dir;
  1207. float dist;
  1208. bool result;
  1209. idEntity *enemyEnt = enemy.GetEntity();
  1210. if ( !enemyEnt ) {
  1211. idThread::ReturnVector( vec3_zero );
  1212. return;
  1213. }
  1214. if ( speed <= 0.0f ) {
  1215. gameLocal.Error( "Invalid speed. speed must be > 0." );
  1216. }
  1217. start = physicsObj.GetOrigin();
  1218. end = pos;
  1219. dir = end - start;
  1220. dist = dir.Normalize();
  1221. if ( dist > 16.0f ) {
  1222. dist -= 16.0f;
  1223. end -= dir * 16.0f;
  1224. }
  1225. result = PredictTrajectory( start, end, speed, physicsObj.GetGravity(), physicsObj.GetClipModel(), MASK_MONSTERSOLID, max_height, this, enemyEnt, ai_debugMove.GetBool() ? 4000 : 0, dir );
  1226. if ( result ) {
  1227. idThread::ReturnVector( dir * speed );
  1228. } else {
  1229. idThread::ReturnVector( vec3_zero );
  1230. }
  1231. }
  1232. /*
  1233. =====================
  1234. idAI::Event_EntityInAttackCone
  1235. =====================
  1236. */
  1237. void idAI::Event_EntityInAttackCone( idEntity *ent ) {
  1238. float attack_cone;
  1239. idVec3 delta;
  1240. float yaw;
  1241. float relYaw;
  1242. if ( !ent ) {
  1243. idThread::ReturnInt( false );
  1244. return;
  1245. }
  1246. delta = ent->GetPhysics()->GetOrigin() - GetEyePosition();
  1247. // get our gravity normal
  1248. const idVec3 &gravityDir = GetPhysics()->GetGravityNormal();
  1249. // infinite vertical vision, so project it onto our orientation plane
  1250. delta -= gravityDir * ( gravityDir * delta );
  1251. delta.Normalize();
  1252. yaw = delta.ToYaw();
  1253. attack_cone = spawnArgs.GetFloat( "attack_cone", "70" );
  1254. relYaw = idMath::AngleNormalize180( ideal_yaw - yaw );
  1255. if ( idMath::Fabs( relYaw ) < ( attack_cone * 0.5f ) ) {
  1256. idThread::ReturnInt( true );
  1257. } else {
  1258. idThread::ReturnInt( false );
  1259. }
  1260. }
  1261. /*
  1262. =====================
  1263. idAI::Event_CanSeeEntity
  1264. =====================
  1265. */
  1266. void idAI::Event_CanSeeEntity( idEntity *ent ) {
  1267. if ( !ent ) {
  1268. idThread::ReturnInt( false );
  1269. return;
  1270. }
  1271. bool cansee = CanSee( ent, false );
  1272. idThread::ReturnInt( cansee );
  1273. }
  1274. /*
  1275. =====================
  1276. idAI::Event_SetTalkTarget
  1277. =====================
  1278. */
  1279. void idAI::Event_SetTalkTarget( idEntity *target ) {
  1280. if ( target && !target->IsType( idActor::Type ) ) {
  1281. gameLocal.Error( "Cannot set talk target to '%s'. Not a character or player.", target->GetName() );
  1282. }
  1283. talkTarget = static_cast<idActor *>( target );
  1284. if ( target ) {
  1285. AI_TALK = true;
  1286. } else {
  1287. AI_TALK = false;
  1288. }
  1289. }
  1290. /*
  1291. =====================
  1292. idAI::Event_GetTalkTarget
  1293. =====================
  1294. */
  1295. void idAI::Event_GetTalkTarget( void ) {
  1296. idThread::ReturnEntity( talkTarget.GetEntity() );
  1297. }
  1298. /*
  1299. ================
  1300. idAI::Event_SetTalkState
  1301. ================
  1302. */
  1303. void idAI::Event_SetTalkState( int state ) {
  1304. if ( ( state < 0 ) || ( state >= NUM_TALK_STATES ) ) {
  1305. gameLocal.Error( "Invalid talk state (%d)", state );
  1306. }
  1307. talk_state = static_cast<talkState_t>( state );
  1308. }
  1309. /*
  1310. =====================
  1311. idAI::Event_EnemyRange
  1312. =====================
  1313. */
  1314. void idAI::Event_EnemyRange( void ) {
  1315. float dist;
  1316. idActor *enemyEnt = enemy.GetEntity();
  1317. if ( enemyEnt ) {
  1318. dist = ( enemyEnt->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).Length();
  1319. } else {
  1320. // Just some really high number
  1321. dist = idMath::INFINITY;
  1322. }
  1323. idThread::ReturnFloat( dist );
  1324. }
  1325. /*
  1326. =====================
  1327. idAI::Event_EnemyRange2D
  1328. =====================
  1329. */
  1330. void idAI::Event_EnemyRange2D( void ) {
  1331. float dist;
  1332. idActor *enemyEnt = enemy.GetEntity();
  1333. if ( enemyEnt ) {
  1334. dist = ( enemyEnt->GetPhysics()->GetOrigin().ToVec2() - GetPhysics()->GetOrigin().ToVec2() ).Length();
  1335. } else {
  1336. // Just some really high number
  1337. dist = idMath::INFINITY;
  1338. }
  1339. idThread::ReturnFloat( dist );
  1340. }
  1341. /*
  1342. =====================
  1343. idAI::Event_GetEnemy
  1344. =====================
  1345. */
  1346. void idAI::Event_GetEnemy( void ) {
  1347. idThread::ReturnEntity( enemy.GetEntity() );
  1348. }
  1349. /*
  1350. =====================
  1351. idAI::Event_GetEnemyPos
  1352. =====================
  1353. */
  1354. void idAI::Event_GetEnemyPos( void ) {
  1355. idThread::ReturnVector( lastVisibleEnemyPos );
  1356. }
  1357. /*
  1358. =====================
  1359. idAI::Event_GetEnemyEyePos
  1360. =====================
  1361. */
  1362. void idAI::Event_GetEnemyEyePos( void ) {
  1363. idThread::ReturnVector( lastVisibleEnemyPos + lastVisibleEnemyEyeOffset );
  1364. }
  1365. /*
  1366. =====================
  1367. idAI::Event_PredictEnemyPos
  1368. =====================
  1369. */
  1370. void idAI::Event_PredictEnemyPos( float time ) {
  1371. predictedPath_t path;
  1372. idActor *enemyEnt = enemy.GetEntity();
  1373. // if no enemy set
  1374. if ( !enemyEnt ) {
  1375. idThread::ReturnVector( physicsObj.GetOrigin() );
  1376. return;
  1377. }
  1378. // predict the enemy movement
  1379. idAI::PredictPath( enemyEnt, aas, lastVisibleEnemyPos, enemyEnt->GetPhysics()->GetLinearVelocity(), SEC2MS( time ), SEC2MS( time ), ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1380. idThread::ReturnVector( path.endPos );
  1381. }
  1382. /*
  1383. =====================
  1384. idAI::Event_CanHitEnemy
  1385. =====================
  1386. */
  1387. void idAI::Event_CanHitEnemy( void ) {
  1388. trace_t tr;
  1389. idEntity *hit;
  1390. idActor *enemyEnt = enemy.GetEntity();
  1391. if ( !AI_ENEMY_VISIBLE || !enemyEnt ) {
  1392. idThread::ReturnInt( false );
  1393. return;
  1394. }
  1395. // don't check twice per frame
  1396. if ( gameLocal.time == lastHitCheckTime ) {
  1397. idThread::ReturnInt( lastHitCheckResult );
  1398. return;
  1399. }
  1400. lastHitCheckTime = gameLocal.time;
  1401. idVec3 toPos = enemyEnt->GetEyePosition();
  1402. idVec3 eye = GetEyePosition();
  1403. idVec3 dir;
  1404. // expand the ray out as far as possible so we can detect anything behind the enemy
  1405. dir = toPos - eye;
  1406. dir.Normalize();
  1407. toPos = eye + dir * MAX_WORLD_SIZE;
  1408. gameLocal.clip.TracePoint( tr, eye, toPos, MASK_SHOT_BOUNDINGBOX, this );
  1409. hit = gameLocal.GetTraceEntity( tr );
  1410. if ( tr.fraction >= 1.0f || ( hit == enemyEnt ) ) {
  1411. lastHitCheckResult = true;
  1412. } else if ( ( tr.fraction < 1.0f ) && ( hit->IsType( idAI::Type ) ) &&
  1413. ( static_cast<idAI *>( hit )->team != team ) ) {
  1414. lastHitCheckResult = true;
  1415. } else {
  1416. lastHitCheckResult = false;
  1417. }
  1418. idThread::ReturnInt( lastHitCheckResult );
  1419. }
  1420. /*
  1421. =====================
  1422. idAI::Event_CanHitEnemyFromAnim
  1423. =====================
  1424. */
  1425. void idAI::Event_CanHitEnemyFromAnim( const char *animname ) {
  1426. int anim;
  1427. idVec3 dir;
  1428. idVec3 local_dir;
  1429. idVec3 fromPos;
  1430. idMat3 axis;
  1431. idVec3 start;
  1432. trace_t tr;
  1433. float distance;
  1434. idActor *enemyEnt = enemy.GetEntity();
  1435. if ( !AI_ENEMY_VISIBLE || !enemyEnt ) {
  1436. idThread::ReturnInt( false );
  1437. return;
  1438. }
  1439. anim = GetAnim( ANIMCHANNEL_LEGS, animname );
  1440. if ( !anim ) {
  1441. idThread::ReturnInt( false );
  1442. return;
  1443. }
  1444. // just do a ray test if close enough
  1445. if ( enemyEnt->GetPhysics()->GetAbsBounds().IntersectsBounds( physicsObj.GetAbsBounds().Expand( 16.0f ) ) ) {
  1446. Event_CanHitEnemy();
  1447. return;
  1448. }
  1449. // calculate the world transform of the launch position
  1450. const idVec3 &org = physicsObj.GetOrigin();
  1451. dir = lastVisibleEnemyPos - org;
  1452. physicsObj.GetGravityAxis().ProjectVector( dir, local_dir );
  1453. local_dir.z = 0.0f;
  1454. local_dir.ToVec2().Normalize();
  1455. axis = local_dir.ToMat3();
  1456. fromPos = physicsObj.GetOrigin() + missileLaunchOffset[ anim ] * axis;
  1457. if ( projectileClipModel == NULL ) {
  1458. CreateProjectileClipModel();
  1459. }
  1460. // check if the owner bounds is bigger than the projectile bounds
  1461. const idBounds &ownerBounds = physicsObj.GetAbsBounds();
  1462. const idBounds &projBounds = projectileClipModel->GetBounds();
  1463. if ( ( ( ownerBounds[1][0] - ownerBounds[0][0] ) > ( projBounds[1][0] - projBounds[0][0] ) ) &&
  1464. ( ( ownerBounds[1][1] - ownerBounds[0][1] ) > ( projBounds[1][1] - projBounds[0][1] ) ) &&
  1465. ( ( ownerBounds[1][2] - ownerBounds[0][2] ) > ( projBounds[1][2] - projBounds[0][2] ) ) ) {
  1466. if ( (ownerBounds - projBounds).RayIntersection( org, viewAxis[ 0 ], distance ) ) {
  1467. start = org + distance * viewAxis[ 0 ];
  1468. } else {
  1469. start = ownerBounds.GetCenter();
  1470. }
  1471. } else {
  1472. // projectile bounds bigger than the owner bounds, so just start it from the center
  1473. start = ownerBounds.GetCenter();
  1474. }
  1475. gameLocal.clip.Translation( tr, start, fromPos, projectileClipModel, mat3_identity, MASK_SHOT_RENDERMODEL, this );
  1476. fromPos = tr.endpos;
  1477. if ( GetAimDir( fromPos, enemy.GetEntity(), this, dir ) ) {
  1478. idThread::ReturnInt( true );
  1479. } else {
  1480. idThread::ReturnInt( false );
  1481. }
  1482. }
  1483. /*
  1484. =====================
  1485. idAI::Event_CanHitEnemyFromJoint
  1486. =====================
  1487. */
  1488. void idAI::Event_CanHitEnemyFromJoint( const char *jointname ) {
  1489. trace_t tr;
  1490. idVec3 muzzle;
  1491. idMat3 axis;
  1492. idVec3 start;
  1493. float distance;
  1494. idActor *enemyEnt = enemy.GetEntity();
  1495. if ( !AI_ENEMY_VISIBLE || !enemyEnt ) {
  1496. idThread::ReturnInt( false );
  1497. return;
  1498. }
  1499. // don't check twice per frame
  1500. if ( gameLocal.time == lastHitCheckTime ) {
  1501. idThread::ReturnInt( lastHitCheckResult );
  1502. return;
  1503. }
  1504. lastHitCheckTime = gameLocal.time;
  1505. const idVec3 &org = physicsObj.GetOrigin();
  1506. idVec3 toPos = enemyEnt->GetEyePosition();
  1507. jointHandle_t joint = animator.GetJointHandle( jointname );
  1508. if ( joint == INVALID_JOINT ) {
  1509. gameLocal.Error( "Unknown joint '%s' on %s", jointname, GetEntityDefName() );
  1510. }
  1511. animator.GetJointTransform( joint, gameLocal.time, muzzle, axis );
  1512. muzzle = org + ( muzzle + modelOffset ) * viewAxis * physicsObj.GetGravityAxis();
  1513. if ( projectileClipModel == NULL ) {
  1514. CreateProjectileClipModel();
  1515. }
  1516. // check if the owner bounds is bigger than the projectile bounds
  1517. const idBounds &ownerBounds = physicsObj.GetAbsBounds();
  1518. const idBounds &projBounds = projectileClipModel->GetBounds();
  1519. if ( ( ( ownerBounds[1][0] - ownerBounds[0][0] ) > ( projBounds[1][0] - projBounds[0][0] ) ) &&
  1520. ( ( ownerBounds[1][1] - ownerBounds[0][1] ) > ( projBounds[1][1] - projBounds[0][1] ) ) &&
  1521. ( ( ownerBounds[1][2] - ownerBounds[0][2] ) > ( projBounds[1][2] - projBounds[0][2] ) ) ) {
  1522. if ( (ownerBounds - projBounds).RayIntersection( org, viewAxis[ 0 ], distance ) ) {
  1523. start = org + distance * viewAxis[ 0 ];
  1524. } else {
  1525. start = ownerBounds.GetCenter();
  1526. }
  1527. } else {
  1528. // projectile bounds bigger than the owner bounds, so just start it from the center
  1529. start = ownerBounds.GetCenter();
  1530. }
  1531. gameLocal.clip.Translation( tr, start, muzzle, projectileClipModel, mat3_identity, MASK_SHOT_BOUNDINGBOX, this );
  1532. muzzle = tr.endpos;
  1533. gameLocal.clip.Translation( tr, muzzle, toPos, projectileClipModel, mat3_identity, MASK_SHOT_BOUNDINGBOX, this );
  1534. if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == enemyEnt ) ) {
  1535. lastHitCheckResult = true;
  1536. } else {
  1537. lastHitCheckResult = false;
  1538. }
  1539. idThread::ReturnInt( lastHitCheckResult );
  1540. }
  1541. /*
  1542. =====================
  1543. idAI::Event_EnemyPositionValid
  1544. =====================
  1545. */
  1546. void idAI::Event_EnemyPositionValid( void ) {
  1547. bool result;
  1548. result = EnemyPositionValid();
  1549. idThread::ReturnInt( result );
  1550. }
  1551. /*
  1552. =====================
  1553. idAI::Event_ChargeAttack
  1554. =====================
  1555. */
  1556. void idAI::Event_ChargeAttack( const char *damageDef ) {
  1557. idActor *enemyEnt = enemy.GetEntity();
  1558. StopMove( MOVE_STATUS_DEST_NOT_FOUND );
  1559. if ( enemyEnt ) {
  1560. idVec3 enemyOrg;
  1561. if ( move.moveType == MOVETYPE_FLY ) {
  1562. // position destination so that we're in the enemy's view
  1563. enemyOrg = enemyEnt->GetEyePosition();
  1564. enemyOrg -= enemyEnt->GetPhysics()->GetGravityNormal() * fly_offset;
  1565. } else {
  1566. enemyOrg = enemyEnt->GetPhysics()->GetOrigin();
  1567. }
  1568. BeginAttack( damageDef );
  1569. DirectMoveToPosition( enemyOrg );
  1570. TurnToward( enemyOrg );
  1571. }
  1572. }
  1573. /*
  1574. =====================
  1575. idAI::Event_TestChargeAttack
  1576. =====================
  1577. */
  1578. void idAI::Event_TestChargeAttack( void ) {
  1579. trace_t trace;
  1580. idActor *enemyEnt = enemy.GetEntity();
  1581. predictedPath_t path;
  1582. idVec3 end;
  1583. if ( !enemyEnt ) {
  1584. idThread::ReturnFloat( 0.0f );
  1585. return;
  1586. }
  1587. if ( move.moveType == MOVETYPE_FLY ) {
  1588. // position destination so that we're in the enemy's view
  1589. end = enemyEnt->GetEyePosition();
  1590. end -= enemyEnt->GetPhysics()->GetGravityNormal() * fly_offset;
  1591. } else {
  1592. end = enemyEnt->GetPhysics()->GetOrigin();
  1593. }
  1594. idAI::PredictPath( this, aas, physicsObj.GetOrigin(), end - physicsObj.GetOrigin(), 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1595. if ( ai_debugMove.GetBool() ) {
  1596. gameRenderWorld->DebugLine( colorGreen, physicsObj.GetOrigin(), end, gameLocal.msec );
  1597. gameRenderWorld->DebugBounds( path.endEvent == 0 ? colorYellow : colorRed, physicsObj.GetBounds(), end, gameLocal.msec );
  1598. }
  1599. if ( ( path.endEvent == 0 ) || ( path.blockingEntity == enemyEnt ) ) {
  1600. idVec3 delta = end - physicsObj.GetOrigin();
  1601. float time = delta.LengthFast();
  1602. idThread::ReturnFloat( time );
  1603. } else {
  1604. idThread::ReturnFloat( 0.0f );
  1605. }
  1606. }
  1607. /*
  1608. =====================
  1609. idAI::Event_TestAnimMoveTowardEnemy
  1610. =====================
  1611. */
  1612. void idAI::Event_TestAnimMoveTowardEnemy( const char *animname ) {
  1613. int anim;
  1614. predictedPath_t path;
  1615. idVec3 moveVec;
  1616. float yaw;
  1617. idVec3 delta;
  1618. idActor *enemyEnt;
  1619. enemyEnt = enemy.GetEntity();
  1620. if ( !enemyEnt ) {
  1621. idThread::ReturnInt( false );
  1622. return;
  1623. }
  1624. anim = GetAnim( ANIMCHANNEL_LEGS, animname );
  1625. if ( !anim ) {
  1626. gameLocal.DWarning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
  1627. idThread::ReturnInt( false );
  1628. return;
  1629. }
  1630. delta = enemyEnt->GetPhysics()->GetOrigin() - physicsObj.GetOrigin();
  1631. yaw = delta.ToYaw();
  1632. moveVec = animator.TotalMovementDelta( anim ) * idAngles( 0.0f, yaw, 0.0f ).ToMat3() * physicsObj.GetGravityAxis();
  1633. idAI::PredictPath( this, aas, physicsObj.GetOrigin(), moveVec, 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1634. if ( ai_debugMove.GetBool() ) {
  1635. gameRenderWorld->DebugLine( colorGreen, physicsObj.GetOrigin(), physicsObj.GetOrigin() + moveVec, gameLocal.msec );
  1636. gameRenderWorld->DebugBounds( path.endEvent == 0 ? colorYellow : colorRed, physicsObj.GetBounds(), physicsObj.GetOrigin() + moveVec, gameLocal.msec );
  1637. }
  1638. idThread::ReturnInt( path.endEvent == 0 );
  1639. }
  1640. /*
  1641. =====================
  1642. idAI::Event_TestAnimMove
  1643. =====================
  1644. */
  1645. void idAI::Event_TestAnimMove( const char *animname ) {
  1646. int anim;
  1647. predictedPath_t path;
  1648. idVec3 moveVec;
  1649. anim = GetAnim( ANIMCHANNEL_LEGS, animname );
  1650. if ( !anim ) {
  1651. gameLocal.DWarning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
  1652. idThread::ReturnInt( false );
  1653. return;
  1654. }
  1655. moveVec = animator.TotalMovementDelta( anim ) * idAngles( 0.0f, ideal_yaw, 0.0f ).ToMat3() * physicsObj.GetGravityAxis();
  1656. idAI::PredictPath( this, aas, physicsObj.GetOrigin(), moveVec, 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1657. if ( ai_debugMove.GetBool() ) {
  1658. gameRenderWorld->DebugLine( colorGreen, physicsObj.GetOrigin(), physicsObj.GetOrigin() + moveVec, gameLocal.msec );
  1659. gameRenderWorld->DebugBounds( path.endEvent == 0 ? colorYellow : colorRed, physicsObj.GetBounds(), physicsObj.GetOrigin() + moveVec, gameLocal.msec );
  1660. }
  1661. idThread::ReturnInt( path.endEvent == 0 );
  1662. }
  1663. /*
  1664. =====================
  1665. idAI::Event_TestMoveToPosition
  1666. =====================
  1667. */
  1668. void idAI::Event_TestMoveToPosition( const idVec3 &position ) {
  1669. predictedPath_t path;
  1670. idAI::PredictPath( this, aas, physicsObj.GetOrigin(), position - physicsObj.GetOrigin(), 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1671. if ( ai_debugMove.GetBool() ) {
  1672. gameRenderWorld->DebugLine( colorGreen, physicsObj.GetOrigin(), position, gameLocal.msec );
  1673. gameRenderWorld->DebugBounds( colorYellow, physicsObj.GetBounds(), position, gameLocal.msec );
  1674. if ( path.endEvent ) {
  1675. gameRenderWorld->DebugBounds( colorRed, physicsObj.GetBounds(), path.endPos, gameLocal.msec );
  1676. }
  1677. }
  1678. idThread::ReturnInt( path.endEvent == 0 );
  1679. }
  1680. /*
  1681. =====================
  1682. idAI::Event_TestMeleeAttack
  1683. =====================
  1684. */
  1685. void idAI::Event_TestMeleeAttack( void ) {
  1686. bool result = TestMelee();
  1687. idThread::ReturnInt( result );
  1688. }
  1689. /*
  1690. =====================
  1691. idAI::Event_TestAnimAttack
  1692. =====================
  1693. */
  1694. void idAI::Event_TestAnimAttack( const char *animname ) {
  1695. int anim;
  1696. predictedPath_t path;
  1697. anim = GetAnim( ANIMCHANNEL_LEGS, animname );
  1698. if ( !anim ) {
  1699. gameLocal.DWarning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
  1700. idThread::ReturnInt( false );
  1701. return;
  1702. }
  1703. idAI::PredictPath( this, aas, physicsObj.GetOrigin(), animator.TotalMovementDelta( anim ), 1000, 1000, ( move.moveType == MOVETYPE_FLY ) ? SE_BLOCKED : ( SE_ENTER_OBSTACLE | SE_BLOCKED | SE_ENTER_LEDGE_AREA ), path );
  1704. idThread::ReturnInt( path.blockingEntity && ( path.blockingEntity == enemy.GetEntity() ) );
  1705. }
  1706. /*
  1707. =====================
  1708. idAI::Event_Shrivel
  1709. =====================
  1710. */
  1711. void idAI::Event_Shrivel( float shrivel_time ) {
  1712. float t;
  1713. if ( idThread::BeginMultiFrameEvent( this, &AI_Shrivel ) ) {
  1714. if ( shrivel_time <= 0.0f ) {
  1715. idThread::EndMultiFrameEvent( this, &AI_Shrivel );
  1716. return;
  1717. }
  1718. shrivel_rate = 0.001f / shrivel_time;
  1719. shrivel_start = gameLocal.time;
  1720. }
  1721. t = ( gameLocal.time - shrivel_start ) * shrivel_rate;
  1722. if ( t > 0.25f ) {
  1723. renderEntity.noShadow = true;
  1724. }
  1725. if ( t > 1.0f ) {
  1726. t = 1.0f;
  1727. idThread::EndMultiFrameEvent( this, &AI_Shrivel );
  1728. }
  1729. renderEntity.shaderParms[ SHADERPARM_MD5_SKINSCALE ] = 1.0f - t * 0.5f;
  1730. UpdateVisuals();
  1731. }
  1732. /*
  1733. =====================
  1734. idAI::Event_PreBurn
  1735. =====================
  1736. */
  1737. void idAI::Event_PreBurn( void ) {
  1738. #ifdef _D3XP
  1739. // No grabbing after the burn has started!
  1740. noGrab = true;
  1741. #endif
  1742. // for now this just turns shadows off
  1743. renderEntity.noShadow = true;
  1744. }
  1745. /*
  1746. =====================
  1747. idAI::Event_Burn
  1748. =====================
  1749. */
  1750. void idAI::Event_Burn( void ) {
  1751. renderEntity.shaderParms[ SHADERPARM_TIME_OF_DEATH ] = gameLocal.time * 0.001f;
  1752. SpawnParticles( "smoke_burnParticleSystem" );
  1753. UpdateVisuals();
  1754. }
  1755. /*
  1756. =====================
  1757. idAI::Event_ClearBurn
  1758. =====================
  1759. */
  1760. void idAI::Event_ClearBurn( void ) {
  1761. renderEntity.noShadow = spawnArgs.GetBool( "noshadows" );
  1762. renderEntity.shaderParms[ SHADERPARM_TIME_OF_DEATH ] = 0.0f;
  1763. UpdateVisuals();
  1764. }
  1765. /*
  1766. =====================
  1767. idAI::Event_SetSmokeVisibility
  1768. =====================
  1769. */
  1770. void idAI::Event_SetSmokeVisibility( int num, int on ) {
  1771. int i;
  1772. int time;
  1773. if ( num >= particles.Num() ) {
  1774. gameLocal.Warning( "Particle #%d out of range (%d particles) on entity '%s'", num, particles.Num(), name.c_str() );
  1775. return;
  1776. }
  1777. if ( on != 0 ) {
  1778. time = gameLocal.time;
  1779. BecomeActive( TH_UPDATEPARTICLES );
  1780. } else {
  1781. time = 0;
  1782. }
  1783. if ( num >= 0 ) {
  1784. particles[ num ].time = time;
  1785. } else {
  1786. for ( i = 0; i < particles.Num(); i++ ) {
  1787. particles[ i ].time = time;
  1788. }
  1789. }
  1790. UpdateVisuals();
  1791. }
  1792. /*
  1793. =====================
  1794. idAI::Event_NumSmokeEmitters
  1795. =====================
  1796. */
  1797. void idAI::Event_NumSmokeEmitters( void ) {
  1798. idThread::ReturnInt( particles.Num() );
  1799. }
  1800. /*
  1801. =====================
  1802. idAI::Event_StopThinking
  1803. =====================
  1804. */
  1805. void idAI::Event_StopThinking( void ) {
  1806. BecomeInactive( TH_THINK );
  1807. idThread *thread = idThread::CurrentThread();
  1808. if ( thread ) {
  1809. thread->DoneProcessing();
  1810. }
  1811. }
  1812. /*
  1813. =====================
  1814. idAI::Event_GetTurnDelta
  1815. =====================
  1816. */
  1817. void idAI::Event_GetTurnDelta( void ) {
  1818. float amount;
  1819. if ( turnRate ) {
  1820. amount = idMath::AngleNormalize180( ideal_yaw - current_yaw );
  1821. idThread::ReturnFloat( amount );
  1822. } else {
  1823. idThread::ReturnFloat( 0.0f );
  1824. }
  1825. }
  1826. /*
  1827. =====================
  1828. idAI::Event_GetMoveType
  1829. =====================
  1830. */
  1831. void idAI::Event_GetMoveType( void ) {
  1832. idThread::ReturnInt( move.moveType );
  1833. }
  1834. /*
  1835. =====================
  1836. idAI::Event_SetMoveTypes
  1837. =====================
  1838. */
  1839. void idAI::Event_SetMoveType( int moveType ) {
  1840. if ( ( moveType < 0 ) || ( moveType >= NUM_MOVETYPES ) ) {
  1841. gameLocal.Error( "Invalid movetype %d", moveType );
  1842. }
  1843. move.moveType = static_cast<moveType_t>( moveType );
  1844. if ( move.moveType == MOVETYPE_FLY ) {
  1845. travelFlags = TFL_WALK|TFL_AIR|TFL_FLY;
  1846. } else {
  1847. travelFlags = TFL_WALK|TFL_AIR;
  1848. }
  1849. }
  1850. /*
  1851. =====================
  1852. idAI::Event_SaveMove
  1853. =====================
  1854. */
  1855. void idAI::Event_SaveMove( void ) {
  1856. savedMove = move;
  1857. }
  1858. /*
  1859. =====================
  1860. idAI::Event_RestoreMove
  1861. =====================
  1862. */
  1863. void idAI::Event_RestoreMove( void ) {
  1864. idVec3 goalPos;
  1865. idVec3 dest;
  1866. switch( savedMove.moveCommand ) {
  1867. case MOVE_NONE :
  1868. StopMove( savedMove.moveStatus );
  1869. break;
  1870. case MOVE_FACE_ENEMY :
  1871. FaceEnemy();
  1872. break;
  1873. case MOVE_FACE_ENTITY :
  1874. FaceEntity( savedMove.goalEntity.GetEntity() );
  1875. break;
  1876. case MOVE_TO_ENEMY :
  1877. MoveToEnemy();
  1878. break;
  1879. case MOVE_TO_ENEMYHEIGHT :
  1880. MoveToEnemyHeight();
  1881. break;
  1882. case MOVE_TO_ENTITY :
  1883. MoveToEntity( savedMove.goalEntity.GetEntity() );
  1884. break;
  1885. case MOVE_OUT_OF_RANGE :
  1886. MoveOutOfRange( savedMove.goalEntity.GetEntity(), savedMove.range );
  1887. break;
  1888. case MOVE_TO_ATTACK_POSITION :
  1889. MoveToAttackPosition( savedMove.goalEntity.GetEntity(), savedMove.anim );
  1890. break;
  1891. case MOVE_TO_COVER :
  1892. MoveToCover( savedMove.goalEntity.GetEntity(), lastVisibleEnemyPos );
  1893. break;
  1894. case MOVE_TO_POSITION :
  1895. MoveToPosition( savedMove.moveDest );
  1896. break;
  1897. case MOVE_TO_POSITION_DIRECT :
  1898. DirectMoveToPosition( savedMove.moveDest );
  1899. break;
  1900. case MOVE_SLIDE_TO_POSITION :
  1901. SlideToPosition( savedMove.moveDest, savedMove.duration );
  1902. break;
  1903. case MOVE_WANDER :
  1904. WanderAround();
  1905. break;
  1906. }
  1907. if ( GetMovePos( goalPos ) ) {
  1908. CheckObstacleAvoidance( goalPos, dest );
  1909. }
  1910. }
  1911. /*
  1912. =====================
  1913. idAI::Event_AllowMovement
  1914. =====================
  1915. */
  1916. void idAI::Event_AllowMovement( float flag ) {
  1917. allowMove = ( flag != 0.0f );
  1918. }
  1919. /*
  1920. =====================
  1921. idAI::Event_JumpFrame
  1922. =====================
  1923. */
  1924. void idAI::Event_JumpFrame( void ) {
  1925. AI_JUMP = true;
  1926. }
  1927. /*
  1928. =====================
  1929. idAI::Event_EnableClip
  1930. =====================
  1931. */
  1932. void idAI::Event_EnableClip( void ) {
  1933. physicsObj.SetClipMask( MASK_MONSTERSOLID );
  1934. disableGravity = false;
  1935. }
  1936. /*
  1937. =====================
  1938. idAI::Event_DisableClip
  1939. =====================
  1940. */
  1941. void idAI::Event_DisableClip( void ) {
  1942. physicsObj.SetClipMask( 0 );
  1943. disableGravity = true;
  1944. }
  1945. /*
  1946. =====================
  1947. idAI::Event_EnableGravity
  1948. =====================
  1949. */
  1950. void idAI::Event_EnableGravity( void ) {
  1951. disableGravity = false;
  1952. }
  1953. /*
  1954. =====================
  1955. idAI::Event_DisableGravity
  1956. =====================
  1957. */
  1958. void idAI::Event_DisableGravity( void ) {
  1959. disableGravity = true;
  1960. }
  1961. /*
  1962. =====================
  1963. idAI::Event_EnableAFPush
  1964. =====================
  1965. */
  1966. void idAI::Event_EnableAFPush( void ) {
  1967. af_push_moveables = true;
  1968. }
  1969. /*
  1970. =====================
  1971. idAI::Event_DisableAFPush
  1972. =====================
  1973. */
  1974. void idAI::Event_DisableAFPush( void ) {
  1975. af_push_moveables = false;
  1976. }
  1977. /*
  1978. =====================
  1979. idAI::Event_SetFlySpeed
  1980. =====================
  1981. */
  1982. void idAI::Event_SetFlySpeed( float speed ) {
  1983. if ( move.speed == fly_speed ) {
  1984. move.speed = speed;
  1985. }
  1986. fly_speed = speed;
  1987. }
  1988. /*
  1989. ================
  1990. idAI::Event_SetFlyOffset
  1991. ================
  1992. */
  1993. void idAI::Event_SetFlyOffset( int offset ) {
  1994. fly_offset = offset;
  1995. }
  1996. /*
  1997. ================
  1998. idAI::Event_ClearFlyOffset
  1999. ================
  2000. */
  2001. void idAI::Event_ClearFlyOffset( void ) {
  2002. spawnArgs.GetInt( "fly_offset", "0", fly_offset );
  2003. }
  2004. /*
  2005. =====================
  2006. idAI::Event_GetClosestHiddenTarget
  2007. =====================
  2008. */
  2009. void idAI::Event_GetClosestHiddenTarget( const char *type ) {
  2010. int i;
  2011. idEntity *ent;
  2012. idEntity *bestEnt;
  2013. float time;
  2014. float bestTime;
  2015. const idVec3 &org = physicsObj.GetOrigin();
  2016. idActor *enemyEnt = enemy.GetEntity();
  2017. if ( !enemyEnt ) {
  2018. // no enemy to hide from
  2019. idThread::ReturnEntity( NULL );
  2020. return;
  2021. }
  2022. if ( targets.Num() == 1 ) {
  2023. ent = targets[ 0 ].GetEntity();
  2024. if ( ent && idStr::Cmp( ent->GetEntityDefName(), type ) == 0 ) {
  2025. if ( !EntityCanSeePos( enemyEnt, lastVisibleEnemyPos, ent->GetPhysics()->GetOrigin() ) ) {
  2026. idThread::ReturnEntity( ent );
  2027. return;
  2028. }
  2029. }
  2030. idThread::ReturnEntity( NULL );
  2031. return;
  2032. }
  2033. bestEnt = NULL;
  2034. bestTime = idMath::INFINITY;
  2035. for( i = 0; i < targets.Num(); i++ ) {
  2036. ent = targets[ i ].GetEntity();
  2037. if ( ent && idStr::Cmp( ent->GetEntityDefName(), type ) == 0 ) {
  2038. const idVec3 &destOrg = ent->GetPhysics()->GetOrigin();
  2039. time = TravelDistance( org, destOrg );
  2040. if ( ( time >= 0.0f ) && ( time < bestTime ) ) {
  2041. if ( !EntityCanSeePos( enemyEnt, lastVisibleEnemyPos, destOrg ) ) {
  2042. bestEnt = ent;
  2043. bestTime = time;
  2044. }
  2045. }
  2046. }
  2047. }
  2048. idThread::ReturnEntity( bestEnt );
  2049. }
  2050. /*
  2051. =====================
  2052. idAI::Event_GetRandomTarget
  2053. =====================
  2054. */
  2055. void idAI::Event_GetRandomTarget( const char *type ) {
  2056. int i;
  2057. int num;
  2058. int which;
  2059. idEntity *ent;
  2060. idEntity *ents[ MAX_GENTITIES ];
  2061. num = 0;
  2062. for( i = 0; i < targets.Num(); i++ ) {
  2063. ent = targets[ i ].GetEntity();
  2064. if ( ent && idStr::Cmp( ent->GetEntityDefName(), type ) == 0 ) {
  2065. ents[ num++ ] = ent;
  2066. if ( num >= MAX_GENTITIES ) {
  2067. break;
  2068. }
  2069. }
  2070. }
  2071. if ( !num ) {
  2072. idThread::ReturnEntity( NULL );
  2073. return;
  2074. }
  2075. which = gameLocal.random.RandomInt( num );
  2076. idThread::ReturnEntity( ents[ which ] );
  2077. }
  2078. /*
  2079. ================
  2080. idAI::Event_TravelDistanceToPoint
  2081. ================
  2082. */
  2083. void idAI::Event_TravelDistanceToPoint( const idVec3 &pos ) {
  2084. float time;
  2085. time = TravelDistance( physicsObj.GetOrigin(), pos );
  2086. idThread::ReturnFloat( time );
  2087. }
  2088. /*
  2089. ================
  2090. idAI::Event_TravelDistanceToEntity
  2091. ================
  2092. */
  2093. void idAI::Event_TravelDistanceToEntity( idEntity *ent ) {
  2094. float time;
  2095. time = TravelDistance( physicsObj.GetOrigin(), ent->GetPhysics()->GetOrigin() );
  2096. idThread::ReturnFloat( time );
  2097. }
  2098. /*
  2099. ================
  2100. idAI::Event_TravelDistanceBetweenPoints
  2101. ================
  2102. */
  2103. void idAI::Event_TravelDistanceBetweenPoints( const idVec3 &source, const idVec3 &dest ) {
  2104. float time;
  2105. time = TravelDistance( source, dest );
  2106. idThread::ReturnFloat( time );
  2107. }
  2108. /*
  2109. ================
  2110. idAI::Event_TravelDistanceBetweenEntities
  2111. ================
  2112. */
  2113. void idAI::Event_TravelDistanceBetweenEntities( idEntity *source, idEntity *dest ) {
  2114. float time;
  2115. assert( source );
  2116. assert( dest );
  2117. time = TravelDistance( source->GetPhysics()->GetOrigin(), dest->GetPhysics()->GetOrigin() );
  2118. idThread::ReturnFloat( time );
  2119. }
  2120. /*
  2121. =====================
  2122. idAI::Event_LookAtEntity
  2123. =====================
  2124. */
  2125. void idAI::Event_LookAtEntity( idEntity *ent, float duration ) {
  2126. if ( ent == this ) {
  2127. ent = NULL;
  2128. }
  2129. if ( ( ent != focusEntity.GetEntity() ) || ( focusTime < gameLocal.time ) ) {
  2130. focusEntity = ent;
  2131. alignHeadTime = gameLocal.time;
  2132. forceAlignHeadTime = gameLocal.time + SEC2MS( 1 );
  2133. blink_time = 0;
  2134. }
  2135. focusTime = gameLocal.time + SEC2MS( duration );
  2136. }
  2137. /*
  2138. =====================
  2139. idAI::Event_LookAtEnemy
  2140. =====================
  2141. */
  2142. void idAI::Event_LookAtEnemy( float duration ) {
  2143. idActor *enemyEnt;
  2144. enemyEnt = enemy.GetEntity();
  2145. if ( ( enemyEnt != focusEntity.GetEntity() ) || ( focusTime < gameLocal.time ) ) {
  2146. focusEntity = enemyEnt;
  2147. alignHeadTime = gameLocal.time;
  2148. forceAlignHeadTime = gameLocal.time + SEC2MS( 1 );
  2149. blink_time = 0;
  2150. }
  2151. focusTime = gameLocal.time + SEC2MS( duration );
  2152. }
  2153. /*
  2154. ===============
  2155. idAI::Event_SetJointMod
  2156. ===============
  2157. */
  2158. void idAI::Event_SetJointMod( int allow ) {
  2159. allowJointMod = ( allow != 0 );
  2160. }
  2161. /*
  2162. ================
  2163. idAI::Event_ThrowMoveable
  2164. ================
  2165. */
  2166. void idAI::Event_ThrowMoveable( void ) {
  2167. idEntity *ent;
  2168. idEntity *moveable = NULL;
  2169. for ( ent = GetNextTeamEntity(); ent != NULL; ent = ent->GetNextTeamEntity() ) {
  2170. if ( ent->GetBindMaster() == this && ent->IsType( idMoveable::Type ) ) {
  2171. moveable = ent;
  2172. break;
  2173. }
  2174. }
  2175. if ( moveable ) {
  2176. moveable->Unbind();
  2177. moveable->PostEventMS( &EV_SetOwner, 200, NULL );
  2178. }
  2179. }
  2180. /*
  2181. ================
  2182. idAI::Event_ThrowAF
  2183. ================
  2184. */
  2185. void idAI::Event_ThrowAF( void ) {
  2186. idEntity *ent;
  2187. idEntity *af = NULL;
  2188. for ( ent = GetNextTeamEntity(); ent != NULL; ent = ent->GetNextTeamEntity() ) {
  2189. if ( ent->GetBindMaster() == this && ent->IsType( idAFEntity_Base::Type ) ) {
  2190. af = ent;
  2191. break;
  2192. }
  2193. }
  2194. if ( af ) {
  2195. af->Unbind();
  2196. af->PostEventMS( &EV_SetOwner, 200, NULL );
  2197. }
  2198. }
  2199. /*
  2200. ================
  2201. idAI::Event_SetAngles
  2202. ================
  2203. */
  2204. void idAI::Event_SetAngles( idAngles const &ang ) {
  2205. current_yaw = ang.yaw;
  2206. viewAxis = idAngles( 0, current_yaw, 0 ).ToMat3();
  2207. }
  2208. /*
  2209. ================
  2210. idAI::Event_GetAngles
  2211. ================
  2212. */
  2213. void idAI::Event_GetAngles( void ) {
  2214. idThread::ReturnVector( idVec3( 0.0f, current_yaw, 0.0f ) );
  2215. }
  2216. /*
  2217. ================
  2218. idAI::Event_RealKill
  2219. ================
  2220. */
  2221. void idAI::Event_RealKill( void ) {
  2222. health = 0;
  2223. if ( af.IsLoaded() ) {
  2224. // clear impacts
  2225. af.Rest();
  2226. // physics is turned off by calling af.Rest()
  2227. BecomeActive( TH_PHYSICS );
  2228. }
  2229. Killed( this, this, 0, vec3_zero, INVALID_JOINT );
  2230. }
  2231. /*
  2232. ================
  2233. idAI::Event_Kill
  2234. ================
  2235. */
  2236. void idAI::Event_Kill( void ) {
  2237. PostEventMS( &AI_RealKill, 0 );
  2238. }
  2239. /*
  2240. ================
  2241. idAI::Event_WakeOnFlashlight
  2242. ================
  2243. */
  2244. void idAI::Event_WakeOnFlashlight( int enable ) {
  2245. wakeOnFlashlight = ( enable != 0 );
  2246. }
  2247. /*
  2248. ================
  2249. idAI::Event_LocateEnemy
  2250. ================
  2251. */
  2252. void idAI::Event_LocateEnemy( void ) {
  2253. idActor *enemyEnt;
  2254. int areaNum;
  2255. enemyEnt = enemy.GetEntity();
  2256. if ( !enemyEnt ) {
  2257. return;
  2258. }
  2259. enemyEnt->GetAASLocation( aas, lastReachableEnemyPos, areaNum );
  2260. SetEnemyPosition();
  2261. UpdateEnemyPosition();
  2262. }
  2263. /*
  2264. ================
  2265. idAI::Event_KickObstacles
  2266. ================
  2267. */
  2268. void idAI::Event_KickObstacles( idEntity *kickEnt, float force ) {
  2269. idVec3 dir;
  2270. idEntity *obEnt;
  2271. if ( kickEnt ) {
  2272. obEnt = kickEnt;
  2273. } else {
  2274. obEnt = move.obstacle.GetEntity();
  2275. }
  2276. if ( obEnt ) {
  2277. dir = obEnt->GetPhysics()->GetOrigin() - physicsObj.GetOrigin();
  2278. dir.Normalize();
  2279. } else {
  2280. dir = viewAxis[ 0 ];
  2281. }
  2282. KickObstacles( dir, force, obEnt );
  2283. }
  2284. /*
  2285. ================
  2286. idAI::Event_GetObstacle
  2287. ================
  2288. */
  2289. void idAI::Event_GetObstacle( void ) {
  2290. idThread::ReturnEntity( move.obstacle.GetEntity() );
  2291. }
  2292. /*
  2293. ================
  2294. idAI::Event_PushPointIntoAAS
  2295. ================
  2296. */
  2297. void idAI::Event_PushPointIntoAAS( const idVec3 &pos ) {
  2298. int areaNum;
  2299. idVec3 newPos;
  2300. areaNum = PointReachableAreaNum( pos );
  2301. if ( areaNum ) {
  2302. newPos = pos;
  2303. aas->PushPointIntoAreaNum( areaNum, newPos );
  2304. idThread::ReturnVector( newPos );
  2305. } else {
  2306. idThread::ReturnVector( pos );
  2307. }
  2308. }
  2309. /*
  2310. ================
  2311. idAI::Event_GetTurnRate
  2312. ================
  2313. */
  2314. void idAI::Event_GetTurnRate( void ) {
  2315. idThread::ReturnFloat( turnRate );
  2316. }
  2317. /*
  2318. ================
  2319. idAI::Event_SetTurnRate
  2320. ================
  2321. */
  2322. void idAI::Event_SetTurnRate( float rate ) {
  2323. turnRate = rate;
  2324. }
  2325. /*
  2326. ================
  2327. idAI::Event_AnimTurn
  2328. ================
  2329. */
  2330. void idAI::Event_AnimTurn( float angles ) {
  2331. turnVel = 0.0f;
  2332. anim_turn_angles = angles;
  2333. if ( angles ) {
  2334. anim_turn_yaw = current_yaw;
  2335. anim_turn_amount = idMath::Fabs( idMath::AngleNormalize180( current_yaw - ideal_yaw ) );
  2336. if ( anim_turn_amount > anim_turn_angles ) {
  2337. anim_turn_amount = anim_turn_angles;
  2338. }
  2339. } else {
  2340. anim_turn_amount = 0.0f;
  2341. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( 0, 1.0f );
  2342. animator.CurrentAnim( ANIMCHANNEL_LEGS )->SetSyncedAnimWeight( 1, 0.0f );
  2343. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( 0, 1.0f );
  2344. animator.CurrentAnim( ANIMCHANNEL_TORSO )->SetSyncedAnimWeight( 1, 0.0f );
  2345. }
  2346. }
  2347. /*
  2348. ================
  2349. idAI::Event_AllowHiddenMovement
  2350. ================
  2351. */
  2352. void idAI::Event_AllowHiddenMovement( int enable ) {
  2353. allowHiddenMovement = ( enable != 0 );
  2354. }
  2355. /*
  2356. ================
  2357. idAI::Event_TriggerParticles
  2358. ================
  2359. */
  2360. void idAI::Event_TriggerParticles( const char *jointName ) {
  2361. TriggerParticles( jointName );
  2362. }
  2363. /*
  2364. =====================
  2365. idAI::Event_FindActorsInBounds
  2366. =====================
  2367. */
  2368. void idAI::Event_FindActorsInBounds( const idVec3 &mins, const idVec3 &maxs ) {
  2369. idEntity * ent;
  2370. idEntity * entityList[ MAX_GENTITIES ];
  2371. int numListedEntities;
  2372. int i;
  2373. numListedEntities = gameLocal.clip.EntitiesTouchingBounds( idBounds( mins, maxs ), CONTENTS_BODY, entityList, MAX_GENTITIES );
  2374. for( i = 0; i < numListedEntities; i++ ) {
  2375. ent = entityList[ i ];
  2376. if ( ent != this && !ent->IsHidden() && ( ent->health > 0 ) && ent->IsType( idActor::Type ) ) {
  2377. idThread::ReturnEntity( ent );
  2378. return;
  2379. }
  2380. }
  2381. idThread::ReturnEntity( NULL );
  2382. }
  2383. /*
  2384. ================
  2385. idAI::Event_CanReachPosition
  2386. ================
  2387. */
  2388. void idAI::Event_CanReachPosition( const idVec3 &pos ) {
  2389. aasPath_t path;
  2390. int toAreaNum;
  2391. int areaNum;
  2392. toAreaNum = PointReachableAreaNum( pos );
  2393. areaNum = PointReachableAreaNum( physicsObj.GetOrigin() );
  2394. if ( !toAreaNum || !PathToGoal( path, areaNum, physicsObj.GetOrigin(), toAreaNum, pos ) ) {
  2395. idThread::ReturnInt( false );
  2396. } else {
  2397. idThread::ReturnInt( true );
  2398. }
  2399. }
  2400. /*
  2401. ================
  2402. idAI::Event_CanReachEntity
  2403. ================
  2404. */
  2405. void idAI::Event_CanReachEntity( idEntity *ent ) {
  2406. aasPath_t path;
  2407. int toAreaNum;
  2408. int areaNum;
  2409. idVec3 pos;
  2410. if ( !ent ) {
  2411. idThread::ReturnInt( false );
  2412. return;
  2413. }
  2414. if ( move.moveType != MOVETYPE_FLY ) {
  2415. if ( !ent->GetFloorPos( 64.0f, pos ) ) {
  2416. idThread::ReturnInt( false );
  2417. return;
  2418. }
  2419. if ( ent->IsType( idActor::Type ) && static_cast<idActor *>( ent )->OnLadder() ) {
  2420. idThread::ReturnInt( false );
  2421. return;
  2422. }
  2423. } else {
  2424. pos = ent->GetPhysics()->GetOrigin();
  2425. }
  2426. toAreaNum = PointReachableAreaNum( pos );
  2427. if ( !toAreaNum ) {
  2428. idThread::ReturnInt( false );
  2429. return;
  2430. }
  2431. const idVec3 &org = physicsObj.GetOrigin();
  2432. areaNum = PointReachableAreaNum( org );
  2433. if ( !toAreaNum || !PathToGoal( path, areaNum, org, toAreaNum, pos ) ) {
  2434. idThread::ReturnInt( false );
  2435. } else {
  2436. idThread::ReturnInt( true );
  2437. }
  2438. }
  2439. /*
  2440. ================
  2441. idAI::Event_CanReachEnemy
  2442. ================
  2443. */
  2444. void idAI::Event_CanReachEnemy( void ) {
  2445. aasPath_t path;
  2446. int toAreaNum;
  2447. int areaNum;
  2448. idVec3 pos;
  2449. idActor *enemyEnt;
  2450. enemyEnt = enemy.GetEntity();
  2451. if ( !enemyEnt ) {
  2452. idThread::ReturnInt( false );
  2453. return;
  2454. }
  2455. if ( move.moveType != MOVETYPE_FLY ) {
  2456. if ( enemyEnt->OnLadder() ) {
  2457. idThread::ReturnInt( false );
  2458. return;
  2459. }
  2460. enemyEnt->GetAASLocation( aas, pos, toAreaNum );
  2461. } else {
  2462. pos = enemyEnt->GetPhysics()->GetOrigin();
  2463. toAreaNum = PointReachableAreaNum( pos );
  2464. }
  2465. if ( !toAreaNum ) {
  2466. idThread::ReturnInt( false );
  2467. return;
  2468. }
  2469. const idVec3 &org = physicsObj.GetOrigin();
  2470. areaNum = PointReachableAreaNum( org );
  2471. if ( !PathToGoal( path, areaNum, org, toAreaNum, pos ) ) {
  2472. idThread::ReturnInt( false );
  2473. } else {
  2474. idThread::ReturnInt( true );
  2475. }
  2476. }
  2477. /*
  2478. ================
  2479. idAI::Event_GetReachableEntityPosition
  2480. ================
  2481. */
  2482. void idAI::Event_GetReachableEntityPosition( idEntity *ent ) {
  2483. int toAreaNum;
  2484. idVec3 pos;
  2485. if ( move.moveType != MOVETYPE_FLY ) {
  2486. if ( !ent->GetFloorPos( 64.0f, pos ) ) {
  2487. // NOTE: not a good way to return 'false'
  2488. return idThread::ReturnVector( vec3_zero );
  2489. }
  2490. if ( ent->IsType( idActor::Type ) && static_cast<idActor *>( ent )->OnLadder() ) {
  2491. // NOTE: not a good way to return 'false'
  2492. return idThread::ReturnVector( vec3_zero );
  2493. }
  2494. } else {
  2495. pos = ent->GetPhysics()->GetOrigin();
  2496. }
  2497. if ( aas ) {
  2498. toAreaNum = PointReachableAreaNum( pos );
  2499. aas->PushPointIntoAreaNum( toAreaNum, pos );
  2500. }
  2501. idThread::ReturnVector( pos );
  2502. }
  2503. #ifdef _D3XP
  2504. /*
  2505. ================
  2506. idAI::Event_MoveToPositionDirect
  2507. ================
  2508. */
  2509. void idAI::Event_MoveToPositionDirect( const idVec3 &pos ) {
  2510. StopMove( MOVE_STATUS_DONE );
  2511. DirectMoveToPosition( pos );
  2512. }
  2513. /*
  2514. ================
  2515. idAI::Event_AvoidObstacles
  2516. ================
  2517. */
  2518. void idAI::Event_AvoidObstacles( int ignore) {
  2519. ignore_obstacles = (ignore == 1) ? false : true;
  2520. }
  2521. /*
  2522. ================
  2523. idAI::Event_TriggerFX
  2524. ================
  2525. */
  2526. void idAI::Event_TriggerFX( const char* joint, const char* fx ) {
  2527. TriggerFX(joint, fx);
  2528. }
  2529. void idAI::Event_StartEmitter( const char* name, const char* joint, const char* particle ) {
  2530. idEntity *ent = StartEmitter(name, joint, particle);
  2531. idThread::ReturnEntity(ent);
  2532. }
  2533. void idAI::Event_GetEmitter( const char* name ) {
  2534. idThread::ReturnEntity(GetEmitter(name));
  2535. }
  2536. void idAI::Event_StopEmitter( const char* name ) {
  2537. StopEmitter(name);
  2538. }
  2539. #endif