mendozabossgameobj.cpp 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : combat *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/mendozabossgameobj.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/23/02 3:28p $*
  29. * *
  30. * $Revision:: 13 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "mendozabossgameobj.h"
  36. #include "wwhack.h"
  37. #include "simpledefinitionfactory.h"
  38. #include "persistfactory.h"
  39. #include "combatchunkid.h"
  40. #include "debug.h"
  41. #include "animcontrol.h"
  42. #include "crandom.h"
  43. #include "weapons.h"
  44. #include "rendobj.h"
  45. #include "wwaudio.h"
  46. #include "audiblesound.h"
  47. #include "explosion.h"
  48. #include "phys.h"
  49. #include "pscene.h"
  50. #include "waypath.h"
  51. #include "waypoint.h"
  52. #include "pathfind.h"
  53. #include "pathmgr.h"
  54. #include "string_ids.h"
  55. #include "translateobj.h"
  56. #include "translatedb.h"
  57. #include "wwprofile.h"
  58. #include "conversationmgr.h"
  59. #include "activeconversation.h"
  60. #include "conversation.h"
  61. #include "combat.h"
  62. #include "assetmgr.h"
  63. #include "ccamera.h"
  64. #include "gameobjmanager.h"
  65. #include "transitioneffect.h"
  66. #include "coltest.h"
  67. #include "phys3.h"
  68. #include "animobj.h"
  69. #include "powerup.h"
  70. #include "weaponbag.h"
  71. #include "humanphys.h"
  72. #include "physcoltest.h"
  73. #include "objlibrary.h"
  74. #include "hudinfo.h"
  75. DECLARE_FORCE_LINK (MendozaBoss)
  76. //////////////////////////////////////////////////////////////////////////
  77. // Constants
  78. //////////////////////////////////////////////////////////////////////////
  79. static const AABoxClass BOSS_AREA_BOX01 (Vector3 (-19.2585F, 27.7224F, 0.434677F), Vector3 (5.06771F, 15.6146F, 1.0F));
  80. static const AABoxClass BOSS_AREA_BOX02 (Vector3 (-42.3353F, 32.8650F, 0.434677F), Vector3 (18.1846F, 22.7105F, 1.0F));
  81. static const AABoxClass BOSS_AREA_BOX03 (Vector3 (-64.4650F, 29.5306F, 0.434677F), Vector3 (4.15638F, 18.2853F, 1.0F));
  82. static Vector3 MENDOZA_END_POS (-58.088F, 15.389F, 0.334F);
  83. static Vector3 SYDNEY_END_POS (-57.931F, 12.133F, 0.412F);
  84. static Vector3 HELIPAD_CENTER_POS (-43.329F, 30.796F, 1.605F);
  85. static const float UNINITIALIZED_TIMER = -5000.0F;
  86. static const float FALLDOWN_TIMER = 6.0F;
  87. //////////////////////////////////////////////////////////////////////////
  88. // Waypath IDs
  89. //////////////////////////////////////////////////////////////////////////
  90. //////////////////////////////////////////////////////////////////////////
  91. // Weapon and state enumerations
  92. //////////////////////////////////////////////////////////////////////////
  93. //////////////////////////////////////////////////////////////////////////
  94. // Taunt constants
  95. //////////////////////////////////////////////////////////////////////////
  96. static const char *TAUNT_IDS[6] =
  97. {
  98. "IDS_SAKURA_BOSS_TAUNT1",
  99. "IDS_SAKURA_BOSS_TAUNT2",
  100. "IDS_SAKURA_BOSS_TAUNT3",
  101. "IDS_SAKURA_BOSS_TAUNT4",
  102. "IDS_SAKURA_BOSS_TAUNT5",
  103. "IDS_SAKURA_BOSS_TAUNT6"
  104. };
  105. //////////////////////////////////////////////////////////////////////////
  106. // Save/load constants
  107. //////////////////////////////////////////////////////////////////////////
  108. enum
  109. {
  110. CHUNKID_DEF_PARENT = 0x09230242,
  111. CHUNKID_DEF_VARIABLES,
  112. VARID_DEF_GATLING_DEF_ID = 1,
  113. VARID_DEF_ROCKET_DEF_ID,
  114. VARID_DEF_GATLING_REV_SOUND_ID,
  115. VARID_DEF_ROCKET_DOOR_SOUND_ID,
  116. VARID_DEF_ROCKET_DESTROYED_EXPLOSION_ID
  117. };
  118. enum
  119. {
  120. CHUNKID_PARENT = 0x09230243,
  121. CHUNKID_VARIABLES,
  122. CHUNKID_STATE_MACHINES,
  123. CHUNKID_CAMERA_SPLINE,
  124. CHUNKID_OVERALL_STATE_MACHINE,
  125. CHUNKID_MENDOZA_STATE_MACHINE,
  126. CHUNKID_SYDNEY_STATE_MACHINE,
  127. CHUNKID_MOVE_STATE_MACHINE,
  128. CHUNKID_HEAD_STATE_MACHINE,
  129. CHUNKID_CAMERA_STATE_MACHINE,
  130. CHUNKID_ATTACK_STATE_MACHINE,
  131. VARID_OVERALLSTATE_TIMER = 0,
  132. VARID_MENDOZASTATE_TIMER,
  133. VARID_CAMERASTATE_TIMER,
  134. VARID_CAMERASHAKE_TIMER,
  135. VARID_ATTACKSTATE_TIMER,
  136. VARID_RANDOMTARGET_TIMER,
  137. VARID_SYDNEYSTATE_TIMER,
  138. VARID_MOVESTATE_TIMER,
  139. VARID_NEXT_MELEE_ATTACK_TIME,
  140. VARID_FIREBALL_START_TIMER,
  141. VARID_NEXT_KNOCKDOWN_AVAILABLE_TIME,
  142. VARID_HAS_MELEE_ATTACK_HIT,
  143. VARID_LAST_MELEE_ANIM_FRAME,
  144. VARID_START_TIMER,
  145. VARID_SIDE_KICK_POS,
  146. VARID_SHOOT_GROUND_POS,
  147. VARID_ATTACKING_BONE_NAME,
  148. VARID_CAMERA_BONE_PTR,
  149. VARID_CAMERA_BONE_TM
  150. };
  151. //////////////////////////////////////////////////////////////////////////
  152. // Factories
  153. //////////////////////////////////////////////////////////////////////////
  154. SimplePersistFactoryClass<MendozaBossGameObjDefClass, CHUNKID_GAME_OBJECT_DEF_MENDOZA_BOSS> _MendozaBossGameObjDefPersistFactory;
  155. SimplePersistFactoryClass<MendozaBossGameObjClass, CHUNKID_GAME_OBJECT_MENDOZA_BOSS> _MendozaBossGameObjPersistFactory;
  156. DECLARE_DEFINITION_FACTORY(MendozaBossGameObjDefClass, CLASSID_GAME_OBJECT_DEF_MENDOZA_BOSS, "Mendoza Boss") _MendozaBossGameObjDefDefFactory;
  157. //////////////////////////////////////////////////////////////////////////
  158. //
  159. // MendozaBossGameObjDefClass
  160. //
  161. //////////////////////////////////////////////////////////////////////////
  162. MendozaBossGameObjDefClass::MendozaBossGameObjDefClass (void)
  163. {
  164. UseInnateBehavior = false;
  165. PARAM_SEPARATOR (MendozaBossGameObjDefClass, "Boss Settings");
  166. PARAM_SEPARATOR (MendozaBossGameObjDefClass, "");
  167. return ;
  168. }
  169. //////////////////////////////////////////////////////////////////////////
  170. //
  171. // ~MendozaBossGameObjDefClass
  172. //
  173. //////////////////////////////////////////////////////////////////////////
  174. MendozaBossGameObjDefClass::~MendozaBossGameObjDefClass (void)
  175. {
  176. return ;
  177. }
  178. //////////////////////////////////////////////////////////////////////////
  179. //
  180. // Get_Class_ID
  181. //
  182. //////////////////////////////////////////////////////////////////////////
  183. uint32
  184. MendozaBossGameObjDefClass::Get_Class_ID (void) const
  185. {
  186. return CLASSID_GAME_OBJECT_DEF_MENDOZA_BOSS;
  187. }
  188. //////////////////////////////////////////////////////////////////////////
  189. //
  190. // Create
  191. //
  192. //////////////////////////////////////////////////////////////////////////
  193. PersistClass *
  194. MendozaBossGameObjDefClass::Create (void) const
  195. {
  196. MendozaBossGameObjClass *obj = new MendozaBossGameObjClass;
  197. obj->Init(*this);
  198. return obj;
  199. }
  200. //////////////////////////////////////////////////////////////////////////
  201. //
  202. // Save
  203. //
  204. //////////////////////////////////////////////////////////////////////////
  205. bool
  206. MendozaBossGameObjDefClass::Save (ChunkSaveClass &csave)
  207. {
  208. csave.Begin_Chunk (CHUNKID_DEF_PARENT);
  209. SoldierGameObjDef::Save (csave);
  210. csave.End_Chunk ();
  211. csave.Begin_Chunk (CHUNKID_DEF_VARIABLES);
  212. Save_Variables (csave);
  213. csave.End_Chunk();
  214. return true;
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. //
  218. // Load
  219. //
  220. //////////////////////////////////////////////////////////////////////////
  221. bool
  222. MendozaBossGameObjDefClass::Load (ChunkLoadClass &cload)
  223. {
  224. while (cload.Open_Chunk ()) {
  225. switch(cload.Cur_Chunk_ID ()) {
  226. case CHUNKID_DEF_PARENT:
  227. SoldierGameObjDef::Load (cload);
  228. break;
  229. case CHUNKID_DEF_VARIABLES:
  230. Load_Variables (cload);
  231. break;
  232. default:
  233. Debug_Say (("Unrecognized MendozaBossGameObjDefClass chunkID\n"));
  234. break;
  235. }
  236. cload.Close_Chunk ();
  237. }
  238. return true;
  239. }
  240. ///////////////////////////////////////////////////////////////////////////
  241. //
  242. // Save_Variables
  243. //
  244. ///////////////////////////////////////////////////////////////////////////
  245. void
  246. MendozaBossGameObjDefClass::Save_Variables (ChunkSaveClass &csave)
  247. {
  248. return ;
  249. }
  250. ///////////////////////////////////////////////////////////////////////////
  251. //
  252. // Load_Variables
  253. //
  254. ///////////////////////////////////////////////////////////////////////////
  255. void
  256. MendozaBossGameObjDefClass::Load_Variables (ChunkLoadClass &cload)
  257. {
  258. /*while (cload.Open_Micro_Chunk ()) {
  259. switch (cload.Cur_Micro_Chunk_ID ()) {
  260. default:
  261. Debug_Say (("Unrecognized MendozaBossGameObjDefClass Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID ()));
  262. break;
  263. }
  264. cload.Close_Micro_Chunk ();
  265. }*/
  266. return ;
  267. }
  268. ///////////////////////////////////////////////////////////////////////////
  269. //
  270. // Get_Factory
  271. //
  272. ///////////////////////////////////////////////////////////////////////////
  273. const PersistFactoryClass &
  274. MendozaBossGameObjDefClass::Get_Factory (void) const
  275. {
  276. return _MendozaBossGameObjDefPersistFactory;
  277. }
  278. /*
  279. **
  280. ** Start of MendozaBossGameObjClass
  281. **
  282. */
  283. ///////////////////////////////////////////////////////////////////////////
  284. //
  285. // MendozaBossGameObjClass
  286. //
  287. ///////////////////////////////////////////////////////////////////////////
  288. MendozaBossGameObjClass::MendozaBossGameObjClass (void) :
  289. MendozaTauntTimeLeft (0),
  290. AvailableTaunts (0xFFFFFF),
  291. OverallState (this),
  292. MendozaState (this),
  293. SydneyState (this),
  294. AttackState (this),
  295. CameraState (this),
  296. MoveState (this),
  297. HeadState (this),
  298. OverallStateTimer (0),
  299. MendozaStateTimer (0),
  300. CameraShakeTimer (0),
  301. CameraStateTimer (0),
  302. StartTimer (0),
  303. AttackStateTimer (0),
  304. RandomTargetTimer (0),
  305. FireballStartTimer (0),
  306. NextKnockdownAvailableTime (0),
  307. SydneyStateTimer (0),
  308. HasMeleeAttackHit (false),
  309. LastMeleeAnimFrame (0),
  310. NextMeleeAttackTime (0),
  311. MoveStateTimer (0),
  312. CameraBoneModel (NULL),
  313. Sydney (NULL),
  314. MendozaPos (0, 0, 0),
  315. StarPos (0, 0, 0),
  316. ShootGroundPos (0, 0, 0),
  317. SideKickPos (0, 0, 0)
  318. {
  319. Shuffle_Taunt_List ();
  320. TauntList[0] = 1;//IDS_SAKURA_BOSS_TAUNT1;
  321. TauntList[1] = 2;//IDS_SAKURA_BOSS_TAUNT2;
  322. TauntList[2] = 3;//IDS_SAKURA_BOSS_TAUNT3;
  323. TauntList[3] = 4;//IDS_SAKURA_BOSS_TAUNT4;
  324. TauntList[4] = 5;//IDS_SAKURA_BOSS_TAUNT5;
  325. TauntList[5] = 6;//IDS_SAKURA_BOSS_TAUNT6;
  326. //
  327. // Register the Overall states with its state machine
  328. //
  329. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_FLYING_SIDEKICK);
  330. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_MELEE_ATTACK);
  331. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_RANGED_ATTACK);
  332. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_FIREBALL_ATTACK);
  333. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_FIND_HEALTH);
  334. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_SYDNEY_BOLTS);
  335. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_RUN_AFTER_SYDNEY);
  336. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_TOY_WITH_SYDNEY);
  337. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_DEATH_SEQUENCE);
  338. //
  339. // Register the Move states with its state machine
  340. //
  341. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_STOP);
  342. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_GET_CLOSE_TO_PLAYER);
  343. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_ATTACK_PATTERN1);
  344. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_ATTACK_PATTERN2);
  345. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_GOTO_HELIPAD);
  346. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_RUN_TO_HEALTH);
  347. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_CHASE_SYDNEY);
  348. //
  349. // Register the Mendoza states with its state machine
  350. //
  351. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_STANDING);
  352. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_FALLING);
  353. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_KIPPING);
  354. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_PACK_EXPLODING);
  355. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_DYING);
  356. ADD_STATE_TO_MACHINE (MendozaState, MENDOZA_STATE_DEAD);
  357. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  358. //
  359. // Register the Sydney states with its state machine
  360. //
  361. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_WAITING);
  362. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_BOLTING);
  363. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_TRIPPING);
  364. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_GETTING_UP);
  365. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_COWERING);
  366. ADD_STATE_TO_MACHINE (SydneyState, SYDNEY_STATE_STRIKE_A_POSE);
  367. //
  368. // Register the Head states with its state machine
  369. //
  370. ADD_STATE_TO_MACHINE (HeadState, HEAD_STATE_NONE);
  371. ADD_STATE_TO_MACHINE (HeadState, HEAD_STATE_LOOKING_AT_STAR);
  372. ADD_STATE_TO_MACHINE (HeadState, HEAD_STATE_LOOKING_AT_SYDNEY);
  373. //
  374. // Register the attack states with its state machine
  375. //
  376. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_NONE);
  377. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE);
  378. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN);
  379. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_FLYING_SIDEKICK);
  380. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_CRESENT_KICK);
  381. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_SIDE_KICK);
  382. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_SIDE_KICK_RETRACT);
  383. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_MELEE_PUNCH);
  384. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_FLAMETHROWER);
  385. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_FIREBALL);
  386. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_HANDGUN);
  387. ADD_STATE_TO_MACHINE (AttackState, ATTACK_STATE_SYDNEY);
  388. AttackState.Set_State (ATTACK_STATE_NONE);
  389. //
  390. // Register the camera states with its state machine
  391. //
  392. CameraState.Add_State (NULL, NULL, On_CAMERA_STATE_NORMAL_Begin, NULL);
  393. CameraState.Add_State (On_CAMERA_STATE_FACE_ZOOM_Think, NULL, On_CAMERA_STATE_FACE_ZOOM_Begin, NULL);
  394. CameraState.Add_State (On_CAMERA_STATE_WAYPATH_FOLLOW_Think, NULL, On_CAMERA_STATE_WAYPATH_FOLLOW_Begin, NULL);
  395. CameraState.Add_State (On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Think, NULL, On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Begin, NULL);
  396. CameraState.Set_State (CAMERA_STATE_NORMAL);
  397. //
  398. // Create the camera bone model...
  399. //
  400. CameraBoneModel = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("CAMBONE");
  401. return ;
  402. }
  403. ///////////////////////////////////////////////////////////////////////////
  404. //
  405. // ~MendozaBossGameObjClass
  406. //
  407. ///////////////////////////////////////////////////////////////////////////
  408. MendozaBossGameObjClass::~MendozaBossGameObjClass (void)
  409. {
  410. REF_PTR_RELEASE (CameraBoneModel);
  411. return ;
  412. }
  413. ///////////////////////////////////////////////////////////////////////////
  414. //
  415. // Get_Factory
  416. //
  417. ///////////////////////////////////////////////////////////////////////////
  418. const PersistFactoryClass &
  419. MendozaBossGameObjClass::Get_Factory (void) const
  420. {
  421. return _MendozaBossGameObjPersistFactory;
  422. }
  423. ////////////////////////////////////////////////////////////////
  424. //
  425. // Init
  426. //
  427. ////////////////////////////////////////////////////////////////
  428. void MendozaBossGameObjClass::Init (void)
  429. {
  430. Init ( Get_Definition ());
  431. return ;
  432. }
  433. ///////////////////////////////////////////////////////////////////////////
  434. //
  435. // Init
  436. //
  437. ///////////////////////////////////////////////////////////////////////////
  438. void
  439. MendozaBossGameObjClass::Init (const MendozaBossGameObjDefClass &definition)
  440. {
  441. SoldierGameObj::Init (definition);
  442. Initialize_Boss ();
  443. return ;
  444. }
  445. ///////////////////////////////////////////////////////////////////////////
  446. //
  447. // Get_Definition
  448. //
  449. ///////////////////////////////////////////////////////////////////////////
  450. const MendozaBossGameObjDefClass &
  451. MendozaBossGameObjClass::Get_Definition (void) const
  452. {
  453. return (const MendozaBossGameObjDefClass &)BaseGameObj::Get_Definition ();
  454. }
  455. ///////////////////////////////////////////////////////////////////////////
  456. //
  457. // Save
  458. //
  459. ///////////////////////////////////////////////////////////////////////////
  460. bool
  461. MendozaBossGameObjClass::Save (ChunkSaveClass & csave)
  462. {
  463. csave.Begin_Chunk (CHUNKID_PARENT);
  464. SoldierGameObj::Save (csave);
  465. csave.End_Chunk ();
  466. //
  467. // Save the state machines to their own chunk
  468. //
  469. csave.Begin_Chunk (CHUNKID_OVERALL_STATE_MACHINE);
  470. OverallState.Save (csave);
  471. csave.End_Chunk ();
  472. csave.Begin_Chunk (CHUNKID_MENDOZA_STATE_MACHINE);
  473. MendozaState.Save (csave);
  474. csave.End_Chunk ();
  475. csave.Begin_Chunk (CHUNKID_SYDNEY_STATE_MACHINE);
  476. SydneyState.Save (csave);
  477. csave.End_Chunk ();
  478. csave.Begin_Chunk (CHUNKID_MOVE_STATE_MACHINE);
  479. MoveState.Save (csave);
  480. csave.End_Chunk ();
  481. csave.Begin_Chunk (CHUNKID_HEAD_STATE_MACHINE);
  482. HeadState.Save (csave);
  483. csave.End_Chunk ();
  484. csave.Begin_Chunk (CHUNKID_CAMERA_STATE_MACHINE);
  485. CameraState.Save (csave);
  486. csave.End_Chunk ();
  487. csave.Begin_Chunk (CHUNKID_ATTACK_STATE_MACHINE);
  488. AttackState.Save (csave);
  489. csave.End_Chunk ();
  490. //
  491. // Save the camera spline
  492. //
  493. csave.Begin_Chunk (CHUNKID_CAMERA_SPLINE);
  494. CameraSpline.Save (csave);
  495. csave.End_Chunk ();
  496. csave.Begin_Chunk (CHUNKID_VARIABLES);
  497. Save_Variables (csave);
  498. csave.End_Chunk ();
  499. return true;
  500. }
  501. ///////////////////////////////////////////////////////////////////////////
  502. //
  503. // Load
  504. //
  505. ///////////////////////////////////////////////////////////////////////////
  506. bool
  507. MendozaBossGameObjClass::Load (ChunkLoadClass &cload)
  508. {
  509. while (cload.Open_Chunk ()) {
  510. switch(cload.Cur_Chunk_ID ()) {
  511. case CHUNKID_PARENT:
  512. SoldierGameObj::Load (cload);
  513. break;
  514. case CHUNKID_OVERALL_STATE_MACHINE:
  515. OverallState.Load (cload);
  516. break;
  517. case CHUNKID_MENDOZA_STATE_MACHINE:
  518. MendozaState.Load (cload);
  519. break;
  520. case CHUNKID_SYDNEY_STATE_MACHINE:
  521. SydneyState.Load (cload);
  522. break;
  523. case CHUNKID_MOVE_STATE_MACHINE:
  524. MoveState.Load (cload);
  525. break;
  526. case CHUNKID_HEAD_STATE_MACHINE:
  527. HeadState.Load (cload);
  528. break;
  529. case CHUNKID_CAMERA_STATE_MACHINE:
  530. CameraState.Load (cload);
  531. break;
  532. case CHUNKID_ATTACK_STATE_MACHINE:
  533. AttackState.Load (cload);
  534. break;
  535. //
  536. // Load the state machines from their chunk
  537. //
  538. case CHUNKID_STATE_MACHINES:
  539. OverallState.Load (cload);
  540. MendozaState.Load (cload);
  541. SydneyState.Load (cload);
  542. MoveState.Load (cload);
  543. HeadState.Load (cload);
  544. CameraState.Load (cload);
  545. AttackState.Load (cload);
  546. break;
  547. //
  548. // Load the camera spline
  549. //
  550. case CHUNKID_CAMERA_SPLINE:
  551. CameraSpline.Load (cload);
  552. break;
  553. case CHUNKID_VARIABLES:
  554. Load_Variables (cload);
  555. break;
  556. default:
  557. Debug_Say (("Unrecognized MendozaBossGameObjClass chunk ID\n"));
  558. break;
  559. }
  560. cload.Close_Chunk ();
  561. }
  562. SaveLoadSystemClass::Register_Post_Load_Callback (this);
  563. return true;
  564. }
  565. ///////////////////////////////////////////////////////////////////////////
  566. //
  567. // On_Post_Load
  568. //
  569. ///////////////////////////////////////////////////////////////////////////
  570. void
  571. MendozaBossGameObjClass::On_Post_Load (void)
  572. {
  573. SoldierGameObj::On_Post_Load ();
  574. Initialize_Boss ();
  575. return ;
  576. }
  577. ///////////////////////////////////////////////////////////////////////////
  578. //
  579. // Initialize_Boss
  580. //
  581. ///////////////////////////////////////////////////////////////////////////
  582. void
  583. MendozaBossGameObjClass::Initialize_Boss (void)
  584. {
  585. //
  586. // Find Sydney
  587. //
  588. PhysicalGameObj *game_obj = GameObjManager::Find_PhysicalGameObj (101010);
  589. if (game_obj != NULL) {
  590. Sydney = game_obj->As_SoldierGameObj ();
  591. //
  592. // Turn off her innate AI...
  593. //
  594. Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ()->Innate_Disable ();
  595. }
  596. return ;
  597. }
  598. ///////////////////////////////////////////////////////////////////////////
  599. //
  600. // Save_Variables
  601. //
  602. ///////////////////////////////////////////////////////////////////////////
  603. void
  604. MendozaBossGameObjClass::Save_Variables (ChunkSaveClass &csave)
  605. {
  606. Matrix3D cam_tm = CameraBoneModel->Get_Transform ();
  607. WRITE_MICRO_CHUNK (csave, VARID_CAMERA_BONE_PTR, CameraBoneModel);
  608. WRITE_MICRO_CHUNK (csave, VARID_CAMERA_BONE_TM, cam_tm);
  609. WRITE_MICRO_CHUNK (csave, VARID_OVERALLSTATE_TIMER, OverallStateTimer);
  610. WRITE_MICRO_CHUNK (csave, VARID_MENDOZASTATE_TIMER, MendozaStateTimer);
  611. WRITE_MICRO_CHUNK (csave, VARID_CAMERASTATE_TIMER, CameraStateTimer);
  612. WRITE_MICRO_CHUNK (csave, VARID_CAMERASHAKE_TIMER, CameraShakeTimer);
  613. WRITE_MICRO_CHUNK (csave, VARID_ATTACKSTATE_TIMER, AttackStateTimer);
  614. WRITE_MICRO_CHUNK (csave, VARID_RANDOMTARGET_TIMER, RandomTargetTimer);
  615. WRITE_MICRO_CHUNK (csave, VARID_SYDNEYSTATE_TIMER, SydneyStateTimer);
  616. WRITE_MICRO_CHUNK (csave, VARID_MOVESTATE_TIMER, MoveStateTimer);
  617. WRITE_MICRO_CHUNK (csave, VARID_NEXT_MELEE_ATTACK_TIME, NextMeleeAttackTime);
  618. WRITE_MICRO_CHUNK (csave, VARID_FIREBALL_START_TIMER, FireballStartTimer);
  619. WRITE_MICRO_CHUNK (csave, VARID_NEXT_KNOCKDOWN_AVAILABLE_TIME, NextKnockdownAvailableTime);
  620. WRITE_MICRO_CHUNK (csave, VARID_HAS_MELEE_ATTACK_HIT, HasMeleeAttackHit);
  621. WRITE_MICRO_CHUNK (csave, VARID_LAST_MELEE_ANIM_FRAME, LastMeleeAnimFrame);
  622. WRITE_MICRO_CHUNK (csave, VARID_START_TIMER, StartTimer);
  623. WRITE_MICRO_CHUNK (csave, VARID_SIDE_KICK_POS, SideKickPos);
  624. WRITE_MICRO_CHUNK (csave, VARID_SHOOT_GROUND_POS, ShootGroundPos);
  625. WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_ATTACKING_BONE_NAME, AttackingBoneName);
  626. return ;
  627. }
  628. ///////////////////////////////////////////////////////////////////////////
  629. //
  630. // Load_Variables
  631. //
  632. ///////////////////////////////////////////////////////////////////////////
  633. void
  634. MendozaBossGameObjClass::Load_Variables (ChunkLoadClass &cload)
  635. {
  636. RenderObjClass *old_camera_bone_ptr = NULL;
  637. Matrix3D cam_tm (1);
  638. while (cload.Open_Micro_Chunk ()) {
  639. switch (cload.Cur_Micro_Chunk_ID ()) {
  640. READ_MICRO_CHUNK (cload, VARID_CAMERA_BONE_PTR, old_camera_bone_ptr);
  641. READ_MICRO_CHUNK (cload, VARID_CAMERA_BONE_TM, cam_tm);
  642. READ_MICRO_CHUNK (cload, VARID_OVERALLSTATE_TIMER, OverallStateTimer);
  643. READ_MICRO_CHUNK (cload, VARID_MENDOZASTATE_TIMER, MendozaStateTimer);
  644. READ_MICRO_CHUNK (cload, VARID_CAMERASTATE_TIMER, CameraStateTimer);
  645. READ_MICRO_CHUNK (cload, VARID_CAMERASHAKE_TIMER, CameraShakeTimer);
  646. READ_MICRO_CHUNK (cload, VARID_ATTACKSTATE_TIMER, AttackStateTimer);
  647. READ_MICRO_CHUNK (cload, VARID_RANDOMTARGET_TIMER, RandomTargetTimer);
  648. READ_MICRO_CHUNK (cload, VARID_SYDNEYSTATE_TIMER, SydneyStateTimer);
  649. READ_MICRO_CHUNK (cload, VARID_MOVESTATE_TIMER, MoveStateTimer);
  650. READ_MICRO_CHUNK (cload, VARID_NEXT_MELEE_ATTACK_TIME, NextMeleeAttackTime);
  651. READ_MICRO_CHUNK (cload, VARID_FIREBALL_START_TIMER, FireballStartTimer);
  652. READ_MICRO_CHUNK (cload, VARID_NEXT_KNOCKDOWN_AVAILABLE_TIME, NextKnockdownAvailableTime);
  653. READ_MICRO_CHUNK (cload, VARID_HAS_MELEE_ATTACK_HIT, HasMeleeAttackHit);
  654. READ_MICRO_CHUNK (cload, VARID_LAST_MELEE_ANIM_FRAME, LastMeleeAnimFrame);
  655. READ_MICRO_CHUNK (cload, VARID_START_TIMER, StartTimer);
  656. READ_MICRO_CHUNK (cload, VARID_SIDE_KICK_POS, SideKickPos);
  657. READ_MICRO_CHUNK (cload, VARID_SHOOT_GROUND_POS, ShootGroundPos);
  658. READ_MICRO_CHUNK_WWSTRING (cload, VARID_ATTACKING_BONE_NAME, AttackingBoneName);
  659. default:
  660. Debug_Say (("Unrecognized MendozaBossGameObjClass Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID ()));
  661. break;
  662. }
  663. cload.Close_Micro_Chunk ();
  664. }
  665. //
  666. // Register the camera bone pointers...
  667. //
  668. if (old_camera_bone_ptr != NULL) {
  669. SaveLoadSystemClass::Register_Pointer (old_camera_bone_ptr, CameraBoneModel);
  670. CameraBoneModel->Set_Transform (cam_tm);
  671. }
  672. return ;
  673. }
  674. ///////////////////////////////////////////////////////////////////////////
  675. //
  676. // Apply_Control
  677. //
  678. ///////////////////////////////////////////////////////////////////////////
  679. void
  680. MendozaBossGameObjClass::Apply_Control (void)
  681. {
  682. SoldierGameObj::Apply_Control ();
  683. return ;
  684. }
  685. ///////////////////////////////////////////////////////////////////////////
  686. //
  687. // Think
  688. //
  689. ///////////////////////////////////////////////////////////////////////////
  690. void
  691. MendozaBossGameObjClass::Think (void)
  692. {
  693. WWPROFILE ("Mendoza Think");
  694. bool ok_to_think = true;
  695. //
  696. // Don't do this in the editor
  697. //
  698. #ifdef PARAM_EDITING_ON
  699. ok_to_think = false;
  700. #endif
  701. if (COMBAT_STAR == NULL || Sydney == NULL) {
  702. ok_to_think = false;
  703. }
  704. if (ok_to_think) {
  705. //
  706. // Get the position of both Mendoza and the star (this information
  707. // is used throughout the AI)
  708. //
  709. Get_Position (&MendozaPos);
  710. COMBAT_STAR->Get_Position (&StarPos);
  711. //
  712. // Check to see if its OK to kick off the boss logic
  713. //
  714. if (StartTimer > UNINITIALIZED_TIMER) {
  715. StartTimer -= TimeManager::Get_Frame_Seconds ();
  716. if (StartTimer <= 0) {
  717. Spawn_Health_Powerups ();
  718. StartTimer = UNINITIALIZED_TIMER;
  719. OverallState.Set_State (OVERALL_STATE_FLYING_SIDEKICK);
  720. }
  721. } else {
  722. //
  723. // Decrement the "global" timer that determines when its OK
  724. // for Mendoza to fall down due to a frontal hit
  725. //
  726. NextKnockdownAvailableTime -= TimeManager::Get_Frame_Seconds ();
  727. //
  728. // Let the state machines think
  729. //
  730. OverallState.Think ();
  731. MendozaState.Think ();
  732. MoveState.Think ();
  733. HeadState.Think ();
  734. CameraState.Think ();
  735. AttackState.Think ();
  736. SydneyState.Think ();
  737. }
  738. }
  739. //
  740. // Give Mendoza 100 extra health points so he doesn't get "killed" due to any
  741. // "special" damage such as fire or electricity
  742. //
  743. float old_health = DefenseObject.Get_Health ();
  744. float old_health_max = DefenseObject.Get_Health_Max ();
  745. old_health += 100.0F;
  746. old_health_max += 100.0F;
  747. DefenseObject.Set_Health_Max (old_health_max);
  748. DefenseObject.Set_Health (old_health);
  749. //
  750. // Let the soldier think
  751. //
  752. SoldierGameObj::Think ();
  753. //
  754. // Restore his health
  755. //
  756. float curr_health = DefenseObject.Get_Health ();
  757. curr_health -= 100.0F;
  758. old_health_max -= 100.0F;
  759. DefenseObject.Set_Health (max (curr_health, 1.0F));
  760. DefenseObject.Set_Health_Max (old_health_max);
  761. return ;
  762. }
  763. ///////////////////////////////////////////////////////////////////////////
  764. //
  765. // Shuffle_Taunt_List
  766. //
  767. ///////////////////////////////////////////////////////////////////////////
  768. void
  769. MendozaBossGameObjClass::Shuffle_Taunt_List (void)
  770. {
  771. ::memset (TauntList, 0, sizeof (TauntList));
  772. //
  773. // Grab an entry from the taunt id list
  774. //
  775. for (int index = 0; index < MAX_TAUNTS; index ++) {
  776. //
  777. // Choose a random list entry to plug this taunt ID into
  778. //
  779. int list_index = 0;
  780. do
  781. {
  782. list_index = FreeRandom.Get_Int (MAX_TAUNTS);
  783. } while (TauntList[list_index] != 0);
  784. //
  785. // Stick this taunt ID into the list
  786. //
  787. TauntList[list_index] = index + 1;
  788. }
  789. return ;
  790. }
  791. ///////////////////////////////////////////////////////////////////////////
  792. //
  793. // Apply_Damage_Extended
  794. //
  795. ///////////////////////////////////////////////////////////////////////////
  796. void
  797. MendozaBossGameObjClass::Apply_Damage_Extended
  798. (
  799. const OffenseObjectClass & damager,
  800. float scale,
  801. const Vector3 & direction,
  802. const char * collision_box_name
  803. )
  804. {
  805. if ( !CombatManager::I_Am_Server () ||
  806. OverallState.Get_State () == OVERALL_STATE_DEATH_SEQUENCE)
  807. {
  808. return ;
  809. }
  810. //
  811. // Give Mendoza 100 extra health points so he doesn't get "killed"
  812. //
  813. float old_health = DefenseObject.Get_Health ();
  814. //
  815. // Apply the damage
  816. //
  817. DefenseObject.Set_Can_Object_Die (false);
  818. SoldierGameObj::Apply_Damage_Extended (damager, scale, direction, collision_box_name);
  819. //
  820. // Readjust the current and old health
  821. //
  822. float curr_health = DefenseObject.Get_Health ();
  823. //
  824. // If Sydney is cowering in front of Mendoza then we should trigger
  825. // the end sequence soon...
  826. //
  827. if (SydneyState.Get_State () == SYDNEY_STATE_COWERING) {
  828. if (FreeRandom.Get_Int (4) == 1) {
  829. OverallState.Set_State (OVERALL_STATE_DEATH_SEQUENCE);
  830. }
  831. } else {
  832. //
  833. // Calculate what our health percents were both before and after this damage
  834. //
  835. float old_health_percent = old_health / DefenseObject.Get_Health_Max ();
  836. float health_percent = curr_health / DefenseObject.Get_Health_Max ();
  837. //
  838. // At 25% health we trigger the "chase after Sydney" event which has different behavior
  839. //
  840. if (health_percent > 0.25F) {
  841. //
  842. // Were we shot in the front? (If so we may want to trigger our fall down event)
  843. //
  844. if ( health_percent > 0.3F &&
  845. NextKnockdownAvailableTime <= 0 &&
  846. OverallState.Get_State () >= OVERALL_STATE_MELEE_ATTACK)
  847. {
  848. Vector3 relative_direction = Get_Transform ().Inverse_Rotate_Vector (direction);
  849. relative_direction.Normalize ();
  850. if (relative_direction.X < -0.7F && (FreeRandom.Get_Int (5) == 1)) {
  851. MendozaState.Set_State (MENDOZA_STATE_FALLING);
  852. }
  853. NextKnockdownAvailableTime = FALLDOWN_TIMER;
  854. }
  855. //
  856. // If Mendoza's health crosses the 75% mark, then switch to a ranged attack
  857. //
  858. if (old_health_percent > 0.75F && health_percent <= 0.75F) {
  859. OverallState.Set_State (OVERALL_STATE_RANGED_ATTACK);
  860. }
  861. } else {
  862. //
  863. // Did we just change over to this state?
  864. //
  865. if (old_health_percent > 0.25F) {
  866. OverallState.Set_State (OVERALL_STATE_SYDNEY_BOLTS);
  867. }
  868. }
  869. }
  870. return ;
  871. }
  872. ///////////////////////////////////////////////////////////////////////////
  873. //
  874. // On_MENDOZA_STATE_STANDING_Begin
  875. //
  876. ///////////////////////////////////////////////////////////////////////////
  877. void
  878. MendozaBossGameObjClass::On_MENDOZA_STATE_STANDING_Begin (void)
  879. {
  880. MendozaStateTimer = 0;
  881. return ;
  882. }
  883. ///////////////////////////////////////////////////////////////////////////
  884. //
  885. // On_MENDOZA_STATE_STANDING_Think
  886. //
  887. ///////////////////////////////////////////////////////////////////////////
  888. void
  889. MendozaBossGameObjClass::On_MENDOZA_STATE_STANDING_Think (void)
  890. {
  891. if (COMBAT_STAR == NULL) {
  892. return ;
  893. }
  894. return ;
  895. }
  896. ///////////////////////////////////////////////////////////////////////////
  897. //
  898. // On_MENDOZA_STATE_FALLING_Begin
  899. //
  900. ///////////////////////////////////////////////////////////////////////////
  901. void
  902. MendozaBossGameObjClass::On_MENDOZA_STATE_FALLING_Begin (void)
  903. {
  904. Set_Animation ("S_A_HUMAN.H_A_635A", false);
  905. AttackState.Halt_State ();
  906. MoveState.Halt_State ();
  907. return ;
  908. }
  909. ///////////////////////////////////////////////////////////////////////////
  910. //
  911. // On_MENDOZA_STATE_FALLING_Think
  912. //
  913. ///////////////////////////////////////////////////////////////////////////
  914. void
  915. MendozaBossGameObjClass::On_MENDOZA_STATE_FALLING_Think (void)
  916. {
  917. if (Get_Anim_Control ()->Is_Complete ()) {
  918. MendozaState.Set_State (MENDOZA_STATE_KIPPING, true);
  919. }
  920. return ;
  921. }
  922. ///////////////////////////////////////////////////////////////////////////
  923. //
  924. // On_MENDOZA_STATE_FALLING_Request_End
  925. //
  926. ///////////////////////////////////////////////////////////////////////////
  927. bool
  928. MendozaBossGameObjClass::On_MENDOZA_STATE_FALLING_Request_End (int /*new_state*/)
  929. {
  930. return false;
  931. }
  932. ///////////////////////////////////////////////////////////////////////////
  933. //
  934. // On_MENDOZA_STATE_KIPPING_Begin
  935. //
  936. ///////////////////////////////////////////////////////////////////////////
  937. void
  938. MendozaBossGameObjClass::On_MENDOZA_STATE_KIPPING_Begin (void)
  939. {
  940. Set_Blended_Animation ("S_A_HUMAN.H_A_H12C", false);
  941. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  942. ((HumanAnimControlClass *)Get_Anim_Control ())->Set_Anim_Speed_Scale (2.0F);
  943. return ;
  944. }
  945. ///////////////////////////////////////////////////////////////////////////
  946. //
  947. // STATE_IMPL_END(MENDOZA_STATE_KIPPING)
  948. //
  949. ///////////////////////////////////////////////////////////////////////////
  950. void
  951. MendozaBossGameObjClass::STATE_IMPL_END(MENDOZA_STATE_KIPPING) (void)
  952. {
  953. //
  954. // Resume the state's we halted
  955. //
  956. MoveState.Resume_State ();
  957. AttackState.Set_State (ATTACK_STATE_HANDGUN);
  958. AttackState.Resume_State ();
  959. return ;
  960. }
  961. ///////////////////////////////////////////////////////////////////////////
  962. //
  963. // On_MENDOZA_STATE_KIPPING_Think
  964. //
  965. ///////////////////////////////////////////////////////////////////////////
  966. void
  967. MendozaBossGameObjClass::On_MENDOZA_STATE_KIPPING_Think (void)
  968. {
  969. if (Get_Anim_Control ()->Is_Complete ()) {
  970. MendozaState.Set_State (MENDOZA_STATE_STANDING, true);
  971. HumanState.Set_State (HumanStateClass::ANIMATION);
  972. ((HumanAnimControlClass *)Get_Anim_Control ())->Set_Anim_Speed_Scale (1.0F);
  973. }
  974. return ;
  975. }
  976. ///////////////////////////////////////////////////////////////////////////
  977. //
  978. // On_MENDOZA_STATE_KIPPING_Request_End
  979. //
  980. ///////////////////////////////////////////////////////////////////////////
  981. bool
  982. MendozaBossGameObjClass::On_MENDOZA_STATE_KIPPING_Request_End (int /*new_state*/)
  983. {
  984. return false;
  985. }
  986. ///////////////////////////////////////////////////////////////////////////
  987. //
  988. // On_MENDOZA_STATE_PACK_EXPLODING_Begin
  989. //
  990. ///////////////////////////////////////////////////////////////////////////
  991. void
  992. MendozaBossGameObjClass::On_MENDOZA_STATE_PACK_EXPLODING_Begin (void)
  993. {
  994. //
  995. // Create the explosion aggregate to attach to Mendoza
  996. //
  997. RenderObjClass *die_aggregate = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("AG_MENDOZA_DIE");
  998. if (die_aggregate != NULL) {
  999. //
  1000. // Play the animation on the object
  1001. //
  1002. HAnimClass *anim = WW3DAssetManager::Get_Instance ()->Get_HAnim ("AG_MENDOZA_DIE.AG_MENDOZA_DIE");
  1003. if (anim != NULL) {
  1004. die_aggregate->Set_Animation (anim, 0, RenderObjClass::ANIM_MODE_ONCE);
  1005. REF_PTR_RELEASE (anim);
  1006. }
  1007. //
  1008. // Attach the object to the back of Mendoza
  1009. //
  1010. Peek_Model ()->Add_Sub_Object_To_Bone (die_aggregate, "BACKGUNBONE");
  1011. REF_PTR_RELEASE (die_aggregate);
  1012. }
  1013. //
  1014. // Snap Sydney to the right position
  1015. //
  1016. SydneyState.Set_State (SYDNEY_STATE_STRIKE_A_POSE);
  1017. //
  1018. // Stay in this state for 8 more seconds
  1019. //
  1020. MendozaStateTimer = 8.0F;
  1021. CameraShakeTimer = 8.0F;
  1022. return ;
  1023. }
  1024. ///////////////////////////////////////////////////////////////////////////
  1025. //
  1026. // STATE_IMPL_REQUEST_END(MENDOZA_STATE_PACK_EXPLODING)
  1027. //
  1028. ///////////////////////////////////////////////////////////////////////////
  1029. bool
  1030. MendozaBossGameObjClass::STATE_IMPL_REQUEST_END(MENDOZA_STATE_PACK_EXPLODING) (int state)
  1031. {
  1032. return false;
  1033. }
  1034. ///////////////////////////////////////////////////////////////////////////
  1035. //
  1036. // On_MENDOZA_STATE_PACK_EXPLODING_Think
  1037. //
  1038. ///////////////////////////////////////////////////////////////////////////
  1039. void
  1040. MendozaBossGameObjClass::On_MENDOZA_STATE_PACK_EXPLODING_Think (void)
  1041. {
  1042. float old_timer = MendozaStateTimer;
  1043. CameraShakeTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1044. if (CameraShakeTimer <= 0 && CameraShakeTimer > UNINITIALIZED_TIMER) {
  1045. COMBAT_SCENE->Add_Camera_Shake (MendozaPos, 50.0, 1.0F, 0.25F);
  1046. CameraShakeTimer = UNINITIALIZED_TIMER;
  1047. }
  1048. MendozaStateTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1049. if (MendozaStateTimer <= 0) {
  1050. //
  1051. // Kick into the dying state
  1052. //
  1053. MendozaState.Set_State (MENDOZA_STATE_DYING, true);
  1054. } else if (old_timer >= 7.5F && MendozaStateTimer < 7.5F) {
  1055. //
  1056. // Force Mendoza to be on fire
  1057. //
  1058. Set_Special_Damage_Mode (ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE);
  1059. SpecialDamageTimer = 100.0F;
  1060. Set_Blended_Animation ("S_A_HUMAN.H_A_FLMA", true);
  1061. //
  1062. // Play the on-fire sound
  1063. //
  1064. Attach_Fire_Sound ();
  1065. }
  1066. return ;
  1067. }
  1068. ///////////////////////////////////////////////////////////////////////////
  1069. //
  1070. // On_MENDOZA_STATE_DYING_Begin
  1071. //
  1072. ///////////////////////////////////////////////////////////////////////////
  1073. void
  1074. MendozaBossGameObjClass::On_MENDOZA_STATE_DYING_Begin (void)
  1075. {
  1076. //
  1077. // Start the falling to your knees animation
  1078. //
  1079. Set_Blended_Animation ("S_A_HUMAN.H_A_FLMB", false);
  1080. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1081. //
  1082. // Look at the dying Mendoza for a few seconds
  1083. //
  1084. MendozaStateTimer = 7.0F;
  1085. return ;
  1086. }
  1087. ///////////////////////////////////////////////////////////////////////////
  1088. //
  1089. // On_MENDOZA_STATE_DYING_Think
  1090. //
  1091. ///////////////////////////////////////////////////////////////////////////
  1092. void
  1093. MendozaBossGameObjClass::On_MENDOZA_STATE_DYING_Think (void)
  1094. {
  1095. MendozaStateTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1096. if (MendozaStateTimer <= 0) {
  1097. //
  1098. // Set the dead state
  1099. //
  1100. MendozaState.Set_State (MENDOZA_STATE_DEAD);
  1101. }
  1102. return ;
  1103. }
  1104. ///////////////////////////////////////////////////////////////////////////
  1105. //
  1106. // On_MENDOZA_STATE_DEAD_Begin
  1107. //
  1108. ///////////////////////////////////////////////////////////////////////////
  1109. void
  1110. MendozaBossGameObjClass::On_MENDOZA_STATE_DEAD_Begin (void)
  1111. {
  1112. //
  1113. // Give the user 15 seconds before the level ends
  1114. //
  1115. MendozaStateTimer = 10.0F;
  1116. return ;
  1117. }
  1118. ///////////////////////////////////////////////////////////////////////////
  1119. //
  1120. // On_MENDOZA_STATE_DEAD_Think
  1121. //
  1122. ///////////////////////////////////////////////////////////////////////////
  1123. void
  1124. MendozaBossGameObjClass::On_MENDOZA_STATE_DEAD_Think (void)
  1125. {
  1126. MendozaStateTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1127. if (MendozaStateTimer <= 0) {
  1128. //
  1129. // For right now, just restore everything so we can do it again...
  1130. //
  1131. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  1132. Set_Special_Damage_Mode (ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE);
  1133. HumanState.Set_State (HumanStateClass::ANIMATION);
  1134. }
  1135. return ;
  1136. }
  1137. ///////////////////////////////////////////////////////////////////////////
  1138. //
  1139. // On_CAMERA_STATE_NORMAL_Begin
  1140. //
  1141. ///////////////////////////////////////////////////////////////////////////
  1142. void
  1143. MendozaBossGameObjClass::On_CAMERA_STATE_NORMAL_Begin (void)
  1144. {
  1145. return ;
  1146. }
  1147. ///////////////////////////////////////////////////////////////////////////
  1148. //
  1149. // On_CAMERA_STATE_FACE_ZOOM_Begin
  1150. //
  1151. ///////////////////////////////////////////////////////////////////////////
  1152. void
  1153. MendozaBossGameObjClass::On_CAMERA_STATE_FACE_ZOOM_Begin (void)
  1154. {
  1155. //
  1156. // Attach the camera to a dummy object we can move around
  1157. //
  1158. CameraBoneModel->Set_Transform (COMBAT_CAMERA->Get_Transform ());
  1159. COMBAT_CAMERA->Set_Host_Model (CameraBoneModel);
  1160. //
  1161. // Slow time down...
  1162. //
  1163. TimeManager::Set_Time_Scale (0.25F);
  1164. GameObjManager::Activate_Cinematic_Freeze (false);
  1165. return ;
  1166. }
  1167. ///////////////////////////////////////////////////////////////////////////
  1168. //
  1169. // On_CAMERA_STATE_FACE_ZOOM_Think
  1170. //
  1171. ///////////////////////////////////////////////////////////////////////////
  1172. void
  1173. MendozaBossGameObjClass::On_CAMERA_STATE_FACE_ZOOM_Think (void)
  1174. {
  1175. //
  1176. // Determine the current and destination points
  1177. //
  1178. Vector3 curr_pos = CameraBoneModel->Get_Transform ().Get_Translation ();
  1179. Vector3 dest_pos = Peek_Model ()->Get_Bone_Transform ("C HEAD").Get_Translation ();
  1180. dest_pos += Vector3 (0, 0, 0.125F);
  1181. //
  1182. // Get the vector from our current position to our destination
  1183. //
  1184. Vector3 vector = dest_pos - curr_pos;
  1185. if (vector.Length () < 5.0F && MendozaState.Get_State () != MENDOZA_STATE_PACK_EXPLODING) {
  1186. MendozaState.Set_State (MENDOZA_STATE_PACK_EXPLODING, true);
  1187. } else if (vector.Length () < 1.15F) {
  1188. //
  1189. // Snap Mendoza to the right position
  1190. //
  1191. Matrix3D new_tm (MENDOZA_END_POS);
  1192. new_tm.Rotate_Z (DEG_TO_RADF (270.0F));
  1193. Set_Transform (new_tm);
  1194. //
  1195. // Detonate the backpack and start following the waypath
  1196. //
  1197. CameraState.Set_State (CAMERA_STATE_WAYPATH_FOLLOW, true);
  1198. } else {
  1199. //
  1200. // Move closer to the target
  1201. //
  1202. vector.Normalize ();
  1203. float time = TimeManager::Get_Frame_Real_Seconds () * 8.0F;
  1204. Vector3 new_pos = curr_pos + (vector * time);
  1205. //
  1206. // Look at the target
  1207. //
  1208. Matrix3D new_tm;
  1209. new_tm.Look_At (new_pos, dest_pos, 0);
  1210. //
  1211. // Update the camera's position and orientation
  1212. //
  1213. CameraBoneModel->Set_Transform (new_tm);
  1214. }
  1215. return ;
  1216. }
  1217. ///////////////////////////////////////////////////////////////////////////
  1218. //
  1219. // On_CAMERA_STATE_WAYPATH_FOLLOW_Begin
  1220. //
  1221. ///////////////////////////////////////////////////////////////////////////
  1222. void
  1223. MendozaBossGameObjClass::On_CAMERA_STATE_WAYPATH_FOLLOW_Begin (void)
  1224. {
  1225. //
  1226. // Restore time
  1227. //
  1228. TimeManager::Set_Time_Scale (1.0F);
  1229. //
  1230. // Reset the spline
  1231. //
  1232. CameraSpline.Clear_Keys ();
  1233. //
  1234. // Get the waypath we're going to follow
  1235. //
  1236. WaypathClass *waypath = PathfindClass::Get_Instance ()->Find_Waypath (3000100);
  1237. WWASSERT (waypath != NULL);
  1238. //
  1239. // Add the points from the waypath to the spline
  1240. //
  1241. float percent = 0.0F;
  1242. float percent_inc = 1.0F / waypath->Get_Point_Count ();
  1243. for (int index = 0; index < waypath->Get_Point_Count (); index ++) {
  1244. //
  1245. // Add this point to the spline
  1246. //
  1247. WaypointClass *waypoint = waypath->Get_Point (index);
  1248. WWASSERT (waypoint != NULL);
  1249. CameraSpline.Add_Key (waypoint->Get_Position (), percent);
  1250. //
  1251. // Increment the percent
  1252. //
  1253. percent += percent_inc;
  1254. }
  1255. //
  1256. // Let the camera follow the path for 8 seconds
  1257. //
  1258. CameraStateTimer = 8.0F;
  1259. return ;
  1260. }
  1261. ///////////////////////////////////////////////////////////////////////////
  1262. //
  1263. // On_CAMERA_STATE_WAYPATH_FOLLOW_Think
  1264. //
  1265. ///////////////////////////////////////////////////////////////////////////
  1266. void
  1267. MendozaBossGameObjClass::On_CAMERA_STATE_WAYPATH_FOLLOW_Think (void)
  1268. {
  1269. //
  1270. // Evaluate the spline at the current "time"
  1271. //
  1272. float percent = 1.0F - WWMath::Clamp (CameraStateTimer / 8.0F, 0.0F, 1.0F);
  1273. Vector3 camera_position;
  1274. CameraSpline.Evaluate (percent, &camera_position);
  1275. float camera_twist = 0.0F;
  1276. if (percent > 0.77F) {
  1277. camera_twist = ((percent - 0.77F) / 0.33F) * DEG_TO_RADF (-30.0F);
  1278. }
  1279. Vector3 dest_pos = Peek_Model ()->Get_Bone_Transform ("C HEAD").Get_Translation ();
  1280. if (percent < 0.22F) {
  1281. dest_pos += Get_Transform ().Rotate_Vector (Vector3 (2.0F, 0, 0));
  1282. } else if (percent >= 0.22F && percent < 0.55F) {
  1283. float dist = 2.0F * (1.0F - ((percent - 0.22F) / 0.33F));
  1284. dest_pos += Get_Transform ().Rotate_Vector (Vector3 (dist, 0, 0));
  1285. }
  1286. //
  1287. // Move along the spline, looking at the character's head
  1288. //
  1289. Matrix3D new_tm;
  1290. new_tm.Look_At (camera_position, dest_pos, camera_twist);
  1291. CameraBoneModel->Set_Transform (new_tm);
  1292. //
  1293. // Kick out of this state when finished
  1294. //
  1295. CameraStateTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1296. if (CameraStateTimer <= 0) {
  1297. CameraState.Set_State (CAMERA_STATE_LOOK_AT_DEAD_BOSS, true);
  1298. }
  1299. return ;
  1300. }
  1301. ///////////////////////////////////////////////////////////////////////////
  1302. //
  1303. // On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Begin
  1304. //
  1305. ///////////////////////////////////////////////////////////////////////////
  1306. void
  1307. MendozaBossGameObjClass::On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Begin (void)
  1308. {
  1309. //
  1310. // Look at Mendoza for a few seconds
  1311. //
  1312. CameraStateTimer = 7.0F;
  1313. TimeManager::Set_Time_Scale (0.5F);
  1314. return ;
  1315. }
  1316. ///////////////////////////////////////////////////////////////////////////
  1317. //
  1318. // On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Think
  1319. //
  1320. ///////////////////////////////////////////////////////////////////////////
  1321. void
  1322. MendozaBossGameObjClass::On_CAMERA_STATE_LOOK_AT_DEAD_BOSS_Think (void)
  1323. {
  1324. //
  1325. // Kick out of this state when finished
  1326. //
  1327. CameraStateTimer -= TimeManager::Get_Frame_Real_Seconds ();
  1328. if (CameraStateTimer <= 0) {
  1329. CameraState.Set_State (CAMERA_STATE_NORMAL, true);
  1330. //
  1331. // Restore the camera state
  1332. //
  1333. TimeManager::Set_Time_Scale (1.0F);
  1334. COMBAT_CAMERA->Set_Host_Model (NULL);
  1335. REF_PTR_RELEASE (CameraBoneModel);
  1336. //
  1337. // Trigger mission success
  1338. //
  1339. CombatManager::Mission_Complete (true);
  1340. }
  1341. return ;
  1342. }
  1343. ///////////////////////////////////////////////////////////////////////////
  1344. //
  1345. // Attach_Sound
  1346. //
  1347. ///////////////////////////////////////////////////////////////////////////
  1348. void
  1349. MendozaBossGameObjClass::Attach_Sound (const char *sound_name, const char *bone_name)
  1350. {
  1351. //
  1352. // Create the sound object from its preset
  1353. //
  1354. AudibleSoundClass *sound = WWAudioClass::Get_Instance ()->Create_Sound (sound_name);
  1355. if (sound != NULL) {
  1356. //
  1357. // Attach the sound to the object
  1358. //
  1359. sound->Attach_To_Object (Peek_Model (), bone_name);
  1360. //
  1361. // Add the sound to the world and release our hold on it
  1362. //
  1363. sound->Add_To_Scene ();
  1364. REF_PTR_RELEASE (sound);
  1365. }
  1366. return ;
  1367. }
  1368. ///////////////////////////////////////////////////////////////////////////
  1369. //
  1370. // Attach_Fire_Sound
  1371. //
  1372. ///////////////////////////////////////////////////////////////////////////
  1373. void
  1374. MendozaBossGameObjClass::Attach_Fire_Sound (void)
  1375. {
  1376. //
  1377. // Create the sound object from its preset
  1378. //
  1379. AudibleSoundClass *sound = WWAudioClass::Get_Instance ()->Create_Sound ("SFX.Fire_Small_01");
  1380. if (sound != NULL) {
  1381. //
  1382. // Attach the sound to the object
  1383. //
  1384. sound->Attach_To_Object (Peek_Model ());
  1385. //
  1386. // Add the sound to the world and release our hold on it
  1387. //
  1388. sound->Add_To_Scene ();
  1389. REF_PTR_RELEASE (sound);
  1390. }
  1391. return ;
  1392. }
  1393. ///////////////////////////////////////////////////////////////////////////
  1394. //
  1395. // On_ATTACK_STATE_NONE_Begin
  1396. //
  1397. ///////////////////////////////////////////////////////////////////////////
  1398. void
  1399. MendozaBossGameObjClass::On_ATTACK_STATE_NONE_Begin (void)
  1400. {
  1401. return ;
  1402. }
  1403. ///////////////////////////////////////////////////////////////////////////
  1404. //
  1405. // On_ATTACK_STATE_NONE_Think
  1406. //
  1407. ///////////////////////////////////////////////////////////////////////////
  1408. void
  1409. MendozaBossGameObjClass::On_ATTACK_STATE_NONE_Think (void)
  1410. {
  1411. return ;
  1412. }
  1413. ///////////////////////////////////////////////////////////////////////////
  1414. //
  1415. // On_ATTACK_STATE_MELEE_Begin
  1416. //
  1417. ///////////////////////////////////////////////////////////////////////////
  1418. void
  1419. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_Begin (void)
  1420. {
  1421. NextMeleeAttackTime = WWMath::Random_Float (0.125F, 0.7F);
  1422. return ;
  1423. }
  1424. ///////////////////////////////////////////////////////////////////////////
  1425. //
  1426. // On_ATTACK_STATE_MELEE_Think
  1427. //
  1428. ///////////////////////////////////////////////////////////////////////////
  1429. void
  1430. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_Think (void)
  1431. {
  1432. //
  1433. // Is it time to attack the player again?
  1434. //
  1435. NextMeleeAttackTime -= TimeManager::Get_Frame_Seconds ();
  1436. if (NextMeleeAttackTime <= 0) {
  1437. //
  1438. // Is Mendoza close to the player?
  1439. //
  1440. float dist2 = (MendozaPos - StarPos).Length2 ();
  1441. if (dist2 < 4.0F) {
  1442. //
  1443. // Pick random melee attack...
  1444. //
  1445. int attack_id = FreeRandom.Get_Int (3);
  1446. if (attack_id == 0) {
  1447. AttackState.Set_State (ATTACK_STATE_MELEE_CRESENT_KICK);
  1448. } else if (attack_id == 1) {
  1449. AttackState.Set_State (ATTACK_STATE_MELEE_SIDE_KICK);
  1450. } else if (attack_id == 2) {
  1451. AttackState.Set_State (ATTACK_STATE_MELEE_PUNCH);
  1452. }
  1453. }
  1454. }
  1455. return ;
  1456. }
  1457. ///////////////////////////////////////////////////////////////////////////
  1458. //
  1459. // STATE_IMPL_BEGIN(ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN)
  1460. //
  1461. ///////////////////////////////////////////////////////////////////////////
  1462. void
  1463. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN) (void)
  1464. {
  1465. //
  1466. // Kill the action
  1467. //
  1468. Get_Action ()->Reset (100);
  1469. HasMeleeAttackHit = false;
  1470. LastMeleeAnimFrame = 0;
  1471. //
  1472. // Aim for the player
  1473. //
  1474. SideKickPos = StarPos;
  1475. Set_Targeting (StarPos, false);
  1476. //
  1477. // Play the run animation
  1478. //
  1479. Set_Blended_Animation ("S_A_HUMAN.H_A_A0A1", false);
  1480. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1481. //
  1482. // Stop the animation at frame 4
  1483. //
  1484. Get_Anim_Control()->Set_Mode (ANIM_MODE_TARGET, 0);
  1485. Get_Anim_Control()->Set_Target_Frame (4);
  1486. Peek_Physical_Object ()->Enable_Objects_Simulation (false);
  1487. return ;
  1488. }
  1489. ///////////////////////////////////////////////////////////////////////////
  1490. //
  1491. // STATE_IMPL_THINK(ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN)
  1492. //
  1493. ///////////////////////////////////////////////////////////////////////////
  1494. void
  1495. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN) (void)
  1496. {
  1497. //
  1498. // Move onto the kick if the animation is complete
  1499. //
  1500. if (Get_Anim_Control ()->Is_Complete ()) {
  1501. AttackState.Set_State (ATTACK_STATE_MELEE_FLYING_SIDEKICK);
  1502. } else {
  1503. //
  1504. // Get a direction vector between Mendoza and his destination
  1505. //
  1506. Vector3 dir_vector = (SideKickPos - MendozaPos);
  1507. dir_vector.Normalize ();
  1508. const float SIDEKICK_RATE = 10.0F;
  1509. //
  1510. // Fly through the air to our target
  1511. //
  1512. float rate = SIDEKICK_RATE * TimeManager::Get_Frame_Seconds ();
  1513. Fly_Move (dir_vector * rate);
  1514. }
  1515. return ;
  1516. }
  1517. ///////////////////////////////////////////////////////////////////////////
  1518. //
  1519. // STATE_IMPL_BEGIN(ATTACK_STATE_MELEE_FLYING_SIDEKICK)
  1520. //
  1521. ///////////////////////////////////////////////////////////////////////////
  1522. void
  1523. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_MELEE_FLYING_SIDEKICK) (void)
  1524. {
  1525. HasMeleeAttackHit = false;
  1526. LastMeleeAnimFrame = 0;
  1527. //
  1528. // Play the side kick animation
  1529. //
  1530. Set_Blended_Animation ("S_A_HUMAN.H_A_FLYKICK", false);
  1531. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1532. return ;
  1533. }
  1534. ///////////////////////////////////////////////////////////////////////////
  1535. //
  1536. // STATE_IMPL_END(ATTACK_STATE_MELEE_FLYING_SIDEKICK)
  1537. //
  1538. ///////////////////////////////////////////////////////////////////////////
  1539. void
  1540. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_MELEE_FLYING_SIDEKICK) (void)
  1541. {
  1542. //
  1543. // Now, play the animation backwards a few frams to simulate "landing"
  1544. //
  1545. int curr_frame = Get_Anim_Control()->Get_Current_Frame ();
  1546. Set_Blended_Animation ("S_A_HUMAN.H_A_FLYKICK", false);
  1547. Get_Anim_Control()->Set_Mode (ANIM_MODE_TARGET, curr_frame);
  1548. Get_Anim_Control()->Set_Target_Frame (0);
  1549. //
  1550. // Release our lock on the human state
  1551. //
  1552. HumanState.Set_State (HumanStateClass::ANIMATION);
  1553. return ;
  1554. }
  1555. ///////////////////////////////////////////////////////////////////////////
  1556. //
  1557. // STATE_IMPL_THINK(ATTACK_STATE_MELEE_FLYING_SIDEKICK)
  1558. //
  1559. ///////////////////////////////////////////////////////////////////////////
  1560. void
  1561. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_MELEE_FLYING_SIDEKICK) (void)
  1562. {
  1563. //
  1564. // Get a direction vector between Mendoza and his destination
  1565. //
  1566. Vector3 dir_vector = (SideKickPos - MendozaPos);
  1567. float dist2 = dir_vector.Length2 ();
  1568. dir_vector.Normalize ();
  1569. //
  1570. // Are we close to our goal?
  1571. //
  1572. bool is_finished = false;
  1573. if (dist2 < 0.2F) {
  1574. is_finished = true;
  1575. } else {
  1576. const float SIDEKICK_RATE = 10.0F;
  1577. //
  1578. // Fly through the air to our target
  1579. //
  1580. float rate = SIDEKICK_RATE * TimeManager::Get_Frame_Seconds ();
  1581. if (Fly_Move (dir_vector * rate)) {
  1582. is_finished = true;
  1583. }
  1584. //
  1585. // Apply any damage done by the foot that's kicking...
  1586. //
  1587. if (HasMeleeAttackHit == false) {
  1588. HasMeleeAttackHit = Apply_Bone_Collision_Damage ("C L FOOT");
  1589. }
  1590. }
  1591. //
  1592. // If we're finished, then reset back to normal Melee state
  1593. //
  1594. if (is_finished) {
  1595. Peek_Physical_Object ()->Enable_Objects_Simulation (true);
  1596. OverallState.Set_State (OVERALL_STATE_MELEE_ATTACK);
  1597. }
  1598. //
  1599. // Cache the last frame number...
  1600. //
  1601. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1602. return ;
  1603. }
  1604. ///////////////////////////////////////////////////////////////////////////
  1605. //
  1606. // On_ATTACK_STATE_MELEE_CRESENT_KICK_Begin
  1607. //
  1608. ///////////////////////////////////////////////////////////////////////////
  1609. void
  1610. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_CRESENT_KICK_Begin (void)
  1611. {
  1612. //
  1613. // Kill the action
  1614. //
  1615. //Get_Action ()->Reset (100.0F);
  1616. MoveState.Halt_State ();
  1617. HasMeleeAttackHit = false;
  1618. LastMeleeAnimFrame = 0;
  1619. //
  1620. // Aim for the player
  1621. //
  1622. Set_Targeting (StarPos, false);
  1623. //
  1624. // Play the kick backwards so it becomes a reverse-cresent kick (which
  1625. // looks a lot better).
  1626. //
  1627. Set_Blended_Animation ("S_A_HUMAN.H_A_CRESENTKICK", false, 0, true);
  1628. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1629. //
  1630. // Play the whoosh sound...
  1631. //
  1632. Attach_Sound ("Fight Whoosh Sound Twiddler", "ROOTTRANSFORM");
  1633. return ;
  1634. }
  1635. ///////////////////////////////////////////////////////////////////////////
  1636. //
  1637. // STATE_IMPL_END(ATTACK_STATE_MELEE_CRESENT_KICK)
  1638. //
  1639. ///////////////////////////////////////////////////////////////////////////
  1640. void
  1641. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_MELEE_CRESENT_KICK) (void)
  1642. {
  1643. //
  1644. // Release our lock on the human state
  1645. //
  1646. HumanState.Set_State (HumanStateClass::ANIMATION);
  1647. MoveState.Resume_State ();
  1648. return ;
  1649. }
  1650. ///////////////////////////////////////////////////////////////////////////
  1651. //
  1652. // On_ATTACK_STATE_MELEE_CRESENT_KICK_Think
  1653. //
  1654. ///////////////////////////////////////////////////////////////////////////
  1655. void
  1656. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_CRESENT_KICK_Think (void)
  1657. {
  1658. if (Get_Anim_Control ()->Is_Complete ()) {
  1659. //
  1660. // Reset back to general melee state
  1661. //
  1662. HumanState.Set_State (HumanStateClass::ANIMATION);
  1663. AttackState.Set_State (ATTACK_STATE_MELEE);
  1664. } else if (Get_Anim_Control ()->Get_Current_Frame () < 7.0F) {
  1665. //
  1666. // Apply any damage done by the foot that's kicking...
  1667. //
  1668. if (HasMeleeAttackHit == false) {
  1669. HasMeleeAttackHit = Apply_Bone_Collision_Damage ("C R FOOT");
  1670. }
  1671. }
  1672. //
  1673. // Cache the last frame number...
  1674. //
  1675. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1676. return ;
  1677. }
  1678. ///////////////////////////////////////////////////////////////////////////
  1679. //
  1680. // On_ATTACK_STATE_MELEE_SIDE_KICK_Begin
  1681. //
  1682. ///////////////////////////////////////////////////////////////////////////
  1683. void
  1684. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_SIDE_KICK_Begin (void)
  1685. {
  1686. //
  1687. // Kill the action
  1688. //
  1689. //Get_Action ()->Reset (100.0F);
  1690. MoveState.Halt_State ();
  1691. HasMeleeAttackHit = false;
  1692. //
  1693. // Aim for the player
  1694. //
  1695. Set_Targeting (StarPos, false);
  1696. //
  1697. // Do the kick!
  1698. //
  1699. Set_Blended_Animation ("S_A_HUMAN.H_A_SIDEKICK", false);
  1700. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1701. //
  1702. // Play the whoosh sound...
  1703. //
  1704. Attach_Sound ("Fight Whoosh Sound Twiddler", "ROOTTRANSFORM");
  1705. return ;
  1706. }
  1707. ///////////////////////////////////////////////////////////////////////////
  1708. //
  1709. // STATE_IMPL_END(ATTACK_STATE_MELEE_SIDE_KICK)
  1710. //
  1711. ///////////////////////////////////////////////////////////////////////////
  1712. void
  1713. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_MELEE_SIDE_KICK) (void)
  1714. {
  1715. //
  1716. // Release our lock on the human state
  1717. //
  1718. HumanState.Set_State (HumanStateClass::ANIMATION);
  1719. MoveState.Resume_State ();
  1720. return ;
  1721. }
  1722. ///////////////////////////////////////////////////////////////////////////
  1723. //
  1724. // On_ATTACK_STATE_MELEE_SIDE_KICK_Think
  1725. //
  1726. ///////////////////////////////////////////////////////////////////////////
  1727. void
  1728. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_SIDE_KICK_Think (void)
  1729. {
  1730. if (Get_Anim_Control ()->Is_Complete ()) {
  1731. //
  1732. // Now retract the kick...
  1733. //
  1734. AttackState.Set_State (ATTACK_STATE_MELEE_SIDE_KICK_RETRACT);
  1735. } else if (Get_Anim_Control ()->Get_Current_Frame () > 6.0F) {
  1736. //
  1737. // Apply any damage done by the foot that's kicking...
  1738. //
  1739. if (HasMeleeAttackHit == false) {
  1740. HasMeleeAttackHit =Apply_Bone_Collision_Damage ("C L FOOT");
  1741. }
  1742. }
  1743. //
  1744. // Cache the last frame number...
  1745. //
  1746. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1747. return ;
  1748. }
  1749. ///////////////////////////////////////////////////////////////////////////
  1750. //
  1751. // On_ATTACK_STATE_MELEE_SIDE_KICK_RETRACT_Begin
  1752. //
  1753. ///////////////////////////////////////////////////////////////////////////
  1754. void
  1755. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_SIDE_KICK_RETRACT_Begin (void)
  1756. {
  1757. //
  1758. // Play the kick backwards... :>
  1759. //
  1760. Set_Blended_Animation ("S_A_HUMAN.H_A_SIDEKICK", false, 0, true);
  1761. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1762. return ;
  1763. }
  1764. ///////////////////////////////////////////////////////////////////////////
  1765. //
  1766. // STATE_IMPL_END(ATTACK_STATE_MELEE_SIDE_KICK_RETRACT)
  1767. //
  1768. ///////////////////////////////////////////////////////////////////////////
  1769. void
  1770. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_MELEE_SIDE_KICK_RETRACT) (void)
  1771. {
  1772. //
  1773. // Release our lock on the human state
  1774. //
  1775. HumanState.Set_State (HumanStateClass::ANIMATION);
  1776. MoveState.Resume_State ();
  1777. return ;
  1778. }
  1779. ///////////////////////////////////////////////////////////////////////////
  1780. //
  1781. // On_ATTACK_STATE_MELEE_SIDE_KICK_RETRACT_Think
  1782. //
  1783. ///////////////////////////////////////////////////////////////////////////
  1784. void
  1785. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_SIDE_KICK_RETRACT_Think (void)
  1786. {
  1787. if (Get_Anim_Control ()->Is_Complete ()) {
  1788. //
  1789. // Reset back to general melee state
  1790. //
  1791. HumanState.Set_State (HumanStateClass::ANIMATION);
  1792. AttackState.Set_State (ATTACK_STATE_MELEE);
  1793. }
  1794. return ;
  1795. }
  1796. ///////////////////////////////////////////////////////////////////////////
  1797. //
  1798. // On_ATTACK_STATE_MELEE_PUNCH_Begin
  1799. //
  1800. ///////////////////////////////////////////////////////////////////////////
  1801. void
  1802. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_PUNCH_Begin (void)
  1803. {
  1804. //
  1805. // Kill the action
  1806. //
  1807. //Get_Action ()->Reset (100.0F);
  1808. MoveState.Halt_State ();
  1809. HasMeleeAttackHit = false;
  1810. LastMeleeAnimFrame = 0;
  1811. //
  1812. // Aim for the player
  1813. //
  1814. Set_Targeting (StarPos, false);
  1815. //
  1816. // Play the punch animation
  1817. //
  1818. Set_Blended_Animation ("S_A_HUMAN.H_A_PunchCombo", false);
  1819. HumanState.Set_State (HumanStateClass::LOCKED_ANIMATION);
  1820. AttackingBoneName = "C R HAND";
  1821. //
  1822. // Play the whoosh sound...
  1823. //
  1824. Attach_Sound ("Fight Whoosh Sound Twiddler", "ROOTTRANSFORM");
  1825. return ;
  1826. }
  1827. ///////////////////////////////////////////////////////////////////////////
  1828. //
  1829. // STATE_IMPL_END(ATTACK_STATE_MELEE_PUNCH)
  1830. //
  1831. ///////////////////////////////////////////////////////////////////////////
  1832. void
  1833. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_MELEE_PUNCH) (void)
  1834. {
  1835. //
  1836. // Release our lock on the human state
  1837. //
  1838. HumanState.Set_State (HumanStateClass::ANIMATION);
  1839. MoveState.Resume_State ();
  1840. return ;
  1841. }
  1842. ///////////////////////////////////////////////////////////////////////////
  1843. //
  1844. // On_ATTACK_STATE_MELEE_PUNCH_Think
  1845. //
  1846. ///////////////////////////////////////////////////////////////////////////
  1847. void
  1848. MendozaBossGameObjClass::On_ATTACK_STATE_MELEE_PUNCH_Think (void)
  1849. {
  1850. if (Get_Anim_Control ()->Is_Complete ()) {
  1851. //
  1852. // Reset back to general melee state
  1853. //
  1854. AttackState.Set_State (ATTACK_STATE_MELEE);
  1855. } else {
  1856. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  1857. //
  1858. // Handy macro
  1859. //
  1860. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  1861. //
  1862. // Determine what frame we've passed
  1863. //
  1864. bool is_new_attack = true;
  1865. if (PASSED_FRAME (10.0F)) {
  1866. AttackingBoneName = "C R HAND";
  1867. } else if (PASSED_FRAME (13.0F)) {
  1868. AttackingBoneName = "C R HAND";
  1869. } else if (PASSED_FRAME (21.0F)) {
  1870. AttackingBoneName = "C R HAND";
  1871. } else if (PASSED_FRAME (30.0F)) {
  1872. AttackingBoneName = "C L HAND";
  1873. } else if (PASSED_FRAME (42.0F)) {
  1874. AttackingBoneName = "C R HAND";
  1875. } else {
  1876. is_new_attack = false;
  1877. }
  1878. //
  1879. // Play the "whoosh" sound... :)
  1880. //
  1881. if (is_new_attack) {
  1882. HasMeleeAttackHit = false;
  1883. Attach_Sound ("Fight Whoosh Sound Twiddler", "ROOTTRANSFORM");
  1884. }
  1885. if (curr_frame >= 13.0F && curr_frame < 45.0F) {
  1886. //
  1887. // Apply any damage done by the foot that's kicking...
  1888. //
  1889. if (HasMeleeAttackHit == false) {
  1890. HasMeleeAttackHit = Apply_Bone_Collision_Damage (AttackingBoneName);
  1891. }
  1892. }
  1893. }
  1894. //
  1895. // Cache the last frame number...
  1896. //
  1897. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1898. return ;
  1899. }
  1900. ///////////////////////////////////////////////////////////////////////////
  1901. //
  1902. // STATE_IMPL_BEGIN(ATTACK_STATE_FLAMETHROWER)
  1903. //
  1904. ///////////////////////////////////////////////////////////////////////////
  1905. void
  1906. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_FLAMETHROWER) (void)
  1907. {
  1908. //
  1909. // Switch to the flamethrower...
  1910. //
  1911. WeaponBag->Select_Weapon_ID (Get_Definition ().WeaponDefID);
  1912. AttackStateTimer = 0.0F;
  1913. return ;
  1914. }
  1915. ///////////////////////////////////////////////////////////////////////////
  1916. //
  1917. // STATE_IMPL_END(ATTACK_STATE_FLAMETHROWER)
  1918. //
  1919. ///////////////////////////////////////////////////////////////////////////
  1920. void
  1921. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_FLAMETHROWER) (void)
  1922. {
  1923. //
  1924. // Stop firing the flamethrower
  1925. //
  1926. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, false);
  1927. return ;
  1928. }
  1929. ///////////////////////////////////////////////////////////////////////////
  1930. //
  1931. // STATE_IMPL_THINK(ATTACK_STATE_FLAMETHROWER)
  1932. //
  1933. ///////////////////////////////////////////////////////////////////////////
  1934. void
  1935. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_FLAMETHROWER) (void)
  1936. {
  1937. //
  1938. // Get the player's position relative to Mendoza
  1939. //
  1940. Vector3 relative_position;
  1941. Matrix3D::Inverse_Transform_Vector (Get_Transform (), StarPos, &relative_position);
  1942. bool turn_on_weapon = false;
  1943. //
  1944. // Is the player within 10 meters of Mendoza?
  1945. //
  1946. if ((MendozaPos - StarPos).Length2 () < 100.0F) {
  1947. //
  1948. // Is the player mostly in front of Mendoza?
  1949. //
  1950. if (relative_position.X > 0 && WWMath::Fabs (relative_position.Y) < 5.0F) {
  1951. turn_on_weapon = true;
  1952. }
  1953. }
  1954. //
  1955. // Turn on or off the flamethrower
  1956. //
  1957. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, turn_on_weapon);
  1958. return ;
  1959. }
  1960. ///////////////////////////////////////////////////////////////////////////
  1961. //
  1962. // STATE_IMPL_BEGIN(ATTACK_STATE_FIREBALL)
  1963. //
  1964. ///////////////////////////////////////////////////////////////////////////
  1965. void
  1966. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_FIREBALL) (void)
  1967. {
  1968. //
  1969. // Switch to the flamethrower...
  1970. //
  1971. WeaponBag->Select_Weapon_ID (Get_Definition ().WeaponDefID);
  1972. AttackStateTimer = WWMath::Random_Float (5.0F, 9.0F);
  1973. RandomTargetTimer = 0;
  1974. ShootGroundPos = StarPos;
  1975. return ;
  1976. }
  1977. ///////////////////////////////////////////////////////////////////////////
  1978. //
  1979. // STATE_IMPL_END(ATTACK_STATE_FIREBALL)
  1980. //
  1981. ///////////////////////////////////////////////////////////////////////////
  1982. void
  1983. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_FIREBALL) (void)
  1984. {
  1985. //
  1986. // Stop firing the fireball launcher
  1987. //
  1988. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_PRIMARY, false);
  1989. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, false);
  1990. return ;
  1991. }
  1992. ///////////////////////////////////////////////////////////////////////////
  1993. //
  1994. // STATE_IMPL_THINK(ATTACK_STATE_FIREBALL)
  1995. //
  1996. ///////////////////////////////////////////////////////////////////////////
  1997. void
  1998. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_FIREBALL) (void)
  1999. {
  2000. //
  2001. // Target somewhere around the star
  2002. //
  2003. RandomTargetTimer -= TimeManager::Get_Frame_Seconds ();
  2004. if (RandomTargetTimer <= 0) {
  2005. RandomTargetTimer = WWMath::Random_Float (0.25F, 0.6F);
  2006. ShootGroundPos = StarPos;
  2007. ShootGroundPos.X += WWMath::Random_Float (-1.0F, 1.0F);
  2008. ShootGroundPos.Y += WWMath::Random_Float (-1.0F, 1.0F);
  2009. ShootGroundPos.Z += WWMath::Random_Float (0.0F, 2.0F);
  2010. }
  2011. Set_Targeting (ShootGroundPos, true);
  2012. //
  2013. // Determine if its safe for Mendoza to fire his Fireball launcher
  2014. //
  2015. bool is_safe_to_fire = false;
  2016. Vector3 weapon_hit_pos;
  2017. if (WeaponBag->Get_Weapon ()->Cast_Weapon_Down_Muzzle (weapon_hit_pos)) {
  2018. float hit_distance = (MendozaPos - weapon_hit_pos).Length2 ();
  2019. if (hit_distance > 8.0F) {
  2020. is_safe_to_fire = true;
  2021. }
  2022. }
  2023. //
  2024. // Get the player's position relative to Mendoza
  2025. //
  2026. Vector3 relative_position;
  2027. Matrix3D::Inverse_Transform_Vector (Get_Transform (), StarPos, &relative_position);
  2028. //
  2029. // Is the player mostly in front of Mendoza?
  2030. //
  2031. bool turn_on_weapon = false;
  2032. if ((relative_position.X > 0) && WWMath::Fabs (relative_position.Y) < 7.0F) {
  2033. turn_on_weapon = true;
  2034. }
  2035. //
  2036. // Turn on or off the fireball launcher (or flamethrower)
  2037. //
  2038. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_PRIMARY, turn_on_weapon && is_safe_to_fire);
  2039. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, turn_on_weapon && !is_safe_to_fire);
  2040. //
  2041. // Check to see if we're finished with this state...
  2042. //
  2043. AttackStateTimer -= TimeManager::Get_Frame_Seconds ();
  2044. if (AttackStateTimer <= 0) {
  2045. OverallState.Set_State (OVERALL_STATE_RANGED_ATTACK);
  2046. }
  2047. return ;
  2048. }
  2049. ///////////////////////////////////////////////////////////////////////////
  2050. //
  2051. // STATE_IMPL_BEGIN(ATTACK_STATE_HANDGUN)
  2052. //
  2053. ///////////////////////////////////////////////////////////////////////////
  2054. void
  2055. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_HANDGUN) (void)
  2056. {
  2057. //
  2058. // Switch to the handgun...
  2059. //
  2060. WeaponBag->Select_Weapon_ID (Get_Definition ().SecondaryWeaponDefID);
  2061. AttackStateTimer = 2.0F;
  2062. return ;
  2063. }
  2064. ///////////////////////////////////////////////////////////////////////////
  2065. //
  2066. // STATE_IMPL_END(ATTACK_STATE_HANDGUN)
  2067. //
  2068. ///////////////////////////////////////////////////////////////////////////
  2069. void
  2070. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_HANDGUN) (void)
  2071. {
  2072. //
  2073. // Stop firing the handgun
  2074. //
  2075. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_PRIMARY, false);
  2076. WeaponBag->Deselect ();
  2077. return ;
  2078. }
  2079. ///////////////////////////////////////////////////////////////////////////
  2080. //
  2081. // STATE_IMPL_THINK(ATTACK_STATE_HANDGUN)
  2082. //
  2083. ///////////////////////////////////////////////////////////////////////////
  2084. void
  2085. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_HANDGUN) (void)
  2086. {
  2087. bool turn_on_weapon = false;
  2088. //
  2089. // Get the player's position relative to Mendoza
  2090. //
  2091. Vector3 relative_position;
  2092. Matrix3D::Inverse_Transform_Vector (Get_Transform (), StarPos, &relative_position);
  2093. //
  2094. // Is the player in front of Mendoza?
  2095. //
  2096. if (relative_position.X > 0) {
  2097. turn_on_weapon = true;
  2098. }
  2099. //
  2100. // Turn on or off the handgun
  2101. //
  2102. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_PRIMARY, turn_on_weapon);
  2103. //
  2104. // Switch back to the normal attack state if we're finished
  2105. //
  2106. AttackStateTimer -= TimeManager::Get_Frame_Seconds ();
  2107. if (AttackStateTimer <= 0) {
  2108. //
  2109. // Determine which attack state to revert to
  2110. //
  2111. if (OverallState.Get_State () == OVERALL_STATE_MELEE_ATTACK) {
  2112. AttackState.Set_State (ATTACK_STATE_MELEE);
  2113. } else if (OverallState.Get_State () == OVERALL_STATE_RANGED_ATTACK) {
  2114. AttackState.Set_State (ATTACK_STATE_FLAMETHROWER);
  2115. } else if (OverallState.Get_State () == OVERALL_STATE_FIREBALL_ATTACK) {
  2116. AttackState.Set_State (ATTACK_STATE_FIREBALL);
  2117. }
  2118. }
  2119. return ;
  2120. }
  2121. ///////////////////////////////////////////////////////////////////////////
  2122. //
  2123. // STATE_IMPL_BEGIN(ATTACK_STATE_SYDNEY)
  2124. //
  2125. ///////////////////////////////////////////////////////////////////////////
  2126. void
  2127. MendozaBossGameObjClass::STATE_IMPL_BEGIN(ATTACK_STATE_SYDNEY) (void)
  2128. {
  2129. //
  2130. // Switch to the handgun...
  2131. //
  2132. WeaponBag->Select_Weapon_ID (Get_Definition ().WeaponDefID);
  2133. //
  2134. // Set the timer so the first think call will cause the action...
  2135. //
  2136. AttackStateTimer = 0;
  2137. return ;
  2138. }
  2139. ///////////////////////////////////////////////////////////////////////////
  2140. //
  2141. // STATE_IMPL_END(ATTACK_STATE_SYDNEY)
  2142. //
  2143. ///////////////////////////////////////////////////////////////////////////
  2144. void
  2145. MendozaBossGameObjClass::STATE_IMPL_END(ATTACK_STATE_SYDNEY) (void)
  2146. {
  2147. //
  2148. // Stop firing...
  2149. //
  2150. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, false);
  2151. return ;
  2152. }
  2153. ///////////////////////////////////////////////////////////////////////////
  2154. //
  2155. // STATE_IMPL_THINK(ATTACK_STATE_SYDNEY)
  2156. //
  2157. ///////////////////////////////////////////////////////////////////////////
  2158. void
  2159. MendozaBossGameObjClass::STATE_IMPL_THINK(ATTACK_STATE_SYDNEY) (void)
  2160. {
  2161. AttackStateTimer -= TimeManager::Get_Frame_Seconds ();
  2162. if (AttackStateTimer <= 0) {
  2163. AttackStateTimer = WWMath::Random_Float (0.5F, 1.5F);
  2164. //
  2165. // Get her position
  2166. //
  2167. Sydney.Get_Ptr ()->Get_Position (&ShootGroundPos);
  2168. const float RADIUS = 2.0F;
  2169. //
  2170. // Pick a random position in a circle around her feet
  2171. //
  2172. float angle = WWMath::Random_Float (DEG_TO_RADF (0.0F), DEG_TO_RADF (180.0F));
  2173. ShootGroundPos.X += WWMath::Fast_Cos (angle) * RADIUS;
  2174. ShootGroundPos.Y += WWMath::Fast_Sin (angle) * RADIUS;
  2175. }
  2176. //
  2177. // Target the ground at Sydney's feet
  2178. //
  2179. Set_Targeting (ShootGroundPos, true);
  2180. //
  2181. // Fire the weapon...
  2182. //
  2183. Set_Boolean_Control (ControlClass::BOOLEAN_WEAPON_FIRE_SECONDARY, true);
  2184. return ;
  2185. }
  2186. ///////////////////////////////////////////////////////////////////////////
  2187. //
  2188. // Fly_Move
  2189. //
  2190. ///////////////////////////////////////////////////////////////////////////
  2191. bool
  2192. MendozaBossGameObjClass::Fly_Move (const Vector3 &vector)
  2193. {
  2194. //
  2195. // Get Mendoza's collision box
  2196. //
  2197. AABoxClass collision_box = Peek_Physical_Object ()->As_HumanPhysClass ()->Get_Collision_Box ();
  2198. collision_box.Center += MendozaPos;
  2199. //
  2200. // Check to see if we've hit something
  2201. //
  2202. CastResultStruct result;
  2203. AABoxCollisionTestClass col_test (collision_box, vector, &result, COLLISION_TYPE_PHYSICAL);
  2204. //
  2205. // Find where we hit
  2206. //
  2207. bool retval = COMBAT_STAR->Peek_Model ()->Cast_AABox (col_test);
  2208. if (result.StartBad == false) {
  2209. //
  2210. // Calculate where to move to...
  2211. //
  2212. Vector3 new_pos = MendozaPos + (vector * (result.Fraction * 0.99F));
  2213. //
  2214. // Move Mendoza
  2215. //
  2216. Set_Position (new_pos);
  2217. }
  2218. return retval;
  2219. }
  2220. ///////////////////////////////////////////////////////////////////////////
  2221. //
  2222. // Apply_Bone_Collision_Damage
  2223. //
  2224. ///////////////////////////////////////////////////////////////////////////
  2225. bool
  2226. MendozaBossGameObjClass::Apply_Bone_Collision_Damage (const char *bone_name)
  2227. {
  2228. int bone_index = Peek_Model ()->Get_Bone_Index (bone_name);
  2229. //
  2230. // Lookup the current and last positions of the bone in question
  2231. //
  2232. Matrix3D last_bone_tm;
  2233. Matrix3D curr_bone_tm;
  2234. ((Animatable3DObjClass *)Peek_Model ())->Simple_Evaluate_Bone (bone_index, &curr_bone_tm);
  2235. ((Animatable3DObjClass *)Peek_Model ())->Simple_Evaluate_Bone (bone_index, LastMeleeAnimFrame, &last_bone_tm);
  2236. //
  2237. // Calculate where the bone moved
  2238. //
  2239. Vector3 move_vector = curr_bone_tm.Get_Translation () - last_bone_tm.Get_Translation ();
  2240. //
  2241. // Build a box around the bone that we can use for collision detection
  2242. //
  2243. AABoxClass bone_box;
  2244. bone_box.Center = curr_bone_tm.Get_Translation ();
  2245. bone_box.Extent.Set (0.2F, 0.2F, 0.2F);
  2246. //
  2247. // Try to find where (if anywhere) we hit the player
  2248. //
  2249. CastResultStruct result;
  2250. result.ComputeContactPoint = true;
  2251. AABoxCollisionTestClass col_test (bone_box, move_vector, &result, COLLISION_TYPE_PROJECTILE);
  2252. //
  2253. // Find where we hit
  2254. //
  2255. bool retval = COMBAT_STAR->Peek_Model ()->Cast_AABox (col_test);
  2256. if (retval) {
  2257. //
  2258. // Dig the name of the mesh out
  2259. //
  2260. StringClass obj_name;
  2261. if (col_test.CollidedRenderObj != NULL) {
  2262. obj_name = col_test.CollidedRenderObj->Get_Name ();
  2263. }
  2264. //
  2265. // Apply 10 points of "steel" damage to the player
  2266. //
  2267. OffenseObjectClass offense_obj (5.0F, 1);
  2268. COMBAT_STAR->Apply_Damage_Extended (offense_obj, 1.0F, Vector3 (-1, 0, 0), obj_name);
  2269. //
  2270. // Knock the player back a little bit
  2271. //
  2272. Vector3 delta_vector = move_vector;
  2273. delta_vector.Normalize ();
  2274. COMBAT_STAR->Peek_Physical_Object ()->As_Phys3Class ()->Collide (delta_vector * 0.75F);
  2275. //
  2276. // Play the hit sound...
  2277. //
  2278. Attach_Sound ("Fight Impact Sound Twiddler", "ROOTTRANSFORM");
  2279. }
  2280. return retval;
  2281. }
  2282. ///////////////////////////////////////////////////////////////////////////
  2283. //
  2284. // STATE_IMPL_BEGIN(OVERALL_STATE_FLYING_SIDEKICK)
  2285. //
  2286. ///////////////////////////////////////////////////////////////////////////
  2287. void
  2288. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_FLYING_SIDEKICK) (void)
  2289. {
  2290. //
  2291. // Pull the strings to get the melee battle to begin
  2292. //
  2293. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2294. MoveState.Set_State (MOVE_STATE_STOP);
  2295. AttackState.Set_State (ATTACK_STATE_MELEE_FLYING_SIDEKICK_RUN);
  2296. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2297. SydneyState.Set_State (SYDNEY_STATE_WAITING);
  2298. HeadState.Set_State (HEAD_STATE_LOOKING_AT_STAR);
  2299. //
  2300. // Get rid of the weapon in his hands
  2301. //
  2302. WeaponBag->Deselect ();
  2303. return ;
  2304. }
  2305. ///////////////////////////////////////////////////////////////////////////
  2306. //
  2307. // STATE_IMPL_BEGIN(OVERALL_STATE_MELEE_ATTACK)
  2308. //
  2309. ///////////////////////////////////////////////////////////////////////////
  2310. void
  2311. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_MELEE_ATTACK) (void)
  2312. {
  2313. //
  2314. // Pull the strings to get the melee battle to begin
  2315. //
  2316. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2317. MoveState.Set_State (MOVE_STATE_GET_CLOSE_TO_PLAYER);
  2318. AttackState.Set_State (ATTACK_STATE_MELEE);
  2319. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2320. SydneyState.Set_State (SYDNEY_STATE_WAITING);
  2321. HeadState.Set_State (HEAD_STATE_LOOKING_AT_STAR);
  2322. //
  2323. // Get rid of the weapon in his hands
  2324. //
  2325. WeaponBag->Deselect ();
  2326. return ;
  2327. }
  2328. ///////////////////////////////////////////////////////////////////////////
  2329. //
  2330. // STATE_IMPL_BEGIN(OVERALL_STATE_RANGED_ATTACK)
  2331. //
  2332. ///////////////////////////////////////////////////////////////////////////
  2333. void
  2334. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_RANGED_ATTACK) (void)
  2335. {
  2336. //
  2337. // Pull the strings to get the ranged battle to begin
  2338. //
  2339. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2340. MoveState.Set_State (MOVE_STATE_ATTACK_PATTERN1);
  2341. AttackState.Set_State (ATTACK_STATE_FLAMETHROWER);
  2342. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2343. HeadState.Set_State (HEAD_STATE_LOOKING_AT_STAR);
  2344. OverallStateTimer = 0;
  2345. //
  2346. // Reset the fireball launcher state timer as necessary.
  2347. // We want to ensure this state happens from time to time,
  2348. // however we don't want it happening all the time.
  2349. //
  2350. if (FireballStartTimer == 0) {
  2351. FireballStartTimer = WWMath::Random_Float (6.0F, 12.0F);
  2352. }
  2353. return ;
  2354. }
  2355. ///////////////////////////////////////////////////////////////////////////
  2356. //
  2357. // STATE_IMPL_THINK(OVERALL_STATE_RANGED_ATTACK)
  2358. //
  2359. ///////////////////////////////////////////////////////////////////////////
  2360. void
  2361. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_RANGED_ATTACK) (void)
  2362. {
  2363. //
  2364. // Every half second check to see if Mendoza should try to find a powerup
  2365. // to pickup...
  2366. //
  2367. OverallStateTimer -= TimeManager::Get_Frame_Seconds ();
  2368. if (OverallStateTimer <= 0) {
  2369. OverallStateTimer = 0.5F;
  2370. //
  2371. // Take a random roll of the dice to decide whether or not to try to pickup health...
  2372. //
  2373. float curr_health = DefenseObject.Get_Health () / DefenseObject.Get_Health_Max ();
  2374. int probability = int(curr_health * 20.0F);
  2375. if (FreeRandom.Get_Int (probability) == 1) {
  2376. OverallState.Set_State (OVERALL_STATE_FIND_HEALTH);
  2377. }
  2378. } else {
  2379. //
  2380. // Is it time to change to the "fireball" attack?
  2381. //
  2382. FireballStartTimer -= TimeManager::Get_Frame_Seconds ();
  2383. if (FireballStartTimer <= 0) {
  2384. FireballStartTimer = WWMath::Random_Float (6.0F, 12.0F);
  2385. //
  2386. // Do the fireball attack
  2387. //
  2388. OverallState.Set_State (OVERALL_STATE_FIREBALL_ATTACK);
  2389. }
  2390. }
  2391. return ;
  2392. }
  2393. ///////////////////////////////////////////////////////////////////////////
  2394. //
  2395. // STATE_IMPL_BEGIN(OVERALL_STATE_FIREBALL_ATTACK)
  2396. //
  2397. ///////////////////////////////////////////////////////////////////////////
  2398. void
  2399. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_FIREBALL_ATTACK) (void)
  2400. {
  2401. //
  2402. // Pull the strings to get the ranged battle to begin
  2403. //
  2404. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2405. MoveState.Set_State (MOVE_STATE_GOTO_HELIPAD);
  2406. AttackState.Set_State (ATTACK_STATE_NONE);
  2407. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2408. HeadState.Set_State (HEAD_STATE_LOOKING_AT_STAR);
  2409. return ;
  2410. }
  2411. ///////////////////////////////////////////////////////////////////////////
  2412. //
  2413. // STATE_IMPL_THINK(OVERALL_STATE_FIREBALL_ATTACK)
  2414. //
  2415. ///////////////////////////////////////////////////////////////////////////
  2416. void
  2417. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_FIREBALL_ATTACK) (void)
  2418. {
  2419. return ;
  2420. }
  2421. ///////////////////////////////////////////////////////////////////////////
  2422. //
  2423. // STATE_IMPL_BEGIN(OVERALL_STATE_FIND_HEALTH)
  2424. //
  2425. ///////////////////////////////////////////////////////////////////////////
  2426. void
  2427. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_FIND_HEALTH) (void)
  2428. {
  2429. //
  2430. // Reset the states
  2431. //
  2432. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2433. AttackState.Set_State (ATTACK_STATE_NONE);
  2434. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2435. MoveState.Set_State (MOVE_STATE_RUN_TO_HEALTH, true);
  2436. HeadState.Set_State (HEAD_STATE_LOOKING_AT_STAR);
  2437. return ;
  2438. }
  2439. ///////////////////////////////////////////////////////////////////////////
  2440. //
  2441. // STATE_IMPL_THINK(OVERALL_STATE_FIND_HEALTH)
  2442. //
  2443. ///////////////////////////////////////////////////////////////////////////
  2444. void
  2445. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_FIND_HEALTH) (void)
  2446. {
  2447. //
  2448. // Return to attacking the star if we've found our health
  2449. //
  2450. if (Get_Action ()->Is_Active () == false) {
  2451. OverallState.Set_State (OVERALL_STATE_RANGED_ATTACK);
  2452. }
  2453. return ;
  2454. }
  2455. ///////////////////////////////////////////////////////////////////////////
  2456. //
  2457. // STATE_IMPL_BEGIN(OVERALL_STATE_SYDNEY_BOLTS)
  2458. //
  2459. ///////////////////////////////////////////////////////////////////////////
  2460. void
  2461. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_SYDNEY_BOLTS) (void)
  2462. {
  2463. OverallStateTimer = 3.0F;
  2464. //
  2465. // Stand still and look at Sydney
  2466. //
  2467. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2468. AttackState.Set_State (ATTACK_STATE_NONE);
  2469. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2470. MoveState.Set_State (MOVE_STATE_STOP);
  2471. SydneyState.Set_State (SYDNEY_STATE_BOLTING);
  2472. HeadState.Set_State (HEAD_STATE_LOOKING_AT_SYDNEY);
  2473. return ;
  2474. }
  2475. ///////////////////////////////////////////////////////////////////////////
  2476. //
  2477. // STATE_IMPL_THINK(OVERALL_STATE_SYDNEY_BOLTS)
  2478. //
  2479. ///////////////////////////////////////////////////////////////////////////
  2480. void
  2481. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_SYDNEY_BOLTS) (void)
  2482. {
  2483. OverallStateTimer -= TimeManager::Get_Frame_Seconds ();
  2484. if (OverallStateTimer <= 0) {
  2485. //
  2486. // Start chasing Sydney
  2487. //
  2488. OverallState.Set_State (OVERALL_STATE_RUN_AFTER_SYDNEY);
  2489. }
  2490. return ;
  2491. }
  2492. ///////////////////////////////////////////////////////////////////////////
  2493. //
  2494. // STATE_IMPL_BEGIN(OVERALL_STATE_RUN_AFTER_SYDNEY)
  2495. //
  2496. ///////////////////////////////////////////////////////////////////////////
  2497. void
  2498. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_RUN_AFTER_SYDNEY) (void)
  2499. {
  2500. //
  2501. // Start chasing Sydney
  2502. //
  2503. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2504. AttackState.Set_State (ATTACK_STATE_NONE);
  2505. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2506. MoveState.Set_State (MOVE_STATE_CHASE_SYDNEY);
  2507. HeadState.Set_State (HEAD_STATE_LOOKING_AT_SYDNEY);
  2508. //
  2509. // Clue the player in that they need to assist Sydney
  2510. //
  2511. HUDInfo::Set_HUD_Help_Text (TRANSLATE (IDS_MENDOZA_BOSS_HELP_SYDNEY), Vector3 (1.0F, 0.0F, 0.0F));
  2512. return ;
  2513. }
  2514. ///////////////////////////////////////////////////////////////////////////
  2515. //
  2516. // STATE_IMPL_THINK(OVERALL_STATE_RUN_AFTER_SYDNEY)
  2517. //
  2518. ///////////////////////////////////////////////////////////////////////////
  2519. void
  2520. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_RUN_AFTER_SYDNEY) (void)
  2521. {
  2522. //
  2523. // If Mendoza is within 2 meters of his goal, then switch to his "toying" state...
  2524. //
  2525. float dist = (MendozaPos - MENDOZA_END_POS).Length ();
  2526. if (dist < 2.0F) {
  2527. OverallState.Set_State (OVERALL_STATE_TOY_WITH_SYDNEY);
  2528. }
  2529. return ;
  2530. }
  2531. ///////////////////////////////////////////////////////////////////////////
  2532. //
  2533. // STATE_IMPL_BEGIN(OVERALL_STATE_TOY_WITH_SYDNEY)
  2534. //
  2535. ///////////////////////////////////////////////////////////////////////////
  2536. void
  2537. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_TOY_WITH_SYDNEY) (void)
  2538. {
  2539. //
  2540. // Stand still so we can take pot-shots at Sydney
  2541. //
  2542. MendozaState.Set_State (MENDOZA_STATE_STANDING);
  2543. AttackState.Set_State (ATTACK_STATE_SYDNEY);
  2544. CameraState.Set_State (CAMERA_STATE_NORMAL);
  2545. //MoveState.Set_State (MOVE_STATE_STOP);
  2546. HeadState.Set_State (HEAD_STATE_LOOKING_AT_SYDNEY);
  2547. return ;
  2548. }
  2549. ///////////////////////////////////////////////////////////////////////////
  2550. //
  2551. // STATE_IMPL_THINK(OVERALL_STATE_TOY_WITH_SYDNEY)
  2552. //
  2553. ///////////////////////////////////////////////////////////////////////////
  2554. void
  2555. MendozaBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_TOY_WITH_SYDNEY) (void)
  2556. {
  2557. if (MoveState.Get_State () != MOVE_STATE_STOP) {
  2558. //
  2559. // If Mendoza has gotten close enough to his goal, then make him stop...
  2560. //
  2561. float dist = (MendozaPos - MENDOZA_END_POS).Length ();
  2562. if (dist < 1.0F) {
  2563. MoveState.Set_State (MOVE_STATE_STOP);
  2564. }
  2565. }
  2566. return ;
  2567. }
  2568. ///////////////////////////////////////////////////////////////////////////
  2569. //
  2570. // STATE_IMPL_BEGIN(OVERALL_STATE_DEATH_SEQUENCE)
  2571. //
  2572. ///////////////////////////////////////////////////////////////////////////
  2573. void
  2574. MendozaBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_DEATH_SEQUENCE) (void)
  2575. {
  2576. //
  2577. // Set the defense object to "blamo" so the game object won't die prematurely...
  2578. //
  2579. DefenseObject.Set_Skin ((ArmorType)1);
  2580. DefenseObject.Set_Shield_Type ((ArmorType)1);
  2581. //
  2582. // Force the states necessary for the death sequence
  2583. //
  2584. MendozaState.Set_State (MENDOZA_STATE_STANDING, true);
  2585. AttackState.Set_State (ATTACK_STATE_NONE, true);
  2586. CameraState.Set_State (CAMERA_STATE_FACE_ZOOM, true);
  2587. MoveState.Set_State (MOVE_STATE_STOP, true);
  2588. HeadState.Set_State (HEAD_STATE_NONE, true);
  2589. return ;
  2590. }
  2591. ///////////////////////////////////////////////////////////////////////////
  2592. //
  2593. // STATE_IMPL_BEGIN(SYDNEY_STATE_WAITING)
  2594. //
  2595. ///////////////////////////////////////////////////////////////////////////
  2596. void
  2597. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_WAITING) (void)
  2598. {
  2599. return ;
  2600. }
  2601. ///////////////////////////////////////////////////////////////////////////
  2602. //
  2603. // STATE_IMPL_BEGIN(SYDNEY_STATE_BOLTING)
  2604. //
  2605. ///////////////////////////////////////////////////////////////////////////
  2606. void
  2607. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_BOLTING) (void)
  2608. {
  2609. //
  2610. // Make Sydney bolt to her "end" position
  2611. //
  2612. ActionParamsStruct params;
  2613. params.Set_Basic ((long)0, 100, 777);
  2614. params.Set_Movement (SYDNEY_END_POS, 1.0F, 0.5F);
  2615. Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ()->Get_Action ()->Goto (params);
  2616. return ;
  2617. }
  2618. ///////////////////////////////////////////////////////////////////////////
  2619. //
  2620. // STATE_IMPL_THINK(SYDNEY_STATE_BOLTING)
  2621. //
  2622. ///////////////////////////////////////////////////////////////////////////
  2623. void
  2624. MendozaBossGameObjClass::STATE_IMPL_THINK(SYDNEY_STATE_BOLTING) (void)
  2625. {
  2626. Vector3 syd_pos;
  2627. Sydney.Get_Ptr ()->Get_Position (&syd_pos);
  2628. //
  2629. // Determine how far away Sydney is from her goal...
  2630. //
  2631. float dist = (SYDNEY_END_POS - syd_pos).Length ();
  2632. //
  2633. // If Sydney is within a few meters of her goal, then make her trip. :)
  2634. //
  2635. if (dist <= 5.0F) {
  2636. SydneyState.Set_State (SYDNEY_STATE_TRIPPING);
  2637. }
  2638. return ;
  2639. }
  2640. ///////////////////////////////////////////////////////////////////////////
  2641. //
  2642. // STATE_IMPL_BEGIN(SYDNEY_STATE_TRIPPING)
  2643. //
  2644. ///////////////////////////////////////////////////////////////////////////
  2645. void
  2646. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_TRIPPING) (void)
  2647. {
  2648. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2649. //
  2650. // Play the animation of Sydney tripping
  2651. //
  2652. sydney->Set_Blended_Animation ("S_A_HUMAN.H_A_690A", false, 7.0F);
  2653. sydney->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2654. ((HumanAnimControlClass *)sydney->Get_Anim_Control ())->Set_Anim_Speed_Scale (2.0F);
  2655. return ;
  2656. }
  2657. ///////////////////////////////////////////////////////////////////////////
  2658. //
  2659. // STATE_IMPL_THINK(SYDNEY_STATE_TRIPPING)
  2660. //
  2661. ///////////////////////////////////////////////////////////////////////////
  2662. void
  2663. MendozaBossGameObjClass::STATE_IMPL_THINK(SYDNEY_STATE_TRIPPING) (void)
  2664. {
  2665. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2666. //
  2667. // If Sydney finished tripping, and Mendoza is standing over her,
  2668. // then switch her to the cowering state
  2669. //
  2670. if ( sydney->Get_Anim_Control ()->Is_Complete () &&
  2671. OverallState.Get_State () == OVERALL_STATE_TOY_WITH_SYDNEY)
  2672. {
  2673. SydneyState.Set_State (SYDNEY_STATE_GETTING_UP);
  2674. sydney->Get_Human_State ()->Set_State (HumanStateClass::ANIMATION);
  2675. ((HumanAnimControlClass *)sydney->Get_Anim_Control ())->Set_Anim_Speed_Scale (1.0F);
  2676. }
  2677. return ;
  2678. }
  2679. ///////////////////////////////////////////////////////////////////////////
  2680. //
  2681. // STATE_IMPL_BEGIN(SYDNEY_STATE_GETTING_UP)
  2682. //
  2683. ///////////////////////////////////////////////////////////////////////////
  2684. void
  2685. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_GETTING_UP) (void)
  2686. {
  2687. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2688. //
  2689. // Play the animation of Sydney getting up
  2690. //
  2691. sydney->Set_Blended_Animation ("S_A_HUMAN.H_A_H11C", false);
  2692. sydney->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2693. return ;
  2694. }
  2695. ///////////////////////////////////////////////////////////////////////////
  2696. //
  2697. // STATE_IMPL_THINK(SYDNEY_STATE_GETTING_UP)
  2698. //
  2699. ///////////////////////////////////////////////////////////////////////////
  2700. void
  2701. MendozaBossGameObjClass::STATE_IMPL_THINK(SYDNEY_STATE_GETTING_UP) (void)
  2702. {
  2703. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2704. //
  2705. // If Sydney finished getting up, then switch her to the cowering state
  2706. //
  2707. if (sydney->Get_Anim_Control ()->Is_Complete ()) {
  2708. sydney->Get_Human_State ()->Set_State (HumanStateClass::ANIMATION);
  2709. SydneyState.Set_State (SYDNEY_STATE_COWERING);
  2710. }
  2711. return ;
  2712. }
  2713. ///////////////////////////////////////////////////////////////////////////
  2714. //
  2715. // STATE_IMPL_BEGIN(SYDNEY_STATE_COWERING)
  2716. //
  2717. ///////////////////////////////////////////////////////////////////////////
  2718. void
  2719. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_COWERING) (void)
  2720. {
  2721. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2722. sydney->Get_Action ()->Reset (100);
  2723. //
  2724. // Play the "cowering" animation, but stop at frame 7
  2725. //
  2726. sydney->Set_Blended_Animation ("S_A_HUMAN.H_A_A0A0_L50", false);
  2727. sydney->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2728. //
  2729. // Stop the animation at frame 7
  2730. //
  2731. sydney->Get_Anim_Control()->Set_Mode (ANIM_MODE_TARGET, 0);
  2732. sydney->Get_Anim_Control()->Set_Target_Frame (7);
  2733. SydneyStateTimer = 1.0F;
  2734. return ;
  2735. }
  2736. ///////////////////////////////////////////////////////////////////////////
  2737. //
  2738. // STATE_IMPL_END(SYDNEY_STATE_COWERING)
  2739. //
  2740. ///////////////////////////////////////////////////////////////////////////
  2741. void
  2742. MendozaBossGameObjClass::STATE_IMPL_END(SYDNEY_STATE_COWERING) (void)
  2743. {
  2744. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2745. //
  2746. // Release our lock on the animation state
  2747. //
  2748. sydney->Get_Human_State ()->Set_State (HumanStateClass::ANIMATION);
  2749. return ;
  2750. }
  2751. ///////////////////////////////////////////////////////////////////////////
  2752. //
  2753. // STATE_IMPL_THINK(SYDNEY_STATE_COWERING)
  2754. //
  2755. ///////////////////////////////////////////////////////////////////////////
  2756. void
  2757. MendozaBossGameObjClass::STATE_IMPL_THINK(SYDNEY_STATE_COWERING) (void)
  2758. {
  2759. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2760. //
  2761. // Make Sydney face Mendoza
  2762. //
  2763. sydney->Set_Targeting (MENDOZA_END_POS, false);
  2764. //
  2765. // Loop a different part of her cowering animation as necessary...
  2766. //
  2767. SydneyStateTimer -= TimeManager::Get_Frame_Seconds ();
  2768. if (SydneyStateTimer <= 0) {
  2769. SydneyStateTimer = WWMath::Random_Float (1.0F, 2.0F);
  2770. //
  2771. // Toggle the frame range so she keeps flinching
  2772. //
  2773. if (sydney->Get_Anim_Control()->Get_Target_Frame () == 7) {
  2774. sydney->Get_Anim_Control()->Set_Target_Frame (12);
  2775. } else {
  2776. sydney->Get_Anim_Control()->Set_Target_Frame (7);
  2777. }
  2778. //
  2779. // Apply some damage to Sydney...
  2780. //
  2781. OffenseObjectClass off (2.0F, 1);
  2782. sydney->Apply_Damage (off, 1.0F);
  2783. }
  2784. return ;
  2785. }
  2786. ///////////////////////////////////////////////////////////////////////////
  2787. //
  2788. // STATE_IMPL_BEGIN(SYDNEY_STATE_STRIKE_A_POSE)
  2789. //
  2790. ///////////////////////////////////////////////////////////////////////////
  2791. void
  2792. MendozaBossGameObjClass::STATE_IMPL_BEGIN(SYDNEY_STATE_STRIKE_A_POSE) (void)
  2793. {
  2794. SoldierGameObj *sydney = Sydney.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj ();
  2795. //
  2796. // Set the posed animation
  2797. //
  2798. sydney->Set_Animation ("S_B_HUMAN.H_B_A0A0_14", true);
  2799. //
  2800. // Snap Sydney to the right position
  2801. //
  2802. Matrix3D syd_tm (SYDNEY_END_POS);
  2803. syd_tm.Rotate_Z (DEG_TO_RADF (90.0F));
  2804. sydney->Set_Transform (syd_tm);
  2805. return ;
  2806. }
  2807. ///////////////////////////////////////////////////////////////////////////
  2808. //
  2809. // STATE_IMPL_BEGIN(MOVE_STATE_CHASE_SYDNEY)
  2810. //
  2811. ///////////////////////////////////////////////////////////////////////////
  2812. void
  2813. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_CHASE_SYDNEY) (void)
  2814. {
  2815. //
  2816. // Move to our "end" position which should make us look like we're
  2817. // either chasing Sydney or cutting her off...
  2818. //
  2819. ActionParamsStruct params;
  2820. params.Set_Basic ((long)0, 100, 777);
  2821. params.Set_Movement (MENDOZA_END_POS, 0.75F, 0.5F);
  2822. Get_Action ()->Goto (params);
  2823. return ;
  2824. }
  2825. ///////////////////////////////////////////////////////////////////////////
  2826. //
  2827. // STATE_IMPL_BEGIN(MOVE_STATE_STOP)
  2828. //
  2829. ///////////////////////////////////////////////////////////////////////////
  2830. void
  2831. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_STOP) (void)
  2832. {
  2833. //
  2834. // Simply stop any action
  2835. //
  2836. Get_Action ()->Reset (100);
  2837. return ;
  2838. }
  2839. ///////////////////////////////////////////////////////////////////////////
  2840. //
  2841. // STATE_IMPL_BEGIN(MOVE_STATE_GET_CLOSE_TO_PLAYER)
  2842. //
  2843. ///////////////////////////////////////////////////////////////////////////
  2844. void
  2845. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_GET_CLOSE_TO_PLAYER) (void)
  2846. {
  2847. MoveStateTimer = 0.0F;
  2848. return ;
  2849. }
  2850. ///////////////////////////////////////////////////////////////////////////
  2851. //
  2852. // STATE_IMPL_END(MOVE_STATE_GET_CLOSE_TO_PLAYER)
  2853. //
  2854. ///////////////////////////////////////////////////////////////////////////
  2855. void
  2856. MendozaBossGameObjClass::STATE_IMPL_END(MOVE_STATE_GET_CLOSE_TO_PLAYER) (void)
  2857. {
  2858. //
  2859. // Simply stop any action
  2860. //
  2861. Get_Action ()->Reset (100);
  2862. return ;
  2863. }
  2864. ///////////////////////////////////////////////////////////////////////////
  2865. //
  2866. // STATE_IMPL_THINK(MOVE_STATE_GET_CLOSE_TO_PLAYER)
  2867. //
  2868. ///////////////////////////////////////////////////////////////////////////
  2869. void
  2870. MendozaBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_GET_CLOSE_TO_PLAYER) (void)
  2871. {
  2872. //
  2873. // Is it time to track down the player again?
  2874. //
  2875. MoveStateTimer -= TimeManager::Get_Frame_Seconds ();
  2876. if (MoveStateTimer <= 0) {
  2877. MoveStateTimer = 1.0F;
  2878. //
  2879. // Track down the player (if possible)
  2880. //
  2881. if (COMBAT_STAR != NULL && (StarPos.X > -70.0F)) {
  2882. ActionParamsStruct params;
  2883. params.Set_Basic ((long)0, 100, 777);
  2884. params.Set_Movement (COMBAT_STAR, 1.0F, 1.0F);
  2885. params.MoveFollow = true;
  2886. Get_Action ()->Goto (params);
  2887. } else if (COMBAT_STAR != NULL) {
  2888. //
  2889. // If the player goes out of range, then switch to the fireball attack
  2890. //
  2891. OverallState.Set_State (OVERALL_STATE_FIREBALL_ATTACK);
  2892. }
  2893. }
  2894. return ;
  2895. }
  2896. ///////////////////////////////////////////////////////////////////////////
  2897. //
  2898. // STATE_IMPL_BEGIN(MOVE_STATE_ATTACK_PATTERN1)
  2899. //
  2900. ///////////////////////////////////////////////////////////////////////////
  2901. void
  2902. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_ATTACK_PATTERN1) (void)
  2903. {
  2904. MoveStateTimer = 0.0F;
  2905. return ;
  2906. }
  2907. ///////////////////////////////////////////////////////////////////////////
  2908. //
  2909. // STATE_IMPL_END(MOVE_STATE_ATTACK_PATTERN1)
  2910. //
  2911. ///////////////////////////////////////////////////////////////////////////
  2912. void
  2913. MendozaBossGameObjClass::STATE_IMPL_END(MOVE_STATE_ATTACK_PATTERN1) (void)
  2914. {
  2915. //
  2916. // Simply stop any action
  2917. //
  2918. Get_Action ()->Reset (100);
  2919. return ;
  2920. }
  2921. ///////////////////////////////////////////////////////////////////////////
  2922. //
  2923. // STATE_IMPL_THINK(MOVE_STATE_ATTACK_PATTERN1)
  2924. //
  2925. ///////////////////////////////////////////////////////////////////////////
  2926. void
  2927. MendozaBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_ATTACK_PATTERN1) (void)
  2928. {
  2929. //
  2930. // Make sure we are always facing the player...
  2931. //
  2932. Vector3 target_pos = StarPos;
  2933. target_pos.Z += 1.0F;
  2934. Set_Targeting (target_pos, true);
  2935. //
  2936. // Is it time to move somewhere else?
  2937. //
  2938. MoveStateTimer -= TimeManager::Get_Frame_Seconds ();
  2939. if (MoveStateTimer <= 0) {
  2940. MoveStateTimer = WWMath::Random_Float (1.0F, 7.0F);
  2941. if (StarPos.X > -70.0F) {
  2942. //
  2943. // Simply find a random spot next to the player to move to...
  2944. //
  2945. Vector3 position;
  2946. if (PathfindClass::Get_Instance ()->Find_Random_Spot (StarPos, 10.0F, &position)) {
  2947. float speed = WWMath::Random_Float (0.25, 1.0F);
  2948. //
  2949. // Move to this random spot, but use a random speed as well
  2950. //
  2951. ActionParamsStruct params;
  2952. params.Set_Basic ((long)0, 100, 777);
  2953. params.Set_Movement (position, speed, 1.0F);
  2954. params.IgnoreFacing = true;
  2955. Get_Action ()->Goto (params);
  2956. }
  2957. } else {
  2958. //
  2959. // If the player goes out of range, then switch to the fireball attack
  2960. //
  2961. OverallState.Set_State (OVERALL_STATE_FIREBALL_ATTACK);
  2962. }
  2963. }
  2964. return ;
  2965. }
  2966. ///////////////////////////////////////////////////////////////////////////
  2967. //
  2968. // STATE_IMPL_BEGIN(MOVE_STATE_ATTACK_PATTERN2)
  2969. //
  2970. ///////////////////////////////////////////////////////////////////////////
  2971. void
  2972. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_ATTACK_PATTERN2) (void)
  2973. {
  2974. MoveStateTimer = 0.0F;
  2975. return ;
  2976. }
  2977. ///////////////////////////////////////////////////////////////////////////
  2978. //
  2979. // STATE_IMPL_END(MOVE_STATE_ATTACK_PATTERN2)
  2980. //
  2981. ///////////////////////////////////////////////////////////////////////////
  2982. void
  2983. MendozaBossGameObjClass::STATE_IMPL_END(MOVE_STATE_ATTACK_PATTERN2) (void)
  2984. {
  2985. //
  2986. // Simply stop any action
  2987. //
  2988. Get_Action ()->Reset (100);
  2989. return ;
  2990. }
  2991. ///////////////////////////////////////////////////////////////////////////
  2992. //
  2993. // STATE_IMPL_THINK(MOVE_STATE_ATTACK_PATTERN2)
  2994. //
  2995. ///////////////////////////////////////////////////////////////////////////
  2996. void
  2997. MendozaBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_ATTACK_PATTERN2) (void)
  2998. {
  2999. //
  3000. // Is it time to move somewhere else?
  3001. //
  3002. MoveStateTimer -= TimeManager::Get_Frame_Seconds ();
  3003. if (MoveStateTimer <= 0) {
  3004. MoveStateTimer = WWMath::Random_Float (1.0F, 5.0F);
  3005. if (StarPos.X > -70.0F) {
  3006. //
  3007. // Simply find a random spot to move to...
  3008. //
  3009. Vector3 position;
  3010. if (PathfindClass::Get_Instance ()->Find_Random_Spot (StarPos, 10.0F, &position)) {
  3011. float speed = WWMath::Random_Float (0.25, 1.0F);
  3012. //
  3013. // Move to this random spot, but use a random speed as well
  3014. //
  3015. ActionParamsStruct params;
  3016. params.Set_Basic ((long)0, 100, 777);
  3017. params.Set_Movement (position, speed, 1.0F);
  3018. params.IgnoreFacing = true;
  3019. Get_Action ()->Goto (params);
  3020. }
  3021. } else {
  3022. //
  3023. // If the player goes out of range, then switch to the fireball attack
  3024. //
  3025. OverallState.Set_State (OVERALL_STATE_FIREBALL_ATTACK);
  3026. }
  3027. }
  3028. return ;
  3029. }
  3030. ///////////////////////////////////////////////////////////////////////////
  3031. //
  3032. // STATE_IMPL_BEGIN(MOVE_STATE_GOTO_HELIPAD)
  3033. //
  3034. ///////////////////////////////////////////////////////////////////////////
  3035. void
  3036. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_GOTO_HELIPAD) (void)
  3037. {
  3038. //
  3039. // Move to the center of the helipad (with all haste)
  3040. //
  3041. ActionParamsStruct params;
  3042. params.Set_Basic ((long)0, 100, 777);
  3043. params.Set_Movement (HELIPAD_CENTER_POS, 1.0F, 0.5F);
  3044. Get_Action ()->Goto (params);
  3045. return ;
  3046. }
  3047. ///////////////////////////////////////////////////////////////////////////
  3048. //
  3049. // STATE_IMPL_END(MOVE_STATE_GOTO_HELIPAD)
  3050. //
  3051. ///////////////////////////////////////////////////////////////////////////
  3052. void
  3053. MendozaBossGameObjClass::STATE_IMPL_END(MOVE_STATE_GOTO_HELIPAD) (void)
  3054. {
  3055. //
  3056. // Simply stop any action
  3057. //
  3058. Get_Action ()->Reset (100);
  3059. return ;
  3060. }
  3061. ///////////////////////////////////////////////////////////////////////////
  3062. //
  3063. // STATE_IMPL_THINK(MOVE_STATE_GOTO_HELIPAD)
  3064. //
  3065. ///////////////////////////////////////////////////////////////////////////
  3066. void
  3067. MendozaBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_GOTO_HELIPAD) (void)
  3068. {
  3069. float dist2 = (MendozaPos - HELIPAD_CENTER_POS).Length2 ();
  3070. //
  3071. // If we've gotten there, then start attacking...
  3072. //
  3073. if (dist2 <= 1.0F) {
  3074. AttackState.Set_State (ATTACK_STATE_FIREBALL, true);
  3075. MoveState.Set_State (MOVE_STATE_STOP);
  3076. }
  3077. return ;
  3078. }
  3079. ///////////////////////////////////////////////////////////////////////////
  3080. //
  3081. // STATE_IMPL_BEGIN(MOVE_STATE_RUN_TO_HEALTH)
  3082. //
  3083. ///////////////////////////////////////////////////////////////////////////
  3084. void
  3085. MendozaBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_RUN_TO_HEALTH) (void)
  3086. {
  3087. //
  3088. // First, find the "best" health powerup in the region...
  3089. //
  3090. PowerUpGameObj *powerup = Find_Best_Powerup ();
  3091. if (powerup != NULL) {
  3092. //
  3093. // Get the position of the powerup
  3094. //
  3095. Vector3 position;
  3096. powerup->Get_Position (&position);
  3097. //
  3098. // Now, move to the spot where the powerup is (at all haste)
  3099. //
  3100. ActionParamsStruct params;
  3101. params.Set_Basic ((long)0, 100, 777);
  3102. params.Set_Movement (position, 1.0F, 0.125F);
  3103. Get_Action ()->Goto (params);
  3104. }
  3105. return ;
  3106. }
  3107. ///////////////////////////////////////////////////////////////////////////
  3108. //
  3109. // STATE_IMPL_END(MOVE_STATE_RUN_TO_HEALTH)
  3110. //
  3111. ///////////////////////////////////////////////////////////////////////////
  3112. void
  3113. MendozaBossGameObjClass::STATE_IMPL_END(MOVE_STATE_RUN_TO_HEALTH) (void)
  3114. {
  3115. //
  3116. // Simply stop any action
  3117. //
  3118. Get_Action ()->Reset (100);
  3119. return ;
  3120. }
  3121. ///////////////////////////////////////////////////////////////////////////
  3122. //
  3123. // Find_Best_Powerup
  3124. //
  3125. ///////////////////////////////////////////////////////////////////////////
  3126. PowerUpGameObj *
  3127. MendozaBossGameObjClass::Find_Best_Powerup (void)
  3128. {
  3129. if (COMBAT_STAR == NULL) {
  3130. return NULL;
  3131. }
  3132. PowerUpGameObj *best_powerup = NULL;
  3133. float best_powerup_rating = 100.0F;
  3134. //
  3135. // Loop over all the game objects in the world (looking for powerups)
  3136. //
  3137. SLNode<BaseGameObj> *obj_node = NULL;
  3138. for (obj_node = GameObjManager::Get_Game_Obj_List ()->Head (); obj_node; obj_node = obj_node->Next ()) {
  3139. //
  3140. // Is this a powerup?
  3141. //
  3142. PhysicalGameObj *phys_game_obj = obj_node->Data ()->As_PhysicalGameObj ();
  3143. if (phys_game_obj != NULL && phys_game_obj->As_PowerUpGameObj () != NULL) {
  3144. PowerUpGameObj *powerup = phys_game_obj->As_PowerUpGameObj ();
  3145. if (powerup != NULL) {
  3146. //
  3147. // Get the position of the powerup
  3148. //
  3149. Vector3 powerup_pos;
  3150. powerup->Get_Position (&powerup_pos);
  3151. //
  3152. // Is this powerup in the boss area?
  3153. //
  3154. if ( BOSS_AREA_BOX01.Contains (powerup_pos) ||
  3155. BOSS_AREA_BOX02.Contains (powerup_pos) ||
  3156. BOSS_AREA_BOX03.Contains (powerup_pos))
  3157. {
  3158. powerup_pos.Z = 0;
  3159. //
  3160. // Calculate how far this powerup is from Mendoza and the player
  3161. //
  3162. float dist_to_me = (powerup_pos - MendozaPos).Length () / 10.0F;
  3163. float dist_to_star = (powerup_pos - StarPos).Length () / 10.0F;
  3164. dist_to_star = WWMath::Clamp (1.0F - dist_to_star, 0.0F, 1.0F);
  3165. //
  3166. // Is this the powerup that's closest to Mendoza and farthest from the player?
  3167. //
  3168. float rating = (dist_to_me * 0.5F) + (dist_to_star * 0.5F);
  3169. if (rating < best_powerup_rating) {
  3170. best_powerup = powerup;
  3171. best_powerup_rating = rating;
  3172. }
  3173. }
  3174. }
  3175. }
  3176. }
  3177. return best_powerup;
  3178. }
  3179. ///////////////////////////////////////////////////////////////////////////
  3180. //
  3181. // STATE_IMPL_BEGIN(HEAD_STATE_NONE)
  3182. //
  3183. ///////////////////////////////////////////////////////////////////////////
  3184. void
  3185. MendozaBossGameObjClass::STATE_IMPL_BEGIN(HEAD_STATE_NONE) (void)
  3186. {
  3187. Cancel_Look_At ();
  3188. return ;
  3189. }
  3190. ///////////////////////////////////////////////////////////////////////////
  3191. //
  3192. // STATE_IMPL_THINK(HEAD_STATE_LOOKING_AT_STAR)
  3193. //
  3194. ///////////////////////////////////////////////////////////////////////////
  3195. void
  3196. MendozaBossGameObjClass::STATE_IMPL_THINK(HEAD_STATE_LOOKING_AT_STAR) (void)
  3197. {
  3198. //
  3199. // Look at the star's head
  3200. //
  3201. Vector3 position (StarPos);
  3202. position.Z += 1.7F;
  3203. if (Is_Looking () == false) {
  3204. Look_At (position, 100);
  3205. } else {
  3206. Update_Look_At (position);
  3207. }
  3208. return ;
  3209. }
  3210. ///////////////////////////////////////////////////////////////////////////
  3211. //
  3212. // STATE_IMPL_THINK(HEAD_STATE_LOOKING_AT_SYDNEY)
  3213. //
  3214. ///////////////////////////////////////////////////////////////////////////
  3215. void
  3216. MendozaBossGameObjClass::STATE_IMPL_THINK(HEAD_STATE_LOOKING_AT_SYDNEY) (void)
  3217. {
  3218. Vector3 syd_pos;
  3219. Sydney.Get_Ptr ()->Get_Position (&syd_pos);
  3220. //
  3221. // Look at the Sydney's head
  3222. //
  3223. syd_pos.Z += 1.7F;
  3224. if (Is_Looking () == false) {
  3225. Look_At (syd_pos, 100);
  3226. } else {
  3227. Update_Look_At (syd_pos);
  3228. }
  3229. return ;
  3230. }
  3231. ///////////////////////////////////////////////////////////////////////////
  3232. //
  3233. // Spawn_Health_Powerups
  3234. //
  3235. ///////////////////////////////////////////////////////////////////////////
  3236. void
  3237. MendozaBossGameObjClass::Spawn_Health_Powerups (void)
  3238. {
  3239. const int POWERUP_COUNT = 15;
  3240. //
  3241. // Create some health powerups
  3242. //
  3243. for (int index = 0; index < POWERUP_COUNT; index ++) {
  3244. //
  3245. // Pick a random part of the level to create the powerup in...
  3246. //
  3247. const AABoxClass *area_box = NULL;
  3248. int area_id = FreeRandom.Get_Int (3);
  3249. if (area_id == 0) {
  3250. area_box = &BOSS_AREA_BOX01;
  3251. } else if (area_id == 1) {
  3252. area_box = &BOSS_AREA_BOX02;
  3253. } else {
  3254. area_box = &BOSS_AREA_BOX03;
  3255. }
  3256. //
  3257. // Pick a random spot in this area
  3258. //
  3259. Vector3 rand_pos;
  3260. rand_pos.X = area_box->Center.X + WWMath::Random_Float (-area_box->Extent.X * 0.95F, area_box->Extent.X * 0.95F);
  3261. rand_pos.Y = area_box->Center.Y + WWMath::Random_Float (-area_box->Extent.Y * 0.95F, area_box->Extent.Y * 0.95F);
  3262. rand_pos.Z = area_box->Center.Z;
  3263. //
  3264. // Ensure this is a valid spot to walk
  3265. //
  3266. if (PathfindClass::Get_Instance ()->Find_Random_Spot (rand_pos, 1.0F, &rand_pos)) {
  3267. //
  3268. // Build a ray-test to determine at what height to position the powerup
  3269. //
  3270. rand_pos.Z += 10.0F;
  3271. Vector3 delta (0, 0, -20.0F);
  3272. Vector3 end_pos = rand_pos + delta;
  3273. LineSegClass ray_cast (rand_pos, end_pos);
  3274. CastResultStruct result;
  3275. PhysRayCollisionTestClass ray_test (ray_cast, &result, TERRAIN_ONLY_COLLISION_GROUP, COLLISION_TYPE_PHYSICAL);
  3276. COMBAT_SCENE->Cast_Ray (ray_test);
  3277. //
  3278. // Calculate the powerup's new position
  3279. //
  3280. Vector3 powerup_pos = rand_pos + (delta * (result.Fraction * 0.99F));
  3281. //
  3282. // Create and position the object
  3283. //
  3284. PhysicalGameObj *powerup = ObjectLibraryManager::Create_Object ("POW_Health_025");
  3285. if (powerup != NULL) {
  3286. powerup->Start_Observers ();
  3287. powerup->Set_Position (powerup_pos);
  3288. }
  3289. }
  3290. }
  3291. return ;
  3292. }