| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Combat/soldier.cpp $*
- * *
- * $Author:: Byon_g $*
- * *
- * $Modtime:: 3/29/02 4:58p $*
- * *
- * $Revision:: 570 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "soldier.h"
- #include "debug.h"
- #include "pscene.h"
- #include "combat.h"
- #include "weapons.h"
- #include "damage.h"
- #include "humanphys.h"
- #include "animcontrol.h"
- #include "rendobj.h"
- #include "wwpacket.h"
- #include "assets.h"
- #include "gameobjmanager.h"
- #include "vehicle.h"
- #include "c4.h"
- #include "objlibrary.h"
- #include "physicalgameobj.h"
- #include "persistfactory.h"
- #include "combatchunkid.h"
- #include "definition.h"
- #include "simpledefinitionfactory.h"
- #include "wwhack.h"
- #include "surfaceeffects.h"
- #include "weaponmanager.h"
- #include "weaponbag.h"
- #include "physcoltest.h"
- #include "htree.h"
- #include "animobj.h"
- #include "wwaudio.h"
- #include "soldierobserver.h"
- #include "playertype.h"
- #include "crandom.h"
- #include "ccamera.h"
- #include "bitpackids.h"
- #include "translatedb.h"
- #include "translateobj.h"
- #include "hlod.h"
- #include "audiblesound.h"
- #include "wwprofile.h"
- #include "globalsettings.h"
- #include "colors.h"
- #include "input.h"
- #include "gametype.h"
- #include "messagewindow.h"
- #include "conversationmgr.h"
- #include "activeconversation.h"
- #include "bones.h"
- #include "dynamicspeechanim.h"
- #include "hudinfo.h"
- #include "powerup.h"
- #include "diaglog.h"
- #include "vistable.h"
- #include "crandom.h"
- #include "transitioneffect.h"
- #include "combatmaterialeffectmanager.h"
- #include "explosion.h"
- #include "playerdata.h"
- #include "encyclopediamgr.h"
- #include "apppackettypes.h"
- #include "hud.h"
- #include "unitcoordinationzonemgr.h"
- #include "specialbuilds.h"
- #include "weaponview.h"
- #include "ffactory.h"
- #include "realcrc.h"
- /*
- **
- */
- #define GUN_BONE_NAME "GUNBONE"
- #define BACK_GUN_BONE_NAME "BACKGUNBONE"
- #define POKE_ANGLE DEG_TO_RAD( 22 )
- #define AMBUSH_DAMAGE_SCALE 1
- const float EMOT_ICON_HEIGHT = 2.0F;
- /*
- ** SoldierGameObjDef
- */
- DECLARE_FORCE_LINK( Soldier )
- SimplePersistFactoryClass<SoldierGameObjDef, CHUNKID_GAME_OBJECT_DEF_SOLDIER> _SoldierGameObjDefPersistFactory;
- DECLARE_DEFINITION_FACTORY(SoldierGameObjDef, CLASSID_GAME_OBJECT_DEF_SOLDIER, "Soldier") _SoldierGameObjDefDefFactory;
- SoldierGameObjDef::SoldierGameObjDef( void ) :
- TurnRate( DEG_TO_RADF( 360.0f ) ),
- JumpVelocity( 2 ),
- SkeletonHeight( 0 ),
- SkeletonWidth( 0 ),
- UseInnateBehavior( true ),
- InnateAggressiveness( 0.5f ),
- InnateTakeCoverProbability( 0.5f ),
- InnateIsStationary( false ),
- HumanAnimOverrideDefID( 0 ),
- HumanLoiterCollectionDefID( 0 ),
- DeathSoundPresetID( 0 )
- {
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_ANGLE, TurnRate );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FLOAT, JumpVelocity );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FLOAT, SkeletonHeight );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FLOAT, SkeletonWidth );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_BOOL, UseInnateBehavior );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FLOAT, InnateAggressiveness );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FLOAT, InnateTakeCoverProbability );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_BOOL, InnateIsStationary );
- EDITABLE_PARAM( SoldierGameObjDef, ParameterClass::TYPE_FILENAME, FirstPersonHands );
- GENERIC_DEFID_PARAM( SoldierGameObjDef, HumanAnimOverrideDefID, CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_ANIM_OVERRIDE );
- GENERIC_DEFID_PARAM( SoldierGameObjDef, HumanLoiterCollectionDefID, CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_LOITER );
- GENERIC_DEFID_PARAM( SoldierGameObjDef, DeathSoundPresetID, CLASSID_SOUND );
- MODEL_DEF_PARAM( SoldierGameObjDef, PhysDefID, "HumanPhysDef" );
- //
- // We want soldiers to use innate conversations by default
- //
- AllowInnateConversations = true;
- return ;
- }
- uint32 SoldierGameObjDef::Get_Class_ID (void) const
- {
- return CLASSID_GAME_OBJECT_DEF_SOLDIER;
- }
- PersistClass * SoldierGameObjDef::Create( void ) const
- {
- SoldierGameObj * obj = new SoldierGameObj;
- obj->Init( *this );
- return obj;
- }
- enum {
- CHUNKID_DEF_PARENT = 909991656,
- CHUNKID_DEF_VARIABLES,
- CHUNKID_DEF_DIALOG_ENTRY,
- MICROCHUNKID_DEF_TURN_RATE = 1,
- MICROCHUNKID_DEF_JUMP_VELOCITY,
- MICROCHUNKID_DEF_SKELETON_HEIGHT,
- MICROCHUNKID_DEF_SKELETON_WIDTH,
- MICROCHUNKID_DEF_USE_INNATE_BEHAVIOR,
- MICROCHUNKID_DEF_INNATE_AGGRESSIVENESS,
- MICROCHUNKID_DEF_INNATE_TAKE_COVER_PROB,
- XXXMICROCHUNKID_DEF_INNATE_ESCORT_ID,
- XXXMICROCHUNKID_DEF_INNATE_ESCORT_RANGE,
- MICROCHUNKID_DEF_FIRST_PERSON_HANDS,
- XXXMICROCHUNKID_DEF_CORPSE_PERSIST_TIME,
- MICROCHUNKID_DEF_USE_INNATE_CONVERSATIONS,
- MICROCHUNKID_DEF_INNATE_IS_STATIONARY,
- MICROCHUNKID_DEF_ORATOR_TYPE,
- MICROCHUNKID_DEF_HUMAN_ANIM_OVERRIDE_DEF_ID,
- MICROCHUNKID_DEF_DEATH_SOUND_PRESET,
- MICROCHUNKID_DEF_HUMAN_LOITER_COLLECTION_DEF_ID,
- };
- bool SoldierGameObjDef::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_DEF_PARENT );
- SmartGameObjDef::Save( csave );
- csave.End_Chunk();
- //
- // Save the dialog entries
- //
- for (int index = 0; index < DIALOG_MAX; index ++) {
- csave.Begin_Chunk( CHUNKID_DEF_DIALOG_ENTRY );
- DialogList[index].Save (csave);
- csave.End_Chunk();
- }
- csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_TURN_RATE, TurnRate );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_JUMP_VELOCITY, JumpVelocity );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_SKELETON_HEIGHT, SkeletonHeight );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_SKELETON_WIDTH, SkeletonWidth );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_USE_INNATE_BEHAVIOR, UseInnateBehavior );
- //WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_USE_INNATE_CONVERSATIONS, UseInnateConversations );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_INNATE_AGGRESSIVENESS, InnateAggressiveness );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_INNATE_TAKE_COVER_PROB, InnateTakeCoverProbability );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_INNATE_IS_STATIONARY, InnateIsStationary );
- WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_DEF_FIRST_PERSON_HANDS, FirstPersonHands );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_HUMAN_ANIM_OVERRIDE_DEF_ID, HumanAnimOverrideDefID );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_HUMAN_LOITER_COLLECTION_DEF_ID, HumanLoiterCollectionDefID );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_DEATH_SOUND_PRESET, DeathSoundPresetID );
-
- csave.End_Chunk();
- return true;
- }
- bool SoldierGameObjDef::Load( ChunkLoadClass &cload )
- {
- int dialog_index = 0;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_DEF_PARENT:
- SmartGameObjDef::Load( cload );
- break;
- case CHUNKID_DEF_DIALOG_ENTRY:
- if (dialog_index < DIALOG_MAX) {
- DialogList[dialog_index++].Load (cload);
- }
- break;
-
- case CHUNKID_DEF_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_TURN_RATE, TurnRate );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_JUMP_VELOCITY, JumpVelocity );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_SKELETON_HEIGHT, SkeletonHeight );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_SKELETON_WIDTH, SkeletonWidth );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_USE_INNATE_BEHAVIOR, UseInnateBehavior );
- //READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_USE_INNATE_CONVERSATIONS, UseInnateConversations );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_INNATE_AGGRESSIVENESS, InnateAggressiveness );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_INNATE_TAKE_COVER_PROB, InnateTakeCoverProbability );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_INNATE_IS_STATIONARY, InnateIsStationary );
- READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_DEF_FIRST_PERSON_HANDS, FirstPersonHands );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ORATOR_TYPE, OratorType );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_HUMAN_ANIM_OVERRIDE_DEF_ID, HumanAnimOverrideDefID );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_HUMAN_LOITER_COLLECTION_DEF_ID, HumanLoiterCollectionDefID );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_DEATH_SOUND_PRESET, DeathSoundPresetID );
- default:
- //Debug_Say(( "Unrecognized SoldierDef Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
- default:
- Debug_Say(( "Unrecognized SoldierDef chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- const PersistFactoryClass & SoldierGameObjDef::Get_Factory (void) const
- {
- return _SoldierGameObjDefPersistFactory;
- }
- /*
- ** SolderGameObj
- */
- SimplePersistFactoryClass<SoldierGameObj, CHUNKID_GAME_OBJECT_SOLDIER> _SoldierGameObjPersistFactory;
- const PersistFactoryClass & SoldierGameObj::Get_Factory (void) const
- {
- return _SoldierGameObjPersistFactory;
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::DisplayDebugBoxForGhostCollision = false;
- //------------------------------------------------------------------------------------
- SoldierGameObj::SoldierGameObj() :
- WeaponRenderModel( NULL ),
- BackWeaponRenderModel( NULL ),
- BackFlagRenderModel( NULL ),
- WeaponAnimControl( NULL ),
- TransitionCompletionData( NULL ),
- Vehicle( NULL ),
- LegFacing( 0 ),
- SyncLegs( false ),
- LastLegMode( 0 ),
- HeadLookDuration( 0 ),
- HeadRotation( 0,0,0 ),
- HeadLookTarget( 0,0,0 ),
- HeadLookAngle( 0,0,0 ),
- HeadLookAngleTimer( 0 ),
- InnateEnableBits( 0xFFFFFFFF ),
- InnateObserver( NULL ),
- // FlameTimer( 0 ),
- SpecialDamageMode(ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE),
- SpecialDamageTimer( 0 ),
- GenerateIdleFacialAnimTimer( 0 ),
- KeyRing( 0 ),
- InFlyMode( false ),
- IsVisible( true ),
- CurrentSpeech( NULL ),
- AIState( AI_STATE_IDLE ),
- SpeechAnim( NULL ),
- HeadModel( NULL ),
- EmotIconModel( NULL ),
- EmotIconTimer( 0 ),
- LadderUpMask( false ),
- LadderDownMask( false ),
- SpecialDamageEffect( NULL ),
- HealingEffect( NULL ),
- ReloadingTilt(0),
- WaterWake(NULL),
- WeaponChanged( false )
- {
- // All Humans need a HuamnAnimControl
- Set_Anim_Control( new HumanAnimControlClass );
- Set_App_Packet_Type(APPPACKETTYPE_SOLDIER);
- // create a water wake object
- WaterWake = SurfaceEffectsManager::Create_Persistant_Emitter();
- }
- //------------------------------------------------------------------------------------
- SoldierGameObj::~SoldierGameObj()
- {
- if ( HealingEffect != NULL ) {
- Peek_Human_Phys()->Remove_Effect_From_Me( HealingEffect );
- REF_PTR_RELEASE( HealingEffect );
- }
- Set_Special_Damage_Mode( ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE );
- Set_Emot_Icon (NULL, 0);
- REF_PTR_RELEASE( HeadModel );
- REF_PTR_RELEASE( SpeechAnim );
- REF_PTR_RELEASE( CurrentSpeech );
- if (CombatManager::I_Am_Server()) {
- CombatManager::On_Soldier_Death(this);
- }
- Set_Weapon_Model( NULL );
- if ( BackWeaponRenderModel != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackWeaponRenderModel);
- BackWeaponRenderModel->Release_Ref();
- BackWeaponRenderModel = NULL;
- }
- if ( BackFlagRenderModel != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackFlagRenderModel);
- BackFlagRenderModel->Release_Ref();
- BackFlagRenderModel = NULL;
- }
- if ( WeaponAnimControl != NULL ) {
- delete WeaponAnimControl;
- WeaponAnimControl = NULL;
- }
- if (Vehicle != NULL) {
- // Remove myself from the vehicle !
- Vehicle->Remove_Occupant(this);
- }
- COMBAT_SCENE->Remove_Object( Peek_Physical_Object() );
- if ( Is_Human_Controlled() ) {
- GameObjManager::Remove_Star( this );
- }
- Reset_RenderObjs();
- if (WaterWake != NULL) {
- SurfaceEffectsManager::Destroy_Persistant_Emitter( WaterWake );
- WaterWake = NULL;
- }
- return ;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Init( void )
- {
- Re_Init( Get_Definition() );
- return ;
- }
- void SoldierGameObj::Init( const SoldierGameObjDef & definition )
- {
- SmartGameObj::Init( definition );
- Copy_Settings( definition );
- return ;
- }
- void SoldierGameObj::Copy_Settings( const SoldierGameObjDef & definition )
- {
- HumanState.Init( Peek_Human_Phys() );
- HumanState.Set_Anim_Control( (HumanAnimControlClass *)Get_Anim_Control() ); // Must set the anim control after the phys object
- //HumanState.Set_Human_Anim_Override( "HAO Test" );
- if ( Get_Definition().HumanAnimOverrideDefID != 0 ) {
- HumanState.Set_Human_Anim_Override( Get_Definition().HumanAnimOverrideDefID );
- }
- if ( Get_Definition().HumanLoiterCollectionDefID != 0 ) {
- HumanState.Set_Human_Loiter_Collection( Get_Definition().HumanLoiterCollectionDefID );
- }
- Adjust_Skeleton( definition.SkeletonHeight, definition.SkeletonWidth );
- // All characters force their heads and hands to use the same LOD level as their body.
- RenderObjClass * model = Peek_Human_Phys()->Peek_Model();
- if (model != NULL) {
- model->Set_Sub_Objects_Match_LOD(true);
- }
- if ( InnateObserver == NULL &&
- Get_Definition().UseInnateBehavior &&
- Is_Controlled_By_Me () == false ) {
- InnateObserver = new SoldierObserverClass;
- Insert_Observer( InnateObserver );
- }
- //
- // Copy the dialog entries from the definition
- //
- for( int index = 0; index < DIALOG_MAX; index ++ ) {
- DialogList[index] = definition.DialogList[index];
- }
- //
- // Put the soldier in its own collision group
- //
- Peek_Physical_Object ()->Set_Collision_Group( SOLDIER_COLLISION_GROUP );
- Prepare_Speech_Framework ();
- return ;
- }
- void SoldierGameObj::Prepare_Speech_Framework( void )
- {
- //
- // Make sure we have an allocated animation to use for speech
- //
- if ( SpeechAnim == NULL) {
- HeadModel = Find_Head_Model();
- //
- // Dig out the skeleton name for the head model
- //
- if (HeadModel != NULL) {
- const HTreeClass *htree = HeadModel->Get_HTree ();
- if (htree != NULL) {
- StringClass skeleton_name = htree->Get_Name ();
- //
- // Generate the animation
- //
- SpeechAnim = new DynamicSpeechAnimClass (skeleton_name);
- GenerateIdleFacialAnimTimer = 0;
- }
- }
- }
- return ;
- }
- void SoldierGameObj::Re_Init( const SoldierGameObjDef & definition )
- {
- if ( this == COMBAT_STAR ) {
- HUDClass::Force_Weapon_Chart_Update();
- WeaponViewClass::Reset();
- }
- //
- // Remove the object from the world (just to be safe)
- //
- COMBAT_SCENE->Remove_Object( Peek_Physical_Object() );
- //
- // Reset the weapon model
- //
- Set_Weapon_Model( NULL );
- if ( BackWeaponRenderModel != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackWeaponRenderModel);
- BackWeaponRenderModel->Release_Ref();
- BackWeaponRenderModel = NULL;
- }
- if ( BackFlagRenderModel != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackFlagRenderModel);
- BackFlagRenderModel->Release_Ref();
- BackFlagRenderModel = NULL;
- }
- if ( WeaponAnimControl != NULL ) {
- delete WeaponAnimControl;
- WeaponAnimControl = NULL;
- }
- //
- // Re-initialize the base class
- //
- SmartGameObj::Re_Init( definition );
- //
- // Free some of the data we will be re-initializing
- //
- REF_PTR_RELEASE( HeadModel );
- REF_PTR_RELEASE( SpeechAnim );
- REF_PTR_RELEASE( CurrentSpeech );
- HumanState.Reset();
- //
- // Copy any internal settings from the definition
- //
- Copy_Settings( definition );
- //
- // "Dirty" the object for networking
- //
- Set_Object_Dirty_Bit( NetworkObjectClass::BIT_RARE, true );
- // When class changes, update for new weapon
- if ( this == COMBAT_STAR ) {
- HUDClass::Reset();
- }
- return ;
- }
- //------------------------------------------------------------------------------------
- const SoldierGameObjDef & SoldierGameObj::Get_Definition( void ) const
- {
- return (const SoldierGameObjDef &)BaseGameObj::Get_Definition();
- }
- void SoldierGameObj::Set_Control_Owner(int control_owner)
- {
- if ( Is_Human_Controlled() ) {
- GameObjManager::Remove_Star( this );
- }
- SmartGameObj::Set_Control_Owner(control_owner);
- if ( Is_Human_Controlled() ) {
- GameObjManager::Add_Star( this );
- }
- }
- /*
- ** Soldier Save and Load
- */
- enum {
- CHUNKID_PARENT = 909991656,
- CHUNKID_VARIABLES,
- CHUNKID_WEAPON_ANIM,
- CHUNKID_HUMAN_STATE,
- XXXCHUNKID_C4_TIMER,
- XXXCHUNKID_WEAPON_MODEL,
- CHUNKID_TRANSITION_COMPLETION_DATA,
- CHUNKID_DIALOG_ENTRY,
- CHUNKID_RENDER_OBJS,
- CHUNKID_SPECIAL_DAMAGE_DAMAGER,
- MICROCHUNKID_DETONATE_C4 = 1,
- MICROCHUNKID_LEG_FACING,
- MICROCHUNKID_SYNC_LEGS,
- MICROCHUNKID_ANIMATION_NAME,
- MICROCHUNKID_VEHICLE,
- XXX_MICROCHUNKID_TRANSITION,
- XXX_MICROCHUNKID_FORCE_FACING,
- MICROCHUNKID_INNATE_ENABLE_BITS,
- MICROCHUNKID_INNATE_OBSERVER_PTR,
- MICROCHUNKID_LAST_LEG_MODE,
- MICROCHUNKID_HEAD_LOOK_DURATION,
- MICROCHUNKID_HEAD_ROTATION,
- MICROCHUNKID_LOOK_TARGET,
- XXXMICROCHUNKID_FLAME_TIMER,
- MICROCHUNKID_KEY_RING,
- MICROCHUNKID_AI_STATE,
- XXX_MICROCHUNKID_IN_CONVERSATION,
- MICROCHUNKID_LOOK_ANGLE,
- MICROCHUNKID_LOOK_ANGLE_TIMER,
- XXX_MICROCHUNKID_ACTIVE_CONVERSATION,
- MICROCHUNKID_WEAPON_MODEL,
- MICROCHUNKID_SPECIAL_DAMAGE_MODE,
- MICROCHUNKID_SPECIAL_DAMAGE_TIMER,
- MICROCHUNKID_IS_USING_GHOST_COLLISION
- };
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_PARENT );
- SmartGameObj::Save( csave );
- csave.End_Chunk();
- //
- // Save the dialog entries
- //
- for (int index = 0; index < DIALOG_MAX; index ++) {
- csave.Begin_Chunk( CHUNKID_DIALOG_ENTRY );
- DialogList[index].Save (csave);
- csave.End_Chunk();
- }
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DETONATE_C4, DetonateC4 );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LEG_FACING, LegFacing );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SYNC_LEGS, SyncLegs );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_KEY_RING, KeyRing );
- // WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FORCE_FACING, ForceFacing );
- if ( Vehicle != NULL ) {
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_VEHICLE, Vehicle );
- }
- csave.Begin_Micro_Chunk( MICROCHUNKID_ANIMATION_NAME );
- char anim_string[80];
- strcpy( anim_string, AnimationName );
- csave.Write( anim_string, strlen( anim_string ) + 1);
- csave.End_Micro_Chunk();
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_INNATE_ENABLE_BITS, InnateEnableBits );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_INNATE_OBSERVER_PTR, InnateObserver );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LAST_LEG_MODE, LastLegMode );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_HEAD_LOOK_DURATION, HeadLookDuration );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_HEAD_ROTATION, HeadRotation );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LOOK_TARGET, HeadLookTarget );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LOOK_ANGLE, HeadLookAngle );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_LOOK_ANGLE_TIMER, HeadLookAngleTimer );
- // WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FLAME_TIMER, FlameTimer );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SPECIAL_DAMAGE_MODE, SpecialDamageMode );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SPECIAL_DAMAGE_TIMER, SpecialDamageTimer );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AI_STATE, AIState );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_WEAPON_MODEL, WeaponRenderModel );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_IS_USING_GHOST_COLLISION, IsUsingGhostCollision );
-
- csave.End_Chunk();
- if ( WeaponAnimControl ) {
- csave.Begin_Chunk( CHUNKID_WEAPON_ANIM );
- WeaponAnimControl->Save( csave );
- csave.End_Chunk();
- }
- csave.Begin_Chunk( CHUNKID_HUMAN_STATE );
- HumanState.Save( csave );
- csave.End_Chunk();
- if ( TransitionCompletionData ) {
- csave.Begin_Chunk( CHUNKID_TRANSITION_COMPLETION_DATA );
- TransitionCompletionData->Save( csave );
- csave.End_Chunk();
- }
- for ( int i = 0; i < RenderObjList.Count(); i++ ) {
- csave.Begin_Chunk( CHUNKID_RENDER_OBJS );
- csave.Begin_Chunk(RenderObjList[i]->Get_Factory().Chunk_ID());
- RenderObjList[i]->Get_Factory().Save( csave, RenderObjList[i] );
- csave.End_Chunk();
- csave.End_Chunk();
- }
- if ( SpecialDamageDamager.Get_Ptr() != NULL ) {
- csave.Begin_Chunk( CHUNKID_SPECIAL_DAMAGE_DAMAGER );
- SpecialDamageDamager.Save( csave );
- csave.End_Chunk();
- }
- return true;
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Load( ChunkLoadClass &cload )
- {
- char anim_string[80];
- int dialog_index = 0;
- WWASSERT( Vehicle == NULL );
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_PARENT:
- SmartGameObj::Load( cload );
- break;
- case CHUNKID_DIALOG_ENTRY:
- if (dialog_index < DIALOG_MAX) {
- DialogList[dialog_index++].Load (cload);
- }
- break;
-
- case CHUNKID_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DETONATE_C4, DetonateC4 );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_LEG_FACING, LegFacing );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SYNC_LEGS, SyncLegs );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_VEHICLE, Vehicle );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_KEY_RING, KeyRing );
- // READ_MICRO_CHUNK( cload, MICROCHUNKID_FORCE_FACING, ForceFacing );
- case MICROCHUNKID_ANIMATION_NAME:
- cload.Read( anim_string, cload.Cur_Micro_Chunk_Length() );
- AnimationName = anim_string;
- break;
- case MICROCHUNKID_INNATE_OBSERVER_PTR:
- cload.Read( &InnateObserver, sizeof (InnateObserver) );
- if ( InnateObserver != NULL ) {
- REQUEST_POINTER_REMAP( (void **)&InnateObserver );
- }
- break;
- READ_MICRO_CHUNK( cload, MICROCHUNKID_INNATE_ENABLE_BITS, InnateEnableBits );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_LAST_LEG_MODE, LastLegMode );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_HEAD_LOOK_DURATION, HeadLookDuration );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_HEAD_ROTATION, HeadRotation );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_LOOK_TARGET, HeadLookTarget );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_LOOK_ANGLE, HeadLookAngle );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_LOOK_ANGLE_TIMER, HeadLookAngleTimer );
- // READ_MICRO_CHUNK( cload, MICROCHUNKID_FLAME_TIMER, FlameTimer );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SPECIAL_DAMAGE_MODE, SpecialDamageMode );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_SPECIAL_DAMAGE_TIMER, SpecialDamageTimer );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_AI_STATE, AIState );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_WEAPON_MODEL, WeaponRenderModel );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_IS_USING_GHOST_COLLISION, IsUsingGhostCollision );
- default:
- Debug_Say(( "Unrecognized Soldier Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- if ( Vehicle != NULL ) {
- REQUEST_POINTER_REMAP( (void **)&Vehicle );
- }
- break;
- case CHUNKID_WEAPON_ANIM:
- Set_Weapon_Animation( NULL ); // Get the anim control built
- WeaponAnimControl->Load( cload );
- break;
- case CHUNKID_HUMAN_STATE:
- HumanState.Load( cload );
- break;
- case CHUNKID_RENDER_OBJS:
- cload.Open_Chunk();
- PersistFactoryClass * factory;
- factory = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
- WWASSERT(factory != NULL);
- if (factory != NULL) {
- RenderObjClass * robj = (RenderObjClass *)factory->Load(cload);
- Add_RenderObj( robj );
- robj->Release_Ref();
- }
- cload.Close_Chunk();
- break;
- case CHUNKID_TRANSITION_COMPLETION_DATA:
- WWASSERT( TransitionCompletionData == NULL );
- TransitionCompletionData = new TransitionCompletionDataStruct();
- TransitionCompletionData->Load( cload );
- break;
- case CHUNKID_SPECIAL_DAMAGE_DAMAGER:
- SpecialDamageDamager.Load( cload );
- break;
- default:
- Debug_Say(( "Unrecognized SoldierGameObj chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- if ( WeaponRenderModel != NULL ) {
- REQUEST_REF_COUNTED_POINTER_REMAP( (RefCountClass **)&WeaponRenderModel );
- }
- SaveLoadSystemClass::Register_Post_Load_Callback(this);
- return true;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::On_Post_Load( void )
- {
- HumanState.Set_Anim_Control( (HumanAnimControlClass *)Get_Anim_Control() ); // Must set the anim control after the phys object
- SmartGameObj::On_Post_Load();
- if ( Peek_Model() && (WeaponRenderModel != NULL) ) {
- Peek_Model()->Add_Sub_Object_To_Bone( WeaponRenderModel, GUN_BONE_NAME );
- }
- Adjust_Skeleton( Get_Definition().SkeletonHeight, Get_Definition().SkeletonWidth );
- // Fixup BackWeaponRenderModel
- Update_Back_Gun();
- // Hide if in vehicle
- if ( Is_In_Vehicle() && Peek_Model() != NULL ) {
- Peek_Model()->Set_Hidden( true );
- }
- //
- // Make sure we have an allocated animation to use for speech
- //
- Prepare_Speech_Framework ();
- return ;
- }
- //-----------------------------------------------------------------------------
- CollisionReactionType SoldierGameObj::Collision_Occurred(const CollisionEventClass & event)
- {
- // Debug_Say(( "Soldier Collision %p %p\n", this, event.OtherObj ));
- // Detect squishing...
- if ( event.OtherObj != NULL && event.OtherObj->Get_Observer() != NULL ) {
- PhysicalGameObj * obj = ((CombatPhysObserverClass *)event.OtherObj->Get_Observer())->As_PhysicalGameObj();
- if ( obj && obj->As_VehicleGameObj() ) {
- // if ( !Is_Teammate( obj ) ) { // never squish teammates
- if ( Is_Enemy( obj ) ) { // only squish enemies
- Vector3 vel;
- if ( event.OtherObj->As_MoveablePhysClass() != NULL ) {
- event.OtherObj->As_MoveablePhysClass()->Get_Velocity( &vel );
- Vector3 my_pos;
- Vector3 vehicle_pos;
- Get_Position(&my_pos);
- obj->Get_Position(&vehicle_pos);
- // only squish if velocity is high enough, and velocity is towards the soldier
- if ( (vel.Length() > obj->As_VehicleGameObj()->Get_Squish_Velocity() ) &&
- (Vector3::Dot_Product(vel,my_pos - vehicle_pos) > 0.0f) )
- {
- if ( HumanState.Get_State() != HumanStateClass::DEATH ) {
- // We need to pick a better warhead to damage with
- SmartGameObj * damager = obj->As_VehicleGameObj()->Get_Driver();
- if ( damager == NULL ) {
- damager = obj->As_VehicleGameObj();
- }
- OffenseObjectClass offense( 10000, 1, damager );
- Apply_Damage_Extended( offense, 10000.0f, vel, NULL );
- // Play the squish sound
- // Stats
- if (( obj->As_VehicleGameObj()->Get_Driver() != NULL ) &&
- ( obj->As_VehicleGameObj()->Get_Driver()->Get_Player_Data() != NULL ) ) {
- obj->As_VehicleGameObj()->Get_Driver()->Get_Player_Data()->Stats_Add_Squish();
- }
- }
- }
- }
- }
- }
- }
- return COLLISION_REACTION_DEFAULT;
- }
- /*
- **
- */
- void SoldierGameObj::Export_Creation( BitStreamClass &packet )
- {
- //TSS091001
- //WWDEBUG_SAY((">>>>> SoldierGameObj::Export_Creation id %d\n", Get_ID()));
- SmartGameObj::Export_Creation( packet );
- return ;
- }
- /*
- **
- */
- void SoldierGameObj::Import_Creation( BitStreamClass &packet )
- {
- SmartGameObj::Import_Creation( packet );
- //TSS091001
- //WWDEBUG_SAY((">>>>> SoldierGameObj::Import_Creation id %d\n", Get_ID()));
- /*
- //
- // Setup the speed settings for this soldier
- //
- float speed_factor = CombatManager::Get_Max_Speed_Pc( this ) / 100.0f;
- Set_Max_Speed( speed_factor * Get_Max_Speed() );
- */
- return ;
- }
- /*
- **
- */
- void SoldierGameObj::Export_Rare( BitStreamClass &packet )
- {
- SmartGameObj::Export_Rare( packet );
- //
- // Add our definition ID to the packet
- //
- uint32 definition_id = Get_Definition ().Get_ID ();
- packet.Add( definition_id );
- }
- /*
- **
- */
- void SoldierGameObj::Import_Rare( BitStreamClass &packet )
- {
- Set_Weapon_Model (NULL);
- // If we are changing to the same def, the above line made us lose our weapon model, and we won't get it back.
- // The next line makes us get it back.
- Get_Weapon_Bag()->Force_Changed();
- SmartGameObj::Import_Rare( packet );
- //
- // Read the definition ID from the packet
- //
- uint32 definition_id = 0;
- packet.Get( definition_id );
- //
- // Did our definition change?
- //
- if (definition_id != Get_Definition ().Get_ID ()) {
- DefinitionClass *definition = DefinitionMgrClass::Find_Definition (definition_id);
- //
- // Did we find the right definition?
- //
- if (definition != NULL && definition->Get_Class_ID() == CLASSID_GAME_OBJECT_DEF_SOLDIER) {
- SoldierGameObjDef *soldier_def = reinterpret_cast<SoldierGameObjDef *> (definition);
-
- //
- // Re-initialize ourselves
- //
- Re_Init (*soldier_def);
- }
- }
- return ;
- }
- /*
- **
- */
- void SoldierGameObj::Export_Occasional( BitStreamClass &packet )
- {
- SmartGameObj::Export_Occasional( packet );
- //
- // What weapon is being held?
- //
- #if 0 //(gth) moving this back to Frequent to fix the game, re-optimize later...
- WeaponClass * p_weapon = Get_Weapon();
- bool has_weapon = (p_weapon != NULL);
- packet.Add(has_weapon);
- if (has_weapon) {
- packet.Add(p_weapon->Get_ID());
- packet.Add(p_weapon->Get_Total_Rounds());
- }
- #endif
- WWASSERT(WeaponBag != NULL);
- WeaponBag->Export_Weapon_List(packet);
- //packet.Add(CtfTeamFlag, BITPACK_CTF_TEAM_FLAG);
- }
- /*
- **
- */
- void SoldierGameObj::Import_Occasional( BitStreamClass &packet )
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- SmartGameObj::Import_Occasional( packet );
- //
- // Held weapon
- //
- #if 0 // (gth) moving back to "Frequent" to fix the game, re-optimize later?
- bool has_weapon = packet.Get(has_weapon);
- if (has_weapon) {
- WWASSERT(!packet.Is_Flushed());
-
- int weapon_id = packet.Get(weapon_id);
- int rounds = packet.Get(rounds);
- if ((Get_Weapon() == NULL) || (weapon_id != Get_Weapon()->Get_ID())) {
- WeaponBag->Select_Weapon_ID(weapon_id);
- }
- if (Get_Weapon() != NULL) {
- // If this weapon is currently being fired, ignore the server rounds count packet
- // This should help the jittery rounds count
- if ( !Get_Weapon()->Is_Triggered() ) {
- Get_Weapon()->Set_Total_Rounds( rounds );
- }
- }
- } else {
- if (Get_Weapon() != NULL) {
- Get_Weapon_Bag()->Deselect();
- }
- }
- #endif
- //
- // Weapon list
- //
- WWASSERT(WeaponBag != NULL);
- WeaponBag->Import_Weapon_List(packet);
- /*
- //
- // Flag pickup/drop
- //
- int ctf_team_flag = packet.Get(ctf_team_flag, BITPACK_CTF_TEAM_FLAG);
- if (CtfTeamFlag != ctf_team_flag) {
- CombatManager::Change_Flag_Status(this, ctf_team_flag);
- }
- */
- }
- /*
- **
- */
- void SoldierGameObj::Export_Frequent(BitStreamClass & packet)
- {
- /**/
- //TSS101601
- bool in_vehicle = (Get_State() == HumanStateClass::IN_VEHICLE);
- packet.Add(in_vehicle);
- if (in_vehicle)
- {
- // Just do the control info
- SmartGameObj::Export_Frequent(packet);
- return;
- }
- /**/
- //
- // What weapon is being held?
- // (gth) moved this back into frequent to fix the game, re-optimize later
- //
- WeaponClass * p_weapon = Get_Weapon();
- bool has_weapon = (p_weapon != NULL);
- packet.Add(has_weapon);
- if (has_weapon) {
- packet.Add(p_weapon->Get_ID());
- packet.Add(p_weapon->Get_Total_Rounds());
- }
- //
- // Export Position and state
- //
- Vector3 position;
- Get_Position(&position);
- #ifdef MULTIPLAYERDEMO
- //
- // Mix up the packet order to make demo/non-demo code more incompatible.
- //
- packet.Add(position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Add(position.Z, BITPACK_WORLD_POSITION_Z);
- packet.Add(position.X, BITPACK_WORLD_POSITION_X);
- #else
- packet.Add(position.X, BITPACK_WORLD_POSITION_X);
- packet.Add(position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Add(position.Z, BITPACK_WORLD_POSITION_Z);
- #endif
-
- packet.Add((int) HumanState.Get_State(), BITPACK_HUMAN_STATE);
- packet.Add(HumanState.Get_Sub_State(), BITPACK_HUMAN_SUB_STATE);
- if (HumanState.Get_State() == HumanStateClass::AIRBORNE) {
- // velocity is only needed for jumping
- Vector3 velocity;
- Get_Velocity(velocity);
- packet.Add(velocity.X);
- packet.Add(velocity.Y);
- packet.Add(velocity.Z);
- }
- if ((Get_State() == HumanStateClass::TRANSITION) ||
- (Get_State() == HumanStateClass::ANIMATION) ||
- (Get_State() == HumanStateClass::IN_VEHICLE)) {
- packet.Add_Terminated_String(AnimationName);
- // Debug_Say(( "In Transition %s\n", TransitionName ));
- }
- bool is_special_damage = SpecialDamageMode != ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE;
- packet.Add(is_special_damage);
- if ( is_special_damage ) {
- packet.Add( SpecialDamageMode );
- }
- SmartGameObj::Export_Frequent(packet);
- }
- /*
- **
- */
- void SoldierGameObj::Import_Frequent( BitStreamClass & packet )
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- /**/
- //TSS101601
- bool in_vehicle = packet.Get(in_vehicle);
- if (in_vehicle)
- {
- // Just get control info
- SmartGameObj::Import_Frequent(packet);
- return;
- }
- /**/
- //
- // What weapon is being held?
- // (gth) moved this back into frequent to fix the game, re-optimize later
- //
- bool has_weapon = packet.Get(has_weapon);
- if (has_weapon) {
- WWASSERT(!packet.Is_Flushed());
-
- int weapon_id = packet.Get(weapon_id);
- int rounds = packet.Get(rounds);
- if ((Get_Weapon() == NULL) || (weapon_id != Get_Weapon()->Get_ID())) {
- WeaponBag->Select_Weapon_ID(weapon_id);
- }
- if (Get_Weapon() != NULL) {
- // If this weapon is currently being fired, ignore the server rounds count packet
- // This should help the jittery rounds count
- if ( !Get_Weapon()->Is_Triggered() ) {
- Get_Weapon()->Set_Total_Rounds( rounds );
- }
- }
- } else {
- if (Get_Weapon() != NULL) {
- Get_Weapon_Bag()->Deselect();
- }
- }
- //
- // Position
- //
- Vector3 sc_position;
- #ifdef MULTIPLAYERDEMO
- //
- // Mix up the packet order to make demo/non-demo code more incompatible.
- //
- packet.Get(sc_position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Get(sc_position.Z, BITPACK_WORLD_POSITION_Z);
- packet.Get(sc_position.X, BITPACK_WORLD_POSITION_X);
- #else
- packet.Get(sc_position.X, BITPACK_WORLD_POSITION_X);
- packet.Get(sc_position.Y, BITPACK_WORLD_POSITION_Y);
- packet.Get(sc_position.Z, BITPACK_WORLD_POSITION_Z);
- #endif
- // Bump Z up to the top of the possible values due to packing
- // we assume the max error is half of the resolution
- float max_error = cEncoderList::Get_Encoder_Type_Entry( BITPACK_WORLD_POSITION_Z ).Get_Resolution() / 2.0f;
- sc_position.Z += max_error;
- Interpret_Sc_Position_Data(sc_position);
- //
- // State and substate
- //
- int h_state = packet.Get(h_state, BITPACK_HUMAN_STATE);
- HumanStateClass::HumanStateType state =
- (HumanStateClass::HumanStateType) h_state;
- int sub_state = packet.Get(sub_state, BITPACK_HUMAN_SUB_STATE);
- //
- // Velocity (if airborne)
- //
- Vector3 velocity;
- if (state == HumanStateClass::AIRBORNE) {
- packet.Get(velocity.X);
- packet.Get(velocity.Y);
- packet.Get(velocity.Z);
- }
- if (HumanState.Is_Locked()) {
- packet.Flush();
- return;
- }
- #if 0
- if ( Get_State() == HumanStateClass::TRANSITION ) {
- Debug_Say(( "Ignoring Transitioning!\n" ));
- packet.Flush();
- return;
- }
- #endif
- char trans_name[80] = "";
- if ( ( state == HumanStateClass::TRANSITION ) ||
- ( state == HumanStateClass::ANIMATION ) ||
- ( state == HumanStateClass::IN_VEHICLE ) ) {
- packet.Get_Terminated_String(trans_name, sizeof(trans_name));
- }
- Interpret_Sc_State_Data(state, sub_state, trans_name, velocity, sc_position);
- bool is_special_damage;
- packet.Get(is_special_damage);
- int mode = ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE;
- if ( is_special_damage ) {
- packet.Get(mode);
- }
- if ( mode != SpecialDamageMode ) {
- Set_Special_Damage_Mode( (ArmorWarheadManager::SpecialDamageType)mode );
- }
- if (Get_State() == HumanStateClass::DIVE) {
- packet.Flush();
- } else {
- SmartGameObj::Import_Frequent(packet);
- }
- WWASSERT(packet.Is_Flushed());
- }
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Import_State_Cs(BitStreamClass & packet)
- {
- bool is_sniping = packet.Get( is_sniping );
- if ( is_sniping != Is_Sniping() ) {
- // Take sniping state from client
- // Debug_Say(( "Fixing Sniper State\n" ));
- HumanState.Toggle_State_Flag( HumanStateClass::SNIPING_FLAG );
- }
- bool checking = packet.Get( checking );
- if ( checking ) {
- int check = packet.Get( check );
- if ( check != Check() ) {
- // React to cheating
- if ( Get_Player_Data() ) {
- Get_Player_Data()->Inc_Punish_Timer( TimeManager::Get_Frame_Seconds() ) ;
- }
- }
- }
- SmartGameObj::Import_State_Cs(packet);
- }
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Export_State_Cs(BitStreamClass & packet)
- {
- bool is_sniping = Is_Sniping();
- packet.Add( is_sniping );
- bool checking = Control.Get_Boolean( ControlClass::BOOLEAN_ACTION );
- packet.Add( checking );
- if ( checking ) {
- int check = Check();
- packet.Add( check );
- }
- SmartGameObj::Export_State_Cs(packet);
- }
- //-----------------------------------------------------------------------------
- int SoldierGameObj::Check(void)
- {
- Matrix3D tm(1);
- #define UNINITIALLIZED_CRC 0x78629140
- static int crc = UNINITIALLIZED_CRC;
- tm.Rotate_X( 1.4f );
- if ( crc == UNINITIALLIZED_CRC ) {
- char * filelist[] = {
- "laif`wp-gga", //"objects.ddb",
- "bqnlq-jmj", //"armor.ini",
- "almfp-jmj", //"bones.ini",
- "pvqeb`ffeef`wp-jmj", //"surfaceeffects.ini",
- "`bnfqbp-jmj", //"cameras.ini",
- "`\\mlg\\nd\\o3-t0g", //"c_nod_mg_l0.w3d",
- "`\\mlg\\qh\\o3-t0g", //"c_nod_rk_l0.w3d",
- "`\\mlg\\eo\\o3-t0g", //"c_nod_fl_l0.w3d",
- "`\\mlg\\fm\\o3-t0g", //"c_nod_en_l0.w3d",
- "`\\mlg\\ndl\\o3-t0g", //"c_nod_mgo_l0.w3d",
- "`\\mlg\\qhl\\o3-t0g", //"c_nod_rko_l0.w3d",
- "`\\mlg\\`kfnw\\o3-t0g", //"c_nod_chemt_l0.w3d",
- "`\\mlg\\pmjsfq\\o3-t0g", //"c_nod_sniper_l0.w3d",
- "`\\mlg\\qplog\\o3-t0g", //"c_nod_rsold_l0.w3d",
- "`\\mlg\\pwowk\\o3-t0g", //"c_nod_stlth_l0.w3d",
- "`\\mlg\\pbhv\\o3-t0g", //"c_nod_saku_l0.w3d",
- "`\\mlg\\pbhv1\\o3-t0g", //"c_nod_saku2_l0.w3d",
- "`\\mlg\\qbu\\o3-t0g", //"c_nod_rav_l0.w3d",
- "`\\mlg\\nqbu\\o3-t0g", //"c_nod_mrav_l0.w3d",
- "`\\mlg\\ngy\\o3-t0g", //"c_nod_mdz_l0.w3d",
- "`\\mlg\\ngy1\\o3-t0g", //"c_nod_mdz2_l0.w3d",
- "`\\mlg\\w`\\o3-t0g", //"c_nod_tc_l0.w3d",
- "`\\mlg\\nvwbmw\\o3-t0g", //"c_nod_mutant_l0.w3d",
- "`\\mlg\\npog\\o3-t0g", //"c_nod_msld_l0.w3d",
- "`\\mlg\\pplog\\o3-t0g", //"c_nod_ssold_l0.w3d",
- "`\\mlg\\sfwn\\o3-t0g", //"c_nod_petm_l0.w3d",
- "`\\mlg\\hbmf\\o3-t0g", //"c_nod_kane_l0.w3d",
- "`\\dgj\\nd\\o3-t0g", //"c_gdi_mg_l0.w3d",
- "`\\dgj\\qh\\o3-t0g", //"c_gdi_rk_l0.w3d",
- "`\\dgj\\dq\\o3-t0g", //"c_gdi_gr_l0.w3d",
- "`\\dgj\\fm\\o3-t0g", //"c_gdi_en_l0.w3d",
- "`\\dgj\\ndl\\o3-t0g", //"c_gdi_mgo_l0.w3d",
- "`\\dgj\\qhl\\o3-t0g", //"c_gdi_rko_l0.w3d",
- "`\\dgj\\pzg\\o3-t0g", //"c_gdi_syd_l0.w3d",
- "`\\dgj\\gfbg\\o3-t0g", //"c_gdi_dead_l0.w3d",
- "`\\dgj\\dvm\\o3-t0g", //"c_gdi_gun_l0.w3d",
- "`\\dgj\\sw`k\\o3-t0g", //"c_gdi_ptch_l0.w3d",
- "`\\kbul`\\o3-t0g", //"c_havoc_l0.w3d",
- "`\\kbul`m\\o3-t0g", //"c_havocn_l0.w3d",
- "`\\kbul`t\\o3-t0g", //"c_havocw_l0.w3d",
- "`\\kbul`g\\o3-t0g", //"c_havocd_l0.w3d",
- "`\\dgj\\pzg\\o3-t0g", //"c_gdi_syd_l0.w3d",
- "`\\dgj\\pzg1\\o3-t0g", //"c_gdi_syd2_l0.w3d",
- "`\\dgj\\nlaj\\o3-t0g", //"c_gdi_mobi_l0.w3d",
- "`\\dgj\\klwt\\o3-t0g", //"c_gdi_hotw_l0.w3d",
- "`\\dgj\\ow\\o3-t0g", //"c_gdi_lt_l0.w3d",
- "`\\mlg\\sfwq\\o3-t0g", //"c_nod_petr_l0.w3d",
- "`\\oldbm\\o3-t0g", //"c_logan_l0.w3d",
- "`\\dgj\\ol`hf\\o3-t0g", //"c_gdi_locke_l0.w3d",
- "u\\mlg\\avddz-t0g", //"v_nod_buggy.w3d",
- "u\\mlg\\bs`\\n-t0g", //"v_nod_apc_m.w3d",
- "u\\mlg\\bqwoqz-t0g", //"v_nod_artlry.w3d",
- "u\\mlg\\eobnf-t0g", //"v_nod_flame.w3d",
- "u\\mlg\\owbmh-t0g", //"v_nod_ltank.w3d",
- "u\\mlg\\pwowk-t0g", //"v_nod_stlth.w3d",
- "u\\mlg\\wqmpsw\\n-t0g", //"v_nod_trnspt_m.w3d",
- "u\\mlg\\bsb`kf\\n-t0g", //"v_nod_apache_m.w3d",
- "u\\`kbnfoflm-t0g", //"v_chameleon.w3d",
- "u\\dgj\\kvnuff-t0g", //"v_gdi_humvee.w3d",
- "u\\dgj\\bs`\\n-t0g", //"v_gdi_apc_m.w3d",
- "u\\dgj\\nqop-t0g", //"v_gdi_mrls.w3d",
- "u\\dgj\\nfgwmh-t0g", //"v_gdi_medtnk.w3d",
- "u\\dgj\\nbnnwk-t0g", //"v_gdi_mammth.w3d",
- "u\\sj`hvs32-t0g", //"v_pickup01.w3d",
- "u\\pfgbm32-t0g", //"v_sedan01.w3d",
- "u\\dgj\\lq`b\\n-t0g", //"v_gdi_orca_m.w3d",
- "u\\dgj\\wqmpsw\\n-t0g", //"v_gdi_trnspt_m.w3d",
- };
- #define NUM_CRC_FILES (sizeof( filelist ) / sizeof( filelist[0] ) )
- crc = 0;
- tm.Rotate_Y( 2.8f );
- for ( int i = 0; i < NUM_CRC_FILES; i++ ) {
- StringClass name = filelist[i];
- // Obfuscate name
- char * n = &name[0];
- while ( *n ) *n++ ^= 0x3;
- tm.Rotate_Z( 3.6f );
- // Debug_Say(( " \"%s\",\n", name ));
- FileClass * file = _TheFileFactory->Get_File( name );
- tm.Pre_Rotate_X( 0.3f );
- if ( file && file->Is_Available() ) {
- int size = file->Size();
- tm.Pre_Rotate_Y( 0.4f );
- file->Open();
- tm.Pre_Rotate_Z( 0.5f );
- while ( size > 0 ) {
- unsigned char buffer[ 4096 ];
- int amount = min( (int)size, (int)sizeof(buffer) );
- tm.Translate_X( 3.1f );
- amount = file->Read( buffer, amount );
- tm.Translate_Y( 4.6f );
- crc = CRC_Memory( buffer, amount, crc );
- tm.Translate_Z( 8.2f );
- size -= amount;
- }
- file->Close();
- } else {
- // Debug_Say(( "***%s not found\n", name ));
- }
- tm.Rotate_X( 1.4f );
- }
- }
- return crc;
- }
- //-----------------------------------------------------------------------------
- /*
- **
- */
- bool _UseLatencyInterpret = true;
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Interpret_Sc_Position_Data( const Vector3 & sc_position)
- {
- Vector3 position = sc_position;
- // Only use the latency code for the star
- if ( _UseLatencyInterpret && (this == COMBAT_STAR) ) {
- Peek_Human_Phys()->Network_Latency_State_Update(sc_position,Vector3(0,0,0));
- return;
- }
- WWASSERT(CombatManager::I_Am_Only_Client());
- if (Get_State() == HumanStateClass::TRANSITION) {
- //
- // Pop
- //
- // Set_Position(sc_position);
- Peek_Human_Phys()->Network_State_Update(sc_position,Vector3(0,0,0));
- } else {
- Vector3 current_position;
- Get_Position(¤t_position);
- Vector3 pos_error = current_position - sc_position;
- //TSS081501
- if (Is_In_Elevator()) {
- position.Z = current_position.Z;
- }
- // Set_Position(sc_position);
- Peek_Human_Phys()->Network_State_Update(position,Vector3(0,0,0));
- }
- }
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Interpret_Sc_State_Data(
- HumanStateClass::HumanStateType state, int sub_state,
- LPCSTR trans_name, const Vector3 & velocity, const Vector3 & sc_position)
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- if ( ( Get_State() != state ) || ( Get_Sub_State() != sub_state ) ){
- if ( ( Get_State() == HumanStateClass::TRANSITION ) && // If in TRANSITION, don't switch to TRANSITION_COMPLETE
- ( state == HumanStateClass::TRANSITION_COMPLETE ) ) {
- // do nothing
- } else if ( ( Get_State() == HumanStateClass::UPRIGHT ) && // If UPRIGHT, don't switch to LAND
- ( state == HumanStateClass::LAND ) ) {
- // do nothing
- } else {
- if (Is_Controlled_By_Me() &&
- ((( Get_State() == HumanStateClass::UPRIGHT ) || ( Get_State() == HumanStateClass::AIRBORNE ) || ( Get_State() == HumanStateClass::LAND )) &&
- (( state == HumanStateClass::UPRIGHT ) || ( state == HumanStateClass::AIRBORNE ) || ( state == HumanStateClass::LAND )) )) {
- // do nothing
- // } else if (Is_Controlled_By_Me() == false) {
- } else {
- // take the new state
- if (state == HumanStateClass::TRANSITION) {
- Start_Transition_Animation( trans_name, NULL );
- AnimationName = trans_name;
- } else if (state == HumanStateClass::ANIMATION) {
- AnimationName = trans_name;
- HumanState.Start_Scripted_Animation( AnimationName, true, false );
- } else if (state == HumanStateClass::IN_VEHICLE) {
- HumanState.Force_Animation( trans_name, false );
- AnimationName = trans_name;
- }
- //TSS2001
- // if (state != HumanStateClass::IN_VEHICLE) {
- HumanState.Set_State( state, sub_state );
- // }
- }
- }
- }
-
- if (( state == HumanStateClass::AIRBORNE ) && ( this != COMBAT_STAR ) ) {
- Peek_Human_Phys()->Set_In_Contact( false );
- Peek_Human_Phys()->Set_Velocity( velocity );
- Peek_Human_Phys()->Set_Position( sc_position );
- }
- }
- //-----------------------------------------------------------------------------
- int SoldierGameObj::Tally_Vis_Visible_Soldiers( void )
- {
- int retcode = -1;
- Vector3 position;
- Get_Position(&position);
- position.Z += 1.5f;
- WWASSERT(COMBAT_SCENE != NULL);
- VisTableClass * pvs = COMBAT_SCENE->Get_Vis_Table(position);
-
- if (pvs != NULL) {
- retcode = 0;
- for (
- SLNode<SmartGameObj> * smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head();
- smart_objnode != NULL;
- smart_objnode = smart_objnode->Next()) {
- SoldierGameObj * p_soldier = smart_objnode->Data()->As_SoldierGameObj();
- if (p_soldier != NULL) {
- PhysClass * phys_obj = p_soldier->Peek_Physical_Object();
- if (phys_obj != NULL && pvs->Get_Bit(phys_obj->Get_Vis_Object_ID())) {
- retcode++;
- }
- }
- }
- }
- return retcode;
- }
- //-----------------------------------------------------------------------------
- bool SoldierGameObj::Is_In_Elevator( void )
- {
- HumanPhysClass * p_human_phys = Peek_Human_Phys();
- return
- p_human_phys != NULL &&
- p_human_phys->Peek_Carrier_Object() != NULL &&
- p_human_phys->Peek_Carrier_Object()->As_ElevatorPhysClass() != NULL;
- }
- //-----------------------------------------------------------------------------
- float SoldierGameObj::Get_Max_Speed( void )
- {
- return Peek_Human_Phys()->Get_Normalized_Speed();
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Max_Speed( float speed )
- {
- Peek_Human_Phys()->Set_Normalized_Speed( speed );
- }
- //------------------------------------------------------------------------------------
- float SoldierGameObj::Get_Turn_Rate( void )
- {
- return Get_Definition().TurnRate;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Generate_Control( void )
- {
- switch( Get_State() ) {
- case HumanStateClass::DEATH:
- // case HumanStateClass::WOUNDED:
- // case HumanStateClass::DESTROY:
- Clear_Control();
- break;
- default:
- SmartGameObj::Generate_Control();
- break;
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Apply_Control( void )
- {
- // if gameplay not permitted, skip
- if ( !CombatManager::Is_Gameplay_Permitted() ) {
- Clear_Control();
- Controller.Reset();
- return;
- }
- #ifdef WWDEBUG
- // Change the control before applying
- if ( IS_SOLOPLAY && Is_Human_Controlled() && Input::Get_State( INPUT_FUNCTION_DEBUG_RAPID_MOVE ) ) {
- if ( InFlyMode ) {
- Control.Set_Analog( ControlClass::ANALOG_MOVE_UP,
- Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) );
- Control.Set_Analog( ControlClass::ANALOG_MOVE_FORWARD, 0 );
- } else {
- Control.Set_Analog( ControlClass::ANALOG_MOVE_FORWARD,
- Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) * 10 );
- }
- }
- #endif
- if ( Get_State() == HumanStateClass::IN_VEHICLE ) {
- // Handle Vehicle Gunner Toggle
- if ( Get_Vehicle() && Get_Vehicle()->Get_Driver() == this ) {
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_VEHICLE_TOGGLE_GUNNER ) ) {
- Get_Vehicle()->Toggle_Driver_Is_Gunner();
- }
- }
- if ( CombatManager::I_Am_Server() ) // Server authoritative
- // if ( CombatManager::I_Am_Server() ||
- // (Is_Controlled_By_Me() && TransitionCompletionData == NULL) )
- {
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_ACTION ) ) {
- TransitionManager::Check( this, true );
- }
- }
- return;
- }
- if ( ( Get_State() == HumanStateClass::TRANSITION ) ||
- ( Get_State() == HumanStateClass::ANIMATION ) ||
- ( Get_State() == HumanStateClass::DESTROY ) ||
- ( Get_State() == HumanStateClass::DEATH ) ||
- ( Get_State() == HumanStateClass::ON_FIRE ) ||
- ( Get_State() == HumanStateClass::ON_CHEM ) ||
- ( Get_State() == HumanStateClass::ON_CNC_FIRE ) ||
- ( Get_State() == HumanStateClass::ON_CNC_CHEM ) ||
- ( Get_State() == HumanStateClass::ON_ELECTRIC ) ) {
- // Force exit of the corpse mode
- if ( Get_State() == HumanStateClass::DESTROY && Is_Human_Controlled() ) {
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_WEAPON_FIRE_PRIMARY ) ) {
- HumanState.Set_State_Timer( 1000 ); // Done!
- }
- }
- // Debug_Say(( "No Control in transition\n" ));
- Clear_Control();
- // Controller.Reset();
- // return;
- }
- if ( Get_State() == HumanStateClass::DIVE ) {
- Clear_Control();
- SmartGameObj::Apply_Control();
- Vector3 forced_move(0,0,0);
- int sub_state = HumanState.Get_Sub_State();
- if ( sub_state & HumanStateClass::SUB_STATE_FORWARD ) forced_move = Vector3( 0.5f,0,0 );
- if ( sub_state & HumanStateClass::SUB_STATE_BACKWARD ) forced_move = Vector3( -0.5f,0,0 );
- if ( sub_state & HumanStateClass::SUB_STATE_LEFT ) forced_move = Vector3( 0,0.5f,0 );
- if ( sub_state & HumanStateClass::SUB_STATE_RIGHT ) forced_move = Vector3( 0,-0.5f,0 );
- Controller.Set_Move_Forward( forced_move.X );
- Controller.Set_Move_Left( forced_move.Y );
- Controller.Set_Move_Up( forced_move.Z );
- return;
- }
- #define CLIMB_SCALE 0.3f
- // Skip all this if control is clear?!?!?!
- if ( Get_State() == HumanStateClass::LADDER ) {
- // Convert Forward motion to Up motion
- float up_down = CLIMB_SCALE * Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD );
- if ( Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) == 0 ) {
- LadderUpMask = false;
- LadderDownMask = false;
- }
- if ( LadderUpMask ) {
- up_down = MIN( up_down, 0 );
- }
- if ( LadderDownMask ) {
- up_down = MAX( up_down, 0 );
- }
- // when on ladder, clear all velocity
- Control.Set_Analog( ControlClass::ANALOG_MOVE_UP, up_down );
- // Can't clear this, or we wont be able to climb next net frame!!!
- // Control.Set_Analog( ControlClass::ANALOG_MOVE_FORWARD, 0 );
- Control.Set_Analog( ControlClass::ANALOG_MOVE_LEFT, 0 );
- Control.Set_Analog( ControlClass::ANALOG_TURN_LEFT, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_JUMP, 0 );
- } else {
- LadderUpMask = false;
- LadderDownMask = false;
- // no move up
- if ( !InFlyMode ) {
- Control.Set_Analog( ControlClass::ANALOG_MOVE_UP, 0 );
- }
- }
- #if 0
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_CROUCH ) ) {
- if ( HumanState.Is_Sub_State_Adjustable() ) {
- // HumanState.Set_Sub_State( Get_Sub_State() ^ HumanStateClass::CROUCHED );
- HumanState.Toggle_State_Flag( HumanStateClass::CROUCHED_FLAG );
- if ( this == COMBAT_STAR ) {
- Vector3 pos;
- Get_Position( &pos );
- if ( Is_Crouched() ) {
- DIAG_LOG(( "COEN", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- } else {
- DIAG_LOG(( "COEX", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- }
- }
- }
- }
- #else
- if ( HumanState.Is_Sub_State_Adjustable() ) {
- bool new_state = Control.Get_Boolean( ControlClass::BOOLEAN_CROUCH );
- bool old_state = HumanState.Get_State_Flag( HumanStateClass::CROUCHED_FLAG );
- if ( new_state != old_state ) {
-
- HumanState.Toggle_State_Flag( HumanStateClass::CROUCHED_FLAG );
- if ( this == COMBAT_STAR ) {
- Vector3 pos;
- Get_Position( &pos );
- if ( Is_Crouched() ) {
- DIAG_LOG(( "COEN", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- } else {
- DIAG_LOG(( "COEX", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- }
- }
- }
- }
- #endif
- /*
- if ( CombatManager::I_Am_Server() &&
- Control.Get_Boolean(ControlClass::BOOLEAN_DROP_FLAG) ) {
- CombatManager::Soldier_Drops_Flag(this);
- }
- */
- DetonateC4 = false;
- if ( Get_Weapon() && Control.Get_Boolean( ControlClass::BOOLEAN_WEAPON_USE ) ) {
- if ( Get_Weapon()->Get_Style() == WEAPON_HOLD_STYLE_C4 ) {
- DetonateC4 = true;
- }
- if ( Get_Weapon()->Get_Can_Snipe() ) {
- if ( HumanState.Is_Sub_State_Adjustable() ) {
- HumanState.Toggle_State_Flag( HumanStateClass::SNIPING_FLAG );
- }
- }
- }
- #if 0
- if ( Is_Sniping() ) {
- // No motion for snipers (I don't know if this should be in Soldier.cpp)
- // (But then, Sniper mode means nothing for plain soldiers, only for players)
- // Don't clear the move forward, just don't allow the controller to have
- // any move forward. This was not alowing sniper zoom
- // Control.Set_Analog( ControlClass::ANALOG_MOVE_FORWARD, 0 );
- Control.Set_Analog( ControlClass::ANALOG_MOVE_LEFT, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_JUMP, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_CROUCH, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_FORWARD, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_BACKWARD, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_LEFT, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_RIGHT, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_ACTION, 0 ); // stop ladder
- }
- #endif
- if ( Is_Sniping() || Is_On_Ladder() ) {
- // No diving for snipers or on ladders
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_FORWARD, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_BACKWARD, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_LEFT, 0 );
- Control.Set_Boolean( ControlClass::BOOLEAN_DIVE_RIGHT, 0 );
- }
- bool dove = false;
- // Can only dive if upright
- if ( Get_State() == HumanStateClass::UPRIGHT ) {
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_DIVE_FORWARD ) ) {
- HumanState.Set_State( HumanStateClass::DIVE, HumanStateClass::SUB_STATE_FORWARD );
- dove = true;
- }
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_DIVE_BACKWARD ) ) {
- HumanState.Set_State( HumanStateClass::DIVE, HumanStateClass::SUB_STATE_BACKWARD );
- dove = true;
- }
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_DIVE_LEFT ) ) {
- HumanState.Set_State( HumanStateClass::DIVE, HumanStateClass::SUB_STATE_LEFT );
- dove = true;
- }
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_DIVE_RIGHT ) ) {
- HumanState.Set_State( HumanStateClass::DIVE, HumanStateClass::SUB_STATE_RIGHT );
- dove = true;
- }
- if ( dove && this == COMBAT_STAR ) {
- Vector3 pos;
- Get_Position( &pos );
- DefenseObjectClass * defense = Get_Defense_Object();
- const char * weapon_name = "";
- int ammo = 0;
- if ( Get_Weapon() != NULL ) {
- weapon_name = Get_Weapon()->Get_Definition()->Get_Name();
- ammo = Get_Weapon()->Get_Total_Rounds();
- }
- DIAG_LOG(( "ROUS", "%1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %s; %d", pos.X, pos.Y, pos.Z, defense->Get_Shield_Strength(), defense->Get_Health(), weapon_name, ammo ));
- }
- }
- // Handle facing
- float amount = Control.Get_Analog( ControlClass::ANALOG_TURN_LEFT );
- if ( COMBAT_STAR == this ) { // Star gets turning from the camera
- amount = 0;
- }
- if ( amount != 0 ) {
- float heading = Peek_Human_Phys()->Get_Heading();
- heading += amount * Get_Turn_Rate() * TimeManager::Get_Frame_Seconds();
- heading = WWMath::Wrap( heading, DEG_TO_RADF( -180.0f ), DEG_TO_RADF( 180.0f ) );
- Peek_Human_Phys()->Set_Heading(heading);
- Control.Set_Analog(ControlClass::ANALOG_TURN_LEFT,0.0f);
- if ( !Is_Human_Controlled() ) { // human players don't use turn anims
- HumanState.Set_Turn_Velocity( amount ); // play the leg turning anim
- }
- }
- // Let parent class handle the rest
- SmartGameObj::Apply_Control();
- #if 01
- // Have to Move_Up after after Apply control, but BOOLEAN_JUMP is cleared
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_JUMP ) ) {
- if ( Get_State() != HumanStateClass::AIRBORNE ) {
- Controller.Set_Move_Up( Get_Definition().JumpVelocity );
- }
- if ( this == COMBAT_STAR ) {
- Vector3 pos;
- Get_Position( &pos );
- DefenseObjectClass * defense = Get_Defense_Object();
- const char * weapon_name = "";
- int ammo = 0;
- if ( Get_Weapon() != NULL ) {
- weapon_name = Get_Weapon()->Get_Definition()->Get_Name();
- ammo = Get_Weapon()->Get_Total_Rounds();
- }
- DIAG_LOG(( "JUUS", "%1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %s; %d", pos.X, pos.Y, pos.Z, defense->Get_Shield_Strength(), defense->Get_Health(), weapon_name, ammo ));
- }
- }
- #else
- static float jump_timer = 0;
- // Have to Move_Up after after Apply control, but BOOLEAN_JUMP is cleared
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_JUMP ) ) {
- if ( Get_State() != HumanStateClass::AIRBORNE ) {
- HumanState.Set_State( HumanStateClass::AIRBORNE, HumanState.Get_Sub_State() );
- jump_timer = 0.2f;
- }
- }
- if ( jump_timer > 0 ) {
- jump_timer -= TimeManager::Get_Frame_Seconds();
- if ( jump_timer <= 0 ) {
- Controller.Set_Move_Up( Get_Definition().JumpVelocity );
- }
- }
- #endif
- #if 0
- if ( Is_Sniping() ) {
- // Dont allow move forward. It may have been requested by the
- // Control, because we can't clear it if it must persist for
- // network sniper zoom. So just clear it here.
- Controller.Set_Move_Forward( 0 );
- }
- #else
- if ( Is_Sniping() ) {
- // Dont allow move forward. It may have been requested by the
- // Control, because we can't clear it if it must persist for
- // network sniper zoom. So just clear it here.
- Controller.Set_Move_Forward( WWMath::Clamp( Controller.Get_Move_Forward(), -0.25f, 0.25f ) );
- Controller.Set_Move_Left( WWMath::Clamp( Controller.Get_Move_Left(), -0.25f, 0.25f ) );
- }
- #endif
- if ( Get_State() == HumanStateClass::LADDER ) {
- // When on ladder, you can't move forward
- // Same rules as above wrt the network persistence
- Controller.Set_Move_Forward( 0 );
- }
- if ( ( Get_State() == HumanStateClass::UPRIGHT ) && Is_Crouched() ) {
- float crouch_speed = GlobalSettingsDef::Get_Global_Settings ()->Get_Soldier_Crouch_Speed();
- Controller.Set_Move_Forward( Controller.Get_Move_Forward() * crouch_speed );
- Controller.Set_Move_Left( Controller.Get_Move_Left() * crouch_speed );
- } else if ( Control.Get_Boolean( ControlClass::BOOLEAN_WALK ) ) {
- float walk_speed = GlobalSettingsDef::Get_Global_Settings ()->Get_Soldier_Walk_Speed();
- Controller.Set_Move_Forward( Controller.Get_Move_Forward() * walk_speed );
- Controller.Set_Move_Left( Controller.Get_Move_Left() * walk_speed );
- }
- if ( this == COMBAT_STAR ) {
- static bool was_walking = false;
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_WALK ) != was_walking ) {
- Vector3 pos;
- Get_Position( &pos );
- if ( !was_walking ) {
- DIAG_LOG(( "WAEN", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- } else {
- DIAG_LOG(( "WAEX", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- }
- was_walking = Control.Get_Boolean( ControlClass::BOOLEAN_WALK );
- }
- }
- if ( this == COMBAT_STAR && Control.Get_Boolean( ControlClass::BOOLEAN_ACTION ) ) {
- Vector3 pos;
- COMBAT_STAR->Get_Position( &pos );
- DIAG_LOG(( "ACPR", "%1.2f; %1.2f; %1.2f", pos.X, pos.Y, pos.Z ));
- }
- if ( CombatManager::I_Am_Server() ||
- (Is_Controlled_By_Me() && TransitionCompletionData == NULL) )
- {
- bool action_triggered = Control.Get_Boolean( ControlClass::BOOLEAN_ACTION );
- /// Transitions only trigger on server
- bool transition_triggered = false;
- if ( CombatManager::I_Am_Server() ) {
- transition_triggered = TransitionManager::Check( this, action_triggered );
- }
- if ( !transition_triggered ) {
- if ( action_triggered ) {
- //
- // Lookup the current target
- //
- // DamageableGameObj *damageable_target = HUDInfo::Get_Weapon_Target_Object();
- DamageableGameObj *damageable_target = HUDInfo::Get_Info_Object();
- if ( damageable_target != NULL ) {
- PhysicalGameObj *physical_target = damageable_target->As_PhysicalGameObj();
- if ( physical_target != NULL ) {
- Vector3 target_pos;
- physical_target->Get_Position( &target_pos );
- Vector3 my_pos;
- Get_Position( &my_pos );
- //
- // Check to see if the target is within the "poke" range
- //
- if ( (target_pos - my_pos).Length() <= 2 ) {
- //
- // Notify all the observers
- //
- if ( CombatManager::I_Am_Server () ) {
- const GameObjObserverList & observer_list = physical_target->Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- observer_list[ index ]->Poked( physical_target, this );
- }
- }
- //
- // Was the player the soldier who did the poking?
- //
- if ( COMBAT_STAR == this ) {
- //
- // Display this object in the encyclopedia
- //
- EncyclopediaMgrClass::Reveal_Object( damageable_target );
-
- //
- // Check for player terminal access
- //
- if ( physical_target->As_SimpleGameObj () != NULL ) {
-
- //
- // Is this a player terminal?
- //
- PlayerTerminalClass::TYPE type = PlayerTerminalClass::TYPE_NONE;
- type = (physical_target->As_SimpleGameObj())->Get_Definition().Get_Player_Terminal_Type();
- if (type != PlayerTerminalClass::TYPE_NONE) {
- //
- // Show the player terminal
- //
- PlayerTerminalClass::Get_Instance()->Display_Terminal( this, type );
- }
- }
- }
- }
- }
- }
- }
- } else {
- // We started a transition, clear the control
- Controller.Reset();
- }
- }
- // Override the following controls
- if ( IS_SOLOPLAY && Is_Human_Controlled() && Input::Get_State( INPUT_FUNCTION_DEBUG_RAPID_MOVE ) ) {
- if ( Control.Get_Boolean( ControlClass::BOOLEAN_JUMP ) ) {
- Controller.Set_Move_Up( Get_Definition().JumpVelocity );
- }
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Handle_Legs( void )
- {
- #if 0
- if ( Get_State() != HumanStateClass::UPRIGHT ) {
- LegFacing = Get_Facing();
- SyncLegs = false;
- }
- // If Moving, clear LegFacing
- if ((Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) != 0.0f ) ||
- (Control.Get_Analog( ControlClass::ANALOG_MOVE_LEFT ) != 0.0f )) {
- LegFacing = Get_Facing();
- SyncLegs = false;
- } else {
- #define CLAMP_DEGREES 60
- #define SYNC_DEGREES 35
- #define SYNC_RATE 75
- #define FLIP_RATE 720
- // find the leg difference;
- LegFacing = WWMath::Wrap( LegFacing, DEG_TO_RADF( -180 ), DEG_TO_RADF( 180 ) );
- float legs_rotation = Get_Facing() - LegFacing;
- legs_rotation = WWMath::Wrap( legs_rotation, DEG_TO_RADF( -180 ), DEG_TO_RADF( 180 ) );
- // Clamp to with 90
- legs_rotation = WWMath::Clamp( legs_rotation, DEG_TO_RADF( -CLAMP_DEGREES ), DEG_TO_RADF( CLAMP_DEGREES ) );
- LegFacing = Get_Facing() - legs_rotation;
- LegFacing = WWMath::Wrap( LegFacing, DEG_TO_RADF( -180 ), DEG_TO_RADF( 180 ) );
- // if legs are more than 30 degrees off, start correcting
- if ( WWMath::Fabs( legs_rotation ) > DEG_TO_RAD( SYNC_DEGREES ) ) {
- SyncLegs = true;
- }
- SyncLegs = true;
- // if syncing, start moving legs to match rotation
- if ( SyncLegs ) {
- float move = DEG_TO_RAD( SYNC_RATE ) * TimeManager::Get_Frame_Seconds() *
- WWMath::Sign( legs_rotation );
- if ( WWMath::Fabs( move ) >= WWMath::Fabs( legs_rotation ) ) {
- move = legs_rotation; // Complete syncing
- SyncLegs = false;
- } else {
- LegFacing += move;
- if ( !Is_Human_Controlled() ) { // human players don't use turn anims
- HumanState.Set_Turn_Velocity( move ); // Also, play the leg turning anim
- }
- }
- }
- }
- if ( !SyncLegs ) {
- HumanState.Set_Turn_Velocity( 0 );
- }
- // I'm making this staic for now, because all human
- // skeletons have the bone at the same index
- static int root_bone = -1;
- if ( root_bone == -1 ) { // Get root bone index
- root_bone = Peek_Model()->Get_Bone_Index( "root" );
- }
- static int torso_bone = -1;
- if ( torso_bone == -1 ) { // Get torso bone index
- torso_bone = Peek_Model()->Get_Bone_Index( "thorax" );
- }
- // Update the model
- float legs_rotation = Get_Facing() - LegFacing;
- if ( legs_rotation ) {
- WWASSERT( root_bone != -1 );
- WWASSERT( torso_bone != -1 );
- if ( !Peek_Model()->Is_Bone_Captured( root_bone ) ) {
- Peek_Model()->Capture_Bone( root_bone );
- }
- if ( !Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
- Peek_Model()->Capture_Bone( torso_bone );
- }
- // LOOK INTO RELATIVE_CONTROL_BONE
- Matrix3D root_adjust(1); // adjust it
- root_adjust.Rotate_Z( -legs_rotation );
- Peek_Model()->Control_Bone( root_bone, root_adjust );
- Matrix3D legs_adjust(1); // adjust it
- legs_adjust.Rotate_Z( legs_rotation );
- Peek_Model()->Control_Bone( torso_bone, legs_adjust );
- } else { // no adjustment, release
- if ( Peek_Model()->Is_Bone_Captured( root_bone ) ) {
- Peek_Model()->Release_Bone( root_bone );
- }
- if ( Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
- Peek_Model()->Release_Bone( torso_bone );
- }
- }
- #else
- #if 0
- float legs_rotation = 0;
- // Compare the facing to the motion, set leg_racing to the difference
- Vector3 move( Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ), Control.Get_Analog( ControlClass::ANALOG_MOVE_LEFT ), 0 );
- if ( move.Length() > 0 ) {
- float move_direction = ::WWMath::Atan2( -move.Y, move.X );
- float diff = move_direction;
- diff += 2*DEG_TO_RADF( 360 ) + DEG_TO_RADF( 45 );
- diff -= WWMath::Floor( diff / DEG_TO_RADF( 90 ) ) * DEG_TO_RADF( 90 );
- diff -= DEG_TO_RADF( 45 );
- legs_rotation = diff;
- Debug_Say(( "Move (%1.1f) %1.1f %1.1f %1.1f %1.1f\n", RAD_TO_DEG(diff), move.X, move.Y, move.Z, RAD_TO_DEG( move_direction ) ));
- }
- // I'm making this staic for now, because all human
- // skeletons have the bone at the same index
- static int root_bone = -1;
- if ( root_bone == -1 ) { // Get root bone index
- root_bone = Peek_Model()->Get_Bone_Index( "c spine" );
- }
- static int torso_bone = -1;
- if ( torso_bone == -1 ) { // Get torso bone index
- torso_bone = Peek_Model()->Get_Bone_Index( "c spine1" );
- }
- if ( legs_rotation ) {
- WWASSERT( root_bone != -1 );
- WWASSERT( torso_bone != -1 );
- if ( !Peek_Model()->Is_Bone_Captured( root_bone ) ) {
- Peek_Model()->Capture_Bone( root_bone );
- }
- if ( !Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
- Peek_Model()->Capture_Bone( torso_bone );
- }
- Matrix3D root_adjust(1); // adjust it
- root_adjust.Rotate_X( legs_rotation );
- Peek_Model()->Control_Bone( root_bone, root_adjust );
- Matrix3D legs_adjust(1); // adjust it
- legs_adjust.Rotate_X( -legs_rotation );
- Peek_Model()->Control_Bone( torso_bone, legs_adjust );
- } else { // no adjustment, release
- if ( Peek_Model()->Is_Bone_Captured( root_bone ) ) {
- Peek_Model()->Release_Bone( root_bone );
- }
- if ( Peek_Model()->Is_Bone_Captured( torso_bone ) ) {
- Peek_Model()->Release_Bone( torso_bone );
- }
- }
- #endif
- #endif
- bool do_steps = false;
- if ( Is_On_Ladder() ) {
- do_steps = (Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) != 0.0f );
- } else {
- do_steps = ((Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) != 0.0f ) ||
- (Control.Get_Analog( ControlClass::ANALOG_MOVE_LEFT ) != 0.0f ));
- }
- // Footsteps
- if (!Is_Sniping() && !InFlyMode && CombatManager::Is_Gameplay_Permitted() && do_steps && Is_Control_Enabled() ) {
- bool leg_mode = HumanState.Get_Leg_Mode();
- // Watch for the legs to reach certain percentage completions
- if ( leg_mode != LastLegMode ) {
- int my_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_RUN;
- if ( Is_Crouched() ) {
- my_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_CROUCHED;
- } else if ( HumanState.Get_Sub_State() & HumanStateClass::SUB_STATE_SLOW ) {
- my_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_WALK;
- }
- int ground_type = Peek_Human_Phys()->Get_Contact_Surface_Type();
- // Try effects on ladders again BMG
- /**/if ( Is_On_Ladder() ) {
- my_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_LADDER;
- ground_type = SURFACE_TYPE_LIGHT_METAL;
- }/**/
- Matrix3D tm;
- tm = Get_Transform();
- if ( Control.Get_Analog( ControlClass::ANALOG_MOVE_FORWARD ) != 0.0f ) {
- tm.Rotate_Z( DEG_TO_RAD( -90 ) );
- }
- float offset = leg_mode ? -0.15f : 0.1f;
- tm.Translate( Vector3( offset, 0.3f, 0 ) );
-
- bool allow_emitters = !Is_Stealthed();
- SurfaceEffectsManager::Apply_Effect( ground_type, my_type, tm, NULL, this, true, allow_emitters);
- LastLegMode = leg_mode;
- }
- }
- }
- static float _shake_delay = 0;
- static float _cry_delay = 0;
- static char * _profile_name = "Soldier Think";
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Think( void )
- {
- { WWPROFILE( _profile_name );
- if ( this == COMBAT_STAR ) {
- _shake_delay -= TimeManager::Get_Frame_Seconds();
- _cry_delay -= TimeManager::Get_Frame_Seconds();
- }
- /*
- ActionClass * p_action = Get_Action();
- WWASSERT(p_action != NULL);
- */
-
- //
- // Simply check to see if this soldier has entered a coordination zone (which bound
- // the entrances/exits of ladders and elevators). If so, then disable
- // collision between them and all other soldiers.
- //
- Vector3 position;
- {
- WWPROFILE("Coordination Zone");
- Get_Position( &position );
- if ( UnitCoordinationZoneMgr::Is_Unit_In_Zone( position ) ) {
- Enable_Ghost_Collision( true );
- } else if ( Is_Safe_To_Disable_Ghost_Collision( position ) ) {
- Enable_Ghost_Collision( false );
- }
- }
- //
- // Display a debug box to show the ghosted collision as ncessary
- //
- if ( DisplayDebugBoxForGhostCollision &&
- (Peek_Physical_Object ()->Get_Collision_Group() == SOLDIER_GHOST_COLLISION_GROUP))
- {
- WWPROFILE("Add_Debug_AABox");
- AABoxClass soldier_box;
- soldier_box.Center = position + Vector3( 0, 0, 1.0F );
- soldier_box.Extent.Set( 0.3F, 0.3F, 1.0F );
- PhysicsSceneClass::Get_Instance ()->Add_Debug_AABox( soldier_box, Vector3( 1.0F, 0.0F, 0.25F ) );
- }
- // Stats
- if ( Get_Player_Data() != NULL ) {
- WWPROFILE("Stats");
- Get_Player_Data()->Stats_Add_Game_Time( TimeManager::Get_Frame_Seconds() );
- Get_Player_Data()->Stats_Set_Final_Health( Get_Defense_Object()->Get_Health() );
- if ( Get_Vehicle() != NULL ) {
- Get_Player_Data()->Stats_Add_Vehicle_Time( TimeManager::Get_Frame_Seconds() );
- }
- }
- //
- // Update the soldier's facing
- //
- {
- WWPROFILE("Update_Locked_Facing");
- Update_Locked_Facing();
- }
- /*
- //
- // In CTF a flag-bearer may not be permitted to use weapons
- // This code will deselect the weapon if that is the case.
- //
- if (CombatManager::I_Am_Server() && Get_Weapon() != NULL &&
- !CombatManager::Is_Firing_Enabled(this)) {
- Get_Weapon_Bag()->Deselect();
- }
- */
- // Handle_Legs moved form Apply_Control because clients don't run it for server objects
- {
- WWPROFILE("Handle_Legs");
- Handle_Legs();
- }
- /*
- if (CombatManager::I_Am_Server()) {
- TransitionManager::Check( this );
- }*/
- }
- {
- WWPROFILE( "Embedded smart think in soldier" );
- SmartGameObj::Think(); // Perform smart object thinking ( apply controls )
- }
- {
- WWPROFILE( _profile_name );
- if ( CombatManager::I_Am_Server() ) {
- WWPROFILE("Handle C4");
- // Handle C4 in a special way. When C4 is fired, the human plays
- // a crouching animation, and starts a c4 placement timer.
- if ( Get_Weapon() &&
- (Get_Weapon()->Get_Style() == WEAPON_HOLD_STYLE_C4) &&
- (Get_Weapon()->Is_Firing()) &&
- (Get_State() == HumanStateClass::UPRIGHT) ) {
- AnimationName = "s_a_human.h_a_j12c";
- HumanState.Start_Scripted_Animation( AnimationName, true, false );
- }
- }
- if ( Get_State() != HumanStateClass::IN_VEHICLE ) {
- WWPROFILE("Vehicle");
- // This may try to change controls, so can't be in Post_Think
- HumanState.Update_Weapon( Get_Weapon(), WeaponBag->Is_Changed() );
- if ( WeaponBag->Is_Changed() ) {
- WeaponChanged = true;
- WeaponBag->Reset_Changed();
- }
- // HumanState.Update_Aiming( Get_Weapon_Tilt(), Get_Weapon_Turn() );
- HumanState.Update_State();
- // Remove C4 from hand if empty
- if ( Get_Weapon() && WeaponRenderModel ) {
- if ( Get_Weapon()->Get_Style() == WEAPON_HOLD_STYLE_C4 || Get_Weapon()->Get_Style() == WEAPON_HOLD_STYLE_BEACON ) {
- WeaponRenderModel->Set_Hidden( !Get_Weapon()->Is_Loaded() );
- } else {
- WeaponRenderModel->Set_Hidden( false );
- }
- }
- } else {
- // Debug_Say(( "No state update in vehicle\n" ));
- }
- /*
- ** Special Death
- */
- // ArmorWarheadManager::SpecialDamageType SpecialDamageMode;
- // float SpecialDamageTimer;
- if ( SpecialDamageMode != ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE &&
- SpecialDamageTimer > 0 ) {
- WWPROFILE("Special Damage");
- float previous_timer = SpecialDamageTimer;
- SpecialDamageTimer -= TimeManager::Get_Frame_Seconds();
- // Once a second, make an explosion
- if ( (int)SpecialDamageTimer != (int)previous_timer ) {
- StringClass explosion_name = ArmorWarheadManager::Get_Special_Damage_Explosion( SpecialDamageMode );
- if ( !explosion_name.Is_Empty() ) {
- ExplosionDefinitionClass * def = (ExplosionDefinitionClass *)DefinitionMgrClass::Find_Typed_Definition( explosion_name, CLASSID_DEF_EXPLOSION );
- if ( def != NULL) {
- Vector3 pos = Get_Bullseye_Position();
- ExplosionManager::Create_Explosion_At( def->Get_ID(), pos, NULL );
- }
- }
- }
- // Fix to allow taking fire damage in CNC
- // if ( Get_Defense_Object()->Get_Health() > 0 && Allow_Special_Damage_State_Lock () ) {
- if ( Get_Defense_Object()->Get_Health() > 0 &&
- (Allow_Special_Damage_State_Lock () || Is_Human_Controlled() ) ) {
- // do damage
- WarheadType warhead = ArmorWarheadManager::Get_Special_Damage_Warhead( SpecialDamageMode );
- float damage = ArmorWarheadManager::Get_Special_Damage_Scale( SpecialDamageMode ) *
- TimeManager::Get_Frame_Seconds();
- OffenseObjectClass off( damage, warhead, (ArmedGameObj*)SpecialDamageDamager.Get_Ptr() );
- // Apply_Damage( off, 1 );
- Apply_Damage_Extended( off, 1 );
- }
- if ( HumanState.Get_State() != HumanStateClass::DEATH ) {
- // if dead, play death
- if ( Get_Defense_Object()->Get_Health() <= 0 ) {
- HumanState.Set_State( HumanStateClass::DEATH,
- SpecialDamageMode - ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_FIRE + HumanStateClass::OUCH_FIRE );
- }
- if ( SpecialDamageTimer <= 0 ) { // Stop the flame
- // HumanState.Set_State( HumanStateClass::UPRIGHT );
- Set_Special_Damage_Mode( ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE );
- }
- }
- }
- if (Get_State() == HumanStateClass::DESTROY) {
- if ( HumanState.Get_State_Timer() > CORPSE_PERSIST_TIME ) {
- // If Human Controlled, drop a backpack
- if ( Is_Human_Controlled() ) {
- // PowerUpGameObj::Create_Backpack( this ); // No more backpacks
- }
- Set_Delete_Pending();
- }
- }
- // ClientOnlys doen't handle TRANSITION_COMPLETE
- if ( !CombatManager::I_Am_Only_Client() || Is_Controlled_By_Me()) {
- if ( Get_State() == HumanStateClass::TRANSITION_COMPLETE ) {
- if ( TransitionCompletionData != NULL ) {
- // Debug_Say(( "Ended Transition %p\n", Transition ));
- // We just completed a transition, notify
- TransitionInstanceClass::End( this, TransitionCompletionData );
- TransitionCompletionData = NULL;
- } else {
- // Debug_Say(( "Ended Unknown Transition %p\n", Transition ));
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- }
- }
- }
- //
- // Remove the emot icon (if necessary)
- //
- {
- WWPROFILE("EmotIcon");
- EmotIconTimer -= TimeManager::Get_Frame_Seconds();
- if ( EmotIconTimer <= 0 ) {
- //
- // Remove the emoticon
- //
- if ( EmotIconModel != NULL && EmotIconModel->Is_In_Scene() ) {
- EmotIconModel->Remove();
- REF_PTR_RELEASE( EmotIconModel );
- }
- } else if ( EmotIconModel != NULL ) {
- //
- // Put the icon over the soldier's head
- //
- Matrix3D tm = Get_Transform();
- tm.Set_Translation (tm.Get_Translation() + Vector3 (0, 0, EMOT_ICON_HEIGHT));
- EmotIconModel->Set_Transform( tm );
- }
- }
- //
- // Should we change the idle facial animation?
- //
- GenerateIdleFacialAnimTimer -= TimeManager::Get_Frame_Seconds();
- if ( GenerateIdleFacialAnimTimer <= 0 ) {
- WWPROFILE("FacialAnims");
-
- //
- // Change the facial animation
- //
- if ( HeadModel != NULL ) {
- // Don't stop a playing script animation
- if ( ( HeadModel->Peek_Animation() == NULL ) ||
- (HeadModel->Peek_Animation() == SpeechAnim ) ) {
- SpeechAnim->Generate_Idle_Animation( 20, 0.5F );
- HeadModel->Set_Animation( SpeechAnim, 0, RenderObjClass::ANIM_MODE_LOOP );
- }
- }
- //
- // Reset the timer
- //
- GenerateIdleFacialAnimTimer = 100.0F;
- }
- /*
- if (!Is_Destroy()) {
- CombatManager::Set_Soldier_Tint(this);
- }
- */
- // Apply Surface damage
- {
- WWPROFILE("Apply_Damage");
- if ( Peek_Human_Phys() ) {
- SurfaceEffectsManager::Apply_Damage( Peek_Human_Phys()->Get_Contact_Surface_Type(), this );
- }
- }
- // Update the water wake
- // - If our feet are not on "underwater dirt" we don't even check for water
- // - Otherwise, do a ray cast to find the water surface, if it hits
- {
- WWPROFILE("Water");
- bool in_water = false;
- Vector3 p0 = Get_Transform().Get_Translation();
- Vector3 p1 = Get_Bullseye_Position();
- int hit_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_RUN;
- if ( Is_Crouched() ) {
- hit_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_CROUCHED;
- } else if ( HumanState.Get_Sub_State() & HumanStateClass::SUB_STATE_SLOW ) {
- hit_type = SurfaceEffectsManager::HITTER_TYPE_FOOTSTEP_WALK;
- }
- Vector3 vel;
- Peek_Human_Phys()->Get_Velocity(&vel);
- if ((Peek_Human_Phys()->Get_Contact_Surface_Type() == SURFACE_TYPE_UNDERWATER_DIRT) &&
- (vel.Length2() > 0.1f))
- {
-
- // Raycast to find water surface
- CastResultStruct res;
- LineSegClass ray(p0,p1);
- PhysRayCollisionTestClass raytest(ray,&res,BULLET_COLLISION_GROUP,COLLISION_TYPE_PROJECTILE);
-
- Peek_Human_Phys()->Inc_Ignore_Counter();
- COMBAT_SCENE->Cast_Ray(raytest);
- Peek_Human_Phys()->Dec_Ignore_Counter();
- // if found update emitter
- if ((res.Fraction < 1.0f) && (res.SurfaceType == SURFACE_TYPE_WATER_PERMEABLE)) {
- Vector3 point;
- ray.Compute_Point(res.Fraction,&point);
- SurfaceEffectsManager::Update_Persistant_Emitter( WaterWake,
- res.SurfaceType,
- hit_type,
- Matrix3D(point));
- in_water = true;
- }
- }
-
- if (!in_water) {
- SurfaceEffectsManager::Update_Persistant_Emitter( WaterWake,
- SURFACE_TYPE_DEFAULT,
- hit_type,
- Matrix3D(p0));
- }
- }
- // Punish update
- if ( Get_Player_Data() && Get_Player_Data()->Get_Punish_Timer() > 0 ) {
- Get_Player_Data()->Inc_Punish_Timer( TimeManager::Get_Frame_Seconds() ) ;
- }
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Post_Think( void )
- {
- if ( Get_State() == HumanStateClass::IN_VEHICLE ) {
- SmartGameObj::Post_Think();
- return;
- }
- { WWPROFILE( "Soldier PostThink" );
- HumanState.Post_Think();
- bool update_weapon = false;
- if ( WeaponChanged ) {
- WeaponChanged = false;
- Update_Back_Gun();
- update_weapon = true;
- }
- if ( ( Get_Weapon() != NULL ) && ( Get_Weapon()->Is_Model_Update_Needed() ) ) {
- update_weapon = true;
- Get_Weapon()->Reset_Model_Update(); // reset model update needed
- }
- if ( update_weapon ) {
- if ( Get_Weapon() != NULL ) {
- Set_Weapon_Model( Get_Weapon()->Get_Model_Name() );
- } else {
- Set_Weapon_Model( NULL );
- }
- }
- // if ( Get_Weapon()->Is_Anim_Update_Needed() ) {
- // Set_Weapon_Animation( Get_Weapon()->Get_Anim_Name() );
- // Get_Weapon()->Reset_Anim_Update(); // reset model anim update needed
- // }
- if (WeaponAnimControl) {
- WeaponAnimControl->Update( TimeManager::Get_Frame_Seconds() ); // update the animation control
- }
- Handle_Head_look();
- if ( Get_Weapon() != NULL && Get_State() == HumanStateClass::ON_FIRE ) {
- Get_Weapon()->Set_Primary_Triggered( false );
- Get_Weapon()->Set_Secondary_Triggered( false );
- }
- }
- SmartGameObj::Post_Think();
- Update_Healing_Effect();
- }
- //------------------------------------------------------------------------------------
- const Matrix3D & SoldierGameObj::Get_Muzzle( int index )
- {
- static Matrix3D _muzzle(1);
- if ( WeaponRenderModel != NULL ) {
- Matrix3D true_muzzle = WeaponRenderModel->Get_Bone_Transform( "muzzlea0" );
- Vector3 muzzle_pos = true_muzzle.Get_Translation();
- _muzzle.Obj_Look_At( muzzle_pos, Get_Targeting_Pos(), 0 );
- if ( !Is_Human_Controlled() ) {
- // If the bullet is not close to going down the muzzle, force it to be
- Vector3 to_target = _muzzle.Get_X_Vector();
- Vector3 down_muzzle = true_muzzle.Get_X_Vector();
- float cos = Vector3::Dot_Product( to_target, down_muzzle );
- if ( cos < WWMath::Cos( DEG_TO_RADF( 20 ) ) ) {
- _muzzle = true_muzzle;
- }
- }
- }
- return _muzzle;
- }
- static int head_bone = -1;
- static int neck_bone = -1;
- //------------------------------------------------------------------------------------
- Matrix3D SoldierGameObj::Get_Look_Transform(void)
- {
- if ( head_bone != -1 ) {
- // Convert from CS head convention back to normal
- Matrix3D tm = Peek_Model()->Get_Bone_Transform( head_bone );
- tm.Rotate_Z( DEG_TO_RAD( 90 ) );
- tm.Rotate_X( DEG_TO_RAD( 90 ) );
- return tm;
- }
- return Get_Transform();
- }
- //------------------------------------------------------------------------------------
- #define HEAD_TURN_LIMIT DEG_TO_RADF( 70 )
- #define HEAD_TILT_LIMIT DEG_TO_RADF( 20 )
- void SoldierGameObj::Look_Random( float time )
- {
- if ( time == 0 && HeadLookDuration != 0 ) {
- HeadLookDuration = 0.0001f; // maybe done next time...
- } else {
- HeadLookDuration = time;
- }
- HeadLookAngleTimer = 0;
- HeadLookAngle = Vector3( 1,1,1 );
- }
- ////////////////////////////////////////////////////////////////
- // Clamp_Angle
- ////////////////////////////////////////////////////////////////
- static inline float
- Clamp_Angle (float angle, float min_angle, float max_angle)
- {
- //
- // Make sure all the parameters are in the same range
- //
- angle = WWMath::Wrap (angle, 0, DEG_TO_RADF (360));
- min_angle = WWMath::Wrap (min_angle, 0, DEG_TO_RADF (360));
- max_angle = WWMath::Wrap (max_angle, 0, DEG_TO_RADF (360));
- float result = angle;
- if (min_angle <= max_angle) {
-
- //
- // Handle the 'typical' case where there is no 360-mark wrap-around
- //
- if (angle < min_angle) {
- result = min_angle;
- } else if (angle > max_angle) {
- result = max_angle;
- }
- } else {
-
- //
- // Handle the 360-mark wrap-around case
- //
- if (angle < min_angle && angle > max_angle) {
- float min_delta = min_angle - angle;
- float max_delta = angle - max_angle;
- //
- // Which edge is the angle closer to?
- //
- if (min_delta < max_delta) {
- result = min_angle;
- } else {
- result = max_angle;
- }
- }
- }
- return result;
- }
- void SoldierGameObj::Handle_Head_look( void )
- {
- if ( Peek_Model ()->Get_HTree () == NULL ) {
- return ;
- }
- //
- // Get the head bone
- //
- if ( head_bone == -1 || neck_bone == -1) {
- head_bone = Peek_Model()->Get_Bone_Index( "C HEAD" );
- neck_bone = Peek_Model()->Get_Bone_Index( "C NECK" );
- WWASSERT( head_bone != -1 );
- WWASSERT( neck_bone != -1 );
- }
- if ( HeadLookDuration > 0 ) {
- HeadLookDuration -= TimeManager::Get_Frame_Seconds();
- // Should we be returning to look ahead?
- bool returning = HeadLookDuration < 0;
- //Matrix3D head(1);
- Vector3 desired_head_rotation( 0,0,0 );
- if ( !returning ) {
- if ( HeadLookAngle.Length() > 0.001f ) {
- HeadLookAngleTimer -= TimeManager::Get_Frame_Seconds();
- if ( HeadLookAngleTimer < 0 ) {
- HeadLookAngle = Vector3(
- FreeRandom.Get_Float( -HEAD_TURN_LIMIT, HEAD_TURN_LIMIT ),
- FreeRandom.Get_Float( -HEAD_TILT_LIMIT, HEAD_TILT_LIMIT ) ,0);
- // Debug_Say(( "New Look Turn %f Tilt %f\n", RAD_TO_DEG(HeadLookAngle.X), RAD_TO_DEG(HeadLookAngle.Y) ));
- HeadLookAngleTimer = FreeRandom.Get_Float( 2, 5 );
- }
- desired_head_rotation = HeadLookAngle;
- } else {
- //
- // Release the captured bone, this will have the effect of causing the Get_Bone_Transform ()
- // methods to return the un-modified (due to being controlled) transform of the bone.
- //
- /*if ( Peek_Model()->Is_Bone_Captured( head_bone ) ) {
- Peek_Model()->Release_Bone( head_bone );
- }*/
- ///
- // Get the transform that has been used to modify the head bone...
- //
- const HTreeClass *htree = Peek_Model()->Get_HTree();
- WWASSERT( htree != NULL );
- Matrix3D bone_control_tm( 1 );
- htree->Get_Bone_Control( head_bone, bone_control_tm );
- //
- // Get the inverse of the head-bone transform
- //
- Matrix3D inv_bone_control_tm;
- bone_control_tm.Get_Orthogonal_Inverse (inv_bone_control_tm);
- //
- // Get the head to world and neck to world transforms
- //
- Matrix3D cur_head = Peek_Model()->Get_Bone_Transform( head_bone );
- Matrix3D cur_neck = Peek_Model()->Get_Bone_Transform( neck_bone );
- //
- // Strip off the control transform from last frame
- //
- cur_head = cur_head * inv_bone_control_tm;
- //
- // Get the world to neck transform
- //
- Matrix3D world_to_neck_tm;
- cur_neck.Get_Orthogonal_Inverse (world_to_neck_tm);
- //
- // Build a head to neck transform
- //
- Matrix3D head_to_neck_tm = world_to_neck_tm * cur_head;
- //
- // Get the target relative to the head
- //
- Vector3 relative_head_target;
- Matrix3D::Inverse_Transform_Vector( cur_head, HeadLookTarget, &relative_head_target );
- //
- // Determine the 'twist' and lookup/down angles.
- // Note: Currently in the head bone coordinate system, the X axis is the same
- // as the Z axis in object space, the Y axis is the same as the X axis in object space,
- // and the Z axis is the same as the Y axis in object space.
- //
- desired_head_rotation.X = WWMath::Atan2( relative_head_target.Z, relative_head_target.Y );
- desired_head_rotation.Z = -WWMath::Fast_Asin( relative_head_target.X / relative_head_target.Length() );
- desired_head_rotation.Y = 0;
- //
- // Determine how far to allow the character to turn and tilt his/her head.
- // These boundaries are based on the "absolute" amount the person can turn
- // their head, this has to take into consideration the amount that the current
- // animation is turning the head and the amount we need to turn to look at the target.
- //
- Vector3 temp_vec = head_to_neck_tm.Get_Y_Vector ();
- float curr_rot_x = ::atan2 (temp_vec.Z, temp_vec.Y);
- float curr_rot_z = ::atan2 (temp_vec.X, temp_vec.Y);
-
- float min_twist = ((-HEAD_TURN_LIMIT) - curr_rot_x);
- float max_twist = (HEAD_TURN_LIMIT - curr_rot_x);
- float min_tilt = ((-HEAD_TILT_LIMIT) - curr_rot_z);
- float max_tilt = (HEAD_TILT_LIMIT - curr_rot_z);
- //
- // Clamp the rotations
- //
- desired_head_rotation.X = WWMath::Clamp( desired_head_rotation.X, min_twist, max_twist);
- desired_head_rotation.Z = WWMath::Clamp( desired_head_rotation.Z, min_tilt, max_tilt);
- }
- }
- #define HEAD_TURN_RATE (DEG_TO_RAD( 360 )/2)
- #define HEAD_TILT_RATE (DEG_TO_RAD( 180 )/2)
- float max_turn = HEAD_TURN_RATE * TimeManager::Get_Frame_Seconds();
- float max_tilt = HEAD_TILT_RATE * TimeManager::Get_Frame_Seconds();
- HeadRotation.X += WWMath::Clamp( (desired_head_rotation.X - HeadRotation.X), -max_turn, max_turn );
- HeadRotation.Z += WWMath::Clamp( (desired_head_rotation.Z - HeadRotation.Z), -max_tilt, max_tilt );
- Matrix3D head(1);
- head.Rotate_X( HeadRotation.X );
- head.Rotate_Z( HeadRotation.Z );
- if ( !Peek_Model()->Is_Bone_Captured( head_bone ) ) {
- Peek_Model()->Capture_Bone( head_bone );
- }
- WWASSERT( Peek_Model()->Is_Bone_Captured( head_bone ) );
- if ( Peek_Model()->Is_Bone_Captured( head_bone ) ) {
- Peek_Model()->Control_Bone( head_bone, head );
- }
- HeadRotation.Z = 0;
- if ( returning && HeadRotation.Length() > 0.001f ) {
- HeadLookDuration = 0.0001f; // maybe done next time...
- }
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Blended_Animation( const char *animation_name, bool looping, float frame_offset, bool play_backwards )
- {
- if ( animation_name == NULL ) {
- HumanState.Stop_Scripted_Animation();
- return;
- }
- // Humans ignore the start_frame parameter for now
- AnimationName = animation_name;
- HumanState.Start_Scripted_Animation( animation_name, true, looping );
- Get_Anim_Control()->Set_Mode( looping ? ANIM_MODE_LOOP : ANIM_MODE_ONCE, frame_offset );
- if ( play_backwards ) {
- HAnimClass *anim = Get_Anim_Control()->Peek_Animation();
- if ( anim != NULL ) {
- int frame_count = anim->Get_Num_Frames();
- Get_Anim_Control()->Set_Mode( ANIM_MODE_TARGET, frame_count - 1 );
- Get_Anim_Control()->Set_Target_Frame( 0 );
- }
- }
- return ;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Animation( const char *animation_name, bool looping, float start_frame )
- {
- if ( animation_name == NULL ) {
- // Debug_Say(( "Stoping Scripted Human Animation\n" ));
- HumanState.Stop_Scripted_Animation();
- // FIX AnimControl->UnLock_Animation();
- return;
- }
- // Humans ignore the start_frame parameter for now
- // Debug_Say(( "Starting Scripted Human Animation %s\n", animation_name ));
- AnimationName = animation_name;
- HumanState.Start_Scripted_Animation( animation_name, false, looping );
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Start_Transition_Animation( const char * anim_name, TransitionCompletionDataStruct *data )
- {
- // Debug_Say(( "Starting Human Transition Animation %s\n", anim_name ));
- //WWASSERT( TransitionCompletionData == NULL );
- TransitionCompletionData = data;
- AnimationName = anim_name;
- HumanState.Start_Transition_Animation( anim_name, false );
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Weapon_Model( const char *model_name )
- {
- if ( WeaponRenderModel != NULL ) { // remove old gun model
- if ( Peek_Model() != NULL ) {
- Peek_Model()->Remove_Sub_Object(WeaponRenderModel); // Clean the bone
- }
- WeaponRenderModel->Release_Ref();
- WeaponRenderModel = NULL;
- }
- if ( (model_name != NULL) && (*model_name != 0) ) {
- //Debug_Say(( "Updating soldier Weapon model to %s!!!\n", model_name ));
- StringClass stripped_name(true);
- Get_Render_Obj_Name_From_Filename( stripped_name, model_name );
- WeaponRenderModel = SoldierGameObj::Find_RenderObj( stripped_name );
- if ( WeaponRenderModel == NULL ) {
- WeaponRenderModel = Create_Render_Obj_From_Filename( model_name );
- WWASSERT( WeaponRenderModel );
- SET_REF_OWNER( WeaponRenderModel );
- Add_RenderObj( WeaponRenderModel );
- WeaponRenderModel->Release_Ref();
- }
- WeaponRenderModel->Add_Ref();
- // Create and add new gun model
- if ( Peek_Model() != NULL ) {
- if ( WeaponRenderModel->Get_Container() != Peek_Model() ) {
- Peek_Model()->Add_Sub_Object_To_Bone( WeaponRenderModel, GUN_BONE_NAME );
- }
- }
- assert( Get_Weapon() );
- Get_Weapon()->Set_Model( WeaponRenderModel ); // let the weapon know who's firing him
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Weapon_Animation( const char *anim_name )
- {
- if ( WeaponAnimControl == NULL ) {
- WeaponAnimControl = new SimpleAnimControlClass;
- if (WeaponRenderModel != NULL ) {
- // Update Anim Control
- WeaponAnimControl->Set_Model( WeaponRenderModel );
- }
- }
- if ( WeaponAnimControl != NULL ) {
- // Debug_Say(( "Updating soldier gun anim to \"%s\"!!!\n", anim_name ));
- if ( ( anim_name != NULL ) && ( *anim_name != 0 ) ) {
- WeaponAnimControl->Set_Animation( anim_name );
- }
- }
- }
- void SoldierGameObj::Set_Back_Weapon_Model( const char *model_name )
- {
- if ( BackWeaponRenderModel != NULL ) { // remove old gun model
- if (Peek_Model() != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackWeaponRenderModel);
- }
- BackWeaponRenderModel->Release_Ref();
- BackWeaponRenderModel = NULL;
- }
- if ( (model_name != NULL) && (*model_name != 0) ) {
-
- // Create and add back gun model
- StringClass stripped_name(true);
- Get_Render_Obj_Name_From_Filename( stripped_name, model_name );
- BackWeaponRenderModel = SoldierGameObj::Find_RenderObj( stripped_name );
- if ( BackWeaponRenderModel == NULL ) {
- BackWeaponRenderModel = Create_Render_Obj_From_Filename( model_name );
- // WWASSERT( BackWeaponRenderModel );
- if ( BackWeaponRenderModel != NULL ) {
- SET_REF_OWNER( BackWeaponRenderModel );
- Add_RenderObj( BackWeaponRenderModel );
- BackWeaponRenderModel->Release_Ref();
- }
- }
- if ( BackWeaponRenderModel != NULL ) {
- BackWeaponRenderModel->Add_Ref();
- if (Peek_Model() != NULL ) {
- Peek_Model()->Add_Sub_Object_To_Bone( BackWeaponRenderModel, BACK_GUN_BONE_NAME );
- }
- } else {
- Debug_Say(( "Missing Back Model %s", model_name ));
- }
- }
- }
- void SoldierGameObj::Set_Back_Flag_Model(const char *model_name,
- const Vector3 & tint)
- {
- if ( BackFlagRenderModel != NULL ) { // remove old gun model
- if (Peek_Model() != NULL ) {
- Peek_Model()->Remove_Sub_Object(BackFlagRenderModel);
- }
- BackFlagRenderModel->Release_Ref();
- BackFlagRenderModel = NULL;
- }
- if ( (model_name != NULL) && (*model_name != 0) ) {
-
- // Create and add back gun model
- BackFlagRenderModel = Create_Render_Obj_From_Filename( model_name );
- if ( BackFlagRenderModel != NULL ) {
- SET_REF_OWNER( BackFlagRenderModel );
- /*
- extern void Tint(RenderObjClass *robj, const Vector3 & color);
- Tint(BackFlagRenderModel, tint);
- */
- if (Peek_Model() != NULL ) {
- Peek_Model()->Add_Sub_Object_To_Bone( BackFlagRenderModel, BACK_GUN_BONE_NAME );
- }
- } else {
- Debug_Say(( "Missing Back Model %s", model_name ));
- }
- }
- }
- void SoldierGameObj::Update_Back_Gun( void )
- {
- //Debug_Say(("CommandoGameObj::Update_Back_Gun\n"));
- WeaponClass *next_weapon = WeaponBag->Get_Next_Weapon();
- if ( next_weapon && ( next_weapon != Get_Weapon() ) ) {
- Set_Back_Weapon_Model( next_weapon->Get_Back_Model_Name() );
- } else {
- Set_Back_Weapon_Model( NULL );
- }
- }
- //------------------------------------------------------------------------------------
- float SoldierGameObj::Get_Weapon_Height( void )
- {
- float height = 1.62f; // set to be at about eye level
- if ( Is_Crouched() ) {
- height -= 0.56f;
- }
- return height; // verticle offset, move to weapon
- }
- //------------------------------------------------------------------------------------
- float SoldierGameObj::Get_Weapon_Length( void )
- {
- return 0.8f; // forward offset, move to weapon
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Internal_Set_Targeting( const Vector3 & target_pos, bool do_tilt )
- {
- WWPROFILE( "Soldier Set Targeting" );
- if ( CombatManager::Is_Skeleton_Slider_Demo_Enabled() ) {
- return false;
- }
- SmartGameObj::Set_Targeting( target_pos );
- if ( ( Get_State() == HumanStateClass::DEATH ) ||
- ( Get_State() == HumanStateClass::DESTROY ) ||
- ( Get_State() == HumanStateClass::TRANSITION ) ||
- ( Get_State() == HumanStateClass::LADDER ) ) {
- // Debug_Say(( "Ignore Set Target in Transition \n" ));
- return false;
- }
- if ( Get_State() == HumanStateClass::IN_VEHICLE ) {
- if ( Vehicle != NULL ) {
- if ( Vehicle->Get_Driver_Is_Gunner() ) {
- if ( Vehicle->Get_Driver() == this ) {
- Vehicle->Set_Targeting( target_pos );
- }
- } else {
- if ( Vehicle->Get_Driver() == this && Vehicle->Get_Gunner() == NULL ) {
- Vehicle->Set_Targeting( target_pos );
- } else if ( Vehicle->Get_Gunner() == this ) {
- Vehicle->Set_Targeting( target_pos );
- }
- }
- }
- return false;
- }
- Vector3 muzzle_pos;
- Get_Position( &muzzle_pos );
- muzzle_pos.Z += Get_Weapon_Height();
- Vector3 rel_target_pos = target_pos - muzzle_pos;
-
- // Set Tilt
- float dist = rel_target_pos.Length();
- float tilt = 0;
- if ( dist && do_tilt ) {
- tilt = WWMath::Fast_Asin( rel_target_pos.Z / dist );
- }
- // tilt = 0;
- // Debug_Say(( "Tilt %f", tilt ));
- bool is_complete = true;
- // Set Facing
- float cur_facing = Peek_Human_Phys()->Get_Heading();
- float facing = WWMath::Atan2( rel_target_pos.Y, rel_target_pos.X );
- float facing_dif = facing - cur_facing;
- if ( WWMath::Fabs(facing_dif) > 0.001f ) {
- WWPROFILE( "Facing" );
- facing_dif = WWMath::Wrap( facing_dif, DEG_TO_RADF( -180.0f ), DEG_TO_RADF( 180.0f ) );
- // Debug_Say(( "Must change %1.3f, from facing %1.3f to facing %1.3f\n", RAD_TO_DEG( facing_dif ), RAD_TO_DEG( cur_facing ), RAD_TO_DEG( facing ) ));
- float change = facing_dif;
- if ( !Is_Human_Controlled() ) { // human players don't use turn limits
- float max_change = Get_Turn_Rate() * TimeManager::Get_Frame_Seconds();
- // Turn more slowly when turning a small amount
- if ( WWMath::Fabs( change ) < DEG_TO_RAD( 20 ) ) {
- max_change *= 0.3f;
- }
- change = WWMath::Clamp( facing_dif, -max_change, max_change );
- }
- if ( !Is_Human_Controlled() ) { // human players don't use turn anims
- HumanState.Set_Turn_Velocity( change ); // play the leg turning anim
- }
- is_complete = (change == facing_dif); // are we facing?
- facing = cur_facing + change;
- facing = WWMath::Wrap( facing, DEG_TO_RADF( -180.0f ), DEG_TO_RADF( 180.0f ) );
- Peek_Human_Phys()->Set_Heading( facing );
- }
- if ( Is_Human_Controlled() && Get_State() != HumanStateClass::IN_VEHICLE ) {
- #define TILT_DOWN_SPEED 4.0
- float direction = -1;
- if ( Get_Weapon() && Get_Weapon()->Is_Reloading() ) {
- direction = 1;
- }
- ReloadingTilt += direction * TimeManager::Get_Frame_Seconds() * TILT_DOWN_SPEED;
- ReloadingTilt = WWMath::Clamp( ReloadingTilt, 0, 1 );
- if ( ReloadingTilt > 0 ) {
- tilt = WWMath::Lerp( (float)tilt, DEG_TO_RADF( -90 ), ReloadingTilt );
- }
- }
- HumanState.Update_Aiming( tilt, 0 ); // no turn
- // facing = HumanState.Peek_Physical_Object()->Get_Heading();
- // Debug_Say(( "Soldier Facing %f Tilt %f\n", RAD_TO_DEG( facing ), RAD_TO_DEG( WeaponTilt ) ));
- // Debug_Say(( "rel_target_pos %f %f %f\n", rel_target_pos.X, rel_target_pos.Y, rel_target_pos.Z ));
- return is_complete;
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Set_Targeting( const Vector3 & target_pos, bool do_tilt )
- {
- bool retval = false;
- //
- // Don't do the targetting if we are locked on an object
- //
- if ( FacingObject == NULL ) {
- retval = Internal_Set_Targeting( target_pos, do_tilt );
- }
- return retval;
- }
- //------------------------------------------------------------------------------------
- RenderObjClass * SoldierGameObj::Find_Head_Model( void )
- {
- RenderObjClass *head_model = NULL;
- //
- // Get a pointer to the HLod this object is using
- //
- RenderObjClass *model = Peek_Model ();
- if ( model != NULL && model->Class_ID () == RenderObjClass::CLASSID_HLOD ) {
- HLodClass *lod = reinterpret_cast<HLodClass *> ( model );
-
- //
- // Try to find the head-bone
- //
- int bone_index = lod->Get_Bone_Index ( "C HEAD" );
- int obj_count = lod->Get_Num_Sub_Objects_On_Bone(bone_index);
- //
- // Try to find a model on the head bone that uses the human head skeleton
- //
- for (int index = 0; index < obj_count; index ++) {
- RenderObjClass *render_obj = lod->Get_Sub_Object_On_Bone ( index, bone_index );
- if (render_obj != NULL) {
- const HTreeClass *htree = render_obj->Get_HTree();
- if ( htree != NULL ) {
- //
- // Is this really a head model?
- //
- if ( ::stricmp (htree->Get_Name(), "S_A_HEAD") == 0 ||
- ::stricmp (htree->Get_Name(), "S_B_HEAD") == 0)
- {
- head_model = render_obj;
- break;
- }
- }
- render_obj->Release_Ref ();
- }
- }
- }
- return head_model;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Emot_Icon ( const char *model_name, float duration )
- {
- //
- // Free the old emot icon
- //
- if ( EmotIconModel != NULL ) {
- if ( EmotIconModel->Is_In_Scene() ) {
- EmotIconModel->Remove ();
- }
- REF_PTR_RELEASE( EmotIconModel );
- }
-
- //
- // Try to load the new emot icon model
- //
- if ( model_name != NULL ) {
- //
- // Create the new model
- //
- EmotIconModel = ::Create_Render_Obj_From_Filename( model_name );
- if ( EmotIconModel != NULL ) {
- //
- // Determine what the animation name for the model is
- //
- const char *name = EmotIconModel->Get_Name ();
- StringClass anim_name;
- anim_name.Format ("%s.%s", name, name);
- //
- // Animate the model
- //
- HAnimClass *anim = WW3DAssetManager::Get_Instance ()->Get_HAnim( anim_name );
- if ( anim != NULL ) {
- EmotIconModel->Set_Animation( anim, 0.0F, RenderObjClass::ANIM_MODE_LOOP );
- REF_PTR_RELEASE( anim );
- }
-
- //
- // Put the icon a few meters above the soldier's head
- //
- Matrix3D tm = Get_Transform();
- tm.Set_Translation (tm.Get_Translation() + Vector3 (0, 0, EMOT_ICON_HEIGHT));
- EmotIconModel->Set_Transform( tm );
- COMBAT_SCENE->Add_Render_Object( EmotIconModel );
- EmotIconTimer = duration;
- }
- }
-
- return ;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Say_Dialogue( int dialog_id )
- {
- WWASSERT( dialog_id >= 0 && dialog_id < DIALOG_MAX );
- //
- // Lookup the conversation we are starting
- //
- int conversation_id = DialogList[dialog_id].Get_Conversation();
- if ( conversation_id > 0 ) {
- //
- // Start the conversation
- //
- ActiveConversationClass *conversation = ConversationMgrClass::Start_Conversation( this, conversation_id, true );
- REF_PTR_RELEASE (conversation);
- }
-
- return ;
- }
- //------------------------------------------------------------------------------------
- float SoldierGameObj::Say_Dynamic_Dialogue
- (
- int text_id,
- SoldierGameObj * speaker,
- AudibleSoundClass ** sound_obj_to_return
- )
- {
- float duration = 2.0F;
-
- //
- // Lookup the translation object from the strings database
- //
- TDBObjClass *translate_obj = TranslateDBClass::Find_Object( text_id );
- if (translate_obj != NULL) {
-
- const WCHAR *string = translate_obj->Get_String ();
- int sound_def_id = (int)translate_obj->Get_Sound_ID ();
- const char *anim_name = translate_obj->Get_Animation_Name ();
- //
- // If this soldier was still talking from a previos call, then
- // kill the old sound
- //
- if ( speaker != NULL ) {
- speaker->Stop_Current_Speech();
- }
- //
- // Play the sound effect
- //
- bool display_text = true;
- if ( sound_def_id > 0 ) {
-
- //
- // Create the sound object
- //
- AudibleSoundClass *speech = WWAudioClass::Get_Instance ()->Create_Sound( sound_def_id );
- if ( speech != NULL ) {
- duration = (speech->Get_Duration() / 1000.0F);
- //
- // Return the sound object to the caller as necessary
- //
- if ( sound_obj_to_return != NULL ) {
- (*sound_obj_to_return) = speech;
- (*sound_obj_to_return)->Add_Ref();
- }
- //
- // Either play the sound at the speaker's location
- // or just play it as a 2D sample.
- //
- if ( speaker != NULL ) {
- speech->Set_Transform( speaker->Get_Transform() );
- speech->Add_To_Scene();
- display_text = (speech->Is_Sound_Culled() == false);
- } else {
-
- //
- // Play the sound
- //
- speech->Play();
- }
- }
- //
- // Update the speaker's internal sound object pointer
- //
- if ( speaker != NULL ) {
- speaker->CurrentSpeech = speech;
- } else {
- REF_PTR_RELEASE (speech);
- }
- }
- //
- // Check to see if this string is commented out.
- //
- if( string != NULL && string[0] == L'/' && string[1] == L'/' ) {
- string += 2;
- display_text = false;
- }
- //
- // Display the text on the screen
- //
- if ( display_text && string != NULL && string[0] != 0 ) {
- float message_duration = max( duration, 5.0F );
- CombatManager::Get_Message_Window ()->Add_Message( string, Vector3 (1, 1, 1),
- speaker, message_duration );
- }
-
- //
- // Play the facial animation (if one exists)
- //
- if ( speaker != NULL && speaker->HeadModel != NULL) {
- HAnimClass *head_anim = NULL;
- //
- // Dig out the skeleton name for the head model
- //
- StringClass anim_root_name;
- const HTreeClass *htree = speaker->HeadModel->Get_HTree ();
- if (htree != NULL) {
- anim_root_name = htree->Get_Name ();
- anim_root_name += ".";
- }
-
- //
- // Determine if we should use a pre-canned animation, or
- // if we should build one dynamically
- //
- if ( anim_name == NULL || anim_name[0] == 0 ) {
-
- //
- // Build an animation dynamically
- //
- const char *english_string = translate_obj->Get_English_String();
- if ( english_string != NULL && english_string[0] != 0 ) {
- if (speaker->SpeechAnim->Generate_Animation( english_string, duration )) {
- head_anim = speaker->SpeechAnim;
- }
- }
-
- } else {
-
- //
- // Build a string containing the fully qualified animation name
- //
- StringClass full_anim_name;
- if ( ::strchr( anim_name, '.' ) == 0 ) {
- full_anim_name = anim_root_name;
- full_anim_name += anim_name;
- } else {
- full_anim_name = anim_name;
- }
- head_anim = WW3DAssetManager::Get_Instance()->Get_HAnim( full_anim_name );
- }
- //
- // Recreate the facial animation when the speech is complete
- //
- speaker->GenerateIdleFacialAnimTimer = duration + 1.0F;
-
- //
- // Play the animation on the head model (if one exists)
- //
- if ( speaker->HeadModel != NULL && head_anim != NULL ) {
- speaker->HeadModel->Set_Animation( head_anim, 0, RenderObjClass::ANIM_MODE_ONCE );
- }
- }
- }
- return duration;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Stop_Current_Speech( void )
- {
- //
- // Kill the current sound we are making (speech, scream, grunt, etc)
- //
- if ( CurrentSpeech != NULL ) {
- GenerateIdleFacialAnimTimer = 0;
- CurrentSpeech->Stop();
- CurrentSpeech->Remove_From_Scene();
- CurrentSpeech->Release_Ref();
- CurrentSpeech = NULL;
- }
-
- return ;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Apply_Damage( const OffenseObjectClass & damager, float scale, int alternate_skin )
- {
- if ( !Is_In_Vehicle() ) {
- SmartGameObj::Apply_Damage( damager, scale, alternate_skin );
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Apply_Damage_Extended( const OffenseObjectClass & damager, float scale,
- const Vector3 & direction, const char * collision_box_name )
- {
- // If negative damage, just apply
- if ( Get_Defense_Object()->Is_Repair( damager ) ) {
- // if ( damager.Get_Damage() * scale < 0 ) {
- SmartGameObj::Apply_Damage_Extended( damager, scale, direction, collision_box_name );
- // Add electric effect
- if ( HealingEffect == NULL ) {
- HealingEffect = CombatMaterialEffectManager::Get_Health_Effect();
- if ( HealingEffect != NULL ) {
- Peek_Human_Phys()->Add_Effect_To_Me( HealingEffect );
- }
- }
- if ( HealingEffect != NULL ) {
- HealingEffect->Set_Target_Parameter(0.495f); // go almost halfway
- }
- return;
- }
- // Do this after the repair effect
- /* if ( !CombatManager::I_Am_Server() ) { Clients can apply damage
- return;
- }*/
- if ( Is_In_Vehicle() ) {
- return;
- }
- bool ambushed = false;
- // Ambush Kill
- if ( ( Get_AI_State() == AI_STATE_IDLE ) || ( Get_AI_State() == AI_STATE_SECONDARY_IDLE ) ) {
- // Only ambush if there is an owner to the damage, and the target is human controlled
- if ( damager.Get_Owner() != NULL && !Is_Human_Controlled() ) {
- scale *= AMBUSH_DAMAGE_SCALE;
- ambushed = true;
- // Debug_Say(( "Ambush Damage!!\n" ));
- }
- }
- bool anim_ok = true;
- Reset_Hibernating(); // Wake up when damaged
- int ouch_type = Get_Ouch_Type( direction, collision_box_name );
- // Stats
- PlayerDataClass * damager_data = NULL;
- if ( damager.Get_Owner() && damager.Get_Owner()->As_SoldierGameObj() ) {
- damager_data = damager.Get_Owner()->As_SoldierGameObj()->Get_Player_Data();
- }
- // Dont add stats for "non-directional" damage. E.g. standing in a tiberium
- // field should not count as thousands of hits.
- if (direction.Length2() > WWMATH_EPSILON) {
- switch( ouch_type ) {
- case HumanStateClass::HEAD_FROM_BEHIND:
- case HumanStateClass::HEAD_FROM_FRONT:
- if ( Get_Player_Data() != NULL ) {
- Get_Player_Data()->Stats_Add_Head_Hit();
- }
- if ( damager_data != NULL ) {
- damager_data->Stats_Add_Head_Shot();
- }
- break;
- case HumanStateClass::TORSO_FROM_BEHIND:
- case HumanStateClass::TORSO_FROM_FRONT:
- if ( Get_Player_Data() != NULL ) {
- Get_Player_Data()->Stats_Add_Torso_Hit();
- }
- if ( damager_data != NULL ) {
- damager_data->Stats_Add_Torso_Shot();
- }
- break;
- case HumanStateClass::LEFT_ARM_FROM_BEHIND:
- case HumanStateClass::LEFT_ARM_FROM_FRONT:
- case HumanStateClass::RIGHT_ARM_FROM_BEHIND:
- case HumanStateClass::RIGHT_ARM_FROM_FRONT:
- if ( Get_Player_Data() != NULL ) {
- Get_Player_Data()->Stats_Add_Arm_Hit();
- }
- if ( damager_data != NULL ) {
- damager_data->Stats_Add_Arm_Shot();
- }
- break;
- case HumanStateClass::LEFT_LEG_FROM_BEHIND:
- case HumanStateClass::LEFT_LEG_FROM_FRONT:
- case HumanStateClass::RIGHT_LEG_FROM_BEHIND:
- case HumanStateClass::RIGHT_LEG_FROM_FRONT:
- if ( Get_Player_Data() != NULL ) {
- Get_Player_Data()->Stats_Add_Leg_Hit();
- }
- if ( damager_data != NULL ) {
- damager_data->Stats_Add_Leg_Shot();
- }
- break;
- case HumanStateClass::GROIN:
- if ( Get_Player_Data() != NULL ) {
- Get_Player_Data()->Stats_Add_Crotch_Hit();
- }
- if ( damager_data != NULL ) {
- damager_data->Stats_Add_Crotch_Shot();
- }
- break;
- }
- }
- // Determine what (if any) dialogue to say
- int dialogue_id = -1;
- ArmedGameObj *damage_owner = damager.Get_Owner();
- if( damage_owner != NULL ) {
-
- // Were we injured by a friend or foe?
- if ( Is_Enemy( damage_owner ) ) {
- dialogue_id = DIALOG_ON_TAKE_DAMAGE_FROM_ENEMY;
- } else {
- dialogue_id = DIALOG_ON_TAKE_DAMAGE_FROM_FRIEND;
- }
- }
- float health_before = Get_Defense_Object()->Get_Health();
- float armor_before = Get_Defense_Object()->Get_Shield_Strength();
- if ( collision_box_name != NULL ) {
- char * start = ::strchr( collision_box_name, '.' );
- if ( start != NULL ) {
- start++;
- float bone_scale = BonesManager::Get_Bone_Damage_Scale( start );
- scale *= bone_scale;
- }
- }
- // Update damage indicators
- if ( this == COMBAT_STAR ) {
- if ( Get_Defense_Object()->Would_Damage( damager ) && !damager.ForceServerDamage ) {
- if ( direction.Length() == 0 ) {
- for ( int i = 0; i < 8; i++ ) {
- CombatManager::Show_Star_Damage_Direction( i );
- }
- // Set all
- } else {
- Vector3 relative_direction = Get_Transform().Inverse_Rotate_Vector( direction );
- // Convert direction into 0 .. 7
- float angle = ::WWMath::Atan2 ( relative_direction.Y, -relative_direction.X);
- int dir = (int)(8.0f * angle / DEG_TO_RAD( 360 ) + 8.5f);
- CombatManager::Show_Star_Damage_Direction( dir & 7 );
- }
- }
- }
- SmartGameObj::Apply_Damage_Extended( damager, scale, direction, collision_box_name );
- float health = Get_Defense_Object()->Get_Health();
- if ( this == COMBAT_STAR ) {
- Vector3 pos;
- COMBAT_STAR->Get_Position( &pos );
- int hitter_id = 0;
- const char * weapon_name = "";
- if ( damager.Get_Owner() ) {
- hitter_id = damager.Get_Owner()->Get_ID();
- if ( damager.Get_Owner()->Get_Weapon() ) {
- weapon_name = damager.Get_Owner()->Get_Weapon()->Get_Definition()->Get_Name();
- }
- }
- const char * body_part = ( collision_box_name != NULL ) ? collision_box_name : "";
- float armor = Get_Defense_Object()->Get_Shield_Strength();
- DIAG_LOG(( "DRCE", "%s; %d; %s; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f", weapon_name, hitter_id, body_part, armor, health, pos.X, pos.Y, pos.Z ));
- }
- if (( damager.Get_Owner() == COMBAT_STAR ) && ( COMBAT_STAR != NULL )) {
- Vector3 pos;
- COMBAT_STAR->Get_Position( &pos );
- const char * weapon_name = "";
- int ammo = 0;
- if ( COMBAT_STAR->Get_Weapon() ) {
- weapon_name = COMBAT_STAR->Get_Weapon()->Get_Definition()->Get_Name();
- ammo = COMBAT_STAR->Get_Weapon()->Get_Total_Rounds();
- }
- int hittee_id = Get_ID();
- const char * body_part = ( collision_box_name != NULL ) ? collision_box_name : "";
- float armor = Get_Defense_Object()->Get_Shield_Strength();
- Vector3 victim_pos;
- Get_Position( &victim_pos );
- const char * team_name = Player_Type_Name( Get_Player_Type() );
- DIAG_LOG(( "DEFE", "%1.2f; %1.2f; %1.2f; %s; %d; %d; %s; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %s ", pos.X, pos.Y, pos.Z, weapon_name, ammo, hittee_id, body_part, armor, health, victim_pos.X, victim_pos.Y, victim_pos.Z, team_name ));
- }
- if ( ambushed ) {
- int victim_id = Get_ID();
- Vector3 victim_pos;
- Get_Position( &victim_pos );
- Vector3 shooter_pos;
- damager.Get_Owner()->Get_Position( &shooter_pos );
- float armor = Get_Defense_Object()->Get_Shield_Strength();
- DIAG_LOG(( "AMGE", "%1.2f; %1.2f; %1.2f; %d; %1.2f; %1.2f; %1.2f; %1.2f; %1.2f", victim_pos.X, victim_pos.Y, victim_pos.Z, victim_id, shooter_pos.X, shooter_pos.Y, shooter_pos.Z, armor, health ));
- }
- if (health == health_before && Get_Defense_Object()->Get_Shield_Strength() == armor_before) {
- //
- // No damage was applied.
- // This is a hack.
- //
- // Handle zero health bug
- if ( health > 0 ||
- HumanState.Get_State() == HumanStateClass::DEATH ||
- HumanState.Get_State() == HumanStateClass::DESTROY ) {
- return;
- } else {
- Debug_Say(( "Solving Zero health Bug %f %d\n", health, HumanState.Get_State() ));
- }
- }
- // Can't start special damage unless damage was done.
- // Check for special damage
- int warhead = damager.Get_Warhead();
- ArmorWarheadManager::SpecialDamageType special_damage = ArmorWarheadManager::Get_Special_Damage_Type( warhead );
- if ( special_damage != 0 ) {
- float probability = ArmorWarheadManager::Get_Special_Damage_Probability( warhead );
- if (health <= 0) {
- probability = 1;
- }
- if ( FreeRandom.Get_Float() < probability ) {
- // if skin is not impervious to the damage
- int skin = Get_Defense_Object()->Get_Skin();
- ArmorWarheadManager::SpecialDamageType special_damage = ArmorWarheadManager::Get_Special_Damage_Type( warhead );
- if ( !ArmorWarheadManager::Is_Skin_Impervious( special_damage, skin ) ) {
- Set_Special_Damage_Mode( special_damage, damager.Get_Owner() );
- }
- }
- }
- if ( this == COMBAT_STAR ) {
- if ( _shake_delay < 0 ) {
- _shake_delay = 0.6f; // don't shake/sound too fast
- // And Shake the camera
- Vector3 pos = COMBAT_CAMERA->Get_Transform().Get_Translation();
- COMBAT_SCENE->Add_Camera_Shake( pos, 1, 0.5f, 0.05f );
- }
- anim_ok = false;
- if ( _cry_delay < 0 ) {
- _cry_delay = 2; // don't shake/sound too fast
- anim_ok = true;
- // Play ouch sound
- AudibleSoundClass * sound = WWAudioClass::Get_Instance()->Create_Sound( "Take_Damage_Sound" );
- if ( sound ) {
- sound->Play();
- sound->Release_Ref();
- }
- }
- }
- if ( health <= 0 ) {
- // Check for creating visceroids
- if ( IS_MISSION ) {
- int warhead = damager.Get_Warhead();
- float visceroid_probability = ArmorWarheadManager::Get_Visceroid_Probability( warhead );
- if ( !Is_Human_Controlled() && visceroid_probability != 0 ) {
- if ( FreeRandom.Get_Float() < visceroid_probability ) {
- #define VISCEROID_NAME "Visceroid"
- // Not from other visceroids
- if ( ::stricmp( Get_Definition().Get_Name(), VISCEROID_NAME ) != 0 ) {
- // Create a visceroid
- PhysicalGameObj * vis = ObjectLibraryManager::Create_Object( VISCEROID_NAME );
- if ( vis != NULL ) {
- vis->Set_Transform( Get_Transform() );
- vis->Start_Observers ();
- Set_Delete_Pending(); // Kill me
- Debug_Say(( "Made Visceroid\n" ));
- }
- }
- }
- }
- }
- Enable_Hibernation( false );
- // Stats
- SoldierGameObj * damager_owner = NULL;
- if ( damager.Get_Owner() && damager.Get_Owner()->As_SoldierGameObj() ) {
- damager_owner = damager.Get_Owner()->As_SoldierGameObj();
- }
- if ( damager_owner && damager_owner->Get_Player_Data() ) {
- if ( Is_Teammate( damager_owner ) ) {
- damager_owner->Get_Player_Data()->Stats_Add_Ally_Killed();
- }
- if ( Is_Enemy( damager_owner ) ) {
- damager_owner->Get_Player_Data()->Stats_Add_Enemy_Killed();
- }
- if ( damager_owner->Get_Vehicle() ) {
- damager_owner->Get_Player_Data()->Stats_Add_Kill_From_Vehicle();
- }
- }
- if ( HumanState.Get_State() != HumanStateClass::DEATH ) {
- if ( this == COMBAT_STAR ) {
- CombatManager::Register_Star_Killer( damager.Get_Owner() );
- }
- // Play death animation
- HumanState.Set_State( HumanStateClass::DEATH, ouch_type );
- //
- // Stop any sound we WERE making
- //
- Stop_Current_Speech ();
- int death_sound_id = Get_Definition ().DeathSoundPresetID;
- if (death_sound_id == 0) {
- //
- // Lookup the global death sound
- //
- GlobalSettingsDef *global_settings = GlobalSettingsDef::Get_Global_Settings ();
- if (global_settings != NULL) {
- death_sound_id = global_settings->Get_Death_Sound_ID();
- }
- }
- //
- // Reveal this object to the player's encyclopedia
- //
- if ( damager.Get_Owner () == COMBAT_STAR ) {
- EncyclopediaMgrClass::Reveal_Object( this );
- }
- //
- // Play the death sound
- //
- if (death_sound_id != 0) {
- Matrix3D tm = Get_Transform();
- RefCountedGameObjReference *owner_ref = new RefCountedGameObjReference(this);
- WWAudioClass::Get_Instance()->Create_Instant_Sound( death_sound_id, tm, owner_ref );
- REF_PTR_RELEASE(owner_ref);
- }
- // Play death explosion, since we don't call Completely_Damaged
- if ( Get_Definition().KilledExplosion != 0 ) {
- Vector3 pos;
- Get_Position(&pos);
- WWASSERT(pos.Is_Valid());// most likely candidate for explosion damage bug....?
- ExplosionManager::Create_Explosion_At( Get_Definition().KilledExplosion, pos, damager.Get_Owner() ); // no one gets credit for this
- }
- //
- // Queue the guy who killed us...
- //
- if ( damage_owner != NULL &&
- damage_owner != this &&
- damage_owner->As_SoldierGameObj () != NULL )
- {
- SoldierGameObj *our_killer = damage_owner->As_SoldierGameObj ();
-
- //
- // Were we killed by a friend or foe?
- //
- if ( Is_Enemy( damage_owner ) ) {
- our_killer->Say_Dialogue( DIALOG_ON_KILLED_ENEMY );
- } else {
- our_killer->Say_Dialogue( DIALOG_ON_KILLED_FRIEND );
- }
- }
- }
- } else {
- // Play wound animation
- // If state is interruptable.....
- if ( Get_State() == HumanStateClass::UPRIGHT && anim_ok ) {
- HumanState.Set_State( HumanStateClass::WOUNDED, ouch_type );
- }
- }
- if( CurrentSpeech == NULL && dialogue_id >= 0 ) {
- Say_Dialogue( dialogue_id );
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Exit_Ladder( void )
- {
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Enter_Ladder( bool top )
- {
- HumanState.Set_State( HumanStateClass::LADDER );
- if ( Is_Human_Controlled() ) {
- if ( top ) {
- LadderUpMask = true;
- } else {
- LadderDownMask = true;
- }
- }
- }
- //------------------------------------------------------------------------------------
- HumanPhysClass *SoldierGameObj::Peek_Human_Phys( void ) const
- {
- WWASSERT( Peek_Physical_Object() );
- WWASSERT( Peek_Physical_Object()->As_HumanPhysClass() );
- return Peek_Physical_Object()->As_HumanPhysClass();
- }
- //------------------------------------------------------------------------------------
- /*
- ** Vehicles
- */
- void SoldierGameObj::Enter_Vehicle( VehicleGameObj * vehicle, const char * anim_name )
- {
- // WWASSERT( Get_State() != HumanStateClass::IN_VEHICLE );
- Vehicle = vehicle;
- HumanState.Set_State( HumanStateClass::IN_VEHICLE );
- AnimationName = anim_name;
- HumanState.Force_Animation( anim_name, false );
- if ( this == COMBAT_STAR && vehicle != NULL ) {
- Vector3 pos;
- Vehicle->Get_Position( &pos );
- int ammo = 0;
- if ( vehicle->Get_Weapon() ) {
- ammo = vehicle->Get_Weapon()->Get_Total_Rounds();
- }
- DefenseObjectClass * defense = vehicle->Get_Defense_Object();
- DIAG_LOG(( "ENVE", "%1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %d", pos.X, pos.Y, pos.Z, defense->Get_Shield_Strength(), defense->Get_Health(), ammo ));
- }
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Exit_Vehicle( void )
- {
- if ( this == COMBAT_STAR && Vehicle != NULL ) {
- Vector3 pos;
- Vehicle->Get_Position( &pos );
- int ammo = 0;
- if ( Vehicle->Get_Weapon() ) {
- ammo = Vehicle->Get_Weapon()->Get_Total_Rounds();
- }
- DefenseObjectClass * defense = Vehicle->Get_Defense_Object();
- DIAG_LOG(( "EXVE", "%1.2f; %1.2f; %1.2f; %1.2f; %1.2f; %d", pos.X, pos.Y, pos.Z, defense->Get_Shield_Strength(), defense->Get_Health(), ammo ));
- }
- Vehicle = NULL;
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- }
- void SoldierGameObj::Exit_Destroyed_Vehicle( int seat_num, const Vector3 & vehicle_pos )
- {
- Vehicle = NULL;
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- Vector3 extent = Peek_Human_Phys()->Get_Collision_Box().Extent;
- float width = MAX( extent.X, extent.Y ) * 1.1f;
- if ( Peek_Model() ) {
- Peek_Model()->Set_Hidden( false );
- }
- Vector3 offsets[4] = {
- Vector3( -1.0f, -1.0f, 0 ),
- Vector3( -1.0f, 1.0f, 0 ),
- Vector3( 1.0f, -1.0f, 0 ),
- Vector3( 1.0f, 1.0f, 0 ),
- };
- Vector3 pos = vehicle_pos + offsets[ seat_num & 3 ] * width;
- Matrix3D tm( pos );
- if ( Peek_Human_Phys()->Can_Teleport( tm ) ) {
- Peek_Human_Phys()->Set_Position( pos );
- } else {
- Vector3 new_pos = pos;
- Peek_Human_Phys()->Find_Teleport_Location( pos, 4, &new_pos );
- Peek_Human_Phys()->Set_Position( new_pos );
- }
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Is_Permitted_To_Enter_Vehicle(void)
- {
- if (!CombatManager::Is_Gameplay_Permitted()) {
- //
- // You can't enter a vehicle if there are no opponents, etc
- //
- return false;
- }
- /*
- //
- // A soldier cannot enter a vehicle if he is carrying a flag
- //
- if (CtfTeamFlag == NO_FLAG) {
- return true;
- } else {
- return false;
- }
- */
- return true;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Get_Velocity(Vector3 & vel)
- {
- Peek_Human_Phys()->Get_Velocity(&vel);
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Velocity(Vector3 & vel)
- {
- Peek_Human_Phys()->Set_Velocity(vel);
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Give_All_Weapons(void)
- {
- //WWASSERT(CombatManager::I_Am_Server());
- // WWASSERT(PlayerType != PLAYERTYPE_NEUTRAL);
- // For all weapon defs with the AGiveWeaponsWeapon checked, Give It!
- for ( WeaponDefinitionClass *weapon_def = (WeaponDefinitionClass *)DefinitionMgrClass::Get_First( CLASSID_DEF_WEAPON );
- weapon_def != NULL;
- weapon_def = (WeaponDefinitionClass *)DefinitionMgrClass::Get_Next( weapon_def, CLASSID_DEF_WEAPON ) ) {
- if ( weapon_def->AGiveWeaponsWeapon ) {
- WeaponBag->Add_Weapon( weapon_def->Get_Name(), -1 );
- }
- }
- }
- //------------------------------------------------------------------------------------
- VehicleGameObj * SoldierGameObj::Get_Profile_Vehicle( void )
- {
- if (( Get_State() == HumanStateClass::IN_VEHICLE ) && Vehicle ) {
- return Vehicle;
- }
- if (( Get_State() == HumanStateClass::TRANSITION ) &&
- ( TransitionCompletionData != NULL )) {
- if ( TransitionCompletionData->Type == TransitionDataClass::VEHICLE_ENTER ) {
- return (VehicleGameObj *)TransitionCompletionData->Vehicle.Get_Ptr();
- }
- }
- return NULL;
- }
- bool SoldierGameObj::Use_Ladder_View( void )
- {
- if ( Get_State() == HumanStateClass::LADDER ) {
- return true;
- }
- if (( Get_State() == HumanStateClass::TRANSITION ) &&
- ( TransitionCompletionData != NULL )) {
- if (( TransitionCompletionData->Type == TransitionDataClass::LADDER_ENTER_TOP ) ||
- ( TransitionCompletionData->Type == TransitionDataClass::LADDER_ENTER_BOTTOM )) {
- return true;
- }
- }
- return false;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Model(const char *model_name)
- {
- Peek_Physical_Object()->Set_Model_By_Name(model_name);
- HumanState.Set_Anim_Control( (HumanAnimControlClass *)Get_Anim_Control() ); // Must set the anim control after the phys object
- }
- //------------------------------------------------------------------------------------
- Vector3 SoldierGameObj::Get_Bullseye_Position( void )
- {
- if ( Get_Vehicle() != NULL ) {
- return Get_Vehicle()->Get_Bullseye_Position();
- }
- Vector3 pos;
- Get_Position(&pos);
- if ( Is_Crouched() ) {
- pos.Z += 0.5f;
- } else {
- pos.Z += Get_Bullseye_Offset_Z();
- }
- // pos.Z += 1.2f;
- return pos;
- }
- //------------------------------------------------------------------------------------
- bool SoldierGameObj::Can_See(SoldierGameObj * p_soldier)
- {
- WWASSERT(p_soldier != NULL);
- Vector3 ray_start = Get_Bullseye_Position();
- Vector3 ray_end = p_soldier->Get_Bullseye_Position(); // This may a big high
- Vector3 path = ray_end - ray_start;
- if (path.Length() > 1) {
- Vector3 offset = path;
- offset.Normalize();
- ray_start += offset;
- }
- LineSegClass ray(ray_start, ray_end);
- CastResultStruct result;
- PhysRayCollisionTestClass raytest(ray, &result,
- BULLET_COLLISION_GROUP, COLLISION_TYPE_PHYSICAL);
- WWASSERT(COMBAT_SCENE != NULL);
- { WWPROFILE( "Cast Ray" );
- COMBAT_SCENE->Cast_Ray(raytest);
- }
- bool can_see = false;
-
- if (raytest.CollidedPhysObj != NULL) {
- SmartGameObj * p_blocker = NULL;
- if ( raytest.CollidedPhysObj->Get_Observer() != NULL ) {
- PhysicalGameObj * p_obj = ((CombatPhysObserverClass *)raytest.CollidedPhysObj->Get_Observer())->As_PhysicalGameObj();
- if ( p_obj != NULL ) {
- p_blocker = p_obj->As_SmartGameObj();
- }
- }
- if (p_blocker != NULL && p_blocker->Get_Control_Owner() ==
- p_soldier->Get_Control_Owner()) {
- can_see = true;
- }
- }
- return can_see;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Adjust_Skeleton( float height, float width )
- {
- // Debug_Say(( "Height %f, width %f\n", height, width ));
- // Only adjust male skeletons
- Animatable3DObjClass * robj = (Animatable3DObjClass *)Peek_Model();
- if ( !robj || !robj->Get_HTree() || robj->Get_HTree()->Get_Name()[2] != 'A' ) {
- return;
- }
- HTreeClass * tree_base = NULL;
- HTreeClass * tree_tall = NULL;
- HTreeClass * tree_wide = NULL;
- if ( tree_base == NULL ) {
- tree_base = WW3DAssetManager::Get_Instance()->Get_HTree( "s_a_human" );
- tree_tall = WW3DAssetManager::Get_Instance()->Get_HTree( "s_a_tall" );
- tree_wide = WW3DAssetManager::Get_Instance()->Get_HTree( "s_a_wide" );
- }
- if ( ( tree_base != NULL ) && ( tree_tall != NULL ) && ( tree_wide != NULL ) ) {
- HTreeClass *tree = HTreeClass::Create_Interpolated( tree_base, tree_tall, tree_wide,
- height, width );
- if ( tree ) {
- robj->Set_HTree( tree );
- delete tree;
- }
- }
- }
- /*
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Ctf_Team_Flag(int team)
- {
- WWASSERT(
- team == NO_FLAG ||
- team == PLAYERTYPE_NOD ||
- team == PLAYERTYPE_GDI);
- CtfTeamFlag = team;
- Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
- if (team == NO_FLAG) {
- Set_Back_Flag_Model(NULL);
- } else {
- //Set_Back_Flag_Model("O_Flag.w3d", Get_Team_Color());
- Set_Back_Flag_Model("O_Flag.w3d", Get_Color_For_Team(team));
- }
- }
- */
- /*
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Set_Precision(void)
- {
- cEncoderList::Set_Precision(BITPACK_CTF_TEAM_FLAG, NO_FLAG, (int) PLAYERTYPE_GDI);
- }
- */
- //------------------------------------------------------------------------------------
- SoldierObserverClass * SoldierGameObj::Get_Innate_Controller( void )
- {
- if ( Get_Definition().UseInnateBehavior ) {
- const GameObjObserverList & observer_list = Get_Observers();
- for( int index = 0; index < observer_list.Count(); index++ ) {
- if ( !strcmp( observer_list[ index ]->Get_Name(), "Innate Soldier" ) ) {
- return (SoldierObserverClass *)observer_list[ index ];
- }
- }
- }
- return NULL;
- }
- //------------------------------------------------------------------------------------
- const char * SoldierGameObj::Get_First_Person_Hands_Model_Name( void )
- {
- return Get_Definition().FirstPersonHands;
- }
- //------------------------------------------------------------------------------------
- void SoldierGameObj::Get_Information( StringClass & string )
- {
- SmartGameObj::Get_Information( string );
- HumanState.Get_Information( string );
- SoldierObserverClass * innate = Get_Innate_Controller();
- if ( innate ) {
- innate->Get_Information( string );
- StringClass disabled;
- if (!Is_Innate_Enabled(SOLDIER_INNATE_EVENT_BULLET_HEARD)) {
- disabled += "B";
- }
- if (!Is_Innate_Enabled(SOLDIER_INNATE_EVENT_GUNSHOT_HEARD)) {
- disabled += "G";
- }
- if (!Is_Innate_Enabled(SOLDIER_INNATE_EVENT_FOOTSTEP_HEARD)) {
- disabled += "F";
- }
- if (!Is_Innate_Enabled(SOLDIER_INNATE_EVENT_ENEMY_SEEN)) {
- disabled += "S";
- }
- if (!Is_Innate_Enabled(SOLDIER_INNATE_ACTIONS)) {
- disabled += "A";
- }
- if ( !disabled.Is_Empty() ) {
- string += "Disabled:";
- string += disabled;
- string += "\n";
- }
- }
- }
- //------------------------------------------------------------------------------------
- //void SoldierGameObj::Get_Extended_Information(StringClass & description)
- void SoldierGameObj::Get_Description(StringClass & description)
- {
- StringClass line;
- line.Format("ID: %d\n", Get_ID());
- description += line;
- line.Format("NAME: %s\n", Get_Definition().Get_Name());
- description += line;
- line.Format("TEAM: %d\n", Get_Player_Type());
- description += line;
- line.Format("CONTR: %d\n", Get_Control_Owner());
- description += line;
- Vector3 position;
- Get_Position(&position);
- line.Format("POS: %-5.2f, %-5.2f, %-5.2f\n", position.X, position.Y, position.Z);
- description += line;
- Vector3 target = Get_Targeting_Pos();
- line.Format("TGT: %-5.2f, %-5.2f, %-5.2f\n", target.X, target.Y, target.Z);
- description += line;
- Vector3 velocity;
- Get_Velocity(velocity);
- line.Format("VEL: %-5.2f, %-5.2f, %-5.2f\n", velocity.X, velocity.Y, velocity.Z);
- description += line;
- WeaponClass * p_weapon = Get_Weapon();
- if (p_weapon != NULL) {
- line.Format("WEAP: %s\n", p_weapon->Get_Name());
- description += line;
- line.Format("TRNDS: %d\n", p_weapon->Get_Total_Rounds());
- description += line;
- }
- line.Format("HLTH: %-5.2f\n", DefenseObject.Get_Health());
- description += line;
- line.Format("HMAX: %-5.2f\n", DefenseObject.Get_Health_Max());
- description += line;
- HumanPhysClass * p_human_phys = Peek_Human_Phys();
- if (p_human_phys != NULL) {
- line.Format("FACE: %-5.2f\n", p_human_phys->Get_Facing());
- description += line;
- }
- line.Format("STATE: %s", Get_State_Name());
- if (Is_Crouched()) {
- line += " (Crouched)";
- }
- line += "\n";
- description += line;
- line.Format("ANIM: %s\n", AnimationName);
- description += line;
- if (Vehicle != NULL) {
- line.Format("VEH: %d\n", Vehicle->Get_ID());
- description += line;
- }
- const GameObjObserverList & observer_list = Get_Observers();
- line.Format("#OBSV: %d\n", observer_list.Count());
- description += line;
- for (int index = 0; index < observer_list.Count(); index++) {
- line.Format(" %s\n", observer_list[index]->Get_Name());
- description += line;
- }
-
- line.Format("INNAT: %d\n", Is_Innate_Enabled());
- description += line;
- line.Format("HIB: %d\n", Is_Hibernating());
- description += line;
- line.Format("CTRL: %d, %d, %5.2f, %5.2f, %5.2f, %5.2f\n",
- Control.Get_One_Time_Boolean_Bits(),
- Control.Get_Continuous_Boolean_Bits(),
- Control.Get_Analog(ControlClass::ANALOG_MOVE_FORWARD),
- Control.Get_Analog(ControlClass::ANALOG_MOVE_LEFT),
- Control.Get_Analog(ControlClass::ANALOG_MOVE_UP),
- Control.Get_Analog(ControlClass::ANALOG_TURN_LEFT));
- description += line;
- ActionClass * p_action = Get_Action();
- if (p_action != NULL)
- {
- line.Format("ACTCT: %d\n", p_action->Get_Act_Count());
- description += line;
- Vector3 move_loc = p_action->Get_Parameters().MoveLocation;
- line.Format("MVLOC: (%5.2f, %5.2f, %5.2f)\n", move_loc.X, move_loc.Y, move_loc.Z);
- description += line;
- }
- line.Format("stlth: %d\n", Is_Stealth_Enabled());
- description += line;
- line.Format(" on: %d\n", Is_Stealthed());
- description += line;
- line.Format("ISC: %d\n", Get_Import_State_Count());
- description += line;
- }
- //------------------------------------------------------------------------------------
- struct {
- ArmorWarheadManager::SpecialDamageType Mode;
- const char * EmitterName;
- const char * BoneName;
- } _SpecialDamageEmitters[] = {
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_FIRE, "AG_FLAME01", "C SPINE" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C SPINE" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C L UPPERARM" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C R UPPERARM" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C L CALF" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C R CALF" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE, "AG_FLAME01", "C NECK" },
- // { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_FIRE, "E_FLAME01", "C L UPPERARM" },
- // { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_FIRE, "E_FLAME01", "C R UPPERARM" },
- { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_CHEM, "e_tib_dump", "C SPINE" },
- // { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_CHEM, "e_tib_dump", "C L UPPERARM" },
- // { ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_CHEM, "e_tib_dump", "C R UPPERARM" },
- };
- #define NUM_SPECIAL_DAMAGE_EMITTERS (sizeof(_SpecialDamageEmitters)/sizeof(_SpecialDamageEmitters[0]))
- void SoldierGameObj::Set_Special_Damage_Mode( ArmorWarheadManager::SpecialDamageType mode, ArmedGameObj * damager )
- {
- // Check for turning off
- if ( mode == ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE ) {
- // remove all subobjs from the bones used
- for ( int emitter = 0; emitter < NUM_SPECIAL_DAMAGE_EMITTERS; emitter++ ) {
- if ( _SpecialDamageEmitters[emitter].Mode == SpecialDamageMode ) {
- int bone = Peek_Model()->Get_Bone_Index( _SpecialDamageEmitters[emitter].BoneName );
- int sub_count = Peek_Model()->Get_Num_Sub_Objects_On_Bone( bone );
- while ( --sub_count >= 0 ) {
- RenderObjClass * sub = Peek_Model()->Get_Sub_Object_On_Bone( sub_count, bone );
- if ( ::stricmp(sub->Get_Name(), _SpecialDamageEmitters[emitter].EmitterName ) == 0 ) {
- Peek_Model()->Remove_Sub_Object( sub );
- }
- sub->Release_Ref();
- }
- }
- }
- if ( SpecialDamageEffect != NULL ) {
- SpecialDamageEffect->Set_Target_Parameter(0);
- SpecialDamageEffect->Enable_Remove_On_Complete(true);
- REF_PTR_RELEASE( SpecialDamageEffect );
- }
- if ( !Is_Human_Controlled() && IS_MISSION ) {
- if ( HumanState.Get_State() >= HumanStateClass::ON_FIRE &&
- HumanState.Get_State() <= HumanStateClass::ON_CNC_CHEM ) {
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- }
- }
- SpecialDamageDamager = NULL;
- } else {
- if ( mode != SpecialDamageMode ) {
- // Remove old mode
- Set_Special_Damage_Mode( ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_NONE );
- if ( Allow_Special_Damage_State_Lock() && IS_MISSION && mode != ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_SUPER_FIRE ) {
- HumanState.Set_State( (HumanStateClass::HumanStateType)( mode -
- ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_FIRE + HumanStateClass::ON_FIRE ) );
- }
- // Add new emitters
- for ( int emitter = 0; emitter < NUM_SPECIAL_DAMAGE_EMITTERS; emitter++ ) {
- if ( _SpecialDamageEmitters[emitter].Mode == mode ) {
- RenderObjClass * ro = WW3DAssetManager::Get_Instance()->Create_Render_Obj(
- _SpecialDamageEmitters[emitter].EmitterName );
- if ( ro != NULL ) {
- Peek_Model()->Add_Sub_Object_To_Bone( ro, _SpecialDamageEmitters[emitter].BoneName );
- ro->Release_Ref();
- }
- }
- }
- // Add electric effect
- if ( mode == ArmorWarheadManager::SPECIAL_DAMAGE_TYPE_ELECTRIC ) {
- WWASSERT( SpecialDamageEffect == NULL );
- SpecialDamageEffect = CombatMaterialEffectManager::Get_Electrocution_Effect();
- if ( SpecialDamageEffect != NULL ) {
- SpecialDamageEffect->Set_Target_Parameter(0.49f); // go almost halfway
- Peek_Human_Phys()->Add_Effect_To_Me( SpecialDamageEffect );
- }
- }
- // Save Damager
- SpecialDamageDamager = damager;
- }
- }
- SpecialDamageMode = mode;
- SpecialDamageTimer = ArmorWarheadManager::Get_Special_Damage_Duration( SpecialDamageMode );
- }
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Perturb_Position(float max_perturb)
- {
- //
- // Jiggle the soldier to a non-intersecting position
- //
- Vector3 initial_position;
- Get_Position(&initial_position);
- Vector3 new_position;
- WWASSERT(Peek_Human_Phys() != NULL);
- bool succeeded = Peek_Human_Phys()->Find_Teleport_Location(
- initial_position, max_perturb, &new_position);
- if (succeeded) {
- Set_Position(new_position);
- }
- }
- /*
- **
- */
- void SoldierGameObj::Toggle_Fly_Mode( void )
- {
- InFlyMode = !InFlyMode;
- if ( InFlyMode ) {
- HumanState.Set_State( HumanStateClass::DEBUG_FLY );
- Peek_Physical_Object()->Set_Collision_Group( UNCOLLIDEABLE_GROUP );
- } else {
- HumanState.Set_State( HumanStateClass::UPRIGHT );
- Peek_Physical_Object()->Set_Collision_Group( SOLDIER_COLLISION_GROUP );
- }
- }
- /*
- **
- */
- void SoldierGameObj::Set_AI_State( SoldierAIState state )
- {
- //
- // Is the soldier changing states?
- //
- if ( AIState != state ) {
- //
- // Kill the conversation (if necessary)
- //
- if ( state >= AI_STATE_SEARCH && state > AIState &&
- ActiveConversation != NULL &&
- ActiveConversation->Is_Interruptable ())
- {
- ActiveConversation->Stop_Conversation (ACTION_COMPLETE_CONVERSATION_INTERRUPTED);
- }
- AIState = state;
- }
- return ;
- }
- /*
- ** Soldiers maintain all RenderObjs they have created for later use and saving
- ** This is used for weapon models
- */
- void SoldierGameObj::Add_RenderObj( RenderObjClass * obj )
- {
- RenderObjList.Add( obj );
- obj->Add_Ref();
- }
- RenderObjClass * SoldierGameObj::Find_RenderObj( const char * name )
- {
- for ( int i = 0; i < RenderObjList.Count(); i++ ) {
- if ( !stricmp( RenderObjList[i]->Get_Name(), name ) ) {
- return RenderObjList[i];
- }
- }
- return NULL;
- }
- void SoldierGameObj::Reset_RenderObjs( void )
- {
- while ( RenderObjList.Count() ) {
- RenderObjList[0]->Release_Ref();
- RenderObjList.Delete( 0 );
- }
- }
- /*
- //-----------------------------------------------------------------------------
- void SoldierGameObj::Change_Flag_Status(int ctf_team_flag)
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- if (ctf_team_flag == NO_FLAG) {
- //
- // We dropped a flag
- //
- WWASSERT(WWAudioClass::Get_Instance() != NULL);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Drop_Flag", Get_Transform());
- float speed_factor = 100 / (float) CombatManager::Get_Max_Speed_Pc(this);
- Set_Max_Speed(speed_factor * Get_Max_Speed());
- Set_Ctf_Team_Flag(ctf_team_flag);
- } else {
- //
- // We picked up a flag
- //
- WWASSERT(WWAudioClass::Get_Instance() != NULL);
- WWAudioClass::Get_Instance()->Create_Instant_Sound("Pick_Up_Flag", Get_Transform());
- Set_Ctf_Team_Flag(ctf_team_flag);
- float speed_factor = CombatManager::Get_Max_Speed_Pc(this) / 100.0f;
- Set_Max_Speed(speed_factor * Get_Max_Speed());
- }
- }
- */
- /*
- void SoldierGameObj::Interpret_Sc_Position_Data(Vector3 & sc_position)
- {
- WWASSERT(CombatManager::I_Am_Only_Client());
- switch (CombatManager::Get_Client_Interpolation_Model()) {
- case CLIENT_INTERPOLATION_SERVER_AUTHORITATIVE:
- //
- // Simplest case - pop to location given by server
- //
- //Set_Position(sc_position);
- if (Get_State() == HumanStateClass::TRANSITION) {
- //
- // Pop
- //
- Set_Position(sc_position);
- if (Get_Control_Owner() == CombatManager::Get_My_Id()) {
- Debug_Say(("Popping own soldier at time %s\n", cMiscUtil::Get_Text_Time()));
- }
- } else {
- Vector3 current_position;
- Get_Position(¤t_position);
- Vector3 pos_error = current_position - sc_position;
- if (pos_error.Length() > 2.0f) {
- Set_Position(sc_position);
- if (Get_Control_Owner() == CombatManager::Get_My_Id()) {
- Debug_Say(("Popping own soldier at time %s\n", cMiscUtil::Get_Text_Time()));
- }
- }
- }
- break;
- case CLIENT_INTERPOLATION_SERVER_AUTHORITATIVE_WITH_BLENDING:
- if (Get_State() == HumanStateClass::TRANSITION) {
- //
- // Pop
- //
- Set_Position(sc_position);
- } else {
- //
- // Blend to position given by server
- //
- Vector3 current_position;
- Get_Position(¤t_position);
- Set_Position(0.50 * current_position + 0.50 * sc_position);
- }
- break;
- case CLIENT_INTERPOLATION_PATHFIND: {
- Vector3 current_position;
- Get_Position(¤t_position);
- Vector3 pos_error = current_position - sc_position;
- if (pos_error.Length() > 0.02f) {
- if (Get_Control_Owner() == CombatManager::Get_My_Id()) {
- if (pos_error.Length() > 2) {
- //
- // Client is authoritative over his own guy, unless error
- // becomes significant. In this case, pop.
- //
- Set_Position(sc_position);
- }
- } else {
- //if (pos_error.Length() > 20) {
- // //
- // // Pop
- // //
- // Set_Position(sc_position);
- //} else {
-
- //
- // For NPC's the server could transmit the final destination as well as
- // the proper location. Pop if appropriate to get as close to
- // proper dest as possible, but pathfind instead to the final dest.
- //
- ActionParamsStruct parameters;
- parameters.Priority = 1;
- parameters.MoveLocation = sc_position;
- parameters.MoveArrivedDistance = 0.1f;
- WWASSERT(Get_Action() != NULL);
- Get_Action()->Goto(parameters);
- //}
- }
- }
- break;
- }
- default:
- WWASSERT(0);
- }
- }
- */
- /*
- void SoldierGameObj::Think_Pathfind( void )
- {
- // CLIENT_PATHFINDING
- //
- // Pop pathfinding client-side soldiers at the earliest opportunity -
- // as soon as we find them out of the camera fulcrum.
- //
- if (CombatManager::I_Am_Only_Client() &&
- Get_Control_Owner() != CombatManager::Get_My_Id()) {
-
- Vector3 current_position;
- Get_Position(¤t_position);
- ActionClass * p_action = Get_Action();
- WWASSERT(p_action != NULL);
- const Vector3 height_offset(0, 0, 0.9f);
- Vector3 from_position = current_position + height_offset;
- Vector3 to_position = p_action->MovementLocation + height_offset;
- //
- // We can only pop if he is not presently in the camera fulcrum.
- //
- if (p_action->MovementAction != NULL &&
- !CombatManager::Is_In_Camera_Frustrum(from_position)) {
- if (!CombatManager::Is_In_Camera_Frustrum(to_position)) {
- //
- // If the correct position is also out of the fulcrum, pop
- // all the way there.
- //
- Set_Position(p_action->MovementLocation);
- p_action->Set_Movement(NULL);
- } else {
- //
- // We are crossing into the fulcrum. Pop as close to the edge
- // of the fulcrum as possible and pathfind from there.
- //
-
- //Debug_Say(("FRAME\n"));
- bool is_finished = false;
- do {
- Vector3 next_pos;
- p_action->Movement_Act(next_pos);
-
- //if (CombatManager::Is_In_Camera_Frustrum(next_pos + height_offset)) {
- // is_finished = true;
- //
- // //
- // // Logically it would be better if the next line could be omitted.
- // // However this seems to screw things up.
- // //
- // Set_Position(next_pos);
- //
- // //Debug_Say(("Finished skipping."));
- //} else {
- // Set_Position(next_pos);
- //
- // //Debug_Say(("Skipping to (%5.2f, %5.2f, %5.2f)\n",
- // // next_pos.X, next_pos.Y, next_pos.Z));
- //}
-
- Set_Position(next_pos);
- Vector3 adjusted_next_pos = next_pos + height_offset;
- if (CombatManager::Is_In_Camera_Frustrum(adjusted_next_pos)) {
- is_finished = true;
- }
- } while ((p_action->MovementAction != NULL) && !is_finished);
- }
- }
- }
- }
- void SoldierGameObj::Think_Pathfind(void)
- {
- //
- // Pop pathfinding client-side soldiers at the earliest opportunity -
- // as soon as we find them out of the camera fulcrum.
- //
- if ((CombatManager::Get_Client_Interpolation_Model() == CLIENT_INTERPOLATION_PATHFIND) &&
- CombatManager::I_Am_Only_Client() &&
- Get_Control_Owner() != CombatManager::Get_My_Id()) {
-
- Vector3 current_position;
- Get_Position(¤t_position);
- ActionClass * p_action = Get_Action();
- WWASSERT(p_action != NULL);
- ActionParamsStruct parameters = p_action->Get_Parameters();
- const Vector3 height_offset(0, 0, 0.9f);
- Vector3 from_position = current_position + height_offset;
- Vector3 to_position = parameters.MoveLocation + height_offset;
- //
- // We can only pop if he is not presently in the camera fulcrum.
- //
- if (!CombatManager::Is_In_Camera_Frustrum(from_position)) {
- if (!CombatManager::Is_In_Camera_Frustrum(to_position)) {
- //
- // If the correct position is also out of the fulcrum, pop
- // all the way there.
- //
- Set_Position(to_position);
- } else {
- //
- // Keep popping until we are almost in the fulcrum.
- //
- Vector3 current_pos;
- Get_Position(¤t_pos);
- Vector3 last_pos;
- Vector3 test_pos;
- do {
- last_pos = current_pos;
- p_action->Act();
- Get_Position(¤t_pos);
- test_pos = current_pos + height_offset;
- } while ((current_pos != last_pos) &&
- !CombatManager::Is_In_Camera_Frustrum(test_pos));
- Set_Position(last_pos);
- }
- }
- }
- }
- */
- void SoldierGameObj::Update_Healing_Effect( void )
- {
- if ( HealingEffect != NULL ) {
- if (( HealingEffect->Get_Target_Parameter() >= 0.49f ) &&
- ( HealingEffect->Get_Parameter() >= 0.49f ) ) {
- HealingEffect->Set_Target_Parameter( 0 );
- }
- if (( HealingEffect->Get_Target_Parameter() == 0 ) &&
- ( HealingEffect->Get_Parameter() == 0 ) ) {
- Peek_Human_Phys()->Remove_Effect_From_Me( HealingEffect );
- REF_PTR_RELEASE( HealingEffect );
- }
- }
- }
- void SoldierGameObj::Enable_Ghost_Collision( bool onoff )
- {
- bool is_using_ghost_collision = (Peek_Physical_Object ()->Get_Collision_Group() == SOLDIER_GHOST_COLLISION_GROUP);
- if ( onoff == is_using_ghost_collision ) {
- return ;
- }
- //
- // Change the collision group as necessary
- //
- if ( onoff ) {
- Peek_Physical_Object ()->Set_Collision_Group( SOLDIER_GHOST_COLLISION_GROUP );
- } else {
- Peek_Physical_Object ()->Set_Collision_Group( SOLDIER_COLLISION_GROUP );
- }
- return ;
- }
- bool SoldierGameObj::Is_Safe_To_Disable_Ghost_Collision( const Vector3 &curr_pos )
- {
- const Vector3 PERSONAL_SPACE_BOX_SIZE (1.5F, 1.5F, 1.0F);
- const float HUMAN_HALF_HEIGHT = 1.0F;
- bool retval = true;
- //
- // Build a box that represents the "personal" space around the soldier
- //
- Vector3 box_pos = curr_pos + Vector3 (0, 0, HUMAN_HALF_HEIGHT);
- AABoxClass box (box_pos, PERSONAL_SPACE_BOX_SIZE);
- //
- // Collect all the dynamic objects in this box
- //
- NonRefPhysListClass obj_list;
- PhysicsSceneClass::Get_Instance ()->Collect_Objects (box, false, true, &obj_list);
- //
- // Loop over all the collected objects
- //
- NonRefPhysListIterator it (&obj_list);
- for (it.First(); !it.Is_Done(); it.Next()) {
- PhysClass *phys_obj = it.Peek_Obj ();
- PhysicalGameObj *game_obj = NULL;
- if ( phys_obj->As_HumanPhysClass () && phys_obj->Get_Observer() != NULL ) {
- game_obj = ((CombatPhysObserverClass *)phys_obj->Get_Observer())->As_PhysicalGameObj();
- }
- //
- // Is this a living soldier?
- //
- if ( game_obj != NULL && game_obj != this &&
- game_obj->As_SoldierGameObj() != NULL &&
- game_obj->As_SoldierGameObj()->Is_Destroyed () == false)
- {
- Vector3 block_pos;
- game_obj->Get_Position (&block_pos);
- //
- // Lets make sure the boxes really intersect
- //
- AABoxClass block_box (block_pos + Vector3 (0, 0, 1.0F), Vector3 (0.3F, 0.3F, 1.0F));
- if (CollisionMath::Overlap_Test (box, block_box) != CollisionMath::OUTSIDE) {
- //
- // Is the boxes intersect, then it is NOT SAFE to disable ghost collision
- // mode.
- //
- retval = false;
- break;
- }
- }
- }
- return retval;
- }
- bool SoldierGameObj::Is_Soldier_Blocked( const Vector3 &curr_pos )
- {
- //
- // Only do this for soldiers who meet our criteria
- //
- if ( (Get_Action () != NULL && Get_Action ()->Is_Busy ()) ||
- Is_Destroyed () || (IS_SOLOPLAY == false))
- {
- return false;
- }
- const Vector3 PERSONAL_SPACE_BOX_SIZE (1.5F, 1.5F, 1.0F);
- const float HUMAN_HALF_HEIGHT = 1.0F;
- //
- // Build a box that represents the "personal" space around the soldier
- //
- Vector3 box_pos = curr_pos + Vector3 (0, 0, HUMAN_HALF_HEIGHT);
- AABoxClass box (box_pos, PERSONAL_SPACE_BOX_SIZE);
- //
- // Collect all the dynamic objects in this box
- //
- NonRefPhysListClass obj_list;
- PhysicsSceneClass::Get_Instance ()->Collect_Objects (box, false, true, &obj_list);
- uint32 my_id = Get_ID ();
- uint32 smallest_id = my_id;
- //
- // Loop over all the collected objects
- //
- NonRefPhysListIterator it (&obj_list);
- for (it.First(); !it.Is_Done(); it.Next()) {
- PhysClass *phys_obj = it.Peek_Obj ();
- PhysicalGameObj *game_obj = NULL;
- if ( phys_obj->As_HumanPhysClass () && phys_obj->Get_Observer() != NULL ) {
- game_obj = ((CombatPhysObserverClass *)phys_obj->Get_Observer())->As_PhysicalGameObj();
- }
- //
- // Is this a living soldier?
- //
- if ( game_obj != NULL && game_obj != this &&
- game_obj->As_SoldierGameObj() != NULL &&
- game_obj->As_SoldierGameObj()->Is_Destroyed () == false)
- {
- Vector3 block_pos;
- game_obj->Get_Position (&block_pos);
- //
- // Lets make sure the boxes really intersect
- //
- AABoxClass block_box (block_pos + Vector3 (0, 0, 1.0F), Vector3 (0.3F, 0.3F, 1.0F));
- if (CollisionMath::Overlap_Test (box, block_box) != CollisionMath::OUTSIDE) {
- if (game_obj->As_SmartGameObj ()->Is_Human_Controlled () == false) {
-
- //
- // Is this soldier moving?
- //
- ActionClass *curr_action = game_obj->As_SmartGameObj ()->Get_Action ();
- Vector3 dest_pos = curr_action->Get_Parameters ().MoveLocation;
- float distance = (block_pos - dest_pos).Length ();
- if (distance > curr_action->Get_Parameters ().MoveArrivedDistance) {
- //
- // Is this the smallest ID so far?
- //
- uint32 curr_id = game_obj->Get_ID ();
- if (curr_id < smallest_id) {
- smallest_id = curr_id;
- }
- //
- // Push the other guy out of the way (a little)
- //
- /*if (Is_Human_Controlled () || curr_id > my_id) {
- Vector3 delta_vector = block_pos - curr_pos;
- delta_vector.Normalize ();
- SoldierGameObj *soldier = game_obj->As_SoldierGameObj ();
- if (soldier->Peek_Human_Phys () != NULL) {
- soldier->Peek_Human_Phys ()->Collide (delta_vector * TimeManager::Get_Frame_Seconds ());
- }
- }*/
- }
- }
- }
- }
- }
- return (smallest_id != my_id);
- }
- bool SoldierGameObj::Is_Targetable( void ) const
- {
- return (!(((SoldierGameObj*)this)->Is_In_Vehicle())) &&
- SmartGameObj::Is_Targetable();
- }
- float SoldierGameObj::Get_Stealth_Fade_Distance(void) const
- {
- if (IS_MISSION) {
- return GlobalSettingsDef::Get_Global_Settings()->Get_Stealth_Distance_Human();
- } else {
- return GlobalSettingsDef::Get_Global_Settings()->Get_MP_Stealth_Distance_Human();
- }
- }
- void SoldierGameObj::Lock_Facing( PhysicalGameObj * game_obj, bool turn_body )
- {
- FacingObject = game_obj;
- FacingAllowBodyTurn = turn_body;
- //
- // Stop facing if there's nothing to look at
- //
- if ( game_obj == NULL ) {
- Cancel_Look_At();
- }
- return ;
- }
- void SoldierGameObj::Update_Locked_Facing( void )
- {
- if ( FacingObject != NULL ) {
- //
- // Get the position of the object we're "looking" at.
- //
- Vector3 pos;
- FacingObject.Get_Ptr ()->Get_Position( &pos );
- //
- // If the object is a soldier, then look at his head
- //
- if ( FacingObject.Get_Ptr ()->As_PhysicalGameObj ()->As_SoldierGameObj () != NULL ) {
- const float SOLDIER_HEIGHT = 1.7F;
- pos.Z += SOLDIER_HEIGHT;
- }
- //
- // Look at the object
- //
- Look_At( pos, 100.0F );
-
- //
- // If we can turn to face the object, do so...
- //
- if ( FacingAllowBodyTurn ) {
- Internal_Set_Targeting( pos, false );
- }
- }
- return ;
- }
- /*
- if (CombatManager::I_Am_Server()) {
- CombatManager::Soldier_Dies(this);
- }
- */
|