1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510 |
- //******************************************************************************************
- //
- // mover.cpp - This file contains the Mover Class code
- //
- // MechCommander 2
- //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- #ifndef MCLIB_h
- #include "mclib.h"
- #endif
- #ifndef GAMEOBJ_H
- #include "gameobj.h"
- #endif
- #ifndef OBJMGR_H
- #include "objmgr.h"
- #endif
- #ifndef MOVER_H
- #include "mover.h"
- #endif
- #ifndef MOVE_H
- #include "move.h"
- #endif
- #ifndef MECH_H
- #include "mech.h"
- #endif
- #ifndef GVEHICL_H
- #include "gvehicl.h"
- #endif
- #ifndef MECH3D_H
- #include "mech3d.h"
- #endif
- #ifndef CMPONENT_H
- #include "cmponent.h"
- #endif
- #ifndef WARRIOR_H
- #include "warrior.h"
- #endif
- #ifdef USE_DEBRIS
- #ifndef DEBRIS_H
- #include "debris.h"
- #endif
- #endif
- #ifndef GAMELOG_H
- #include "gamelog.h"
- #endif
- #ifndef TACORDR_H
- #include "tacordr.h"
- #endif
- #ifndef GAMESOUND_H
- #include "gamesound.h"
- #endif
- //#ifndef SOUNDSYS_H
- //#include "soundsys.h"
- //#endif
- //#ifndef SOUNDS_H
- //#include "sounds.h"
- //#endif
- #ifndef COLLSN_H
- #include "collsn.h"
- #endif
- #ifndef MECHCLASS_H
- #include "mechclass.h"
- #endif
- #ifndef UNITDESG_H
- #include "unitdesg.h"
- #endif
- #ifndef MULTPLYR_H
- #include "multplyr.h"
- #endif
- #ifndef TEAM_H
- #include "team.h"
- #endif
- #ifndef COMNDR_H
- #include "comndr.h"
- #endif
- #ifndef GROUP_H
- #include "group.h"
- #endif
- #ifndef CONTACT_H
- #include "contact.h"
- #endif
- #ifndef TRIGGER_H
- #include "trigger.h"
- #endif
- #ifndef MISSION_H
- #include "mission.h"
- #endif
- #ifndef LOGISTICSPILOT_H
- #include "logisticspilot.h"
- #endif
- //--------
- // DEFINES
- #define GOALMAP_CELL_DIM 61
- //--------
- // GLOBALS
- extern long SimpleMovePathRange;
- extern long GroupMoveTrailLen[2];
- extern long tileMulMAPCELL_DIM[MAX_MAP_CELL_WIDTH];
- extern long RamObjectWID;
- long MaxMoveGoalChecks = 60;
- float DelayedOrderTime = 1.0;
- float GroupOrderGoalOffset = 127.0;
- //BaseObjectPtr MoverRoster[MAX_MOVER_PART_ID - MIN_MOVER_PART_ID + 1];
- extern MoveMapPtr PathFindMap[2/*NUM_PATHMAPS*/];
- long goalMap[GOALMAP_CELL_DIM * GOALMAP_CELL_DIM];
- long goalMapRowStart[GOALMAP_CELL_DIM] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- };
- char goalMapRowCol[GOALMAP_CELL_DIM * GOALMAP_CELL_DIM][2];
- long Mover::numMovers = 0;
- SortListPtr Mover::sortList = NULL;
- extern float DefaultAttackRadius;
- extern float WeaponFireModifiers[NUM_WEAPONFIRE_MODIFIERS];
- extern void DebugWeaponFireChunk (WeaponFireChunkPtr chunk1, WeaponFireChunkPtr chunk2, GameObjectPtr attacker);
- //--------
- // EXTERNS
- //extern ObjectMapPtr GameObjectMap;
- extern unsigned long NextIdNumber;
- #ifdef USE_SOUNDS
- extern bool friendlyDestroyed;
- extern bool enemyDestroyed;
- #endif
- extern TeamPtr homeTeam;
- extern bool JumpOnBlocked;
- extern bool FindingEscapePath;
- //extern float FireOddsTable[NUM_FIREODDS];
- extern float RankVersusChassisCombatModifier[NUM_WARRIOR_RANKS][NUM_MECH_CLASSES];
- float WeaponFireModifiers[NUM_WEAPONFIRE_MODIFIERS] = {
- 0.0, // Short Range To Target
- -10.0, // Medium Range To Target
- -20.0, // Long Range To Target
- -98.0, // Aimed Shot To Head
- -85.0, // Aimed Shot To Torso
- -88.0, // Aimed Shot To Arm/Leg
- 50.0, // Target is Stationary
- 0.0, // Green/Light
- -5.0, // Green/Medium
- -15.0, // Green/Heavy
- -25.0, // Green/Assault
- 5.0, // Regular/Light
- 0.0, // Regular/Medium
- -5.0, // Regular/Heavy
- -15.0, // Regular/Assault
- 10.0, // Veteran/Light
- 5.0, // Veteran/Medium
- 0.0, // Veteran/Heavy
- -5.0, // Veteran/Assault
- 15.0, // Elite/Light
- 10.0, // Elite/Medium
- 5.0, // Elite/Heavy
- 0.0, // Elite/Assault
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0
- };
- extern float WarriorRankScale[NUM_WARRIOR_RANKS];
- extern char * SpecialtySkillsTable[NUM_SPECIALTY_SKILLS];
- float WeaponSpecialistModifier = 20.0f;
- extern float MovementUpdateFrequency;
- extern float CombatUpdateFrequency;
- extern float CommandUpdateFrequency;
- extern float PilotCheckUpdateFrequency;
- extern long PilotCheckModifierTable[2];
- //extern float ElementalTargetNoJumpDistance;
- extern long MechSalvageChance;
- extern float MapCellDiagonal;
- //extern long OverlayWeightIndex[NUM_OVERLAY_TYPES];
- extern long NumLocationCriticalSpaces[NUM_BODY_LOCATIONS];
- extern GlobalMapPtr GlobalMoveMap[3];
- extern long adjCellTable[MAPCELL_DIM * MAPCELL_DIM][8][4];
- extern bool useUnlimitedAmmo;
- extern bool CantBlowSalvage;
- long TargetRolo = -1;
- WeaponFireChunk CurMoverWeaponFireChunk;
- extern char* ExceptionGameMsg;
- extern char ChunkDebugMsg[5120];
- extern char OverlayIsBridge[NUM_OVERLAY_TYPES];
- float GroundVehiclePivotYawMultiplier = 0.25;
- extern bool friendlyDestroyed;
- extern bool enemyDestroyed;
- extern GameLog* CombatLog;
- //**********************************************************************************
- float Mover::newThreatMultiplier = 3.0;
- float Mover::marginOfError[2] = {5.0, 10.0};
- float Mover::refitRange;
- float Mover::refitTime;
- float Mover::refitCostArray[NUM_COSTS][NUM_FIXERS];
- float Mover::refitAmount;
- float Mover::recoverRange;
- float Mover::recoverTime;
- float Mover::recoverCost;
- float Mover::recoverAmount;
- long Mover::IndirectFireWeapons[20] = {-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1};
- long Mover::AreaEffectWeapons[20] = {-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1};
- bool Mover::inRecoverUpdate = false;
- long StatusChunkUnpackErr = 0;
- char AttackParameters[14][3] = {
- {ATTACK_TO_DESTROY, FIRERANGE_OPTIMAL, 1}, // DESTROY
- {ATTACK_TO_DESTROY, FIRERANGE_SHORT, 0}, // STOP AND HOLD FIRE
- {ATTACK_TO_DESTROY, FIRERANGE_SHORT, 1}, // DESTROY - SR
- {ATTACK_TO_DESTROY, FIRERANGE_MEDIUM, 1}, // DESTROY - MR
- {ATTACK_TO_DESTROY, FIRERANGE_LONG, 1}, // DESTROY - LR
- {ATTACK_TO_DESTROY, FIRERANGE_MEDIUM, 0}, // DESTROY FROM HERE
- {ATTACK_TO_DESTROY, FIRERANGE_MEDIUM, 1}, // DESTROY ALL OUT
- {ATTACK_TO_DISABLE, FIRERANGE_MEDIUM, 1}, // DISABLE
- {ATTACK_TO_DISABLE, FIRERANGE_SHORT, 0}, // STOP AND HOLD FIRE
- {ATTACK_TO_DISABLE, FIRERANGE_SHORT, 1}, // DISABLE - SR
- {ATTACK_TO_DISABLE, FIRERANGE_MEDIUM, 1}, // DISABLE - MR
- {ATTACK_TO_DISABLE, FIRERANGE_LONG, 1}, // DISABLE - LR
- {ATTACK_TO_DISABLE, FIRERANGE_MEDIUM, 0}, // DISABLE FROM HERE
- {ATTACK_TO_DISABLE, FIRERANGE_MEDIUM, 1} // DISABLE MAX SALVAGE
- };
- long rearAttackTable[NUM_DIRECTIONS][3][2] = {
- {{1, 0}, {1, -1}, {0, 1}},
- {{1, -1}, {0, -1}, {1, 1}},
- {{0, -1}, {-1, -1}, {1, 0}},
- {{-1, -1}, {-1, 0}, {1, -1}},
- {{-1, 0}, {-1, 1}, {0, -1}},
- {{-1, 1}, {0, 1}, {-1, -1}},
- {{1, 0}, {1, 1}, {-1, 0}},
- {{1, 1}, {1, 0}, {-1, 1}}
- };
- //---------------------------------------------------------------------------
- // Game System Tweakable Data
- //---------------------------------------------------------------------------
- float WeaponRange[NUM_FIRERANGES] = {
- 250,
- 500,
- 1000
- };
- float WeaponRanges[NUM_WEAPON_RANGE_TYPES][2] = {
- {0, 100},
- {50, 150},
- {100, 225},
- {0, 0},
- {0, 0}
- };
- float OptimalRangePoints[NUM_WEAPON_RANGE_TYPES] = {
- 25, //Short
- 125, //Med
- 200, //Long
- 75, //Short-Med
- 125 //Med-Long
- };
- bool OptimalRangePointInRange[NUM_WEAPON_RANGE_TYPES][3];
- unsigned char OptimalRangeTieTable[32] = {
- 255, 0, 1, 1,
- 2, 2, 2, 2,
- 3, 3, 3, 3,
- 3, 3, 3, 3,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4
- };
- float DefaultAttackRange = 75.0;
- float DisableAttackModifier = 10.0;
- float DisableGunneryModifier = 5.0;
- float SalvageAttackModifier = 30.0;
- float PilotingCheckFactor = 1.0;
- long hitLevel[2] = {
- 10, // weak hit is damage of <10
- 20 // moderate hit is damage <20, else heavy hit
- };
- long ClusterSizeSRM = 2; // eventually, let's just kill clusters!
- long ClusterSizeLRM = 5; // eventually, let's just kill clusters!
- long AntiMissileSystemStats[2][2] = {
- {1, 2}, // IS
- {2, 2} // CLAN
- };
- float PilotCheckHalfRate = 5.0;
- float DamageRateFrequency = 10.0;
- byte AttitudeEffect[NUM_ATTITUDES][6] = {
- {50, 75, 5, -2, 0, 3},
- {40, 60, 10, -1, 1, 5},
- {30, 50, 15, 0, 2, 10},
- {20, 40, 20, 1, 3, 15},
- {10, 25, 25, 1, 4, 20},
- {0, 0, 32, 2, 5, 128}
- };
- //extern bool SensorAutomaticSuccess;
- //extern float SensorModifier[8];
- float SensorBaseChance = 50.0;
- float SensorSkillFactor = 10.0;
- extern long DebugMovePathType;
- #ifdef USEHEAT
- float SensorHeatMultiplier = 5.0;
- float SensorWeaponHeatMultiplier = 5.0;
- float SensorHeatSourceModifiers[2] = {10.0, -10.0};
- extern float WeaponHeatCheckDelay;
- #endif
- float SensorBlockingObjectModifier = -5.0;
- float SensorShutDownMechModifier = -50.0;
- float SensorRangeModifier[4][2] = {
- {0.25f, 50.0},
- {0.15f, 20.0},
- {0.35f, 0.0},
- {0.25f, -25.0}
- };
- float SensorSizeModifier[3][2] = {
- {25.0, -10.0},
- {60.0, 0.0},
- {999.0, 15.0}
- };
- float SensorBlockingTerrain[2] = {-25.0, -5.0};
- long AimedFireAbort;
- long AimedFireHitTable[3];
- float FireArc[3];
- //bool LongRangeMovementEnabled[MAX_TEAMS];
- extern char ProfessionalismOffsetTable[NUM_OFFSET_RANGES][2];
- extern char DecorumOffsetTable[NUM_OFFSET_RANGES][2];
- extern char AmmoConservationModifiers[2][2];
- //extern long OverlayWeightTable[NUM_OVERLAY_WEIGHT_CLASSES * NUM_OVERLAY_TYPES * MAPCELL_DIM * MAPCELL_DIM];
- //extern long OverlayWeightIndex[NUM_OVERLAY_TYPES];
- //extern float MoveMarginOfError[2];
- extern float MoveTimeOut;
- extern float MoveYieldTime;
- extern long DefaultMechJumpCost;
- extern char SensorSkillMoveRange[4];
- extern float SensorSkillMoveFactor[8];
- float SkillTry[4];
- float SkillSuccess[4];
- float KillSkill[6];
- float WeaponHit;
- float SensorSkill;
- long MoveChunk::err = 0;
- float MaxStationaryTime = 0.0;
- float MaxTimeRevealed = 0.0f;
- #define CLAN_SEEN_FLAG 2
- #define IS_SEEN_FLAG 1
- extern float worldUnitsPerMeter;
- char Mover::optimalCells[MAX_ATTACK_CELLRANGE][MAX_ATTACK_INCREMENTS][2];
- long Mover::numOptimalIncrements = 0;
- short Mover::rangedCellsIndices[MAX_ATTACK_CELLRANGE][2];
- char Mover::rangedCells[RANGED_CELLS_DIM][2];
- TriggerAreaManager* Mover::triggerAreaMgr = NULL;
- unsigned long Mover::holdFireIconHandle = 0;
- float HeadShotModifier = 0.0f;
- float ArmShotModifier = 0.0f;
- float LegShotModifier = 0.0f;
- bool CalcValidAreaTable = true;
- void DEBUGWINS_print (char* s, long window);
- //***************************************************************************
- // MISC routines
- //***************************************************************************
- inline MoverPtr getMoverFromHandle (long handle) {
- return(dynamic_cast<MoverPtr>(ObjectManager->get(handle)));
- }
- //***************************************************************************
- // MOVECHUNK class
- //***************************************************************************
- #define MOVECHUNK_CELLPOS_BITS 9
- #define MOVECHUNK_NUMSTEPS_BITS 2
- #define MOVECHUNK_RUN_BITS 1
- #define MOVECHUNK_MOVING_BITS 1
- #define MOVECHUNK_STEP_BITS 3
- #define MOVECHUNK_CELLPOS_MASK 0x000001FF
- #define MOVECHUNK_NUMSTEPS_MASK 0x00000003
- #define MOVECHUNK_RUN_MASK 0x00000001
- #define MOVECHUNK_MOVING_MASK 0x00000001
- #define MOVECHUNK_STEP_MASK 0x00000007
- #define MOVECHUNK_NUM_STEPS 3
- //---------------------------------------------------------------------------
- void DebugMoveChunk (MoverPtr mover, MoveChunkPtr chunk1, MoveChunkPtr chunk2) {
- ChunkDebugMsg[0] = NULL;
- char outString[512];
- if (mover) {
- sprintf(outString, "Mover = %s (%d)\n",
- mover->getName(),
- mover->getPartId());
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "Mover World Pos = (%.4f, %.4f, %.4f)\n",
- mover->getPosition().x,
- mover->getPosition().y,
- mover->getPosition().z);
- strcat(ChunkDebugMsg, outString);
- long cellPos[2];
- mover->getCellPosition(cellPos[0], cellPos[1]);
- sprintf(outString, "Mover Obj Cell Pos = [%d, %d]\n", cellPos[0], cellPos[1]);
- strcat(ChunkDebugMsg, outString);
- if (mover->getPilot() == NULL)
- strcat(ChunkDebugMsg, "NULL pilot!\n");
- if ((mover->getObjectClass() == BATTLEMECH) && ((BattleMechPtr)mover)->inJump) {
- long jumpDest[2];
- land->worldToCell(((BattleMechPtr)mover)->jumpGoal, jumpDest[0], jumpDest[1]);
- sprintf(outString, "Jumping to [%d, %d]\n", jumpDest[0], jumpDest[1]);
- strcat(ChunkDebugMsg, outString);
- }
- strcat(ChunkDebugMsg, "\n");
- }
- if (chunk1) {
- strcat(ChunkDebugMsg, "CHUNK1\n");
- for (long i = 0; i < 4; i++) {
- sprintf(outString, "stepPos[%d] = (%d, %d)\n",
- i,
- chunk1->stepPos[i][0],
- chunk1->stepPos[i][1]);
- strcat(ChunkDebugMsg, outString);
- }
- sprintf(outString, "stepRelPos = %d, %d, %d\n",
- chunk1->stepRelPos[0],
- chunk1->stepRelPos[1],
- chunk1->stepRelPos[2]);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "numSteps = %d\n", chunk1->numSteps);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "run = %c\n", chunk1->run ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "moving = %c\n", chunk1->moving ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- }
- if (chunk2) {
- strcat(ChunkDebugMsg, "\nCHUNK2\n");
- for (long i = 0; i < 4; i++) {
- sprintf(outString, "stepPos[%d] = (%d, %d)\n",
- i,
- chunk2->stepPos[i][0],
- chunk2->stepPos[i][1]);
- strcat(ChunkDebugMsg, outString);
- }
- sprintf(outString, "stepRelPos = %d, %d, %d\n",
- chunk2->stepRelPos[0],
- chunk2->stepRelPos[1],
- chunk2->stepRelPos[2]);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "numSteps = %d\n", chunk2->numSteps);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "moving = %c\n", chunk2->moving ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "run = %c\n", chunk2->run ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- }
- File* debugFile = new File;
- debugFile->create("mvchunk.dbg");
- debugFile->writeString(ChunkDebugMsg);
- debugFile->close();
- delete debugFile;
- debugFile = NULL;
- ExceptionGameMsg = ChunkDebugMsg;
- }
- //---------------------------------------------------------------------------
- void* MoveChunk::operator new (size_t ourSize) {
- void* result = systemHeap->Malloc(ourSize);
- return(result);
- }
- //---------------------------------------------------------------------------
- void MoveChunk::operator delete (void* us) {
- systemHeap->Free(us);
- }
- //---------------------------------------------------------------------------
- inline void getAdjCell (long row,
- long col,
- long dir,
- long& adjRow,
- long& adjCol) {
- long adjMod[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1},
- {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
- adjRow = row + adjMod[dir][0];
- adjCol = col + adjMod[dir][1];
- }
- //---------------------------------------------------------------------------
- inline long cellDirToCell (long fromCellRow,
- long fromCellCol,
- long toCellRow,
- long toCellCol) {
- //-------------------------------------------------
- // This routine assumes the two cells are adjacent!
- static long deltaDir[3][3] = {
- {7, 0, 1},
- {6, -1, 2},
- {5, 4, 3}
- };
- long rowCellDelta = toCellRow - fromCellRow + 1;
- long colCellDelta = toCellCol - fromCellCol + 1;
- if ((rowCellDelta < 0) || (rowCellDelta > 2))
- return(-2);
- if ((colCellDelta < 0) || (colCellDelta > 2))
- return(-2);
- long dir = deltaDir[rowCellDelta][colCellDelta];
- if (dir == -1)
- return(-2);
- return(dir);
- }
- //---------------------------------------------------------------------------
- void MoveChunk::build (MoverPtr mover, MovePathPtr path1, MovePathPtr path2) {
- long cellPos[2];
- mover->getCellPosition(cellPos[0], cellPos[1]);
- stepPos[0][0] = cellPos[0];
- stepPos[0][1] = cellPos[1];
- stepRelPos[0] = 0;
- stepRelPos[1] = 0;
- stepRelPos[2] = 0;
- numSteps = 1;
- moving = path1 && (path1->numSteps > 0);
- if (path1 && path1->numSteps > 0) {
- bool reachedEndOfPath1 = true;
- long curStep = 1;
- if (path1->curStep < path1->numSteps) {
- reachedEndOfPath1 = false;
- long curPath1Step = path1->curStep;
- bool startWithCurStep = false;
- if ((cellPos[0] == path1->stepList[curPath1Step].cell[0]) &&
- (cellPos[1] == path1->stepList[curPath1Step].cell[1]))
- startWithCurStep = true;
- else {
- //--------------------------------------------------------------
- // Whacky case, since current object position is not next to the
- // next step in the path...
- long relDir = cellDirToCell(cellPos[0],
- cellPos[1],
- path1->stepList[curPath1Step].cell[0],
- path1->stepList[curPath1Step].cell[1]);
- startWithCurStep = (relDir == -2);
- // if (relDir == -2)
- // OutputDebugString("***jumped cell***\n");
- }
- if (startWithCurStep) {
- //---------------------
- // step 0 = curStep
- // step 1 = curStep + 1
- // step 2 = curStep + 2
- // step 3 = curStep + 3
- stepPos[0][0] = path1->stepList[curPath1Step].cell[0];
- stepPos[0][1] = path1->stepList[curPath1Step].cell[1];
- curPath1Step++;
- numSteps = MOVECHUNK_NUM_STEPS;
- long numStepsLeft = path1->numSteps - curPath1Step;
- if (numStepsLeft < MOVECHUNK_NUM_STEPS) {
- numSteps = numStepsLeft;
- reachedEndOfPath1 = true;
- }
- for (long i = 0; i < numSteps; i++) {
- stepPos[curStep][0] = path1->stepList[curPath1Step].cell[0];
- stepPos[curStep][1] = path1->stepList[curPath1Step].cell[1];
- if (curStep == 1)
- stepRelPos[curStep - 1] = cellDirToCell(stepPos[0][0],
- stepPos[0][1],
- stepPos[1][0],
- stepPos[1][1]);
- else
- stepRelPos[curStep - 1] = path1->stepList[curPath1Step].direction;
- curPath1Step++;
- curStep++;
- }
- //-----------------------------------------------------
- // Since we count the cur position as the first step...
- numSteps++;
-
- }
- else {
- //---------------------
- // step 0 = curPosition
- // step 1 = curStep
- // step 2 = curStep + 1
- // step 3 = curStep + 2
- numSteps = MOVECHUNK_NUM_STEPS;
- long numStepsLeft = path1->numSteps - curPath1Step;
- if (numStepsLeft < MOVECHUNK_NUM_STEPS) {
- numSteps = numStepsLeft;
- reachedEndOfPath1 = true;
- }
- for (long i = 0; i < numSteps; i++) {
- stepPos[curStep][0] = path1->stepList[curPath1Step].cell[0];
- stepPos[curStep][1] = path1->stepList[curPath1Step].cell[1];
- if (curStep == 1)
- stepRelPos[curStep - 1] = cellDirToCell(stepPos[0][0],
- stepPos[0][1],
- stepPos[1][0],
- stepPos[1][1]);
- else
- stepRelPos[curStep - 1] = path1->stepList[curPath1Step].direction;
- curPath1Step++;
- curStep++;
- }
- //-----------------------------------------------------
- // Since we count the cur position as the first step...
- numSteps++;
- }
- }
- bool path2Continues = path2 && (path1->globalStep > -1) && (path2->globalStep == (path1->globalStep + 1));
- if (reachedEndOfPath1 && path2Continues && (path2->numStepsWhenNotPaused > 0)) {
- //--------------------------------------------------------------
- // Splice second (queued) path into the chunk.
- // One assumption: if the first path is empty, it is assumed the
- // second path is irrelevant...
- // Assert(curStep > 1, curStep, " MoveChunk.build: path2 and curStep == 1 ");
- if (numSteps < (MOVECHUNK_NUM_STEPS + 1)) {
- //-----------------------------------------------------
- // Let's fill up the remaining steps in this chunk with
- // steps from the second path...
- long numAdditionalSteps = (MOVECHUNK_NUM_STEPS + 1) - numSteps;
- if (path2->numSteps < numAdditionalSteps)
- numAdditionalSteps = path2->numSteps;
- for (long i = 0; i < numAdditionalSteps; i++) {
- Assert(curStep <= MOVECHUNK_NUM_STEPS, curStep, " MoveChunk.build: path2 and bad curStep > MOVECHUNK_NUM_STEPS ");
- stepPos[curStep][0] = path2->stepList[i].cell[0];
- stepPos[curStep][1] = path2->stepList[i].cell[1];
- if (curStep == 1)
- stepRelPos[curStep - 1] = cellDirToCell(stepPos[0][0],
- stepPos[0][1],
- stepPos[1][0],
- stepPos[1][1]);
- else
- stepRelPos[curStep - 1] = path2->stepList[i].direction;
- curStep++;
- }
- numSteps += numAdditionalSteps;
- Assert(numSteps <= (MOVECHUNK_NUM_STEPS + 1), curStep, " MoveChunk.build: path2 and bad curStep > MOVECHUNK_NUM_STEPS ");
- }
- }
-
- }
- if ((numSteps < 1) || (numSteps > 4)) {
- //-----------------------------------------------------------------
- // For now, a safety guard. However, it would be nice to catch this
- // sooner and avoid this HACK. EXPANSION DISK!
- stepPos[0][0] = cellPos[0];
- stepPos[0][1] = cellPos[1];
- stepRelPos[0] = 0;
- stepRelPos[1] = 0;
- stepRelPos[2] = 0;
- numSteps = 1;
- }
- run = mover->getPilot()->getMoveRun();
- if (run && (mover->getObjectClass() == BATTLEMECH))
- run = ((BattleMechPtr)mover)->canRun();
- data = 0;
- }
- //---------------------------------------------------------------------------
- // DON'T USE THIS NOW, AS JUMPGOAL IS STORED IN THE STATUS CHUNK IF IT'S
- // A JUMP ORDER!
- void MoveChunk::build (MoverPtr mover, Stuff::Vector3D jumpGoal) {
- long jumpCoords[2];
- land->worldToCell(jumpGoal, jumpCoords[0], jumpCoords[1]);
- stepPos[0][0] = jumpCoords[0];
- stepPos[0][1] = jumpCoords[1];
- stepRelPos[0] = 0;
- stepRelPos[1] = 0;
- stepRelPos[2] = 0;
- numSteps = 1;
- run = false;
- moving = false;
- }
- //---------------------------------------------------------------------------
- #define DEBUG_MOVECHUNK
- void MoveChunk::pack (MoverPtr mover) {
- data = stepPos[0][0];
- data <<= MOVECHUNK_CELLPOS_BITS;
- data |= stepPos[0][1];
- data <<= MOVECHUNK_NUMSTEPS_BITS;
- data |= (numSteps - 1);
- data <<= MOVECHUNK_RUN_BITS;
- if (run)
- data |= 1;
- data <<= MOVECHUNK_MOVING_BITS;
-
- if (moving)
- data |= 1;
- data <<= MOVECHUNK_STEP_BITS;
- data |= stepRelPos[0];
- data <<= MOVECHUNK_STEP_BITS;
- data |= stepRelPos[1];
- data <<= MOVECHUNK_STEP_BITS;
- data |= stepRelPos[2];
- #ifdef DEBUG_MOVECHUNK
- //-------------------------
- // Lots'a error checking...
- if ((numSteps < 1) || (numSteps > 4)) {
- DebugMoveChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " MoveChunk.pack: bad numSteps %d (save mvchunk.dbg file) ", numSteps);
- Assert(false, numSteps, errMsg);
- }
- #endif
- }
- //---------------------------------------------------------------------------
-
- void MoveChunk::unpack (MoverPtr mover) {
- err = 0;
- stepRelPos[2] = (data & MOVECHUNK_STEP_MASK);
- data >>= MOVECHUNK_STEP_BITS;
- stepRelPos[1] = (data & MOVECHUNK_STEP_MASK);
- data >>= MOVECHUNK_STEP_BITS;
- stepRelPos[0] = (data & MOVECHUNK_STEP_MASK);
- data >>= MOVECHUNK_STEP_BITS;
- moving = ((data & MOVECHUNK_MOVING_MASK) != 0);
- data >>= MOVECHUNK_MOVING_BITS;
- run = ((data & MOVECHUNK_RUN_MASK) != 0);
- data >>= MOVECHUNK_RUN_BITS;
- numSteps = (data & MOVECHUNK_NUMSTEPS_MASK) + 1;
- data >>= MOVECHUNK_NUMSTEPS_BITS;
- stepPos[0][1] = (data & MOVECHUNK_CELLPOS_MASK);
- data >>= MOVECHUNK_CELLPOS_BITS;
- stepPos[0][0] = (data & MOVECHUNK_CELLPOS_MASK);
- //---------------------------------------------------------------
- // Finally, set the delta steps based upon the first step and the
- // relPos list...
- if ((numSteps < 1) || (numSteps > 4)) {
- //--------------------------------------------------------------------
- // HACK!!!!!!!!!! All of this unpackerr stuff is a last minute hack...
- err = 1;
- return;
- }
- if (numSteps > 1) {
- for (long i = 0; i < (numSteps - 1); i++) {
- long nextStep = i + 1;
- if ((i < 0) || (i > 2)) {
- err = 2;
- return;
- }
- if ((stepRelPos[i] < 0) || (stepRelPos[i] > 7)) {
- err = 3;
- return;
- }
- getAdjCell(stepPos[i][0],
- stepPos[i][1],
- stepRelPos[i],
- stepPos[nextStep][0],
- stepPos[nextStep][1]);
- }
- }
- #ifdef DEBUG_MOVECHUNK
- //-------------------------
- // Lots'a error checking...
- if ((numSteps < 1) || (numSteps > 4)) {
- DebugMoveChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " MoveChunk.unpack: bad numSteps %d (save mvchunk.dbg file) ", numSteps);
- Assert(false, numSteps, errMsg);
- }
- #endif
- }
- //---------------------------------------------------------------------------
- bool MoveChunk::equalTo (MoverPtr mover, MoveChunkPtr chunk) {
- if (numSteps != chunk->numSteps) {
- DebugMoveChunk(mover, this, chunk);
- return(false);
- }
- if (run != chunk->run) {
- DebugMoveChunk(mover, this, chunk);
- return(false);
- }
- if (moving != chunk->moving) {
- DebugMoveChunk(mover, this, chunk);
- return(false);
- }
- for (long i = 0; i < numSteps; i++)
- if ((stepPos[i][0] != chunk->stepPos[i][0]) || (stepPos[i][1] != chunk->stepPos[i][1])) {
- DebugMoveChunk(mover, this, chunk);
- return(false);
- }
- for (i = 0; i < numSteps - 1; i++) {
- if (stepRelPos[i] != chunk->stepRelPos[i]) {
- DebugMoveChunk(mover, this, chunk);
- return(false);
- }
- }
- return(true);
- }
- //---------------------------------------------------------------------------
- void Mover::setMoveChunk (MovePathPtr path, MoveChunkPtr chunk) {
- for (long i = 0; i < chunk->numSteps; i++) {
- PathStepPtr pathStep = &path->stepList[i];
- pathStep->cell[0] = chunk->stepPos[i][0];
- pathStep->cell[1] = chunk->stepPos[i][1];
- pathStep->distanceToGoal = 0.0;
- land->cellToWorld(pathStep->cell[0], pathStep->cell[1], pathStep->destination);
- }
- path->goal = path->stepList[chunk->numSteps - 1].destination;
- path->target.Zero();
- path->numSteps = path->numStepsWhenNotPaused = chunk->numSteps;
- path->curStep = 0;
- path->cost = -1;
- path->marked = false;
- path->globalStep = -1;
- }
- //***************************************************************************
- // Status Chunk class
- //***************************************************************************
- void DebugStatusChunk (MoverPtr mover, StatusChunkPtr chunk1, StatusChunkPtr chunk2) {
- ChunkDebugMsg[0] = NULL;
- char outString[512];
- if (mover) {
- sprintf(outString, "\nmover = %s (%d)\n", mover->name, mover->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- else
- strcat(ChunkDebugMsg, "\nmover = ???\n");
- if (chunk1) {
- strcat(ChunkDebugMsg, "\nCHUNK1\n");
- GameObjectPtr target = NULL;
- Stuff::Vector3D targetPoint;
- targetPoint.Zero();
- bool isTargetPoint = false;
- if (chunk1->targetType == STATUSCHUNK_TARGET_MOVER)
- target = (GameObjectPtr)MPlayer->moverRoster[chunk1->targetId];
- else if (chunk1->targetType == STATUSCHUNK_TARGET_TERRAIN)
- target = ObjectManager->findByPartId(chunk1->targetId);
- else if (chunk1->targetType == STATUSCHUNK_TARGET_SPECIAL)
- target = ObjectManager->findByPartId(chunk1->targetId);
- else if (chunk1->targetType == STATUSCHUNK_TARGET_LOCATION) {
- targetPoint.x = (float)chunk1->targetCellRC[1] * Terrain::worldUnitsPerCell + Terrain::worldUnitsPerCell / 2 - Terrain::worldUnitsMapSide / 2;
- targetPoint.y = (Terrain::worldUnitsMapSide / 2) - ((float)chunk1->targetCellRC[0] * Terrain::worldUnitsPerCell) - Terrain::worldUnitsPerCell / 2;
- targetPoint.z = (float)land->getTerrainElevation(targetPoint);
- isTargetPoint = true;
- }
- if (target) {
- if (target->isMover()) {
- sprintf(outString, "target = %s (%d)\n", ((MoverPtr)target)->name, target->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- else {
- sprintf(outString, "target = objClass %d (%d)\n", target->getObjectClass(), target->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- }
- else if (isTargetPoint) {
- sprintf(outString, "target point = (%f, %f, %f)\n", targetPoint.x, targetPoint.y, targetPoint.z);
- strcat(ChunkDebugMsg, outString);
- }
- else if (chunk1->targetType == STATUSCHUNK_TARGET_NONE) {
- sprintf(outString, "target = NONE\n");
- strcat(ChunkDebugMsg, outString);
- }
- else {
- strcat(ChunkDebugMsg, "target = ???\n");
- if (chunk1->targetType == STATUSCHUNK_TARGET_TERRAIN) {
- //---------------------------------------------------------------------
- // If the TargetType is terrain, let's at least list all of the terrain
- // objects in this Block/Vertex...
- long numObjsInTile = 0;
- long partId = chunk1->targetId - chunk1->targetItemNumber;
- for (long i = 0; i < MAX_TERRAIN_TILE_ITEMS; i++) {
- GameObjectPtr curTarget = ObjectManager->findByPartId(partId + i);
- if (curTarget) {
- numObjsInTile++;
- sprintf(outString, " %d: objClass %d (%d)\n", i, curTarget->getObjectClass(), curTarget->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- }
- if (numObjsInTile > 0) {
- sprintf(outString, " There are %d terrain objects in this tile.\n", numObjsInTile);
- strcat(ChunkDebugMsg, outString);
- }
- }
- }
- sprintf(outString, "bodyState = %d\n", chunk1->bodyState);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetType = %d\n", chunk1->targetType);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "targetId = %d\n", chunk1->targetId);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetBlockOrTrainNumber = %d\n", chunk1->targetBlockOrTrainNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetVertexOrCarNumber = %d\n", chunk1->targetVertexOrCarNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetItemNumber = %d\n", chunk1->targetItemNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetCellRC = (%d, %d)\n", chunk1->targetCellRC[0], chunk1->targetCellRC[1]);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "ejectOrderGiven = %c\n", chunk1->ejectOrderGiven ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "jumpOrder = %c\n", chunk1->jumpOrder ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "data = %x\n", chunk1->data);
- strcat(ChunkDebugMsg, outString);
- }
- if (chunk2) {
- strcat(ChunkDebugMsg, "\nCHUNK2\n");
- GameObjectPtr target = NULL;
- Stuff::Vector3D targetPoint;
- targetPoint.Zero();
- bool isTargetPoint = false;
- if (chunk1->targetType == STATUSCHUNK_TARGET_MOVER)
- target = (GameObjectPtr)MPlayer->moverRoster[chunk2->targetId];
- else if (chunk1->targetType == STATUSCHUNK_TARGET_TERRAIN)
- target = ObjectManager->findByPartId(chunk2->targetId);
- else if (chunk1->targetType == STATUSCHUNK_TARGET_SPECIAL)
- target = ObjectManager->findByPartId(chunk2->targetId);
- else if (chunk1->targetType == STATUSCHUNK_TARGET_LOCATION) {
- targetPoint.x = (float)chunk2->targetCellRC[1] * Terrain::worldUnitsPerCell + Terrain::worldUnitsPerCell / 2 - Terrain::worldUnitsMapSide / 2;
- targetPoint.y = (Terrain::worldUnitsMapSide / 2) - ((float)chunk2->targetCellRC[0] * Terrain::worldUnitsPerCell) - Terrain::worldUnitsPerCell / 2;
- targetPoint.z = (float)land->getTerrainElevation(targetPoint);
- isTargetPoint = true;
- }
- if (target) {
- if (target->isMover()) {
- sprintf(outString, "target = %s (%d)\n", ((MoverPtr)target)->name, target->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- else {
- sprintf(outString, "target = objClass %d (%d)\n", target->getObjectClass(), target->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- }
- else if (isTargetPoint) {
- sprintf(outString, "target point = (%f, %f, %f)\n", targetPoint.x, targetPoint.y, targetPoint.z);
- strcat(ChunkDebugMsg, outString);
- }
- else if (chunk1->targetType == STATUSCHUNK_TARGET_NONE) {
- sprintf(outString, "target = NONE\n");
- strcat(ChunkDebugMsg, outString);
- }
- else {
- strcat(ChunkDebugMsg, "target = ???\n");
- if (chunk2->targetType == STATUSCHUNK_TARGET_TERRAIN) {
- //---------------------------------------------------------------------
- // If the TargetType is terrain, let's at least list all of the terrain
- // objects in this Block/Vertex...
- long numObjsInTile = 0;
- long partId = chunk1->targetId - chunk2->targetItemNumber;
- for (long i = 0; i < MAX_TERRAIN_TILE_ITEMS; i++) {
- GameObjectPtr curTarget = ObjectManager->findByPartId(partId + i);
- if (curTarget) {
- numObjsInTile++;
- sprintf(outString, " %d: objClass %d (%d)\n", i, curTarget->getObjectClass(), curTarget->getPartId());
- strcat(ChunkDebugMsg, outString);
- }
- }
- if (numObjsInTile > 0) {
- sprintf(outString, " There are %d terrain objects in this tile.\n", numObjsInTile);
- strcat(ChunkDebugMsg, outString);
- }
- }
- }
- sprintf(outString, "bodyState = %d\n", chunk2->bodyState);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetType = %d\n", chunk2->targetType);
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "targetId = %d\n", chunk2->targetId);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetBlockOrTrainNumber = %d\n", chunk2->targetBlockOrTrainNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetVertexOrCarNumber = %d\n", chunk2->targetVertexOrCarNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetItemNumber = %d\n", chunk2->targetItemNumber);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "targetCellRC = (%d, %d)\n", chunk2->targetCellRC[0], chunk2->targetCellRC[1]);
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "ejectOrderGiven = %c\n", chunk2->ejectOrderGiven ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
-
- sprintf(outString, "jumpOrder = %c\n", chunk2->jumpOrder ? 'T' : 'F');
- strcat(ChunkDebugMsg, outString);
- sprintf(outString, "data = %x\n", chunk2->data);
- strcat(ChunkDebugMsg, outString);
- }
- File* debugFile = new File;
- debugFile->create("stchunk.dbg");
- debugFile->writeString(ChunkDebugMsg);
- debugFile->close();
- delete debugFile;
- debugFile = NULL;
- ExceptionGameMsg = ChunkDebugMsg;
- }
- //---------------------------------------------------------------------------
- void* StatusChunk::operator new (size_t ourSize) {
- void* result;
- result = systemHeap->Malloc(ourSize);
- return(result);
- }
- //---------------------------------------------------------------------------
- void StatusChunk::operator delete (void* us) {
- systemHeap->Free(us);
- }
- //---------------------------------------------------------------------------
- void StatusChunk::build (MoverPtr mover) {
- bodyState = 0;
- data = 0;
- }
- //---------------------------------------------------------------------------
- #define DEBUG_STATUSCHUNK
- //#define ASSERT_STATUSCHUNK
- void StatusChunk::pack (MoverPtr mover) {
- data = 0;
- if (jumpOrder) {
- data |= targetCellRC[0];
- data <<= STATUSCHUNK_CELLPOS_BITS;
- data |= targetCellRC[1];
- data <<= STATUSCHUNK_TARGETTYPE_BITS;
- }
- else {
- switch (targetType) {
- case STATUSCHUNK_TARGET_MOVER:
- //----------------
- // Mover Target...
- data |= targetId;
- data <<= STATUSCHUNK_TARGETTYPE_BITS;
- break;
- case STATUSCHUNK_TARGET_TERRAIN:
- //-------------------------
- // Terrain Object Target...
- data |= (targetId - MIN_TERRAIN_PART_ID);
- data <<= STATUSCHUNK_TARGETTYPE_BITS;
- break;
- case STATUSCHUNK_TARGET_SPECIAL:
- data |= targetBlockOrTrainNumber;
- data <<= STATUSCHUNK_TRAINCAR_BITS;
- data |= targetVertexOrCarNumber;
- data <<= STATUSCHUNK_TARGETTYPE_BITS;
- break;
- case STATUSCHUNK_TARGET_LOCATION:
- //-----------------------------------------
- // Must be a Location Target (or a Miss)...
- data |= targetCellRC[0];
- data <<= STATUSCHUNK_CELLPOS_BITS;
- data |= targetCellRC[1];
- data <<= STATUSCHUNK_TARGETTYPE_BITS;
- break;
- }
- }
- data |= targetType;
- data <<= STATUSCHUNK_EJECTORDER_BITS;
- if (ejectOrderGiven)
- data |= 1;
- data <<= STATUSCHUNK_JUMPORDER_BITS;
- if (jumpOrder)
- data |= 1;
- data <<= STATUSCHUNK_BODYSTATE_BITS;
- data |= bodyState;
- #ifdef DEBUG_STATUSCHUNK
- //-------------------------
- // Lots'a error checking...
- switch (targetType) {
- case STATUSCHUNK_TARGET_NONE:
- break;
- case STATUSCHUNK_TARGET_MOVER: {
- if ((targetId < 0) || (targetId >= MAX_MULTIPLAYER_MOVERS)) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.pack: bad targetId %d (save stchunk.dbg file) ", targetId);
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 1;
- #endif
- }
- GameObjectPtr target = (GameObjectPtr)MPlayer->moverRoster[targetId];
- //----------------------------------------------------------------------------
- // Mover targets could be NULL now, since we free them when they're destroyed.
- //if (!target) {
- // #ifdef ASSERT_STATUSCHUNK
- // DebugStatusChunk(mover, this, NULL);
- // char errMsg[1024];
- // sprintf(errMsg, " StatusChunk.pack: NULL Mover Target (save stchunk.dbg file) ");
- // Assert(false, targetId, errMsg);
- // #else
- // StatusChunkUnpackErr = 2;
- // #endif
- //}
- }
- break;
- case STATUSCHUNK_TARGET_TERRAIN: {
- GameObjectPtr target = ObjectManager->findByPartId(targetId);
- if (!target) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.pack: NULL Terrain Target (save stchunk.dbg file) ");
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 3;
- #endif
- }
- }
- break;
- case STATUSCHUNK_TARGET_SPECIAL: {
- GameObjectPtr target = ObjectManager->findByPartId(targetId);
- if (!target) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.pack: NULL Special Target (save stchunk.dbg file) ");
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 4;
- #endif
- }
- }
- break;
- case STATUSCHUNK_TARGET_LOCATION:
- break;
- default:
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.pack: bad targetType %d (save stchunk.dbg file) ", targetType);
- Assert(false, targetType, errMsg);
- #else
- StatusChunkUnpackErr = 5;
- #endif
- }
- #endif
- }
- //---------------------------------------------------------------------------
- void StatusChunk::unpack (MoverPtr mover) {
- StatusChunkUnpackErr = 0;
- unsigned long tempData = data;
- bodyState = (tempData & STATUSCHUNK_BODYSTATE_MASK);
- tempData >>= STATUSCHUNK_BODYSTATE_BITS;
- jumpOrder = ((tempData & STATUSCHUNK_JUMPORDER_MASK) != 0);
- tempData >>= STATUSCHUNK_JUMPORDER_BITS;
- // if (jumpOrder)
- // OutputDebugString("JUMP ORDER\n");
- ejectOrderGiven = ((tempData & STATUSCHUNK_EJECTORDER_MASK) != 0);
- tempData >>= STATUSCHUNK_EJECTORDER_BITS;
- targetType = (tempData & STATUSCHUNK_TARGETTYPE_MASK);
- tempData >>= STATUSCHUNK_TARGETTYPE_BITS;
- if (jumpOrder) {
- targetCellRC[1] = (tempData & STATUSCHUNK_CELLPOS_MASK);
- tempData >>= STATUSCHUNK_CELLPOS_BITS;
-
- targetCellRC[0] = (tempData & STATUSCHUNK_CELLPOS_MASK);
- }
- else {
- switch (targetType) {
- case STATUSCHUNK_TARGET_NONE:
- break;
- case STATUSCHUNK_TARGET_MOVER:
- //----------------
- // Mover Target...
- targetId = (tempData & STATUSCHUNK_MOVERINDEX_MASK);
- break;
- case STATUSCHUNK_TARGET_TERRAIN:
- //-------------------------
- // Terrain Object Target...
- targetId = (tempData & STATUSCHUNK_TERRAINPARTID_MASK) + MIN_TERRAIN_PART_ID;
- break;
- case STATUSCHUNK_TARGET_SPECIAL:
- //-----------------------
- // Train Object Target...
- targetVertexOrCarNumber = (tempData & STATUSCHUNK_TRAIN_MASK);
- tempData >>= STATUSCHUNK_TRAIN_BITS;
- targetBlockOrTrainNumber = (tempData & STATUSCHUNK_TRAINCAR_MASK);
- tempData >>= STATUSCHUNK_TRAINCAR_BITS;
- if (targetBlockOrTrainNumber == 128)
- targetId = MIN_CAMERA_DRONE_ID + targetVertexOrCarNumber;
- else
- targetId = MIN_TRAIN_PART_ID +
- targetBlockOrTrainNumber * MAX_TRAIN_CARS +
- targetVertexOrCarNumber;
- break;
- case STATUSCHUNK_TARGET_LOCATION:
- //-----------------------------------------
- // Must be a Location Target (or a Miss)...
- targetCellRC[1] = (tempData & STATUSCHUNK_CELLPOS_MASK);
- tempData >>= STATUSCHUNK_CELLPOS_BITS;
-
- targetCellRC[0] = (tempData & STATUSCHUNK_CELLPOS_MASK);
- break;
- }
- }
- #ifdef DEBUG_STATUSCHUNK
- //-------------------------
- // Lots'a error checking...
- switch (targetType) {
- case STATUSCHUNK_TARGET_NONE:
- break;
- case STATUSCHUNK_TARGET_MOVER: {
- if ((targetId < 0) || (targetId >= MAX_MULTIPLAYER_MOVERS)) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.unpack: bad targetId %d (save stchunk.dbg file) ", targetId);
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 1;
- #endif
- }
- GameObjectPtr target = (GameObjectPtr)MPlayer->moverRoster[targetId];
- //----------------------------------------------------------------------------
- // Mover targets could be NULL now, since we free them when they're destroyed.
- //if (!target) {
- // #ifdef ASSERT_STATUSCHUNK
- // DebugStatusChunk(mover, this, NULL);
- // char errMsg[1024];
- // sprintf(errMsg, " StatusChunk.unpack: NULL Mover Target (save stchunk.dbg file) ");
- // Assert(false, targetId, errMsg);
- // #else
- // StatusChunkUnpackErr = 2;
- // #endif
- //}
- }
- break;
- case STATUSCHUNK_TARGET_TERRAIN: {
- GameObjectPtr target = ObjectManager->findByPartId(targetId);
- if (!target) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.unpack: NULL Terrain Target (save stchunk.dbg file) ");
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 3;
- #endif
- }
- }
- break;
- case STATUSCHUNK_TARGET_SPECIAL: {
- GameObjectPtr target = ObjectManager->findByPartId(targetId);
- if (!target) {
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.unpack: NULL Special Target (save stchunk.dbg file) ");
- Assert(false, targetId, errMsg);
- #else
- StatusChunkUnpackErr = 4;
- #endif
- }
- }
- break;
- case STATUSCHUNK_TARGET_LOCATION:
- break;
- default:
- #ifdef ASSERT_STATUSCHUNK
- DebugStatusChunk(mover, this, NULL);
- char errMsg[1024];
- sprintf(errMsg, " StatusChunk.unpack: bad targetType %d (save stchunk.dbg file) ", targetType);
- Assert(false, targetType, errMsg);
- #else
- StatusChunkUnpackErr = 5;
- #endif
- }
- #endif
- }
- //---------------------------------------------------------------------------
- bool StatusChunk::equalTo (StatusChunkPtr chunk) {
- if (bodyState != chunk->bodyState) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (ejectOrderGiven != chunk->ejectOrderGiven) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (jumpOrder != chunk->jumpOrder) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (targetType != chunk->targetType) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (targetId != chunk->targetId) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (targetCellRC[0] != chunk->targetCellRC[0]) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- if (targetCellRC[1] != chunk->targetCellRC[1]) {
- DebugStatusChunk(NULL, this, chunk);
- return(false);
- }
- return(true);
- }
- //***************************************************************************
- // MOVER DYNAMICS class
- //***************************************************************************
- void MoverDynamics::init (void) {
- type = DYNAMICS_BASE;
- }
- //---------------------------------------------------------------------------
- void MoverDynamics::init (DynamicsType newType) {
- type = newType;
- switch (newType) {
- case DYNAMICS_MECH:
- max.mech.torsoYawRate = 0;
- max.mech.torsoYaw = 0;
- break;
- case DYNAMICS_GROUNDVEHICLE:
- max.groundVehicle.yawRate = 0;
- //cur.groundVehicle.yaw = 0.0;
- break;
- case DYNAMICS_ELEMENTAL:
- max.elemental.yawRate = 0;
- //cur.elemental.yaw = 0.0;
- break;
- default:
- Fatal(newType, " ugh ");
- }
- }
- //---------------------------------------------------------------------------
- void MoverDynamics::init (CSVFilePtr dynamicsFile) {
- if (type == DYNAMICS_MECH)
- {
- //Its a new day!!!
-
- dynamicsFile->readLong(8,5,max.mech.torsoYawRate);
- dynamicsFile->readLong(9,5,max.mech.torsoYaw);
- }
- else if (type == DYNAMICS_GROUNDVEHICLE) {
- /*
- long result = 0;
- result = dynamicsFile->seekBlock("VehicleDynamics");
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 0 ");
- result = dynamicsFile->readIdLong("maxTurretYawRate",max.groundVehicle.turretYawRate);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 1 ");
-
- result = dynamicsFile->readIdLong("maxTurretYaw",max.groundVehicle.turretYaw);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 2 ");
-
- result = dynamicsFile->readIdLong("maxVehicleYawRate",max.groundVehicle.yawRate);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 3 ");
- if (max.groundVehicle.yawRate < 720)
- max.groundVehicle.yawRate = 720;
- result = dynamicsFile->readIdLong("maxVehiclePivotRate",max.groundVehicle.pivotRate);
- if (result != NO_ERR)
- max.groundVehicle.pivotRate = (long)((float)max.groundVehicle.yawRate * GroundVehiclePivotYawMultiplier);
- result = dynamicsFile->readIdFloat("maxAccel",max.groundVehicle.accel);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 4 ");
-
- result = dynamicsFile->readIdFloat("maxVelocity",max.groundVehicle.speed);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 5 ");
- // Frank Hack
- max.groundVehicle.accel = max.groundVehicle.speed * 5.0;
- */
- }
- else if (type == DYNAMICS_ELEMENTAL) {
- Fatal(type, " MoverDynamics.init: bad elemental ");
- }
- else
- Fatal(type, " MoverDynamics.init: bad type ");
- }
- //---------------------------------------------------------------------------
- void MoverDynamics::init (FitIniFilePtr dynamicsFile)
- {
- if (type == DYNAMICS_MECH)
- {
- }
- else if (type == DYNAMICS_GROUNDVEHICLE) {
- long result = 0;
- result = dynamicsFile->seekBlock("VehicleDynamics");
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 0 ");
- result = dynamicsFile->readIdLong("maxTurretYawRate",max.groundVehicle.turretYawRate);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 1 ");
-
- result = dynamicsFile->readIdLong("maxTurretYaw",max.groundVehicle.turretYaw);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 2 ");
-
- result = dynamicsFile->readIdLong("maxVehicleYawRate",max.groundVehicle.yawRate);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 3 ");
- if (max.groundVehicle.yawRate < 720)
- max.groundVehicle.yawRate = 720;
- result = dynamicsFile->readIdLong("maxVehiclePivotRate",max.groundVehicle.pivotRate);
- if (result != NO_ERR)
- max.groundVehicle.pivotRate = (long)((float)max.groundVehicle.yawRate * GroundVehiclePivotYawMultiplier);
- result = dynamicsFile->readIdFloat("maxAccel",max.groundVehicle.accel);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 4 ");
-
- result = dynamicsFile->readIdFloat("maxVelocity",max.groundVehicle.speed);
- Assert(result == NO_ERR, result, " MoverDynamics.init: vehicle error 5 ");
- // Frank Hack
- max.groundVehicle.accel = max.groundVehicle.speed * 5.0;
- }
- else if (type == DYNAMICS_ELEMENTAL) {
- Fatal(type, " MoverDynamics.init: bad elemental ");
- }
- else
- Fatal(type, " MoverDynamics.init: bad type ");
- }
- //***************************************************************************
- // MOVER CONTROL class
- //***************************************************************************
- void MoverControl::reset (void) {
- switch (dataType) {
- case CONTROL_DATA_BASE:
- break;
- case CONTROL_DATA_MECH:
- //settings.mech.throttle = 100;
- settings.mech.rotate = 0.0;
- settings.mech.facingRotate = 0.0f;
- settings.mech.rotateTorso = 0;
- settings.mech.rotateLeftArm = 0;
- settings.mech.rotateRightArm = 0;
- settings.mech.gestureGoal = -1;
- settings.mech.blowLeftArm = false;
- settings.mech.blowRightArm = false;
- settings.mech.pivot = false;
- break;
- case CONTROL_DATA_GROUNDVEHICLE:
- settings.groundVehicle.rotate = 0.0;
- settings.groundVehicle.rotateTurret = 0.0;
- settings.groundVehicle.gestureGoal = -1;
- settings.groundVehicle.pivot = false;
- settings.groundVehicle.isWalking = false;
- settings.groundVehicle.throttle = 0.0;
- break;
- case CONTROL_DATA_ELEMENTAL:
- break;
- }
- }
- //---------------------------------------------------------------------------
- void MoverControl::brake (void) {
- switch (dataType) {
- case CONTROL_DATA_BASE:
- break;
- case CONTROL_DATA_MECH:
- settings.mech.throttle = 100;
- settings.mech.gestureGoal = MECH_STATE_STANDING;
- break;
- case CONTROL_DATA_GROUNDVEHICLE:
- settings.mech.throttle = 0;
- break;
- case CONTROL_DATA_ELEMENTAL:
- break;
- }
- }
- //---------------------------------------------------------------------------
- void MoverControl::update (MoverPtr mover) {
- switch (type) {
- case CONTROL_AI:
- mover->updateAIControl();
- break;
- case CONTROL_NET:
- mover->updateNetworkControl();
- break;
- case CONTROL_PLAYER:
- mover->updatePlayerControl();
- break;
- default:
- Fatal(type, " MoverControl.update: bad control type ");
- }
- }
- //---------------------------------------------------------------------------
- long MoverControl::init (FitIniFilePtr controlFile) {
- return(NO_ERR);
- }
- //***************************************************************************
- // MOVER class
- //***************************************************************************
- long Mover::loadGameSystem (FitIniFilePtr mechFile, float visualRange) {
- long result = 0;
- result = mechFile->seekBlock("Pathfinding");
- if (result != NO_ERR)
- return(result);
- // long longRangeMoveEnabled[MAX_TEAMS];
- // result = mechFile->readIdLongArray("LongRangeMovementEnabled", longRangeMoveEnabled, NUM_TEAMS);
- // if (result != NO_ERR)
- // return(result);
- // for (long i = 0; i < NUM_TEAMS; i++)
- // LongRangeMovementEnabled[i] = (longRangeMoveEnabled[i] == 1);
- result = mechFile->readIdLong("SimplePathTileRange", SimpleMovePathRange);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("DelayedOrderTime", DelayedOrderTime);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("MoveTimeOut", MoveTimeOut);
- if (result != NO_ERR)
- MoveTimeOut = 30.0;
- result = mechFile->readIdFloat("MoveYieldTime", MoveYieldTime);
- if (result != NO_ERR)
- MoveYieldTime = 1.5;
- result = mechFile->readIdLongArray("GroupMoveTrailLength", GroupMoveTrailLen, 2);
- if (result != NO_ERR) {
- GroupMoveTrailLen[0] = 0;
- GroupMoveTrailLen[1] = 1;
- }
- result = mechFile->readIdLongArray("GroupMoveTrailLength", GroupMoveTrailLen, 2);
- if (result != NO_ERR) {
- GroupMoveTrailLen[0] = 0;
- GroupMoveTrailLen[1] = 1;
- }
- result = mechFile->readIdFloat("GroupOrderGoalOffset", GroupOrderGoalOffset);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloatArray("MoveMarginOfError", Mover::marginOfError, 2);
- if (result != NO_ERR)
- return(result);
- // for (long i = 0; i < NUM_OVERLAY_TYPES; i++)
- // OverlayWeightIndex[i] = i * MAPCELL_DIM * MAPCELL_DIM;
- // result = mechFile->readIdLongArray("OverlayCellCosts", OverlayWeightTable, NUM_OVERLAY_WEIGHT_CLASSES * NUM_OVERLAY_TYPES * MAPCELL_DIM * MAPCELL_DIM);
- // if (result != NO_ERR)
- // return(result);
- result = mechFile->seekBlock("Mover:General");
- Assert(result == NO_ERR, 0, "Couldn't find Mover:General block in gamesys.fit");
- result = mechFile->readIdFloat("NewThreatMultiplier", newThreatMultiplier);
- if (result != NO_ERR)
- newThreatMultiplier = 3.0;
- result = mechFile->readIdFloat("BlockCaptureRange", GameObject::blockCaptureRange);
- Assert(result == NO_ERR, 0, "Couldn't find BlockCaptureRange in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitTime", Mover::refitTime);
- Assert(result == NO_ERR, 0, "Couldn't find RefitTime in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitRange", Mover::refitRange);
- Assert(result == NO_ERR, 0, "Couldn't find RefitRange in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitAmount", Mover::refitAmount);
- Assert(result == NO_ERR, 0, "Couldn't find RefitAmount in Mover:General block in gamesys.fit");
- result = mechFile->readIdFloat("RefitVehicleArmorCost", Mover::refitCostArray[ARMOR_REFIT_COST][REFIT_VEHICLE]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitVehicleArmorCost in Mover:General block in gamesys.fit");
- result = mechFile->readIdFloat("RecoverTime", Mover::recoverTime);
- Assert(result == NO_ERR, 0, "Couldn't find RecoverTime in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RecoverRange", Mover::recoverRange);
- Assert(result == NO_ERR, 0, "Couldn't find RecoverRange in Mover:General block in gamesys.fit");
- result = mechFile->readIdFloat("RecoverAmount", Mover::recoverAmount);
- Assert(result == NO_ERR, 0, "Couldn't find RecoverAmount in Mover:General block in gamesys.fit");
- result = mechFile->readIdFloat("RecoverCost", Mover::recoverCost);
- Assert(result == NO_ERR, 0, "Couldn't find RecoverCost in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitVehicleInternalCost", Mover::refitCostArray[INTERNAL_REFIT_COST][REFIT_VEHICLE]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitVehicleInternalCost in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitVehiclePointsToAmmo", Mover::refitCostArray[AMMO_REFIT_COST][REFIT_VEHICLE]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitVehiclePointsToAmmo in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitBayArmorCost", Mover::refitCostArray[ARMOR_REFIT_COST][REFIT_BAY]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitBayArmorCost in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitBayInternalCost", Mover::refitCostArray[INTERNAL_REFIT_COST][REFIT_BAY]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitBayInternalCost in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdFloat("RefitBayAmmoCost", Mover::refitCostArray[AMMO_REFIT_COST][REFIT_BAY]);
- Assert(result == NO_ERR, 0, "Couldn't find RefitBayAmmoCost in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdLongArray("IndirectFireWeaponComponentIndex",Mover::IndirectFireWeapons,20);
- Assert(result == NO_ERR, 0, "Couldn't find IndirectFireWeaponComponentIndex in Mover:General block in gamesys.fit");
-
- result = mechFile->readIdLongArray("AreaEffectWeaponComponentIndex",Mover::AreaEffectWeapons,20);
- Assert(result == NO_ERR, 0, "Couldn't find AreaEffectWeaponComponentIndex in Mover:General block in gamesys.fit");
-
- result = mechFile->seekBlock("Mover:FireWeapon");
- if (result != NO_ERR)
- return(result);
- // result = mechFile->readIdFloatArray("WeaponFireModifiers", WeaponFireModifiers, NUM_WEAPONFIRE_MODIFIERS);
- // if (result == NO_ERR) {
- // for (long i = 0; i < NUM_WARRIOR_RANKS; i++)
- // for (long j = 0; j < (NUM_MECH_CLASSES - 1); j++)
- // RankVersusChassisCombatModifier[i][j + 1] = WeaponFireModifiers[7 + i * NUM_WARRIOR_RANKS + j];
- // }
- result = mechFile->readIdFloatArray("FireArc", FireArc, 3);
- if (result != NO_ERR)
- return(result);
- for (long arc = 0; arc < 3; arc++)
- FireArc[arc] /= 2.0;
- result = mechFile->readIdLong("AimedFireAbort", AimedFireAbort);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdLongArray("AimedFireHitTable", AimedFireHitTable, 3);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("DisableAttackModifier", DisableAttackModifier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("DisableGunneryModifier", DisableGunneryModifier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("SalvageAttackModifier", SalvageAttackModifier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("MaxStationaryTime", MaxStationaryTime);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("MaxTimeRevealed",MaxTimeRevealed);
- if (result != NO_ERR)
- return(result);
-
- result = mechFile->readIdFloat("HeadShotModifier",HeadShotModifier);
- if (result != NO_ERR)
- HeadShotModifier = 0.08f;
-
- result = mechFile->readIdFloat("ArmShotModifier",ArmShotModifier);
- if (result != NO_ERR)
- ArmShotModifier = 0.15f;
-
- result = mechFile->readIdFloat("LegShotModifier",LegShotModifier);
- if (result != NO_ERR)
- LegShotModifier = 0.20f;
-
- result = mechFile->seekBlock("Mover:Damage");
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdLongArray("HitLevel", hitLevel, 2);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("PilotingCheckFactor", PilotingCheckFactor);
- if (result != NO_ERR)
- return(result);
- result = mechFile->seekBlock("Components");
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdLong("ClusterSizeSRM", ClusterSizeSRM);
- if (result != NO_ERR)
- return(result);
- // Hard code--ultimately, we kill clusters in game code!
- ClusterSizeSRM = 2;
- result = mechFile->readIdLong("ClusterSizeLRM", ClusterSizeLRM);
- if (result != NO_ERR)
- return(result);
- // Hard code--ultimately, we kill clusters in game code!
- ClusterSizeLRM = 5;
- result = mechFile->readIdLongArray("InnerSphereAntiMissile", AntiMissileSystemStats[0], 2);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdLongArray("ClanAntiMissile", AntiMissileSystemStats[1], 2);
- if (result != NO_ERR)
- return(result);
- result = mechFile->seekBlock("Warrior");
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("DefaultAttackRadius", DefaultAttackRadius);
- if (result != NO_ERR)
- DefaultAttackRadius = 275.0;
- result = mechFile->readIdFloatArray("WarriorRankScale", WarriorRankScale, NUM_WARRIOR_RANKS);
- if (result != NO_ERR)
- return(result);
- char profData[NUM_OFFSET_RANGES * 2];
- result = mechFile->readIdCharArray("ProfessionalismTable", profData, NUM_OFFSET_RANGES * 2);
- if (result != NO_ERR)
- return(result);
- for (long i = 0; i < NUM_OFFSET_RANGES; i++)
- memcpy(&ProfessionalismOffsetTable[i], &profData[i * 2], 2);
- result = mechFile->readIdCharArray("DecorumTable", profData, NUM_OFFSET_RANGES * 2);
- if (result != NO_ERR)
- return(result);
- for (i = 0; i < NUM_OFFSET_RANGES; i++)
- memcpy(&DecorumOffsetTable[i], &profData[i * 2], 2);
- result = mechFile->readIdCharArray("AmmoTable", profData, 2 * 2);
- if (result != NO_ERR)
- return(result);
- for (i = 0; i < 2; i++)
- memcpy(&AmmoConservationModifiers[i], &profData[i * 2], 2);
- #ifdef USEHEAT
- result = mechFile->readIdFloat("WeaponHeatCheckDelay", WeaponHeatCheckDelay);
- if (result != NO_ERR)
- return(result);
- #endif
- result = mechFile->readIdFloat("PilotCheckHalfRate", PilotCheckHalfRate);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdLongArray("PilotCheckModifiers", PilotCheckModifierTable, 2);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("DamageRateFrequency", DamageRateFrequency);
- if (result != NO_ERR)
- return(result);
- char charData[NUM_ATTITUDES * 6];
- result = mechFile->readIdCharArray("AttitudeEffect", charData, NUM_ATTITUDES * 6);
- if (result != NO_ERR)
- return(result);
- for (i = 0; i < NUM_ATTITUDES; i++)
- memcpy(&AttitudeEffect[i], &charData[i * 6], 6);
- result = mechFile->readIdFloat("MovementUpdateFrequency", MovementUpdateFrequency);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("CombatUpdateFrequency", CombatUpdateFrequency);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("CommandUpdateFrequency", CommandUpdateFrequency);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("PilotCheckUpdateFrequency", PilotCheckUpdateFrequency);
- if (result != NO_ERR)
- return(result);
- // result = mechFile->readIdFloatArray("FireOddsTable", FireOddsTable, NUM_FIREODDS);
- // if (result != NO_ERR)
- // return(result);
- result = mechFile->readIdLong("SkillIncreaseCap", MechWarrior::increaseCap);
- Assert(result == NO_ERR, result, " Couldn't find SkillCap variable in Warrior block of gamesys.fit ");
- result = mechFile->readIdFloat("SkillMax", MechWarrior::maxSkill);
- Assert(result == NO_ERR, result, " Couldn't find SkillMax variable in Warrior block of gamesys.fit ");
-
- result = mechFile->readIdFloat("SkillMin", MechWarrior::minSkill);
- Assert(result == NO_ERR, result, " Couldn't find SkillMin variable in Warrior block of gamesys.fit ");
- // result = mechFile->readIdLong("JumpSkillMod", PilotJumpMod);
- // Assert(result == NO_ERR, result, " Couldn't find JumpSkillMod variable in Warrior block of gamesys.fit ");
-
- result = mechFile->seekBlock("Sensors");
- if (result != NO_ERR)
- return(result);
- // result = mechFile->readIdFloatArray("SensorModifiers", SensorModifier, 8);
- // if (result != NO_ERR)
- // return(result);
- result = mechFile->readIdFloat("BaseSensorRollTarget", SensorBaseChance);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("SensorSkillFactor", SensorSkillFactor);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("BlockingObjectModifier", SensorBlockingObjectModifier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("ShutdownMech", SensorShutDownMechModifier);
- if (result != NO_ERR)
- return(result);
- #ifdef USEHEAT
- result = mechFile->readIdFloat("HeatMultiplier", SensorHeatMultiplier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("WeaponHeatMultiplier", SensorWeaponHeatMultiplier);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloatArray("HeatSourceModifiers", SensorHeatSourceModifiers, 2);
- if (result != NO_ERR)
- return(result);
- #endif
- float rangeTable[8];
- result = mechFile->readIdFloatArray("SensorRangeModifier", rangeTable, 8);
- if (result != NO_ERR)
- return(result);
- for (i = 0; i < 4; i++) {
- SensorRangeModifier[i][0] = rangeTable[i * 2];
- SensorRangeModifier[i][1] = rangeTable[i * 2 + 1];
- }
- float sizeTable[6];
- result = mechFile->readIdFloatArray("SizeModifier", sizeTable, 6);
- if (result != NO_ERR)
- return(result);
- for (i = 0; i < 3; i++) {
- SensorSizeModifier[i][0] = sizeTable[i * 2];
- SensorSizeModifier[i][1] = sizeTable[i * 2 + 1];
- }
- long masterIDs[9];
- result = mechFile->readIdLongArray("SensorMasterIDs", masterIDs, 9);
- if (result != NO_ERR)
- return(result);
-
- /*
- float rangeMultipliers[9];
- result = mechFile->readIdFloatArray("SensorRangeMultipliers", rangeMultipliers, 9);
- if (result != NO_ERR)
- return(result);
- //------------------------------------------------------------------------------
- // The following relies upon knowing the MasterComponentID for all of the sensor
- // components...
- for (i = 0; i < 9; i++)
- if (masterIDs[i] > -1)
- MasterComponentList[masterIDs[i]].setSensorRange(visualRange * rangeMultipliers[i]);
- */
- result = mechFile->readIdFloatArray("BlockingTerrainModifiers", SensorBlockingTerrain, 2);
- if (result != NO_ERR)
- return(result);
- result = mechFile->seekBlock("Skills");
- if (result != NO_ERR)
- Fatal(result, "Couldn't find skill block in gamesys.fit");
- result = mechFile->readIdFloatArray("Skill Attempt", SkillTry, 4);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloatArray("Skill Success", SkillSuccess, 4);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("WeaponHit", WeaponHit);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloatArray("KillSkillValues", KillSkill, 6);
- if (result != NO_ERR)
- return(result);
- result = mechFile->readIdFloat("Sensor Contact Skill", SensorSkill);
- if (result != NO_ERR)
- return(result);
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- void Mover::set (Mover copy) {
- GameObject::set(copy);
- //ID = copy.ID;
- positionNormal = copy.positionNormal;
- velocity = copy.velocity;
- rotation = copy.rotation;
- strncpy(name, copy.name, MAXLEN_MOVER_NAME - 1);
- chassis = copy.chassis;
- damageRateTally = copy.damageRateTally;
- damageRateCheckTime = copy.damageRateCheckTime;
- pilotCheckDamageTally = copy.pilotCheckDamageTally;
- numBodyLocations = copy.numBodyLocations;
- for (long i = 0; i < numBodyLocations; i++)
- body[i] = copy.body[i];
- fieldedCV = copy.fieldedCV;
-
- numArmorLocations = copy.numArmorLocations;
- for (i = 0; i < numArmorLocations; i++)
- armor[i] = copy.armor[i];
- }
- //---------------------------------------------------------------------------
- void Mover::init (bool create) {
-
- GameObject::init(create);
- if (initialize) {
- killed = false;
- lost = false;
- salvaged = false;
- appearance = NULL;
- lowestWeaponNodeID = -2;
- sensorSystem = NULL;
- lastMapCell[0] = -1;
- lastMapCell[1] = -1;
- contactInfo = new ContactInfo;
- pilot = NULL;
- pilotHandle = 0;
- numWeaponHitsHandled = 0;
- prevTeamId = -1;
- numMovers++;
- }
- objectClass = MOVER;
- unitGroup = 2;
- causeOfDeath = -1;
- iconPictureIndex = 0;
- lowestWeaponNodeZ = -9999.9f;
- positionNormal.Zero();
- velocity.Zero();
- name[0] = NULL;
- chassis = 0;
- startDisabled = false;
- pathLocks = true;
-
- damageRateTally = 0;
- damageRateCheckTime = 1.0;
- pilotCheckDamageTally = 0;
- numBodyLocations = 0;
- fieldedCV = 0;
- numArmorLocations = 0;
- attackRange = FIRERANGE_OPTIMAL;
- suppressionFire = 0;
- numArmorLocations = 0;
- numOther = 0;
- numWeapons = 0;
- numAmmos = 0;
- numAmmoTypes = 0;
- cockpit = 255;
- engine = 255;
- lifeSupport = 255;
- sensor = 255;
- ecm = 255;
- probe = 255;
- jumpJets = 255;
- nullSignature = 255;
- maxWeaponEffectiveness = 0.0;
- weaponEffectiveness = 0.0;
- minRange = 0.0;
- maxRange = 0.0;
- optimalRange = 0.0;
- numFunctionalWeapons = 0;
- numAntiMissileSystems = 0;
- engineBlowTime = -1.0;
- maxMoveSpeed = 0.0;
- shutDownThisFrame = false;
- startUpThisFrame = false;
- disableThisFrame = false;
- //
- teamId = -1;
- groupId = -1;
- squadId = -1;
- selectionIndex = -1;
- teamRosterIndex = -1;
- commanderId = -1;
- unitGroup = 2; // the thing the user sets by hitting ctrl and a number
- pilotCheckModifier = -1;
- prevPilotCheckUpdate = 0.0;
- prevPilotCheckModifier = 0;
- prevPilotCheckDelta = 0;
- failedPilotingCheck = false;
- collisionFreeFromWID = 0;
- collisionFreeTime = -1.0;
- lastWeaponEffectivenessCalc = 0.0;
- lastOptimalRangeCalc = 0.0;
- challengerWID = 0;
- lastGesture = -1;
- control.init();
- dynamics.init();
- //netPlayerId = 0;
- if (MPlayer) {
- #ifdef USE_STRING_RESOURCES
- cLoadString(thisInstance,IDS_LOSTPLAYER+languageOffset,netPlayerName,254);
- #else
- sprintf(netPlayerName, "%s", "NEED STRING RESOURCES");
- #endif
- }
- else
- netPlayerName[0] = NULL;
- localMoverId = -1;
- netRosterIndex = -1;
- statusChunk.init();
- newMoveChunk = false;
- moveChunk.init();
- numWeaponFireChunks[CHUNK_RECEIVE] = 0;
- numWeaponFireChunks[CHUNK_SEND] = 0;
- numCriticalHitChunks[CHUNK_RECEIVE] = 0;
- numCriticalHitChunks[CHUNK_SEND] = 0;
- numRadioChunks[CHUNK_RECEIVE] = 0;
- numRadioChunks[CHUNK_SEND] = 0;
- ejectOrderGiven = false;
- timeLeft = 1.0;
- exploding = false;
- withdrawing = false;
- yieldTimeLeft = 0.0;
- lastValidPosition.Zero();
- pivotDirection = 0;
- lastHustleTime = -999.0;
- salvageVehicle = false;
- markDistanceMoved = 0.0;
- refitBuddyWID = 0;
- recoverBuddyWID = 0;
- crashAvoidSelf = 1;
- crashAvoidPath = 1;
- crashBlockSelf = 1;
- crashBlockPath = 1;
- crashYieldTime = 1.5;
- pathLockLength = 0;
- moveType = MOVETYPE_GROUND;
- moveLevel = 0;
- moveCenter.Zero();
- moveRadius = -1.0;
- followRoads = false;
- overlayWeightClass = 0;
- timeToClearSelection = 0.0;
- timeSinceMoving = 0.0;
- timeSinceFiredLast = MaxTimeRevealed;
- lastMovingTargetWID = 0;
- mechSalvage = true;
- setTangible(true);
- setFlag(OBJECT_FLAG_SENSOR, true);
- if (!sortList) {
- sortList = new SortList;
- if (!sortList)
- Fatal(0, " Unable to create Mover::sortList ");
- sortList->init(4000);
- }
- teleportPosition.x = -999999.0;
- teleportPosition.y = -999999.0;
- teleportPosition.z = -999999.0;
- debugPage = 0;
-
- conStat = 0;
- fadeTime = 0.0f;
- alphaValue = 0x0;
- if ( !holdFireIconHandle )
- {
- FullPathFileName path;
- path.init( artPath, "blip", ".tga" );
-
- holdFireIconHandle = mcTextureManager->loadTexture( path, gos_Texture_Alpha, gosHint_DisableMipmap | gosHint_DontShrink );
- }
- }
- //---------------------------------------------------------------------------
- void Mover::release (void) {
- setTeamId(-1, false);
- if (getGroup())
- getGroup()->remove(this);
- setCommanderId(-1);
- MechWarrior::freeWarrior(pilot);
- pilot = NULL;
- }
- //---------------------------------------------------------------------------
- extern GameObjectPtr DebugGameObject[3];
- void Mover::updateDebugWindow (GameDebugWindow* debugWindow) {
- debugPage %= 3;
- debugWindow->clear();
- static char s[128];
- MovePathPtr path = getPilot()->getMovePath();
- long distToObj1 = -1;
- if (DebugGameObject[2])
- distToObj1 = (long)distanceFrom(DebugGameObject[2]->getPosition());
- long sensorRange = 0;
- if (sensorSystem)
- sensorRange = (long)sensorSystem->getEffectiveRange();
- long contStat = contactInfo->getContactStatus(0, true);
- static char* contactStr[NUM_CONTACT_STATUSES] = {
- " ",
- "SENSOR_1",
- "SENSOR_2",
- "SENSOR_3",
- "SENSOR_4",
- "VISUAL "
- };
- if (debugPage == 0) {
- sprintf(s, "%s (%s %02d)", getName(), getPilot()->getName(), getPilot()->getIndex());
- debugWindow->print(s);
- long gestID = -1;
- if (getObjectClass() == BATTLEMECH)
- gestID = ((Mech3DAppearance*)appearance)->getCurrentGestureId();
- sprintf(s, "cmdr: %d, team: %d, gestID: %d, partID: %d", getCommanderId(), getTeamId(), gestID, getPartId());
- debugWindow->print(s);
- if (path->curStep < path->numStepsWhenNotPaused) {
- long curDir = path->stepList[path->curStep].direction;
- if (curDir > 7)
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s] JMP", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- else
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s] MOV", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- }
- else
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s]", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- debugWindow->print(s);
- #if 0
- if (getObjectClass() == BATTLEMECH) {
- sprintf(s, "JMP: (%.f) cgid=%d, Su=%d, in=%d, Ar=%d",
- getJumpRange(),
- ((Mech3DAppearance*)appearance)->getCurrentGestureId(),
- ((Mech3DAppearance*)appearance)->isJumpSetup() ? 1 : 0,
- ((Mech3DAppearance*)appearance)->isInJump() ? 1 : 0,
- ((Mech3DAppearance*)appearance)->isJumpAirborne() ? 1 : 0);
- debugWindow->print(s);
- }
- #else
- sprintf(s, "range: [%.f/%.f/%.f] %.f",
- getMinFireRange(),
- getOptimalFireRange(),
- getMaxFireRange(),
- getPilot()->getCurrentTarget() ? distanceFrom(getPilot()->getCurrentTarget()->getPosition()) : 0.0);
- debugWindow->print(s);
- #endif
- strcpy(s, "order: ");
- if (getPilot()->getNumTacOrdersQueued()) {
- if (getPilot()->getExecutingTacOrderQueue()) {
- char ts[40];
- sprintf(ts, "[%d%c] ", getPilot()->getNumTacOrdersQueued(), getPilot()->getTacOrderQueueLooping() ? "@" : ".");
- strcat(s, ts);
- }
- else {
- char ts[40];
- sprintf(ts, "[%d] ", getPilot()->getNumTacOrdersQueued());
- strcat(s, ts);
- }
- }
- getPilot()->getCurTacOrder()->debugString(getPilot(), &s[7]);
- debugWindow->print(s);
- if (getPilot()->getBrain())
- {
- ModuleInfo brainInfo;
- getPilot()->getBrain()->getInfo(&brainInfo);
- debugWindow->print(" ");
- sprintf(s, "brain: %s", brainInfo.name);
- debugWindow->print(s);
- //-----------------------------------------------------------------
- // Skip the "data\missions\warriors" text when printing filename...
- sprintf(s, "file: %s", &brainInfo.fileName[23]);
- debugWindow->print(s);
- }
-
- sprintf(s, "cont:");
- if (sensorSystem) {
- // display up to 4...
- long numConts = 4;
- if (sensorSystem->numContacts < 4)
- numConts = sensorSystem->numContacts;
- for (long i = 0; i < numConts; i++) {
- MoverPtr contact = (MoverPtr)ObjectManager->get(sensorSystem->contacts[i] & 0x7FFF);
- Assert(contact != NULL, sensorSystem->contacts[i] & 0x7FFF, " null contact ");
- char s2[10];
- sprintf(s2, " %d.%d", sensorSystem->contacts[i] & 0x7FFF, contact->getContactStatus(teamId, true));
- strcat(s, s2);
- }
- if (sensorSystem->numContacts > 4)
- strcat(s, " +++");
- }
- debugWindow->print(s);
- if (getPilot()->getCurrentTarget()) {
- char ts[50];
- getPilot()->printWeaponsStatus(ts);
- sprintf(s, "%s", ts);
- }
- else
- sprintf(s, "no current target");
- debugWindow->print(s);
- for (long i = 0; i < 5; i++) {
- sprintf(s, "%s", getPilot()->getDebugString(i));
- debugWindow->print(s);
- }
- }
- else if (debugPage == 1) {
- sprintf(s, "%s (%s %02d)", getName(), getPilot()->getName(), getPilot()->getIndex());
- debugWindow->print(s);
- sprintf(s, "team: %d, handle: %d, partID: %d, rank: %d", getTeamId(), getHandle(), getPartId(), getPilot()->getRank());
- debugWindow->print(s);
- if (path->curStep < path->numStepsWhenNotPaused) {
- long curDir = path->stepList[path->curStep].direction;
- if (curDir > 7)
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s] JMP", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- else
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s] MOV", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- }
- else
- sprintf(s, "pos: [%d, %d](%d) snsr: %d[%s]", cellPositionRow, cellPositionCol, distToObj1, sensorRange, contactStr[contStat]);
- debugWindow->print(s);
- sprintf(s, "cur step = [%d, %d], area = %d", 0, 0, GlobalMoveMap[0]->calcArea(cellPositionRow, cellPositionCol));
- debugWindow->print(s);
- MoveOrders* moveOrders = getPilot()->getMoveOrders();
- if (moveOrders->numGlobalSteps > 0) {
- sprintf(s, "LR:");
- long lastIndex = moveOrders->curGlobalStep + 8;
- if (lastIndex > moveOrders->numGlobalSteps)
- lastIndex = moveOrders->numGlobalSteps;
- for (long i = 0; i < lastIndex; i++) {
- char ss[15];
- if (i == moveOrders->curGlobalStep)
- sprintf(ss, " [%d]", moveOrders->globalPath[i].thruArea);
- else
- sprintf(ss, " %d", moveOrders->globalPath[i].thruArea);
- strcat(s, ss);
- }
- if (lastIndex < moveOrders->numGlobalSteps)
- strcat(s, " +");
- debugWindow->print(s);
- }
- static char* moveStateStr[NUM_MOVESTATES] = {
- "SS",
- "FF",
- "RR",
- "*F",
- "*R",
- "*T"
- };
- sprintf(s, "MoveState Cur/Goal = %s[%s]",
- moveStateStr[pilot->getMoveState()],
- moveStateStr[pilot->getMoveStateGoal()]);
- debugWindow->print(s);
- GameObjectPtr target = pilot->getCurrentTarget();
- float torsoRelFacing = -1.0;
- if (objectClass == BATTLEMECH) {
- sprintf(s, "torsoRotation = %.2f", ((BattleMechPtr)this)->torsoRotation);
- debugWindow->print(s);
- if (target)
- torsoRelFacing = relFacingTo(target->getPosition()) + ((BattleMechPtr)this)->torsoRotation;
- else if (pilot->getCurTacOrder()->code == TACTICAL_ORDER_ATTACK_POINT)
- torsoRelFacing = relFacingTo(pilot->getAttackTargetPoint()) + ((BattleMechPtr)this)->torsoRotation;
- else
- torsoRelFacing = ((BattleMechPtr)this)->torsoRotation;
- sprintf(s, "C-Bills = %d", ((BattleMechPtr)this)->cBills);
- debugWindow->print(s);
- }
- else if (objectClass == GROUNDVEHICLE) {
- sprintf(s, "turretRotation = %.2f", ((GroundVehiclePtr)this)->turretRotation);
- debugWindow->print(s);
- if (target)
- torsoRelFacing = relFacingTo(target->getPosition()) + ((GroundVehiclePtr)this)->turretRotation;
- else if (pilot->getCurTacOrder()->code == TACTICAL_ORDER_ATTACK_POINT)
- torsoRelFacing = relFacingTo(pilot->getAttackTargetPoint()) + ((GroundVehiclePtr)this)->turretRotation;
- else
- torsoRelFacing = ((GroundVehiclePtr)this)->turretRotation;
- }
- sprintf(s, "torsoRelFacing = %.2f", torsoRelFacing);
- debugWindow->print(s);
- }
- else if (debugPage == 2) {
- static char* locationStrings [] = {
- "head: ",
- "c torso: ",
- "l torso: ",
- "r torso: ",
- "l arm: ",
- "r arm: ",
- "l leg: ",
- "r leg: ",
- "rc torso: ",
- "rl torso: ",
- "rr torso: ",
- "front: ",
- "left: ",
- "right: ",
- "rear: ",
- "turret: "
- };
- static char* bodyState[] = {
- "normal",
- "DAM",
- "DEST"
- };
- sprintf(s, "%s (%s %02d)", getName(), getPilot()->getName(), getPilot()->getIndex());
- debugWindow->print(s);
- sprintf(s, "team: %d, partID: %d, threat: %d", getTeamId(), getPartId(), getThreatRating());
- debugWindow->print(s);
- debugWindow->print(" ");
- if (getObjectClass() == BATTLEMECH) {
- for (long i = 0; i < numBodyLocations; i++) {
- sprintf(s, "%s IS:%3.1f(%02d) AR:%3.1f(%02d) %s",
- locationStrings[i],
- body[i].curInternalStructure,
- body[i].maxInternalStructure,
- armor[i].curArmor,
- armor[i].maxArmor,
- bodyState[body[i].damageState]);
- debugWindow->print(s);
- }
- for (i = numArmorLocations; i < numArmorLocations; i++) {
- sprintf(s, "%s AR:%02d(%02d) %s",
- locationStrings[i],
- armor[i].curArmor,
- armor[i].maxArmor);
- debugWindow->print(s);
- }
- }
- else if (getObjectClass() == GROUNDVEHICLE) {
- for (long i = 0; i < numBodyLocations; i++) {
- sprintf(s, "%s IS:%3.1f(%02d) AR:%3.1f(%02d) %s",
- locationStrings[i + 11],
- body[i].curInternalStructure,
- body[i].maxInternalStructure,
- armor[i].curArmor,
- armor[i].maxArmor,
- bodyState[body[i].damageState]);
- debugWindow->print(s);
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- void Mover::setPartId (long newPartId) {
- partId = newPartId;
- //MoverRoster[newPartId - MIN_MOVER_PART_ID] = (BaseObjectPtr)this;
- }
- //---------------------------------------------------------------------------
- long Mover::setTeamId (long _teamId, bool setup) {
- if (teamId > -1) {
- //----------------------------------
- // Remove me from my current team...
- prevTeamId = teamId;
- TeamPtr team = Team::teams[teamId];
- if (sensorSystem)
- SensorManager->removeTeamSensor(teamId, sensorSystem);
- //if (ecm != 255)
- // SensorManager->removeEcm(this,);
- if (pilot)
- pilot->setTeam(NULL);
- team->removeFromRoster(this);
- }
- teamId = _teamId;
- Assert(teamId > -2, teamId, " Mover.setTeamId: bad teamId ");
- if (setup) {
- if (teamId > -1) {
- TeamPtr team = Team::teams[teamId];
- Assert(team != NULL, 0, " Mover.setTeamId: NULL team ");
- if (sensorSystem)
- SensorManager->addTeamSensor(teamId, sensorSystem);
- if (pilot)
- pilot->setTeam(team);
- }
- }
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- TeamPtr Mover::getTeam (void) {
- if (teamId == -1)
- return(NULL);
- return(Team::teams[teamId]);
- }
- //---------------------------------------------------------------------------
- CommanderPtr Mover::getCommander (void) {
- if (commanderId == -1)
- return(NULL);
- return(Commander::commanders[commanderId]);
- }
- //---------------------------------------------------------------------------
- bool Mover::isFriendly (TeamPtr team) {
- if (teamId > -1 && team)
- return(Team::relations[teamId][team->getId()] == RELATION_FRIENDLY);
- return(false);
- }
- //---------------------------------------------------------------------------
- bool Mover::isEnemy (TeamPtr team) {
- if (teamId > -1 && team)
- return(Team::relations[teamId][team->getId()] == RELATION_ENEMY);
- return(false);
- }
- //---------------------------------------------------------------------------
- bool Mover::isNeutral (TeamPtr team) {
- if (teamId > -1 && team)
- return(Team::relations[teamId][team->getId()] == RELATION_NEUTRAL);
- return(true);
- }
- //---------------------------------------------------------------------------
- long Mover::setGroupId (long _groupId, bool setup) {
- groupId = _groupId;
- if (setup && (groupId > -1) && pilot) {
- pilot->clearCurTacOrder(false);
- pilot->setOrderState(ORDERSTATE_GENERAL);
- }
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- MoverGroupPtr Mover::getGroup (void) {
- if (groupId == -1)
- return(NULL);
- return(Commander::commanders[commanderId]->getGroup(groupId));
- }
- //---------------------------------------------------------------------------
- void Mover::setPosition (Stuff::Vector3D& newPosition) {
- //-------------------------------------------
- // Confirm position as on map and move it
- // back on map if necessary
- float maxMap = Terrain::worldUnitsMapSide / 2.0;
- bool offMap = false;
- if (newPosition.x < -maxMap)
- {
- newPosition.x = -maxMap;
- offMap = true;
- }
- if (newPosition.x > maxMap)
- {
- newPosition.x = maxMap;
- offMap = true;
- }
- if (newPosition.y < -maxMap)
- {
- newPosition.y = -maxMap;
- offMap = true;
- }
- if (newPosition.y > maxMap)
- {
- newPosition.y = maxMap;
- offMap = true;
- }
- if (!offMap)
- {
- //--------------------------------------------------------------
- // New map clip code here. Actually easy once thought out!
- float maxVisual = Terrain::worldUnitsPerVertex * Terrain::blocksMapSide * Terrain::verticesBlockSide / 2;
- maxVisual -= 1300.0;
- float clipChk1 = newPosition.y - newPosition.x;
- float clipChk2 = newPosition.y + newPosition.x;
-
- bool clipA = (clipChk1 > maxVisual);
- bool clipB = (clipChk1 < -maxVisual);
- bool clipC = (clipChk2 > maxVisual);
- bool clipD = (clipChk2 < -maxVisual);
-
- if (clipA || clipB || clipC || clipD)
- offMap = true;
- }
-
- //--------------------------------------------
- //-- Code to whack Object if it moves off of map
- //-- I.e. Withdrawing or a camera Drone. hehehe.
- if (offMap && withdrawing)
- {
- ObjectManager->getObjectType(typeHandle)->handleDestruction(this,NULL);
- }
- GameObject::setPosition(newPosition);
- triggerAreaMgr->setHit(this);
- //-------------------------------------------------------------------------------------
- // If we've marked our cell as occupied, and our position has changed, then clear it...
- if (lastMapCell[0] != -1)
- if ((lastMapCell[0] != cellPositionRow) || (lastMapCell[1] != cellPositionCol)) {
- GameMap->setMover(lastMapCell[0], lastMapCell[1], false);
- lastMapCell[0] = -1;
- lastMapCell[1] = -1;
- }
-
- //--------------------------------------------------
- // Now, mark our current cell if we're NOT moving...
- if (pilot->getMovePath()->numSteps == 0) {
- lastMapCell[0] = cellPositionRow;
- lastMapCell[1] = cellPositionCol;
- GameMap->setMover(cellPositionRow, cellPositionCol, true);
- }
- //if (objPosition)
- // GameObjectMap->updateObject(this);
- }
- //---------------------------------------------------------------------------
- void Mover::rotate (float angle)
- {
- //Old function. If only one is passed in, facing and rotation are equal!
- rotate(angle,angle);
- }
- //---------------------------------------------------------------------------
- void Mover::rotate (float angle, float facingAngle)
- {
- rotation += angle;
- if (rotation < -180.0)
- rotation += 360.0;
- else if (rotation > 180.0)
- rotation -= 360.0;
- }
- //---------------------------------------------------------------------------
- void Mover::setAwake (bool set) {
- GameObject::setAwake(set);
- if (set && pilot && (getStatus() == OBJECT_STATUS_SHUTDOWN))
- pilot->orderPowerUp(false, ORDER_ORIGIN_SELF);
- }
- //---------------------------------------------------------------------------
- float Mover::relFacingDelta (Stuff::Vector3D goalPos, Stuff::Vector3D targetPos) {
- float relFacingToGoal = relFacingTo(goalPos);
- float relFacingToTarget = relFacingTo(targetPos);
- float facingDelta = 0.0;
- if (relFacingToGoal >= 0) {
- if (relFacingToTarget >= 0)
- if (relFacingToGoal > relFacingToTarget)
- facingDelta = relFacingToGoal - relFacingToTarget;
- else
- facingDelta = relFacingToTarget - relFacingToGoal;
- else {
- facingDelta = relFacingToGoal - relFacingToTarget;
- if (facingDelta > 180)
- facingDelta = 360.0 - facingDelta;
- }
- }
- else {
- if (relFacingToTarget >= 0) {
- facingDelta = -relFacingToGoal + relFacingToTarget;
- if (facingDelta > 180)
- facingDelta = 360.0 - facingDelta;
- }
- else
- if (relFacingToGoal > relFacingToTarget)
- facingDelta = relFacingToGoal - relFacingToTarget;
- else
- facingDelta = relFacingToTarget - relFacingToGoal;
- }
- return(facingDelta);
- }
- //---------------------------------------------------------------------------
- float Mover::relFacingTo (Stuff::Vector3D goal, long bodyLocation) {
- #if 1
- Stuff::Vector3D facingVec = getRotationVector();
- Stuff::Vector3D goalVec;
- goalVec.Subtract(goal, position);
- goalVec.z = 0.0;
- float angle = angle_from(facingVec, goalVec);
- Stuff::Vector3D angleSign;
- angleSign.Cross(facingVec, goalVec);
- if (angleSign.z >= 0.0)
- {
- angle = -angle;
- }
- return(angle);
- #else
- Stuff::Vector3D curPos = position;
- curPos.z = 0;
- goal.z = 0;
- //-------------------------
- // Create vector for facing
- frame_of_ref workFrame = frame;
- //float angle45 = 45.0;
- //workFrame.rotate_about_k(angle45);
- Stuff::Vector3D velVect = -(workFrame.j);
- Stuff::Vector3D goalVec;
- goalVec = goal - curPos;
- goalVec.normalize();
-
- float resultAngle = velVect.angle_from(goalVec);
- Stuff::Vector3D angleSign = velVect CROSS goalVec;
- if (angleSign.z >= 0.0)
- {
- resultAngle = -resultAngle;
- }
- /*
- if (angle < 180.0) {
- //---------------------------------------------------
- // Now, let's determine if it's to the right or left.
- // If to the right, return a positive angle.
- // If to the left, return a negative angle.
- // There has to be a cleaner way to get this, right?!
- float one = 1.0;
- workFrame.rotate_about_k(one);
- velVect = -(workFrame.j);
- float angle2 = velVect.angle_from(goal - curPos);
- if (angle2 < angle)
- return(-angle);
- }
- */
- return(resultAngle);
- #endif
- }
- //------------------------------------------------------------------------------------------
- float Mover::getTerrainAngle (void) {
- Stuff::Vector3D worldK(0.0, 0.0, 1.0);
- float result = positionNormal * worldK;
- result = my_acos(result) * RADS_TO_DEGREES;
- return(result);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getVelocityTilt (void) {
- //---------------------------
- // Create vector for velocity
- Stuff::Vector3D facingVec = getRotationVector();
- float result = positionNormal * facingVec;
- result = my_acos(result) * RADS_TO_DEGREES;
- return(result);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getFireArc (void) {
- switch (getObjectClass()) {
- case BATTLEMECH:
- return(FireArc[0]);
- break;
- case GROUNDVEHICLE:
- return(FireArc[1]);
- break;
- case ELEMENTAL:
- return(FireArc[2]);
- break;
- }
- return(45.0);
- }
- //------------------------------------------------------------------------------------------
- void Mover::destroy (void)
- {
- //We only destroy on game end. Most of this is caught in the heap frees!!
- //----------------------------------------------
- // This will free any memory the mover is using.
- if (appearance)
- {
- delete appearance;
- appearance = NULL;
- }
- if (contactInfo)
- {
- delete contactInfo;
- contactInfo = NULL;
- }
- }
- //----------------------------------------------------------------------------------
- Stuff::Vector3D Mover::relativePosition (float angle, float distance, unsigned long flags) {
- //--------------------------------------------------------
- // Note that the angle should be -180 <= angle <= 180, and
- // the distance is in meters...
- distance *= -worldUnitsPerMeter;
-
- //--------------------------------------------
- // Absolute facing, based upon north facing...
- Stuff::Vector3D shiftVect(0.0, 1.0, 0.0);
- if ((flags & RELPOS_FLAG_ABS) == 0) {
- //----------------------------------------------------
- // Create vector for facing, rotated to adjust for the
- // relative angle...
- shiftVect = getRotationVector();
- }
- Rotate(shiftVect, angle);
- shiftVect *= distance;
- Stuff::Vector3D curPos(position.x, position.y, 0.0);
- Stuff::Vector3D relPos(curPos.x + shiftVect.x, curPos.y + shiftVect.y, 0.0);
- Stuff::Vector3D start;
- Stuff::Vector3D goal;
- Stuff::Vector3D deltaVector;
- if (flags & RELPOS_FLAG_PASSABLE_START) {
- start = curPos;
- goal = relPos;
- }
- else {
- start = relPos;
- goal = curPos;
- }
- deltaVector.Subtract(goal, start);
- //-------------------------------------------------------------
- // First, we need to calc the delta vector--how much we extend
- // the ray everytime we check the map cell for clear placement.
- deltaVector.Normalize(deltaVector);
- float cellLength = Terrain::worldUnitsPerCell;
- cellLength *= 0.5;
- deltaVector *= cellLength;
- if (deltaVector.GetLength() == 0.0)
- return(curPos);
- //-------------------------------------------------
- // Determine the max length the ray must be cast...
- float maxLength = distance_from(goal, start);
- //------------------------------------------------------------
- // We'll start at the target, and if it's blocked, we'll move
- // toward our start location, looking for the first valid/open
- // cell...
- Stuff::Vector3D curPoint = start;
- Stuff::Vector3D curRay;
- curRay.Zero();
- float rayLength = 0.0;
- long cellR, cellC;
- land->worldToCell(curPoint, cellR, cellC);
- bool cellClear = GameMap->getPassable(cellR, cellC);
- Stuff::Vector3D lastGoodPoint = curPoint;
- if (flags & RELPOS_FLAG_PASSABLE_START)
- while (cellClear && (rayLength < maxLength)) {
- lastGoodPoint = curPoint;
- curPoint += deltaVector;
- curRay.Subtract(curPoint, start);
- rayLength = curRay.GetLength();
- land->worldToCell(curPoint, cellR, cellC);
- cellClear = GameMap->getPassable(cellR, cellC);
- }
- else
- while (!cellClear && (rayLength < maxLength)) {
- lastGoodPoint = curPoint;
- curPoint += deltaVector;
- curRay.Subtract(curPoint, start);
- rayLength = curRay.GetLength();
- land->worldToCell(curPoint, cellR, cellC);
- cellClear = GameMap->getPassable(cellR, cellC);
- }
- curPoint.x = lastGoodPoint.x;
- curPoint.y = lastGoodPoint.y;
- curPoint.z = land->getTerrainElevation(curPoint);
- return(curPoint);
- }
- //---------------------------------------------------------------------------
- void Mover::setSensorRange (float range) {
- if (sensorSystem)
- sensorSystem->setRange(range);
- }
- //---------------------------------------------------------------------------
- bool Mover::hasActiveProbe (void) {
- return(probe != 255);
- }
- //---------------------------------------------------------------------------
- float Mover::getEcmRange (void) {
- if ((ecm != 255))
- return 10.0f; //ANY ECM means I am invisible!!
- return(0.0);
- }
- //---------------------------------------------------------------------------
- bool Mover::hasNullSignature (void) {
- return(nullSignature != 255);
- }
- //---------------------------------------------------------------------------
- extern bool InitWayPath;
- long Mover::handleTacticalOrder (TacticalOrder tacOrder, long priority, bool queuePlayerOrder) {
- //queuePlayerOrder = true;
- if (queuePlayerOrder)
- tacOrder.pack(NULL, NULL);
- #if 1
- if (MPlayer && !MPlayer->isServer()) {
- //----------------------------
- // Simply for test purposes...
- tacOrder.pack(NULL, NULL);
- TacticalOrder tacOrder2;
- tacOrder2.data[0] = tacOrder.data[0];
- tacOrder2.data[1] = tacOrder.data[1];
- tacOrder2.unpack();
- }
- #endif
- //----------------------------------------------------
- // Any tacorder that gets here IS NOT a lance order...
- bool processOrder = true;
- long message = -1;
- switch (tacOrder.code) {
- case TACTICAL_ORDER_WAIT:
- suppressionFire = false;
- break;
- case TACTICAL_ORDER_MOVETO_POINT:
- //---------------------------------------------------
- // If we're part of a selected group, offset our goal
- // slightly...
- if (selectionIndex != -1)
- {
- tacOrder.delayedTime = scenarioTime + (selectionIndex * DelayedOrderTime);
- }
- if (!canMove())
- {
- //DO NOT send readio message. Players will know artillery cannot move.
- // BUT do not allow order through. Will cancel out a forceFire command!
- processOrder = false;
- }
- break;
- case TACTICAL_ORDER_JUMPTO_POINT:
- case TACTICAL_ORDER_JUMPTO_OBJECT: {
- bool canJump = (getObjectClass() == BATTLEMECH);
- GameObjectPtr target = tacOrder.getTarget();
- if (target && target->isMover() && (target->getTeam() == getTeam()))
- canJump = false;
- if (getJumpRange() < distanceFrom(tacOrder.getWayPoint(0)))
- canJump = false;
- if (getObjectClass() == BATTLEMECH) {
- long cellR, cellC;
- land->worldToCell(tacOrder.getWayPoint(0), cellR, cellC);
- if (!GameMap->getPassable(cellR, cellC))
- canJump = false;
- }
- if (!canJump) {
- message = RADIO_ILLEGAL_ORDER;
- processOrder = false;
- }
- //else
- // message = RADIO_JUMPTO;
- }
- //-----------------------------------------
- // No break here--should fall down below...
- case TACTICAL_ORDER_MOVETO_OBJECT:
- case TACTICAL_ORDER_TRAVERSE_PATH:
- case TACTICAL_ORDER_PATROL_PATH:
- //---------------------------------------------------
- // Tell everyone we have received the order.
- if (isDisabled() || !canMove()) {
- processOrder = false;
- }
- break;
- case TACTICAL_ORDER_ATTACK_OBJECT:
- //tacOrder.code = TACTICAL_ORDER_ATTACK_POINT;
- //tacOrder.attackParams.targetPoint = (GameObjectPtr(BaseObjectPtr(tacOrder.target)))->getPosition();
- //tacOrder.target = NULL;
- if (tacOrder.attackParams.method == ATTACKMETHOD_DFA) {
- //-------------------------------------------------
- // Let's just make it a move/jump order, for now...
- tacOrder.code = TACTICAL_ORDER_JUMPTO_OBJECT;
- //tacOrder.target = mouseObject;
- tacOrder.moveParams.wait = false;
- tacOrder.moveParams.wayPath.mode[0] = TRAVEL_MODE_SLOW;
- GameObjectPtr target = tacOrder.getTarget();
- if (target)
- tacOrder.setWayPoint(0, target->getPosition());
- }
- if (tacOrder.attackParams.aimLocation != -1)
- {
- message = RADIO_CALLED_SHOT;
- }
- break;
- case TACTICAL_ORDER_POWERUP:
- case TACTICAL_ORDER_POWERDOWN:
- //tacOrder.delayedTime = scenarioTime + 5.0;
- //break;
- case TACTICAL_ORDER_ESCORT:
- case TACTICAL_ORDER_FOLLOW:
- case TACTICAL_ORDER_GUARD:
- case TACTICAL_ORDER_STOP:
- case TACTICAL_ORDER_WAYPOINTS_DONE:
- case TACTICAL_ORDER_EJECT:
- case TACTICAL_ORDER_HOLD_FIRE:
- case TACTICAL_ORDER_WITHDRAW:
- case TACTICAL_ORDER_ATTACK_POINT:
- case TACTICAL_ORDER_REFIT:
- case TACTICAL_ORDER_GETFIXED:
- case TACTICAL_ORDER_CAPTURE:
- case TACTICAL_ORDER_RECOVER:
- case TACTICAL_ORDER_LOAD_INTO_CARRIER:
- case TACTICAL_ORDER_DEPLOY_ELEMENTALS:
- break;
- default: {
- char s[256];
- sprintf(s, "Mover::handleTacticalOrder->Bad TacOrder Code (%d)", tacOrder.code);
- Assert(false, tacOrder.code, s);
- return(1);
- }
- }
- if (pilot)
- pilot->radioMessage(message, true);
- //-------------------------------------------------------
- // Acknowledgement of a good order is done when the order
- // is executed...
- if (processOrder)
- switch (tacOrder.origin) {
- case ORDER_ORIGIN_PLAYER:
- if (queuePlayerOrder)
- pilot->addQueuedTacOrder(tacOrder);
- else {
- // if (pilot->getNumTacOrdersQueued())
- //This is a hack to simply trigger the execution of
- //the queued orders. The current order is ignored (and
- //is simply used for this trigger)...
- // pilot->executeTacOrderQueue();
- // else
- pilot->setPlayerTacOrder(tacOrder);
- }
- break;
- case ORDER_ORIGIN_COMMANDER:
- pilot->setGeneralTacOrder(tacOrder);
- break;
- case ORDER_ORIGIN_SELF:
- pilot->setAlarmTacOrder(tacOrder, priority);
- break;
- }
- return(NO_ERR);
- }
- //----------------------------------------------------------------------------------
- void Mover::reduceAntiMissileAmmo (long numAntiMissiles) {
- if (numAntiMissiles > 0)
- reduceAmmo(MasterComponent::masterList[inventory[antiMissileSystem[0]].masterID].getWeaponAmmoMasterId(), numAntiMissiles);
- }
- //----------------------------------------------------------------------------------
- void Mover::pilotingCheck (unsigned long situation, float modifier) {
- failedPilotingCheck = false;
- }
- //-------------------------------------------------------------------------------------------
- void Mover::updateDamageTakenRate (void) {
- if (damageRateCheckTime < scenarioTime) {
- long damageRate = (damageRateTally / DamageRateFrequency);
- if (damageRate > 10 /*AttitudeEffect[pilot->getAttitude(ORDER_CURRENT)][5]*/)
- pilot->triggerAlarm(PILOT_ALARM_DAMAGE_TAKEN_RATE, damageRate);
- damageRateTally = 0;
- damageRateCheckTime += DamageRateFrequency;
- }
- }
- //-------------------------------------------------------------------------------------------
- void Mover::setPilotHandle (long _pilotHandle) {
- if (pilot) {
- pilot->setVehicle(NULL);
- pilot = NULL;
- }
- pilotHandle = _pilotHandle;
- if (pilotHandle > 0) {
- pilot = MechWarrior::warriorList[pilotHandle];
- pilot->setVehicle((GameObjectPtr)this);
- }
- }
- //---------------------------------------------------------------------------
- void Mover::loadPilot (char* pilotFileName, char* brainFileName, LogisticsPilot *lPilot) {
- if (pilot) {
- MechWarrior::freeWarrior(pilot);
- pilot = NULL;
- }
- //---------------------------------------------------------------
- // Loads a new pilot into the pilot manager and then puts it into
- // this mover. If a pilot already exists in this mover, it is
- // replaced...
- MechWarriorPtr pilot = MechWarrior::newWarrior();
- if (!pilot)
- STOP(("Too many pilots in this mission!"));
- FullPathFileName pilotFullFileName;
- pilotFullFileName.init(warriorPath, pilotFileName, ".fit");
-
- FitIniFile* pilotFile = new FitIniFile;
- gosASSERT(pilotFile != NULL);
-
- long result = pilotFile->open(pilotFullFileName);
- gosASSERT(result == NO_ERR);
- result = pilot->init(pilotFile);
- gosASSERT(result == NO_ERR);
-
- pilotFile->close();
- delete pilotFile;
- pilotFile = NULL;
- //Copy logistics data to pilot AFTER loading old data.
- // ONLY if we overrode the data in logistics!!
- if (lPilot)
- {
- pilot->skills[MWS_GUNNERY] = pilot->skillRank[MWS_GUNNERY] = lPilot->getGunnery();
- pilot->skills[MWS_PILOTING] = pilot->skillRank[MWS_PILOTING] = lPilot->getPiloting();
- memcpy(pilot->specialtySkills,lPilot->getSpecialtySkills(),sizeof(bool) * NUM_SPECIALTY_SKILLS);
- pilot->calcRank();
- }
- //*********************
- // NOTE: Need to send packet to other players in MP with new pilot and
- // mover data!
- //*********************
- long numErrors, numLinesProcessed;
- FullPathFileName brainFullFileName;
- if (MPlayer) {
- pilot->setBrainName("pbrain");
- brainFullFileName.init(warriorPath, "pbrain", ".abl");
- }
- else {
- pilot->setBrainName(brainFileName);
- brainFullFileName.init(warriorPath, brainFileName, ".abl");
- }
-
- long moduleHandle = ABLi_preProcess(brainFullFileName, &numErrors, &numLinesProcessed);
- gosASSERT(moduleHandle >= 0);
- pilot->setBrain(moduleHandle);
- setPilotHandle(pilot->getIndex());
- }
- //---------------------------------------------------------------------------
- void Mover::setCommanderId (long _commanderId) {
- if (commanderId > -1)
- prevCommanderId = commanderId;
- commanderId = _commanderId;
- }
- //---------------------------------------------------------------------------
- MoverPtr Mover::getPoint (void) {
- #ifdef USE_GROUPS
- if (group)
- return(group->getPoint());
- #endif
- return(NULL);
- }
- //---------------------------------------------------------------------------
- bool Mover::hasWeaponNode (void)
- {
- if ((lowestWeaponNodeID == -1) || (lowestWeaponNodeID == -2) || (turn < 6))
- {
- lowestWeaponNodeID = appearance->getLowestWeaponNode();
- Stuff::Vector3D nodePos = appearance->getWeaponNodePosition(lowestWeaponNodeID);
- lowestWeaponNodeZ = nodePos.z - land->getTerrainElevation(nodePos);
- }
- return (lowestWeaponNodeID != -1);
- }
- //---------------------------------------------------------------------------
- Stuff::Vector3D Mover::getLOSPosition (void)
- {
- float jumpLowestNode = 0.0f;
- if (appearance)
- {
- bool oldInView = appearance->canBeSeen();
- appearance->setInView(true);
- if ((getStatus() == OBJECT_STATUS_NORMAL) &&
- ((appearance->getCurrentGestureId() == 2) ||
- (appearance->getCurrentGestureId() == 4) ||
- (appearance->getCurrentGestureId() == 7) || !isMech()) &&
- ((lowestWeaponNodeID == -1) || (lowestWeaponNodeID == -2) || (turn < 6)) )
- {
- lowestWeaponNodeID = appearance->getLowestWeaponNode();
- if (lowestWeaponNodeID == -1)
- {
- //We must not have ever rendered this guy. Probably multiplayer.
- // Update his Geometry.
- appearance->update();
- lowestWeaponNodeID = appearance->getLowestWeaponNode();
- }
- Stuff::Vector3D nodePos = appearance->getWeaponNodePosition(lowestWeaponNodeID);
- lowestWeaponNodeZ = nodePos.z - land->getTerrainElevation(nodePos);
- }
- if (appearance->getCurrentGestureId() == 20)
- {
- Stuff::Vector3D nodePos = appearance->getWeaponNodePosition(lowestWeaponNodeID);
- jumpLowestNode = nodePos.z - land->getTerrainElevation(nodePos);
- }
- if (lowestWeaponNodeZ <= 0.0f)
- {
- Stuff::Vector3D nodePos = appearance->getWeaponNodePosition(lowestWeaponNodeID);
- lowestWeaponNodeZ = nodePos.z - land->getTerrainElevation(nodePos);
- }
- appearance->setInView(oldInView);
- }
- Stuff::Vector3D losPos = position;
- if (lowestWeaponNodeZ != -9999.9f)
- losPos.z += lowestWeaponNodeZ;
- else
- losPos.z += 15.0f; //Fudge in some higher value so shutdown mechs don't just disappear!!
- if (jumpLowestNode > 0.0f)
- {
- losPos = position;
- losPos.z += jumpLowestNode;
- }
- return (losPos);
- }
- //---------------------------------------------------------------------------
- void Mover::printFireWeaponDebugInfo (GameObjectPtr target, Stuff::Vector3D* targetPoint, long chance, long aimLocation, long roll, WeaponShotInfo* shotInfo) {
- if (!CombatLog)
- return;
- static char* locationStrings [] = {
- "head",
- "center torso",
- "left torso",
- "right torso",
- "left arm",
- "right arm",
- "left leg",
- "right leg",
- "rear center torso",
- "rear left torso",
- "rear right torso"
- };
- if (roll < chance) {
- if (target) {
- char* targetName = target->getName();
- char s[1024];
- if (getObjectClass() == BATTLEMECH)
- sprintf(s, "[%.2f] mech.fireWeapon HIT: (%05d)%s @ (%05d)%s", scenarioTime, getPartId(), name, target->getPartId(), targetName ? targetName : "unknown");
- else
- sprintf(s, "[%.2f] vehicle.fireWeapon HIT: (%05d)%s @ (%05d)%s", scenarioTime, getPartId(), name, target->getPartId(), targetName ? targetName : "unknown");
- CombatLog->write(s);
- sprintf(s, " chance = %03d, roll = %03d", chance, roll);
- CombatLog->write(s);
- sprintf(s, " weapon = (%03d)%s, hitLocation = (%d)%s, damage = %.2f, angle = %.2f",
- shotInfo->masterId, MasterComponent::masterList[shotInfo->masterId].getName(),
- shotInfo->hitLocation, (shotInfo->hitLocation > -1) ? locationStrings[shotInfo->hitLocation] : "none",
- shotInfo->damage,
- shotInfo->entryAngle);
- CombatLog->write(s);
- if (aimLocation != -1) {
- sprintf(s, " aimed shot = (%d)%s", aimLocation, locationStrings[aimLocation]);
- CombatLog->write(s);
- }
- sprintf(s, " attacker pilot = %s (team id = %d)", getPilot()->getName(), getTeamId());
- CombatLog->write(s);
- CombatLog->write(" ");
- }
- else if (targetPoint) {
- }
- }
- else {
- if (target) {
- char* targetName = target->getName();
- char s[1024];
- if (getObjectClass() == BATTLEMECH)
- sprintf(s, "[%.2f] mech.fireWeapon MISS: (%05d)%s @ (%05d)%s", scenarioTime, getPartId(), name, target->getPartId(), targetName ? targetName : "unknown");
- else
- sprintf(s, "[%.2f] vehicle.fireWeapon HIT: (%05d)%s @ (%05d)%s", scenarioTime, getPartId(), name, target->getPartId(), targetName ? targetName : "unknown");
- CombatLog->write(s);
- sprintf(s, " chance = %03d, roll = %03d", chance, roll);
- CombatLog->write(s);
- sprintf(s, " weapon = (%03d)%s, hitLocation = (%d)%s, damage = %.2f, angle = %.2f",
- shotInfo->masterId, MasterComponent::masterList[shotInfo->masterId].getName(),
- shotInfo->hitLocation, (shotInfo->hitLocation > -1) ? locationStrings[shotInfo->hitLocation] : "none",
- shotInfo->damage,
- shotInfo->entryAngle);
- CombatLog->write(s);
- if (aimLocation != -1) {
- sprintf(s, " aimed shot = (%d)%s", aimLocation, locationStrings[aimLocation]);
- CombatLog->write(s);
- }
- sprintf(s, " attacker pilot = %s (team id = %d)", getPilot()->getName(), getTeamId());
- CombatLog->write(s);
- CombatLog->write(" ");
- }
- else if (targetPoint) {
- }
- }
- }
- //----------------------------------------------------------------------------
- bool FromMP = false;
- void Mover::printHandleWeaponHitDebugInfo (WeaponShotInfo* shotInfo) {
- if (!CombatLog)
- return;
- static char* locationStrings [] = {
- "head",
- "center torso",
- "left torso",
- "right torso",
- "left arm",
- "right arm",
- "left leg",
- "right leg",
- "rear center torso",
- "rear left torso",
- "rear right torso"
- };
- char s[1024];
- char statusStr[15];
- if (FromMP) {
- if (isDestroyed())
- sprintf(statusStr, " DESTROYED:");
- else if (getTeam() && Team::noPain[getTeamId()])
- sprintf(statusStr, " NO PAIN:");
- else
- sprintf(statusStr, ":");
- }
- else {
- if (isDestroyed())
- sprintf(statusStr, " *** DESTROYED:");
- else if (getTeam() && Team::noPain[getTeamId()])
- sprintf(statusStr, " *** NO PAIN:");
- else
- sprintf(statusStr, " ***:");
- }
- if (getObjectClass() == BATTLEMECH)
- sprintf(s, "[%.2f] mech.handleWeaponHit%s (%05d)%s ",
- scenarioTime,
- statusStr,
- getPartId(),
- name);
- else
- sprintf(s, "[%.2f] vehicle.handleWeaponHit%s (%05d)%s ",
- scenarioTime,
- statusStr,
- getPartId(),
- name);
- CombatLog->write(s);
- GameObjectPtr attacker = ObjectManager->getByWatchID(shotInfo->attackerWID);
- if (attacker)
- sprintf(s, " attacker = (%05d)%s", attacker->getPartId(), attacker->getName());
- else
- sprintf(s, " attacker = (%05)<unknown WID>", shotInfo->attackerWID);
- CombatLog->write(s);
- sprintf(s, " weapon = (%03d)%s, hitLocation = (%d)%s, damage = %.2f, angle = %.2f",
- shotInfo->masterId, MasterComponent::masterList[shotInfo->masterId].getName(),
- shotInfo->hitLocation, (shotInfo->hitLocation > -1) ? locationStrings[shotInfo->hitLocation] : "none",
- shotInfo->damage,
- shotInfo->entryAngle);
- CombatLog->write(s);
- sprintf(s, " num weaponhits = %d", numWeaponHitsHandled);
- CombatLog->write(s);
- CombatLog->write(" ");
- }
- //----------------------------------------------------------------------------
- long Mover::clearWeaponFireChunks (long which) {
- long numChunks = numWeaponFireChunks[which];
- numWeaponFireChunks[which] = 0;
- return(numChunks);
- }
- //---------------------------------------------------------------------------
- long Mover::addWeaponFireChunk (long which, WeaponFireChunkPtr chunk) {
- if (numWeaponFireChunks[which] == MAX_WEAPONFIRE_CHUNKS)
- Fatal(0, " Mover::addWeaponFireChunk--Too many weaponfire chunks ");
- chunk->pack(this);
- WeaponFireChunk testChunk;
- testChunk.init();
- testChunk.data = chunk->data;
- testChunk.unpack(this);
- if (!chunk->equalTo(&testChunk)) {
- DebugWeaponFireChunk(chunk, &testChunk, this);
- Assert(false, 0, " Mover.addWeaponFireChunk: bad weaponfire chunk (save wfchunk.dbg file) ");
- }
- weaponFireChunks[which][numWeaponFireChunks[which]++] = chunk->data;
- return(numWeaponFireChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::addWeaponFireChunks (long which, unsigned long* packedChunkBuffer, long numChunks) {
- if ((numWeaponFireChunks[which] + numChunks) >= MAX_WEAPONFIRE_CHUNKS)
- Fatal(0, " Mover::addWeaponFireChunks--Too many weaponfire chunks ");
- #if 0
- memcpy(&weaponFireChunks[which][numWeaponFireChunks[which]], packedChunkBuffer, 4 * numChunks);
- numWeaponFireChunks[which] += numChunks;
- #else
- for (long i = 0; i < numChunks; i++) {
- weaponFireChunks[which][numWeaponFireChunks[which]++] = packedChunkBuffer[i];
- //---------------
- // FOR TESTING...
- WeaponFireChunk chunk;
- chunk.init();
- chunk.data = packedChunkBuffer[i];
- chunk.unpack(this);
- }
- #endif
- return(numWeaponFireChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::grabWeaponFireChunks (long which, unsigned long* packedChunkBuffer, long maxChunks) {
- long numChunks = numWeaponFireChunks[which];
- if (numChunks > maxChunks)
- numChunks = maxChunks;
- if (numChunks > 0) {
- for (long i = 0; i < numChunks; i++)
- packedChunkBuffer[i] = weaponFireChunks[which][i];
- //memcpy(packedChunkBuffer, weaponFireChunks[which], 4 * numWeaponFireChunks[which]);
- }
- numWeaponFireChunks[which] -= numChunks;
- return(numChunks);
- }
- //---------------------------------------------------------------------------
- long Mover::updateWeaponFireChunks (long which) {
- for (long i = 0; i < numWeaponFireChunks[which]; i++) {
- WeaponFireChunk chunk;
- chunk.init();
- chunk.data = weaponFireChunks[which][i];
- chunk.unpack(this);
- //-----------------
- // For debugging...
- CurMoverWeaponFireChunk = chunk;
- static float entryQuadTable[4] = {0.0, 180.0, -90.0, 90.0};
- long weaponIndex = chunk.weaponIndex + numOther;
- if (!isWeaponIndex(weaponIndex))
- continue;
- TargetRolo = chunk.targetType;
- if (chunk.targetType == 0 /*WEAPONFIRECHUNK_TARGET_MOVER*/) {
- GameObjectPtr target = (GameObjectPtr)MPlayer->moverRoster[chunk.targetId];
- //----------------------------------------------------------------------------
- // Mover targets could be NULL now, since we free them when they're destroyed.
- if (target)
- handleWeaponFire(weaponIndex,
- target,
- NULL,
- chunk.hit,
- entryQuadTable[chunk.entryAngle],
- chunk.numMissiles,
- chunk.hitLocation);
- }
- else if (chunk.targetType == 1 /*WEAPONFIRECHUNK_TARGET_TERRAIN*/) {
- GameObjectPtr target = ObjectManager->findByPartId(chunk.targetId);
- if (target == NULL) {
- DebugWeaponFireChunk (&chunk, NULL, this);
- Assert(false, 0, " Mover.updateWeaponFireChunks: NULL Terrain Target (save wfchunk.dbg file) ");
- }
- handleWeaponFire(weaponIndex,
- target,
- NULL,
- chunk.hit,
- entryQuadTable[chunk.entryAngle],
- chunk.numMissiles,
- chunk.hitLocation);
- }
- else if (chunk.targetType == 2 /*WEAPONFIRECHUNK_TARGET_TRAIN*/) {
- GameObjectPtr target = ObjectManager->findByPartId(chunk.targetId);
- if (target == NULL) {
- DebugWeaponFireChunk (&chunk, NULL, this);
- Assert(false, 0, " Mover.updateWeaponFireChunks: NULL Special Target (save wfchunk.dbg file) ");
- }
- handleWeaponFire(weaponIndex,
- target,
- NULL,
- chunk.hit,
- entryQuadTable[chunk.entryAngle],
- chunk.numMissiles,
- chunk.hitLocation);
- }
- else if (chunk.targetType == 3 /*WEAPONFIRECHUNK_TARGET_LOCATION*/) {
- Stuff::Vector3D targetPoint;
- targetPoint.x = (float)chunk.targetCell[1] * Terrain::worldUnitsPerCell + Terrain::worldUnitsPerCell / 2 - Terrain::worldUnitsMapSide / 2;
- targetPoint.y = (Terrain::worldUnitsMapSide / 2) - ((float)chunk.targetCell[0] * Terrain::worldUnitsPerCell) - Terrain::worldUnitsPerCell / 2;
- targetPoint.z = (float)land->getTerrainElevation(targetPoint);
- handleWeaponFire(weaponIndex, NULL, &targetPoint, chunk.hit, 0.0, chunk.numMissiles, 0);
- }
- else
- Fatal(0, " Mover.updateWeaponFireChunks: bad targetType ");
- }
- numWeaponFireChunks[which] = 0;
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long Mover::clearCriticalHitChunks (long which) {
- long numChunks = numCriticalHitChunks[which];
- numCriticalHitChunks[which] = 0;
- return(numChunks);
- }
- //---------------------------------------------------------------------------
- long Mover::addCriticalHitChunk (long which, long bodyLocation, long criticalSpace) {
- if (numCriticalHitChunks[which] == MAX_CRITICALHIT_CHUNKS)
- Fatal(0, " Mover::addCriticalHitChunk--Too many criticalhit chunks ");
- //-----------------------------------------------------------
- // Since the "chunk" is so simple, we'll just make it here...
- unsigned char chunkData = (unsigned char)((bodyLocation << 4) + criticalSpace);
- criticalHitChunks[which][numCriticalHitChunks[which]++] = chunkData;
- return(numCriticalHitChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::addCriticalHitChunks (long which, unsigned char* packedChunkBuffer, long numChunks) {
- if ((numCriticalHitChunks[which] + numChunks) >= MAX_CRITICALHIT_CHUNKS)
- Fatal(0, " Mover::addCriticalHitChunks--Too many criticalhit chunks ");
- memcpy(&criticalHitChunks[which][numCriticalHitChunks[which]], packedChunkBuffer, numChunks);
- numCriticalHitChunks[which] += numChunks;
- return(numCriticalHitChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::grabCriticalHitChunks (long which, unsigned char* packedChunkBuffer) {
- if (numCriticalHitChunks[which] > 0)
- memcpy(packedChunkBuffer, criticalHitChunks[which], numCriticalHitChunks[which]);
- return(numCriticalHitChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::updateCriticalHitChunks (long which) {
- numCriticalHitChunks[which] = 0;
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long Mover::clearRadioChunks (long which) {
- long numChunks = numRadioChunks[which];
- numRadioChunks[which] = 0;
- return(numChunks);
- }
- //---------------------------------------------------------------------------
- long Mover::addRadioChunk (long which, unsigned char msg) {
- if (numRadioChunks[which] == MAX_RADIO_CHUNKS)
- return(numRadioChunks[which]);
- //Fatal(0, " Mover::addRadioChunk--Too many radio chunks ");
- //-----------------------------------------------------------
- // Since the "chunk" is so simple, we'll just make it here...
- radioChunks[which][numRadioChunks[which]++] = msg;
- return(numRadioChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::addRadioChunks (long which, unsigned char* packedChunkBuffer, long numChunks) {
- // if ((numRadioChunks[which] + numChunks) >= MAX_RADIO_CHUNKS)
- // Fatal(0, " Mover::addRadioChunks--Too many radio chunks ");
- for (long i = 0; i < numChunks; i++)
- addRadioChunk(which, packedChunkBuffer[i]);
- //memcpy(&radioChunks[which][numRadioChunks[which]], packedChunkBuffer, numChunks);
- //numRadioChunks[which] += numChunks;
- return(numRadioChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::grabRadioChunks (long which, unsigned char* packedChunkBuffer) {
- if (numRadioChunks[which] > 0)
- memcpy(packedChunkBuffer, radioChunks[which], numRadioChunks[which]);
- return(numRadioChunks[which]);
- }
- //---------------------------------------------------------------------------
- long Mover::updateRadioChunks (long which) {
- if (getCommander() == Commander::home)
- for (long i = 0; i < numRadioChunks[which]; i++)
- playMessage((RadioMessageType)radioChunks[which][i]);
- numRadioChunks[which] = 0;
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- void Mover::playMessage (RadioMessageType messageId, bool propogateIfMultiplayer) {
- if (pilot)
- pilot->radioMessage(messageId, propogateIfMultiplayer);
- }
- //---------------------------------------------------------------------------
- void Mover::setThreatRating (short rating) {
- threatRating = rating;
- if (threatRating == -1) {
- //-----------
- // Calc it...
- threatRating = calcCV();
- }
- }
- //---------------------------------------------------------------------------
- long Mover::getThreatRating (void) {
- if ((scenarioTime - creationTime) < 5.0)
- return((long)((float)threatRating * newThreatMultiplier));
- return(threatRating);
- }
- //---------------------------------------------------------------------------
- bool Mover::enemyRevealed (void)
- {
- //-----------------------------------------------------
- // What is our block and vertex number?
- //NOTE: This function not used Anymore!!
- return(false);
- }
- //---------------------------------------------------------------------------
- #if 0
- void Mover::getDamageClass (long& damageClass, bool& shutDown) {
- //--------------------------------------------
- // DamageClass is based upon the current CV...
- float CV = (float)curCV / (float)maxCV;
- if (CV > 0.90)
- damageClass = DAMAGE_CLASS_NONE;
- else if (CV > 0.75)
- damageClass = DAMAGE_CLASS_LIGHT;
- else if (CV > 0.50)
- damageClass = DAMAGE_CLASS_MODERATE;
- else if (CV > 0.10)
- damageClass = DAMAGE_CLASS_SEVERE;
- else
- damageClass = DAMAGE_CLASS_WRECKAGE;
- //--------------------------------------------
- // Is the mech currently shutdown due to heat?
- shutDown = (status == OBJECT_STATUS_SHUTDOWN);
- }
- #endif
- //------------------------------------------------------------------------------------------
- void Mover::setTeleportPosition (Stuff::Vector3D& newPos) {
- teleportPosition = newPos;
- }
- //------------------------------------------------------------------------------------------
- long Mover::getInventoryDamage (long itemIndex) {
- if (itemIndex < (numOther + numWeapons + numAmmos))
- return (MasterComponent::masterList[inventory[itemIndex].masterID].getHealth() - inventory[itemIndex].health);
- return(0);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getVisualRange (void) {
- return(MechWarrior::maxVisualRadius);
- }
- //------------------------------------------------------------------------------------------
- void Mover::setChallenger (GameObjectPtr challenger) {
- challengerWID = challenger->getWatchID();
- }
- //------------------------------------------------------------------------------------------
- GameObjectPtr Mover::getChallenger (void) {
- //------------------------------------------------------
- // We ASSUME a disabled challenger is as good as none...
- GameObjectPtr obj = ObjectManager->get(challengerWID);
- if (obj && obj->isDisabled()) {
- challengerWID = 0;
- return(NULL);
- }
- return(obj);
- }
- //------------------------------------------------------------------------------------------
- Stuff::Vector3D Mover::calcOffsetMoveGoal (Stuff::Vector3D target) {
- Stuff::Vector3D start = getPosition();
- Stuff::Vector2DOf<float> start2d;
- start2d.x = start.x;
- start2d.y = start.y;
- Stuff::Vector2DOf<float> target2d;
- target2d.x = target.x;
- target2d.y = target.y;
- //---------------------------------------------------------------
- // First, we need to calc the delta vector--how much we extend
- // the ray everytime we check the map cell for clear placement.
- Stuff::Vector2DOf<float> deltaVector;
- deltaVector.Subtract(start2d, target2d);
- if ((deltaVector.x == 0.0) && (deltaVector.y == 0.0)) {
- return(start);
- }
- deltaVector.Normalize(deltaVector);
- float cellLength = (Terrain::worldUnitsPerCell);
- cellLength *= 0.5;
- deltaVector *= cellLength;
- //if (deltaVector.GetLength() == 0.0) {
- // newGoal = start;
- // return(NO_ERR);
- //}
- //------------------------------------------
- // Determine how far the ray must be cast...
- float distanceToTarget = distance_from(start, target) /* * metersPerWorldUnit*/;
- //------------------------------------------------------------
- // We'll start at the target, and if it's blocked, we'll move
- // toward our start location, looking for the first valid/open
- // cell...
- Stuff::Vector2DOf<float> curPoint;
- curPoint.x = target.x;
- curPoint.y = target.y;
- Stuff::Vector2DOf<float> curRay;
- curRay.x = 0.0;
- curRay.y = 0.0;
- float rayLength = 0.0;
- long cellR, cellC;
- Stuff::Vector3D curPoint3d(curPoint.x, curPoint.y, 0.0);
- land->worldToCell(curPoint3d, cellR, cellC);
- if (!GameMap->getPassable(cellR, cellC))
- while (rayLength < distanceToTarget) {
- curPoint3d.x = curPoint.x;
- curPoint3d.y = curPoint.y;
- curPoint3d.z = 0.0;
- land->worldToCell(curPoint3d, cellR, cellC);
- if (GameMap->getPassable(cellR, cellC))
- break;
- curPoint += deltaVector;
- curRay.Subtract(curPoint, start2d);
- rayLength = curRay.GetLength() /* * metersPerWorldUnit*/;
- }
- curPoint3d.z = land->getTerrainElevation(curPoint3d);
- return(curPoint3d);
- }
- //---------------------------------------------------------------------------
- #define MAX_MOVE_GOALS 60
- inline void insertMoveGoal (long goalList[MAX_MOVE_GOALS][3], long r, long c, long wt) {
- //------------------------------------------------------------
- // This routine assumes wt > goaList[MAX_MOVE_GOALS - 1][2]...
- // AND that MAX_MOVE_GOALS >= 2...
- for (long i = MAX_MOVE_GOALS - 2; i > -1; i--)
- if (wt < goalList[i][2])
- break;
- if (i < (MAX_MOVE_GOALS - 2))
- memmove(&goalList[i + 2][0], &goalList[i + 1][0], (MAX_MOVE_GOALS - 2 - i) * sizeof(long) * 3);
- goalList[i + 1][0] = r;
- goalList[i + 1][1] = c;
- goalList[i + 1][2] = wt;
- }
- //---------------------------------------------------------------------------
- inline bool inMapBounds (long r, long c, long mapHeight, long mapWidth) {
- return((r >= 0) && (r < mapHeight) && (c >= 0) && (c < mapWidth));
- }
- //---------------------------------------------------------------------------
- long calcBestGoalFromTarget (long targetPos[2], long maxPos[2], float minRange, float bestRange, long* bestCell) {
- float startLocal = 40.0f;
- //------------------------------------------------------------------------------------------
- // Within magic radius. Check REAL LOS now.
- // Check is really simple.
- // Find deltaCellRow and deltaCellCol and iterate over them from source to dest.
- // If the magic line ever goes BELOW the terrainElevation PLUS localElevation return false.
- Stuff::Vector3D startPos, endPos;
- startPos.Zero();
- endPos.Zero();
-
- land->getCellPos(maxPos[0], maxPos[1], endPos);
- land->getCellPos(targetPos[0], targetPos[1], startPos);
- Stuff::Vector3D deltaCellVec;
- deltaCellVec.y = maxPos[0] - targetPos[0];
- deltaCellVec.x = maxPos[1] - targetPos[1];
- deltaCellVec.z = 0.0f;
- float startHeight = startPos.z;
- float cellLength = (Terrain::worldUnitsPerCell * metersPerWorldUnit);
- float length = deltaCellVec.GetApproximateLength();
- long lastCellR = -1;
- long lastCellC = -1;
- if (length > Stuff::SMALL) {
- float colLength = deltaCellVec.x / length;
- float rowLength = deltaCellVec.y / length;
- float heightLen = (endPos.z - startPos.z) / length;
-
- float lastCol = fabs(colLength * 2.0);
- float lastRow = fabs(rowLength * 2.0);
-
- float startCellRow = targetPos[0];
- float startCellCol = targetPos[1];
-
- float endCellRow = maxPos[0];
- float endCellCol = maxPos[1];
-
- Stuff::Vector3D currentPos = startPos;
- Stuff::Vector3D dist;
- dist.Subtract(endPos,currentPos);
-
- float remainingDist = dist.GetApproximateLength();
- float bestRemainingDist = remainingDist - (bestRange * worldUnitsPerMeter);
- bool colDone = false, rowDone = false;
- while (!colDone || !rowDone) {
- if (fabs(startCellRow - endCellRow) > lastRow) //DO NOT INCLUDE LAST CELL!!!!!
- startCellRow += rowLength;
- else {
- startCellRow = (endCellRow - lastRow);
- rowDone = true;
- }
-
- if (fabs(startCellCol - endCellCol) > lastCol) //DO NOT INCLUDE LAST CELL!!!!!
- startCellCol += colLength;
- else {
- startCellCol = (endCellCol - lastCol);
- colDone = true;
- }
- startHeight += heightLen;
-
- long startCellC = startCellCol;
- long startCellR = startCellRow;
- land->getCellPos(startCellR,startCellC,currentPos);
- float localElev = (worldUnitsPerMeter * (float)GameMap->getLocalHeight(startCellR,startCellC));
- currentPos.z += localElev;
-
- if (startHeight+startLocal < currentPos.z)
- if (GameMap->inBounds(lastCellR, lastCellC) && GameMap->getCell(lastCellR, lastCellC)->getPassable()) {
- bestCell[0] = lastCellR;
- bestCell[1] = lastCellC;
- return(1);
- }
- dist.Subtract(endPos,currentPos);
- remainingDist = dist.GetApproximateLength();
- if (fabs(remainingDist - bestRemainingDist) < cellLength)
- if (remainingDist > bestRemainingDist)
- if (GameMap->inBounds(startCellR, startCellC) && GameMap->getCell(startCellR, startCellC)->getPassable()) {
- bestCell[0] = startCellR;
- bestCell[1] = startCellC;
- return(1);
- }
- if (remainingDist < 10.0) {
- if (GameMap->inBounds(startCellR, startCellC) && GameMap->getCell(startCellR, startCellC)->getPassable()) {
- bestCell[0] = startCellR;
- bestCell[1] = startCellC;
- return(1);
- }
- else
- return(0);
- }
- if (GameMap->inBounds(startCellR, startCellC) && GameMap->getCell(startCellR, startCellC)->getPassable()) {
- //-----------------------------------------------------------
- // Save the last passable cell checked so far that has LOS...
- lastCellR = startCellR;
- lastCellC = startCellC;
- }
- }
- }
- if (lastCellR != -1) {
- bestCell[0] = lastCellR;
- bestCell[1] = lastCellC;
- return(1);
- }
- return(0);
- }
- //----------------------------------------------------------------------------
- long Mover::calcLineOfSightView (long range) {
- GameMap->clearCellDebugs(1);
- for (long r = cellPositionRow - range; r < cellPositionRow + range; r++)
- for (long c = cellPositionCol - range; c < cellPositionCol + range; c++) {
- if (GameMap->inBounds(r, c)) {
- if (lineOfSight(r, c, false))
- GameMap->setCellDebug(r, c, 1, 1);
- else {
- GameMap->setCellDebug(r, c, 2, 1);
- }
- }
- }
- return(0);
- }
- //----------------------------------------------------------------------------
- void Mover::setMoveType (long type) {
- moveType = type;
- //--------------------------------------------------------------------
- // For now, level = type. This can change in the future, so always set
- // it here!
- if (moveType == MOVETYPE_GROUND)
- moveLevel = 0;
- else if (moveType == MOVETYPE_AIR)
- moveLevel = 2;
- else
- STOP(("Mover.setMoveType: bad moveType %d", type));
- }
- //-----------------------------------------------------------------------------
- //void Mover::precalcAttackZones (void) {
- //}
- //-----------------------------------------------------------------------------
- long Mover::calcGlobalPath (GlobalPathStep* globalPath, GameObjectPtr obj, Stuff::Vector3D* location, bool useClosedAreas) {
- #if 1
- long startArea = GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol);
- long goalArea = -1;
- long goalCell[2] = {-1, -1};
- if (obj) {
- goalArea = GlobalMoveMap[moveLevel]->calcArea(obj->cellPositionRow, obj->cellPositionCol);
- if (goalArea == -1) {
- Stuff::Vector3D goalPos = obj->getPosition();
- if (obj->isBuilding()) {
- BuildingPtr building = (BuildingPtr)obj;
- long goalRow = 0, goalCol = 0;
- bool foundGoal = building->calcAdjacentAreaCell(moveLevel, -1, goalRow, goalCol);
- if (foundGoal)
- land->cellToWorld(goalRow, goalCol, goalPos);
- else {
- Stuff::Vector3D objectPos = obj->getPosition();
- goalPos = calcOffsetMoveGoal(objectPos);
- }
- }
- else {
- Stuff::Vector3D objectPos = obj->getPosition();
- goalPos = calcOffsetMoveGoal(objectPos);
- }
- land->worldToCell(goalPos, goalCell[0], goalCell[1]);
- goalArea = GlobalMoveMap[moveLevel]->calcArea(goalCell[0], goalCell[1]);
- }
- }
- else if (location) {
- land->worldToCell(*location, goalCell[0], goalCell[1]);
- goalArea = GlobalMoveMap[moveLevel]->calcArea(goalCell[0], goalCell[1]);
- }
- if (goalArea == -1)
- return(0);
- bool startAreaOpen = (startArea >= 0) && GlobalMoveMap[moveLevel]->areas[startArea].open;
- long numSteps = -1;
- if (startAreaOpen) {
- if (numFunctionalWeapons > 0)
- GlobalMoveMap[moveLevel]->useClosedAreas = useClosedAreas;
- GlobalMoveMap[moveLevel]->moverTeamID = getTeamId();
- numSteps = GlobalMoveMap[moveLevel]->calcPath(startArea,
- goalArea,
- globalPath,
- cellPositionRow,
- cellPositionCol,
- goalCell[0],
- goalCell[1]
- );
- GlobalMoveMap[moveLevel]->useClosedAreas = false;
- }
- return(numSteps);
- #else
- return(0);
- #endif
- }
- //-----------------------------------------------------------------------------
- bool Mover::canMoveHere (Stuff::Vector3D worldPos) {
- //-------------------------------------------
- // If I'm a coptor, terrain doesn't matter...
- if (moveLevel == 2)
- return(true);
- if (!GameMap->getPassable(worldPos))
- return(false);
- //---------------------------------------------------------------
- // If I'm a hovercraft and this cell is passable, I know I can...
- if (moveLevel == 1)
- return(true);
- //--------------------------------------------------------
- // Otherwise, I'm a ground mover and there may be water...
- return(land->getWater(worldPos) < 2);
- }
- //-----------------------------------------------------------------------------
- #ifdef LAB_ONLY
- extern __int64 MCTimeCalcGoal1Update;
- extern __int64 MCTimeCalcGoal2Update;
- extern __int64 MCTimeCalcGoal3Update;
- extern __int64 MCTimeCalcGoal4Update;
- extern __int64 MCTimeCalcGoal5Update;
- extern __int64 MCTimeCalcGoal6Update;
- #endif
- long Mover::calcMoveGoal (GameObjectPtr target,
- Stuff::Vector3D moveCenter,
- float moveRadius,
- Stuff::Vector3D moveGoal,
- long selectionIndex,
- Stuff::Vector3D& newGoal,
- long numValidAreas,
- short* validAreas,
- unsigned long moveParams) {
- __int64 startTime = 0;
- if (goalMapRowStart[0] == -1) {
- for (long i = 0; i < GOALMAP_CELL_DIM; i++)
- goalMapRowStart[i] = i * GOALMAP_CELL_DIM;
- for (long r = 0; r < GOALMAP_CELL_DIM; r++)
- for (long c = 0; c < GOALMAP_CELL_DIM; c++) {
- long index = r * GOALMAP_CELL_DIM + c;
- goalMapRowCol[index][0] = r;
- goalMapRowCol[index][1] = c;
- }
- }
- bool playerMove = ((moveParams & MOVEPARAM_PLAYER) != 0);
- bool movingToRepair = (pilot->getCurTacOrder()->code == TACTICAL_ORDER_REFIT);
- bool movingToCapture = (pilot->getCurTacOrder()->code == TACTICAL_ORDER_CAPTURE);
- bool avoidStationaryMovers = movingToRepair;
- bool noTravelOffMap = !GameMap->getOffMap(cellPositionRow, cellPositionCol);
- if (moveParams & MOVEPARAM_MYSTERY_PARAM) {
- newGoal = moveGoal;
- return(NO_ERR);
- }
- if (moveParams & MOVEPARAM_STEP_TOWARD_TARGET) {
- //--------------------------------------------------------------------------
- // We want to pick a goal just a couple cells away from our position, but in
- // the direction of our target...
- Stuff::Vector3D aimVector;
- aimVector.Subtract(moveGoal, position);
- aimVector.z = 0;
- if (aimVector.GetLength() > 0.0) {
- aimVector.Normalize(aimVector);
- float stepLength = (Terrain::worldUnitsPerVertex * 1.5);
- aimVector.x *= stepLength;
- aimVector.y *= stepLength;
- aimVector.z = land->getTerrainElevation(aimVector);
- Stuff::Vector3D targetGoal;
- targetGoal.Add(position, aimVector);
- newGoal = calcOffsetMoveGoal(targetGoal);
- }
- return(NO_ERR);
- }
- if (moveParams & MOVEPARAM_STEP_ADJACENT_TARGET) {
- //--------------------------------------------------------------------------
- // We want to pick a goal just a couple cells away from our position, but in
- // the direction of our target...
- newGoal = calcOffsetMoveGoal(moveGoal);
- return(NO_ERR);
- }
-
- //----------------------------
- // The Goal Map is in CELLS...
- memset(goalMap, 0, sizeof(long) * GOALMAP_CELL_DIM * GOALMAP_CELL_DIM);
- long centerCell[2];
- land->worldToCell(moveCenter, centerCell[0], centerCell[1]);
- long goalCell[2];
- land->worldToCell(moveGoal, goalCell[0], goalCell[1]);
- long mapCellUL[2];
- mapCellUL[0] = centerCell[0] - GOALMAP_CELL_DIM / 2;
- mapCellUL[1] = centerCell[1] - GOALMAP_CELL_DIM / 2;
-
- //DEBUG
- //=================================
- Stuff::Vector3D start;
- land->cellToWorld(mapCellUL[0], mapCellUL[1], start);
- //==============================
- bool isAttackOrder = pilot->getCurTacOrder()->isCombatOrder();
- if (!target && !isAttackOrder) {
- newGoal = calcOffsetMoveGoal(moveGoal);
- return(NO_ERR);
- }
- //--------
- // HACK!!!
- if (target && (pilot->getCurTacOrder()->code == TACTICAL_ORDER_GUARD))
- isAttackOrder = true;
- if (!target)
- moveGoal.z = land->getTerrainElevation(moveGoal);
- long optimalCellRange = 2;
- if (movingToRepair)
- optimalCellRange = 1;
- if (isAttackOrder) {
- float metersPerCell = Terrain::worldUnitsPerCell * metersPerWorldUnit;
- float fireRangeInMeters = pilot->getSituationFireRange();
- long fireCellRange = 0;
- if (fireRangeInMeters > 0.0) {
- fireCellRange = (long)(pilot->getSituationFireRange() / metersPerCell);
- if (fireCellRange < 1)
- fireCellRange = 1;
- if (fireCellRange > (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/)
- fireCellRange = (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/;
- }
- else if (fireRangeInMeters == -1.0)
- fireCellRange = 2;
- long minCellRange = (long)(getMinFireRange() / metersPerCell);
- if (minCellRange > (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/)
- minCellRange = (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/;
- long maxCellRange = (long)(getMaxFireRange() / metersPerCell);
- if (maxCellRange > (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/)
- maxCellRange = (MAX_ATTACK_CELLRANGE - 1)/*(GOALMAP_CELL_DIM / 2)*/;
- //----------------------------------------
- // Anything beyond our max range is bad...
- long fireRange = (long)pilot->getCurTacOrder()->attackParams.range;
- if (/*!playerMove && */(fireRange != FIRERANGE_SHORT) && (fireRange != FIRERANGE_MEDIUM) && (fireRange != FIRERANGE_LONG)) {
- long firstIndex = rangedCellsIndices[maxCellRange + 1][0];
- long lastIndex = rangedCellsIndices[MAX_ATTACK_CELLRANGE - 1][1];
- for (long i = firstIndex; i < lastIndex; i++) {
- long r = goalCell[0] - mapCellUL[0] + rangedCells[i][0];
- long c = goalCell[1] - mapCellUL[1] + rangedCells[i][1];
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] -= 500;
- }
- }
- //---------------------------------------------------
- // If we have a max move radius (i.e. guarding area),
- // anything beyond our radius is bad...
- startTime = GetCycles();
- if (moveRadius > 0.0) {
- long moveCellRange = moveRadius / metersPerCell;
- if (moveCellRange < 1)
- moveCellRange = 1;
- if (moveCellRange > (MAX_ATTACK_CELLRANGE - 1))
- moveCellRange = (MAX_ATTACK_CELLRANGE - 1);
- long firstIndex = rangedCellsIndices[moveCellRange + 1][0];
- long lastIndex = rangedCellsIndices[MAX_ATTACK_CELLRANGE - 1][1];
- for (long i = firstIndex; i < lastIndex; i++) {
- long r = centerCell[0] - mapCellUL[0] + rangedCells[i][0];
- long c = centerCell[1] - mapCellUL[1] + rangedCells[i][1];
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] -= 5000;
- }
- }
- #ifdef LAB_ONLY
- MCTimeCalcGoal2Update += (GetCycles() - startTime);
- #endif
- //---------------------------------------------------------------------------
- // If the pilot has a set fire range, let's use it in determining how far out
- // we would consider attacking. If we're ramming, fireCellrange will stay at
- // 0 since firerange would then be 0.0...
- if (fireRangeInMeters > 0.0) {
- //---------------------------------------------------------------
- // Due to new minimum range rule, we do NOT want to be within our
- // min range...
- if (minCellRange > 0) {
- long lastIndex = rangedCellsIndices[minCellRange][0];
- for (long i = 0; i < lastIndex; i++) {
- long r = goalCell[0] - mapCellUL[0] + rangedCells[i][0];
- long c = goalCell[1] - mapCellUL[1] + rangedCells[i][1];
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] -= 500;
- }
- }
- }
- else if (fireRangeInMeters == -1.0)
- fireCellRange = 2;
- optimalCellRange = fireCellRange;
- }
- //-----------------------------------------------------------------------
- // Optimal Range (based upon current fire range of pilot, if possible)...
- if (moveParams & MOVEPARAM_RANDOM_OPTIMAL)
- for (long i = 0; i < numOptimalIncrements; i++) {
- long r = goalCell[0] - mapCellUL[0] + optimalCells[optimalCellRange][i][0];
- long c = goalCell[0] - mapCellUL[0] + optimalCells[optimalCellRange][i][1];
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] += (500 + RandomNumber(40) * 5);
- }
- else
- for (long i = 0; i < numOptimalIncrements; i++) {
- long r = goalCell[0] - mapCellUL[0] + optimalCells[optimalCellRange][i][0];
- long c = goalCell[0] - mapCellUL[0] + optimalCells[optimalCellRange][i][1];
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] += 500;
- }
- //--------------------------------------
- // Calc the closest map cell to start...
- long startCell[2];
- land->worldToCell(position, startCell[0], startCell[1]);
- startCell[0] -= mapCellUL[0];
- startCell[1] -= mapCellUL[1];
- if (startCell[0] < 0)
- startCell[0] = 0;
- else if (startCell[0] >= GOALMAP_CELL_DIM)
- startCell[0] = GOALMAP_CELL_DIM - 1;
- if (startCell[1] < 0)
- startCell[1] = 0;
- else if (startCell[1] >= GOALMAP_CELL_DIM)
- startCell[1] = GOALMAP_CELL_DIM - 1;
- //---------------------------------------------------------------------------
- //NOTE: Do we even want the following, now? I think this was more a hack than
- //anything. Take it out and see what effect it has... -gd 7/24/00
- //--------------------------------------------------------------
- // The closer we are to the goal, the better (within reason:)...
- if (!playerMove)
- for (long cellR = -1; cellR < 2; cellR++)
- for (long cellC = -1; cellC < 2; cellC++) {
- long r = goalCell[0] - mapCellUL[0] + cellR;
- long c = goalCell[1] - mapCellUL[1] + cellC;
- if (inMapBounds(r, c, GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[r] + c] += 100;
- }
- //----------------------------------
- // If we must move somewhere else...
- if (moveParams & MOVEPARAM_SOMEWHERE_ELSE)
- goalMap[goalMapRowStart[startCell[0]] + startCell[1]] -= 10000;
- //-------------------------------------
- // Cells closer to the start cell get a
- // slight bonus...
- for (long r = 0; r < GOALMAP_CELL_DIM; r++)
- for (long c = 0; c < GOALMAP_CELL_DIM; c++) {
- long dist = 0;
- if (r > startCell[0])
- dist += (r - startCell[0]);
- else
- dist += (startCell[0] - r);
- if (c > startCell[1])
- dist += (c - startCell[1]);
- else
- dist += (startCell[1] - c);
- goalMap[goalMapRowStart[r] + c] -= (dist * 1);
- }
- //----------------------------------------------------------------------
- // If we're attacking this target, let's use a selectionIndex based upon
- // the number of people in my unit attacking this target...
- if (getGroup()) {
- MoverPtr mates[MAX_MOVERGROUP_COUNT];
- long numMates = getGroup()->getMovers(mates);
- for (long i = 0; i < numMates; i++) {
- if (mates[i] == this)
- continue;
- MechWarriorPtr pilot = mates[i]->getPilot();
- Stuff::Vector3D goal;
- goal.x = goal.y = goal.z = 0.0f;
- if (pilot && pilot->getMoveGlobalGoal(goal)) {
- long worldCell[2];
- land->worldToCell(goal, worldCell[0], worldCell[1]);
- worldCell[0] -= mapCellUL[0];
- worldCell[1] -= mapCellUL[1];
- if (inMapBounds(worldCell[0], worldCell[1], GOALMAP_CELL_DIM, GOALMAP_CELL_DIM))
- goalMap[goalMapRowStart[worldCell[0]] + worldCell[1]] -= 100;
- }
- }
- }
- //-----------------------
- // Init the area lists...
- char validAreaTable[MAX_GLOBALMAP_AREAS];
- for (long i = 0; i < GlobalMoveMap[moveLevel]->numAreas; i++)
- validAreaTable[i] = -1;
- long curArea = GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol);
- long goalArea = GlobalMoveMap[moveLevel]->calcArea(goalCell[0], goalCell[1]);
- if (numValidAreas > 0) {
- for (long i = 0; i < numValidAreas; i++) {
- if (validAreas[i] == goalArea) {
- numValidAreas = i + 1;
- break;
- }
- }
- }
- for (i = 0; i < numValidAreas; i++)
- validAreaTable[validAreas[i]] = 1;
- startTime = GetCycles();
- long deepWaterWeight = ((moveLevel == 1) ? 0 : 999999);
- //-----------------------------------------
- // Finally, lay down the terrain weights...
- for (r = 0; r < GOALMAP_CELL_DIM; r++)
- for (long c = 0; c < GOALMAP_CELL_DIM; c++) {
- long curCellRow = mapCellUL[0] + r;
- long curCellCol = mapCellUL[1] + c;
- if (GameMap->inBounds(curCellRow, curCellCol))
- {
- //------------------------------------------------------------
- // In the long run, we should simply have a look-up table that
- // contains a weight for each terrain\tile type (including
- // transitions)...
- MapCellPtr mapCell = GameMap->getCell(curCellRow, curCellCol);
- //-----------------------
- // Tile (terrain) type...
- //long tileType = curTile.getTileType();
- long goalMapIndex = goalMapRowStart[r] + c;
- if (!mapCell->getPassable())
- goalMap[goalMapIndex] -= 10000;
- if (mapCell->getOffMap())
- goalMap[goalMapIndex] -= 10000;
- if (mapCell->getDeepWater())
- goalMap[goalMapIndex] -= deepWaterWeight;
- bool moverHere = mapCell->getMover();
- if (avoidStationaryMovers && moverHere)
- goalMap[goalMapIndex] -= 1000;
- if (noTravelOffMap && GameMap->getOffMap(curCellRow, curCellCol))
- goalMap[goalMapIndex] -= 50000;
- long area = GlobalMoveMap[moveLevel]->calcArea(curCellRow, curCellCol);
- if ((area != curArea) && (area != -1) && (curArea != -1)) {
- if (moveLevel < 2) {
- //if (GlobalMoveMap[moveLevel]->areas[area].type == AREA_TYPE_NORMAL) {
- if (GlobalMoveMap[moveLevel]->getPathExists(curArea, area) == GLOBALPATH_EXISTS_UNKNOWN) {
- if (CalcValidAreaTable) {
- GlobalPathStep globalPath[128];
- long numSteps = GlobalMoveMap[moveLevel]->calcPath(curArea, area, globalPath);
- if (numSteps > 0) {
- for (long j = 0; j < numSteps; j++)
- for (long k = 0; k < numSteps; k++)
- GlobalMoveMap[moveLevel]->setPathExists(globalPath[j].thruArea, globalPath[k].thruArea, GLOBALPATH_EXISTS_TRUE);
- }
- else {
- GlobalMoveMap[moveLevel]->setPathExists(area, curArea, GLOBALPATH_EXISTS_FALSE);
- GlobalMoveMap[moveLevel]->setPathExists(curArea, area, GLOBALPATH_EXISTS_FALSE);
- }
- }
- else
- GlobalMoveMap[moveLevel]->setPathExists(curArea, area, GLOBALPATH_EXISTS_FALSE);
- }
- if (GlobalMoveMap[moveLevel]->getPathExists(curArea, area) == GLOBALPATH_EXISTS_FALSE)
- goalMap[goalMapRowStart[r] + c] -= 50000;
- //}
- }
- }
- }
- else
- goalMap[goalMapRowStart[r] + c] = -999999;
- }
- #ifdef LAB_ONLY
- MCTimeCalcGoal1Update += (GetCycles() - startTime);
- #endif
- startTime = GetCycles();
- long goalList[MAX_MOVE_GOALS][2];
- //------------------
- // Setup the list...
- for (i = 0; i < MAX_MOVE_GOALS; i++) {
- goalList[i][0] = -1;
- goalList[i][1] = -99999;
- }
- for (i = 0; i < MAX_MOVE_GOALS; i++) {
- //-----------------------------------------
- // This assumes that MAX_MOVE_GOALS >= 2...
- long weight = goalMap[i];
- for (long j = MAX_MOVE_GOALS - 2; j > -1; j--)
- if (weight < goalList[j][1])
- break;
- if (j < (MAX_MOVE_GOALS - 2))
- memmove(&goalList[j + 2][0], &goalList[j + 1][0], (MAX_MOVE_GOALS - 2 - j) * sizeof(long) * 2);
- goalList[j + 1][0] = i;
- goalList[j + 1][1] = weight;
- }
- for (i = MAX_MOVE_GOALS; i < (GOALMAP_CELL_DIM * GOALMAP_CELL_DIM); i++) {
- //------------------------------------------------------------
- // This routine assumes wt > goaList[MAX_MOVE_GOALS - 1][2]...
- // AND that MAX_MOVE_GOALS >= 2...
- long weight = goalMap[i];
- if (weight > goalList[MAX_MOVE_GOALS - 1][1]) {
- for (long j = MAX_MOVE_GOALS - 2; j > -1; j--)
- if (weight < goalList[j][1])
- break;
- if (j < (MAX_MOVE_GOALS - 2))
- memmove(&goalList[j + 2][0], &goalList[j + 1][0], (MAX_MOVE_GOALS - 2 - j) * sizeof(long) * 2);
- goalList[j + 1][0] = i;
- goalList[j + 1][1] = weight;
- }
- }
- #ifdef LAB_ONLY
- MCTimeCalcGoal3Update += (GetCycles() - startTime);
- #endif
- //----------------------------------------------------------------------
- // If we're attacking this target, let's use a selectionIndex based upon
- // the number of people in my unit attacking this target...
- //#ifdef USE_GROUPS
- if ((getObjectClass() == ELEMENTAL) && target && getGroup()) {
- MoverPtr mates[MAX_MOVERGROUP_COUNT];
- long numMates = getGroup()->getMovers(mates);
- selectionIndex = 0;
- for (long i = 0; i < numMates; i++) {
- if (mates[i] == this)
- break;
- MechWarriorPtr pilot = mates[i]->getPilot();
- if (pilot) {
- if (pilot->getCurrentTarget() == target)
- selectionIndex++;
- }
- }
- }
- //#endif
- //---------------------------------
- // so they don't select wacky goals
- selectionIndex = -1;
- //------------------------------
- // Now, pick the goal we want...
- long curGoalIndex = 0;
- if ((selectionIndex > 0) && (selectionIndex < MAX_MOVE_GOALS))
- curGoalIndex = selectionIndex;
- long curGoalCell[2];
- bool noLOF = true;
- curGoalCell[0] = mapCellUL[0] + goalMapRowCol[goalList[0][0]][0];
- curGoalCell[1] = mapCellUL[1] + goalMapRowCol[goalList[0][0]][1];
-
- //Stuff::Vector3D goalPos = moveGoal;
- //goalPos.z += target->getAppearRadius(); //Lets not look along the ground, shall we.
- //Target probably has some altitude
- if (hasWeaponNode()) {
- Stuff::Vector3D curMoverPosition;
- curMoverPosition = position;
- long curMoverRow = cellPositionRow;
- long curMoverCol = cellPositionCol;
- startTime = GetCycles();
- long i = 0;
- ObjectManager->useMoverLineOfSightTable = false;
- while (noLOF && (i < MaxMoveGoalChecks)) {
- long index = goalList[i][0];
- curGoalCell[0] = mapCellUL[0] + goalMapRowCol[index][0];
- curGoalCell[1] = mapCellUL[1] + goalMapRowCol[index][1];
- i++;
- if (goalList[i][1] > -900000) {
- Stuff::Vector3D start;
- land->cellToWorld(curGoalCell[0], curGoalCell[1], start);
- //start.x = (float)(mapCellUL[1] + curGoalCell[1]) * Terrain::worldUnitsPerCell + Terrain::worldUnitsPerCell / 2 - Terrain::worldUnitsMapSide / 2;
- //start.y = (Terrain::worldUnitsMapSide / 2) - ((float)(mapCellUL[0] + curGoalCell[0]) * Terrain::worldUnitsPerCell) - Terrain::worldUnitsPerCell / 2;
- start.z = land->getTerrainElevation(start)/* + 25.0f*/; //For that matter, so do we!
- position = start;
- cellPositionRow = curGoalCell[0];
- cellPositionCol = curGoalCell[1];
- __int64 lstartTime = GetCycles();
- if (goalList[i][1] > -10000) {
- if (movingToCapture)
- noLOF = false;
- else if (target)
- noLOF = !lineOfSight(target, 0.0f, false);
- else
- noLOF = !lineOfSight(moveGoal, false);
- }
- #ifdef LAB_ONLY
- MCTimeCalcGoal4Update += (GetCycles() - lstartTime);
- #endif
- }
- }
- #ifdef LAB_ONLY
- MCTimeCalcGoal5Update += (GetCycles() - startTime);
- #endif
- ObjectManager->useMoverLineOfSightTable = true;
- position = curMoverPosition;
- cellPositionRow = curMoverRow;
- cellPositionCol = curMoverCol;
- }
- GameMap->clearCellDebugs(2);
- startTime = GetCycles();
- if (noLOF && hasWeaponNode()) {
- long targetPos[2], maxPos[2], bestCell[4][2];
- float castRange;
- long result[4];
- long resultCost[4] = {0, 0, 0, 0};
- long confidence[4];
- long bestBest = 0;
- if (moveRadius > 0.0) {
- targetPos[0] = centerCell[0];
- targetPos[1] = centerCell[1];
- maxPos[0] = goalCell[0];
- maxPos[1] = goalCell[1];
- castRange = moveRadius;
- result[0] = calcBestGoalFromTarget(targetPos, maxPos, 0.0, castRange, bestCell[0]);
- if (result[0])
- resultCost[0] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol),GlobalMoveMap[moveLevel]->calcArea(bestCell[0][0], bestCell[0][1]), false, confidence[0], true);
- bestCell[1][0] = centerCell[0];
- bestCell[1][1] = centerCell[1];
- result[1] = 1;
- if (result[1])
- resultCost[1] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol),GlobalMoveMap[moveLevel]->calcArea(bestCell[1][0], bestCell[1][1]), false, confidence[1], true);
- if (resultCost[1] > 0)
- if (resultCost[1] < resultCost[bestBest])
- bestBest = 1;
- if (resultCost[bestBest] > 0) {
- curGoalCell[0] = bestCell[bestBest][0];
- curGoalCell[1] = bestCell[bestBest][1];
- }
- if (DebugGameObject[0] == this) {
- if (result[0])
- GameMap->setCellDebug(bestCell[0][0], bestCell[0][1], 3, 2);
- if (result[1])
- GameMap->setCellDebug(bestCell[1][0], bestCell[1][1], 3, 2);
- }
- }
- else {
- targetPos[0] = goalCell[0];
- targetPos[1] = goalCell[1];
- maxPos[0] = targetPos[0] - 10;
- maxPos[1] = targetPos[1];
- castRange = pilot->getSituationFireRange();
- long bestBest = 0;
- result[0] = calcBestGoalFromTarget(targetPos, maxPos, 0.0, castRange, bestCell[0]);
- if (result[0])
- resultCost[0] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol),GlobalMoveMap[moveLevel]->calcArea(bestCell[0][0], bestCell[0][1]), false, confidence[0], true);
- maxPos[0] = targetPos[0];
- maxPos[1] = targetPos[1] + 10;
- result[1] = calcBestGoalFromTarget(targetPos, maxPos, 0.0, pilot->getSituationFireRange(), bestCell[1]);
- if (result[1])
- resultCost[1] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol),GlobalMoveMap[moveLevel]->calcArea(bestCell[1][0], bestCell[1][1]), false, confidence[1], true);
- if (resultCost[1] > 0)
- if (resultCost[1] < resultCost[bestBest])
- bestBest = 1;
- maxPos[0] = targetPos[0] + 10;
- maxPos[1] = targetPos[1];
- result[2] = calcBestGoalFromTarget(targetPos, maxPos, 0.0, pilot->getSituationFireRange(), bestCell[2]);
- if (result[2])
- resultCost[2] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol), GlobalMoveMap[moveLevel]->calcArea(bestCell[2][0], bestCell[2][1]), false, confidence[2], true);
- if (resultCost[2] > 0)
- if (resultCost[2] < resultCost[bestBest])
- bestBest = 2;
- maxPos[0] = targetPos[0];
- maxPos[1] = targetPos[1] - 10;
- result[3] = calcBestGoalFromTarget(targetPos, maxPos, 0.0, pilot->getSituationFireRange(), bestCell[3]);
- if (result[3])
- resultCost[3] = GlobalMoveMap[moveLevel]->getPathCost(GlobalMoveMap[moveLevel]->calcArea(cellPositionRow, cellPositionCol),GlobalMoveMap[moveLevel]->calcArea(bestCell[3][0], bestCell[3][1]), false, confidence[3], true);
- if (resultCost[3] > 0)
- if (resultCost[3] < resultCost[bestBest])
- bestBest = 3;
- if (resultCost[bestBest] > 0) {
- curGoalCell[0] = bestCell[bestBest][0];
- curGoalCell[1] = bestCell[bestBest][1];
- }
- if (DebugGameObject[0] == this) {
- if (result[0])
- GameMap->setCellDebug(bestCell[0][0], bestCell[0][1], 3, 2);
- if (result[1])
- GameMap->setCellDebug(bestCell[1][0], bestCell[1][1], 3, 2);
- if (result[2])
- GameMap->setCellDebug(bestCell[2][0], bestCell[2][1], 3, 2);
- if (result[3])
- GameMap->setCellDebug(bestCell[3][0], bestCell[3][1], 3, 2);
- }
- }
- }
- GameMap->setCellDebug(curGoalCell[0], curGoalCell[1], 3, 2);
- #ifdef LAB_ONLY
- MCTimeCalcGoal6Update += (GetCycles() - startTime);
- #endif
- //--------------------------------------------
- // Let's calc the woorld coord of this cell...
- land->cellToWorld(curGoalCell[0], curGoalCell[1], newGoal);
- newGoal = calcOffsetMoveGoal(newGoal);
- //float distToGoal = distance_from(newGoal, goal) * metersPerWorldUnit;
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- long Mover::calcMovePath (MovePathPtr path,
- long pathType,
- Stuff::Vector3D start,
- Stuff::Vector3D goal,
- long* goalCell,
- unsigned long moveParams) {
- //-------------------------------------------------------------------------
- // This assumes the goal is already the "optimum" goal (it should have been
- // passed thru "calcMoveGoal" before being sent here)...
- if (!PathFindMap[SECTOR_PATHMAP] || !PathFindMap[SIMPLE_PATHMAP])
- Fatal(0, " No PathFindMap in Mover::calcMovePath ");
- long posCellR, posCellC;
- land->worldToCell(start, posCellR, posCellC);
- long goalCellR, goalCellC;
- land->worldToCell(goal, goalCellR, goalCellC);
- path->clear();
- long result = 0;
- if (pathType == MOVEPATH_SIMPLE) {
- long mapULr = posCellR - SimpleMovePathRange;
- if (mapULr < 0)
- mapULr = 0;
- long mapULc = posCellC - SimpleMovePathRange;
- if (mapULc < 0)
- mapULc = 0;
- float cellLength = (Terrain::worldUnitsPerCell * metersPerWorldUnit);
- long clearCost = 0;
- if (maxMoveSpeed != 0.0)
- clearCost = (float2short)(cellLength / maxMoveSpeed * 50.0);
- if (clearCost > 0) {
- long jumpCost = 0;
- long numOffsets = 8;
- if (!pilot->onHomeTeam() && !MPlayer)
- getJumpRange(&numOffsets, &jumpCost);
- #ifdef USE_ELEMENTALS
- if (getObjectClass() == ELEMENTAL) {
- GameObjectPtr target = pilot->getLastTarget();
- if (target && (distanceFrom(target->getPosition()) < ElementalTargetNoJumpDistance)) {
- jumpCost = 0;
- numOffsets = 8;
- }
- else
- JumpOnBlocked = true;
- }
- #endif
- if (isMineSweeper())
- moveParams |= MOVEPARAM_SWEEP_MINES;
- if (followRoads)
- moveParams |= MOVEPARAM_FOLLOW_ROADS;
- if (isMech())
- moveParams |= MOVEPARAM_WATER_SHALLOW;
- if (moveLevel == 1)
- moveParams |= (MOVEPARAM_WATER_SHALLOW + MOVEPARAM_WATER_DEEP);
- PathFindMap[SIMPLE_PATHMAP]->setMover(getWatchID(), getTeamId(), isLayingMines());
- PathFindMap[SIMPLE_PATHMAP]->setUp(mapULr,
- mapULc,
- SimpleMovePathRange * 2 + 1,
- SimpleMovePathRange * 2 + 1,
- moveLevel,
- &start,
- posCellR,
- posCellC,
- goal,
- goalCellR - mapULr,
- goalCellC - mapULc,
- clearCost,
- jumpCost,
- numOffsets,
- moveParams);
- //---------------------
- // Set up debug info...
- DebugMovePathType = pathType;
- long goalCell[2];
- if (numOffsets > 8)
- result = PathFindMap[SIMPLE_PATHMAP]->calcPathJUMP(path, NULL, goalCell);
- else
- result = PathFindMap[SIMPLE_PATHMAP]->calcPath(path, NULL, goalCell);
- PathFindMap[SIMPLE_PATHMAP]->setMover(0);
- JumpOnBlocked = false;
- }
- }
- else {
- //--------------------------------------------------------------------------------------
- // We are now assuming all local pathfinding will fit within two adjacent sectors.
- // So, we can assume both the start and goal locations are within the two adj sectors...
- float cellLength = (Terrain::worldUnitsPerCell * metersPerWorldUnit);
- long clearCost = 0;
- if (maxMoveSpeed != 0.0)
- clearCost = (long)(cellLength / maxMoveSpeed * 50.0);
- if (clearCost > 0) {
- long jumpCost = 0;
- long numOffsets = 8;
- if (!pilot->onHomeTeam() && !MPlayer)
- getJumpRange(&numOffsets, &jumpCost);
- long startSector[2];
- startSector[0] = posCellR / SECTOR_DIM;
- startSector[1] = posCellC / SECTOR_DIM;
- long goalSector[2];
- goalSector[0] = goalCellR / SECTOR_DIM;
- goalSector[1] = goalCellC / SECTOR_DIM;
- long sectorULr = startSector[0] * SECTOR_DIM;
- if (startSector[0] > goalSector[0])
- sectorULr = goalSector[0] * SECTOR_DIM;
- long sectorULc = startSector[1] * SECTOR_DIM;
- if (startSector[1] > goalSector[1])
- sectorULc = goalSector[1] * SECTOR_DIM;
- #ifdef USE_ELEMENTALS
- if (getObjectClass() == ELEMENTAL) {
- GameObjectPtr target = pilot->getLastTarget();
- if (target && (distanceFrom(target->getPosition()) < ElementalTargetNoJumpDistance)) {
- jumpCost = 0;
- numOffsets = 8;
- }
- else
- JumpOnBlocked = true;
- }
- #endif
- if (isMineSweeper())
- moveParams |= MOVEPARAM_SWEEP_MINES;
- if (followRoads)
- moveParams |= MOVEPARAM_FOLLOW_ROADS;
- if (isMech())
- moveParams |= MOVEPARAM_WATER_SHALLOW;
- if (moveLevel == 1)
- moveParams |= (MOVEPARAM_WATER_SHALLOW + MOVEPARAM_WATER_DEEP);
- if (moveParams & MOVEPARAM_JUMP)
- moveParams |= 0;
- PathFindMap[SECTOR_PATHMAP]->setMover(getWatchID(), getTeamId(), isLayingMines());
- PathFindMap[SECTOR_PATHMAP]->setUp(sectorULr,
- sectorULc,
- SECTOR_DIM * 2,
- SECTOR_DIM * 2,
- moveLevel,
- &start,
- posCellR,
- posCellC,
- goal,
- goalCellR - sectorULr,
- goalCellC - sectorULc,
- clearCost,
- jumpCost,
- numOffsets,
- moveParams);
- //---------------------
- // Set up debug info...
- DebugMovePathType = pathType;
- if (numOffsets > 8)
- result = PathFindMap[SECTOR_PATHMAP]->calcPathJUMP(path, NULL, goalCell);
- else
- result = PathFindMap[SECTOR_PATHMAP]->calcPath(path, NULL, goalCell);
- PathFindMap[SECTOR_PATHMAP]->setMover(0);
- JumpOnBlocked = false;
- }
- }
- #if 0
- File* pathDebugFile = new File;
- pathDebugFile->create("movemap1.dbg");
- PathFindMap->writeDebug(pathDebugFile);
- pathDebugFile->close();
- delete pathDebugFile;
- pathDebugFile = NULL;
- #endif
- return(result);
- }
- //---------------------------------------------------------------------------
- long Mover::calcEscapePath (MovePathPtr path,
- Stuff::Vector3D start,
- Stuff::Vector3D goal,
- long* goalCell,
- unsigned long moveParams,
- Stuff::Vector3D& escapeGoal) {
- //------------------------------------------
- // If nothing else, clear the escape goal...
- escapeGoal.x = -999999.0;
- escapeGoal.y = -999999.0;
- escapeGoal.z = -999999.0;
- if (!PathFindMap[SECTOR_PATHMAP] || !PathFindMap[SIMPLE_PATHMAP])
- Fatal(0, " No PathFindMap in Mover::calcMovePath ");
- long posCellR, posCellC;
- land->worldToCell(start, posCellR, posCellC);
- long goalCellR, goalCellC;
- land->worldToCell(goal, goalCellR, goalCellC);
- path->clear();
- long result = 0;
- long mapULr = posCellR - SimpleMovePathRange;
- if (mapULr < 0)
- mapULr = 0;
- long mapULc = posCellC - SimpleMovePathRange;
- if (mapULc < 0)
- mapULc = 0;
- float cellLength = (Terrain::worldUnitsPerCell * metersPerWorldUnit);
- long clearCost = 0;
- if (maxMoveSpeed != 0.0)
- clearCost = (float2short)(cellLength / maxMoveSpeed * 50.0);
- if (clearCost > 0) {
- long jumpCost = 0;
- long numOffsets = 8;
- if (!pilot->onHomeTeam() && !MPlayer)
- getJumpRange(&numOffsets, &jumpCost);
- #ifdef USE_ELEMENTALS
- if (getObjectClass() == ELEMENTAL) {
- GameObjectPtr target = pilot->getLastTarget();
- if (target && (distanceFrom(target->getPosition()) < ElementalTargetNoJumpDistance)) {
- jumpCost = 0;
- numOffsets = 8;
- }
- else
- JumpOnBlocked = true;
- }
- #endif
- if (isMineSweeper())
- moveParams |= MOVEPARAM_SWEEP_MINES;
- if (followRoads)
- moveParams |= MOVEPARAM_FOLLOW_ROADS;
- FindingEscapePath = true;
- PathFindMap[SIMPLE_PATHMAP]->setMover(getWatchID(), getTeamId(), isLayingMines());
- PathFindMap[SIMPLE_PATHMAP]->setUp(mapULr,
- mapULc,
- SimpleMovePathRange * 2 + 1,
- SimpleMovePathRange * 2 + 1,
- moveLevel,
- &start,
- posCellR,
- posCellC,
- goal,
- goalCellR - mapULr,
- goalCellC - mapULc,
- clearCost,
- jumpCost,
- numOffsets,
- moveParams);
- //---------------------
- // Set up debug info...
- DebugMovePathType = 0;
- long goalCell[2];
- result = PathFindMap[SIMPLE_PATHMAP]->calcEscapePath(path, &escapeGoal, goalCell);
- JumpOnBlocked = false;
- FindingEscapePath = false;
- }
- #if 0
- File* pathDebugFile = new File;
- pathDebugFile->create("movemap1.dbg");
- PathFindMap->writeDebug(pathDebugFile);
- pathDebugFile->close();
- delete pathDebugFile;
- pathDebugFile = NULL;
- #endif
- return(result);
- }
- //---------------------------------------------------------------------------
- bool Mover::getAdjacentCellPathLocked (long level, long cellRow, long cellCol, long dir) {
- static long adjCellTable[8][2] = {
- {-1, 0},
- {-1, 1},
- {0, 1},
- {1, 1},
- {1, 0},
- {1, -1},
- {0, -1},
- {-1, -1}
- };
- long adjCellRow = cellRow + adjCellTable[dir][0];
- long adjCellCol = cellCol + adjCellTable[dir][1];
- if (level < 0)
- return(false);
- if (level > (NUM_MOVE_LEVELS - 1))
- return(false);
- return(GameMap->getPathlock(level, adjCellRow, adjCellCol));
- }
- //---------------------------------------------------------------------------
- bool Mover::getPathRangeLock (long range, bool* reachedEnd) {
- MovePathPtr path = pilot->getMovePath();
- if (path)
- return(path->isLocked((moveLevel == 2), -1, range, reachedEnd));
- return(false);
- }
- //---------------------------------------------------------------------------
- long Mover::setPathRangeLock (bool set, long range) {
- MovePathPtr path = pilot->getMovePath();
- long lockLevel = (moveLevel == 2);
- if (set) {
- if (pathLockLength > 0)
- setPathRangeLock(false);
- if (path && (path->numSteps > 0)) {
- long start = path->curStep;
- long lastStep = start + range;
- if (lastStep >= path->numStepsWhenNotPaused)
- lastStep = path->numStepsWhenNotPaused;
- pathLockLength = 0;
- for (long i = start; i < lastStep; i++) {
- if (GameMap->getPathlock(lockLevel, path->stepList[i].cell[0], path->stepList[i].cell[1]))
- return(-1);
- GameMap->setPathlock((moveLevel == 2), path->stepList[i].cell[0], path->stepList[i].cell[1], true);
- pathLockList[pathLockLength][0] = path->stepList[i].cell[0];
- pathLockList[pathLockLength][1] = path->stepList[i].cell[1];
- pathLockLength++;
- }
- }
- }
- else {
- for (long i = 0; i < pathLockLength; i++)
- GameMap->setPathlock(lockLevel, pathLockList[i][0], pathLockList[i][1], false);
- pathLockLength = 0;
- }
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- void Mover::updatePathLock (bool set)
- {
- if (getObjectClass() == BATTLEMECH)
- if (((BattleMechPtr)this)->inJump)
- return;
- //For movers which can be stepped on.
- if (!pathLocks)
- return;
-
- //--------------------------------
- // First, set the cell we're in...
- GameMap->setPathlock((moveLevel == 2), cellPositionRow, cellPositionCol, set);
- //------------------------------------------------------------------------------------------
- // If we're yielding, we should NOT set our path range on. If we are yielding, we can always
- // remove what we've already pathlocked...
- if (!set || !pilot->isYielding())
- setPathRangeLock(set, crashBlockPath);
- }
- //---------------------------------------------------------------------------
- bool Mover::getPathRangeBlocked (long range, bool* reachedEnd) {
- if (moveLevel > 0)
- return(false);
- MovePathPtr path = pilot->getMovePath();
- if (path)
- return(path->isBlocked(-1, range, reachedEnd));
- return(false);
- }
- //---------------------------------------------------------------------------
- void Mover::updateHustleTime (void) {
- #if 0 //Redo when bridges come into play.
- long overlay = GameMap->getOverlay(cellPositionRow, cellPositionCol);
- //---------------------------------------------------------------------------------
- // To avoid blocking movement on bridges, we'll keep track of a "hustle" time
- // for each mover. This will keep us from blocking bridges (and, in the future,
- // any other weird little predicaments) for our buddies. If we're on a bridge (or
- // we're recently on a bridge), our hustle flag will get set so we move it (even if
- // we're in a group move) and don't clog up the tight path...
- switch (overlay) {
- case OVERLAY_WATER_BRIDGE_NS:
- case OVERLAY_WATER_BRIDGE_NS_DESTROYED:
- case OVERLAY_WATER_BRIDGE_EW:
- case OVERLAY_WATER_BRIDGE_EW_DESTROYED:
- case OVERLAY_RAILROAD_WATER_BRIDGE_NS:
- case OVERLAY_RAILROAD_WATER_BRIDGE_NS_DESTROYED:
- case OVERLAY_RAILROAD_WATER_BRIDGE_EW:
- case OVERLAY_RAILROAD_WATER_BRIDGE_EW_DESTROYED:
- lastHustleTime = scenarioTime;
- break;
- }
- #endif
- }
- //---------------------------------------------------------------------------
- long Mover::bounceToAdjCell (void) {
- //--------------------------------------------------------------------
- // Bounces mover to an adjacent open cell. Convenient for collisions:)
- for (long dir = 0; dir < 8; dir++) {
- static long adjCellTable[8][2] = {
- {-1, 0},
- {-1, 1},
- {0, 1},
- {1, 1},
- {1, 0},
- {1, -1},
- {0, -1},
- {-1, -1}
- };
- long adjRow = cellPositionRow + adjCellTable[dir][0];
- long adjCol = cellPositionCol + adjCellTable[dir][1];
- bool cellPathLocked = GameMap->getPathlock((moveLevel == 2), adjRow, adjCol);
- bool cellPassable = GameMap->getPassable(adjRow, adjCol);
- if (!cellPathLocked && cellPassable) {
- //----------------------------------------
- // This is open. Let's set our position...
- bool pathLockMarked = GameMap->getPathlock((moveLevel == 2), cellPositionRow, cellPositionCol);
- if (pathLockMarked)
- updatePathLock(false);
- Stuff::Vector3D newPosition;
- land->cellToWorld(adjRow, adjCol, newPosition);
- setPosition(newPosition);
- pilot->pausePath();
- if (pathLockMarked)
- updatePathLock(true);
- return(dir);
- }
- }
- return(-1);
- }
- //---------------------------------------------------------------------------
- long Mover::calcMovePath (MovePathPtr path,
- Stuff::Vector3D start,
- long thruArea[2],
- long goalDoor,
- Stuff::Vector3D finalGoal,
- Stuff::Vector3D* goal,
- long* goalCell,
- unsigned long moveParams) {
- //-------------------------------------------------------------------------
- // This assumes the goal is already the "optimum" goal (it should have been
- // passed thru "calcMoveGoal" before being sent here)...
- if (!PathFindMap[SECTOR_PATHMAP] || !PathFindMap[SIMPLE_PATHMAP])
- Fatal(0, " No PathFindMap in Mover::calcMovePath ");
- //---------------------------------------------------------------------------------
- // We are now assuming all local pathfinding will fit within one sector. So, we can
- // assume both the start and goal locations are within the sector...
- long result = 0;
- path->clear();
- float cellLength = (Terrain::worldUnitsPerCell * metersPerWorldUnit);
- long clearCost = 0;
- if (maxMoveSpeed != 0)
- clearCost = (long)(cellLength / maxMoveSpeed * 50.0);
- if (clearCost > 0) {
- long jumpCost = 0;
- long numOffsets = 8;
- if (!pilot->onHomeTeam() && !MPlayer)
- getJumpRange(&numOffsets, &jumpCost);
- long posCellR, posCellC;
- land->worldToCell(start, posCellR, posCellC);
- #ifdef USE_ELEMENTALS
- if (getObjectClass() == ELEMENTAL) {
- GameObjectPtr target = pilot->getLastTarget();
- if (target && (distanceFrom(target->getPosition()) < ElementalTargetNoJumpDistance)) {
- jumpCost = 0;
- numOffsets = 8;
- }
- else
- JumpOnBlocked = true;
- }
- #endif
- if (isMineSweeper())
- moveParams |= MOVEPARAM_SWEEP_MINES;
- if (followRoads)
- moveParams |= MOVEPARAM_FOLLOW_ROADS;
- if (isMech())
- moveParams |= MOVEPARAM_WATER_SHALLOW;
- if (moveLevel == 1)
- moveParams |= (MOVEPARAM_WATER_SHALLOW + MOVEPARAM_WATER_DEEP);
- PathFindMap[SECTOR_PATHMAP]->setMover(getWatchID(), getTeamId(), isLayingMines());
- result = PathFindMap[SECTOR_PATHMAP]->setUp(
- moveLevel,
- &start,
- posCellR,
- posCellC,
- thruArea,
- goalDoor,
- finalGoal,
- clearCost,
- jumpCost,
- numOffsets,
- moveParams);
- if (result == -1) {
- //-------------------------------------------------------
- // Goal door is blocked. Can't get thru, at the moment...
- JumpOnBlocked = false;
- return(-999);
- }
- if (numOffsets > 8)
- result = PathFindMap[SECTOR_PATHMAP]->calcPathJUMP(path, goal, goalCell);
- else
- result = PathFindMap[SECTOR_PATHMAP]->calcPath(path, goal, goalCell);
- //if ((goalCell[0] == -1) || (goalCell[1] == -1))
- // STOP(("Mover.calcMovePath: bad goal cell--get GLENN!"));
- PathFindMap[SECTOR_PATHMAP]->setMover(0);
- JumpOnBlocked = false;
- }
- #if 0
- File* pathDebugFile = new File;
- pathDebugFile->create("movemap1.dbg");
- PathFindMap->writeDebug(pathDebugFile);
- pathDebugFile->close();
- delete pathDebugFile;
- pathDebugFile = NULL;
- #endif
- return(result);
- }
- //---------------------------------------------------------------------------
- long Mover::getContacts (long* contactList, long contactCriteria, long sortType) {
- if (sensorSystem)
- return(sensorSystem->getTeamContacts(contactList, contactCriteria, sortType));
- return(0);
- }
- //------------------------------------------------------------------------------------------
- long Mover::getContactStatus (long scanningTeamID, bool includingAllies) {
- if (getFlag(OBJECT_FLAG_REMOVED))
- return(CONTACT_NONE);
- return(getContactInfo()->getContactStatus(scanningTeamID, true));
- }
- //------------------------------------------------------------------------------------------
- float Mover::weaponLocked (long weaponIndex, Stuff::Vector3D targetPosition) {
- long bodyLocation = inventory[weaponIndex].bodyLocation;
- return(relFacingTo(targetPosition, bodyLocation));
- }
- //------------------------------------------------------------------------------------------
- bool Mover::weaponInRange (long weaponIndex, float metersToTarget, float buffer) {
- MasterComponentPtr weapon = &MasterComponent::masterList[inventory[weaponIndex].masterID];
- float minRange = WeaponRanges[weapon->getWeaponRange()][0] - buffer;
- float maxRange = WeaponRanges[weapon->getWeaponRange()][1] + buffer;
- if (metersToTarget < minRange)
- return(false);
- if (metersToTarget > maxRange)
- return(false);
- return(true);
- }
- //------------------------------------------------------------------------------------------
- long Mover::getWeaponsReady (long* list, long listSize) {
- //-----------------------------------------
- // Make sure list is >= the number of ready
- // weapons!
- long numReady = 0;
- if (listSize == -1)
- for (long item = numOther; item < (numOther + numWeapons); item++) {
- if (isWeaponReady(item)) {
- if (list)
- list[numReady++] = item;
- else
- numReady++;
- }
- }
- else
- for (long item = 0; item < listSize; item++) {
- if (isWeaponReady(list[item])) {
- if (list)
- list[numReady++] = list[item];
- else
- numReady++;
- }
- }
- return(numReady);
- }
- //------------------------------------------------------------------------------------------
- long Mover::getWeaponsLocked (long* list, long listSize) {
- //------------------------------------------
- // Make sure list is >= the number of locked
- // weapons!
- GameObjectPtr target = pilot->getCurrentTarget();
- if (!target)
- return(-2);
- Stuff::Vector3D targetPosition = target->getPosition();
- long numLocked = 0;
- float fireArc = getFireArc();
- if (listSize == -1)
- for (long item = numOther; item < (numOther + numWeapons); item++) {
- float relAngle = weaponLocked(item, targetPosition);
- if ((relAngle >= -fireArc) && (relAngle <= fireArc))
- list[numLocked++] = item;
- }
- else
- for (long item = 0; item < listSize; item++) {
- float relAngle = weaponLocked(list[item], targetPosition);
- if ((relAngle >= -fireArc) && (relAngle <= fireArc))
- list[numLocked++] = list[item];
- }
- return(numLocked);
- }
- //------------------------------------------------------------------------------------------
- long Mover::getWeaponsInRange (long* list, long listSize, float fireRangeOrder) {
- //------------------------------------------
- // Make sure list is >= the number of locked
- // weapons!
- GameObjectPtr target = pilot->getCurrentTarget();
- if (!target)
- return(-2);
- float rangeToTarget = distanceFrom(target->getPosition());
- //------------------------------------------------
- // For now, we always obey the fire range order...
- #ifdef STUPID_RULES
- if (rangeToTarget > fireRangeOrder)
- return(-3);
- #endif
- long numInRange = 0;
- if (listSize == -1) {
- for (long item = numOther; item < (numOther + numWeapons); item++)
- if (weaponInRange(item, rangeToTarget, MapCellDiagonal))
- list[numInRange++] = item;
- }
- else {
- for (long item = 0; item < listSize; item++)
- if (weaponInRange(list[item], rangeToTarget, MapCellDiagonal))
- list[numInRange++] = list[item];
- }
- return(numInRange);
- }
- //------------------------------------------------------------------------------------------
- long Mover::getWeaponShots (long weaponIndex) {
- if (!isWeaponIndex(weaponIndex))
- return(-1);
- //--------------------------------------------------------------------
- // All ammo, as listed in the Master Component Table, is a fixed index
- // greater than the weapon itself.
- if (MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponAmmoType())
- return(ammoTypeTotal[inventory[weaponIndex].ammoIndex].curAmount);
- //--------------------------------------------------------------------------
- // If no ammotype, then it has unlimited ammo (energy weapons, for example).
- return(UNLIMITED_SHOTS);
- }
- //------------------------------------------------------------------------------------------
- bool Mover::getWeaponIndirectFire (long weaponIndex)
- {
- if (!isWeaponIndex(weaponIndex))
- return(false);
- //--------------------------------------------------------------------
- for (long i=0;i<20;i++)
- {
- if (IndirectFireWeapons[i] == inventory[weaponIndex].masterID)
- return true;
- }
-
- //--------------------------------------------------------------------------
- // If no ammotype, then it has unlimited ammo (energy weapons, for example).
- return(false);
- }
- //------------------------------------------------------------------------------------------
- bool Mover::getWeaponAreaEffect (long weaponIndex)
- {
- if (!isWeaponIndex(weaponIndex))
- return(false);
- //--------------------------------------------------------------------
- for (long i=0;i<20;i++)
- {
- if (AreaEffectWeapons[i] == inventory[weaponIndex].masterID)
- return true;
- }
-
- //--------------------------------------------------------------------------
- // If no ammotype, then it has unlimited ammo (energy weapons, for example).
- return(false);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getWeaponAmmoLevel (long weaponIndex) {
- if (!isWeaponIndex(weaponIndex))
- return(-1.0);
- return((float)(ammoTypeTotal[inventory[weaponIndex].ammoIndex].curAmount) / (float)(ammoTypeTotal[inventory[weaponIndex].ammoIndex].maxAmount));
- }
- bool Mover::getWeaponIsEnergy( long weaponIndex )
- {
- return MasterComponent::masterList[inventory[weaponIndex].masterID].getForm() == COMPONENT_FORM_WEAPON_ENERGY;
- }
- //------------------------------------------------------------------------------------------
- void Mover::calcWeaponEffectiveness (bool setMax) {
- long effectiveness = 0;
- float avgSkill;
- //----------------------------------
- // Record time of our latest calc...
- lastWeaponEffectivenessCalc = scenarioTime;
-
- if (pilot)
- avgSkill = (float)pilot->getSkill(MWS_GUNNERY) / 50.0;
- else
- avgSkill = 1.0;
- //Ammo is NOT part of weapon effectiveness anymore
- // Per Mike Lee
- // -fs
- for (long curWeapon = numOther; curWeapon < (numOther + numWeapons); curWeapon++) {
- if (setMax || (!inventory[curWeapon].disabled ))
- effectiveness += inventory[curWeapon].effectiveness * avgSkill;
- }
- if (setMax)
- maxWeaponEffectiveness = effectiveness;
- else
- {
- weaponEffectiveness = effectiveness;
- if (weaponEffectiveness == 0)
- playMessage(RADIO_WEAPONS_OUT);
- }
- }
- //---------------------------------------------------------------------------
- void Mover::calcAmmoTotals (void)
- {
- AmmoTally totalList[100];
- numAmmoTypes = 0;
- if (numWeapons > 0)
- {
- //-----------------------------------------------------------
- // We have some ammo in our inventory, so let's count 'em up.
- // First, make a list of all weapon types we have...
- for (long i = numOther; i < (numOther + numWeapons); i++)
- {
- long weaponMasterId = inventory[i].masterID;
- bool newAmmoType = true;
- for (long curAmmo = 0; curAmmo < (long)numAmmoTypes; curAmmo++)
- {
- if (totalList[curAmmo].masterId == (long)MasterComponent::masterList[weaponMasterId].getWeaponAmmoMasterId())
- {
- newAmmoType = false;
- break;
- }
- }
-
- if (newAmmoType)
- {
- totalList[numAmmoTypes].masterId = MasterComponent::masterList[weaponMasterId].getWeaponAmmoMasterId();
- if (MasterComponent::masterList[weaponMasterId].getWeaponAmmoType())
- {
- totalList[numAmmoTypes].curAmount = 0;
- totalList[numAmmoTypes].maxAmount = 0;
- }
- else
- {
- totalList[numAmmoTypes].curAmount = UNLIMITED_SHOTS;
- totalList[numAmmoTypes].maxAmount = UNLIMITED_SHOTS;
- }
- numAmmoTypes++;
- }
- }
-
- //--------------------------------------------------
- // Now, go through all ammo we have and tally 'em...
- for (i = numOther + numWeapons; i < (numOther + numWeapons + numAmmos); i++)
- {
- long ammoMasterId = inventory[i].masterID;
- bool foundAmmoWeapon = false;
- for (long curAmmo = 0; curAmmo < numAmmoTypes; curAmmo++)
- {
- if (totalList[curAmmo].masterId == ammoMasterId)
- {
- foundAmmoWeapon = true;
- if (useUnlimitedAmmo)
- {
- totalList[curAmmo].curAmount = UNLIMITED_SHOTS;
- totalList[curAmmo].maxAmount = UNLIMITED_SHOTS;
- break;
- }
- else
- {
- totalList[curAmmo].curAmount += inventory[i].amount;
- totalList[curAmmo].maxAmount += inventory[i].amount;
- break;
- }
- }
- }
- if (!foundAmmoWeapon)
- STOP(("Mech %s has ammo for a weapon it is not carrying! Ammo Index is %d",name,ammoMasterId));
- }
- //---------------------------------------------------------------------------
- // Since we now know the totals, create the actual total list for this mover...
- memcpy(ammoTypeTotal, totalList, sizeof(AmmoTally) * numAmmoTypes);
- }
- }
- //------------------------------------------------------------------------------------------
- long Mover::calcFireRanges (void) {
- lastOptimalRangeCalc = scenarioTime;
- //---------------------------
- // Calc min and max ranges...
- maxRange = 0;
- minRange = 1000000.0;
- numFunctionalWeapons = 0;
- for (long curWeapon = numOther; curWeapon < (numOther + numWeapons); curWeapon++) {
- if (!inventory[curWeapon].disabled && (getWeaponShots(curWeapon) > 0)) {
- long range = (long)MasterComponent::masterList[inventory[curWeapon].masterID].getWeaponRange();
- float minWeaponRange = WeaponRanges[range][0];
- float maxWeaponRange = WeaponRanges[range][1];
- if (maxWeaponRange > maxRange)
- maxRange = maxWeaponRange;
- if (minWeaponRange < minRange)
- minRange = minWeaponRange;
- numFunctionalWeapons++;
- }
- }
- //---------------------------
- // Now, calc optimal range...
- float rangeTotals[NUM_WEAPON_RANGE_TYPES] = {0, 0, 0, 0, 0};
- for (curWeapon = numOther; curWeapon < (numOther + numWeapons); curWeapon++) {
- MasterComponent* weapon = &MasterComponent::masterList[inventory[curWeapon].masterID];
- if (!inventory[curWeapon].disabled && (getWeaponShots(curWeapon) > 0)) {
- float damageTimeRating = weapon->getWeaponDamage() / weapon->getWeaponRecycleTime();
- //---------------------------------
- // Go thru the five range points...
- for (long i = 0; i < 5; i++)
- if (OptimalRangePointInRange[i][weapon->getWeaponRange()])
- rangeTotals[i] += damageTimeRating;
- }
- }
- float lastOptimalRange = optimalRange;
- if (numFunctionalWeapons == 0) {
- optimalRange = 0.0;
- return(optimalRange != lastOptimalRange);
- }
- else {
- sortList->clear();
- for (long i = 0; i < NUM_WEAPON_RANGE_TYPES; i++) {
- sortList->setId(i, i);
- sortList->setValue(i, rangeTotals[i]);
- }
- sortList->sort();
- if (sortList->getValue(0) <= 0.0) {
- optimalRange = 0.0;
- return(optimalRange != lastOptimalRange);
- }
- }
- long optimalRangeType = sortList->getId(0);
- if (sortList->getValue(0) == sortList->getValue(1)) {
- //--------------------------------------------------------------
- // A tie, so pick one based upon the pre-set range priorities...
- unsigned char tieFlags = 0;
- for (long i = 0; i < 5; i++)
- if (sortList->getValue(i) == sortList->getValue(0))
- tieFlags |= (1 << sortList->getId(i));
- optimalRangeType = OptimalRangeTieTable[tieFlags];
- if (optimalRangeType == 255) {
- optimalRange = 0.0;
- return(optimalRange != lastOptimalRange);
- }
- }
- optimalRange = OptimalRangePoints[optimalRangeType];
-
- return(optimalRange != lastOptimalRange);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getOrderedFireRange (long* attackRange) {
- long fireRange = pilot->getCurTacOrder()->attackParams.range;
- if (attackRange)
- fireRange = *attackRange;
- float orderedFireRange = -1.0;
- switch (fireRange) {
- case FIRERANGE_DEFAULT:
- orderedFireRange = getOptimalFireRange();
- break;
- case FIRERANGE_RAMMING:
- orderedFireRange = 0.0;
- break;
- case FIRERANGE_LONGEST:
- orderedFireRange = getMaxFireRange();
- break;
- case FIRERANGE_OPTIMAL:
- orderedFireRange = getOptimalFireRange();
- break;
- case FIRERANGE_SHORT:
- orderedFireRange = (WeaponRanges[WEAPON_RANGE_SHORT][1] - WeaponRanges[WEAPON_RANGE_SHORT][0])/2.0;
- break;
- case FIRERANGE_MEDIUM:
- orderedFireRange = (WeaponRanges[WEAPON_RANGE_MEDIUM][1] - WeaponRanges[WEAPON_RANGE_MEDIUM][0])/2.0;
- break;
- case FIRERANGE_LONG:
- orderedFireRange = (WeaponRanges[WEAPON_RANGE_LONG][1] - WeaponRanges[WEAPON_RANGE_LONG][0])/2.0;
- break;
- }
- return(orderedFireRange);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getMinFireRange (void) {
- return(minRange);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getMaxFireRange (void) {
- return(maxRange);
- }
- //------------------------------------------------------------------------------------------
- float Mover::getOptimalFireRange (void) {
- return(optimalRange);
- }
- //------------------------------------------------------------------------------------------
- // COMBAT routines
- //------------------------------------------------------------------------------------------
- bool Mover::isWeaponIndex (long itemIndex) {
- return((itemIndex >= numOther) && (itemIndex < (numOther + numWeapons)));
- }
- //---------------------------------------------------------------------------
- bool Mover::isWeaponMissile (long weaponIndex) {
- return(MasterComponent::masterList[inventory[weaponIndex].masterID].getForm() == COMPONENT_FORM_WEAPON_MISSILE);
- }
- //---------------------------------------------------------------------------
- bool Mover::isWeaponReady (long weaponIndex) {
- if (inventory[weaponIndex].disabled)
- return(false);
- else if (inventory[weaponIndex].readyTime > scenarioTime)
- return(false);
- return(true);
- }
- //------------------------------------------------------------------------------------------
- void Mover::startWeaponRecycle (long weaponIndex) {
- inventory[weaponIndex].readyTime = scenarioTime +
- MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponRecycleTime();
- }
- //------------------------------------------------------------------------------------------
- long Mover::tallyAmmo (long ammoMasterId) {
- long tally = 0;
- long firstAmmo = numOther + numWeapons;
- for (long item = firstAmmo; item < firstAmmo + numAmmos; item++) {
- if (inventory[item].masterID == ammoMasterId)
- tally += inventory[item].amount;
- }
- return(tally);
- }
- //---------------------------------------------------------------------------
- bool Mover::needsRefit(void) {
- bool result = false;
- if (!refitBuddyWID && getObjectClass() == BATTLEMECH)
- {
- for (long loc=0; loc<numArmorLocations; loc++)
- {
- if (loc<numBodyLocations && (loc == MECH_ARMOR_LOCATION_LARM || loc == MECH_ARMOR_LOCATION_RARM) &&
- body[loc].damageState == IS_DAMAGE_DESTROYED)
- continue;
- if ((loc<numBodyLocations && body[loc].curInternalStructure < body[loc].maxInternalStructure) ||
- (armor[loc].curArmor < armor[loc].maxArmor))
- {
- result = true;
- break;
- }
- }
- if (!result)
- for (long ammo = 0; ammo < numAmmoTypes; ammo++)
- if (ammoTypeTotal[ammo].curAmount < ammoTypeTotal[ammo].maxAmount)
- {
- result = true;
- break;
- }
- }
- return result;
- }
- //---------------------------------------------------------------------------
- long Mover::reduceAmmo (long ammoMasterId, long amount) {
- long amountUsed = amount;
- //----------------------------------------------------------
- // Deduct it from the first available ammo critical space...
- long firstAmmo = numOther + numWeapons;
- for (long item = firstAmmo; item < firstAmmo + numAmmos; item++) {
- if (inventory[item].masterID == ammoMasterId)
- if (inventory[item].amount > amount) {
- inventory[item].amount -= amount;
- break;
- }
- else {
- amount -= inventory[item].amount;
- inventory[item].amount = 0;
- }
- }
- //-------------------------------------------------------------------
- // Make sure the ammoTypeTotal list, in which we track total ammo for
- // all of the ammo types this mover uses, is adjusted...
- for (long ammo = 0; ammo < numAmmoTypes; ammo++)
- if (ammoTypeTotal[ammo].masterId == ammoMasterId) {
- ammoTypeTotal[ammo].curAmount -= amountUsed;
- if (ammoTypeTotal[ammo].curAmount <= 0) {
- //-----------------------------------------------------
- // Ammo for this weapon type is spent, which may effect
- // our weapon effectiveness and optimal range...
- ammoTypeTotal[ammo].curAmount = 0;
- calcWeaponEffectiveness(false);
- calcFireRanges();
- pilot->radioMessage(RADIO_AMMO_OUT);
- }
- break;
- }
- return(amountUsed);
- }
- //---------------------------------------------------------------------------
- /*
- long Mover::refillAmmo (long ammoMasterId, long amount) {
- long amountUsed = amount;
- //----------------------------------------------------------
- // Deduct it from the first available ammo critical space...
- long firstAmmo = numOther + numWeapons;
- for (long item = firstAmmo; item < firstAmmo + numAmmos; item++) {
- if (inventory[item].masterID == ammoMasterId)
- if (inventory[item].amount > amount) {
- inventory[item].amount -= amount;
- break;
- }
- else {
- amount -= inventory[item].amount;
- inventory[item].amount = 0;
- }
- }
- //-------------------------------------------------------------------
- // Make sure the ammoTypeTotal list, in which we track total ammo for
- // all of the ammo types this mover uses, is adjusted...
- for (long ammo = 0; ammo < numAmmoTypes; ammo++)
- if (ammoTypeTotal[ammo].masterId == ammoMasterId) {
- ammoTypeTotal[ammo].curAmount -= amountUsed;
- if (ammoTypeTotal[ammo].curAmount <= 0) {
- //-----------------------------------------------------
- // Ammo for this weapon type is spent, which may effect
- // our weapon effectiveness and optimal range...
- ammoTypeTotal[ammo].curAmount = 0;
- calcLongestRangeWeapon();
- calcWeaponEffectiveness(false);
- calcOptimalRange(NULL);
- }
- break;
- }
- return(amountUsed);
- }
- */
- //---------------------------------------------------------------------------
- void Mover::deductWeaponShot (long weaponIndex, long ammoAmount) {
- if (ammoAmount > 0)
- reduceAmmo(MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponAmmoMasterId(), ammoAmount);
- }
- //---------------------------------------------------------------------------
- long Mover::sortWeapons (long* weaponList, long* valueList, long listSize, long sortType, bool skillCheck) {
- //------------------------------------------
- // Make sure list is >= the number of locked
- // weapons!
- GameObjectPtr target = pilot->getCurrentTarget();
- if (!target)
- return(-2);
- long aimLocation = -1;
- if (pilot && pilot->getCurTacOrder()->isCombatOrder())
- aimLocation = pilot->getCurTacOrder()->attackParams.aimLocation;
- //----------------------------------------------------------------------
- // BIG ASSUMPTION HERE: That a mech will not have more than 100 weapons.
- sortList->clear();
- if (listSize == -1) {
- for (long item = numOther; item < (numOther + numWeapons); item++) {
- sortList->setId(item - numOther, item);
- switch (sortType) {
- case WEAPONSORT_ATTACKCHANCE:
- sortList->setValue(item - numOther, calcAttackChance(target, aimLocation, scenarioTime, item, 0.0, NULL));
- break;
- default:
- //-----------------
- // Bad Sort Type...
- return(-3);
- }
- }
- sortList->sort();
- for (item = 0; item < numWeapons; item++) {
- weaponList[item] = sortList->getId(item);
- valueList[item] = sortList->getValue(item);
- }
- }
- else {
- for (long item = 0; item < listSize; item++) {
- sortList->setId(item, weaponList[item]);
- float sortValue = 0.0;
- if (weaponList[item] == -1)
- sortValue = -999.0;
- else
- switch (sortType) {
- case WEAPONSORT_ATTACKCHANCE:
- sortValue = calcAttackChance(target, aimLocation, scenarioTime, weaponList[item], 0.0, NULL);
- break;
- default:
- //-----------------
- // Bad Sort Type...
- return(-3);
- }
- sortList->setValue(item, sortValue);
- }
- sortList->sort();
- for (item = 0; item < listSize; item++) {
- weaponList[item] = sortList->getId(item);
- valueList[item] = sortList->getValue(item);
- }
- }
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- bool Mover::hasNonAreaWeapon (void)
- {
- for (long i=numOther;i<numOther+numWeapons;i++)
- {
- if (!getWeaponAreaEffect(i))
- return true;
- }
-
- return false;
- }
- #define MAX_SHORT_RANGE (60.0f * worldUnitsPerMeter)
- #define MIN_MEDIUM_RANGE (31.0f * worldUnitsPerMeter)
- #define MAX_MEDIUM_RANGE (120.0f * worldUnitsPerMeter)
- #define MIN_LONG_RANGE (61.0f * worldUnitsPerMeter)
- #define MAX_LONG_RANGE (180.0f * worldUnitsPerMeter)
- extern float applyDifficultySkill (float chance, bool isPlayer);
- //---------------------------------------------------------------------------
- float Mover::calcAttackChance (GameObjectPtr target, long aimLocation, float targetTime, long weaponIndex, float modifiers, long* range, Stuff::Vector3D* targetPoint)
- {
- if ((weaponIndex < numOther) || (weaponIndex >= numOther + numWeapons))
- return(-9999.0);
- //-------------------------------------------------------------
- // First, let's find out what kind of object we're targeting...
- Stuff::Vector3D targetPosition;
- BattleMechPtr mech = NULL;
- GroundVehiclePtr vehicle = NULL;
-
- if (target)
- {
- long targetObjectClass = target->getObjectClass();
- switch (targetObjectClass)
- {
- case BATTLEMECH:
- mech = (BattleMechPtr)target;
- break;
- case GROUNDVEHICLE:
- vehicle = (GroundVehiclePtr)target;
- break;
- }
- targetPosition = target->getPosition();
- }
- else if (targetPoint)
- targetPosition = *targetPoint;
- else
- return(-9999.0);
- float attackChance = pilot->getSkill(MWS_GUNNERY);
-
- if (!MPlayer && (getCommanderId() == Commander::home->getId())) //Up the gunnery Skill by the difficulty modifier
- attackChance = applyDifficultySkill(attackChance,TRUE);
- else if (!MPlayer && (getCommanderId() == Commander::home->getId())) //Up the gunnery Skill by the difficulty modifier
- attackChance = applyDifficultySkill(attackChance,FALSE);
- //----------------------
- // General fire range...
- float distanceToTarget = distanceFrom(targetPosition);
- if (range)
- {
- if (distanceToTarget <= WeaponRange[FIRERANGE_SHORT])
- *range = FIRERANGE_SHORT;
- else if (distanceToTarget <= WeaponRange[FIRERANGE_MEDIUM])
- *range = FIRERANGE_MEDIUM;
- else
- *range = FIRERANGE_LONG;
- }
-
- //----------------------
- // Range (Per Weapon)...
- float weaponMinRange = WeaponRanges[MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponRange()][0];
- float weaponLongRange = WeaponRanges[MasterComponent::masterList[inventory[weaponIndex].masterID].getWeaponRange()][1];
- if (distanceToTarget <= (weaponMinRange - MapCellDiagonal))
- return(-1.0);
-
- if (distanceToTarget > (weaponLongRange + MapCellDiagonal)) {
- //----------------
- // Out of range...
- return(-1.0);
- }
- //Non-movers get 100% attack chance. Look for modifications for turrets soon!
- // Nothing is better then 100%, no need to modify. Exit here!!
- // -fs 9/8/2000
- if (!target || (target && !target->isMover()) || (target && target->isMover() && target->isDisabled()))
- {
- attackChance = 100.0f;
- return attackChance;
- }
- //Mech specialist modifiers
- if (mech && mech->getPilot())
- {
- if ((mech->tonnage < 40) && mech->getPilot()->isLightMechSpecialist())
- attackChance -= 30.0f;
- else if ((mech->tonnage >= 40) && (mech->tonnage < 60) && mech->getPilot()->isMediumMechSpecialist())
- attackChance -= 20.0f;
- else if ((mech->tonnage >= 60) && (mech->tonnage < 80) && mech->getPilot()->isHevayMechSpecialist())
- attackChance -= 10.0f;
- else if ((mech->tonnage >= 80) && (mech->tonnage < 100) && mech->getPilot()->isAssaultMechSpecialist())
- attackChance -= 10.0f;
- }
-
- //Weapon Specialist Modifiers
- if (pilot && pilot->isLaserSpecialist() && ((inventory[weaponIndex].masterID == 139) ||
- (inventory[weaponIndex].masterID == 140) ||
- (inventory[weaponIndex].masterID == 147) ||
- (inventory[weaponIndex].masterID == 156)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isPulseLaserSpecialist() && ((inventory[weaponIndex].masterID == 142) ||
- (inventory[weaponIndex].masterID == 144) ||
- (inventory[weaponIndex].masterID == 153) ||
- (inventory[weaponIndex].masterID == 151)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isERLaserSpecialist() && ((inventory[weaponIndex].masterID == 141) ||
- (inventory[weaponIndex].masterID == 143) ||
- (inventory[weaponIndex].masterID == 150) ||
- (inventory[weaponIndex].masterID == 152)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isLightACSpecialist() && ((inventory[weaponIndex].masterID == 100) ||
- (inventory[weaponIndex].masterID == 103) ||
- (inventory[weaponIndex].masterID == 110)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isMediumACSpecialist() && ((inventory[weaponIndex].masterID == 101) ||
- (inventory[weaponIndex].masterID == 108) ||
- (inventory[weaponIndex].masterID == 111)))
- {
- attackChance += WeaponSpecialistModifier;
- }
- if (pilot && pilot->isHeavyACSpecialist() && ((inventory[weaponIndex].masterID == 102) ||
- (inventory[weaponIndex].masterID == 109) ||
- (inventory[weaponIndex].masterID == 112)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isLRMSpecialist() && ((inventory[weaponIndex].masterID == 120) ||
- (inventory[weaponIndex].masterID == 123)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isSRMSpecialist() && ((inventory[weaponIndex].masterID == 124) ||
- (inventory[weaponIndex].masterID == 125)))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isPPCSpecialist() && ((inventory[weaponIndex].masterID == 145) ||
- (inventory[weaponIndex].masterID == 146) ||
- (inventory[weaponIndex].masterID == 154)))
- {
- attackChance += WeaponSpecialistModifier;
- }
- if (pilot && pilot->isGaussSpecialist() && (inventory[weaponIndex].masterID == 99))
- {
- attackChance += WeaponSpecialistModifier;
- }
-
- if (pilot && pilot->isSmallArmsSpecialist() && ((inventory[weaponIndex].masterID == 114) ||
- (inventory[weaponIndex].masterID == 155)))
- {
- attackChance += WeaponSpecialistModifier;
- }
- //Range Specialist Modifiers
- if ((distanceToTarget <= MAX_SHORT_RANGE) && pilot && pilot->isShortRangeSpecialist())
- {
- attackChance += 15.0f;
- }
-
- if ((distanceToTarget >= MIN_MEDIUM_RANGE) && (distanceToTarget <= MAX_MEDIUM_RANGE) && pilot && pilot->isMediumRangeSpecialist())
- {
- attackChance += 15.0f;
- }
-
- if ((distanceToTarget >= MIN_LONG_RANGE) && (distanceToTarget <= MAX_LONG_RANGE) && pilot && pilot->isLongRangeSpecialist())
- {
- attackChance += 15.0f;
- }
-
- //Aimed shots go here.
- // Aimed or called shots are percentage of the actual attack chance
- // Therefore, must go here after all modifiers...
- if ((aimLocation > -1) && (mech))
- {
- switch (aimLocation)
- {
- case MECH_BODY_LOCATION_HEAD:
- attackChance *= HeadShotModifier;
- break;
- case MECH_BODY_LOCATION_CTORSO:
- case MECH_BODY_LOCATION_LTORSO:
- case MECH_BODY_LOCATION_RTORSO:
- break;
- case MECH_BODY_LOCATION_LARM:
- case MECH_BODY_LOCATION_RARM:
- attackChance *= ArmShotModifier;
- break;
-
- case MECH_BODY_LOCATION_LLEG:
- case MECH_BODY_LOCATION_RLEG:
- attackChance *= LegShotModifier;
- break;
- }
-
- if (pilot && pilot->isSharpShooter())
- attackChance += 20.0f;
- }
-
- //No more modifiers EXCEPT what is in here.
- if (attackChance > 95.0f)
- attackChance = 95.0f;
-
- if (attackChance < 5.0f)
- attackChance = 5.0f;
-
- return(attackChance);
- }
- //---------------------------------------------------------------------------
- /*
- void Mover::buildAttackChanceTable (void) {
- for (long i = 0; i <
- }
- */
- //---------------------------------------------------------------------------
- void Mover::ammoExplosion (long ammoIndex) {
- pilot->injure(2);
- Assert(ammoIndex < (numOther + numWeapons + numAmmos),ammoIndex," Ammo Index out of range ");
- Assert(ammoIndex >= (numOther + numWeapons),ammoIndex," Ammo Index too low ");
- long ammoMasterId = inventory[ammoIndex].masterID;
- long bodyLocation = inventory[ammoIndex].bodyLocation;
- long remainingAmmo = inventory[ammoIndex].amount;
- float damage = float(remainingAmmo) *
- MasterComponent::masterList[ammoMasterId].getAmmoExplosiveDamage();
- inventory[ammoIndex].amount = 0;
- //-------------------------------------------------------------------
- // Make sure the ammoTypeTotal list, in which we track total ammo for
- // all of the ammo types this mover uses, is adjusted...
- if (inventory[ammoIndex].ammoIndex == -1)
- Fatal(-1," Bad Ammo Index in Ammo Explosion ");
- Assert(inventory[ammoIndex].ammoIndex < numAmmoTypes,inventory[ammoIndex].ammoIndex," Too Many Ammo Types ");
- Assert(inventory[ammoIndex].ammoIndex >= 0,inventory[ammoIndex].ammoIndex," not enough Ammo Types ");
- ammoTypeTotal[inventory[ammoIndex].ammoIndex].curAmount -= remainingAmmo;
- //------------------------------------------------------------------------
- // We can use the bodyLocation as the hitLocation since the location codes
- // for all body locations are the same as the armor location codes.
- // MULTIPLAYER NOTE: Since this is called ONLY by Mech.cpp from hitInventoryItem,
- // there should be no need to call it from the server since it's triggered
- // by a weaponhit already.
- WeaponShotInfo shotInfo;
- //-------------------------------------------------------
- // This is big ass damage for an ammo explosion!!!!
- // Happens with the Hunchback right now.
- if (damage > 255.0f)
- damage = 255.0f;
- shotInfo.init(NULL, inventory[ammoIndex].masterID, damage, bodyLocation, 0.0);
- if (MPlayer) {
- if (MPlayer->isServer())
- handleWeaponHit(&shotInfo, true);
- }
- else
- handleWeaponHit(&shotInfo);
- }
- //---------------------------------------------------------------------------
- void Mover::disable (unsigned long cause)
- {
- //-------------------------------------------------
- // Immediately begin shutting down, then disable...
- if (!isDisabled())
- {
- if (pilot)
- pilot->handleAlarm(PILOT_ALARM_VEHICLE_INCAPACITATED, cause);
- if (getObjectClass() == BATTLEMECH)
- if (MPlayer && MPlayer->isServer() && !((BattleMech*)this)->lost) {
- MPlayer->addKillLossChunk(MAX_MC_PLAYERS, getCommanderId());
- ((BattleMech*)this)->lost = true;
- }
- setStatus(OBJECT_STATUS_DISABLED);
- disableThisFrame = true;
- if (Team::home->isFriendly(getTeam()))
- friendlyDestroyed = true;
- else
- {
- enemyDestroyed = true;
- }
- //-----------------------------
- // Immediately lose contacts...
- if (sensorSystem)
- sensorSystem->disable();
- causeOfDeath = cause;
- if (isMech() && (getMoveType() != MOVETYPE_AIR))
- {
- //We now want to play a BUNCH of critical Hit Explosions on the mech
- // To indicate that we are going down.
- Stuff::Vector3D explosionLoc;
- explosionLoc = appearance->getNodeNamePosition("cockpit");
- ObjectManager->createExplosion(MECH_CRITICAL_HIT_ID,NULL,explosionLoc,0.0f,0.0f);
- explosionLoc = appearance->getNodeNamePosition("hit_left");
- ObjectManager->createExplosion(MECH_CRITICAL_HIT_ID,NULL,explosionLoc,0.0f,0.0f);
-
- explosionLoc = appearance->getNodeNamePosition("hit_right");
- ObjectManager->createExplosion(MECH_CRITICAL_HIT_ID,NULL,explosionLoc,0.0f,0.0f);
- explosionLoc = appearance->getNodeNamePosition("weapon_righttorso");
- ObjectManager->createExplosion(MECH_CRITICAL_HIT_ID,NULL,explosionLoc,0.0f,0.0f);
- explosionLoc = appearance->getNodeNamePosition("weapon_lefttorso");
- ObjectManager->createExplosion(MECH_CRITICAL_HIT_ID,NULL,explosionLoc,0.0f,0.0f);
- }
- }
- }
- //---------------------------------------------------------------------------
- void Mover::shutDown (void) {
- if (isDisabled())
- return;
- if ((status == OBJECT_STATUS_SHUTDOWN) || (status == OBJECT_STATUS_SHUTTING_DOWN))
- return;
- //-----------------------------------
- // Immediately begin shutting down...
- setStatus(OBJECT_STATUS_SHUTTING_DOWN);
- shutDownThisFrame = true;
- }
- //---------------------------------------------------------------------------
- void Mover::startUp (void) {
- if (isDisabled())
- return;
- if ((status == OBJECT_STATUS_STARTING_UP) || (status == OBJECT_STATUS_NORMAL))
- return;
- //---------------------------------
- // Immediately begin starting up...
- setStatus(OBJECT_STATUS_STARTING_UP);
- startUpThisFrame = true;
- }
- //---------------------------------------------------------------------------
- void Mover::tradeRefresh (void) {
- timeLeft = 15.0;
- exploding = false;
- withdrawing = false;
- engineBlowTime = -1.0;
- ejectOrderGiven = false;
- // if (statusChunk.ejectOrderGiven)
- // PAUSE(("whoops"));
- statusChunk.ejectOrderGiven = false;
- }
- //---------------------------------------------------------------------------
- bool Mover::isWithdrawing (void) {
- return(pilot->getCurTacOrder()->code == TACTICAL_ORDER_WITHDRAW);
- }
- //---------------------------------------------------------------------------
- bool Mover::refit (float pointsAvailable, float& pointsUsed, bool ammoOnly) {
- bool result = false;
- float refitPoints = pointsAvailable;
- if (refitPoints > 0.0) {
- float areaMax = refitAmount / 3.0; // size of pool for each section (armor, internals, and ammo) before depletions
- long rearmCount = 0;
- long repairCount = 0;
-
- // how many locations need armor or IS repaired?
- if (!ammoOnly) {
- for (long i = 0; i < numArmorLocations; i++) {
- //-------------------------------
- // don't repair destroyed arms...
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if ((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure))
- repairCount++;
- if (armor[i].curArmor < armor[i].maxArmor)
- repairCount++;
- }
- }
- // how many ammo types need refilling, and how much?
- for (long i = 0; i < numAmmoTypes; i++)
- if (ammoTypeTotal[i].curAmount < ammoTypeTotal[i].maxAmount)
- rearmCount++;
- if (pilot && pilot->getRadio())
- pilot->getRadio()->resetAmmoMessage();
- // repair each armor & IS
- for (i = 0; i < numArmorLocations; i++) {
- if ((repairCount == 0) || (refitPoints <= 0.0))
- continue;
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if (armor[i].curArmor < armor[i].maxArmor) {
- float pointsToUse = areaMax / repairCount;
- if (pointsToUse > refitPoints)
- pointsToUse = refitPoints;
- float repairValue = pointsToUse * refitCostArray[ARMOR_REFIT_COST][REFIT_VEHICLE];
- if ((armor[i].curArmor + repairValue) > armor[i].maxArmor) {
- repairValue = armor[i].maxArmor - armor[i].curArmor;
- pointsToUse = repairValue / refitCostArray[ARMOR_REFIT_COST][REFIT_VEHICLE];
- }
- armor[i].curArmor += repairValue;
- refitPoints -= pointsToUse;
- }
- if ((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure)) {
- float pointsToUse = areaMax / repairCount;
- if (pointsToUse > refitPoints)
- pointsToUse = refitPoints;
- float repairValue = pointsToUse * refitCostArray[INTERNAL_REFIT_COST][REFIT_VEHICLE];
- if ((body[i].curInternalStructure + repairValue) > body[i].maxInternalStructure) {
- repairValue = body[i].maxInternalStructure - body[i].curInternalStructure;
- pointsToUse = repairValue / refitCostArray[INTERNAL_REFIT_COST][REFIT_VEHICLE];
- }
-
- body[i].curInternalStructure += repairValue;
- long newDamageState = IS_DAMAGE_NONE;
- if (body[i].curInternalStructure <= 0.0)
- newDamageState = IS_DAMAGE_DESTROYED;
- else if ((body[i].curInternalStructure / body[i].maxInternalStructure) <= 0.5)
- newDamageState = IS_DAMAGE_PARTIAL;
- if ((getObjectClass() == BATTLEMECH) /*&& (newDamageState != body[i].damageState)*/) {
- if ((i == MECH_BODY_LOCATION_LLEG) || (i == MECH_BODY_LOCATION_RLEG))
- ((BattleMechPtr)this)->calcLegStatus();
- if (i == MECH_BODY_LOCATION_CTORSO)
- ((BattleMechPtr)this)->calcTorsoStatus();
- }
- body[i].damageState = newDamageState;
- refitPoints -= pointsToUse;
- }
- }
- // refit each ammo that needs it
- for (i=0; i < numAmmoTypes; i++) {
- if ((rearmCount > 0) && (refitPoints > 0.0) && (ammoTypeTotal[i].curAmount < ammoTypeTotal[i].maxAmount)) {
- bool recalc = (ammoTypeTotal[i].curAmount == 0);
- float pointsToUse = areaMax / rearmCount;
- if (pointsToUse > refitPoints)
- pointsToUse = refitPoints;
- float repairValue = pointsToUse * refitCostArray[AMMO_REFIT_COST][REFIT_VEHICLE] * MasterComponent::masterList[ammoTypeTotal[i].masterId].getAmmoPerTon();
- if ((ammoTypeTotal[i].curAmount + repairValue) > ammoTypeTotal[i].maxAmount) {
- repairValue = ammoTypeTotal[i].maxAmount - ammoTypeTotal[i].curAmount;
- pointsToUse = repairValue / (refitCostArray[AMMO_REFIT_COST][REFIT_VEHICLE] * MasterComponent::masterList[ammoTypeTotal[i].masterId].getAmmoPerTon());
- }
- ammoTypeTotal[i].curAmount += repairValue;
- refitPoints -= pointsToUse;
- if (recalc) {
- calcWeaponEffectiveness(false);
- calcFireRanges();
- }
- }
- }
-
- // do any locations still need repair?
- rearmCount = 0;
- repairCount = 0;
- if (!ammoOnly) {
- for (i = 0; i < numArmorLocations; i++) {
- // don't repair destroyed arms
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if (((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure)) || (armor[i].curArmor < armor[i].maxArmor)) {
- repairCount++;
- break;
- }
- }
- }
- // if there's no more repairing, do any ammo types need refilling?
- if (repairCount == 0)
- for (i = 0; i < numAmmoTypes; i++)
- if (ammoTypeTotal[i].curAmount < ammoTypeTotal[i].maxAmount) {
- rearmCount++;
- break;
- }
- if ((repairCount == 0) && (rearmCount == 0)) {
- // done fixing, move on
- if (getCommanderId() == Commander::home->getId())
- {
- getPilot()->radioMessage(RADIO_REFIT_DONE, TRUE);
- soundSystem->playBettySample(BETTY_REPAIR_COMPLETE);
- if (appearance)
- appearance->startSmoking(-1); //Turn the smoke off if we successfully repaired.
- }
- result = true;
- }
- }
- else {
- // no points left, so move on
- if (getCommanderId() == Commander::home->getId())
- {
- getPilot()->radioMessage(RADIO_REFIT_INCOMPLETE, TRUE);
- soundSystem->playBettySample( BETTY_REPAIR_GONE );
- }
- result = true;
- }
- pointsUsed = pointsAvailable - refitPoints;
- //-----------------------------------------------------------------------
- // Points used should be rounded to nearest 1/4 point (for consistency in
- // MultiPlayer)...
- if ((pointsUsed > 0.0) && (pointsUsed < 0.25))
- pointsUsed = 0.25;
- pointsUsed = (float)((long)((pointsUsed + 0.125) / 0.25)) / 4.0;
- return(result);
- }
- //---------------------------------------------------------------------------
- float Mover::calcRecoverPrice (void) {
- float repairValue = 0;
- for (long i = 0; i < numBodyLocations; i++) {
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if ((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure))
- repairValue += (body[i].maxInternalStructure - body[i].curInternalStructure);
- }
- float pointsToUse = repairValue / recoverCost;
- //-----------------------------------------------------------------------
- // Points used should be rounded to nearest 1/4 point (for consistency in
- // MultiPlayer)...
- if ((pointsToUse > 0.0) && (pointsToUse < 0.25))
- pointsToUse = 0.25;
- pointsToUse = (float)((long)((pointsToUse + 0.125) / 0.25)) / 4.0;
- return(pointsToUse);
- }
- //---------------------------------------------------------------------------
- bool Mover::recover (void) {
- inRecoverUpdate = true;
- bool result = false;
- float recoverPoints = 100000.0;
- if (recoverPoints > 0.0) {
- long repairCount = 0;
- // how many locations need IS repaired?
- for (long i = 0; i < numBodyLocations; i++) {
- //-------------------------------
- // don't repair destroyed arms...
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if ((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure))
- repairCount++;
- }
- // repair each IS
- for (i = 0; i < numBodyLocations; i++)
- {
- if ((repairCount == 0) || (recoverPoints <= 0.0))
- continue;
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if ((i < numBodyLocations) && (body[i].curInternalStructure < body[i].maxInternalStructure))
- {
- float pointsToUse = recoverAmount / repairCount;
- if (pointsToUse > recoverPoints)
- pointsToUse = recoverPoints;
- float repairValue = pointsToUse * recoverCost;
- if ((body[i].curInternalStructure + repairValue) > body[i].maxInternalStructure)
- {
- repairValue = body[i].maxInternalStructure - body[i].curInternalStructure;
- pointsToUse = repairValue / recoverCost;
- }
-
- body[i].curInternalStructure += repairValue;
- long newDamageState = IS_DAMAGE_NONE;
- if (body[i].curInternalStructure <= 0.0)
- newDamageState = IS_DAMAGE_DESTROYED;
- else if ((body[i].curInternalStructure / body[i].maxInternalStructure) <= 0.5)
- newDamageState = IS_DAMAGE_PARTIAL;
- if ((getObjectClass() == BATTLEMECH) /*&& (newDamageState != body[i].damageState)*/)
- {
- if ((i == MECH_BODY_LOCATION_LLEG) || (i == MECH_BODY_LOCATION_RLEG))
- ((BattleMechPtr)this)->calcLegStatus();
- if (i == MECH_BODY_LOCATION_CTORSO)
- ((BattleMechPtr)this)->calcTorsoStatus();
- }
- body[i].damageState = newDamageState;
- recoverPoints -= pointsToUse;
- }
- }
-
- // do any locations still need repair?
- repairCount = 0;
- for (i = 0; i < numBodyLocations; i++)
- {
- // don't repair destroyed arms
- if (((i == MECH_BODY_LOCATION_LARM) || (i == MECH_BODY_LOCATION_RARM)) && (body[i].damageState == IS_DAMAGE_DESTROYED))
- continue;
- if (body[i].curInternalStructure < body[i].maxInternalStructure) {
- repairCount++;
- break;
- }
- }
- if (repairCount == 0)
- {
- // done fixing, move on
- for (long i = 0; i < numOther; i++)
- {
- MasterComponentPtr component = &MasterComponent::masterList[inventory[i].masterID];
- switch (component->getForm()) {
- case COMPONENT_FORM_WEAPON:
- case COMPONENT_FORM_WEAPON_ENERGY:
- case COMPONENT_FORM_WEAPON_BALLISTIC:
- case COMPONENT_FORM_WEAPON_MISSILE:
- inventory[i].health = component->getHealth();
- inventory[i].disabled = false;
- calcWeaponEffectiveness(false);
- calcFireRanges();
- break;
- default:
- inventory[i].health = component->getHealth();
- inventory[i].disabled = false;
- }
- }
- for (i = 0; i < numBodyLocations; i++)
- for (long j = 0; j < NumLocationCriticalSpaces[i]; j++)
- if (body[i].criticalSpaces[j].inventoryID < 255)
- body[i].criticalSpaces[j].hit = inventory[body[i].criticalSpaces[j].inventoryID].disabled;
- if (getCommanderId() == Commander::home->getId())
- {
- getPilot()->radioMessage(RADIO_REFIT_DONE, TRUE);
- soundSystem->playBettySample(BETTY_REPAIR_COMPLETE);
- }
- result = true;
- }
- }
- else
- {
- // no points left, so move on
- if (getCommanderId() == Commander::home->getId())
- {
- getPilot()->radioMessage(RADIO_REFIT_INCOMPLETE, TRUE);
- soundSystem->playBettySample( BETTY_REPAIR_GONE );
- soundSystem->playBettySample(BETTY_REPAIR_INCOMPLETE);
- }
- result = true;
- }
- inRecoverUpdate = false;
- return(result);
- }
-
- //---------------------------------------------------------------------------
- void Mover::drawSensorTextHelp (float screenX, float screenY, long resID, DWORD color, bool drawBOLD)
- {
- DWORD width, height;
- Stuff::Vector4D moveHere;
- moveHere.x = screenX;
- moveHere.y = screenY;
- char buffer[256];
- cLoadString( resID, buffer, 255 );
- FloatHelp::getTextStringLength(buffer,color,1.0f,true,drawBOLD,true,false,width,height);
- moveHere.x -= width / 2;
- moveHere.z = width;
- moveHere.w = height;
- globalFloatHelp->setFloatHelp(buffer,moveHere,color,0x0,1.0f,true,drawBOLD,true,false);
- }
- //---------------------------------------------------------------------------
- void Mover::drawWaypointPath()
- {
- getPilot()->drawWaypointPath();
- }
- //---------------------------------------------------------------------------
- void Mover::updateDrawWaypointPath()
- {
- getPilot()->updateDrawWaypointPath();
- }
- //---------------------------------------------------------------------------
- void Mover::initOptimalCells (long numIncrements) {
- numOptimalIncrements = numIncrements;
- double degreesToRadians = (double)DEGREES_TO_RADS;
- double incrementDegrees = 360.0 / numOptimalIncrements;
- double doptimalCells[MAX_ATTACK_CELLRANGE][MAX_ATTACK_INCREMENTS][2];
- for (long r = 0; r < MAX_ATTACK_CELLRANGE; r++)
- for (long i = 0; i < numIncrements; i++) {
- double incrementRadians = incrementDegrees * (double)i * degreesToRadians;
- doptimalCells[r][i][0] = sin(incrementRadians) * (double)r;
- doptimalCells[r][i][1] = cos(incrementRadians) * (double)r;
- }
- //--------------------------------------------------------------------
- // Due to double rounding errors, we munge the numbers a little before
- // casting to chars. NOTE: due to this rounding, it's possible that
- // an "optimal" cell may be a cell or more further from the target than
- // the desired range (i.e. there's an error of 10 or so meters in these
- // calcs, in some situations). Therefore, it's imperative that this is
- // acceptable (re: max fire range for the mover), otherwise the mover
- // may select an "optimal" cell from which it's out of range. As long
- // as these optimal ranges fall well within their weapon fire ranges,
- // this should be no problem.
- for (r = 0; r < MAX_ATTACK_CELLRANGE; r++)
- for (long i = 0; i < numIncrements; i++) {
- if (doptimalCells[r][i][0] < 0.00)
- optimalCells[r][i][0] = (char)(doptimalCells[r][i][0] - 0.50);
- else
- optimalCells[r][i][0] = (char)(doptimalCells[r][i][0] + 0.50);
- if (doptimalCells[r][i][1] < 0.00)
- optimalCells[r][i][1] = (char)(doptimalCells[r][i][1] - 0.50);
- else
- optimalCells[r][i][1] = (char)(doptimalCells[r][i][1] + 0.50);
- }
- //-----------------------------------------------
- // Now, initialize the tables for Ranged Areas...
- char rangedMap[MAX_ATTACK_CELLRANGE * 2 + 1][MAX_ATTACK_CELLRANGE * 2 + 1];
- for (r = 0; r < (MAX_ATTACK_CELLRANGE * 2 + 1); r++)
- for (long c = 0; c < (MAX_ATTACK_CELLRANGE * 2 + 1); c++) {
- Stuff::Vector3D start, goal;
- start.x = c;
- start.y = r;
- start.z = 0;
- goal.x = MAX_ATTACK_CELLRANGE;
- goal.y = MAX_ATTACK_CELLRANGE;
- goal.z = 0.0;
- double dist = distance_from(start, goal);
- rangedMap[r][c] = (char)(dist + 0.5);
- }
- long index = 0;
- for (long range = 0; range < MAX_ATTACK_CELLRANGE; range++) {
- rangedCellsIndices[range][0] = index;
- for (long r = 0; r < (MAX_ATTACK_CELLRANGE * 2 + 1); r++)
- for (long c = 0; c < (MAX_ATTACK_CELLRANGE * 2 + 1); c++)
- if (rangedMap[r][c] == range) {
- rangedCells[index][0] = r - MAX_ATTACK_CELLRANGE;
- rangedCells[index][1] = c - MAX_ATTACK_CELLRANGE;
- index++;
- }
- rangedCellsIndices[range][1] = index - 1;
- }
- }
- //***************************************************************************
- // MOVE ROUTINES CALLBACKS
- //***************************************************************************
- void GetBlockedDoorCells (long moveLevel, long door, char* openCells) {
- Assert((door > -1) && (door < GlobalMoveMap[moveLevel]->numDoors), 0, " FUDGE 1");
- Assert((GlobalMoveMap[moveLevel]->doors[door].direction[0] == 1) || (GlobalMoveMap[moveLevel]->doors[door].direction[0] == 2), 0, " FUDGE 2");
- Assert((GlobalMoveMap[moveLevel]->doors[door].length > 0) && (GlobalMoveMap[moveLevel]->doors[door].length < 1024), 0, " FUDGE 3");
- long doorWorldCellRec[4] = {-1, -1, -1, -1};
- if (GlobalMoveMap[moveLevel]->doors[door].direction[0] == 1) {
- doorWorldCellRec[0] = GlobalMoveMap[moveLevel]->doors[door].row;
- doorWorldCellRec[1] = GlobalMoveMap[moveLevel]->doors[door].col;
- doorWorldCellRec[2] = doorWorldCellRec[0] + GlobalMoveMap[moveLevel]->doors[door].length;
- doorWorldCellRec[3] = doorWorldCellRec[1] + 2;
- //NOTE: DO NOT set cells for elementals--only mechs and vehicles.
- long numMovers = ObjectManager->getNumMovers();
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = ObjectManager->getMover(i);
- if ((mover->getWatchID() != PathFindMap[SECTOR_PATHMAP]->moverWID) && (mover->getWatchID() != RamObjectWID) && !mover->isDisabled()) {
- long cellPos[2];
- mover->getCellPosition (cellPos[0], cellPos[1]);
- long worldCellRow = cellPos[0];
- long worldCellCol = cellPos[1];
- if ((worldCellRow >= doorWorldCellRec[0]) && (worldCellRow < doorWorldCellRec[2]))
- if ((worldCellCol >= doorWorldCellRec[1]) && (worldCellCol < doorWorldCellRec[3])) {
- long cellIndex = worldCellRow - doorWorldCellRec[0];
- Assert((cellIndex > -1) && (cellIndex < GlobalMoveMap[moveLevel]->doors[door].length), 0, " Bad Cell Index ");
- openCells[cellIndex] = 0;
- }
- }
- }
- }
- else {
- doorWorldCellRec[0] = GlobalMoveMap[moveLevel]->doors[door].row;
- doorWorldCellRec[1] = GlobalMoveMap[moveLevel]->doors[door].col;
- doorWorldCellRec[2] = doorWorldCellRec[0] + 2;
- doorWorldCellRec[3] = doorWorldCellRec[1] + GlobalMoveMap[moveLevel]->doors[door].length;
- long numMovers = ObjectManager->getNumMovers();
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = ObjectManager->getMover(i);
- if ((mover->getObjectClass() != ELEMENTAL) && (mover->getWatchID() != PathFindMap[SECTOR_PATHMAP]->moverWID) && (mover->getWatchID() != RamObjectWID) && !mover->isDisabled()) {
- long cellPos[2];
- mover->getCellPosition (cellPos[0], cellPos[1]);
- long worldCellRow = cellPos[0];
- long worldCellCol = cellPos[1];
- if ((worldCellRow >= doorWorldCellRec[0]) && (worldCellRow < doorWorldCellRec[2]))
- if ((worldCellCol >= doorWorldCellRec[1]) && (worldCellCol < doorWorldCellRec[3])) {
- long cellIndex = worldCellCol - doorWorldCellRec[1];
- Assert((cellIndex > -1) && (cellIndex < GlobalMoveMap[moveLevel]->doors[door].length), 0, " Bad Cell Index ");
- openCells[cellIndex] = 0;
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- void PlaceMovers (void) {
- long numMovers = ObjectManager->getNumMovers();
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = (MoverPtr)ObjectManager->getMover(i);
- if (mover->getUseMe()) {
- long cellRow, cellCol;
- mover->getCellPosition(cellRow, cellCol);
- if (!GameMap->getPreserved(cellRow, cellCol))
- GameMap->setPreserved(cellRow, cellCol, true);
- GameMap->placeObject(mover->getPosition(), mover->getExtentRadius());
- GameMap->setPassable(cellRow, cellCol, false);
- }
- }
- }
- //---------------------------------------------------------------------------
- void adjustMoveMapCellCost (MoveMapNodePtr cell, long costAdj);
- void PlaceStationaryMovers (MoveMap* map) {
- long numMovers = ObjectManager->getNumMovers();
- for (long i = 0; i < numMovers; i++) {
- MoverPtr mover = ObjectManager->getMover(i);
- if ((mover->getObjectClass() != ELEMENTAL) && (mover->getWatchID() != map->moverWID) && (mover->getWatchID() != RamObjectWID) && !mover->isDisabled()) {
- long cellRow, cellCol;
- mover->getCellPosition(cellRow, cellCol);
- if ((cellRow >= 0) && (cellRow < map->height) && (cellCol >= 0) && (cellCol < map->width)) {
-
- if ((cellRow != map->startR) || (cellCol != map->startC)) {
- if ((map->map[cellRow * map->maxWidth + cellCol].flags & MOVEFLAG_GOAL) == 0) {
- MovePathPtr path = mover->getPilot()->getMovePath();
- if (path && (path->numSteps == 0)) {
- map->map[cellRow * map->maxWidth + cellCol].setFlag(MOVEFLAG_MOVER_HERE);
- #ifdef USE_OVERLAYS
- long bridgeCost = COST_BLOCKED / 3;
- long overlay = GameMap->getOverlay(cellRow, cellCol);
- if (OverlayIsBridge[overlay])
- map->adjustCellCost(cellRow, cellCol, bridgeCost);
- else
- #endif
- map->adjustCost(cellRow, cellCol, COST_BLOCKED * 2);
- }
- }
- }
- }
- }
- }
- }
- bool Mover::isCloseToFirstTacOrder( Stuff::Vector3D& pos )
- {
- return getPilot()->isCloseToFirstTacOrder( pos );
- }
- void Mover::removeFromUnitGroup( int id )
- {
- unitGroup = -1;
- //unitGroup &= (~(1<<id));
- }
- void Mover::addToUnitGroup( int id )
- {
- unitGroup = (1 << id); // now you only get to be in one at a time
- }
- bool Mover::isInUnitGroup( int id )
- {
- if ( unitGroup == -1 )
- return false;
- return unitGroup & ( 1 << id ) ? true : false;
- }
- bool Mover::handleEjection()
- {
- if (pilot && ((pilot->getStatus() == WARRIOR_STATUS_NORMAL) || (pilot->getStatus() == WARRIOR_STATUS_WITHDRAWING))) {
- //----------------
- // First, eject...
- getPilot()->eject();
- ejectOrderGiven = true;
-
- //------------------
- // The head blows...
- // destroyBodyLocation(MECH_BODY_LOCATION_HEAD);
- //---------------------
- // Create the Eject FX
- // WHEN READY -fs
-
- //---------------------------------------------
- // If we aren't already disabled, we are now...
- disable(EJECTION_DEATH);
- #ifdef USE_IFACE
- //------------------------------------------------------
- // The interface needs to know I'm not around anymore...
- theInterface->RemoveMech(getPartId());
- #endif
- #ifdef USE_MOODMUSIC
- //------------------------------------
- // What heroic music should be played?
- if (alignment == homeTeam->getAlignment())
- friendlyDestroyed = true;
- else
- enemyDestroyed = true;
- #endif
- }
- return(true);
- }
- bool Mover::isWeaponWorking (long weaponIndex)
- {
- if (inventory[weaponIndex].disabled)
- return(FALSE);
- else if (getWeaponShots(weaponIndex) == 0)
- return (FALSE);
- return(TRUE);
- }
- //***************************************************************************
- void Mover::Save (PacketFilePtr file, long packetNum)
- {
- MoverData data;
- CopyTo(&data);
- //PacketNum incremented in ObjectManager!!
- file->writePacket(packetNum,(MemoryPtr)&data,sizeof(MoverData),STORAGE_TYPE_ZLIB);
- }
- //***************************************************************************
- void Mover::CopyTo (MoverData *data)
- {
- data->killed = killed;
- data->lost = lost;
- data->positionNormal = positionNormal;
- data->velocity = velocity;
- memcpy(data->name,name, sizeof(char) * MAXLEN_MOVER_NAME);
- data->chassis = chassis;
- data->startDisabled = startDisabled;
- data->creationTime = creationTime;
-
- data->moveType = moveType;
- data->moveLevel = moveLevel;
- data->followRoads = followRoads;
-
- memcpy(data->lastMapCell,lastMapCell,sizeof(long) * 2);
-
- data->damageRateTally = damageRateTally;
- data->damageRateCheckTime = damageRateCheckTime;
- data->pilotCheckDamageTally = pilotCheckDamageTally;
-
- memcpy(data->body,body,sizeof(BodyLocation) * MAX_MOVER_BODY_LOCATIONS);
- data->numBodyLocations = numBodyLocations;
- data->fieldedCV = fieldedCV;
-
- data->attackRange = attackRange;
-
- memcpy(data->armor,armor, sizeof(ArmorLocation) * MAX_MOVER_ARMOR_LOCATIONS);
- data->numArmorLocations = numArmorLocations;
- memcpy(data->longName,longName, sizeof(char) * MAXLEN_MECH_LONGNAME);
-
- memcpy(data->inventory,inventory,sizeof(InventoryItem) * MAX_MOVER_INVENTORY_ITEMS);
- data->numOther = numOther;
- data->numWeapons = numWeapons;
- data->numAmmos = numAmmos;
- memcpy(data->ammoTypeTotal,ammoTypeTotal,sizeof(AmmoTally) * MAX_AMMO_TYPES);
- data->numAmmoTypes = numAmmoTypes;
- data->pilotHandle = pilotHandle;
-
- data->cockpit = cockpit;
- data->engine = engine;
- data->lifeSupport = lifeSupport;
- data->sensor = sensor;
- data->ecm = ecm;
- data->probe = probe;
- data->jumpJets = jumpJets;
- data->nullSignature = nullSignature;
- data->maxWeaponEffectiveness = maxWeaponEffectiveness;
- data->weaponEffectiveness = weaponEffectiveness;
-
- data->minRange = minRange;
- data->maxRange = maxRange;
- data->optimalRange = optimalRange;
- data->numFunctionalWeapons = numFunctionalWeapons;
-
- data->numAntiMissileSystems = numAntiMissileSystems;
- memcpy(data->antiMissileSystem,antiMissileSystem,sizeof(unsigned char) * MAX_ANTI_MISSILE_SYSTEMS);
-
- data->engineBlowTime = engineBlowTime;
- data->maxMoveSpeed = maxMoveSpeed;
- data->shutDownThisFrame = shutDownThisFrame;
- data->startUpThisFrame = startUpThisFrame;
- data->disableThisFrame = disableThisFrame;
-
- data->teamId = teamId;
- data->groupId = groupId;
- data->squadId = squadId;
- data->selectionIndex = selectionIndex;
- data->teamRosterIndex = teamRosterIndex;
- data->commanderId = commanderId;
- data->unitGroup = unitGroup;
-
- data->iconPictureIndex = iconPictureIndex;
- data->suppressionFire = suppressionFire;
-
- data->pilotCheckModifier = pilotCheckModifier;
- data->prevPilotCheckModifier = prevPilotCheckModifier;
- data->prevPilotCheckDelta = prevPilotCheckDelta;
- data->prevPilotCheckUpdate = prevPilotCheckUpdate;
- data->failedPilotingCheck = failedPilotingCheck;
- data->lastWeaponEffectivenessCalc = lastWeaponEffectivenessCalc;
- data->lastOptimalRangeCalc = lastOptimalRangeCalc;
- data->challengerWID = challengerWID;
-
- data->lastGesture = lastGesture;
-
- data->control = control;
- data->dynamics = dynamics;
-
- data->numWeaponHitsHandled = numWeaponHitsHandled;
- data->timeLeft = timeLeft;
- data->exploding = exploding;
- data->withdrawing = withdrawing;
-
- data->yieldTimeLeft = yieldTimeLeft;
- data->lastValidPosition = lastValidPosition;
- data->pivotDirection = pivotDirection;
- data->lastHustleTime = lastHustleTime;
-
- data->salvageVehicle = salvageVehicle;
-
- data->markDistanceMoved = markDistanceMoved;
-
- data->refitBuddyWID = refitBuddyWID;
- data->recoverBuddyWID = recoverBuddyWID;
-
- data->crashAvoidSelf = crashAvoidSelf;
- data->crashAvoidPath = crashAvoidPath;
- data->crashBlockSelf = crashBlockSelf;
- data->crashBlockPath = crashBlockPath;
- data->crashYieldTime = crashYieldTime;
- data->pathLockLength = pathLockLength;
- memcpy(data->pathLockList,pathLockList, sizeof(long) * MAX_LOCK_RANGE * 2);
- data->moveCenter = moveCenter;
- data->moveRadius = moveRadius;
-
- data->overlayWeightClass = overlayWeightClass;
-
- data->timeToClearSelection = timeToClearSelection;
-
- data->timeSinceMoving = timeSinceMoving;
-
- data->timeSinceFiredLast = timeSinceFiredLast;
-
- data->lastMovingTargetWID = lastMovingTargetWID;
-
- data->mechSalvage = mechSalvage;
-
- data->teleportPosition = teleportPosition;
- data->debugPage = debugPage;
-
- data->pathLocks = pathLocks;
- data->isOnGui = isOnGui;
-
- data->conStat = conStat;
- data->fadeTime = fadeTime;
- data->alphaValue = alphaValue;
- data->causeOfDeath = causeOfDeath;
-
- data->lowestWeaponNodeID = lowestWeaponNodeID;
- if (getAppearance())
- {
- getAppearance()->getPaintScheme(data->psRed,data->psGreen,data->psBlue);
- }
- GameObject::CopyTo(dynamic_cast<GameObjectData *>(data));
- }
- //---------------------------------------------------------------------------
- void Mover::Load (MoverData *data)
- {
- GameObject::Load(dynamic_cast<GameObjectData *>(data));
- killed = data->killed;
- lost = data->lost;
- positionNormal = data->positionNormal;
- velocity = data->velocity;
- memcpy(name,data->name, sizeof(char) * MAXLEN_MOVER_NAME);
- chassis = data->chassis;
- startDisabled = data->startDisabled;
- creationTime = data->creationTime;
-
- moveType = data->moveType;
- moveLevel = data->moveLevel;
- followRoads = data->followRoads;
-
- memcpy(lastMapCell,data->lastMapCell,sizeof(long) * 2);
-
- damageRateTally = data->damageRateTally;
- damageRateCheckTime = data->damageRateCheckTime;
- pilotCheckDamageTally = data->pilotCheckDamageTally;
-
- memcpy(body,data->body,sizeof(BodyLocation) * MAX_MOVER_BODY_LOCATIONS);
- numBodyLocations = data->numBodyLocations;
- fieldedCV = data->fieldedCV;
-
- attackRange = data->attackRange;
-
- memcpy(armor,data->armor, sizeof(ArmorLocation) * MAX_MOVER_ARMOR_LOCATIONS);
- numArmorLocations = data->numArmorLocations;
- memcpy(longName,data->longName, sizeof(char) * MAXLEN_MECH_LONGNAME);
-
- memcpy(inventory,data->inventory,sizeof(InventoryItem) * MAX_MOVER_INVENTORY_ITEMS);
- numOther = data->numOther;
- numWeapons = data->numWeapons;
- numAmmos = data->numAmmos;
- memcpy(ammoTypeTotal,data->ammoTypeTotal,sizeof(AmmoTally) * MAX_AMMO_TYPES);
- numAmmoTypes = data->numAmmoTypes;
- pilotHandle = data->pilotHandle;
-
- cockpit = data->cockpit;
- engine = data->engine;
- lifeSupport = data->lifeSupport;
- sensor = data->sensor;
- ecm = data->ecm;
- probe = data->probe;
- jumpJets = data->jumpJets;
- nullSignature = data->nullSignature;
- maxWeaponEffectiveness = data->maxWeaponEffectiveness;
- weaponEffectiveness = data->weaponEffectiveness;
-
- minRange = data->minRange;
- maxRange = data->maxRange;
- optimalRange = data->optimalRange;
- numFunctionalWeapons = data->numFunctionalWeapons;
-
- numAntiMissileSystems = data->numAntiMissileSystems;
- memcpy(antiMissileSystem,data->antiMissileSystem,sizeof(unsigned char) * MAX_ANTI_MISSILE_SYSTEMS);
-
- engineBlowTime = data->engineBlowTime;
- maxMoveSpeed = data->maxMoveSpeed;
- shutDownThisFrame = data->shutDownThisFrame;
- startUpThisFrame = data->startUpThisFrame;
- disableThisFrame = data->disableThisFrame;
-
- teamId = data->teamId;
- groupId = data->groupId;
- squadId = data->squadId;
- selectionIndex = data->selectionIndex;
- teamRosterIndex = data->teamRosterIndex;
- commanderId = data->commanderId;
- unitGroup = data->unitGroup;
-
- iconPictureIndex = data->iconPictureIndex;
- suppressionFire = data->suppressionFire;
-
- pilotCheckModifier = data->pilotCheckModifier;
- prevPilotCheckModifier = data->prevPilotCheckModifier;
- prevPilotCheckDelta = data->prevPilotCheckDelta;
- prevPilotCheckUpdate = data->prevPilotCheckUpdate;
- failedPilotingCheck = data->failedPilotingCheck;
- lastWeaponEffectivenessCalc = data->lastWeaponEffectivenessCalc;
- lastOptimalRangeCalc = data->lastOptimalRangeCalc;
- challengerWID = data->challengerWID;
-
- lastGesture = data->lastGesture;
-
- control = data->control;
- dynamics = data->dynamics;
-
- numWeaponHitsHandled = data->numWeaponHitsHandled;
- timeLeft = data->timeLeft;
- exploding = data->exploding;
- withdrawing = data->withdrawing;
-
- yieldTimeLeft = data->yieldTimeLeft;
- lastValidPosition = data->lastValidPosition;
- pivotDirection = data->pivotDirection;
- lastHustleTime = data->lastHustleTime;
-
- salvageVehicle = data->salvageVehicle;
-
- markDistanceMoved = data->markDistanceMoved;
-
- refitBuddyWID = data->refitBuddyWID;
- recoverBuddyWID = data->recoverBuddyWID;
-
- crashAvoidSelf = data->crashAvoidSelf;
- crashAvoidPath = data->crashAvoidPath;
- crashBlockSelf = data->crashBlockSelf;
- crashBlockPath = data->crashBlockPath;
- crashYieldTime = data->crashYieldTime;
- pathLockLength = data->pathLockLength;
- memcpy(pathLockList,data->pathLockList, sizeof(long) * MAX_LOCK_RANGE * 2);
- moveCenter = data->moveCenter;
- moveRadius = data->moveRadius;
-
- overlayWeightClass = data->overlayWeightClass;
-
- timeToClearSelection = data->timeToClearSelection;
-
- timeSinceMoving = data->timeSinceMoving;
-
- timeSinceFiredLast = data->timeSinceFiredLast;
-
- lastMovingTargetWID = data->lastMovingTargetWID;
-
- mechSalvage = data->mechSalvage;
-
- teleportPosition = data->teleportPosition;
- debugPage = data->debugPage;
-
- pathLocks = data->pathLocks;
- isOnGui = data->isOnGui;
-
- conStat = data->conStat;
- fadeTime = data->fadeTime;
- alphaValue = data->alphaValue;
- causeOfDeath = data->causeOfDeath;
-
- lowestWeaponNodeID = data->lowestWeaponNodeID;
- //OK. Must get pilotPtr back.
- pilot = MechWarrior::warriorList[pilotHandle];
- if (!pilot)
- STOP(("Could not find pilot for mover after in-mission load"));
- //Set the PaintScheme
- if (getAppearance())
- {
- getAppearance()->resetPaintScheme(data->psRed,data->psGreen,data->psBlue);
- }
- }
- //***************************************************************************
|