raveshawbossgameobj.cpp 119 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555
  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/raveshawbossgameobj.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/20/02 4:40p $*
  29. * *
  30. * $Revision:: 14 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "raveshawbossgameobj.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. #include "stealtheffect.h"
  76. #include "damageablestaticphys.h"
  77. #include "boxrobj.h"
  78. DECLARE_FORCE_LINK (RaveshawBoss)
  79. //////////////////////////////////////////////////////////////////////////
  80. // ManualTransitionEffectClass
  81. //////////////////////////////////////////////////////////////////////////
  82. class ManualTransitionEffectClass : public TransitionEffectClass
  83. {
  84. public:
  85. ///////////////////////////////////////////////////////////////////
  86. // Public constructors/destructors
  87. ///////////////////////////////////////////////////////////////////
  88. ManualTransitionEffectClass (void)
  89. {
  90. RenderBaseMaterial = true;
  91. RenderTransitionMaterial = true;
  92. IntensityScale = 0;
  93. RemoveOnComplete = false;
  94. return ;
  95. }
  96. ///////////////////////////////////////////////////////////////////
  97. // Public methods
  98. ///////////////////////////////////////////////////////////////////
  99. //
  100. // Inherited
  101. //
  102. void Timestep (float dt)
  103. {
  104. //
  105. // Stolen from base class
  106. //
  107. Vector2 uv_rate = MinUVRate + IntensityScale * IntensityScale * (MaxUVRate - MinUVRate);
  108. UVOffset += uv_rate * dt;
  109. UVOffset.X = fmod(UVOffset.X , 2.0f);
  110. UVOffset.Y = fmod(UVOffset.Y , 2.0f);
  111. return ;
  112. }
  113. //
  114. // Manual control
  115. //
  116. void Enable_Effect (bool onoff) { RenderTransitionMaterial = onoff; }
  117. bool Is_Effect_Enabled (void) const { return RenderTransitionMaterial; }
  118. void Set_Intensity (float value) { IntensityScale = value; }
  119. float Get_Intensity (void) const { return IntensityScale; }
  120. };
  121. //////////////////////////////////////////////////////////////////////////
  122. // Constants
  123. //////////////////////////////////////////////////////////////////////////
  124. static const float UNINITIALIZED_TIMER = -5000.0F;
  125. static const Vector3 TIBERIUM_POS (-130.499F, 483.243F, -189.617F);
  126. static const float TIBERIUM_RADIUS = 1.35F;
  127. static const float SAFE_JUMP_RADIUS = 12.0F;
  128. static const float CAMERA_RADIUS = 10.0F;
  129. static const float HEAL_TIME = 3.0F;
  130. static const float EFFECT_FADE_TIME = 12.0F;
  131. static const float EFFECT_INTENSITY = 0.75F;
  132. static const char *ARC_BONE_NAMES[6] =
  133. {
  134. "BONE02",
  135. "BONE03",
  136. "BONE04",
  137. "BONE05",
  138. "BONE06",
  139. "BONE07",
  140. };
  141. //////////////////////////////////////////////////////////////////////////
  142. // Waypath IDs
  143. //////////////////////////////////////////////////////////////////////////
  144. static const int CATWALK_WAYPATH_ID = 3000100;
  145. //////////////////////////////////////////////////////////////////////////
  146. // Weapon and state enumerations
  147. //////////////////////////////////////////////////////////////////////////
  148. //////////////////////////////////////////////////////////////////////////
  149. // Taunt constants
  150. //////////////////////////////////////////////////////////////////////////
  151. static const char *TAUNT_IDS[6] =
  152. {
  153. "IDS_SAKURA_BOSS_TAUNT1",
  154. "IDS_SAKURA_BOSS_TAUNT2",
  155. "IDS_SAKURA_BOSS_TAUNT3",
  156. "IDS_SAKURA_BOSS_TAUNT4",
  157. "IDS_SAKURA_BOSS_TAUNT5",
  158. "IDS_SAKURA_BOSS_TAUNT6"
  159. };
  160. //////////////////////////////////////////////////////////////////////////
  161. // Save/load constants
  162. //////////////////////////////////////////////////////////////////////////
  163. enum
  164. {
  165. CHUNKID_DEF_PARENT = 0x09230242,
  166. CHUNKID_DEF_VARIABLES,
  167. VARID_DEF_GATLING_DEF_ID = 1,
  168. VARID_DEF_ROCKET_DEF_ID,
  169. VARID_DEF_GATLING_REV_SOUND_ID,
  170. VARID_DEF_ROCKET_DOOR_SOUND_ID,
  171. VARID_DEF_ROCKET_DESTROYED_EXPLOSION_ID
  172. };
  173. enum
  174. {
  175. CHUNKID_PARENT = 0x09230243,
  176. CHUNKID_VARIABLES,
  177. CHUNKID_TIBERIUM_EFFECT,
  178. CHUNKID_OVERALL_STATE_MACHINE,
  179. CHUNKID_RAVESHAW_STATE_MACHINE,
  180. CHUNKID_ENGORGED_STATE_MACHINE,
  181. CHUNKID_MOVE_STATE_MACHINE,
  182. CHUNKID_STEALTH_SOLDIER_STATE_MACHINE,
  183. CHUNKID_THROWN_OBJ_STATE_MACHINE,
  184. CHUNKID_JUMP_STATE_MACHINE,
  185. CHUNKID_LIGHTNING_ROD_STATE_MACHINE,
  186. CHUNKID_STEALTH_SOLDIER,
  187. CHUNKID_HAVOC_STATE_MACHINE,
  188. XXX_VARID_STEALTH_SOLIDER_PTR = 0,
  189. VARID_THROWN_OBJECT_PTR,
  190. VARID_IS_TIBERIUM_EFFECT_APPLIED,
  191. VARID_CURRENT_DEST_POS,
  192. VARID_OVERALL_STATE_TIMER,
  193. VARID_ENGORGED_STATE_TIMER,
  194. VARID_MOVE_STATE_TIMER,
  195. VARID_BODY_SLAM_TIMER,
  196. VARID_RAVESHAW_STATE_TIMER,
  197. VARID_STEALTHSOLDIER_STATE_TIMER,
  198. VARID_LIGHTNINGROD_STATE_TIMER,
  199. VARID_START_TIMER,
  200. VARID_LAST_MELEE_ANIM_FRAME,
  201. VARID_HAS_MELEE_ATTACK_HIT,
  202. VARID_FLYING_OBJECT_VECTOR,
  203. VARID_FLYING_OBJECT_DEST,
  204. VARID_FLYING_DIST,
  205. VARID_RELOBJ_TM,
  206. VARID_ARC_OBJ_PTR,
  207. VARID_CURR_JUMP_POS,
  208. VARID_CAMERA_BONE_PTR,
  209. VARID_CAMERA_BONE_TM,
  210. VARID_RESTORE_FIRST_PERSON,
  211. };
  212. //////////////////////////////////////////////////////////////////////////
  213. // Factories
  214. //////////////////////////////////////////////////////////////////////////
  215. SimplePersistFactoryClass<RaveshawBossGameObjDefClass, CHUNKID_GAME_OBJECT_DEF_RAVESHAW_BOSS> _RaveshawBossGameObjDefPersistFactory;
  216. SimplePersistFactoryClass<RaveshawBossGameObjClass, CHUNKID_GAME_OBJECT_RAVESHAW_BOSS> _RaveshawBossGameObjPersistFactory;
  217. DECLARE_DEFINITION_FACTORY(RaveshawBossGameObjDefClass, CLASSID_GAME_OBJECT_DEF_RAVESHAW_BOSS, "Raveshaw Boss") _RaveshawBossGameObjDefDefFactory;
  218. //////////////////////////////////////////////////////////////////////////
  219. //
  220. // RaveshawBossGameObjDefClass
  221. //
  222. //////////////////////////////////////////////////////////////////////////
  223. RaveshawBossGameObjDefClass::RaveshawBossGameObjDefClass (void)
  224. {
  225. UseInnateBehavior = false;
  226. PARAM_SEPARATOR (RaveshawBossGameObjDefClass, "Boss Settings");
  227. PARAM_SEPARATOR (RaveshawBossGameObjDefClass, "");
  228. return ;
  229. }
  230. //////////////////////////////////////////////////////////////////////////
  231. //
  232. // ~RaveshawBossGameObjDefClass
  233. //
  234. //////////////////////////////////////////////////////////////////////////
  235. RaveshawBossGameObjDefClass::~RaveshawBossGameObjDefClass (void)
  236. {
  237. return ;
  238. }
  239. //////////////////////////////////////////////////////////////////////////
  240. //
  241. // Get_Class_ID
  242. //
  243. //////////////////////////////////////////////////////////////////////////
  244. uint32
  245. RaveshawBossGameObjDefClass::Get_Class_ID (void) const
  246. {
  247. return CLASSID_GAME_OBJECT_DEF_RAVESHAW_BOSS;
  248. }
  249. //////////////////////////////////////////////////////////////////////////
  250. //
  251. // Create
  252. //
  253. //////////////////////////////////////////////////////////////////////////
  254. PersistClass *
  255. RaveshawBossGameObjDefClass::Create (void) const
  256. {
  257. RaveshawBossGameObjClass *obj = new RaveshawBossGameObjClass;
  258. obj->Init(*this);
  259. return obj;
  260. }
  261. //////////////////////////////////////////////////////////////////////////
  262. //
  263. // Save
  264. //
  265. //////////////////////////////////////////////////////////////////////////
  266. bool
  267. RaveshawBossGameObjDefClass::Save (ChunkSaveClass &csave)
  268. {
  269. csave.Begin_Chunk (CHUNKID_DEF_PARENT);
  270. SoldierGameObjDef::Save (csave);
  271. csave.End_Chunk ();
  272. csave.Begin_Chunk (CHUNKID_DEF_VARIABLES);
  273. Save_Variables (csave);
  274. csave.End_Chunk();
  275. return true;
  276. }
  277. //////////////////////////////////////////////////////////////////////////
  278. //
  279. // Load
  280. //
  281. //////////////////////////////////////////////////////////////////////////
  282. bool
  283. RaveshawBossGameObjDefClass::Load (ChunkLoadClass &cload)
  284. {
  285. while (cload.Open_Chunk ()) {
  286. switch(cload.Cur_Chunk_ID ()) {
  287. case CHUNKID_DEF_PARENT:
  288. SoldierGameObjDef::Load (cload);
  289. break;
  290. case CHUNKID_DEF_VARIABLES:
  291. Load_Variables (cload);
  292. break;
  293. default:
  294. Debug_Say (("Unrecognized RaveshawBossGameObjDefClass chunkID\n"));
  295. break;
  296. }
  297. cload.Close_Chunk ();
  298. }
  299. return true;
  300. }
  301. ///////////////////////////////////////////////////////////////////////////
  302. //
  303. // Save_Variables
  304. //
  305. ///////////////////////////////////////////////////////////////////////////
  306. void
  307. RaveshawBossGameObjDefClass::Save_Variables (ChunkSaveClass &csave)
  308. {
  309. return ;
  310. }
  311. ///////////////////////////////////////////////////////////////////////////
  312. //
  313. // Load_Variables
  314. //
  315. ///////////////////////////////////////////////////////////////////////////
  316. void
  317. RaveshawBossGameObjDefClass::Load_Variables (ChunkLoadClass &cload)
  318. {
  319. /*while (cload.Open_Micro_Chunk ()) {
  320. switch (cload.Cur_Micro_Chunk_ID ()) {
  321. default:
  322. Debug_Say (("Unrecognized RaveshawBossGameObjDefClass Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID ()));
  323. break;
  324. }
  325. cload.Close_Micro_Chunk ();
  326. }*/
  327. return ;
  328. }
  329. ///////////////////////////////////////////////////////////////////////////
  330. //
  331. // Get_Factory
  332. //
  333. ///////////////////////////////////////////////////////////////////////////
  334. const PersistFactoryClass &
  335. RaveshawBossGameObjDefClass::Get_Factory (void) const
  336. {
  337. return _RaveshawBossGameObjDefPersistFactory;
  338. }
  339. /*
  340. **
  341. ** Start of RaveshawBossGameObjClass
  342. **
  343. */
  344. ///////////////////////////////////////////////////////////////////////////
  345. //
  346. // RaveshawBossGameObjClass
  347. //
  348. ///////////////////////////////////////////////////////////////////////////
  349. RaveshawBossGameObjClass::RaveshawBossGameObjClass (void) :
  350. RaveshawTauntTimeLeft (0),
  351. AvailableTaunts (0xFFFFFF),
  352. OverallState (this),
  353. RaveshawState (this),
  354. EngorgedState (this),
  355. MoveState (this),
  356. StealthSoldierState (this),
  357. HavocState (this),
  358. ThrownObjectState (this),
  359. JumpState (this),
  360. LightningRodState (this),
  361. OverallStateTimer (0),
  362. StealthSoldierStateTimer (0),
  363. LightningRodStateTimer (0),
  364. RaveshawStateTimer (0),
  365. EngorgedStateTimer (0),
  366. MoveStateTimer (0),
  367. BodySlamTimer (0),
  368. TiberiumEffect (NULL),
  369. IsTiberiumEffectApplied (false),
  370. StealthSoldier (NULL),
  371. StealthEffect (NULL),
  372. ThrownObject (NULL),
  373. RaveshawPos (0, 0, 0),
  374. StarPos (0, 0, 0),
  375. StartTimer (0),
  376. FlyingDist (0),
  377. FlyingObjectVector (0, 0, 0),
  378. FlyingObjectDest (0, 0, 0),
  379. LastMeleeAnimFrame (0),
  380. HasMeleeAttackHit (false),
  381. CameraBoneModel (NULL),
  382. RestoreFirstPerson (true)
  383. {
  384. Shuffle_Taunt_List ();
  385. TauntList[0] = 1;//IDS_SAKURA_BOSS_TAUNT1;
  386. TauntList[1] = 2;//IDS_SAKURA_BOSS_TAUNT2;
  387. TauntList[2] = 3;//IDS_SAKURA_BOSS_TAUNT3;
  388. TauntList[3] = 4;//IDS_SAKURA_BOSS_TAUNT4;
  389. TauntList[4] = 5;//IDS_SAKURA_BOSS_TAUNT5;
  390. TauntList[5] = 6;//IDS_SAKURA_BOSS_TAUNT6;
  391. ::memset (ArcObjects, 0, sizeof (ArcObjects));
  392. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  393. ArcLifeRemaining[index] = 0;
  394. }
  395. //
  396. // Register the Overall states with its state machine
  397. //
  398. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_NOTHING);
  399. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_HEALING);
  400. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_THROWING_OBJECT);
  401. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_THROWING_SOLDIER);
  402. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_THROWING_STAR);
  403. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_GRAB_STAR);
  404. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_JUMP_TO_CATWALK);
  405. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_ON_CATWALK);
  406. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_BODYSLAM);
  407. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_CHASE_STAR);
  408. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_DAZED);
  409. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_FLEE);
  410. ADD_STATE_TO_MACHINE (OverallState, OVERALL_STATE_DEATH_SEQUENCE);
  411. //
  412. // Register the Raveshaw states with its state machine
  413. //
  414. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_NOTHING);
  415. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_ROAR);
  416. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_GRAB_TIBERIUM);
  417. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_GRAB_SOLDIER);
  418. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_THROW_SOLDIER);
  419. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_GRAB_OBJECT);
  420. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_THROW_OBJECT);
  421. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_GRAB_STAR);
  422. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_BODYSLAM);
  423. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_JUMP_DOWN);
  424. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_STUMBLE);
  425. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_LOOK_CONFUSED);
  426. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_DYING);
  427. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_FALL);
  428. ADD_STATE_TO_MACHINE (RaveshawState, RAVESHAW_STATE_DEATH_LANDING);
  429. //
  430. // Register the Move states with its state machine
  431. //
  432. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_STOP);
  433. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_GOTO_TIBERIUM);
  434. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_GOTO_CATWALK);
  435. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_JUMP_TO_CATWALK);
  436. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_CIRCLE_CATWALK);
  437. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_GOTO_THROW_OBJECT);
  438. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_JUMP_TO_STAR);
  439. ADD_STATE_TO_MACHINE (MoveState, MOVE_STATE_FOLLOW_STAR);
  440. //
  441. // Register the Engorged states with its state machine
  442. //
  443. ADD_STATE_TO_MACHINE (EngorgedState, ENGORGED_STATE_NONE);
  444. ADD_STATE_TO_MACHINE (EngorgedState, ENGORGED_STATE_ABSORBING_TIBERIUM);
  445. ADD_STATE_TO_MACHINE (EngorgedState, ENGORGED_STATE_FADING);
  446. //
  447. // Register the Jump states with its state machine
  448. //
  449. ADD_STATE_TO_MACHINE (JumpState, JUMP_STATE_NONE);
  450. ADD_STATE_TO_MACHINE (JumpState, JUMP_STATE_CROUCHING);
  451. ADD_STATE_TO_MACHINE (JumpState, JUMP_STATE_JUMPING);
  452. ADD_STATE_TO_MACHINE (JumpState, JUMP_STATE_LANDING);
  453. JumpState.Set_State (JUMP_STATE_NONE);
  454. //
  455. // Register the Stealth Soldier states with its state machine
  456. //
  457. ADD_STATE_TO_MACHINE (StealthSoldierState, STEALTH_SOLDIER_STATE_NONE);
  458. ADD_STATE_TO_MACHINE (StealthSoldierState, STEALTH_SOLDIER_STATE_DISPLAY);
  459. ADD_STATE_TO_MACHINE (StealthSoldierState, STEALTH_SOLDIER_STATE_FLYING);
  460. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  461. //
  462. // Register the Stealth Soldier states with its state machine
  463. //
  464. ADD_STATE_TO_MACHINE (HavocState, HAVOC_STATE_NONE);
  465. ADD_STATE_TO_MACHINE (HavocState, HAVOC_STATE_GRABBED);
  466. ADD_STATE_TO_MACHINE (HavocState, HAVOC_STATE_FLYING);
  467. HavocState.Set_State (HAVOC_STATE_NONE);
  468. //
  469. // Register the Thrown object states with its state machine
  470. //
  471. ADD_STATE_TO_MACHINE (ThrownObjectState, THROWN_OBJECT_STATE_NONE);
  472. ADD_STATE_TO_MACHINE (ThrownObjectState, THROWN_OBJECT_STATE_PICKUP);
  473. ADD_STATE_TO_MACHINE (ThrownObjectState, THROWN_OBJECT_STATE_FLYING);
  474. ThrownObjectState.Set_State (THROWN_OBJECT_STATE_NONE);
  475. //
  476. // Register the Lightning Rod states with its state machine
  477. //
  478. ADD_STATE_TO_MACHINE (LightningRodState, LIGHTNING_ROD_STATE_NONE);
  479. ADD_STATE_TO_MACHINE (LightningRodState, LIGHTNING_ROD_STATE_ACTIVE);
  480. LightningRodState.Set_State (LIGHTNING_ROD_STATE_NONE);
  481. //
  482. // Allocate a new stealth effect to use...
  483. //
  484. StealthEffect = NEW_REF (StealthEffectClass, ());
  485. //
  486. // Allocate a new tiberium effect to use...
  487. //
  488. TiberiumEffect = NEW_REF (ManualTransitionEffectClass, ());
  489. TextureClass *texture = WW3DAssetManager::Get_Instance ()->Get_Texture ("bluetibeffect.tga");
  490. TiberiumEffect->Set_Texture (texture);
  491. REF_PTR_RELEASE (texture);
  492. //
  493. // Create the camera bone model...
  494. //
  495. CameraBoneModel = WW3DAssetManager::Get_Instance ()->Create_Render_Obj ("CAMBONE");
  496. return ;
  497. }
  498. ///////////////////////////////////////////////////////////////////////////
  499. //
  500. // ~RaveshawBossGameObjClass
  501. //
  502. ///////////////////////////////////////////////////////////////////////////
  503. RaveshawBossGameObjClass::~RaveshawBossGameObjClass (void)
  504. {
  505. REF_PTR_RELEASE (TiberiumEffect);
  506. REF_PTR_RELEASE (StealthEffect);
  507. REF_PTR_RELEASE (CameraBoneModel);
  508. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  509. ArcObjects[index] = NULL;
  510. }
  511. return ;
  512. }
  513. ///////////////////////////////////////////////////////////////////////////
  514. //
  515. // Get_Factory
  516. //
  517. ///////////////////////////////////////////////////////////////////////////
  518. const PersistFactoryClass &
  519. RaveshawBossGameObjClass::Get_Factory (void) const
  520. {
  521. return _RaveshawBossGameObjPersistFactory;
  522. }
  523. ////////////////////////////////////////////////////////////////
  524. //
  525. // Init
  526. //
  527. ////////////////////////////////////////////////////////////////
  528. void RaveshawBossGameObjClass::Init (void)
  529. {
  530. Init ( Get_Definition ());
  531. return ;
  532. }
  533. ///////////////////////////////////////////////////////////////////////////
  534. //
  535. // Init
  536. //
  537. ///////////////////////////////////////////////////////////////////////////
  538. void
  539. RaveshawBossGameObjClass::Init (const RaveshawBossGameObjDefClass &definition)
  540. {
  541. SoldierGameObj::Init (definition);
  542. //
  543. // Make Raveshaw big and beefy...
  544. //
  545. Peek_Model ()->Scale (1.5F);
  546. //
  547. // Make a list of the lightning rods in the area
  548. //
  549. Collect_Lightning_Rods ();
  550. Create_Arc_Effects ();
  551. Prepare_Arc_Effect_Data ();
  552. //
  553. // Start fresh...
  554. //
  555. Get_Action ()->Reset (100);
  556. StartTimer = 2.0F;
  557. //
  558. // Determine which state to do...
  559. //
  560. Determine_New_Overall_State ();
  561. Get_Human_State ()->Set_Human_Anim_Override ("Raveshaw Boss Override");
  562. return ;
  563. }
  564. ///////////////////////////////////////////////////////////////////////////
  565. //
  566. // Get_Definition
  567. //
  568. ///////////////////////////////////////////////////////////////////////////
  569. const RaveshawBossGameObjDefClass &
  570. RaveshawBossGameObjClass::Get_Definition (void) const
  571. {
  572. return (const RaveshawBossGameObjDefClass &)BaseGameObj::Get_Definition ();
  573. }
  574. ///////////////////////////////////////////////////////////////////////////
  575. //
  576. // Save
  577. //
  578. ///////////////////////////////////////////////////////////////////////////
  579. bool
  580. RaveshawBossGameObjClass::Save (ChunkSaveClass & csave)
  581. {
  582. csave.Begin_Chunk (CHUNKID_PARENT);
  583. SoldierGameObj::Save (csave);
  584. csave.End_Chunk ();
  585. //
  586. // Save the tiberium effect to its own chunk
  587. //
  588. csave.Begin_Chunk (CHUNKID_STEALTH_SOLDIER);
  589. StealthSoldier.Save (csave);
  590. csave.End_Chunk ();
  591. //
  592. // Save the tiberium effect to its own chunk
  593. //
  594. csave.Begin_Chunk (CHUNKID_TIBERIUM_EFFECT);
  595. TiberiumEffect->Save (csave);
  596. csave.End_Chunk ();
  597. //
  598. // Save the state machines to their own chunk
  599. //
  600. csave.Begin_Chunk (CHUNKID_OVERALL_STATE_MACHINE);
  601. OverallState.Save (csave);
  602. csave.End_Chunk ();
  603. csave.Begin_Chunk (CHUNKID_RAVESHAW_STATE_MACHINE);
  604. RaveshawState.Save (csave);
  605. csave.End_Chunk ();
  606. csave.Begin_Chunk (CHUNKID_ENGORGED_STATE_MACHINE);
  607. EngorgedState.Save (csave);
  608. csave.End_Chunk ();
  609. csave.Begin_Chunk (CHUNKID_MOVE_STATE_MACHINE);
  610. MoveState.Save (csave);
  611. csave.End_Chunk ();
  612. csave.Begin_Chunk (CHUNKID_STEALTH_SOLDIER_STATE_MACHINE);
  613. StealthSoldierState.Save (csave);
  614. csave.End_Chunk ();
  615. csave.Begin_Chunk (CHUNKID_HAVOC_STATE_MACHINE);
  616. HavocState.Save (csave);
  617. csave.End_Chunk ();
  618. csave.Begin_Chunk (CHUNKID_THROWN_OBJ_STATE_MACHINE);
  619. ThrownObjectState.Save (csave);
  620. csave.End_Chunk ();
  621. csave.Begin_Chunk (CHUNKID_JUMP_STATE_MACHINE);
  622. JumpState.Save (csave);
  623. csave.End_Chunk ();
  624. csave.Begin_Chunk (CHUNKID_LIGHTNING_ROD_STATE_MACHINE);
  625. LightningRodState.Save (csave);
  626. csave.End_Chunk ();
  627. //
  628. // Save the variables
  629. //
  630. csave.Begin_Chunk (CHUNKID_VARIABLES);
  631. Save_Variables (csave);
  632. csave.End_Chunk ();
  633. return true;
  634. }
  635. ///////////////////////////////////////////////////////////////////////////
  636. //
  637. // Load
  638. //
  639. ///////////////////////////////////////////////////////////////////////////
  640. bool
  641. RaveshawBossGameObjClass::Load (ChunkLoadClass &cload)
  642. {
  643. while (cload.Open_Chunk ()) {
  644. switch(cload.Cur_Chunk_ID ()) {
  645. case CHUNKID_PARENT:
  646. SoldierGameObj::Load (cload);
  647. break;
  648. case CHUNKID_STEALTH_SOLDIER:
  649. StealthSoldier.Load (cload);
  650. break;
  651. case CHUNKID_TIBERIUM_EFFECT:
  652. TiberiumEffect->Load (cload);
  653. break;
  654. case CHUNKID_OVERALL_STATE_MACHINE:
  655. OverallState.Load (cload);
  656. break;
  657. case CHUNKID_RAVESHAW_STATE_MACHINE:
  658. RaveshawState.Load (cload);
  659. break;
  660. case CHUNKID_ENGORGED_STATE_MACHINE:
  661. EngorgedState.Load (cload);
  662. break;
  663. case CHUNKID_MOVE_STATE_MACHINE:
  664. MoveState.Load (cload);
  665. break;
  666. case CHUNKID_STEALTH_SOLDIER_STATE_MACHINE:
  667. StealthSoldierState.Load (cload);
  668. break;
  669. case CHUNKID_HAVOC_STATE_MACHINE:
  670. HavocState.Load (cload);
  671. break;
  672. case CHUNKID_THROWN_OBJ_STATE_MACHINE:
  673. ThrownObjectState.Load (cload);
  674. break;
  675. case CHUNKID_JUMP_STATE_MACHINE:
  676. JumpState.Load (cload);
  677. break;
  678. case CHUNKID_LIGHTNING_ROD_STATE_MACHINE:
  679. LightningRodState.Load (cload);
  680. break;
  681. case CHUNKID_VARIABLES:
  682. Load_Variables (cload);
  683. break;
  684. default:
  685. Debug_Say (("Unrecognized RaveshawBossGameObjClass chunk ID\n"));
  686. break;
  687. }
  688. cload.Close_Chunk ();
  689. }
  690. SaveLoadSystemClass::Register_Post_Load_Callback (this);
  691. return true;
  692. }
  693. ///////////////////////////////////////////////////////////////////////////
  694. //
  695. // On_Post_Load
  696. //
  697. ///////////////////////////////////////////////////////////////////////////
  698. void
  699. RaveshawBossGameObjClass::On_Post_Load (void)
  700. {
  701. SoldierGameObj::On_Post_Load ();
  702. //
  703. // Make Raveshaw big and beefy...
  704. //
  705. Peek_Model ()->Scale (1.5F);
  706. //
  707. // Make a list of the lightning rods in the area
  708. //
  709. Collect_Lightning_Rods ();
  710. Prepare_Arc_Effect_Data ();
  711. //
  712. // Override the walking animations for this guy
  713. //
  714. Get_Human_State ()->Set_Human_Anim_Override ("Raveshaw Boss Override");
  715. //
  716. // Apply the blue tiberium effect as necessary
  717. //
  718. if (IsTiberiumEffectApplied) {
  719. Peek_Physical_Object ()->Add_Effect_To_Me (TiberiumEffect);
  720. }
  721. return ;
  722. }
  723. ///////////////////////////////////////////////////////////////////////////
  724. //
  725. // Save_Variables
  726. //
  727. ///////////////////////////////////////////////////////////////////////////
  728. void
  729. RaveshawBossGameObjClass::Save_Variables (ChunkSaveClass &csave)
  730. {
  731. //
  732. // Save a pointer for each arc-object
  733. //
  734. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  735. WRITE_MICRO_CHUNK (csave, VARID_ARC_OBJ_PTR, ArcObjects[index]);
  736. }
  737. Matrix3D cam_tm = CameraBoneModel->Get_Transform ();
  738. WRITE_MICRO_CHUNK (csave, VARID_CAMERA_BONE_PTR, CameraBoneModel);
  739. WRITE_MICRO_CHUNK (csave, VARID_CAMERA_BONE_TM, cam_tm);
  740. WRITE_MICRO_CHUNK (csave, VARID_RESTORE_FIRST_PERSON, RestoreFirstPerson);
  741. WRITE_MICRO_CHUNK (csave, VARID_THROWN_OBJECT_PTR, ThrownObject);
  742. WRITE_MICRO_CHUNK (csave, VARID_IS_TIBERIUM_EFFECT_APPLIED, IsTiberiumEffectApplied);
  743. WRITE_MICRO_CHUNK (csave, VARID_CURRENT_DEST_POS, CurrentDestPos);
  744. WRITE_MICRO_CHUNK (csave, VARID_OVERALL_STATE_TIMER, OverallStateTimer);
  745. WRITE_MICRO_CHUNK (csave, VARID_ENGORGED_STATE_TIMER, EngorgedStateTimer);
  746. WRITE_MICRO_CHUNK (csave, VARID_MOVE_STATE_TIMER, MoveStateTimer);
  747. WRITE_MICRO_CHUNK (csave, VARID_BODY_SLAM_TIMER, BodySlamTimer);
  748. WRITE_MICRO_CHUNK (csave, VARID_RAVESHAW_STATE_TIMER, RaveshawStateTimer);
  749. WRITE_MICRO_CHUNK (csave, VARID_STEALTHSOLDIER_STATE_TIMER, StealthSoldierStateTimer);
  750. WRITE_MICRO_CHUNK (csave, VARID_LIGHTNINGROD_STATE_TIMER, LightningRodStateTimer);
  751. WRITE_MICRO_CHUNK (csave, VARID_START_TIMER, StartTimer);
  752. WRITE_MICRO_CHUNK (csave, VARID_LAST_MELEE_ANIM_FRAME, LastMeleeAnimFrame);
  753. WRITE_MICRO_CHUNK (csave, VARID_HAS_MELEE_ATTACK_HIT, HasMeleeAttackHit);
  754. WRITE_MICRO_CHUNK (csave, VARID_FLYING_OBJECT_VECTOR, FlyingObjectVector);
  755. WRITE_MICRO_CHUNK (csave, VARID_FLYING_OBJECT_DEST, FlyingObjectDest);
  756. WRITE_MICRO_CHUNK (csave, VARID_FLYING_DIST, FlyingDist);
  757. WRITE_MICRO_CHUNK (csave, VARID_RELOBJ_TM, RelObjTM);
  758. WRITE_MICRO_CHUNK (csave, VARID_CURR_JUMP_POS, CurrentJumpToPos);
  759. return ;
  760. }
  761. ///////////////////////////////////////////////////////////////////////////
  762. //
  763. // Load_Variables
  764. //
  765. ///////////////////////////////////////////////////////////////////////////
  766. void
  767. RaveshawBossGameObjClass::Load_Variables (ChunkLoadClass &cload)
  768. {
  769. RenderObjClass *old_camera_bone_ptr = NULL;
  770. Matrix3D cam_tm (1);
  771. int arc_obj_index = 0;
  772. while (cload.Open_Micro_Chunk ()) {
  773. switch (cload.Cur_Micro_Chunk_ID ()) {
  774. case VARID_ARC_OBJ_PTR:
  775. LOAD_MICRO_CHUNK (cload, ArcObjects[arc_obj_index++]);
  776. break;
  777. READ_MICRO_CHUNK (cload, VARID_CAMERA_BONE_PTR, old_camera_bone_ptr);
  778. READ_MICRO_CHUNK (cload, VARID_CAMERA_BONE_TM, cam_tm);
  779. READ_MICRO_CHUNK (cload, VARID_RESTORE_FIRST_PERSON, RestoreFirstPerson);
  780. READ_MICRO_CHUNK (cload, VARID_THROWN_OBJECT_PTR, ThrownObject);
  781. READ_MICRO_CHUNK (cload, VARID_IS_TIBERIUM_EFFECT_APPLIED, IsTiberiumEffectApplied);
  782. READ_MICRO_CHUNK (cload, VARID_CURRENT_DEST_POS, CurrentDestPos);
  783. READ_MICRO_CHUNK (cload, VARID_OVERALL_STATE_TIMER, OverallStateTimer);
  784. READ_MICRO_CHUNK (cload, VARID_ENGORGED_STATE_TIMER, EngorgedStateTimer);
  785. READ_MICRO_CHUNK (cload, VARID_MOVE_STATE_TIMER, MoveStateTimer);
  786. READ_MICRO_CHUNK (cload, VARID_BODY_SLAM_TIMER, BodySlamTimer);
  787. READ_MICRO_CHUNK (cload, VARID_RAVESHAW_STATE_TIMER, RaveshawStateTimer);
  788. READ_MICRO_CHUNK (cload, VARID_STEALTHSOLDIER_STATE_TIMER, StealthSoldierStateTimer);
  789. READ_MICRO_CHUNK (cload, VARID_LIGHTNINGROD_STATE_TIMER, LightningRodStateTimer);
  790. READ_MICRO_CHUNK (cload, VARID_START_TIMER, StartTimer);
  791. READ_MICRO_CHUNK (cload, VARID_LAST_MELEE_ANIM_FRAME, LastMeleeAnimFrame);
  792. READ_MICRO_CHUNK (cload, VARID_HAS_MELEE_ATTACK_HIT, HasMeleeAttackHit);
  793. READ_MICRO_CHUNK (cload, VARID_FLYING_OBJECT_VECTOR, FlyingObjectVector);
  794. READ_MICRO_CHUNK (cload, VARID_FLYING_OBJECT_DEST, FlyingObjectDest);
  795. READ_MICRO_CHUNK (cload, VARID_FLYING_DIST, FlyingDist);
  796. READ_MICRO_CHUNK (cload, VARID_RELOBJ_TM, RelObjTM);
  797. READ_MICRO_CHUNK (cload, VARID_CURR_JUMP_POS, CurrentJumpToPos);
  798. default:
  799. Debug_Say (("Unrecognized RaveshawBossGameObjClass Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID ()));
  800. break;
  801. }
  802. cload.Close_Micro_Chunk ();
  803. }
  804. //
  805. // Remap the arc-object pointers
  806. //
  807. for (int index = 0; index < arc_obj_index; index ++) {
  808. REQUEST_POINTER_REMAP ((void **)&ArcObjects[index]);
  809. }
  810. if (ThrownObject != NULL) {
  811. REQUEST_POINTER_REMAP ((void **)&ThrownObject);
  812. }
  813. //
  814. // Register the camera bone pointers...
  815. //
  816. if (old_camera_bone_ptr != NULL) {
  817. SaveLoadSystemClass::Register_Pointer (old_camera_bone_ptr, CameraBoneModel);
  818. CameraBoneModel->Set_Transform (cam_tm);
  819. }
  820. return ;
  821. }
  822. ///////////////////////////////////////////////////////////////////////////
  823. //
  824. // Apply_Control
  825. //
  826. ///////////////////////////////////////////////////////////////////////////
  827. void
  828. RaveshawBossGameObjClass::Apply_Control (void)
  829. {
  830. SoldierGameObj::Apply_Control ();
  831. return ;
  832. }
  833. ///////////////////////////////////////////////////////////////////////////
  834. //
  835. // Think
  836. //
  837. ///////////////////////////////////////////////////////////////////////////
  838. void
  839. RaveshawBossGameObjClass::Think (void)
  840. {
  841. WWPROFILE ("Raveshaw Think");
  842. bool ok_to_think = true;
  843. //
  844. // Don't do this in the editor
  845. //
  846. #ifdef PARAM_EDITING_ON
  847. ok_to_think = false;
  848. #endif
  849. if (COMBAT_STAR == NULL || COMBAT_STAR->Is_Dead () || COMBAT_STAR->Is_Destroyed ()) {
  850. ok_to_think = false;
  851. }
  852. if (ok_to_think) {
  853. Verify_Stealth_Soldier ();
  854. //
  855. // Get the position of both Raveshaw and the star (this information
  856. // is used throughout the AI)
  857. //
  858. Get_Position (&RaveshawPos);
  859. COMBAT_STAR->Get_Position (&StarPos);
  860. //
  861. // Check to see if its OK to kick off the boss logic
  862. //
  863. if (StartTimer > UNINITIALIZED_TIMER) {
  864. StartTimer -= TimeManager::Get_Frame_Seconds ();
  865. if (StartTimer <= 0) {
  866. StartTimer = UNINITIALIZED_TIMER;
  867. OverallState.Set_State (OVERALL_STATE_CHASE_STAR);
  868. }
  869. } else {
  870. //
  871. // Let the state machines think
  872. //
  873. OverallState.Think ();
  874. RaveshawState.Think ();
  875. MoveState.Think ();
  876. EngorgedState.Think ();
  877. StealthSoldierState.Think ();
  878. HavocState.Think ();
  879. ThrownObjectState.Think ();
  880. JumpState.Think ();
  881. LightningRodState.Think ();
  882. }
  883. }
  884. //
  885. // Give Raveshaw 100 extra health points so he doesn't get "killed" due to any
  886. // "special" damage such as fire or electricity
  887. //
  888. float old_health = DefenseObject.Get_Health ();
  889. float old_health_max = DefenseObject.Get_Health_Max ();
  890. old_health += 100.0F;
  891. old_health_max += 100.0F;
  892. DefenseObject.Set_Health_Max (old_health_max);
  893. DefenseObject.Set_Health (old_health);
  894. //
  895. // Let the soldier think
  896. //
  897. SoldierGameObj::Think ();
  898. //
  899. // Restore his health
  900. //
  901. float curr_health = DefenseObject.Get_Health ();
  902. curr_health -= 100.0F;
  903. old_health_max -= 100.0F;
  904. DefenseObject.Set_Health (max (curr_health, 1.0F));
  905. DefenseObject.Set_Health_Max (old_health_max);
  906. return ;
  907. }
  908. ///////////////////////////////////////////////////////////////////////////
  909. //
  910. // Verify_Stealth_Soldier
  911. //
  912. ///////////////////////////////////////////////////////////////////////////
  913. void
  914. RaveshawBossGameObjClass::Verify_Stealth_Soldier (void)
  915. {
  916. if (StealthSoldierState.Get_State () == STEALTH_SOLDIER_STATE_NONE) {
  917. return ;
  918. }
  919. //
  920. // Check to see if the stealth soldier has been destroyed...
  921. //
  922. SoldierGameObj *stealth_soldier = Peek_Stealth_Soldier ();
  923. if ( stealth_soldier != NULL &&
  924. (stealth_soldier->Is_Dead () || stealth_soldier->Is_Destroyed ()))
  925. {
  926. //
  927. // Get rid of the stealth soldier
  928. //
  929. stealth_soldier->Peek_Physical_Object ()->Remove_Effect_From_Me (StealthEffect);
  930. stealth_soldier->Get_Human_State ()->Stop_Scripted_Animation ();
  931. stealth_soldier->Set_Delete_Pending ();
  932. StealthSoldier = NULL;
  933. OverallState.Set_State (OVERALL_STATE_NOTHING);
  934. RaveshawState.Set_State (RAVESHAW_STATE_ROAR);
  935. MoveState.Set_State (MOVE_STATE_STOP);
  936. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  937. Determine_New_Overall_State ();
  938. return ;
  939. }
  940. return ;
  941. }
  942. ///////////////////////////////////////////////////////////////////////////
  943. //
  944. // Shuffle_Taunt_List
  945. //
  946. ///////////////////////////////////////////////////////////////////////////
  947. void
  948. RaveshawBossGameObjClass::Shuffle_Taunt_List (void)
  949. {
  950. ::memset (TauntList, 0, sizeof (TauntList));
  951. //
  952. // Grab an entry from the taunt id list
  953. //
  954. for (int index = 0; index < MAX_TAUNTS; index ++) {
  955. //
  956. // Choose a random list entry to plug this taunt ID into
  957. //
  958. int list_index = 0;
  959. do
  960. {
  961. list_index = FreeRandom.Get_Int (MAX_TAUNTS);
  962. } while (TauntList[list_index] != 0);
  963. //
  964. // Stick this taunt ID into the list
  965. //
  966. TauntList[list_index] = index + 1;
  967. }
  968. return ;
  969. }
  970. ///////////////////////////////////////////////////////////////////////////
  971. //
  972. // Apply_Damage_Extended
  973. //
  974. ///////////////////////////////////////////////////////////////////////////
  975. void
  976. RaveshawBossGameObjClass::Apply_Damage_Extended
  977. (
  978. const OffenseObjectClass & damager,
  979. float scale,
  980. const Vector3 & direction,
  981. const char * collision_box_name
  982. )
  983. {
  984. if ( !CombatManager::I_Am_Server () ||
  985. OverallState.Get_State () == OVERALL_STATE_DEATH_SEQUENCE)
  986. {
  987. return ;
  988. }
  989. //
  990. // Apply the damage
  991. //
  992. DefenseObject.Set_Can_Object_Die (false);
  993. SoldierGameObj::Apply_Damage_Extended (damager, scale, direction, collision_box_name);
  994. //
  995. // Get the boss's current health
  996. //
  997. float curr_health = DefenseObject.Get_Health ();
  998. if (FreeRandom.Get_Int (7) == 1) {
  999. //
  1000. // Play a hurt sound
  1001. //
  1002. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Hurt_Twidder", Get_Transform ());
  1003. }
  1004. //
  1005. // If he's circling the catwalk, and badly damaged, then
  1006. // proceed to his death
  1007. //
  1008. if (MoveState.Get_State () == MOVE_STATE_CIRCLE_CATWALK && curr_health <= 20.0F) {
  1009. if (FreeRandom.Get_Int (5) == 1) {
  1010. OverallState.Set_State (OVERALL_STATE_DEATH_SEQUENCE);
  1011. }
  1012. }
  1013. return ;
  1014. }
  1015. ///////////////////////////////////////////////////////////////////////////
  1016. //
  1017. // Attach_Sound
  1018. //
  1019. ///////////////////////////////////////////////////////////////////////////
  1020. void
  1021. RaveshawBossGameObjClass::Attach_Sound (const char *sound_name, const char *bone_name)
  1022. {
  1023. //
  1024. // Create the sound object from its preset
  1025. //
  1026. AudibleSoundClass *sound = WWAudioClass::Get_Instance ()->Create_Sound (sound_name);
  1027. if (sound != NULL) {
  1028. //
  1029. // Attach the sound to the object
  1030. //
  1031. sound->Attach_To_Object (Peek_Model (), bone_name);
  1032. //
  1033. // Add the sound to the world and release our hold on it
  1034. //
  1035. sound->Add_To_Scene ();
  1036. REF_PTR_RELEASE (sound);
  1037. }
  1038. return ;
  1039. }
  1040. ///////////////////////////////////////////////////////////////////////////
  1041. //
  1042. // STATE_IMPL_BEGIN(OVERALL_STATE_HEALING)
  1043. //
  1044. ///////////////////////////////////////////////////////////////////////////
  1045. void
  1046. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_HEALING) (void)
  1047. {
  1048. //
  1049. // Pull the strings to get the mutant to run to the blue tiberium
  1050. //
  1051. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1052. MoveState.Set_State (MOVE_STATE_GOTO_TIBERIUM);
  1053. return ;
  1054. }
  1055. ///////////////////////////////////////////////////////////////////////////
  1056. //
  1057. // STATE_IMPL_BEGIN(OVERALL_STATE_THROWING_OBJECT)
  1058. //
  1059. ///////////////////////////////////////////////////////////////////////////
  1060. void
  1061. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_THROWING_OBJECT) (void)
  1062. {
  1063. ThrownObject = Find_Object_To_Throw ();
  1064. if (ThrownObject != NULL) {
  1065. //
  1066. // Pull the strings to get the mutant to grab a stealth soldier...
  1067. //
  1068. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1069. MoveState.Set_State (MOVE_STATE_GOTO_THROW_OBJECT);
  1070. } else {
  1071. OverallState.Set_State (OVERALL_STATE_CHASE_STAR);
  1072. }
  1073. return ;
  1074. }
  1075. ///////////////////////////////////////////////////////////////////////////
  1076. //
  1077. // STATE_IMPL_BEGIN(OVERALL_STATE_THROWING_SOLDIER)
  1078. //
  1079. ///////////////////////////////////////////////////////////////////////////
  1080. void
  1081. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_THROWING_SOLDIER) (void)
  1082. {
  1083. //
  1084. // Pull the strings to get the mutant to grab a stealth soldier...
  1085. //
  1086. RaveshawState.Set_State (RAVESHAW_STATE_GRAB_SOLDIER);
  1087. MoveState.Set_State (MOVE_STATE_STOP);
  1088. return ;
  1089. }
  1090. ///////////////////////////////////////////////////////////////////////////
  1091. //
  1092. // STATE_IMPL_BEGIN(OVERALL_STATE_GRAB_STAR)
  1093. //
  1094. ///////////////////////////////////////////////////////////////////////////
  1095. void
  1096. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_GRAB_STAR) (void)
  1097. {
  1098. //
  1099. // Pull the strings to get the mutant to grab the player
  1100. //
  1101. RaveshawState.Set_State (RAVESHAW_STATE_GRAB_STAR);
  1102. MoveState.Set_State (MOVE_STATE_STOP);
  1103. return ;
  1104. }
  1105. ///////////////////////////////////////////////////////////////////////////
  1106. //
  1107. // STATE_IMPL_BEGIN(OVERALL_STATE_CHASE_STAR)
  1108. //
  1109. ///////////////////////////////////////////////////////////////////////////
  1110. void
  1111. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_CHASE_STAR) (void)
  1112. {
  1113. //
  1114. // Pull the strings to get the mutant to run to the blue tiberium
  1115. //
  1116. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1117. MoveState.Set_State (MOVE_STATE_FOLLOW_STAR);
  1118. //
  1119. // Chase the player for a random amount of time
  1120. //
  1121. OverallStateTimer = WWMath::Random_Float (6.0F, 20.0F);
  1122. return ;
  1123. }
  1124. ///////////////////////////////////////////////////////////////////////////
  1125. //
  1126. // STATE_IMPL_THINK(OVERALL_STATE_CHASE_STAR)
  1127. //
  1128. ///////////////////////////////////////////////////////////////////////////
  1129. void
  1130. RaveshawBossGameObjClass::STATE_IMPL_THINK(OVERALL_STATE_CHASE_STAR) (void)
  1131. {
  1132. const float ARMS_REACH = 3.8F;
  1133. //
  1134. // Check to see if Raveshaw is close enough to the player to do some damage.
  1135. //
  1136. float dist2 = (RaveshawPos - StarPos).Length2 ();
  1137. if (dist2 <= ARMS_REACH && JumpState.Get_State () == JUMP_STATE_NONE) {
  1138. //
  1139. // Grab for the star
  1140. //
  1141. OverallState.Set_State (OVERALL_STATE_GRAB_STAR);
  1142. }
  1143. return ;
  1144. }
  1145. ///////////////////////////////////////////////////////////////////////////
  1146. //
  1147. // STATE_IMPL_BEGIN(OVERALL_STATE_JUMP_TO_CATWALK)
  1148. //
  1149. ///////////////////////////////////////////////////////////////////////////
  1150. void
  1151. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_JUMP_TO_CATWALK) (void)
  1152. {
  1153. //
  1154. // Pull the strings to get the mutant to run to a spot where he
  1155. // can jump to the catwalk
  1156. //
  1157. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1158. MoveState.Set_State (MOVE_STATE_GOTO_CATWALK);
  1159. return ;
  1160. }
  1161. ///////////////////////////////////////////////////////////////////////////
  1162. //
  1163. // STATE_IMPL_BEGIN(OVERALL_STATE_ON_CATWALK)
  1164. //
  1165. ///////////////////////////////////////////////////////////////////////////
  1166. void
  1167. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_ON_CATWALK) (void)
  1168. {
  1169. //
  1170. // Get the mutant to run around the catwalk for a bit...
  1171. //
  1172. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1173. MoveState.Set_State (MOVE_STATE_CIRCLE_CATWALK);
  1174. return ;
  1175. }
  1176. ///////////////////////////////////////////////////////////////////////////
  1177. //
  1178. // STATE_IMPL_BEGIN(OVERALL_STATE_BODYSLAM)
  1179. //
  1180. ///////////////////////////////////////////////////////////////////////////
  1181. void
  1182. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_BODYSLAM) (void)
  1183. {
  1184. //
  1185. // Get Raveshaw to do his bodyslam
  1186. //
  1187. RaveshawState.Set_State (RAVESHAW_STATE_BODYSLAM);
  1188. MoveState.Set_State (MOVE_STATE_STOP);
  1189. return ;
  1190. }
  1191. ///////////////////////////////////////////////////////////////////////////
  1192. //
  1193. // STATE_IMPL_BEGIN(OVERALL_STATE_DEATH_SEQUENCE)
  1194. //
  1195. ///////////////////////////////////////////////////////////////////////////
  1196. void
  1197. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(OVERALL_STATE_DEATH_SEQUENCE) (void)
  1198. {
  1199. RaveshawState.Set_State (RAVESHAW_STATE_DYING);
  1200. MoveState.Set_State (MOVE_STATE_STOP);
  1201. return ;
  1202. }
  1203. ///////////////////////////////////////////////////////////////////////////
  1204. //
  1205. // STATE_IMPL_BEGIN(MOVE_STATE_STOP)
  1206. //
  1207. ///////////////////////////////////////////////////////////////////////////
  1208. void
  1209. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_STOP) (void)
  1210. {
  1211. Get_Action ()->Reset (100);
  1212. return ;
  1213. }
  1214. ///////////////////////////////////////////////////////////////////////////
  1215. //
  1216. // STATE_IMPL_BEGIN(MOVE_STATE_GOTO_TIBERIUM)
  1217. //
  1218. ///////////////////////////////////////////////////////////////////////////
  1219. void
  1220. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_GOTO_TIBERIUM) (void)
  1221. {
  1222. //
  1223. // Find the "closest" position around the tiberium for Raveshaw to run to
  1224. //
  1225. Vector3 dir_vector = (RaveshawPos - TIBERIUM_POS);
  1226. dir_vector.Normalize ();
  1227. CurrentDestPos = TIBERIUM_POS + (TIBERIUM_RADIUS * dir_vector);
  1228. //
  1229. // Make the mutant move to that position
  1230. //
  1231. ActionParamsStruct params;
  1232. params.Set_Basic ((long)0, 100, 777);
  1233. params.Set_Movement (CurrentDestPos, 0.6F, 0.5F);
  1234. Get_Action ()->Goto (params);
  1235. return ;
  1236. }
  1237. ///////////////////////////////////////////////////////////////////////////
  1238. //
  1239. // STATE_IMPL_THINK(MOVE_STATE_GOTO_TIBERIUM)
  1240. //
  1241. ///////////////////////////////////////////////////////////////////////////
  1242. void
  1243. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_GOTO_TIBERIUM) (void)
  1244. {
  1245. //
  1246. // Put Raveshaw in the "healing" state
  1247. //
  1248. if (Get_Action ()->Is_Active () == false) {
  1249. RaveshawState.Set_State (RAVESHAW_STATE_GRAB_TIBERIUM);
  1250. MoveState.Set_State (MOVE_STATE_STOP);
  1251. }
  1252. return ;
  1253. }
  1254. ///////////////////////////////////////////////////////////////////////////
  1255. //
  1256. // STATE_IMPL_BEGIN(MOVE_STATE_GOTO_CATWALK)
  1257. //
  1258. ///////////////////////////////////////////////////////////////////////////
  1259. void
  1260. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_GOTO_CATWALK) (void)
  1261. {
  1262. //const float MIN_JUMP_DIST = 4.0F;
  1263. //const float MAX_JUMP_DIST = 10.0F;
  1264. //
  1265. // Find the closest catwlk position to our current position
  1266. //
  1267. Find_Closest_Catwalk_Pos (RaveshawPos, &CurrentJumpToPos);
  1268. //
  1269. // Detemine what the "most" aligned ground position would be...
  1270. //
  1271. Vector3 dir_vector = (CurrentJumpToPos - TIBERIUM_POS);
  1272. dir_vector.Normalize ();
  1273. CurrentDestPos.X = CurrentJumpToPos.X + (dir_vector.X * 8.0F);
  1274. CurrentDestPos.Y = CurrentJumpToPos.Y + (dir_vector.Y * 8.0F);
  1275. CurrentDestPos.Z = TIBERIUM_POS.Z;
  1276. //
  1277. // Make the mutant move into position
  1278. //
  1279. ActionParamsStruct params;
  1280. params.Set_Basic ((long)0, 100, 777);
  1281. params.Set_Movement (CurrentDestPos, 0.6F, 0.5F);
  1282. Get_Action ()->Goto (params);
  1283. return ;
  1284. }
  1285. ///////////////////////////////////////////////////////////////////////////
  1286. //
  1287. // Find_Closest_Catwalk_Pos
  1288. //
  1289. ///////////////////////////////////////////////////////////////////////////
  1290. void
  1291. RaveshawBossGameObjClass::Find_Closest_Catwalk_Pos (const Vector3 &curr_pos, Vector3 *catwalk_pos)
  1292. {
  1293. float best_dist2 = 99999.0F;
  1294. //
  1295. // Get the catwalk waypath
  1296. //
  1297. WaypathClass *waypath = PathfindClass::Get_Instance ()->Find_Waypath (CATWALK_WAYPATH_ID);
  1298. WWASSERT (waypath != NULL);
  1299. //
  1300. // Now find the closest point which is in-between the waypath points
  1301. //
  1302. for (int index = 0; index < waypath->Get_Point_Count (); index ++) {
  1303. //
  1304. // Determine what the current and next waypath points are
  1305. //
  1306. int curr_index = index;
  1307. int next_index = index + 1;
  1308. if (index + 1 >= waypath->Get_Point_Count ()) {
  1309. next_index = 0;
  1310. }
  1311. //
  1312. // Get the position of the current and next waypoint
  1313. //
  1314. Vector3 curr_waypath_pos = waypath->Get_Point (curr_index)->Get_Position ();
  1315. Vector3 next_waypath_pos = waypath->Get_Point (next_index)->Get_Position ();
  1316. //
  1317. // Evaluate this jump to position (is it the closest?)
  1318. //
  1319. Vector3 jump_to_pos = curr_waypath_pos + ((next_waypath_pos - curr_waypath_pos) * 0.5F);
  1320. Vector3 dir_vector = (curr_pos - jump_to_pos);
  1321. dir_vector.Z = 0;
  1322. float dist2 = dir_vector.Length2 ();
  1323. if (dist2 < best_dist2) {
  1324. best_dist2 = dist2;
  1325. (*catwalk_pos) = jump_to_pos;
  1326. }
  1327. }
  1328. return ;
  1329. }
  1330. ///////////////////////////////////////////////////////////////////////////
  1331. //
  1332. // STATE_IMPL_THINK(MOVE_STATE_GOTO_CATWALK)
  1333. //
  1334. ///////////////////////////////////////////////////////////////////////////
  1335. void
  1336. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_GOTO_CATWALK) (void)
  1337. {
  1338. //
  1339. // Face the tiberium as necessary
  1340. //
  1341. float dist2 = (RaveshawPos - CurrentDestPos).Length2 ();
  1342. if (dist2 < 4.0F) {
  1343. Get_Action ()->Get_Parameters ().IgnoreFacing = true;
  1344. Set_Targeting (TIBERIUM_POS);
  1345. }
  1346. //
  1347. // Put Raveshaw in the jump to position stage
  1348. //
  1349. if (Get_Action ()->Is_Active () == false) {
  1350. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1351. MoveState.Set_State (MOVE_STATE_JUMP_TO_CATWALK);
  1352. }
  1353. return ;
  1354. }
  1355. ///////////////////////////////////////////////////////////////////////////
  1356. //
  1357. // STATE_IMPL_BEGIN(MOVE_STATE_JUMP_TO_CATWALK)
  1358. //
  1359. ///////////////////////////////////////////////////////////////////////////
  1360. void
  1361. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_JUMP_TO_CATWALK) (void)
  1362. {
  1363. //
  1364. // Simply cause the physics to jump to the specified point
  1365. //
  1366. Jump_To_Point (CurrentJumpToPos);
  1367. return ;
  1368. }
  1369. ///////////////////////////////////////////////////////////////////////////
  1370. //
  1371. // STATE_IMPL_THINK(MOVE_STATE_JUMP_TO_CATWALK)
  1372. //
  1373. ///////////////////////////////////////////////////////////////////////////
  1374. void
  1375. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_JUMP_TO_CATWALK) (void)
  1376. {
  1377. //
  1378. // The state ends when the mutant lands
  1379. //
  1380. if (JumpState.Get_State () == JUMP_STATE_NONE) {
  1381. OverallState.Set_State (OVERALL_STATE_ON_CATWALK);
  1382. }
  1383. Set_Targeting (TIBERIUM_POS);
  1384. return ;
  1385. }
  1386. ///////////////////////////////////////////////////////////////////////////
  1387. //
  1388. // STATE_IMPL_BEGIN(MOVE_STATE_CIRCLE_CATWALK)
  1389. //
  1390. ///////////////////////////////////////////////////////////////////////////
  1391. void
  1392. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_CIRCLE_CATWALK) (void)
  1393. {
  1394. MoveStateTimer = 0.0F;
  1395. BodySlamTimer = WWMath::Random_Float (1.0F, 5.0F);
  1396. return ;
  1397. }
  1398. ///////////////////////////////////////////////////////////////////////////
  1399. //
  1400. // STATE_IMPL_THINK(MOVE_STATE_CIRCLE_CATWALK)
  1401. //
  1402. ///////////////////////////////////////////////////////////////////////////
  1403. void
  1404. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_CIRCLE_CATWALK) (void)
  1405. {
  1406. //
  1407. // Always try to face the star
  1408. //
  1409. Set_Targeting (StarPos);
  1410. //
  1411. // Calculate Raveshaw's remaining health
  1412. //
  1413. float health = DefenseObject.Get_Health ();
  1414. float health_percent = health / DefenseObject.Get_Health_Max ();
  1415. //
  1416. // Is it time to bodyslam?
  1417. //
  1418. BodySlamTimer -= TimeManager::Get_Frame_Seconds ();
  1419. if (health_percent > 0.05F && BodySlamTimer <= 0) {
  1420. OverallState.Set_State (OVERALL_STATE_BODYSLAM);
  1421. } else {
  1422. //
  1423. // Is it time to choose a new spot on the catwalk?
  1424. //
  1425. MoveStateTimer -= TimeManager::Get_Frame_Seconds ();
  1426. if (MoveStateTimer <= 0) {
  1427. MoveStateTimer = 0.5F;
  1428. //
  1429. // Find the closest catwalk position to our current position
  1430. //
  1431. Find_Closest_Catwalk_Pos (StarPos, &CurrentDestPos);
  1432. //
  1433. // Now, simply make the mutant move to this position
  1434. //
  1435. ActionParamsStruct params;
  1436. params.Set_Basic ((long)0, 100, 777);
  1437. params.Set_Movement (CurrentDestPos, 0.5F, 0.5F);
  1438. params.IgnoreFacing = true;
  1439. Get_Action ()->Goto (params);
  1440. }
  1441. }
  1442. return ;
  1443. }
  1444. ///////////////////////////////////////////////////////////////////////////
  1445. //
  1446. // STATE_IMPL_BEGIN(MOVE_STATE_GOTO_THROW_OBJECT)
  1447. //
  1448. ///////////////////////////////////////////////////////////////////////////
  1449. void
  1450. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_GOTO_THROW_OBJECT) (void)
  1451. {
  1452. //
  1453. // Walk to the position of the throw object
  1454. //
  1455. ActionParamsStruct params;
  1456. params.Set_Basic ((long)0, 100, 777);
  1457. params.Set_Movement (ThrownObject, 0.5F, 1.25F);
  1458. Get_Action ()->Goto (params);
  1459. return ;
  1460. }
  1461. ///////////////////////////////////////////////////////////////////////////
  1462. //
  1463. // STATE_IMPL_THINK(MOVE_STATE_GOTO_THROW_OBJECT)
  1464. //
  1465. ///////////////////////////////////////////////////////////////////////////
  1466. void
  1467. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_GOTO_THROW_OBJECT) (void)
  1468. {
  1469. Vector3 obj_pos;
  1470. ThrownObject->Get_Position (&obj_pos);
  1471. if ((RaveshawPos - obj_pos).Length2 () < 3.0F || Get_Action ()->Is_Active () == false) {
  1472. //}
  1473. //
  1474. // Stop and pick up the object once we get there
  1475. //
  1476. //if (Get_Action ()->Is_Active () == false) {
  1477. MoveState.Set_State (MOVE_STATE_STOP);
  1478. RaveshawState.Set_State (RAVESHAW_STATE_GRAB_OBJECT);
  1479. }
  1480. return ;
  1481. }
  1482. ///////////////////////////////////////////////////////////////////////////
  1483. //
  1484. // STATE_IMPL_BEGIN(MOVE_STATE_JUMP_TO_STAR)
  1485. //
  1486. ///////////////////////////////////////////////////////////////////////////
  1487. void
  1488. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_JUMP_TO_STAR) (void)
  1489. {
  1490. //
  1491. // Stop any current action and jump to the star's position
  1492. //
  1493. Get_Action ()->Reset (100);
  1494. Jump_To_Point (StarPos);
  1495. //Peek_Human_Phys ()->Jump_To_Point (StarPos);
  1496. return ;
  1497. }
  1498. ///////////////////////////////////////////////////////////////////////////
  1499. //
  1500. // STATE_IMPL_THINK(MOVE_STATE_JUMP_TO_STAR)
  1501. //
  1502. ///////////////////////////////////////////////////////////////////////////
  1503. void
  1504. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_JUMP_TO_STAR) (void)
  1505. {
  1506. //
  1507. // Face the star
  1508. //
  1509. Set_Targeting (StarPos);
  1510. //
  1511. // The state ends when the mutant lands
  1512. //
  1513. if (JumpState.Get_State () == JUMP_STATE_NONE) {
  1514. MoveState.Set_State (MOVE_STATE_FOLLOW_STAR);
  1515. }
  1516. return ;
  1517. }
  1518. ///////////////////////////////////////////////////////////////////////////
  1519. //
  1520. // STATE_IMPL_BEGIN(MOVE_STATE_FOLLOW_STAR)
  1521. //
  1522. ///////////////////////////////////////////////////////////////////////////
  1523. void
  1524. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(MOVE_STATE_FOLLOW_STAR) (void)
  1525. {
  1526. MoveStateTimer = 0.0F;
  1527. return ;
  1528. }
  1529. ///////////////////////////////////////////////////////////////////////////
  1530. //
  1531. // STATE_IMPL_END(MOVE_STATE_FOLLOW_STAR)
  1532. //
  1533. ///////////////////////////////////////////////////////////////////////////
  1534. void
  1535. RaveshawBossGameObjClass::STATE_IMPL_END(MOVE_STATE_FOLLOW_STAR) (void)
  1536. {
  1537. //
  1538. // Simply stop any action
  1539. //
  1540. Get_Action ()->Reset (100);
  1541. return ;
  1542. }
  1543. ///////////////////////////////////////////////////////////////////////////
  1544. //
  1545. // STATE_IMPL_THINK(MOVE_STATE_FOLLOW_STAR)
  1546. //
  1547. ///////////////////////////////////////////////////////////////////////////
  1548. void
  1549. RaveshawBossGameObjClass::STATE_IMPL_THINK(MOVE_STATE_FOLLOW_STAR) (void)
  1550. {
  1551. //
  1552. // Is it time to track down the player again?
  1553. //
  1554. MoveStateTimer -= TimeManager::Get_Frame_Seconds ();
  1555. if (MoveStateTimer <= 0) {
  1556. MoveStateTimer = 0.75F;
  1557. //
  1558. // Should we jump to the player's position?
  1559. //
  1560. float dist2 = (RaveshawPos - StarPos).Length2 ();
  1561. if ((dist2 > 64.0F) && FreeRandom.Get_Int (5) == 1) {
  1562. MoveState.Set_State (MOVE_STATE_JUMP_TO_STAR);
  1563. } else {
  1564. //
  1565. // Track down the player
  1566. //
  1567. ActionParamsStruct params;
  1568. params.Set_Basic ((long)0, 100, 777);
  1569. params.Set_Movement (COMBAT_STAR, 1.0F, 1.0F);
  1570. params.MoveFollow = true;
  1571. Get_Action ()->Goto (params);
  1572. }
  1573. }
  1574. return ;
  1575. }
  1576. ///////////////////////////////////////////////////////////////////////////
  1577. //
  1578. // STATE_IMPL_BEGIN(RAVESHAW_STATE_NOTHING)
  1579. //
  1580. ///////////////////////////////////////////////////////////////////////////
  1581. void
  1582. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_NOTHING) (void)
  1583. {
  1584. //
  1585. // Choose a random time to do something a little different (i.e. roar, etc)
  1586. //
  1587. RaveshawStateTimer = WWMath::Random_Float (5.0F, 15.0F);
  1588. return ;
  1589. }
  1590. ///////////////////////////////////////////////////////////////////////////
  1591. //
  1592. // STATE_IMPL_THINK(RAVESHAW_STATE_NOTHING)
  1593. //
  1594. ///////////////////////////////////////////////////////////////////////////
  1595. void
  1596. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_NOTHING) (void)
  1597. {
  1598. RaveshawStateTimer -= TimeManager::Get_Frame_Seconds ();
  1599. if (RaveshawStateTimer <= 0) {
  1600. //
  1601. // Just throw your head back and roar
  1602. //
  1603. RaveshawState.Set_State (RAVESHAW_STATE_ROAR);
  1604. }
  1605. return ;
  1606. }
  1607. ///////////////////////////////////////////////////////////////////////////
  1608. //
  1609. // STATE_IMPL_BEGIN(RAVESHAW_STATE_ROAR)
  1610. //
  1611. ///////////////////////////////////////////////////////////////////////////
  1612. void
  1613. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_ROAR) (void)
  1614. {
  1615. //
  1616. // Play the roar animation and sound
  1617. //
  1618. Set_Blended_Animation ("S_C_HUMAN.H_C_A0A0_L07", false);
  1619. Attach_Sound ("Rav_Long_Yell_Twiddler", "C HEAD");
  1620. //
  1621. // Stop whatever action he's doing (temporarily)
  1622. //
  1623. Get_Action ()->Pause (true);
  1624. JumpState.Halt_State ();
  1625. MoveState.Halt_State ();
  1626. return ;
  1627. }
  1628. ///////////////////////////////////////////////////////////////////////////
  1629. //
  1630. // STATE_IMPL_END(RAVESHAW_STATE_ROAR)
  1631. //
  1632. ///////////////////////////////////////////////////////////////////////////
  1633. void
  1634. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_ROAR) (void)
  1635. {
  1636. //
  1637. // Release our lock on the animation state
  1638. //
  1639. Get_Human_State ()->Stop_Scripted_Animation ();
  1640. //
  1641. // Resume the action
  1642. //
  1643. MoveState.Resume_State ();
  1644. JumpState.Resume_State ();
  1645. Get_Action ()->Pause (false);
  1646. return ;
  1647. }
  1648. ///////////////////////////////////////////////////////////////////////////
  1649. //
  1650. // STATE_IMPL_THINK(RAVESHAW_STATE_ROAR)
  1651. //
  1652. ///////////////////////////////////////////////////////////////////////////
  1653. void
  1654. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_ROAR) (void)
  1655. {
  1656. //
  1657. // Reset the state when complete
  1658. //
  1659. if (Get_Anim_Control ()->Is_Complete ()) {
  1660. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  1661. }
  1662. return ;
  1663. }
  1664. ///////////////////////////////////////////////////////////////////////////
  1665. //
  1666. // STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_TIBERIUM)
  1667. //
  1668. ///////////////////////////////////////////////////////////////////////////
  1669. void
  1670. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_TIBERIUM) (void)
  1671. {
  1672. //
  1673. // Play the grab the tiberium animation
  1674. //
  1675. Set_Blended_Animation ("S_A_HUMAN.RAV_HEAL", false);
  1676. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  1677. //
  1678. // Stop the animation at frame 34
  1679. //
  1680. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  1681. Get_Anim_Control ()->Set_Target_Frame (34);
  1682. return ;
  1683. }
  1684. ///////////////////////////////////////////////////////////////////////////
  1685. //
  1686. // STATE_IMPL_END(RAVESHAW_STATE_GRAB_TIBERIUM)
  1687. //
  1688. ///////////////////////////////////////////////////////////////////////////
  1689. void
  1690. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_GRAB_TIBERIUM) (void)
  1691. {
  1692. //
  1693. // Release our lock on the animation state
  1694. //
  1695. Get_Human_State ()->Stop_Scripted_Animation ();
  1696. return ;
  1697. }
  1698. ///////////////////////////////////////////////////////////////////////////
  1699. //
  1700. // STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_TIBERIUM)
  1701. //
  1702. ///////////////////////////////////////////////////////////////////////////
  1703. void
  1704. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_TIBERIUM) (void)
  1705. {
  1706. //
  1707. // Face the tiberium
  1708. //
  1709. Set_Targeting (TIBERIUM_POS);
  1710. //
  1711. // Handy macro
  1712. //
  1713. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  1714. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  1715. if (PASSED_FRAME (9.0F)) {
  1716. //
  1717. // Start healing
  1718. //
  1719. EngorgedState.Set_State (ENGORGED_STATE_ABSORBING_TIBERIUM);
  1720. }
  1721. //
  1722. // Loop the animation between frames 12 and 34
  1723. //
  1724. if (Get_Anim_Control ()->Is_Complete ()) {
  1725. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 12);
  1726. Get_Anim_Control ()->Set_Target_Frame (34);
  1727. }
  1728. //
  1729. // Cache the last frame number...
  1730. //
  1731. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1732. return ;
  1733. }
  1734. ///////////////////////////////////////////////////////////////////////////
  1735. //
  1736. // STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_SOLDIER)
  1737. //
  1738. ///////////////////////////////////////////////////////////////////////////
  1739. void
  1740. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_SOLDIER) (void)
  1741. {
  1742. //
  1743. // Play the grab the soldier animation
  1744. //
  1745. Set_Blended_Animation ("S_A_HUMAN.RAV_GRABTHROW", false);
  1746. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  1747. //
  1748. // Stop the animation at frame 27
  1749. //
  1750. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  1751. Get_Anim_Control ()->Set_Target_Frame (27);
  1752. return ;
  1753. }
  1754. ///////////////////////////////////////////////////////////////////////////
  1755. //
  1756. // STATE_IMPL_END(RAVESHAW_STATE_GRAB_SOLDIER)
  1757. //
  1758. ///////////////////////////////////////////////////////////////////////////
  1759. void
  1760. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_GRAB_SOLDIER) (void)
  1761. {
  1762. return ;
  1763. }
  1764. ///////////////////////////////////////////////////////////////////////////
  1765. //
  1766. // STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_SOLDIER)
  1767. //
  1768. ///////////////////////////////////////////////////////////////////////////
  1769. void
  1770. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_SOLDIER) (void)
  1771. {
  1772. //
  1773. // Is it time to show the soldier?
  1774. //
  1775. if ( StealthSoldierState.Get_State () == STEALTH_SOLDIER_STATE_NONE &&
  1776. Get_Anim_Control ()->Is_Complete ())
  1777. {
  1778. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_DISPLAY);
  1779. }
  1780. //
  1781. // Make sure we face the star...
  1782. //
  1783. if (StealthSoldierState.Get_State () != STEALTH_SOLDIER_STATE_NONE) {
  1784. Set_Targeting (StarPos);
  1785. }
  1786. return ;
  1787. }
  1788. ///////////////////////////////////////////////////////////////////////////
  1789. //
  1790. // STATE_IMPL_BEGIN(RAVESHAW_STATE_THROW_SOLDIER)
  1791. //
  1792. ///////////////////////////////////////////////////////////////////////////
  1793. void
  1794. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_THROW_SOLDIER) (void)
  1795. {
  1796. //
  1797. // Play the throw the soldier animation
  1798. //
  1799. /*Set_Blended_Animation ("S_A_HUMAN.GRABTHROW", false);
  1800. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  1801. //
  1802. // Start the animation at frame 27
  1803. //
  1804. Get_Anim_Control ()->Set_Mode (ANIM_MODE_ONCE, 27);*/
  1805. //
  1806. // Advance to frame 49
  1807. //
  1808. Get_Anim_Control ()->Set_Target_Frame (49);
  1809. //
  1810. // Play an exertion sound
  1811. //
  1812. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Exert_01", Get_Transform ());
  1813. return ;
  1814. }
  1815. ///////////////////////////////////////////////////////////////////////////
  1816. //
  1817. // STATE_IMPL_END(RAVESHAW_STATE_THROW_SOLDIER)
  1818. //
  1819. ///////////////////////////////////////////////////////////////////////////
  1820. void
  1821. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_THROW_SOLDIER) (void)
  1822. {
  1823. //
  1824. // Release our lock on the animation state
  1825. //
  1826. Get_Human_State ()->Stop_Scripted_Animation ();
  1827. return ;
  1828. }
  1829. ///////////////////////////////////////////////////////////////////////////
  1830. //
  1831. // STATE_IMPL_THINK(RAVESHAW_STATE_THROW_SOLDIER)
  1832. //
  1833. ///////////////////////////////////////////////////////////////////////////
  1834. void
  1835. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_THROW_SOLDIER) (void)
  1836. {
  1837. //
  1838. // Handy macro
  1839. //
  1840. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  1841. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  1842. if (PASSED_FRAME (36.0F)) {
  1843. //
  1844. // Let the soldier fly!
  1845. //
  1846. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_FLYING);
  1847. }
  1848. //
  1849. // Decide on what to do when finished
  1850. //
  1851. if (Get_Anim_Control ()->Is_Complete ()) {
  1852. Determine_New_Overall_State ();
  1853. }
  1854. //
  1855. // Cache the last frame number...
  1856. //
  1857. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1858. return ;
  1859. }
  1860. ///////////////////////////////////////////////////////////////////////////
  1861. //
  1862. // STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_OBJECT)
  1863. //
  1864. ///////////////////////////////////////////////////////////////////////////
  1865. void
  1866. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_OBJECT) (void)
  1867. {
  1868. //
  1869. // Play the pickup the object animation
  1870. //
  1871. Set_Blended_Animation ("S_A_HUMAN.RAV_THROW", false);
  1872. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  1873. //
  1874. // Stop the animation at frame 22
  1875. //
  1876. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  1877. Get_Anim_Control ()->Set_Target_Frame (22);
  1878. return ;
  1879. }
  1880. ///////////////////////////////////////////////////////////////////////////
  1881. //
  1882. // STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_OBJECT)
  1883. //
  1884. ///////////////////////////////////////////////////////////////////////////
  1885. void
  1886. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_OBJECT) (void)
  1887. {
  1888. //
  1889. // Throw the object
  1890. //
  1891. if (Get_Anim_Control ()->Is_Complete ()) {
  1892. RaveshawState.Set_State (RAVESHAW_STATE_THROW_OBJECT);
  1893. }
  1894. //
  1895. // Handy macro
  1896. //
  1897. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  1898. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  1899. if (PASSED_FRAME (9.0F)) {
  1900. //
  1901. // Pickup the object
  1902. //
  1903. ThrownObjectState.Set_State (THROWN_OBJECT_STATE_PICKUP);
  1904. }
  1905. //
  1906. // Cache the last frame number...
  1907. //
  1908. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1909. return ;
  1910. }
  1911. ///////////////////////////////////////////////////////////////////////////
  1912. //
  1913. // STATE_IMPL_BEGIN(RAVESHAW_STATE_THROW_OBJECT)
  1914. //
  1915. ///////////////////////////////////////////////////////////////////////////
  1916. void
  1917. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_THROW_OBJECT) (void)
  1918. {
  1919. //
  1920. // Play the throw the object animation
  1921. //
  1922. //Set_Blended_Animation ("S_A_HUMAN.A_HOST_L3A", false);
  1923. //Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  1924. //
  1925. // Stop the animation at frame 29
  1926. //
  1927. //Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  1928. //Get_Anim_Control ()->Set_Target_Frame (29);
  1929. RaveshawStateTimer = 1.0F;
  1930. return ;
  1931. }
  1932. ///////////////////////////////////////////////////////////////////////////
  1933. //
  1934. // STATE_IMPL_END(RAVESHAW_STATE_THROW_OBJECT)
  1935. //
  1936. ///////////////////////////////////////////////////////////////////////////
  1937. void
  1938. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_THROW_OBJECT) (void)
  1939. {
  1940. //
  1941. // Release our lock on the animation state
  1942. //
  1943. Get_Human_State ()->Stop_Scripted_Animation ();
  1944. return ;
  1945. }
  1946. ///////////////////////////////////////////////////////////////////////////
  1947. //
  1948. // STATE_IMPL_THINK(RAVESHAW_STATE_THROW_OBJECT)
  1949. //
  1950. ///////////////////////////////////////////////////////////////////////////
  1951. void
  1952. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_THROW_OBJECT) (void)
  1953. {
  1954. if (RaveshawStateTimer != UNINITIALIZED_TIMER) {
  1955. RaveshawStateTimer -= TimeManager::Get_Frame_Seconds ();
  1956. if (RaveshawStateTimer <= 0) {
  1957. RaveshawStateTimer = UNINITIALIZED_TIMER;
  1958. //
  1959. // Finish the animation
  1960. //
  1961. Get_Anim_Control ()->Set_Target_Frame (58);
  1962. }
  1963. } else {
  1964. //
  1965. // Handy macro
  1966. //
  1967. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  1968. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  1969. if (PASSED_FRAME (36.0F)) {
  1970. //
  1971. // Let the object fly!
  1972. //
  1973. ThrownObjectState.Set_State (THROWN_OBJECT_STATE_FLYING);
  1974. }
  1975. if (Get_Anim_Control ()->Is_Complete ()) {
  1976. //
  1977. // Decide on what to do next...
  1978. //
  1979. Determine_New_Overall_State ();
  1980. }
  1981. }
  1982. //
  1983. // Make sure to face the star
  1984. //
  1985. Set_Targeting (StarPos);
  1986. //
  1987. // Cache the last frame number...
  1988. //
  1989. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  1990. return ;
  1991. }
  1992. ///////////////////////////////////////////////////////////////////////////
  1993. //
  1994. // STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_STAR)
  1995. //
  1996. ///////////////////////////////////////////////////////////////////////////
  1997. void
  1998. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_GRAB_STAR) (void)
  1999. {
  2000. HasMeleeAttackHit = false;
  2001. LastMeleeAnimFrame = 0.0F;
  2002. //
  2003. // Play the grab the star animation
  2004. //
  2005. //Set_Blended_Animation ("S_A_HUMAN.RAV_HIT", false);
  2006. //Set_Blended_Animation ("S_C_HUMAN.H_C_A0A0_L02", false);
  2007. //
  2008. // Play the grab the soldier animation
  2009. //
  2010. Set_Blended_Animation ("S_A_HUMAN.RAV_GRABTHROW", false, 14.0F);
  2011. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2012. ((HumanAnimControlClass *)Get_Anim_Control ())->Set_Anim_Speed_Scale (0.5F);
  2013. //
  2014. // Grab the player
  2015. //
  2016. HavocState.Set_State (HAVOC_STATE_GRABBED);
  2017. return ;
  2018. }
  2019. ///////////////////////////////////////////////////////////////////////////
  2020. //
  2021. // STATE_IMPL_END(RAVESHAW_STATE_GRAB_STAR)
  2022. //
  2023. ///////////////////////////////////////////////////////////////////////////
  2024. void
  2025. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_GRAB_STAR) (void)
  2026. {
  2027. //
  2028. // Release our lock on the animation state
  2029. //
  2030. Get_Human_State ()->Stop_Scripted_Animation ();
  2031. return ;
  2032. }
  2033. ///////////////////////////////////////////////////////////////////////////
  2034. //
  2035. // STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_STAR)
  2036. //
  2037. ///////////////////////////////////////////////////////////////////////////
  2038. void
  2039. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_GRAB_STAR) (void)
  2040. {
  2041. //
  2042. // Decide on something new to do if finished
  2043. //
  2044. if (Get_Anim_Control ()->Is_Complete ()) {
  2045. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  2046. Determine_New_Overall_State ();
  2047. } else {
  2048. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  2049. //
  2050. // Handy macro
  2051. //
  2052. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  2053. if (PASSED_FRAME (37.0F)) {
  2054. HavocState.Set_State (HAVOC_STATE_FLYING);
  2055. } else if (PASSED_FRAME (25.0F)) {
  2056. ((HumanAnimControlClass *)Get_Anim_Control ())->Set_Anim_Speed_Scale (1.0F);
  2057. }
  2058. LastMeleeAnimFrame = curr_frame;
  2059. }
  2060. //
  2061. // Always try to face the star
  2062. //
  2063. //Set_Targeting (StarPos);
  2064. /*float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  2065. if (curr_frame >= 7.0F) {
  2066. //
  2067. // Decide on something new to do if finished
  2068. //
  2069. if (Get_Anim_Control ()->Is_Complete ()) {
  2070. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  2071. Determine_New_Overall_State ();
  2072. }
  2073. //
  2074. // Apply hefty damage if we connect
  2075. //
  2076. if (HasMeleeAttackHit == false) {
  2077. HasMeleeAttackHit |= Apply_Bone_Collision_Damage (15.0F, "C R HAND");
  2078. HasMeleeAttackHit |= Apply_Bone_Collision_Damage (15.0F, "C L HAND");
  2079. }
  2080. //
  2081. // Cache the last frame number...
  2082. //
  2083. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  2084. }*/
  2085. return ;
  2086. }
  2087. ///////////////////////////////////////////////////////////////////////////
  2088. //
  2089. // STATE_IMPL_BEGIN(RAVESHAW_STATE_BODYSLAM)
  2090. //
  2091. ///////////////////////////////////////////////////////////////////////////
  2092. void
  2093. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_BODYSLAM) (void)
  2094. {
  2095. //
  2096. // Find the "closest" position around the tiberium for Raveshaw to run to
  2097. //
  2098. Vector3 star_vector_from_tib = (StarPos - TIBERIUM_POS);
  2099. star_vector_from_tib.Z = 0;
  2100. //
  2101. // Check to see if the player is in the right spot for a body slam
  2102. //
  2103. if (star_vector_from_tib.Length2 () < (SAFE_JUMP_RADIUS * SAFE_JUMP_RADIUS)) {
  2104. RaveshawState.Set_State (RAVESHAW_STATE_JUMP_DOWN);
  2105. } else {
  2106. HasMeleeAttackHit = false;
  2107. LastMeleeAnimFrame = 0.0F;
  2108. //
  2109. // Play the bodyslam animation
  2110. //
  2111. Set_Blended_Animation ("S_A_HUMAN.H_A_BODYSLAM", false);
  2112. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2113. //
  2114. // Stop the animation at frame 69
  2115. //
  2116. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  2117. Get_Anim_Control ()->Set_Target_Frame (69);
  2118. //
  2119. // Play a yell sound.
  2120. //
  2121. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Body_Slam_Yell", Get_Transform ());
  2122. }
  2123. return ;
  2124. }
  2125. ///////////////////////////////////////////////////////////////////////////
  2126. //
  2127. // STATE_IMPL_END(RAVESHAW_STATE_BODYSLAM)
  2128. //
  2129. ///////////////////////////////////////////////////////////////////////////
  2130. void
  2131. RaveshawBossGameObjClass::STATE_IMPL_END(RAVESHAW_STATE_BODYSLAM) (void)
  2132. {
  2133. //
  2134. // Release our lock on the animation state
  2135. //
  2136. Get_Human_State ()->Stop_Scripted_Animation ();
  2137. return ;
  2138. }
  2139. ///////////////////////////////////////////////////////////////////////////
  2140. //
  2141. // STATE_IMPL_THINK(RAVESHAW_STATE_BODYSLAM)
  2142. //
  2143. ///////////////////////////////////////////////////////////////////////////
  2144. void
  2145. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_BODYSLAM) (void)
  2146. {
  2147. //
  2148. // Have we finished the body slam?
  2149. //
  2150. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  2151. if (curr_frame >= 174.0F) {
  2152. //
  2153. // Determine which state to goto next...
  2154. //
  2155. Determine_New_Overall_State ();
  2156. } else {
  2157. //
  2158. // Handy macro
  2159. //
  2160. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  2161. if (PASSED_FRAME (37.0F)) {
  2162. //
  2163. // Get the mutant to jump to the star's position
  2164. //
  2165. Peek_Human_Phys ()->Jump_To_Point (StarPos);
  2166. } else if (PASSED_FRAME (90.0F)) {
  2167. //
  2168. // Create an explision when he lands
  2169. //
  2170. DefinitionClass *definition = DefinitionMgrClass::Find_Named_Definition ("Explosion_Raveshaw_Bodyslam");
  2171. if (definition != NULL) {
  2172. //
  2173. // Position the explosion at the mutants pelvis
  2174. //
  2175. const Matrix3D &pelvis_tm = Peek_Model ()->Get_Bone_Transform ("C PELVIS");
  2176. ExplosionManager::Create_Explosion_At (definition->Get_ID (), pelvis_tm.Get_Translation (), NULL);
  2177. }
  2178. }
  2179. //
  2180. // Do we need to check for the ground?
  2181. //
  2182. if (Get_Anim_Control ()->Get_Target_Frame () != 174.0F) {
  2183. //
  2184. // Now determine if the mutant is within a few feet of the ground
  2185. //
  2186. float distance = Get_Distance_From_Ground ();
  2187. if (distance < 1.0F) {
  2188. Get_Anim_Control ()->Set_Target_Frame (174.0F);
  2189. }
  2190. }
  2191. //
  2192. // Apply massive damage if we connect
  2193. //
  2194. Apply_Bone_Collision_Damage (500.0F, "C PELVIS");
  2195. //
  2196. // Cache the last frame number...
  2197. //
  2198. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  2199. }
  2200. return ;
  2201. }
  2202. ///////////////////////////////////////////////////////////////////////////
  2203. //
  2204. // STATE_IMPL_BEGIN(RAVESHAW_STATE_JUMP_DOWN)
  2205. //
  2206. ///////////////////////////////////////////////////////////////////////////
  2207. void
  2208. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_JUMP_DOWN) (void)
  2209. {
  2210. //
  2211. // Find the "closest" position to the star that Raveshaw can jump to
  2212. //
  2213. Vector3 dir_vector = (StarPos - TIBERIUM_POS);
  2214. dir_vector.Normalize ();
  2215. CurrentDestPos = TIBERIUM_POS + (SAFE_JUMP_RADIUS * dir_vector);
  2216. //
  2217. // Now, jump to this position
  2218. //
  2219. Jump_To_Point (CurrentDestPos);
  2220. return ;
  2221. }
  2222. ///////////////////////////////////////////////////////////////////////////
  2223. //
  2224. // STATE_IMPL_THINK(RAVESHAW_STATE_JUMP_DOWN)
  2225. //
  2226. ///////////////////////////////////////////////////////////////////////////
  2227. void
  2228. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_JUMP_DOWN) (void)
  2229. {
  2230. //
  2231. // Apply massive damage if we connect
  2232. //
  2233. Apply_Bone_Collision_Damage (500.0F, "C L FOOT");
  2234. Apply_Bone_Collision_Damage (500.0F, "C R FOOT");
  2235. //
  2236. // The state ends when the mutant lands
  2237. //
  2238. if (JumpState.Get_State () == JUMP_STATE_NONE) {
  2239. RaveshawState.Set_State (RAVESHAW_STATE_NOTHING);
  2240. OverallState.Set_State (OVERALL_STATE_CHASE_STAR);
  2241. }
  2242. return ;
  2243. }
  2244. ///////////////////////////////////////////////////////////////////////////
  2245. //
  2246. // STATE_IMPL_BEGIN(RAVESHAW_STATE_DYING)
  2247. //
  2248. ///////////////////////////////////////////////////////////////////////////
  2249. void
  2250. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_DYING) (void)
  2251. {
  2252. //
  2253. // Play the crouching animation
  2254. //
  2255. Set_Blended_Animation ("S_A_HUMAN.RAV_DEATH", false);
  2256. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2257. //
  2258. // Stop the animation at frame 49
  2259. //
  2260. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  2261. Get_Anim_Control ()->Set_Target_Frame (49);
  2262. return ;
  2263. }
  2264. ///////////////////////////////////////////////////////////////////////////
  2265. //
  2266. // STATE_IMPL_THINK(RAVESHAW_STATE_DYING)
  2267. //
  2268. ///////////////////////////////////////////////////////////////////////////
  2269. void
  2270. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_DYING) (void)
  2271. {
  2272. /*Vector3 delta_vector = RaveshawPos - TIBERIUM_POS;
  2273. Vector3 dir_vector = (RaveshawPos - TIBERIUM_POS);
  2274. dir_vector.Normalize ();
  2275. Vector3 target_pos = TIBERIUM_POS + (8.0F * dir_vector);*/
  2276. Vector3 target_pos (0, 0, 0);
  2277. Find_Death_Facing_Pos (&target_pos);
  2278. Set_Targeting (target_pos);
  2279. //
  2280. // Handy macro
  2281. //
  2282. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  2283. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  2284. if (PASSED_FRAME (43.0F)) {
  2285. //
  2286. // Start falling when the animation gets to the correct frame
  2287. //
  2288. RaveshawState.Set_State (RAVESHAW_STATE_FALL);
  2289. }
  2290. //
  2291. // Cache the last frame number...
  2292. //
  2293. LastMeleeAnimFrame = Get_Anim_Control ()->Get_Current_Frame ();
  2294. return ;
  2295. }
  2296. ///////////////////////////////////////////////////////////////////////////
  2297. //
  2298. // STATE_IMPL_BEGIN(RAVESHAW_STATE_FALL)
  2299. //
  2300. ///////////////////////////////////////////////////////////////////////////
  2301. void
  2302. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_FALL) (void)
  2303. {
  2304. RaveshawStateTimer = 0.125F;
  2305. return ;
  2306. }
  2307. ///////////////////////////////////////////////////////////////////////////
  2308. //
  2309. // STATE_IMPL_THINK(RAVESHAW_STATE_FALL)
  2310. //
  2311. ///////////////////////////////////////////////////////////////////////////
  2312. void
  2313. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_FALL) (void)
  2314. {
  2315. RaveshawStateTimer += TimeManager::Get_Frame_Seconds ();
  2316. float velocity = (22.0F * RaveshawStateTimer);
  2317. Vector3 new_pos = RaveshawPos;
  2318. new_pos.Z -= velocity * TimeManager::Get_Frame_Seconds ();
  2319. //
  2320. // Simply stop falling when he reaches the "ground". (We hard-code the ground's
  2321. // Z-position for simplicity.)
  2322. //
  2323. const float FLOOR_POS1 = -189.1F;
  2324. const float FLOOR_POS2 = -191.0F;
  2325. if ( (new_pos.X >= -133.1F && new_pos.Z <= FLOOR_POS1) ||
  2326. (new_pos.X < -133.1F && new_pos.Z <= FLOOR_POS2))
  2327. {
  2328. if (new_pos.X >= -133.1F) {
  2329. new_pos.Z = FLOOR_POS1;
  2330. } else {
  2331. new_pos.Z = FLOOR_POS2;
  2332. }
  2333. //
  2334. // Move onto the "landing" state
  2335. //
  2336. RaveshawState.Set_State (RAVESHAW_STATE_DEATH_LANDING);
  2337. }
  2338. //
  2339. // Move Raveshaw
  2340. //
  2341. Set_Position (new_pos);
  2342. return ;
  2343. }
  2344. ///////////////////////////////////////////////////////////////////////////
  2345. //
  2346. // STATE_IMPL_BEGIN(RAVESHAW_STATE_DEATH_LANDING)
  2347. //
  2348. ///////////////////////////////////////////////////////////////////////////
  2349. void
  2350. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(RAVESHAW_STATE_DEATH_LANDING) (void)
  2351. {
  2352. //
  2353. // Play the rest of the animation
  2354. //
  2355. Get_Anim_Control ()->Set_Target_Frame (63);
  2356. RaveshawStateTimer = UNINITIALIZED_TIMER;
  2357. //
  2358. // Play a landing sound.
  2359. //
  2360. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Death_Fall", Get_Transform ());
  2361. COMBAT_SCENE->Add_Camera_Shake (RaveshawPos, 40.0, 0.75F, 0.125F);
  2362. return ;
  2363. }
  2364. ///////////////////////////////////////////////////////////////////////////
  2365. //
  2366. // STATE_IMPL_THINK(RAVESHAW_STATE_DEATH_LANDING)
  2367. //
  2368. ///////////////////////////////////////////////////////////////////////////
  2369. void
  2370. RaveshawBossGameObjClass::STATE_IMPL_THINK(RAVESHAW_STATE_DEATH_LANDING) (void)
  2371. {
  2372. if (RaveshawStateTimer != UNINITIALIZED_TIMER) {
  2373. RaveshawStateTimer -= TimeManager::Get_Frame_Seconds ();
  2374. if (RaveshawStateTimer <= 0) {
  2375. //
  2376. // Trigger mission success
  2377. //
  2378. CombatManager::Mission_Complete (true);
  2379. }
  2380. } else {
  2381. //
  2382. // When the animation's complete, sit and wait for
  2383. // a couple of seconds
  2384. //
  2385. if (Get_Anim_Control ()->Is_Complete ()) {
  2386. RaveshawStateTimer = 2.0F;
  2387. }
  2388. }
  2389. return ;
  2390. }
  2391. ///////////////////////////////////////////////////////////////////////////
  2392. //
  2393. // STATE_IMPL_BEGIN(ENGORGED_STATE_ABSORBING_TIBERIUM)
  2394. //
  2395. ///////////////////////////////////////////////////////////////////////////
  2396. void
  2397. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(ENGORGED_STATE_ABSORBING_TIBERIUM) (void)
  2398. {
  2399. EngorgedStateTimer = HEAL_TIME;
  2400. LightningRodState.Set_State (LIGHTNING_ROD_STATE_ACTIVE);
  2401. //
  2402. // Configure the effect
  2403. //
  2404. TiberiumEffect->Set_Intensity (0.0F);
  2405. Peek_Physical_Object ()->Add_Effect_To_Me (TiberiumEffect);
  2406. IsTiberiumEffectApplied = true;
  2407. return ;
  2408. }
  2409. ///////////////////////////////////////////////////////////////////////////
  2410. //
  2411. // STATE_IMPL_THINK(ENGORGED_STATE_ABSORBING_TIBERIUM)
  2412. //
  2413. ///////////////////////////////////////////////////////////////////////////
  2414. void
  2415. RaveshawBossGameObjClass::STATE_IMPL_THINK(ENGORGED_STATE_ABSORBING_TIBERIUM) (void)
  2416. {
  2417. const float HEAL_RATE = 50.0F;
  2418. //
  2419. // If he's finished absorbing the tiberium, then start chasing the player
  2420. //
  2421. EngorgedStateTimer -= TimeManager::Get_Frame_Seconds ();
  2422. if (EngorgedStateTimer <= 0) {
  2423. EngorgedState.Set_State (ENGORGED_STATE_FADING);
  2424. OverallState.Set_State (OVERALL_STATE_CHASE_STAR);
  2425. } else {
  2426. //
  2427. // Configure the intensity
  2428. //
  2429. float percent = 1.0F - WWMath::Clamp ((EngorgedStateTimer / HEAL_TIME), 0.0F, 1.0F);
  2430. TiberiumEffect->Set_Intensity (percent * EFFECT_INTENSITY);
  2431. //
  2432. // Heal the mutant a little bit
  2433. //
  2434. float health = DefenseObject.Get_Health ();
  2435. health += HEAL_RATE * TimeManager::Get_Frame_Seconds ();
  2436. DefenseObject.Set_Health (health);
  2437. }
  2438. return ;
  2439. }
  2440. ///////////////////////////////////////////////////////////////////////////
  2441. //
  2442. // STATE_IMPL_BEGIN(ENGORGED_STATE_FADING)
  2443. //
  2444. ///////////////////////////////////////////////////////////////////////////
  2445. void
  2446. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(ENGORGED_STATE_FADING) (void)
  2447. {
  2448. LightningRodState.Set_State (ENGORGED_STATE_NONE);
  2449. EngorgedStateTimer = TiberiumEffect->Get_Intensity () * EFFECT_FADE_TIME;
  2450. return ;
  2451. }
  2452. ///////////////////////////////////////////////////////////////////////////
  2453. //
  2454. // STATE_IMPL_END(ENGORGED_STATE_FADING)
  2455. //
  2456. ///////////////////////////////////////////////////////////////////////////
  2457. void
  2458. RaveshawBossGameObjClass::STATE_IMPL_END(ENGORGED_STATE_FADING) (void)
  2459. {
  2460. //
  2461. // Remove the blue shimmering effect
  2462. //
  2463. Peek_Physical_Object ()->Remove_Effect_From_Me (TiberiumEffect);
  2464. IsTiberiumEffectApplied = false;
  2465. return ;
  2466. }
  2467. ///////////////////////////////////////////////////////////////////////////
  2468. //
  2469. // STATE_IMPL_THINK(ENGORGED_STATE_FADING)
  2470. //
  2471. ///////////////////////////////////////////////////////////////////////////
  2472. void
  2473. RaveshawBossGameObjClass::STATE_IMPL_THINK(ENGORGED_STATE_FADING) (void)
  2474. {
  2475. //
  2476. // If he's finished absorbing the tiberium, then start chasing the player
  2477. //
  2478. EngorgedStateTimer -= TimeManager::Get_Frame_Seconds ();
  2479. if (EngorgedStateTimer <= 0) {
  2480. EngorgedState.Set_State (ENGORGED_STATE_NONE);
  2481. } else {
  2482. //
  2483. // Configure the intensity
  2484. //
  2485. float percent = WWMath::Clamp ((EngorgedStateTimer / EFFECT_FADE_TIME), 0.0F, 1.0F);
  2486. TiberiumEffect->Set_Intensity (percent * EFFECT_INTENSITY);
  2487. }
  2488. return ;
  2489. }
  2490. ///////////////////////////////////////////////////////////////////////////
  2491. //
  2492. // STATE_IMPL_BEGIN(JUMP_STATE_CROUCHING)
  2493. //
  2494. ///////////////////////////////////////////////////////////////////////////
  2495. void
  2496. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(JUMP_STATE_CROUCHING) (void)
  2497. {
  2498. //
  2499. // Play the crouching animation
  2500. //
  2501. Set_Blended_Animation ("S_A_HUMAN.RAV_JUMP", false);
  2502. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2503. //
  2504. // Stop the animation at frame 10
  2505. //
  2506. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 0);
  2507. Get_Anim_Control ()->Set_Target_Frame (10);
  2508. //
  2509. // Stop any current action
  2510. //
  2511. Get_Action ()->Pause (true);
  2512. return ;
  2513. }
  2514. ///////////////////////////////////////////////////////////////////////////
  2515. //
  2516. // STATE_IMPL_THINK(JUMP_STATE_CROUCHING)
  2517. //
  2518. ///////////////////////////////////////////////////////////////////////////
  2519. void
  2520. RaveshawBossGameObjClass::STATE_IMPL_THINK(JUMP_STATE_CROUCHING) (void)
  2521. {
  2522. if (Get_Anim_Control ()->Is_Complete ()) {
  2523. JumpState.Set_State (JUMP_STATE_JUMPING);
  2524. }
  2525. return ;
  2526. }
  2527. ///////////////////////////////////////////////////////////////////////////
  2528. //
  2529. // STATE_IMPL_BEGIN(JUMP_STATE_JUMPING)
  2530. //
  2531. ///////////////////////////////////////////////////////////////////////////
  2532. void
  2533. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(JUMP_STATE_JUMPING) (void)
  2534. {
  2535. //
  2536. // Play the jumping animation
  2537. //
  2538. Set_Blended_Animation ("S_A_HUMAN.H_A_A0D0", false);
  2539. //Get_Anim_Control ()->Set_Target_Frame (11);
  2540. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2541. //
  2542. // Jump to the given position
  2543. //
  2544. Peek_Human_Phys ()->Jump_To_Point (CurrentJumpToPos);
  2545. return ;
  2546. }
  2547. ///////////////////////////////////////////////////////////////////////////
  2548. //
  2549. // STATE_IMPL_THINK(JUMP_STATE_JUMPING)
  2550. //
  2551. ///////////////////////////////////////////////////////////////////////////
  2552. void
  2553. RaveshawBossGameObjClass::STATE_IMPL_THINK(JUMP_STATE_JUMPING) (void)
  2554. {
  2555. Vector3 velocity;
  2556. Peek_Human_Phys ()->Get_Velocity (&velocity);
  2557. //
  2558. // Is Raveshaw close to the ground?
  2559. //
  2560. if (velocity.Z < 0 && Get_Distance_From_Ground () < 2.0F) {
  2561. JumpState.Set_State (JUMP_STATE_LANDING);
  2562. }
  2563. return ;
  2564. }
  2565. ///////////////////////////////////////////////////////////////////////////
  2566. //
  2567. // STATE_IMPL_BEGIN(JUMP_STATE_LANDING)
  2568. //
  2569. ///////////////////////////////////////////////////////////////////////////
  2570. void
  2571. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(JUMP_STATE_LANDING) (void)
  2572. {
  2573. //
  2574. // Play the landing animation
  2575. //
  2576. //Set_Blended_Animation ("S_A_HUMAN.H_A_A0L0", false, 0.0F, true);
  2577. //Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2578. Set_Blended_Animation ("S_A_HUMAN.RAV_JUMP", false);
  2579. Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2580. Get_Anim_Control ()->Set_Mode (ANIM_MODE_TARGET, 11);
  2581. Get_Anim_Control ()->Set_Target_Frame (31);
  2582. return ;
  2583. }
  2584. ///////////////////////////////////////////////////////////////////////////
  2585. //
  2586. // STATE_IMPL_END(JUMP_STATE_LANDING)
  2587. //
  2588. ///////////////////////////////////////////////////////////////////////////
  2589. void
  2590. RaveshawBossGameObjClass::STATE_IMPL_END(JUMP_STATE_LANDING) (void)
  2591. {
  2592. //
  2593. // Release our lock on the animation state
  2594. //
  2595. Get_Human_State ()->Stop_Scripted_Animation ();
  2596. //
  2597. // Resume the current action
  2598. //
  2599. Get_Action ()->Pause (false);
  2600. return ;
  2601. }
  2602. ///////////////////////////////////////////////////////////////////////////
  2603. //
  2604. // STATE_IMPL_THINK(JUMP_STATE_LANDING)
  2605. //
  2606. ///////////////////////////////////////////////////////////////////////////
  2607. void
  2608. RaveshawBossGameObjClass::STATE_IMPL_THINK(JUMP_STATE_LANDING) (void)
  2609. {
  2610. //
  2611. // Handy macro
  2612. //
  2613. float curr_frame = Get_Anim_Control ()->Get_Current_Frame ();
  2614. #define PASSED_FRAME(frame) (LastMeleeAnimFrame < frame && curr_frame >= frame)
  2615. if (PASSED_FRAME (20.0F)) {
  2616. //
  2617. // Play the landing sound
  2618. //
  2619. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Land_On_Metal", Get_Transform ());
  2620. COMBAT_SCENE->Add_Camera_Shake (RaveshawPos, 40.0, 0.75F, 0.125F);
  2621. }
  2622. LastMeleeAnimFrame = curr_frame;
  2623. //
  2624. // End the state when the animation is complete
  2625. //
  2626. if (Get_Anim_Control ()->Is_Complete ()) {
  2627. JumpState.Set_State (JUMP_STATE_NONE);
  2628. }
  2629. return ;
  2630. }
  2631. ///////////////////////////////////////////////////////////////////////////
  2632. //
  2633. // STATE_IMPL_BEGIN(HAVOC_STATE_GRABBED)
  2634. //
  2635. ///////////////////////////////////////////////////////////////////////////
  2636. void
  2637. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(HAVOC_STATE_GRABBED) (void)
  2638. {
  2639. if (COMBAT_STAR != NULL) {
  2640. COMBAT_STAR->Peek_Physical_Object ()->Enable_Objects_Simulation (false);
  2641. COMBAT_STAR->Control_Enable (false);
  2642. }
  2643. //
  2644. // Now snap to 3rd person so we are rendered
  2645. //
  2646. RestoreFirstPerson = CombatManager::Is_First_Person ();
  2647. CombatManager::Set_First_Person (false);
  2648. //
  2649. // Lock Havoc into a struggling state
  2650. //
  2651. COMBAT_STAR->Set_Blended_Animation ("S_A_HUMAN.STL_STRUGGLE", true);
  2652. COMBAT_STAR->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2653. return ;
  2654. }
  2655. ///////////////////////////////////////////////////////////////////////////
  2656. //
  2657. // STATE_IMPL_THINK(HAVOC_STATE_GRABBED)
  2658. //
  2659. ///////////////////////////////////////////////////////////////////////////
  2660. void
  2661. RaveshawBossGameObjClass::STATE_IMPL_THINK(HAVOC_STATE_GRABBED) (void)
  2662. {
  2663. Link_Player_To_Hands ();
  2664. return ;
  2665. }
  2666. ///////////////////////////////////////////////////////////////////////////
  2667. //
  2668. // STATE_IMPL_BEGIN(HAVOC_STATE_FLYING)
  2669. //
  2670. ///////////////////////////////////////////////////////////////////////////
  2671. void
  2672. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(HAVOC_STATE_FLYING) (void)
  2673. {
  2674. Vector3 dir_vector = Get_Transform ().Get_X_Vector ();
  2675. dir_vector.Z = 0.2F;
  2676. dir_vector.Normalize ();
  2677. //
  2678. // Calculate the direction that the soldier will fly through the air
  2679. //
  2680. FlyingObjectVector = dir_vector * 15.0F;
  2681. FlyingDist = FlyingObjectVector.Length ();
  2682. FlyingObjectDest = StarPos + FlyingObjectVector;
  2683. FlyingObjectVector.Normalize ();
  2684. //
  2685. // Restore control to the player
  2686. //
  2687. COMBAT_STAR->Control_Enable (true);
  2688. CombatManager::Set_First_Person (RestoreFirstPerson);
  2689. //
  2690. // Release Havoc from his struggles
  2691. //
  2692. COMBAT_STAR->Get_Human_State ()->Stop_Scripted_Animation ();
  2693. return ;
  2694. }
  2695. ///////////////////////////////////////////////////////////////////////////
  2696. //
  2697. // STATE_IMPL_THINK(HAVOC_STATE_FLYING)
  2698. //
  2699. ///////////////////////////////////////////////////////////////////////////
  2700. void
  2701. RaveshawBossGameObjClass::STATE_IMPL_THINK(HAVOC_STATE_FLYING) (void)
  2702. {
  2703. const float RATE = 15.0F;
  2704. float percent = RATE * TimeManager::Get_Frame_Seconds ();
  2705. Vector3 move_vector = FlyingObjectVector * percent;
  2706. //
  2707. // Simulate gravity
  2708. //
  2709. Vector3 delta = StarPos - FlyingObjectDest;
  2710. delta.Z = 0;
  2711. float dist = delta.Length ();
  2712. float dist_percent = 1.0F - WWMath::Clamp ((dist / FlyingDist), 0.0F, 1.0F);
  2713. if (dist_percent > 0.3F) {
  2714. move_vector.Z -= (dist_percent - 0.3F) * (8.0F * TimeManager::Get_Frame_Seconds ());
  2715. }
  2716. //
  2717. // Do the move and check to see if we hit anything
  2718. //
  2719. if (Fly_Move (COMBAT_STAR, move_vector)) {
  2720. //
  2721. // Restore physics simulation
  2722. //
  2723. COMBAT_STAR->Peek_Physical_Object ()->Enable_Objects_Simulation (true);
  2724. //
  2725. // Apply some damage to the player
  2726. //
  2727. OffenseObjectClass offense_obj (20.0F, 1);
  2728. COMBAT_STAR->Apply_Damage_Extended (offense_obj, 1.0F);
  2729. //
  2730. // Restore Havoc's state
  2731. //
  2732. HavocState.Set_State (HAVOC_STATE_NONE);
  2733. }
  2734. return ;
  2735. }
  2736. ///////////////////////////////////////////////////////////////////////////
  2737. //
  2738. // STATE_IMPL_BEGIN(STEALTH_SOLDIER_STATE_DISPLAY)
  2739. //
  2740. ///////////////////////////////////////////////////////////////////////////
  2741. void
  2742. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(STEALTH_SOLDIER_STATE_DISPLAY) (void)
  2743. {
  2744. //
  2745. // Create the stealth solider and position its neck at Raveshaw's hand
  2746. //
  2747. Create_Stealth_Soldier (Matrix3D (1));
  2748. Link_Stealth_Soldier_To_Hand ();
  2749. //
  2750. // Check to see if the stealth soldier has been destroyed...
  2751. //
  2752. SoldierGameObj *stealth_soldier = Peek_Stealth_Soldier ();
  2753. if (stealth_soldier == NULL) {
  2754. OverallState.Set_State (OVERALL_STATE_NOTHING);
  2755. RaveshawState.Set_State (RAVESHAW_STATE_ROAR);
  2756. MoveState.Set_State (MOVE_STATE_STOP);
  2757. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  2758. Determine_New_Overall_State ();
  2759. return ;
  2760. }
  2761. //
  2762. // Play a looping animation on the soldier
  2763. //
  2764. stealth_soldier->Set_Blended_Animation ("S_A_HUMAN.STL_STRUGGLE", true);
  2765. stealth_soldier->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2766. StealthSoldierStateTimer = 3.0F;
  2767. //
  2768. // Play the stealth broken sound and the gurgle sound
  2769. //
  2770. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Stealth_Broken", Get_Transform ());
  2771. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Throat_Grab_Twiddler", Get_Transform ());
  2772. return ;
  2773. }
  2774. ///////////////////////////////////////////////////////////////////////////
  2775. //
  2776. // STATE_IMPL_THINK(STEALTH_SOLDIER_STATE_DISPLAY)
  2777. //
  2778. ///////////////////////////////////////////////////////////////////////////
  2779. void
  2780. RaveshawBossGameObjClass::STATE_IMPL_THINK(STEALTH_SOLDIER_STATE_DISPLAY) (void)
  2781. {
  2782. //
  2783. // Move the soldier with Ravesahw
  2784. //
  2785. Link_Stealth_Soldier_To_Hand ();
  2786. //
  2787. // Is it time for the soldier to be thrown yet?
  2788. //
  2789. StealthSoldierStateTimer -= TimeManager::Get_Frame_Seconds ();
  2790. if (StealthSoldierStateTimer <= 0) {
  2791. RaveshawState.Set_State (RAVESHAW_STATE_THROW_SOLDIER);
  2792. }
  2793. return ;
  2794. }
  2795. ///////////////////////////////////////////////////////////////////////////
  2796. //
  2797. // STATE_IMPL_BEGIN(STEALTH_SOLDIER_STATE_FLYING)
  2798. //
  2799. ///////////////////////////////////////////////////////////////////////////
  2800. void
  2801. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(STEALTH_SOLDIER_STATE_FLYING) (void)
  2802. {
  2803. //
  2804. // Check to see if the stealth soldier has been destroyed...
  2805. //
  2806. SoldierGameObj *stealth_soldier = Peek_Stealth_Soldier ();
  2807. if (stealth_soldier == NULL) {
  2808. OverallState.Set_State (OVERALL_STATE_NOTHING);
  2809. RaveshawState.Set_State (RAVESHAW_STATE_ROAR);
  2810. MoveState.Set_State (MOVE_STATE_STOP);
  2811. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  2812. Determine_New_Overall_State ();
  2813. return ;
  2814. }
  2815. Vector3 solider_pos;
  2816. stealth_soldier->Get_Position (&solider_pos);
  2817. //
  2818. // Calculate the direction that the soldier will fly through the air
  2819. //
  2820. FlyingObjectDest = StarPos;
  2821. FlyingObjectVector = (StarPos - solider_pos);
  2822. FlyingDist = FlyingObjectVector.Length ();
  2823. FlyingObjectVector.Normalize ();
  2824. //
  2825. // Check to see which animation we should be play.
  2826. // (Fly forwards, fly backwards, fly right, fly left)
  2827. //
  2828. Vector3 relative_vector = stealth_soldier->Get_Transform ().Inverse_Rotate_Vector (FlyingObjectVector);
  2829. if (WWMath::Fabs (relative_vector.X) > WWMath::Fabs (relative_vector.Y)) {
  2830. if (relative_vector.X > 0) {
  2831. stealth_soldier->Set_Blended_Animation ("S_A_HUMAN.H_A_FLY1", true);
  2832. stealth_soldier->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2833. } else {
  2834. stealth_soldier->Set_Blended_Animation ("S_A_HUMAN.H_A_FLY2", true);
  2835. stealth_soldier->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2836. }
  2837. } else {
  2838. if (relative_vector.Y > 0) {
  2839. stealth_soldier->Set_Blended_Animation ("S_A_HUMAN.H_A_FLY4", true);
  2840. stealth_soldier->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2841. } else {
  2842. stealth_soldier->Set_Blended_Animation ("S_A_HUMAN.H_A_FLY3", true);
  2843. stealth_soldier->Get_Human_State ()->Set_State (HumanStateClass::LOCKED_ANIMATION);
  2844. }
  2845. }
  2846. return ;
  2847. }
  2848. ///////////////////////////////////////////////////////////////////////////
  2849. //
  2850. // STATE_IMPL_THINK(STEALTH_SOLDIER_STATE_FLYING)
  2851. //
  2852. ///////////////////////////////////////////////////////////////////////////
  2853. void
  2854. RaveshawBossGameObjClass::STATE_IMPL_THINK(STEALTH_SOLDIER_STATE_FLYING) (void)
  2855. {
  2856. //
  2857. // Check to see if the stealth soldier has been destroyed...
  2858. //
  2859. SoldierGameObj *stealth_soldier = Peek_Stealth_Soldier ();
  2860. if (stealth_soldier == NULL) {
  2861. OverallState.Set_State (OVERALL_STATE_NOTHING);
  2862. RaveshawState.Set_State (RAVESHAW_STATE_ROAR);
  2863. MoveState.Set_State (MOVE_STATE_STOP);
  2864. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  2865. Determine_New_Overall_State ();
  2866. return ;
  2867. }
  2868. const float RATE = 15.0F;
  2869. Vector3 soldier_pos;
  2870. stealth_soldier->Get_Position (&soldier_pos);
  2871. float dist = (soldier_pos - FlyingObjectDest).Length ();
  2872. float dist_percent = (dist / FlyingDist);
  2873. float percent = RATE * TimeManager::Get_Frame_Seconds ();
  2874. Vector3 move_vector = FlyingObjectVector * percent;
  2875. move_vector.Z += (dist_percent - 0.5F) * (4.0F * TimeManager::Get_Frame_Seconds ());
  2876. //
  2877. // Do the move and check to see if we hit anything
  2878. //
  2879. if (Fly_Move (stealth_soldier, move_vector)) {
  2880. //
  2881. // Kill the soldier (which should create a very large explosion)
  2882. //
  2883. OffenseObjectClass offense_obj (10000.0F, 1);
  2884. stealth_soldier->Apply_Damage_Extended (offense_obj, 1.0F);
  2885. //
  2886. // Restore our state
  2887. //
  2888. StealthSoldierState.Set_State (STEALTH_SOLDIER_STATE_NONE);
  2889. stealth_soldier->Peek_Physical_Object ()->Remove_Effect_From_Me (StealthEffect);
  2890. StealthSoldier = NULL;
  2891. }
  2892. return ;
  2893. }
  2894. ///////////////////////////////////////////////////////////////////////////
  2895. //
  2896. // STATE_IMPL_BEGIN(THROWN_OBJECT_STATE_PICKUP)
  2897. //
  2898. ///////////////////////////////////////////////////////////////////////////
  2899. void
  2900. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(THROWN_OBJECT_STATE_PICKUP) (void)
  2901. {
  2902. if (ThrownObject == NULL) {
  2903. return ;
  2904. }
  2905. //
  2906. // Get the transform of Raveshaw's right hand
  2907. //
  2908. const Matrix3D &r_hand_tm = Peek_Model ()->Get_Bone_Transform ("C R HAND");
  2909. //
  2910. // Now, calculate the object's transform relative to Raveshaw's right hand
  2911. //
  2912. Matrix3D world_to_hand_tm;
  2913. r_hand_tm.Get_Orthogonal_Inverse (world_to_hand_tm);
  2914. const Matrix3D &obj_tm = ThrownObject->Get_Transform ();
  2915. RelObjTM = world_to_hand_tm * obj_tm;
  2916. return ;
  2917. }
  2918. ///////////////////////////////////////////////////////////////////////////
  2919. //
  2920. // STATE_IMPL_THINK(THROWN_OBJECT_STATE_PICKUP)
  2921. //
  2922. ///////////////////////////////////////////////////////////////////////////
  2923. void
  2924. RaveshawBossGameObjClass::STATE_IMPL_THINK(THROWN_OBJECT_STATE_PICKUP) (void)
  2925. {
  2926. //
  2927. // Move the object with Raveshaw
  2928. //
  2929. Link_Thrown_Object_To_Hands ();
  2930. return ;
  2931. }
  2932. ///////////////////////////////////////////////////////////////////////////
  2933. //
  2934. // STATE_IMPL_BEGIN(THROWN_OBJECT_STATE_FLYING)
  2935. //
  2936. ///////////////////////////////////////////////////////////////////////////
  2937. void
  2938. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(THROWN_OBJECT_STATE_FLYING) (void)
  2939. {
  2940. Vector3 object_pos;
  2941. ThrownObject->Get_Position (&object_pos);
  2942. //
  2943. // Calculate the direction that the object will fly through the air
  2944. //
  2945. FlyingObjectDest = StarPos;
  2946. FlyingObjectVector = (StarPos - object_pos);
  2947. FlyingDist = FlyingObjectVector.Length ();
  2948. FlyingObjectVector.Normalize ();
  2949. return ;
  2950. }
  2951. ///////////////////////////////////////////////////////////////////////////
  2952. //
  2953. // STATE_IMPL_THINK(THROWN_OBJECT_STATE_FLYING)
  2954. //
  2955. ///////////////////////////////////////////////////////////////////////////
  2956. void
  2957. RaveshawBossGameObjClass::STATE_IMPL_THINK(THROWN_OBJECT_STATE_FLYING) (void)
  2958. {
  2959. const float RATE = 15.0F;
  2960. Vector3 object_pos;
  2961. ThrownObject->Get_Position (&object_pos);
  2962. float dist = (object_pos - FlyingObjectDest).Length ();
  2963. float dist_percent = (dist / FlyingDist);
  2964. float percent = RATE * TimeManager::Get_Frame_Seconds ();
  2965. Vector3 move_vector = FlyingObjectVector * percent;
  2966. move_vector.Z += (dist_percent - 0.5F) * (4.0F * TimeManager::Get_Frame_Seconds ());
  2967. //
  2968. // Do the move and check to see if we hit anything
  2969. //
  2970. if (Fly_Move (ThrownObject, move_vector)) {
  2971. //
  2972. // Fake-destroy the object
  2973. //
  2974. OffenseObjectClass offense_obj (10000.0F, 1);
  2975. ThrownObject->Completely_Damaged (offense_obj);
  2976. ThrownObject->Set_Delete_Pending ();
  2977. ThrownObject = NULL;
  2978. //
  2979. // Now, revert back to the nothing state
  2980. //
  2981. ThrownObjectState.Set_State (THROWN_OBJECT_STATE_NONE);
  2982. }
  2983. return ;
  2984. }
  2985. ///////////////////////////////////////////////////////////////////////////
  2986. //
  2987. // STATE_IMPL_BEGIN(LIGHTNING_ROD_STATE_ACTIVE)
  2988. //
  2989. ///////////////////////////////////////////////////////////////////////////
  2990. void
  2991. RaveshawBossGameObjClass::STATE_IMPL_BEGIN(LIGHTNING_ROD_STATE_ACTIVE) (void)
  2992. {
  2993. LightningRodStateTimer = 0;
  2994. return ;
  2995. }
  2996. ///////////////////////////////////////////////////////////////////////////
  2997. //
  2998. // STATE_IMPL_END(LIGHTNING_ROD_STATE_ACTIVE)
  2999. //
  3000. ///////////////////////////////////////////////////////////////////////////
  3001. void
  3002. RaveshawBossGameObjClass::STATE_IMPL_END(LIGHTNING_ROD_STATE_ACTIVE) (void)
  3003. {
  3004. //
  3005. // Hide all the arc effects
  3006. //
  3007. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  3008. PhysClass *phys_obj = ArcObjects[index]->Peek_Physical_Object ();
  3009. phys_obj->Peek_Model ()->Set_Hidden (true);
  3010. ArcLifeRemaining[index] = 0;
  3011. }
  3012. return ;
  3013. }
  3014. ///////////////////////////////////////////////////////////////////////////
  3015. //
  3016. // STATE_IMPL_THINK(LIGHTNING_ROD_STATE_ACTIVE)
  3017. //
  3018. ///////////////////////////////////////////////////////////////////////////
  3019. void
  3020. RaveshawBossGameObjClass::STATE_IMPL_THINK(LIGHTNING_ROD_STATE_ACTIVE) (void)
  3021. {
  3022. LightningRodStateTimer -= TimeManager::Get_Frame_Seconds ();
  3023. if (LightningRodStateTimer <= 0) {
  3024. LightningRodStateTimer = 0.125F;
  3025. int count = LightningRodList.Count ();
  3026. int index0 = FreeRandom.Get_Int (count - 1);
  3027. int index1 = index0 + 1;
  3028. const Matrix3D &start_tm = LightningRodList[index0]->Peek_Model ()->Get_Bone_Transform ("BBZZZT");
  3029. const Matrix3D &end_tm = LightningRodList[index1]->Peek_Model ()->Get_Bone_Transform ("BBZZZT");
  3030. Add_Lightning_Arc (start_tm.Get_Translation (), end_tm.Get_Translation ());
  3031. //
  3032. // Randomly strike the mutant
  3033. //
  3034. if (FreeRandom.Get_Int (6) == 1) {
  3035. Add_Lightning_Arc (start_tm.Get_Translation (), RaveshawPos + Vector3 (0, 0, 1.0F));
  3036. //
  3037. // Play an electric sound.
  3038. //
  3039. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Elec_Twiddler", Get_Transform ());
  3040. }
  3041. //
  3042. // Randomly strike the player
  3043. //
  3044. int star_dist = (StarPos - TIBERIUM_POS).Length ();
  3045. if (FreeRandom.Get_Int (star_dist) == 1) {
  3046. //
  3047. // Apply 5 points of "steel" damage to the player
  3048. //
  3049. OffenseObjectClass offense_obj (5.0F, 1);
  3050. COMBAT_STAR->Apply_Damage_Extended (offense_obj, 1.0F, Vector3 (-1, 0, 0));
  3051. Add_Lightning_Arc (end_tm.Get_Translation (), StarPos + Vector3 (0, 0, 1.0F));
  3052. //
  3053. // Play an electric sound.
  3054. //
  3055. WWAudioClass::Get_Instance ()->Create_Instant_Sound ("Rav_Elec_Twiddler", Matrix3D (StarPos));
  3056. }
  3057. }
  3058. //
  3059. // Hide any arc-effects that have finished
  3060. //
  3061. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  3062. if (ArcLifeRemaining[index] > 0) {
  3063. ArcLifeRemaining[index] -= TimeManager::Get_Frame_Seconds ();
  3064. if (ArcLifeRemaining[index] <= 0) {
  3065. PhysClass *phys_obj = ArcObjects[index]->Peek_Physical_Object ();
  3066. phys_obj->Peek_Model ()->Set_Hidden (true);
  3067. }
  3068. }
  3069. }
  3070. return ;
  3071. }
  3072. ///////////////////////////////////////////////////////////////////////////
  3073. //
  3074. // Apply_Bone_Collision_Damage
  3075. //
  3076. ///////////////////////////////////////////////////////////////////////////
  3077. bool
  3078. RaveshawBossGameObjClass::Apply_Bone_Collision_Damage (float damage_scale, const char *bone_name)
  3079. {
  3080. int bone_index = Peek_Model ()->Get_Bone_Index (bone_name);
  3081. //
  3082. // Lookup the current and last positions of the bone in question
  3083. //
  3084. Matrix3D last_bone_tm;
  3085. Matrix3D curr_bone_tm;
  3086. ((Animatable3DObjClass *)Peek_Model ())->Simple_Evaluate_Bone (bone_index, &curr_bone_tm);
  3087. ((Animatable3DObjClass *)Peek_Model ())->Simple_Evaluate_Bone (bone_index, LastMeleeAnimFrame, &last_bone_tm);
  3088. //
  3089. // Calculate where the bone moved
  3090. //
  3091. Vector3 move_vector = curr_bone_tm.Get_Translation () - last_bone_tm.Get_Translation ();
  3092. //
  3093. // Build a box around the bone that we can use for collision detection
  3094. //
  3095. AABoxClass bone_box;
  3096. bone_box.Center = curr_bone_tm.Get_Translation ();
  3097. bone_box.Extent.Set (0.2F, 0.2F, 0.2F);
  3098. //
  3099. // Try to find where (if anywhere) we hit the player
  3100. //
  3101. CastResultStruct result;
  3102. result.ComputeContactPoint = true;
  3103. AABoxCollisionTestClass col_test (bone_box, move_vector, &result, COLLISION_TYPE_PROJECTILE);
  3104. //
  3105. // Find where we hit
  3106. //
  3107. bool retval = COMBAT_STAR->Peek_Model ()->Cast_AABox (col_test);
  3108. if (retval) {
  3109. //
  3110. // Dig the name of the mesh out
  3111. //
  3112. StringClass obj_name;
  3113. if (col_test.CollidedRenderObj != NULL) {
  3114. obj_name = col_test.CollidedRenderObj->Get_Name ();
  3115. }
  3116. //
  3117. // Apply 10 points of "steel" damage to the player
  3118. //
  3119. OffenseObjectClass offense_obj (damage_scale, 1);
  3120. COMBAT_STAR->Apply_Damage_Extended (offense_obj, 1.0F, Vector3 (-1, 0, 0), obj_name);
  3121. //
  3122. // Knock the player back a little bit
  3123. //
  3124. Vector3 delta_vector = move_vector;
  3125. delta_vector.Normalize ();
  3126. COMBAT_STAR->Peek_Physical_Object ()->As_Phys3Class ()->Collide (delta_vector * 0.25F);
  3127. if (delta_vector.Z > 0.0F) {
  3128. delta_vector.Z = 0.5F;
  3129. delta_vector.Normalize ();
  3130. COMBAT_STAR->Peek_Physical_Object ()->As_Phys3Class ()->Apply_Impulse (delta_vector * 2.0F);
  3131. }
  3132. //
  3133. // Play the hit sound...
  3134. //
  3135. Attach_Sound ("Fight Impact Sound Twiddler", "ROOTTRANSFORM");
  3136. }
  3137. return retval;
  3138. }
  3139. ///////////////////////////////////////////////////////////////////////////
  3140. //
  3141. // Get_Distance_From_Ground
  3142. //
  3143. ///////////////////////////////////////////////////////////////////////////
  3144. float
  3145. RaveshawBossGameObjClass::Get_Distance_From_Ground (void)
  3146. {
  3147. const float MAX_DISTANCE = 100.0F;
  3148. float distance = 0.0F;
  3149. //
  3150. // Determine the start and end positions of the ray
  3151. //
  3152. Vector3 start;
  3153. Get_Position (&start);
  3154. Vector3 end = start - Vector3 (0, 0, MAX_DISTANCE);
  3155. LineSegClass ray (start, end);
  3156. //
  3157. // Cast the ray into the world
  3158. //
  3159. CastResultStruct res;
  3160. PhysRayCollisionTestClass raytest (ray, &res, DEFAULT_COLLISION_GROUP, COLLISION_TYPE_PHYSICAL);
  3161. Peek_Physical_Object ()->Inc_Ignore_Counter ();
  3162. COMBAT_SCENE->Cast_Ray (raytest);
  3163. Peek_Physical_Object ()->Dec_Ignore_Counter ();
  3164. //
  3165. // Calculate where in the world this would hit
  3166. //
  3167. if (res.StartBad == false) {
  3168. distance = (res.Fraction * MAX_DISTANCE);
  3169. }
  3170. return distance;
  3171. }
  3172. ///////////////////////////////////////////////////////////////////////////
  3173. //
  3174. // Create_Stealth_Soldier
  3175. //
  3176. ///////////////////////////////////////////////////////////////////////////
  3177. void
  3178. RaveshawBossGameObjClass::Create_Stealth_Soldier (const Matrix3D &tm)
  3179. {
  3180. //
  3181. // Create the stealth soldier
  3182. //
  3183. PhysicalGameObj *phys_game_obj = ObjectLibraryManager::Create_Object ("Raveshaw Boss Fodder");
  3184. WWASSERT (phys_game_obj != NULL);
  3185. StealthSoldier = phys_game_obj;
  3186. //
  3187. // Position the stealth soldier accordingly
  3188. //
  3189. SoldierGameObj *soldier = phys_game_obj->As_SoldierGameObj ();
  3190. soldier->Set_Transform (tm);
  3191. //
  3192. // Configure the stealth effect to be "on" (stealthed)
  3193. //
  3194. StealthEffect->Set_Current_State (1.0F);
  3195. StealthEffect->Set_Target_State (0.0F);
  3196. //
  3197. // Add the effect to the object
  3198. //
  3199. soldier->Peek_Physical_Object ()->Add_Effect_To_Me (StealthEffect);
  3200. //
  3201. // Disable physics for this soldier
  3202. //
  3203. soldier->Peek_Physical_Object ()->Enable_Objects_Simulation (false);
  3204. soldier->Start_Observers ();
  3205. return ;
  3206. }
  3207. ///////////////////////////////////////////////////////////////////////////
  3208. //
  3209. // Link_Thrown_Object_To_Hands
  3210. //
  3211. ///////////////////////////////////////////////////////////////////////////
  3212. void
  3213. RaveshawBossGameObjClass::Link_Thrown_Object_To_Hands (void)
  3214. {
  3215. if (ThrownObject == NULL) {
  3216. return ;
  3217. }
  3218. //
  3219. // Get the transforms of Raveshaw's hands
  3220. //
  3221. const Matrix3D &r_hand_tm = Peek_Model ()->Get_Bone_Transform ("C R HAND");
  3222. const Matrix3D &l_hand_tm = Peek_Model ()->Get_Bone_Transform ("C L HAND");
  3223. //Vector3 z_axis = (l_hand_tm.Get_Translation () - r_hand_tm.Get_Translation ());
  3224. //z_axis.Normalize ();
  3225. Vector3 r_hand_pos = r_hand_tm.Get_Translation ();
  3226. Vector3 l_hand_pos = l_hand_tm.Get_Translation ();
  3227. Vector3 delta_vector = l_hand_pos - r_hand_pos;
  3228. Matrix3D obj_tm;
  3229. //obj_tm.Look_At (r_hand_pos, r_hand_pos - delta_vector, 0);
  3230. Matrix3D::Multiply (r_hand_tm, RelObjTM, &obj_tm);
  3231. ThrownObject->Set_Transform (obj_tm);
  3232. return ;
  3233. }
  3234. ///////////////////////////////////////////////////////////////////////////
  3235. //
  3236. // Link_Player_To_Hands
  3237. //
  3238. ///////////////////////////////////////////////////////////////////////////
  3239. void
  3240. RaveshawBossGameObjClass::Link_Player_To_Hands (void)
  3241. {
  3242. if (COMBAT_STAR == NULL) {
  3243. return ;
  3244. }
  3245. //
  3246. // Get the transform of Raveshaw's hand
  3247. //
  3248. const Matrix3D &hand_tm = Peek_Model ()->Get_Bone_Transform ("C L HAND");
  3249. const Matrix3D &neck_tm = COMBAT_STAR->Peek_Model ()->Get_Bone_Transform ("C NECK");
  3250. const Matrix3D &soldier_tm = COMBAT_STAR->Get_Transform ();
  3251. //
  3252. // Determine where to position the stealth soldier so he's embedded in Raveshaw's hand
  3253. //
  3254. Vector3 hand_pos = hand_tm.Get_Translation ();
  3255. Vector3 delta_pos = neck_tm.Get_Translation () - soldier_tm.Get_Translation ();
  3256. Vector3 new_pos = hand_pos - delta_pos;
  3257. //
  3258. // Disable collision on Raveshaw
  3259. //
  3260. Peek_Physical_Object ()->Inc_Ignore_Counter ();
  3261. COMBAT_STAR->Peek_Physical_Object ()->Inc_Ignore_Counter ();
  3262. //
  3263. // Get the player's collision box
  3264. //
  3265. AABoxClass collision_box;
  3266. collision_box = COMBAT_STAR->Peek_Physical_Object ()->As_HumanPhysClass ()->Get_Collision_Box ();
  3267. collision_box.Center += StarPos;
  3268. //
  3269. // Calculate what vector we'll be teleporting the player through
  3270. //
  3271. Vector3 vector = (new_pos - StarPos);
  3272. //
  3273. // Check to see if we would hit something if we do this
  3274. //
  3275. CastResultStruct result;
  3276. PhysAABoxCollisionTestClass col_test (collision_box, vector, &result, DEFAULT_COLLISION_GROUP, COLLISION_TYPE_PHYSICAL);
  3277. bool retval = COMBAT_SCENE->Cast_AABox (col_test);
  3278. if (retval == false && result.StartBad == false && result.Fraction == 1.0F) {
  3279. //
  3280. // New position should be fine, so allow the position change
  3281. //
  3282. Matrix3D new_soldier_tm (new_pos);
  3283. COMBAT_STAR->Set_Transform (new_soldier_tm);
  3284. }
  3285. //
  3286. // Restore collision on Raveshaw
  3287. //
  3288. Peek_Physical_Object ()->Dec_Ignore_Counter ();
  3289. COMBAT_STAR->Peek_Physical_Object ()->Dec_Ignore_Counter ();
  3290. //
  3291. // Get the target relative to the head
  3292. //
  3293. //Vector3 rav_head_pos = Peek_Model ()->Get_Bone_Transform ("C HEAD").Get_Translation ();
  3294. //COMBAT_STAR->Set_Targeting (rav_head_pos);
  3295. /*Vector3 rav_head_rel;
  3296. Matrix3D::Inverse_Transform_Vector (new_soldier_tm, rav_head_pos, &rav_head_rel);
  3297. float angle = ::atan2 (rav_head_rel.Y, rav_head_rel.X);
  3298. new_soldier_tm.Rotate_Z (angle - DEG_TO_RADF (90.0F));*/
  3299. //
  3300. // Choose a random orientation for the soldier
  3301. //
  3302. //new_soldier_tm.Rotate_Z (WWMath::Random_Float (0, DEG_TO_RADF (319.0F)));
  3303. /*Matrix3D world_to_soldier_tm;
  3304. soldier_tm.Get_Orthogonal_Inverse (world_to_soldier_tm);
  3305. Matrix3D neck_rel_to_sol_tm = neck_tm * world_to_soldier_tm;
  3306. Matrix3D sol_rel_to_neck_tm;
  3307. neck_rel_to_sol_tm.Get_Orthogonal_Inverse (sol_rel_to_neck_tm);
  3308. Matrix3D new_soldier_tm (hand_tm * sol_rel_to_neck_tm);*/
  3309. //Matrix3D test_tm = hand_tm * sol_rel_to_neck_tm;
  3310. //Matrix3D new_soldier_tm (test_tm.Get_Translation ());
  3311. //new_soldier_tm = hand_tm * sol_rel_to_neck_tm;
  3312. /*Matrix3D soldier_to_neck_tm;
  3313. neck_to_soldier_tm.Get_Orthogonal_Inverse (soldier_to_neck_tm);
  3314. Matrix3D world_to_neck_tm;
  3315. neck_tm.Get_Orthogonal_Inverse (world_to_neck_tm);
  3316. Matrix3D neck_to_soldier_tm = soldier_tm * world_to_neck_tm;
  3317. Matrix3D
  3318. Matrix3D new_soldier_tm = (hand_tm * neck_to_soldier_tm);*/
  3319. //COMBAT_STAR->Set_Transform (new_soldier_tm);
  3320. return ;
  3321. }
  3322. ///////////////////////////////////////////////////////////////////////////
  3323. //
  3324. // Link_Stealth_Soldier_To_Hand
  3325. //
  3326. ///////////////////////////////////////////////////////////////////////////
  3327. void
  3328. RaveshawBossGameObjClass::Link_Stealth_Soldier_To_Hand (void)
  3329. {
  3330. //
  3331. // Check to see if the stealth soldier has been destroyed...
  3332. //
  3333. SoldierGameObj *stealth_soldier = Peek_Stealth_Soldier ();
  3334. if (stealth_soldier == NULL) {
  3335. return ;
  3336. }
  3337. //
  3338. // Get the transform of Raveshaw's hand
  3339. //
  3340. const Matrix3D &hand_tm = Peek_Model ()->Get_Bone_Transform ("C L HAND");
  3341. const Matrix3D &neck_tm = stealth_soldier->Peek_Model ()->Get_Bone_Transform ("C NECK");
  3342. const Matrix3D &soldier_tm = stealth_soldier->Get_Transform ();
  3343. //
  3344. // Determine where to position the stealth soldier so he's embedded in Raveshaw's hand
  3345. //
  3346. Vector3 hand_pos = hand_tm.Get_Translation ();
  3347. Vector3 delta_pos = neck_tm.Get_Translation () - soldier_tm.Get_Translation ();
  3348. Vector3 new_pos = hand_pos - delta_pos;
  3349. Matrix3D new_soldier_tm (new_pos);
  3350. //
  3351. // Choose a random orientation for the soldier
  3352. //
  3353. //new_soldier_tm.Rotate_Z (WWMath::Random_Float (0, DEG_TO_RADF (319.0F)));
  3354. /*Matrix3D world_to_soldier_tm;
  3355. soldier_tm.Get_Orthogonal_Inverse (world_to_soldier_tm);
  3356. Matrix3D neck_rel_to_sol_tm = neck_tm * world_to_soldier_tm;
  3357. Matrix3D sol_rel_to_neck_tm;
  3358. neck_rel_to_sol_tm.Get_Orthogonal_Inverse (sol_rel_to_neck_tm);
  3359. Matrix3D new_soldier_tm (hand_tm * sol_rel_to_neck_tm);*/
  3360. //Matrix3D test_tm = hand_tm * sol_rel_to_neck_tm;
  3361. //Matrix3D new_soldier_tm (test_tm.Get_Translation ());
  3362. //new_soldier_tm = hand_tm * sol_rel_to_neck_tm;
  3363. /*Matrix3D soldier_to_neck_tm;
  3364. neck_to_soldier_tm.Get_Orthogonal_Inverse (soldier_to_neck_tm);
  3365. Matrix3D world_to_neck_tm;
  3366. neck_tm.Get_Orthogonal_Inverse (world_to_neck_tm);
  3367. Matrix3D neck_to_soldier_tm = soldier_tm * world_to_neck_tm;
  3368. Matrix3D
  3369. Matrix3D new_soldier_tm = (hand_tm * neck_to_soldier_tm);*/
  3370. stealth_soldier->Set_Transform (new_soldier_tm);
  3371. return ;
  3372. }
  3373. ///////////////////////////////////////////////////////////////////////////
  3374. //
  3375. // Fly_Move
  3376. //
  3377. ///////////////////////////////////////////////////////////////////////////
  3378. bool
  3379. RaveshawBossGameObjClass::Fly_Move (PhysicalGameObj *game_obj, const Vector3 &vector)
  3380. {
  3381. Vector3 curr_pos;
  3382. game_obj->Get_Position (&curr_pos);
  3383. //
  3384. // Get the object's collision box
  3385. //
  3386. AABoxClass collision_box;
  3387. if (game_obj->As_SoldierGameObj () != NULL) {
  3388. collision_box = game_obj->Peek_Physical_Object ()->As_HumanPhysClass ()->Get_Collision_Box ();
  3389. collision_box.Center += curr_pos;
  3390. } else {
  3391. collision_box = game_obj->Peek_Model ()->Get_Bounding_Box ();
  3392. }
  3393. if (game_obj != COMBAT_STAR) {
  3394. collision_box.Extent.Z -= 0.25F;
  3395. }
  3396. //
  3397. // Disable collision on Raveshaw
  3398. //
  3399. Peek_Physical_Object ()->Inc_Ignore_Counter ();
  3400. game_obj->Peek_Physical_Object ()->Inc_Ignore_Counter ();
  3401. //
  3402. // Check to see if we've hit something
  3403. //
  3404. CastResultStruct result;
  3405. PhysAABoxCollisionTestClass col_test (collision_box, vector, &result, DEFAULT_COLLISION_GROUP, COLLISION_TYPE_PHYSICAL);
  3406. //
  3407. // Find where we hit
  3408. //
  3409. bool retval = COMBAT_SCENE->Cast_AABox (col_test);
  3410. if (result.StartBad == false) {
  3411. //
  3412. // Calculate where to move to...
  3413. //
  3414. Vector3 new_pos = curr_pos + (vector * (result.Fraction * 0.99F));
  3415. //
  3416. // Move the object
  3417. //
  3418. game_obj->Set_Position (new_pos);
  3419. }
  3420. //
  3421. // Restore collision to Raveshaw
  3422. //
  3423. Peek_Physical_Object ()->Dec_Ignore_Counter ();
  3424. game_obj->Peek_Physical_Object ()->Dec_Ignore_Counter ();
  3425. return retval;
  3426. }
  3427. ///////////////////////////////////////////////////////////////////////////
  3428. //
  3429. // Find_Object_To_Throw
  3430. //
  3431. ///////////////////////////////////////////////////////////////////////////
  3432. SimpleGameObj *
  3433. RaveshawBossGameObjClass::Find_Object_To_Throw (void)
  3434. {
  3435. if (COMBAT_STAR == NULL) {
  3436. return NULL;
  3437. }
  3438. SimpleGameObj *best_object = NULL;
  3439. float best_object_rating = 100.0F;
  3440. //
  3441. // Loop over all the game objects in the world (looking for simple game objects)
  3442. //
  3443. SLNode<BaseGameObj> *obj_node = NULL;
  3444. for (obj_node = GameObjManager::Get_Game_Obj_List ()->Head (); obj_node; obj_node = obj_node->Next ()) {
  3445. //
  3446. // Is this a simple game object?
  3447. //
  3448. PhysicalGameObj *phys_game_obj = obj_node->Data ()->As_PhysicalGameObj ();
  3449. if (phys_game_obj != NULL && phys_game_obj->As_SimpleGameObj () != NULL) {
  3450. SimpleGameObj *object = phys_game_obj->As_SimpleGameObj ();
  3451. if (object != NULL) {
  3452. //
  3453. // Is this one of Raveshaw's throwable objects?
  3454. //
  3455. const StringClass &name = object->Get_Definition ().Get_Name ();
  3456. if (::strstr (name, "(Raveshaw Ammo)") != NULL) {
  3457. //
  3458. // Get the position of the object
  3459. //
  3460. Vector3 object_pos;
  3461. object->Get_Position (&object_pos);
  3462. //
  3463. // Is this object in the boss area?
  3464. //
  3465. object_pos.Z = 0;
  3466. //
  3467. // Calculate how far this object is from Raveshaw and the player
  3468. //
  3469. float dist_to_me = (object_pos - RaveshawPos).Length () / 10.0F;
  3470. float dist_to_star = (object_pos - StarPos).Length () / 10.0F;
  3471. dist_to_star = WWMath::Clamp (1.0F - dist_to_star, 0.0F, 1.0F);
  3472. //
  3473. // Is this the object that's closest to Raveshaw and farthest from the player?
  3474. //
  3475. float rating = (dist_to_me * 0.5F) + (dist_to_star * 0.5F);
  3476. if (rating < best_object_rating) {
  3477. best_object = object;
  3478. best_object_rating = rating;
  3479. }
  3480. }
  3481. }
  3482. }
  3483. }
  3484. return best_object;
  3485. }
  3486. ///////////////////////////////////////////////////////////////////////////
  3487. //
  3488. // Determine_New_Overall_State
  3489. //
  3490. ///////////////////////////////////////////////////////////////////////////
  3491. void
  3492. RaveshawBossGameObjClass::Determine_New_Overall_State (void)
  3493. {
  3494. float health = DefenseObject.Get_Health ();
  3495. float health_percent = health / DefenseObject.Get_Health_Max ();
  3496. if (health_percent <= 0.05F) {
  3497. //
  3498. // Retreat to the catwalk if we're mostly damaged
  3499. //
  3500. if ( OverallState.Get_State () != OVERALL_STATE_JUMP_TO_CATWALK ||
  3501. OverallState.Get_State () != OVERALL_STATE_ON_CATWALK ||
  3502. OverallState.Get_State () != OVERALL_STATE_DEATH_SEQUENCE)
  3503. {
  3504. OverallState.Set_State (OVERALL_STATE_JUMP_TO_CATWALK);
  3505. }
  3506. } else {
  3507. //
  3508. // Should he heal himself?
  3509. //
  3510. int possibility = (10.0F * health_percent) + 0.5F;
  3511. bool go_heal = (health_percent <= 0.75F && possibility > 0) && (FreeRandom.Get_Int (possibility) == 0);
  3512. if (go_heal) {
  3513. OverallState.Set_State (OVERALL_STATE_HEALING);
  3514. } else {
  3515. //
  3516. // How far away is the player?
  3517. //
  3518. float dist2 = (RaveshawPos - StarPos).Length2 ();
  3519. //
  3520. // Roll a random die to determine which action to take
  3521. //
  3522. int choice = FreeRandom.Get_Int (100);
  3523. if (choice < 35 && dist2 > 16.0F) {
  3524. OverallState.Set_State (OVERALL_STATE_THROWING_SOLDIER);
  3525. } else if (choice < 60 && (ThrownObject == NULL)) {
  3526. OverallState.Set_State (OVERALL_STATE_THROWING_OBJECT);
  3527. } else if (choice < 80) {
  3528. OverallState.Set_State (OVERALL_STATE_CHASE_STAR);
  3529. } else {
  3530. OverallState.Set_State (OVERALL_STATE_JUMP_TO_CATWALK);
  3531. }
  3532. }
  3533. }
  3534. return ;
  3535. }
  3536. ///////////////////////////////////////////////////////////////////////////
  3537. //
  3538. // Jump_To_Point
  3539. //
  3540. ///////////////////////////////////////////////////////////////////////////
  3541. void
  3542. RaveshawBossGameObjClass::Jump_To_Point (const Vector3 &pos)
  3543. {
  3544. //
  3545. // Begin the jump state (if necessary)
  3546. //
  3547. if (JumpState.Get_State () == JUMP_STATE_NONE) {
  3548. CurrentJumpToPos = pos;
  3549. JumpState.Set_State (JUMP_STATE_CROUCHING);
  3550. }
  3551. return ;
  3552. }
  3553. ///////////////////////////////////////////////////////////////////////////
  3554. //
  3555. // Collect_Lightning_Rods
  3556. //
  3557. ///////////////////////////////////////////////////////////////////////////
  3558. void
  3559. RaveshawBossGameObjClass::Collect_Lightning_Rods (void)
  3560. {
  3561. LightningRodList.Delete_All ();
  3562. //
  3563. // Compute the box where the lightning rods in question should live
  3564. //
  3565. AABoxClass box;
  3566. box.Center = TIBERIUM_POS;
  3567. box.Extent.Set (40.0F, 40.0F, 20.0F);
  3568. //
  3569. // Collect all the static objects in this box
  3570. //
  3571. NonRefPhysListClass obj_list;
  3572. COMBAT_SCENE->Collect_Objects (box, true, false, &obj_list);
  3573. //
  3574. // Loop over all the objects
  3575. //
  3576. NonRefPhysListIterator it (&obj_list);
  3577. for (it.First (); !it.Is_Done (); it.Next ()) {
  3578. DamageableStaticPhysClass *phys_obj = it.Peek_Obj ()->As_DamageableStaticPhysClass ();
  3579. //
  3580. // Add this object to our list
  3581. //
  3582. if (phys_obj != NULL) {
  3583. if (phys_obj->Peek_Model ()->Get_Bone_Index ("BBZZZT") > 0) {
  3584. LightningRodList.Add (phys_obj);
  3585. }
  3586. }
  3587. }
  3588. //
  3589. // Sort the lightning rods based on the angle they make with the tiberium
  3590. //
  3591. int rod_count = LightningRodList.Count ();
  3592. if (rod_count > 0) {
  3593. ::qsort (&LightningRodList[0], rod_count, sizeof (DamageableStaticPhysClass *), fnSortLightningRodsCallback);
  3594. }
  3595. return ;
  3596. }
  3597. ///////////////////////////////////////////////////////////////////////////
  3598. //
  3599. // Create_Arc_Effects
  3600. //
  3601. ///////////////////////////////////////////////////////////////////////////
  3602. void
  3603. RaveshawBossGameObjClass::Create_Arc_Effects (void)
  3604. {
  3605. //
  3606. // Create the simple game object's that we'll use to display the lightning effect
  3607. //
  3608. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  3609. ArcObjects[index] = (SimpleGameObj *)ObjectLibraryManager::Create_Object ("Arc Effect");
  3610. }
  3611. return ;
  3612. }
  3613. ///////////////////////////////////////////////////////////////////////////
  3614. //
  3615. // Prepare_Arc_Effect_Data
  3616. //
  3617. ///////////////////////////////////////////////////////////////////////////
  3618. void
  3619. RaveshawBossGameObjClass::Prepare_Arc_Effect_Data (void)
  3620. {
  3621. //
  3622. // Create the simple game object's that we'll use to display the lightning effect
  3623. //
  3624. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  3625. if ( ArcObjects[index]->Peek_Physical_Object () != NULL &&
  3626. ArcObjects[index]->Peek_Physical_Object ()->Peek_Model () != NULL)
  3627. {
  3628. ArcObjects[index]->Peek_Physical_Object ()->Peek_Model ()->Set_Hidden (true);
  3629. }
  3630. ArcLifeRemaining[index] = 0;
  3631. }
  3632. //
  3633. // Get information about the model
  3634. //
  3635. SimpleGameObj *temp_obj = (SimpleGameObj *)ObjectLibraryManager::Create_Object ("Arc Effect");
  3636. if (temp_obj != NULL && temp_obj->Peek_Model () != NULL) {
  3637. RenderObjClass *model = temp_obj->Peek_Model ();
  3638. //
  3639. // Store the original transforms of each bone
  3640. //
  3641. for (int index = 0; index < BONE_COUNT; index ++) {
  3642. Bones[index] = model->Get_Bone_Transform (ARC_BONE_NAMES[index]);
  3643. }
  3644. //
  3645. // Lookup the original transform of the end-bone
  3646. //
  3647. int end_index = model->Get_Bone_Index ("bone_end");
  3648. EndTM = model->Get_Bone_Transform (end_index);
  3649. //
  3650. // Get rid of the temporary object
  3651. //
  3652. temp_obj->Peek_Model ()->Set_Hidden (true);
  3653. temp_obj->Set_Delete_Pending ();
  3654. }
  3655. return ;
  3656. }
  3657. //BBZZZT
  3658. ///////////////////////////////////////////////////////////////////////////
  3659. //
  3660. // Add_Lightning_Arc
  3661. //
  3662. ///////////////////////////////////////////////////////////////////////////
  3663. void
  3664. RaveshawBossGameObjClass::Add_Lightning_Arc (const Vector3 &start_point, const Vector3 &end_point)
  3665. {
  3666. //
  3667. // Try to find an available welding-arc
  3668. //
  3669. for (int index = 0; index < ARC_OBJ_COUNT; index ++) {
  3670. if ((ArcLifeRemaining[index] <= 0)) {
  3671. //
  3672. // Get the model of the object we'll be displaying
  3673. //
  3674. RenderObjClass *model = ArcObjects[index]->Peek_Physical_Object ()->Peek_Model ();
  3675. //
  3676. // Make the object "look" at its endpoint
  3677. //
  3678. Matrix3D start_tm;
  3679. start_tm.Obj_Look_At (start_point, end_point, 0);
  3680. ArcObjects[index]->Peek_Physical_Object ()->Set_Transform (start_tm);
  3681. //
  3682. // Now scale the bone's that control the length of the arc so it
  3683. // will fit perfectly between the start and endpoints.
  3684. //
  3685. for (int bone_index = 0; bone_index < BONE_COUNT; bone_index ++) {
  3686. float percent = WWMath::Fabs (Bones[bone_index].Get_Translation ().X / EndTM.Get_Translation ().X);
  3687. Vector3 new_pos = start_point + (end_point - start_point) * percent;
  3688. //
  3689. // Calculate the world space position of the bone
  3690. //
  3691. Vector3 world_space_pos = start_tm * Bones[bone_index].Get_Translation ();
  3692. Vector3 world_space_offset = new_pos - world_space_pos;
  3693. Matrix3D bone_tm (world_space_offset);
  3694. //
  3695. // Control the bone
  3696. //
  3697. int bone_id = model->Get_Bone_Index (ARC_BONE_NAMES[bone_index]);
  3698. model->Capture_Bone (bone_id);
  3699. model->Control_Bone (bone_id, bone_tm, true);
  3700. }
  3701. //
  3702. // Calculate the world space position of the endpoint
  3703. //
  3704. Vector3 world_space_end_pos = start_tm * EndTM.Get_Translation ();
  3705. Vector3 world_space_offset = end_point - world_space_end_pos;
  3706. Matrix3D end_tm (world_space_offset);
  3707. //
  3708. // Control the ending bone
  3709. //
  3710. int end_index = model->Get_Bone_Index ("bone_end");
  3711. model->Capture_Bone (end_index);
  3712. model->Control_Bone (end_index, end_tm, true);
  3713. //
  3714. // Start the animation
  3715. //
  3716. ArcLifeRemaining[index] = 3.0F;
  3717. HAnimClass *anim = model->Peek_Animation ();
  3718. if (anim != NULL) {
  3719. model->Set_Animation (anim, 0, RenderObjClass::ANIM_MODE_ONCE);
  3720. ArcLifeRemaining[index] = anim->Get_Total_Time ();
  3721. }
  3722. //
  3723. // Show the model
  3724. //
  3725. model->Set_Hidden (false);
  3726. break;
  3727. }
  3728. }
  3729. return ;
  3730. }
  3731. ////////////////////////////////////////////////////////////////
  3732. //
  3733. // fnSortLightningRodsCallback
  3734. //
  3735. ////////////////////////////////////////////////////////////////
  3736. int __cdecl
  3737. RaveshawBossGameObjClass::fnSortLightningRodsCallback
  3738. (
  3739. const void *elem1,
  3740. const void *elem2
  3741. )
  3742. {
  3743. WWASSERT (elem1 != NULL);
  3744. WWASSERT (elem2 != NULL);
  3745. DamageableStaticPhysClass *rod1 = *((DamageableStaticPhysClass **)elem1);
  3746. DamageableStaticPhysClass *rod2 = *((DamageableStaticPhysClass **)elem2);
  3747. //
  3748. // Sort the rods based on the angle they make around the tiberium
  3749. //
  3750. int result = 0;
  3751. if (rod1 != rod2) {
  3752. Vector3 rod1_pos;
  3753. Vector3 rod2_pos;
  3754. rod1->Get_Position (&rod1_pos);
  3755. rod2->Get_Position (&rod2_pos);
  3756. rod1_pos -= TIBERIUM_POS;
  3757. rod2_pos -= TIBERIUM_POS;
  3758. //
  3759. // Compute the angle assuming the tiberium to be the center of a circle
  3760. //
  3761. float angle1 = WWMath::Atan2 (rod1_pos.Y, rod1_pos.X);
  3762. float angle2 = WWMath::Atan2 (rod2_pos.Y, rod2_pos.X);
  3763. angle1 = WWMath::Wrap (angle1 + DEG_TO_RADF (90.0F), 0.0F, DEG_TO_RADF (360.0F));
  3764. angle2 = WWMath::Wrap (angle2 + DEG_TO_RADF (90.0F), 0.0F, DEG_TO_RADF (360.0F));
  3765. //
  3766. // Sort based on this angle
  3767. //
  3768. if (angle1 < angle2) {
  3769. result = -1;
  3770. } else if (angle1 > angle2) {
  3771. result = 1;
  3772. } else {
  3773. result = 0;
  3774. }
  3775. }
  3776. return result;
  3777. }
  3778. ///////////////////////////////////////////////////////////////////////////
  3779. //
  3780. // Find_Death_Facing_Pos
  3781. //
  3782. ///////////////////////////////////////////////////////////////////////////
  3783. void
  3784. RaveshawBossGameObjClass::Find_Death_Facing_Pos (Vector3 *facing_pos)
  3785. {
  3786. float best_dist2 = 99999.0F;
  3787. //
  3788. // Get the catwalk waypath
  3789. //
  3790. WaypathClass *waypath = PathfindClass::Get_Instance ()->Find_Waypath (CATWALK_WAYPATH_ID);
  3791. WWASSERT (waypath != NULL);
  3792. //
  3793. // Now find the closest point which is in-between the waypath points
  3794. //
  3795. for (int index = 0; index < waypath->Get_Point_Count (); index ++) {
  3796. //
  3797. // Determine what the current and next waypath points are
  3798. //
  3799. int curr_index = index;
  3800. int next_index = index + 1;
  3801. if (index + 1 >= waypath->Get_Point_Count ()) {
  3802. next_index = 0;
  3803. }
  3804. //
  3805. // Get the position of the current and next waypoint
  3806. //
  3807. Vector3 curr_waypath_pos = waypath->Get_Point (curr_index)->Get_Position ();
  3808. Vector3 next_waypath_pos = waypath->Get_Point (next_index)->Get_Position ();
  3809. //
  3810. // Evaluate this jump to position (is it the closest?)
  3811. //
  3812. Vector3 jump_to_pos = curr_waypath_pos + ((next_waypath_pos - curr_waypath_pos) * 0.5F);
  3813. Vector3 dir_vector = (RaveshawPos - jump_to_pos);
  3814. dir_vector.Z = 0;
  3815. float dist2 = dir_vector.Length2 ();
  3816. if (dist2 < best_dist2) {
  3817. best_dist2 = dist2;
  3818. (*facing_pos) = curr_waypath_pos;
  3819. }
  3820. }
  3821. return ;
  3822. }