AI_events.cpp 75 KB

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