m_menu.c 155 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2000 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * DOOM selection menu, options, episode etc. (aka Big Font menus)
  31. * Sliders and icons. Kinda widget stuff.
  32. * Setup Menus.
  33. * Extended HELP screens.
  34. * Dynamic HELP screen.
  35. *
  36. *-----------------------------------------------------------------------------*/
  37. #include <stdio.h>
  38. #include <fcntl.h>
  39. #include "doomdef.h"
  40. #include "doomstat.h"
  41. #include "dstrings.h"
  42. #include "d_main.h"
  43. #include "v_video.h"
  44. #include "w_wad.h"
  45. #include "r_main.h"
  46. #include "hu_stuff.h"
  47. #include "g_game.h"
  48. #include "s_sound.h"
  49. #include "sounds.h"
  50. #include "m_menu.h"
  51. #include "d_deh.h"
  52. #include "m_misc.h"
  53. #include "lprintf.h"
  54. #include "am_map.h"
  55. #include "i_main.h"
  56. #include "i_system.h"
  57. #include "i_video.h"
  58. #include "i_sound.h"
  59. #include "r_demo.h"
  60. #include "r_fps.h"
  61. extern patchnum_t hu_font[HU_FONTSIZE];
  62. extern boolean message_dontfuckwithme;
  63. extern boolean chat_on; // in heads-up code
  64. //
  65. // defaulted values
  66. //
  67. int mouseSensitivity_horiz; // has default // killough
  68. int mouseSensitivity_vert; // has default
  69. int showMessages; // Show messages has default, 0 = off, 1 = on
  70. int hide_setup=1; // killough 5/15/98
  71. // Blocky mode, has default, 0 = high, 1 = normal
  72. //int detailLevel; obsolete -- killough
  73. int screenblocks; // has default
  74. int screenSize; // temp for screenblocks (0-9)
  75. int quickSaveSlot; // -1 = no quicksave slot picked!
  76. int messageToPrint; // 1 = message to be printed
  77. // CPhipps - static const
  78. static const char* messageString; // ...and here is the message string!
  79. // message x & y
  80. int messx;
  81. int messy;
  82. int messageLastMenuActive;
  83. boolean messageNeedsInput; // timed message = no input from user
  84. typedef void (*MessageRoutineFunction)(int response);
  85. MessageRoutineFunction messageRoutine;
  86. #define SAVESTRINGSIZE 24
  87. /* killough 8/15/98: when changes are allowed to sync-critical variables */
  88. static int allow_changes(void)
  89. {
  90. return !(demoplayback || demorecording || netgame);
  91. }
  92. static void M_UpdateCurrent(default_t* def)
  93. {
  94. /* cph - requires rewrite of m_misc.c */
  95. if (def->current) {
  96. if (allow_changes()) /* killough 8/15/98 */
  97. *def->current = *def->location.pi;
  98. else if (*def->current != *def->location.pi)
  99. warn_about_changes(S_LEVWARN); /* killough 8/15/98 */
  100. }
  101. }
  102. int warning_about_changes, print_warning_about_changes;
  103. /* cphipps - M_DrawBackground renamed and moved to v_video.c */
  104. #define M_DrawBackground V_DrawBackground
  105. // we are going to be entering a savegame string
  106. int saveStringEnter;
  107. int saveSlot; // which slot to save in
  108. int saveCharIndex; // which char we're editing
  109. // old save description before edit
  110. char saveOldString[SAVESTRINGSIZE];
  111. boolean inhelpscreens; // indicates we are in or just left a help screen
  112. boolean menuactive; // The menus are up
  113. #define SKULLXOFF -32
  114. #define LINEHEIGHT 16
  115. char savegamestrings[10][SAVESTRINGSIZE];
  116. //
  117. // MENU TYPEDEFS
  118. //
  119. typedef struct
  120. {
  121. short status; // 0 = no cursor here, 1 = ok, 2 = arrows ok
  122. char name[10];
  123. // choice = menu item #.
  124. // if status = 2,
  125. // choice=0:leftarrow,1:rightarrow
  126. void (*routine)(int choice);
  127. char alphaKey; // hotkey in menu
  128. } menuitem_t;
  129. typedef struct menu_s
  130. {
  131. short numitems; // # of menu items
  132. struct menu_s* prevMenu; // previous menu
  133. menuitem_t* menuitems; // menu items
  134. void (*routine)(); // draw routine
  135. short x;
  136. short y; // x,y of menu
  137. short lastOn; // last item user was on in menu
  138. } menu_t;
  139. short itemOn; // menu item skull is on (for Big Font menus)
  140. short skullAnimCounter; // skull animation counter
  141. short whichSkull; // which skull to draw (he blinks)
  142. // graphic name of skulls
  143. const char skullName[2][/*8*/9] = {"M_SKULL1","M_SKULL2"};
  144. menu_t* currentMenu; // current menudef
  145. // phares 3/30/98
  146. // externs added for setup menus
  147. extern int mousebfire;
  148. extern int mousebstrafe;
  149. extern int mousebforward;
  150. // proff 08/17/98: Added backward to mousebuttons
  151. extern int mousebbackward;
  152. extern int joybfire;
  153. extern int joybstrafe;
  154. extern int joybuse;
  155. extern int joybspeed;
  156. int mapcolor_me; // cph
  157. extern int map_point_coordinates; // killough 10/98
  158. extern char* chat_macros[]; // chat macros
  159. extern const char* shiftxform;
  160. extern default_t defaults[];
  161. extern int numdefaults;
  162. // end of externs added for setup menus
  163. //
  164. // PROTOTYPES
  165. //
  166. void M_NewGame(int choice);
  167. void M_Episode(int choice);
  168. void M_ChooseSkill(int choice);
  169. void M_LoadGame(int choice);
  170. void M_SaveGame(int choice);
  171. void M_Options(int choice);
  172. void M_EndGame(int choice);
  173. void M_ReadThis(int choice);
  174. void M_ReadThis2(int choice);
  175. void M_QuitDOOM(int choice);
  176. void M_ChangeMessages(int choice);
  177. void M_ChangeSensitivity(int choice);
  178. void M_SfxVol(int choice);
  179. void M_MusicVol(int choice);
  180. /* void M_ChangeDetail(int choice); unused -- killough */
  181. void M_SizeDisplay(int choice);
  182. void M_StartGame(int choice);
  183. void M_Sound(int choice);
  184. void M_Mouse(int choice, int *sens); /* killough */
  185. void M_MouseVert(int choice);
  186. void M_MouseHoriz(int choice);
  187. void M_DrawMouse(void);
  188. void M_FinishReadThis(int choice);
  189. void M_FinishHelp(int choice); // killough 10/98
  190. void M_LoadSelect(int choice);
  191. void M_SaveSelect(int choice);
  192. void M_ReadSaveStrings(void);
  193. void M_QuickSave(void);
  194. void M_QuickLoad(void);
  195. void M_DrawMainMenu(void);
  196. void M_DrawReadThis1(void);
  197. void M_DrawReadThis2(void);
  198. void M_DrawNewGame(void);
  199. void M_DrawEpisode(void);
  200. void M_DrawOptions(void);
  201. void M_DrawSound(void);
  202. void M_DrawLoad(void);
  203. void M_DrawSave(void);
  204. void M_DrawSetup(void); // phares 3/21/98
  205. void M_DrawHelp (void); // phares 5/04/98
  206. void M_DrawSaveLoadBorder(int x,int y);
  207. void M_SetupNextMenu(menu_t *menudef);
  208. void M_DrawThermo(int x,int y,int thermWidth,int thermDot);
  209. void M_DrawEmptyCell(menu_t *menu,int item);
  210. void M_DrawSelCell(menu_t *menu,int item);
  211. void M_WriteText(int x, int y, const char *string);
  212. int M_StringWidth(const char *string);
  213. int M_StringHeight(const char *string);
  214. void M_StartMessage(const char *string,MessageRoutineFunction routine,boolean input);
  215. void M_StopMessage(void);
  216. void M_ClearMenus (void);
  217. // phares 3/30/98
  218. // prototypes added to support Setup Menus and Extended HELP screens
  219. int M_GetKeyString(int,int);
  220. void M_Setup(int choice);
  221. void M_KeyBindings(int choice);
  222. void M_Weapons(int);
  223. void M_StatusBar(int);
  224. void M_Automap(int);
  225. void M_Enemy(int);
  226. void M_Messages(int);
  227. void M_ChatStrings(int);
  228. void M_InitExtendedHelp(void);
  229. void M_ExtHelpNextScreen(int);
  230. void M_ExtHelp(int);
  231. static int M_GetPixelWidth(const char*);
  232. void M_DrawKeybnd(void);
  233. void M_DrawWeapons(void);
  234. static void M_DrawMenuString(int,int,int);
  235. static void M_DrawStringCentered(int,int,int,const char*);
  236. void M_DrawStatusHUD(void);
  237. void M_DrawExtHelp(void);
  238. void M_DrawAutoMap(void);
  239. void M_DrawEnemy(void);
  240. void M_DrawMessages(void);
  241. void M_DrawChatStrings(void);
  242. void M_Compat(int); // killough 10/98
  243. void M_ChangeDemoSmoothTurns(void);
  244. void M_General(int); // killough 10/98
  245. void M_DrawCompat(void); // killough 10/98
  246. void M_DrawGeneral(void); // killough 10/98
  247. void M_FullScreen(void); // nathanh 01/01
  248. menu_t NewDef; // phares 5/04/98
  249. // end of prototypes added to support Setup Menus and Extended HELP screens
  250. /////////////////////////////////////////////////////////////////////////////
  251. //
  252. // DOOM MENUS
  253. //
  254. /////////////////////////////
  255. //
  256. // MAIN MENU
  257. //
  258. // main_e provides numerical values for which Big Font screen you're on
  259. enum
  260. {
  261. newgame = 0,
  262. loadgame,
  263. savegame,
  264. options,
  265. readthis,
  266. quitdoom,
  267. main_end
  268. } main_e;
  269. //
  270. // MainMenu is the definition of what the main menu Screen should look
  271. // like. Each entry shows that the cursor can land on each item (1), the
  272. // built-in graphic lump (i.e. "M_NGAME") that should be displayed,
  273. // the program which takes over when an item is selected, and the hotkey
  274. // associated with the item.
  275. //
  276. menuitem_t MainMenu[]=
  277. {
  278. {1,"M_NGAME", M_NewGame, 'n'},
  279. {1,"M_OPTION",M_Options, 'o'},
  280. {1,"M_LOADG", M_LoadGame,'l'},
  281. {1,"M_SAVEG", M_SaveGame,'s'},
  282. // Another hickup with Special edition.
  283. {1,"M_RDTHIS",M_ReadThis,'r'},
  284. {1,"M_QUITG", M_QuitDOOM,'q'}
  285. };
  286. menu_t MainDef =
  287. {
  288. main_end, // number of menu items
  289. NULL, // previous menu screen
  290. MainMenu, // table that defines menu items
  291. M_DrawMainMenu, // drawing routine
  292. 97,64, // initial cursor position
  293. 0 // last menu item the user was on
  294. };
  295. //
  296. // M_DrawMainMenu
  297. //
  298. void M_DrawMainMenu(void)
  299. {
  300. // CPhipps - patch drawing updated
  301. V_DrawNamePatch(94, 2, 0, "M_DOOM", CR_DEFAULT, VPT_STRETCH);
  302. }
  303. /////////////////////////////
  304. //
  305. // Read This! MENU 1 & 2
  306. //
  307. // There are no menu items on the Read This! screens, so read_e just
  308. // provides a placeholder to maintain structure.
  309. enum
  310. {
  311. rdthsempty1,
  312. read1_end
  313. } read_e;
  314. enum
  315. {
  316. rdthsempty2,
  317. read2_end
  318. } read_e2;
  319. enum // killough 10/98
  320. {
  321. helpempty,
  322. help_end
  323. } help_e;
  324. // The definitions of the Read This! screens
  325. menuitem_t ReadMenu1[] =
  326. {
  327. {1,"",M_ReadThis2,0}
  328. };
  329. menuitem_t ReadMenu2[]=
  330. {
  331. {1,"",M_FinishReadThis,0}
  332. };
  333. menuitem_t HelpMenu[]= // killough 10/98
  334. {
  335. {1,"",M_FinishHelp,0}
  336. };
  337. menu_t ReadDef1 =
  338. {
  339. read1_end,
  340. &MainDef,
  341. ReadMenu1,
  342. M_DrawReadThis1,
  343. 330,175,
  344. //280,185, // killough 2/21/98: fix help screens
  345. 0
  346. };
  347. menu_t ReadDef2 =
  348. {
  349. read2_end,
  350. &ReadDef1,
  351. ReadMenu2,
  352. M_DrawReadThis2,
  353. 330,175,
  354. 0
  355. };
  356. menu_t HelpDef = // killough 10/98
  357. {
  358. help_end,
  359. &HelpDef,
  360. HelpMenu,
  361. M_DrawHelp,
  362. 330,175,
  363. 0
  364. };
  365. //
  366. // M_ReadThis
  367. //
  368. void M_ReadThis(int choice)
  369. {
  370. M_SetupNextMenu(&ReadDef1);
  371. }
  372. void M_ReadThis2(int choice)
  373. {
  374. M_SetupNextMenu(&ReadDef2);
  375. }
  376. void M_FinishReadThis(int choice)
  377. {
  378. M_SetupNextMenu(&MainDef);
  379. }
  380. void M_FinishHelp(int choice) // killough 10/98
  381. {
  382. M_SetupNextMenu(&MainDef);
  383. }
  384. //
  385. // Read This Menus
  386. // Had a "quick hack to fix romero bug"
  387. //
  388. // killough 10/98: updated with new screens
  389. void M_DrawReadThis1(void)
  390. {
  391. inhelpscreens = true;
  392. if (gamemode == shareware)
  393. V_DrawNamePatch(0, 0, 0, "HELP2", CR_DEFAULT, VPT_STRETCH);
  394. else
  395. M_DrawCredits();
  396. }
  397. //
  398. // Read This Menus - optional second page.
  399. //
  400. // killough 10/98: updated with new screens
  401. void M_DrawReadThis2(void)
  402. {
  403. inhelpscreens = true;
  404. if (gamemode == shareware)
  405. M_DrawCredits();
  406. else
  407. V_DrawNamePatch(0, 0, 0, "CREDIT", CR_DEFAULT, VPT_STRETCH);
  408. }
  409. /////////////////////////////
  410. //
  411. // EPISODE SELECT
  412. //
  413. //
  414. // episodes_e provides numbers for the episode menu items. The default is
  415. // 4, to accomodate Ultimate Doom. If the user is running anything else,
  416. // this is accounted for in the code.
  417. //
  418. enum
  419. {
  420. ep1,
  421. ep2,
  422. ep3,
  423. ep4,
  424. ep_end
  425. } episodes_e;
  426. // The definitions of the Episodes menu
  427. menuitem_t EpisodeMenu[]=
  428. {
  429. {1,"M_EPI1", M_Episode,'k'},
  430. {1,"M_EPI2", M_Episode,'t'},
  431. {1,"M_EPI3", M_Episode,'i'},
  432. {1,"M_EPI4", M_Episode,'t'}
  433. };
  434. menu_t EpiDef =
  435. {
  436. ep_end, // # of menu items
  437. &MainDef, // previous menu
  438. EpisodeMenu, // menuitem_t ->
  439. M_DrawEpisode, // drawing routine ->
  440. 48,63, // x,y
  441. ep1 // lastOn
  442. };
  443. //
  444. // M_Episode
  445. //
  446. int epi;
  447. void M_DrawEpisode(void)
  448. {
  449. // CPhipps - patch drawing updated
  450. V_DrawNamePatch(54, 38, 0, "M_EPISOD", CR_DEFAULT, VPT_STRETCH);
  451. }
  452. void M_Episode(int choice)
  453. {
  454. if ( (gamemode == shareware) && choice) {
  455. M_StartMessage(s_SWSTRING,NULL,false); // Ty 03/27/98 - externalized
  456. M_SetupNextMenu(&ReadDef1);
  457. return;
  458. }
  459. // Yet another hack...
  460. if ( (gamemode == registered) && (choice > 2))
  461. {
  462. lprintf( LO_WARN,
  463. "M_Episode: 4th episode requires UltimateDOOM\n");
  464. choice = 0;
  465. }
  466. epi = choice;
  467. M_SetupNextMenu(&NewDef);
  468. }
  469. /////////////////////////////
  470. //
  471. // NEW GAME
  472. //
  473. // numerical values for the New Game menu items
  474. enum
  475. {
  476. killthings,
  477. toorough,
  478. hurtme,
  479. violence,
  480. nightmare,
  481. newg_end
  482. } newgame_e;
  483. // The definitions of the New Game menu
  484. menuitem_t NewGameMenu[]=
  485. {
  486. {1,"M_JKILL", M_ChooseSkill, 'i'},
  487. {1,"M_ROUGH", M_ChooseSkill, 'h'},
  488. {1,"M_HURT", M_ChooseSkill, 'h'},
  489. {1,"M_ULTRA", M_ChooseSkill, 'u'},
  490. {1,"M_NMARE", M_ChooseSkill, 'n'}
  491. };
  492. menu_t NewDef =
  493. {
  494. newg_end, // # of menu items
  495. &EpiDef, // previous menu
  496. NewGameMenu, // menuitem_t ->
  497. M_DrawNewGame, // drawing routine ->
  498. 48,63, // x,y
  499. hurtme // lastOn
  500. };
  501. //
  502. // M_NewGame
  503. //
  504. void M_DrawNewGame(void)
  505. {
  506. // CPhipps - patch drawing updated
  507. V_DrawNamePatch(96, 14, 0, "M_NEWG", CR_DEFAULT, VPT_STRETCH);
  508. V_DrawNamePatch(54, 38, 0, "M_SKILL",CR_DEFAULT, VPT_STRETCH);
  509. }
  510. /* cph - make `New Game' restart the level in a netgame */
  511. static void M_RestartLevelResponse(int ch)
  512. {
  513. if (ch != 'y')
  514. return;
  515. if (demorecording)
  516. exit(0);
  517. currentMenu->lastOn = itemOn;
  518. M_ClearMenus ();
  519. G_RestartLevel ();
  520. }
  521. void M_NewGame(int choice)
  522. {
  523. if (netgame && !demoplayback) {
  524. if (compatibility_level < lxdoom_1_compatibility)
  525. M_StartMessage(s_NEWGAME,NULL,false); // Ty 03/27/98 - externalized
  526. else // CPhipps - query restarting the level
  527. M_StartMessage(s_RESTARTLEVEL,M_RestartLevelResponse,true);
  528. return;
  529. }
  530. if (demorecording) { /* killough 5/26/98: exclude during demo recordings */
  531. M_StartMessage("you can't start a new game\n"
  532. "while recording a demo!\n\n"PRESSKEY,
  533. NULL, false); // killough 5/26/98: not externalized
  534. return;
  535. }
  536. if ( gamemode == commercial )
  537. M_SetupNextMenu(&NewDef);
  538. else
  539. M_SetupNextMenu(&EpiDef);
  540. }
  541. // CPhipps - static
  542. static void M_VerifyNightmare(int ch)
  543. {
  544. if (ch != 'y')
  545. return;
  546. G_DeferedInitNew(nightmare,epi+1,1);
  547. M_ClearMenus ();
  548. }
  549. void M_ChooseSkill(int choice)
  550. {
  551. if (choice == nightmare)
  552. { // Ty 03/27/98 - externalized
  553. M_StartMessage(s_NIGHTMARE,M_VerifyNightmare,true);
  554. return;
  555. }
  556. G_DeferedInitNew(choice,epi+1,1);
  557. M_ClearMenus ();
  558. }
  559. /////////////////////////////
  560. //
  561. // LOAD GAME MENU
  562. //
  563. // numerical values for the Load Game slots
  564. enum
  565. {
  566. load1,
  567. load2,
  568. load3,
  569. load4,
  570. load5,
  571. load6,
  572. load7, //jff 3/15/98 extend number of slots
  573. load8,
  574. load_end
  575. } load_e;
  576. // The definitions of the Load Game screen
  577. menuitem_t LoadMenue[]=
  578. {
  579. {1,"", M_LoadSelect,'1'},
  580. {1,"", M_LoadSelect,'2'},
  581. {1,"", M_LoadSelect,'3'},
  582. {1,"", M_LoadSelect,'4'},
  583. {1,"", M_LoadSelect,'5'},
  584. {1,"", M_LoadSelect,'6'},
  585. {1,"", M_LoadSelect,'7'}, //jff 3/15/98 extend number of slots
  586. {1,"", M_LoadSelect,'8'},
  587. };
  588. menu_t LoadDef =
  589. {
  590. load_end,
  591. &MainDef,
  592. LoadMenue,
  593. M_DrawLoad,
  594. 80,34, //jff 3/15/98 move menu up
  595. 0
  596. };
  597. #define LOADGRAPHIC_Y 8
  598. //
  599. // M_LoadGame & Cie.
  600. //
  601. void M_DrawLoad(void)
  602. {
  603. int i;
  604. //jff 3/15/98 use symbolic load position
  605. // CPhipps - patch drawing updated
  606. V_DrawNamePatch(72 ,LOADGRAPHIC_Y, 0, "M_LOADG", CR_DEFAULT, VPT_STRETCH);
  607. for (i = 0 ; i < load_end ; i++) {
  608. M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
  609. M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
  610. }
  611. }
  612. //
  613. // Draw border for the savegame description
  614. //
  615. void M_DrawSaveLoadBorder(int x,int y)
  616. {
  617. int i;
  618. V_DrawNamePatch(x-8, y+7, 0, "M_LSLEFT", CR_DEFAULT, VPT_STRETCH);
  619. for (i = 0 ; i < 24 ; i++)
  620. {
  621. V_DrawNamePatch(x, y+7, 0, "M_LSCNTR", CR_DEFAULT, VPT_STRETCH);
  622. x += 8;
  623. }
  624. V_DrawNamePatch(x, y+7, 0, "M_LSRGHT", CR_DEFAULT, VPT_STRETCH);
  625. }
  626. //
  627. // User wants to load this game
  628. //
  629. void M_LoadSelect(int choice)
  630. {
  631. // CPhipps - Modified so savegame filename is worked out only internal
  632. // to g_game.c, this only passes the slot.
  633. G_LoadGame(choice, false); // killough 3/16/98, 5/15/98: add slot, cmd
  634. M_ClearMenus ();
  635. }
  636. //
  637. // killough 5/15/98: add forced loadgames
  638. //
  639. static void M_VerifyForcedLoadGame(int ch)
  640. {
  641. if (ch=='y')
  642. G_ForcedLoadGame();
  643. free((char*)messageString); // free the message strdup()'ed below
  644. M_ClearMenus();
  645. }
  646. void M_ForcedLoadGame(const char *msg)
  647. {
  648. M_StartMessage(strdup(msg), M_VerifyForcedLoadGame, true); // free()'d above
  649. }
  650. //
  651. // Selected from DOOM menu
  652. //
  653. void M_LoadGame (int choice)
  654. {
  655. /* killough 5/26/98: exclude during demo recordings
  656. * cph - unless a new demo */
  657. if (demorecording && (compatibility_level < prboom_2_compatibility))
  658. {
  659. M_StartMessage("you can't load a game\n"
  660. "while recording an old demo!\n\n"PRESSKEY,
  661. NULL, false); // killough 5/26/98: not externalized
  662. return;
  663. }
  664. M_SetupNextMenu(&LoadDef);
  665. M_ReadSaveStrings();
  666. }
  667. /////////////////////////////
  668. //
  669. // SAVE GAME MENU
  670. //
  671. // The definitions of the Save Game screen
  672. menuitem_t SaveMenu[]=
  673. {
  674. {1,"", M_SaveSelect,'1'},
  675. {1,"", M_SaveSelect,'2'},
  676. {1,"", M_SaveSelect,'3'},
  677. {1,"", M_SaveSelect,'4'},
  678. {1,"", M_SaveSelect,'5'},
  679. {1,"", M_SaveSelect,'6'},
  680. {1,"", M_SaveSelect,'7'}, //jff 3/15/98 extend number of slots
  681. {1,"", M_SaveSelect,'8'},
  682. };
  683. menu_t SaveDef =
  684. {
  685. load_end, // same number of slots as the Load Game screen
  686. &MainDef,
  687. SaveMenu,
  688. M_DrawSave,
  689. 80,34, //jff 3/15/98 move menu up
  690. 0
  691. };
  692. //
  693. // M_ReadSaveStrings
  694. // read the strings from the savegame files
  695. //
  696. void M_ReadSaveStrings(void)
  697. {
  698. int i;
  699. for (i = 0 ; i < load_end ; i++) {
  700. char name[PATH_MAX+1]; // killough 3/22/98
  701. FILE *fp; // killough 11/98: change to use stdio
  702. /* killough 3/22/98
  703. * cph - add not-demoplayback parameter */
  704. G_SaveGameName(name,sizeof(name),i,false);
  705. fp = fopen(name,"rb");
  706. if (!fp) { // Ty 03/27/98 - externalized:
  707. strcpy(&savegamestrings[i][0],s_EMPTYSTRING);
  708. LoadMenue[i].status = 0;
  709. continue;
  710. }
  711. fread(&savegamestrings[i], SAVESTRINGSIZE, 1, fp);
  712. fclose(fp);
  713. LoadMenue[i].status = 1;
  714. }
  715. }
  716. //
  717. // M_SaveGame & Cie.
  718. //
  719. void M_DrawSave(void)
  720. {
  721. int i;
  722. //jff 3/15/98 use symbolic load position
  723. // CPhipps - patch drawing updated
  724. V_DrawNamePatch(72, LOADGRAPHIC_Y, 0, "M_SAVEG", CR_DEFAULT, VPT_STRETCH);
  725. for (i = 0 ; i < load_end ; i++)
  726. {
  727. M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
  728. M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
  729. }
  730. if (saveStringEnter)
  731. {
  732. i = M_StringWidth(savegamestrings[saveSlot]);
  733. M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_");
  734. }
  735. }
  736. //
  737. // M_Responder calls this when user is finished
  738. //
  739. static void M_DoSave(int slot)
  740. {
  741. G_SaveGame (slot,savegamestrings[slot]);
  742. M_ClearMenus ();
  743. // PICK QUICKSAVE SLOT YET?
  744. if (quickSaveSlot == -2)
  745. quickSaveSlot = slot;
  746. }
  747. //
  748. // User wants to save. Start string input for M_Responder
  749. //
  750. void M_SaveSelect(int choice)
  751. {
  752. // we are going to be intercepting all chars
  753. saveStringEnter = 1;
  754. saveSlot = choice;
  755. strcpy(saveOldString,savegamestrings[choice]);
  756. if (!strcmp(savegamestrings[choice],s_EMPTYSTRING)) // Ty 03/27/98 - externalized
  757. savegamestrings[choice][0] = 0;
  758. saveCharIndex = strlen(savegamestrings[choice]);
  759. }
  760. //
  761. // Selected from DOOM menu
  762. //
  763. void M_SaveGame (int choice)
  764. {
  765. // killough 10/6/98: allow savegames during single-player demo playback
  766. if (!usergame && (!demoplayback || netgame))
  767. {
  768. M_StartMessage(s_SAVEDEAD,NULL,false); // Ty 03/27/98 - externalized
  769. return;
  770. }
  771. if (gamestate != GS_LEVEL)
  772. return;
  773. M_SetupNextMenu(&SaveDef);
  774. M_ReadSaveStrings();
  775. }
  776. /////////////////////////////
  777. //
  778. // OPTIONS MENU
  779. //
  780. // numerical values for the Options menu items
  781. enum
  782. {
  783. general, // killough 10/98
  784. // killough 4/6/98: move setup to be a sub-menu of OPTIONs
  785. setup, // phares 3/21/98
  786. endgame,
  787. messages,
  788. /* detail, obsolete -- killough */
  789. scrnsize,
  790. option_empty1,
  791. mousesens,
  792. /* option_empty2, submenu now -- killough */
  793. soundvol,
  794. opt_end
  795. } options_e;
  796. // The definitions of the Options menu
  797. menuitem_t OptionsMenu[]=
  798. {
  799. // killough 4/6/98: move setup to be a sub-menu of OPTIONs
  800. {1,"M_GENERL", M_General, 'g'}, // killough 10/98
  801. {1,"M_SETUP", M_Setup, 's'}, // phares 3/21/98
  802. {1,"M_ENDGAM", M_EndGame,'e'},
  803. {1,"M_MESSG", M_ChangeMessages,'m'},
  804. /* {1,"M_DETAIL", M_ChangeDetail,'g'}, unused -- killough */
  805. {2,"M_SCRNSZ", M_SizeDisplay,'s'},
  806. {-1,"",0,0},
  807. {1,"M_MSENS", M_ChangeSensitivity,'m'},
  808. /* {-1,"",0}, replaced with submenu -- killough */
  809. {1,"M_SVOL", M_Sound,'s'}
  810. };
  811. menu_t OptionsDef =
  812. {
  813. opt_end,
  814. &MainDef,
  815. OptionsMenu,
  816. M_DrawOptions,
  817. 60,37,
  818. 0
  819. };
  820. //
  821. // M_Options
  822. //
  823. char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"};
  824. char msgNames[2][9] = {"M_MSGOFF","M_MSGON"};
  825. void M_DrawOptions(void)
  826. {
  827. // CPhipps - patch drawing updated
  828. // proff/nicolas 09/20/98 -- changed for hi-res
  829. V_DrawNamePatch(108, 15, 0, "M_OPTTTL", CR_DEFAULT, VPT_STRETCH);
  830. V_DrawNamePatch(OptionsDef.x + 120, OptionsDef.y+LINEHEIGHT*messages, 0,
  831. msgNames[showMessages], CR_DEFAULT, VPT_STRETCH);
  832. M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1),
  833. 9,screenSize);
  834. }
  835. void M_Options(int choice)
  836. {
  837. M_SetupNextMenu(&OptionsDef);
  838. }
  839. /////////////////////////////
  840. //
  841. // M_QuitDOOM
  842. //
  843. int quitsounds[8] =
  844. {
  845. sfx_pldeth,
  846. sfx_dmpain,
  847. sfx_popain,
  848. sfx_slop,
  849. sfx_telept,
  850. sfx_posit1,
  851. sfx_posit3,
  852. sfx_sgtatk
  853. };
  854. int quitsounds2[8] =
  855. {
  856. sfx_vilact,
  857. sfx_getpow,
  858. sfx_boscub,
  859. sfx_slop,
  860. sfx_skeswg,
  861. sfx_kntdth,
  862. sfx_bspact,
  863. sfx_sgtatk
  864. };
  865. static void M_QuitResponse(int ch)
  866. {
  867. if (ch != 'y')
  868. return;
  869. if ((!netgame || demoplayback) // killough 12/98
  870. && !nosfxparm && snd_card) // avoid delay if no sound card
  871. {
  872. int i;
  873. if (gamemode == commercial)
  874. S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
  875. else
  876. S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
  877. // wait till all sounds stopped or 3 seconds are over
  878. i = 30;
  879. while (i>0) {
  880. I_uSleep(100000); // CPhipps - don't thrash cpu in this loop
  881. if (!I_AnySoundStillPlaying())
  882. break;
  883. i--;
  884. }
  885. }
  886. exit(0); // killough
  887. }
  888. void M_QuitDOOM(int choice)
  889. {
  890. static char endstring[160];
  891. // We pick index 0 which is language sensitive,
  892. // or one at random, between 1 and maximum number.
  893. // Ty 03/27/98 - externalized DOSY as a string s_DOSY that's in the sprintf
  894. if (language != english)
  895. sprintf(endstring,"%s\n\n%s",s_DOSY, endmsg[0] );
  896. else // killough 1/18/98: fix endgame message calculation:
  897. sprintf(endstring,"%s\n\n%s", endmsg[gametic%(NUM_QUITMESSAGES-1)+1], s_DOSY);
  898. M_StartMessage(endstring,M_QuitResponse,true);
  899. }
  900. /////////////////////////////
  901. //
  902. // SOUND VOLUME MENU
  903. //
  904. // numerical values for the Sound Volume menu items
  905. // The 'empty' slots are where the sliding scales appear.
  906. enum
  907. {
  908. sfx_vol,
  909. sfx_empty1,
  910. music_vol,
  911. sfx_empty2,
  912. sound_end
  913. } sound_e;
  914. // The definitions of the Sound Volume menu
  915. menuitem_t SoundMenu[]=
  916. {
  917. {2,"M_SFXVOL",M_SfxVol,'s'},
  918. {-1,"",0,0},
  919. {2,"M_MUSVOL",M_MusicVol,'m'},
  920. {-1,"",0,0}
  921. };
  922. menu_t SoundDef =
  923. {
  924. sound_end,
  925. &OptionsDef,
  926. SoundMenu,
  927. M_DrawSound,
  928. 80,64,
  929. 0
  930. };
  931. //
  932. // Change Sfx & Music volumes
  933. //
  934. void M_DrawSound(void)
  935. {
  936. // CPhipps - patch drawing updated
  937. V_DrawNamePatch(60, 38, 0, "M_SVOL", CR_DEFAULT, VPT_STRETCH);
  938. M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1),16,snd_SfxVolume);
  939. M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1),16,snd_MusicVolume);
  940. }
  941. void M_Sound(int choice)
  942. {
  943. M_SetupNextMenu(&SoundDef);
  944. }
  945. void M_SfxVol(int choice)
  946. {
  947. switch(choice)
  948. {
  949. case 0:
  950. if (snd_SfxVolume)
  951. snd_SfxVolume--;
  952. break;
  953. case 1:
  954. if (snd_SfxVolume < 15)
  955. snd_SfxVolume++;
  956. break;
  957. }
  958. S_SetSfxVolume(snd_SfxVolume /* *8 */);
  959. }
  960. void M_MusicVol(int choice)
  961. {
  962. switch(choice)
  963. {
  964. case 0:
  965. if (snd_MusicVolume)
  966. snd_MusicVolume--;
  967. break;
  968. case 1:
  969. if (snd_MusicVolume < 15)
  970. snd_MusicVolume++;
  971. break;
  972. }
  973. S_SetMusicVolume(snd_MusicVolume /* *8 */);
  974. }
  975. /////////////////////////////
  976. //
  977. // MOUSE SENSITIVITY MENU -- killough
  978. //
  979. // numerical values for the Mouse Sensitivity menu items
  980. // The 'empty' slots are where the sliding scales appear.
  981. enum
  982. {
  983. mouse_horiz,
  984. mouse_empty1,
  985. mouse_vert,
  986. mouse_empty2,
  987. mouse_end
  988. } mouse_e;
  989. // The definitions of the Mouse Sensitivity menu
  990. menuitem_t MouseMenu[]=
  991. {
  992. {2,"M_HORSEN",M_MouseHoriz,'h'},
  993. {-1,"",0,0},
  994. {2,"M_VERSEN",M_MouseVert,'v'},
  995. {-1,"",0,0}
  996. };
  997. menu_t MouseDef =
  998. {
  999. mouse_end,
  1000. &OptionsDef,
  1001. MouseMenu,
  1002. M_DrawMouse,
  1003. 60,64,
  1004. 0
  1005. };
  1006. // I'm using a scale of 100 since I don't know what's normal -- killough.
  1007. #define MOUSE_SENS_MAX 100
  1008. //
  1009. // Change Mouse Sensitivities -- killough
  1010. //
  1011. void M_DrawMouse(void)
  1012. {
  1013. int mhmx,mvmx; /* jff 4/3/98 clamp drawn position 99max mead */
  1014. // CPhipps - patch drawing updated
  1015. V_DrawNamePatch(60, 38, 0, "M_MSENS", CR_DEFAULT, VPT_STRETCH);
  1016. //jff 4/3/98 clamp horizontal sensitivity display
  1017. mhmx = mouseSensitivity_horiz>99? 99 : mouseSensitivity_horiz; /*mead*/
  1018. M_DrawThermo(MouseDef.x,MouseDef.y+LINEHEIGHT*(mouse_horiz+1),100,mhmx);
  1019. //jff 4/3/98 clamp vertical sensitivity display
  1020. mvmx = mouseSensitivity_vert>99? 99 : mouseSensitivity_vert; /*mead*/
  1021. M_DrawThermo(MouseDef.x,MouseDef.y+LINEHEIGHT*(mouse_vert+1),100,mvmx);
  1022. }
  1023. void M_ChangeSensitivity(int choice)
  1024. {
  1025. M_SetupNextMenu(&MouseDef); // killough
  1026. // switch(choice)
  1027. // {
  1028. // case 0:
  1029. // if (mouseSensitivity)
  1030. // mouseSensitivity--;
  1031. // break;
  1032. // case 1:
  1033. // if (mouseSensitivity < 9)
  1034. // mouseSensitivity++;
  1035. // break;
  1036. // }
  1037. }
  1038. void M_MouseHoriz(int choice)
  1039. {
  1040. M_Mouse(choice, &mouseSensitivity_horiz);
  1041. }
  1042. void M_MouseVert(int choice)
  1043. {
  1044. M_Mouse(choice, &mouseSensitivity_vert);
  1045. }
  1046. void M_Mouse(int choice, int *sens)
  1047. {
  1048. switch(choice)
  1049. {
  1050. case 0:
  1051. if (*sens)
  1052. --*sens;
  1053. break;
  1054. case 1:
  1055. if (*sens < 99)
  1056. ++*sens; /*mead*/
  1057. break;
  1058. }
  1059. }
  1060. /////////////////////////////
  1061. //
  1062. // M_QuickSave
  1063. //
  1064. char tempstring[80];
  1065. static void M_QuickSaveResponse(int ch)
  1066. {
  1067. if (ch == 'y') {
  1068. M_DoSave(quickSaveSlot);
  1069. S_StartSound(NULL,sfx_swtchx);
  1070. }
  1071. }
  1072. void M_QuickSave(void)
  1073. {
  1074. if (!usergame && (!demoplayback || netgame)) { /* killough 10/98 */
  1075. S_StartSound(NULL,sfx_oof);
  1076. return;
  1077. }
  1078. if (gamestate != GS_LEVEL)
  1079. return;
  1080. if (quickSaveSlot < 0) {
  1081. M_StartControlPanel();
  1082. M_ReadSaveStrings();
  1083. M_SetupNextMenu(&SaveDef);
  1084. quickSaveSlot = -2; // means to pick a slot now
  1085. return;
  1086. }
  1087. sprintf(tempstring,s_QSPROMPT,savegamestrings[quickSaveSlot]); // Ty 03/27/98 - externalized
  1088. M_StartMessage(tempstring,M_QuickSaveResponse,true);
  1089. }
  1090. /////////////////////////////
  1091. //
  1092. // M_QuickLoad
  1093. //
  1094. static void M_QuickLoadResponse(int ch)
  1095. {
  1096. if (ch == 'y') {
  1097. M_LoadSelect(quickSaveSlot);
  1098. S_StartSound(NULL,sfx_swtchx);
  1099. }
  1100. }
  1101. void M_QuickLoad(void)
  1102. {
  1103. // cph - removed restriction against quickload in a netgame
  1104. if (demorecording) { // killough 5/26/98: exclude during demo recordings
  1105. M_StartMessage("you can't quickload\n"
  1106. "while recording a demo!\n\n"PRESSKEY,
  1107. NULL, false); // killough 5/26/98: not externalized
  1108. return;
  1109. }
  1110. if (quickSaveSlot < 0) {
  1111. M_StartMessage(s_QSAVESPOT,NULL,false); // Ty 03/27/98 - externalized
  1112. return;
  1113. }
  1114. sprintf(tempstring,s_QLPROMPT,savegamestrings[quickSaveSlot]); // Ty 03/27/98 - externalized
  1115. M_StartMessage(tempstring,M_QuickLoadResponse,true);
  1116. }
  1117. /////////////////////////////
  1118. //
  1119. // M_EndGame
  1120. //
  1121. static void M_EndGameResponse(int ch)
  1122. {
  1123. if (ch != 'y')
  1124. return;
  1125. // killough 5/26/98: make endgame quit if recording or playing back demo
  1126. if (demorecording || singledemo)
  1127. G_CheckDemoStatus();
  1128. currentMenu->lastOn = itemOn;
  1129. M_ClearMenus ();
  1130. D_StartTitle ();
  1131. }
  1132. void M_EndGame(int choice)
  1133. {
  1134. if (netgame)
  1135. {
  1136. M_StartMessage(s_NETEND,NULL,false); // Ty 03/27/98 - externalized
  1137. return;
  1138. }
  1139. M_StartMessage(s_ENDGAME,M_EndGameResponse,true); // Ty 03/27/98 - externalized
  1140. }
  1141. /////////////////////////////
  1142. //
  1143. // Toggle messages on/off
  1144. //
  1145. void M_ChangeMessages(int choice)
  1146. {
  1147. // warning: unused parameter `int choice'
  1148. choice = 0;
  1149. showMessages = 1 - showMessages;
  1150. if (!showMessages)
  1151. players[consoleplayer].message = s_MSGOFF; // Ty 03/27/98 - externalized
  1152. else
  1153. players[consoleplayer].message = s_MSGON ; // Ty 03/27/98 - externalized
  1154. message_dontfuckwithme = true;
  1155. }
  1156. /////////////////////////////
  1157. //
  1158. // CHANGE DISPLAY SIZE
  1159. //
  1160. // jff 2/23/98 restored to pre-HUD state
  1161. // hud_active controlled soley by F5=key_detail (key_hud)
  1162. // hud_displayed is toggled by + or = in fullscreen
  1163. // hud_displayed is cleared by -
  1164. void M_SizeDisplay(int choice)
  1165. {
  1166. switch(choice) {
  1167. case 0:
  1168. if (screenSize > 0) {
  1169. screenblocks--;
  1170. screenSize--;
  1171. hud_displayed = 0;
  1172. }
  1173. break;
  1174. case 1:
  1175. if (screenSize < 8) {
  1176. screenblocks++;
  1177. screenSize++;
  1178. }
  1179. else
  1180. hud_displayed = !hud_displayed;
  1181. break;
  1182. }
  1183. R_SetViewSize (screenblocks /*, detailLevel obsolete -- killough */);
  1184. }
  1185. //
  1186. // End of Original Menus
  1187. //
  1188. /////////////////////////////////////////////////////////////////////////////
  1189. /////////////////////////////////////////////////////////////////////////////
  1190. //
  1191. // SETUP MENU (phares)
  1192. //
  1193. // We've added a set of Setup Screens from which you can configure a number
  1194. // of variables w/o having to restart the game. There are 7 screens:
  1195. //
  1196. // Key Bindings
  1197. // Weapons
  1198. // Status Bar / HUD
  1199. // Automap
  1200. // Enemies
  1201. // Messages
  1202. // Chat Strings
  1203. //
  1204. // killough 10/98: added Compatibility and General menus
  1205. //
  1206. /////////////////////////////
  1207. //
  1208. // booleans for setup screens
  1209. // these tell you what state the setup screens are in, and whether any of
  1210. // the overlay screens (automap colors, reset button message) should be
  1211. // displayed
  1212. boolean setup_active = false; // in one of the setup screens
  1213. boolean set_keybnd_active = false; // in key binding setup screens
  1214. boolean set_weapon_active = false; // in weapons setup screen
  1215. boolean set_status_active = false; // in status bar/hud setup screen
  1216. boolean set_auto_active = false; // in automap setup screen
  1217. boolean set_enemy_active = false; // in enemies setup screen
  1218. boolean set_mess_active = false; // in messages setup screen
  1219. boolean set_chat_active = false; // in chat string setup screen
  1220. boolean setup_select = false; // changing an item
  1221. boolean setup_gather = false; // gathering keys for value
  1222. boolean colorbox_active = false; // color palette being shown
  1223. boolean default_verify = false; // verify reset defaults decision
  1224. boolean set_general_active = false;
  1225. boolean set_compat_active = false;
  1226. /////////////////////////////
  1227. //
  1228. // set_menu_itemon is an index that starts at zero, and tells you which
  1229. // item on the current screen the cursor is sitting on.
  1230. //
  1231. // current_setup_menu is a pointer to the current setup menu table.
  1232. static int set_menu_itemon; // which setup item is selected? // phares 3/98
  1233. setup_menu_t* current_setup_menu; // points to current setup menu table
  1234. /////////////////////////////
  1235. //
  1236. // The menu_buffer is used to construct strings for display on the screen.
  1237. static char menu_buffer[64];
  1238. /////////////////////////////
  1239. //
  1240. // The setup_e enum is used to provide a unique number for each group of Setup
  1241. // Screens.
  1242. enum
  1243. {
  1244. set_compat,
  1245. set_key_bindings,
  1246. set_weapons,
  1247. set_statbar,
  1248. set_automap,
  1249. set_enemy,
  1250. set_messages,
  1251. set_chatstrings,
  1252. set_setup_end
  1253. } setup_e;
  1254. int setup_screen; // the current setup screen. takes values from setup_e
  1255. /////////////////////////////
  1256. //
  1257. // SetupMenu is the definition of what the main Setup Screen should look
  1258. // like. Each entry shows that the cursor can land on each item (1), the
  1259. // built-in graphic lump (i.e. "M_KEYBND") that should be displayed,
  1260. // the program which takes over when an item is selected, and the hotkey
  1261. // associated with the item.
  1262. menuitem_t SetupMenu[]=
  1263. {
  1264. {1,"M_COMPAT",M_Compat, 'p'},
  1265. {1,"M_KEYBND",M_KeyBindings,'k'},
  1266. {1,"M_WEAP" ,M_Weapons, 'w'},
  1267. {1,"M_STAT" ,M_StatusBar, 's'},
  1268. {1,"M_AUTO" ,M_Automap, 'a'},
  1269. {1,"M_ENEM" ,M_Enemy, 'e'},
  1270. {1,"M_MESS" ,M_Messages, 'm'},
  1271. {1,"M_CHAT" ,M_ChatStrings,'c'},
  1272. };
  1273. /////////////////////////////
  1274. //
  1275. // M_DoNothing does just that: nothing. Just a placeholder.
  1276. static void M_DoNothing(int choice)
  1277. {
  1278. }
  1279. /////////////////////////////
  1280. //
  1281. // Items needed to satisfy the 'Big Font' menu structures:
  1282. //
  1283. // the generic_setup_e enum mimics the 'Big Font' menu structures, but
  1284. // means nothing to the Setup Menus.
  1285. enum
  1286. {
  1287. generic_setupempty1,
  1288. generic_setup_end
  1289. } generic_setup_e;
  1290. // Generic_Setup is a do-nothing definition that the mainstream Menu code
  1291. // can understand, while the Setup Menu code is working. Another placeholder.
  1292. menuitem_t Generic_Setup[] =
  1293. {
  1294. {1,"",M_DoNothing,0}
  1295. };
  1296. /////////////////////////////
  1297. //
  1298. // SetupDef is the menu definition that the mainstream Menu code understands.
  1299. // This is used by M_Setup (below) to define what is drawn and what is done
  1300. // with the main Setup screen.
  1301. menu_t SetupDef =
  1302. {
  1303. set_setup_end, // number of Setup Menu items (Key Bindings, etc.)
  1304. &OptionsDef, // menu to return to when BACKSPACE is hit on this menu
  1305. SetupMenu, // definition of items to show on the Setup Screen
  1306. M_DrawSetup, // program that draws the Setup Screen
  1307. 59,37, // x,y position of the skull (modified when the skull is
  1308. // drawn). The skull is parked on the upper-left corner
  1309. // of the Setup screens, since it isn't needed as a cursor
  1310. 0 // last item the user was on for this menu
  1311. };
  1312. /////////////////////////////
  1313. //
  1314. // Here are the definitions of the individual Setup Menu screens. They
  1315. // follow the format of the 'Big Font' menu structures. See the comments
  1316. // for SetupDef (above) to help understand what each of these says.
  1317. menu_t KeybndDef =
  1318. {
  1319. generic_setup_end,
  1320. &SetupDef,
  1321. Generic_Setup,
  1322. M_DrawKeybnd,
  1323. 34,5, // skull drawn here
  1324. 0
  1325. };
  1326. menu_t WeaponDef =
  1327. {
  1328. generic_setup_end,
  1329. &SetupDef,
  1330. Generic_Setup,
  1331. M_DrawWeapons,
  1332. 34,5, // skull drawn here
  1333. 0
  1334. };
  1335. menu_t StatusHUDDef =
  1336. {
  1337. generic_setup_end,
  1338. &SetupDef,
  1339. Generic_Setup,
  1340. M_DrawStatusHUD,
  1341. 34,5, // skull drawn here
  1342. 0
  1343. };
  1344. menu_t AutoMapDef =
  1345. {
  1346. generic_setup_end,
  1347. &SetupDef,
  1348. Generic_Setup,
  1349. M_DrawAutoMap,
  1350. 34,5, // skull drawn here
  1351. 0
  1352. };
  1353. menu_t EnemyDef = // phares 4/08/98
  1354. {
  1355. generic_setup_end,
  1356. &SetupDef,
  1357. Generic_Setup,
  1358. M_DrawEnemy,
  1359. 34,5, // skull drawn here
  1360. 0
  1361. };
  1362. menu_t MessageDef = // phares 4/08/98
  1363. {
  1364. generic_setup_end,
  1365. &SetupDef,
  1366. Generic_Setup,
  1367. M_DrawMessages,
  1368. 34,5, // skull drawn here
  1369. 0
  1370. };
  1371. menu_t ChatStrDef = // phares 4/10/98
  1372. {
  1373. generic_setup_end,
  1374. &SetupDef,
  1375. Generic_Setup,
  1376. M_DrawChatStrings,
  1377. 34,5, // skull drawn here
  1378. 0
  1379. };
  1380. menu_t GeneralDef = // killough 10/98
  1381. {
  1382. generic_setup_end,
  1383. &OptionsDef,
  1384. Generic_Setup,
  1385. M_DrawGeneral,
  1386. 34,5, // skull drawn here
  1387. 0
  1388. };
  1389. menu_t CompatDef = // killough 10/98
  1390. {
  1391. generic_setup_end,
  1392. &SetupDef,
  1393. Generic_Setup,
  1394. M_DrawCompat,
  1395. 34,5, // skull drawn here
  1396. 0
  1397. };
  1398. /////////////////////////////
  1399. //
  1400. // Draws the Title for the main Setup screen
  1401. void M_DrawSetup(void)
  1402. {
  1403. // CPhipps - patch drawing updated
  1404. V_DrawNamePatch(124, 15, 0, "M_SETUP", CR_DEFAULT, VPT_STRETCH);
  1405. }
  1406. /////////////////////////////
  1407. //
  1408. // Uses the SetupDef structure to draw the menu items for the main
  1409. // Setup screen
  1410. void M_Setup(int choice)
  1411. {
  1412. M_SetupNextMenu(&SetupDef);
  1413. }
  1414. /////////////////////////////
  1415. //
  1416. // Data that's used by the Setup screen code
  1417. //
  1418. // Establish the message colors to be used
  1419. #define CR_TITLE CR_GOLD
  1420. #define CR_SET CR_GREEN
  1421. #define CR_ITEM CR_RED
  1422. #define CR_HILITE CR_ORANGE
  1423. #define CR_SELECT CR_GRAY
  1424. // Data used by the Automap color selection code
  1425. #define CHIP_SIZE 7 // size of color block for colored items
  1426. #define COLORPALXORIG ((320 - 16*(CHIP_SIZE+1))/2)
  1427. #define COLORPALYORIG ((200 - 16*(CHIP_SIZE+1))/2)
  1428. #define PAL_BLACK 0
  1429. #define PAL_WHITE 4
  1430. // Data used by the Chat String editing code
  1431. #define CHAT_STRING_BFR_SIZE 128
  1432. // chat strings must fit in this screen space
  1433. // killough 10/98: reduced, for more general uses
  1434. #define MAXCHATWIDTH 272
  1435. int chat_index;
  1436. char* chat_string_buffer; // points to new chat strings while editing
  1437. /////////////////////////////
  1438. //
  1439. // phares 4/17/98:
  1440. // Added 'Reset to Defaults' Button to Setup Menu screens
  1441. // This is a small button that sits in the upper-right-hand corner of
  1442. // the first screen for each group. It blinks when selected, thus the
  1443. // two patches, which it toggles back and forth.
  1444. char ResetButtonName[2][8] = {"M_BUTT1","M_BUTT2"};
  1445. /////////////////////////////
  1446. //
  1447. // phares 4/18/98:
  1448. // Consolidate Item drawing code
  1449. //
  1450. // M_DrawItem draws the description of the provided item (the left-hand
  1451. // part). A different color is used for the text depending on whether the
  1452. // item is selected or not, or whether it's about to change.
  1453. // CPhipps - static, hanging else removed, const parameter
  1454. static void M_DrawItem(const setup_menu_t* s)
  1455. {
  1456. int x = s->m_x;
  1457. int y = s->m_y;
  1458. int flags = s->m_flags;
  1459. if (flags & S_RESET)
  1460. // This item is the reset button
  1461. // Draw the 'off' version if this isn't the current menu item
  1462. // Draw the blinking version in tune with the blinking skull otherwise
  1463. // proff/nicolas 09/20/98 -- changed for hi-res
  1464. // CPhipps - Patch drawing updated, reformatted
  1465. V_DrawNamePatch(x, y, 0, ResetButtonName[(flags & (S_HILITE|S_SELECT)) ? whichSkull : 0],
  1466. CR_DEFAULT, VPT_STRETCH);
  1467. else { // Draw the item string
  1468. char *p, *t;
  1469. int w = 0;
  1470. int color =
  1471. flags & S_SELECT ? CR_SELECT :
  1472. flags & S_HILITE ? CR_HILITE :
  1473. flags & (S_TITLE|S_NEXT|S_PREV) ? CR_TITLE : CR_ITEM; // killough 10/98
  1474. /* killough 10/98:
  1475. * Enhance to support multiline text separated by newlines.
  1476. * This supports multiline items on horizontally-crowded menus.
  1477. */
  1478. for (p = t = strdup(s->m_text); (p = strtok(p,"\n")); y += 8, p = NULL)
  1479. { /* killough 10/98: support left-justification: */
  1480. strcpy(menu_buffer,p);
  1481. if (!(flags & S_LEFTJUST))
  1482. w = M_GetPixelWidth(menu_buffer) + 4;
  1483. M_DrawMenuString(x - w, y ,color);
  1484. }
  1485. free(t);
  1486. }
  1487. }
  1488. // If a number item is being changed, allow up to N keystrokes to 'gather'
  1489. // the value. Gather_count tells you how many you have so far. The legality
  1490. // of what is gathered is determined by the low/high settings for the item.
  1491. #define MAXGATHER 5
  1492. int gather_count;
  1493. char gather_buffer[MAXGATHER+1]; // killough 10/98: make input character-based
  1494. /////////////////////////////
  1495. //
  1496. // phares 4/18/98:
  1497. // Consolidate Item Setting drawing code
  1498. //
  1499. // M_DrawSetting draws the setting of the provided item (the right-hand
  1500. // part. It determines the text color based on whether the item is
  1501. // selected or being changed. Then, depending on the type of item, it
  1502. // displays the appropriate setting value: yes/no, a key binding, a number,
  1503. // a paint chip, etc.
  1504. static void M_DrawSetting(const setup_menu_t* s)
  1505. {
  1506. int x = s->m_x, y = s->m_y, flags = s->m_flags, color;
  1507. // Determine color of the text. This may or may not be used later,
  1508. // depending on whether the item is a text string or not.
  1509. color = flags & S_SELECT ? CR_SELECT : flags & S_HILITE ? CR_HILITE : CR_SET;
  1510. // Is the item a YES/NO item?
  1511. if (flags & S_YESNO) {
  1512. strcpy(menu_buffer,*s->var.def->location.pi ? "YES" : "NO");
  1513. M_DrawMenuString(x,y,color);
  1514. return;
  1515. }
  1516. // Is the item a simple number?
  1517. if (flags & S_NUM) {
  1518. // killough 10/98: We must draw differently for items being gathered.
  1519. if (flags & (S_HILITE|S_SELECT) && setup_gather) {
  1520. gather_buffer[gather_count] = 0;
  1521. strcpy(menu_buffer, gather_buffer);
  1522. }
  1523. else
  1524. sprintf(menu_buffer,"%d",*s->var.def->location.pi);
  1525. M_DrawMenuString(x,y,color);
  1526. return;
  1527. }
  1528. // Is the item a key binding?
  1529. if (flags & S_KEY) { // Key Binding
  1530. int *key = s->var.m_key;
  1531. // Draw the key bound to the action
  1532. if (key) {
  1533. M_GetKeyString(*key,0); // string to display
  1534. if (key == &key_use) {
  1535. // For the 'use' key, you have to build the string
  1536. if (s->m_mouse)
  1537. sprintf(menu_buffer+strlen(menu_buffer), "/DBL-CLK MB%d",*s->m_mouse+1);
  1538. if (s->m_joy)
  1539. sprintf(menu_buffer+strlen(menu_buffer), "/JSB%d",*s->m_joy+1);
  1540. }
  1541. else if (key == &key_up || key == &key_speed ||
  1542. key == &key_fire || key == &key_strafe)
  1543. {
  1544. if (s->m_mouse)
  1545. sprintf(menu_buffer+strlen(menu_buffer), "/MB%d",
  1546. *s->m_mouse+1);
  1547. if (s->m_joy)
  1548. sprintf(menu_buffer+strlen(menu_buffer), "/JSB%d",
  1549. *s->m_joy+1);
  1550. }
  1551. M_DrawMenuString(x,y,color);
  1552. }
  1553. return;
  1554. }
  1555. // Is the item a weapon number?
  1556. // OR, Is the item a colored text string from the Automap?
  1557. //
  1558. // killough 10/98: removed special code, since the rest of the engine
  1559. // already takes care of it, and this code prevented the user from setting
  1560. // their overall weapons preferences while playing Doom 1.
  1561. //
  1562. // killough 11/98: consolidated weapons code with color range code
  1563. if (flags & (S_WEAP|S_CRITEM)) // weapon number or color range
  1564. {
  1565. sprintf(menu_buffer,"%d", *s->var.def->location.pi);
  1566. M_DrawMenuString(x,y, flags & S_CRITEM ? *s->var.def->location.pi : color);
  1567. return;
  1568. }
  1569. // Is the item a paint chip?
  1570. if (flags & S_COLOR) // Automap paint chip
  1571. {
  1572. int ch;
  1573. ch = *s->var.def->location.pi;
  1574. // proff 12/6/98: Drawing of colorchips completly changed for hi-res, it now uses a patch
  1575. // draw the paint chip
  1576. V_FillRect(0, x*SCREENWIDTH/320, (y-1)*SCREENHEIGHT/200,
  1577. 8*SCREENWIDTH/320, 8*SCREENHEIGHT/200,
  1578. PAL_BLACK);
  1579. V_FillRect(0, (x+1)*SCREENWIDTH/320, y*SCREENHEIGHT/200,
  1580. 6*SCREENWIDTH/320, 6*SCREENHEIGHT/200,
  1581. (byte)ch);
  1582. if (!ch) // don't show this item in automap mode
  1583. V_DrawNamePatch(x+1,y,0,"M_PALNO", CR_DEFAULT, VPT_STRETCH);
  1584. return;
  1585. }
  1586. // Is the item a chat string?
  1587. // killough 10/98: or a filename?
  1588. if (flags & S_STRING) {
  1589. /* cph - cast to char* as it's really a Z_Strdup'd string (see m_misc.h) */
  1590. char *text = (char*)*s->var.def->location.ppsz;
  1591. // Are we editing this string? If so, display a cursor under
  1592. // the correct character.
  1593. if (setup_select && (s->m_flags & (S_HILITE|S_SELECT))) {
  1594. int cursor_start, char_width;
  1595. char c[2];
  1596. // If the string is too wide for the screen, trim it back,
  1597. // one char at a time until it fits. This should only occur
  1598. // while you're editing the string.
  1599. while (M_GetPixelWidth(text) >= MAXCHATWIDTH) {
  1600. int len = strlen(text);
  1601. text[--len] = 0;
  1602. if (chat_index > len)
  1603. chat_index--;
  1604. }
  1605. // Find the distance from the beginning of the string to
  1606. // where the cursor should be drawn, plus the width of
  1607. // the char the cursor is under..
  1608. *c = text[chat_index]; // hold temporarily
  1609. c[1] = 0;
  1610. char_width = M_GetPixelWidth(c);
  1611. if (char_width == 1)
  1612. char_width = 7; // default for end of line
  1613. text[chat_index] = 0; // NULL to get cursor position
  1614. cursor_start = M_GetPixelWidth(text);
  1615. text[chat_index] = *c; // replace stored char
  1616. // Now draw the cursor
  1617. // proff 12/6/98: Drawing of cursor changed for hi-res
  1618. V_FillRect(0, ((x+cursor_start-1)*SCREENWIDTH)/320, (y*SCREENHEIGHT)/200,
  1619. (char_width*SCREENWIDTH)/320, 9*SCREENHEIGHT/200, PAL_WHITE);
  1620. }
  1621. // Draw the setting for the item
  1622. strcpy(menu_buffer,text);
  1623. M_DrawMenuString(x,y,color);
  1624. return;
  1625. }
  1626. // Is the item a selection of choices?
  1627. if (flags & S_CHOICE) {
  1628. if (s->var.def->type == def_int) {
  1629. if (s->selectstrings == NULL) {
  1630. sprintf(menu_buffer,"%d",*s->var.def->location.pi);
  1631. } else {
  1632. strcpy(menu_buffer,s->selectstrings[*s->var.def->location.pi]);
  1633. }
  1634. }
  1635. if (s->var.def->type == def_str) {
  1636. sprintf(menu_buffer,"%s", *s->var.def->location.ppsz);
  1637. }
  1638. M_DrawMenuString(x,y,color);
  1639. return;
  1640. }
  1641. }
  1642. /////////////////////////////
  1643. //
  1644. // M_DrawScreenItems takes the data for each menu item and gives it to
  1645. // the drawing routines above.
  1646. // CPhipps - static, const parameter, formatting
  1647. static void M_DrawScreenItems(const setup_menu_t* src)
  1648. {
  1649. if (print_warning_about_changes > 0) { /* killough 8/15/98: print warning */
  1650. if (warning_about_changes & S_BADVAL) {
  1651. strcpy(menu_buffer, "Value out of Range");
  1652. M_DrawMenuString(100,176,CR_RED);
  1653. } else if (warning_about_changes & S_PRGWARN) {
  1654. strcpy(menu_buffer, "Warning: Program must be restarted to see changes");
  1655. M_DrawMenuString(3, 176, CR_RED);
  1656. } else if (warning_about_changes & S_BADVID) {
  1657. strcpy(menu_buffer, "Video mode not supported");
  1658. M_DrawMenuString(80,176,CR_RED);
  1659. } else {
  1660. strcpy(menu_buffer, "Warning: Changes are pending until next game");
  1661. M_DrawMenuString(18,184,CR_RED);
  1662. }
  1663. }
  1664. while (!(src->m_flags & S_END)) {
  1665. // See if we're to draw the item description (left-hand part)
  1666. if (src->m_flags & S_SHOWDESC)
  1667. M_DrawItem(src);
  1668. // See if we're to draw the setting (right-hand part)
  1669. if (src->m_flags & S_SHOWSET)
  1670. M_DrawSetting(src);
  1671. src++;
  1672. }
  1673. }
  1674. /////////////////////////////
  1675. //
  1676. // Data used to draw the "are you sure?" dialogue box when resetting
  1677. // to defaults.
  1678. #define VERIFYBOXXORG 66
  1679. #define VERIFYBOXYORG 88
  1680. #define PAL_GRAY1 91
  1681. #define PAL_GRAY2 98
  1682. #define PAL_GRAY3 105
  1683. // And the routine to draw it.
  1684. static void M_DrawDefVerify(void)
  1685. {
  1686. // proff 12/6/98: Drawing of verify box changed for hi-res, it now uses a patch
  1687. V_DrawNamePatch(VERIFYBOXXORG,VERIFYBOXYORG,0,"M_VBOX",CR_DEFAULT,VPT_STRETCH);
  1688. // The blinking messages is keyed off of the blinking of the
  1689. // cursor skull.
  1690. if (whichSkull) { // blink the text
  1691. strcpy(menu_buffer,"Reset to defaults? (Y or N)");
  1692. M_DrawMenuString(VERIFYBOXXORG+8,VERIFYBOXYORG+8,CR_RED);
  1693. }
  1694. }
  1695. /////////////////////////////
  1696. //
  1697. // phares 4/18/98:
  1698. // M_DrawInstructions writes the instruction text just below the screen title
  1699. //
  1700. // cph 2006/08/06 - go back to the Boom version, and then clean up by using
  1701. // M_DrawStringCentered (much better than all those magic 'x' valies!)
  1702. static void M_DrawInstructions(void)
  1703. {
  1704. int flags = current_setup_menu[set_menu_itemon].m_flags;
  1705. // There are different instruction messages depending on whether you
  1706. // are changing an item or just sitting on it.
  1707. if (setup_select) {
  1708. switch (flags & (S_KEY | S_YESNO | S_WEAP | S_NUM | S_COLOR | S_CRITEM | S_CHAT | S_RESET | S_FILE | S_CHOICE)) {
  1709. case S_KEY:
  1710. // See if a joystick or mouse button setting is allowed for
  1711. // this item.
  1712. if (current_setup_menu[set_menu_itemon].m_mouse || current_setup_menu[set_menu_itemon].m_joy)
  1713. M_DrawStringCentered(160, 20, CR_SELECT, "Press key or button for this action");
  1714. else
  1715. M_DrawStringCentered(160, 20, CR_SELECT, "Press key for this action");
  1716. break;
  1717. case S_YESNO:
  1718. M_DrawStringCentered(160, 20, CR_SELECT, "Press ENTER key to toggle");
  1719. break;
  1720. case S_WEAP:
  1721. M_DrawStringCentered(160, 20, CR_SELECT, "Enter weapon number");
  1722. break;
  1723. case S_NUM:
  1724. M_DrawStringCentered(160, 20, CR_SELECT, "Enter value. Press ENTER when finished.");
  1725. break;
  1726. case S_COLOR:
  1727. M_DrawStringCentered(160, 20, CR_SELECT, "Select color and press enter");
  1728. break;
  1729. case S_CRITEM:
  1730. M_DrawStringCentered(160, 20, CR_SELECT, "Enter value");
  1731. break;
  1732. case S_CHAT:
  1733. M_DrawStringCentered(160, 20, CR_SELECT, "Type/edit chat string and Press ENTER");
  1734. break;
  1735. case S_FILE:
  1736. M_DrawStringCentered(160, 20, CR_SELECT, "Type/edit filename and Press ENTER");
  1737. break;
  1738. case S_CHOICE:
  1739. M_DrawStringCentered(160, 20, CR_SELECT, "Press left or right to choose");
  1740. break;
  1741. case S_RESET:
  1742. break;
  1743. #ifdef SIMPLECHECKS
  1744. default:
  1745. lprintf(LO_WARN,"Unrecognised menu item type %d", flags);
  1746. #endif
  1747. }
  1748. } else {
  1749. if (flags & S_RESET)
  1750. M_DrawStringCentered(160, 20, CR_HILITE, "Press ENTER key to reset to defaults");
  1751. else
  1752. M_DrawStringCentered(160, 20, CR_HILITE, "Press Enter to Change");
  1753. }
  1754. }
  1755. /////////////////////////////
  1756. //
  1757. // The Key Binding Screen tables.
  1758. #define KB_X 160
  1759. #define KB_PREV 57
  1760. #define KB_NEXT 310
  1761. #define KB_Y 31
  1762. // phares 4/16/98:
  1763. // X,Y position of reset button. This is the same for every screen, and is
  1764. // only defined once here.
  1765. #define X_BUTTON 301
  1766. #define Y_BUTTON 3
  1767. // Definitions of the (in this case) four key binding screens.
  1768. setup_menu_t keys_settings1[];
  1769. setup_menu_t keys_settings2[];
  1770. setup_menu_t keys_settings3[];
  1771. setup_menu_t keys_settings4[];
  1772. // The table which gets you from one screen table to the next.
  1773. setup_menu_t* keys_settings[] =
  1774. {
  1775. keys_settings1,
  1776. keys_settings2,
  1777. keys_settings3,
  1778. keys_settings4,
  1779. NULL
  1780. };
  1781. int mult_screens_index; // the index of the current screen in a set
  1782. // Here's an example from this first screen, with explanations.
  1783. //
  1784. // {
  1785. // "STRAFE", // The description of the item ('strafe' key)
  1786. // S_KEY, // This is a key binding item
  1787. // m_scrn, // It belongs to the m_scrn group. Its key cannot be
  1788. // // bound to two items in this group.
  1789. // KB_X, // The X offset of the start of the right-hand side
  1790. // KB_Y+ 8*8, // The Y offset of the start of the right-hand side.
  1791. // // Always given in multiples off a baseline.
  1792. // &key_strafe, // The variable that holds the key value bound to this
  1793. // OR a string that holds the config variable name.
  1794. // OR a pointer to another setup_menu
  1795. // &mousebstrafe, // The variable that holds the mouse button bound to
  1796. // this. If zero, no mouse button can be bound here.
  1797. // &joybstrafe, // The variable that holds the joystick button bound to
  1798. // this. If zero, no mouse button can be bound here.
  1799. // }
  1800. // The first Key Binding screen table.
  1801. // Note that the Y values are ascending. If you need to add something to
  1802. // this table, (well, this one's not a good example, because it's full)
  1803. // you need to make sure the Y values still make sense so everything gets
  1804. // displayed.
  1805. //
  1806. // Note also that the first screen of each set has a line for the reset
  1807. // button. If there is more than one screen in a set, the others don't get
  1808. // the reset button.
  1809. //
  1810. // Note also that this screen has a "NEXT ->" line. This acts like an
  1811. // item, in that 'activating' it moves you along to the next screen. If
  1812. // there's a "<- PREV" item on a screen, it behaves similarly, moving you
  1813. // to the previous screen. If you leave these off, you can't move from
  1814. // screen to screen.
  1815. setup_menu_t keys_settings1[] = // Key Binding screen strings
  1816. {
  1817. {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL},
  1818. {"FORWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+1*8,{&key_up},&mousebforward,NULL,NULL,NULL},
  1819. {"BACKWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+2*8,{&key_down},NULL,NULL,NULL,NULL},
  1820. {"TURN LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+3*8,{&key_left},NULL,NULL,NULL,NULL},
  1821. {"TURN RIGHT" ,S_KEY ,m_scrn,KB_X,KB_Y+4*8,{&key_right},NULL,NULL,NULL,NULL},
  1822. {"RUN" ,S_KEY ,m_scrn,KB_X,KB_Y+5*8,{&key_speed},0,&joybspeed,NULL,NULL},
  1823. {"STRAFE LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+6*8,{&key_strafeleft},NULL,NULL,NULL,NULL},
  1824. {"STRAFE RIGHT",S_KEY ,m_scrn,KB_X,KB_Y+7*8,{&key_straferight},NULL,NULL,NULL,NULL},
  1825. {"STRAFE" ,S_KEY ,m_scrn,KB_X,KB_Y+8*8,{&key_strafe},&mousebstrafe,&joybstrafe,NULL,NULL},
  1826. {"AUTORUN" ,S_KEY ,m_scrn,KB_X,KB_Y+9*8,{&key_autorun},NULL,NULL,NULL,NULL},
  1827. {"180 TURN" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_reverse},NULL,NULL,NULL,NULL},
  1828. {"USE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_use},&mousebforward,&joybuse,NULL,NULL},
  1829. {"MENUS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL},
  1830. {"NEXT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+13*8,{&key_menu_down},NULL,NULL,NULL,NULL},
  1831. {"PREV ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+14*8,{&key_menu_up},NULL,NULL,NULL,NULL},
  1832. {"LEFT" ,S_KEY ,m_menu,KB_X,KB_Y+15*8,{&key_menu_left},NULL,NULL,NULL,NULL},
  1833. {"RIGHT" ,S_KEY ,m_menu,KB_X,KB_Y+16*8,{&key_menu_right},NULL,NULL,NULL,NULL},
  1834. {"BACKSPACE" ,S_KEY ,m_menu,KB_X,KB_Y+17*8,{&key_menu_backspace},NULL,NULL,NULL,NULL},
  1835. {"SELECT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+18*8,{&key_menu_enter},NULL,NULL,NULL,NULL},
  1836. {"EXIT" ,S_KEY ,m_menu,KB_X,KB_Y+19*8,{&key_menu_escape},NULL,NULL,NULL,NULL},
  1837. // Button for resetting to defaults
  1838. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  1839. {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings2},NULL,NULL,NULL,NULL},
  1840. // Final entry
  1841. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  1842. };
  1843. setup_menu_t keys_settings2[] = // Key Binding screen strings
  1844. {
  1845. {"SCREEN" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL},
  1846. // phares 4/13/98:
  1847. // key_help and key_escape can no longer be rebound. This keeps the
  1848. // player from getting themselves in a bind where they can't remember how
  1849. // to get to the menus, and can't remember how to get to the help screen
  1850. // to give them a clue as to how to get to the menus. :)
  1851. // Also, the keys assigned to these functions cannot be bound to other
  1852. // functions. Introduce an S_KEEP flag to show that you cannot swap this
  1853. // key with other keys in the same 'group'. (m_scrn, etc.)
  1854. {"HELP" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_help},NULL,NULL,NULL,NULL},
  1855. {"MENU" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_escape},NULL,NULL,NULL,NULL},
  1856. // killough 10/98: hotkey for entering setup menu:
  1857. {"SETUP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_setup},NULL,NULL,NULL,NULL},
  1858. {"PAUSE" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_pause},NULL,NULL,NULL,NULL},
  1859. {"AUTOMAP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_map},NULL,NULL,NULL,NULL},
  1860. {"VOLUME" ,S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_soundvolume},NULL,NULL,NULL,NULL},
  1861. {"HUD" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_hud},NULL,NULL,NULL,NULL},
  1862. {"MESSAGES" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_messages},NULL,NULL,NULL,NULL},
  1863. {"GAMMA FIX" ,S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_gamma},NULL,NULL,NULL,NULL},
  1864. {"SPY" ,S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_spy},NULL,NULL,NULL,NULL},
  1865. {"LARGER VIEW" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_zoomin},NULL,NULL,NULL,NULL},
  1866. {"SMALLER VIEW",S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_zoomout},NULL,NULL,NULL,NULL},
  1867. {"SCREENSHOT" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_screenshot},NULL,NULL,NULL,NULL},
  1868. {"GAME" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL},
  1869. {"SAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_savegame},NULL,NULL,NULL,NULL},
  1870. {"LOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&key_loadgame},NULL,NULL,NULL,NULL},
  1871. {"QUICKSAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&key_quicksave},NULL,NULL,NULL,NULL},
  1872. {"QUICKLOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&key_quickload},NULL,NULL,NULL,NULL},
  1873. {"END GAME" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&key_endgame},NULL,NULL,NULL,NULL},
  1874. {"QUIT" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_quit},NULL,NULL,NULL,NULL},
  1875. {"<- PREV", S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings1},NULL,NULL,NULL,NULL},
  1876. {"NEXT ->", S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings3},NULL,NULL,NULL,NULL},
  1877. // Final entry
  1878. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  1879. };
  1880. setup_menu_t keys_settings3[] = // Key Binding screen strings
  1881. {
  1882. {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL},
  1883. {"FIST" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_weapon1},NULL,NULL,NULL,NULL},
  1884. {"PISTOL" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_weapon2},NULL,NULL,NULL,NULL},
  1885. {"SHOTGUN" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_weapon3},NULL,NULL,NULL,NULL},
  1886. {"CHAINGUN",S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_weapon4},NULL,NULL,NULL,NULL},
  1887. {"ROCKET" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_weapon5},NULL,NULL,NULL,NULL},
  1888. {"PLASMA" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_weapon6},NULL,NULL,NULL,NULL},
  1889. {"BFG", S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_weapon7},NULL,NULL,NULL,NULL},
  1890. {"CHAINSAW",S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_weapon8},NULL,NULL,NULL,NULL},
  1891. {"SSG" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_weapon9},NULL,NULL,NULL,NULL},
  1892. {"BEST" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_weapontoggle},NULL,NULL,NULL,NULL},
  1893. {"FIRE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_fire},&mousebfire,&joybfire,NULL,NULL},
  1894. {"<- PREV",S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings2},NULL,NULL,NULL,NULL},
  1895. {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings4},NULL,NULL,NULL,NULL},
  1896. // Final entry
  1897. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  1898. };
  1899. setup_menu_t keys_settings4[] = // Key Binding screen strings
  1900. {
  1901. {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL},
  1902. {"FOLLOW" ,S_KEY ,m_map ,KB_X,KB_Y+ 1*8,{&key_map_follow},NULL,NULL,NULL,NULL},
  1903. {"ZOOM IN" ,S_KEY ,m_map ,KB_X,KB_Y+ 2*8,{&key_map_zoomin},NULL,NULL,NULL,NULL},
  1904. {"ZOOM OUT" ,S_KEY ,m_map ,KB_X,KB_Y+ 3*8,{&key_map_zoomout},NULL,NULL,NULL,NULL},
  1905. {"SHIFT UP" ,S_KEY ,m_map ,KB_X,KB_Y+ 4*8,{&key_map_up},NULL,NULL,NULL,NULL},
  1906. {"SHIFT DOWN" ,S_KEY ,m_map ,KB_X,KB_Y+ 5*8,{&key_map_down},NULL,NULL,NULL,NULL},
  1907. {"SHIFT LEFT" ,S_KEY ,m_map ,KB_X,KB_Y+ 6*8,{&key_map_left},NULL,NULL,NULL,NULL},
  1908. {"SHIFT RIGHT",S_KEY ,m_map ,KB_X,KB_Y+ 7*8,{&key_map_right},NULL,NULL,NULL,NULL},
  1909. {"MARK PLACE" ,S_KEY ,m_map ,KB_X,KB_Y+ 8*8,{&key_map_mark},NULL,NULL,NULL,NULL},
  1910. {"CLEAR MARKS",S_KEY ,m_map ,KB_X,KB_Y+ 9*8,{&key_map_clear},NULL,NULL,NULL,NULL},
  1911. {"FULL/ZOOM" ,S_KEY ,m_map ,KB_X,KB_Y+10*8,{&key_map_gobig},NULL,NULL,NULL,NULL},
  1912. {"GRID" ,S_KEY ,m_map ,KB_X,KB_Y+11*8,{&key_map_grid},NULL,NULL,NULL,NULL},
  1913. {"CHATTING" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL},
  1914. {"BEGIN CHAT" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_chat},NULL,NULL,NULL,NULL},
  1915. {"PLAYER 1" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&destination_keys[0]},NULL,NULL,NULL,NULL},
  1916. {"PLAYER 2" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&destination_keys[1]},NULL,NULL,NULL,NULL},
  1917. {"PLAYER 3" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&destination_keys[2]},NULL,NULL,NULL,NULL},
  1918. {"PLAYER 4" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&destination_keys[3]},NULL,NULL,NULL,NULL},
  1919. {"BACKSPACE" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_backspace},NULL,NULL,NULL,NULL},
  1920. {"ENTER" ,S_KEY ,m_scrn,KB_X,KB_Y+19*8,{&key_enter},NULL,NULL,NULL,NULL},
  1921. {"<- PREV" ,S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings3},NULL,NULL,NULL,NULL},
  1922. // Final entry
  1923. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  1924. };
  1925. // Setting up for the Key Binding screen. Turn on flags, set pointers,
  1926. // locate the first item on the screen where the cursor is allowed to
  1927. // land.
  1928. void M_KeyBindings(int choice)
  1929. {
  1930. M_SetupNextMenu(&KeybndDef);
  1931. setup_active = true;
  1932. setup_screen = ss_keys;
  1933. set_keybnd_active = true;
  1934. setup_select = false;
  1935. default_verify = false;
  1936. setup_gather = false;
  1937. mult_screens_index = 0;
  1938. current_setup_menu = keys_settings[0];
  1939. set_menu_itemon = 0;
  1940. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  1941. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  1942. }
  1943. // The drawing part of the Key Bindings Setup initialization. Draw the
  1944. // background, title, instruction line, and items.
  1945. void M_DrawKeybnd(void)
  1946. {
  1947. inhelpscreens = true; // killough 4/6/98: Force status bar redraw
  1948. // Set up the Key Binding screen
  1949. M_DrawBackground("FLOOR4_6", 0); // Draw background
  1950. // proff/nicolas 09/20/98 -- changed for hi-res
  1951. V_DrawNamePatch(84, 2, 0, "M_KEYBND", CR_DEFAULT, VPT_STRETCH);
  1952. M_DrawInstructions();
  1953. M_DrawScreenItems(current_setup_menu);
  1954. // If the Reset Button has been selected, an "Are you sure?" message
  1955. // is overlayed across everything else.
  1956. if (default_verify)
  1957. M_DrawDefVerify();
  1958. }
  1959. /////////////////////////////
  1960. //
  1961. // The Weapon Screen tables.
  1962. #define WP_X 203
  1963. #define WP_Y 33
  1964. // There's only one weapon settings screen (for now). But since we're
  1965. // trying to fit a common description for screens, it gets a setup_menu_t,
  1966. // which only has one screen definition in it.
  1967. //
  1968. // Note that this screen has no PREV or NEXT items, since there are no
  1969. // neighboring screens.
  1970. enum { // killough 10/98: enum for y-offset info
  1971. weap_recoil,
  1972. weap_bobbing,
  1973. weap_bfg,
  1974. weap_stub1,
  1975. weap_pref1,
  1976. weap_pref2,
  1977. weap_pref3,
  1978. weap_pref4,
  1979. weap_pref5,
  1980. weap_pref6,
  1981. weap_pref7,
  1982. weap_pref8,
  1983. weap_pref9,
  1984. weap_stub2,
  1985. weap_toggle,
  1986. weap_toggle2,
  1987. };
  1988. setup_menu_t weap_settings1[];
  1989. setup_menu_t* weap_settings[] =
  1990. {
  1991. weap_settings1,
  1992. NULL
  1993. };
  1994. setup_menu_t weap_settings1[] = // Weapons Settings screen
  1995. {
  1996. {"ENABLE RECOIL", S_YESNO,m_null,WP_X, WP_Y+ weap_recoil*8, {"weapon_recoil"},NULL,NULL,NULL,NULL},
  1997. {"ENABLE BOBBING",S_YESNO,m_null,WP_X, WP_Y+weap_bobbing*8, {"player_bobbing"},NULL,NULL,NULL,NULL},
  1998. {"1ST CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref1*8, {"weapon_choice_1"},NULL,NULL,NULL,NULL},
  1999. {"2nd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref2*8, {"weapon_choice_2"},NULL,NULL,NULL,NULL},
  2000. {"3rd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref3*8, {"weapon_choice_3"},NULL,NULL,NULL,NULL},
  2001. {"4th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref4*8, {"weapon_choice_4"},NULL,NULL,NULL,NULL},
  2002. {"5th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref5*8, {"weapon_choice_5"},NULL,NULL,NULL,NULL},
  2003. {"6th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref6*8, {"weapon_choice_6"},NULL,NULL,NULL,NULL},
  2004. {"7th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref7*8, {"weapon_choice_7"},NULL,NULL,NULL,NULL},
  2005. {"8th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref8*8, {"weapon_choice_8"},NULL,NULL,NULL,NULL},
  2006. {"9th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref9*8, {"weapon_choice_9"},NULL,NULL,NULL,NULL},
  2007. {"Enable Fist/Chainsaw\n& SG/SSG toggle", S_YESNO, m_null, WP_X,
  2008. WP_Y+ weap_toggle*8, {"doom_weapon_toggles"},NULL,NULL,NULL,NULL},
  2009. // Button for resetting to defaults
  2010. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2011. // Final entry
  2012. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2013. };
  2014. // Setting up for the Weapons screen. Turn on flags, set pointers,
  2015. // locate the first item on the screen where the cursor is allowed to
  2016. // land.
  2017. void M_Weapons(int choice)
  2018. {
  2019. M_SetupNextMenu(&WeaponDef);
  2020. setup_active = true;
  2021. setup_screen = ss_weap;
  2022. set_weapon_active = true;
  2023. setup_select = false;
  2024. default_verify = false;
  2025. setup_gather = false;
  2026. mult_screens_index = 0;
  2027. current_setup_menu = weap_settings[0];
  2028. set_menu_itemon = 0;
  2029. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2030. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2031. }
  2032. // The drawing part of the Weapons Setup initialization. Draw the
  2033. // background, title, instruction line, and items.
  2034. void M_DrawWeapons(void)
  2035. {
  2036. inhelpscreens = true; // killough 4/6/98: Force status bar redraw
  2037. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2038. // proff/nicolas 09/20/98 -- changed for hi-res
  2039. V_DrawNamePatch(109, 2, 0, "M_WEAP", CR_DEFAULT, VPT_STRETCH);
  2040. M_DrawInstructions();
  2041. M_DrawScreenItems(current_setup_menu);
  2042. // If the Reset Button has been selected, an "Are you sure?" message
  2043. // is overlayed across everything else.
  2044. if (default_verify)
  2045. M_DrawDefVerify();
  2046. }
  2047. /////////////////////////////
  2048. //
  2049. // The Status Bar / HUD tables.
  2050. #define ST_X 203
  2051. #define ST_Y 31
  2052. // Screen table definitions
  2053. setup_menu_t stat_settings1[];
  2054. setup_menu_t* stat_settings[] =
  2055. {
  2056. stat_settings1,
  2057. NULL
  2058. };
  2059. setup_menu_t stat_settings1[] = // Status Bar and HUD Settings screen
  2060. {
  2061. {"STATUS BAR" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 1*8,{NULL},NULL,NULL,NULL,NULL },
  2062. {"USE RED NUMBERS" ,S_YESNO, m_null,ST_X,ST_Y+ 2*8, {"sts_always_red"},NULL,NULL,NULL,NULL},
  2063. {"GRAY %" ,S_YESNO, m_null,ST_X,ST_Y+ 3*8, {"sts_pct_always_gray"},NULL,NULL,NULL,NULL},
  2064. {"SINGLE KEY DISPLAY",S_YESNO, m_null,ST_X,ST_Y+ 4*8, {"sts_traditional_keys"},NULL,NULL,NULL,NULL},
  2065. {"HEADS-UP DISPLAY" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 6*8,{NULL},NULL,NULL,NULL,NULL},
  2066. {"HIDE SECRETS" ,S_YESNO ,m_null,ST_X,ST_Y+ 7*8, {"hud_nosecrets"},NULL,NULL,NULL,NULL},
  2067. {"HEALTH LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+ 8*8, {"health_red"},NULL,NULL,NULL,NULL},
  2068. {"HEALTH OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+ 9*8, {"health_yellow"},NULL,NULL,NULL,NULL},
  2069. {"HEALTH GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+10*8, {"health_green"},NULL,NULL,NULL,NULL},
  2070. {"ARMOR LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+11*8, {"armor_red"},NULL,NULL,NULL,NULL},
  2071. {"ARMOR OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+12*8, {"armor_yellow"},NULL,NULL,NULL,NULL},
  2072. {"ARMOR GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+13*8, {"armor_green"},NULL,NULL,NULL,NULL},
  2073. {"AMMO LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+14*8, {"ammo_red"},NULL,NULL,NULL,NULL},
  2074. {"AMMO OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+15*8, {"ammo_yellow"},NULL,NULL,NULL,NULL},
  2075. // Button for resetting to defaults
  2076. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2077. // Final entry
  2078. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2079. };
  2080. // Setting up for the Status Bar / HUD screen. Turn on flags, set pointers,
  2081. // locate the first item on the screen where the cursor is allowed to
  2082. // land.
  2083. void M_StatusBar(int choice)
  2084. {
  2085. M_SetupNextMenu(&StatusHUDDef);
  2086. setup_active = true;
  2087. setup_screen = ss_stat;
  2088. set_status_active = true;
  2089. setup_select = false;
  2090. default_verify = false;
  2091. setup_gather = false;
  2092. mult_screens_index = 0;
  2093. current_setup_menu = stat_settings[0];
  2094. set_menu_itemon = 0;
  2095. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2096. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2097. }
  2098. // The drawing part of the Status Bar / HUD Setup initialization. Draw the
  2099. // background, title, instruction line, and items.
  2100. void M_DrawStatusHUD(void)
  2101. {
  2102. inhelpscreens = true; // killough 4/6/98: Force status bar redraw
  2103. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2104. // proff/nicolas 09/20/98 -- changed for hi-res
  2105. V_DrawNamePatch(59, 2, 0, "M_STAT", CR_DEFAULT, VPT_STRETCH);
  2106. M_DrawInstructions();
  2107. M_DrawScreenItems(current_setup_menu);
  2108. // If the Reset Button has been selected, an "Are you sure?" message
  2109. // is overlayed across everything else.
  2110. if (default_verify)
  2111. M_DrawDefVerify();
  2112. }
  2113. /////////////////////////////
  2114. //
  2115. // The Automap tables.
  2116. #define AU_X 250
  2117. #define AU_Y 31
  2118. #define AU_PREV KB_PREV
  2119. #define AU_NEXT KB_NEXT
  2120. setup_menu_t auto_settings1[];
  2121. setup_menu_t auto_settings2[];
  2122. setup_menu_t* auto_settings[] =
  2123. {
  2124. auto_settings1,
  2125. auto_settings2,
  2126. NULL
  2127. };
  2128. setup_menu_t auto_settings1[] = // 1st AutoMap Settings screen
  2129. {
  2130. {"background", S_COLOR, m_null, AU_X, AU_Y, {"mapcolor_back"},NULL,NULL,NULL,NULL},
  2131. {"grid lines", S_COLOR, m_null, AU_X, AU_Y + 1*8, {"mapcolor_grid"},NULL,NULL,NULL,NULL},
  2132. {"normal 1s wall", S_COLOR, m_null,AU_X,AU_Y+ 2*8, {"mapcolor_wall"},NULL,NULL,NULL,NULL},
  2133. {"line at floor height change", S_COLOR, m_null, AU_X, AU_Y+ 3*8, {"mapcolor_fchg"},NULL,NULL,NULL,NULL},
  2134. {"line at ceiling height change" ,S_COLOR,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_cchg"},NULL,NULL,NULL,NULL},
  2135. {"line at sector with floor = ceiling",S_COLOR,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_clsd"},NULL,NULL,NULL,NULL},
  2136. {"red key" ,S_COLOR,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_rkey"},NULL,NULL,NULL,NULL},
  2137. {"blue key" ,S_COLOR,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_bkey"},NULL,NULL,NULL,NULL},
  2138. {"yellow key" ,S_COLOR,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_ykey"},NULL,NULL,NULL,NULL},
  2139. {"red door" ,S_COLOR,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_rdor"},NULL,NULL,NULL,NULL},
  2140. {"blue door" ,S_COLOR,m_null,AU_X,AU_Y+10*8, {"mapcolor_bdor"},NULL,NULL,NULL,NULL},
  2141. {"yellow door" ,S_COLOR,m_null,AU_X,AU_Y+11*8, {"mapcolor_ydor"},NULL,NULL,NULL,NULL},
  2142. {"AUTOMAP LEVEL TITLE COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+13*8, {"hudcolor_titl"},NULL,NULL,NULL,NULL},
  2143. {"AUTOMAP COORDINATES COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+14*8, {"hudcolor_xyco"},NULL,NULL,NULL,NULL},
  2144. {"Show Secrets only after entering",S_YESNO,m_null,AU_X,AU_Y+15*8, {"map_secret_after"},NULL,NULL,NULL,NULL},
  2145. {"Show coordinates of automap pointer",S_YESNO,m_null,AU_X,AU_Y+16*8, {"map_point_coord"},NULL,NULL,NULL,NULL}, // killough 10/98
  2146. // Button for resetting to defaults
  2147. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2148. {"NEXT ->",S_SKIP|S_NEXT,m_null,AU_NEXT,AU_Y+20*8, {auto_settings2},NULL,NULL,NULL,NULL},
  2149. // Final entry
  2150. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2151. };
  2152. setup_menu_t auto_settings2[] = // 2nd AutoMap Settings screen
  2153. {
  2154. {"teleporter line" ,S_COLOR ,m_null,AU_X,AU_Y, {"mapcolor_tele"},NULL,NULL,NULL,NULL},
  2155. {"secret sector boundary" ,S_COLOR ,m_null,AU_X,AU_Y+ 1*8, {"mapcolor_secr"},NULL,NULL,NULL,NULL},
  2156. //jff 4/23/98 add exit line to automap
  2157. {"exit line" ,S_COLOR ,m_null,AU_X,AU_Y+ 2*8, {"mapcolor_exit"},NULL,NULL,NULL,NULL},
  2158. {"computer map unseen line" ,S_COLOR ,m_null,AU_X,AU_Y+ 3*8, {"mapcolor_unsn"},NULL,NULL,NULL,NULL},
  2159. {"line w/no floor/ceiling changes",S_COLOR ,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_flat"},NULL,NULL,NULL,NULL},
  2160. {"general sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_sprt"},NULL,NULL,NULL,NULL},
  2161. {"countable enemy sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_enemy"},NULL,NULL,NULL,NULL}, // cph 2006/06/30
  2162. {"countable item sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_item"},NULL,NULL,NULL,NULL}, // mead 3/4/2003
  2163. {"crosshair" ,S_COLOR ,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_hair"},NULL,NULL,NULL,NULL},
  2164. {"single player arrow" ,S_COLOR ,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_sngl"},NULL,NULL,NULL,NULL},
  2165. {"your colour in multiplayer" ,S_COLOR ,m_null,AU_X,AU_Y+10*8, {"mapcolor_me"},NULL,NULL,NULL,NULL},
  2166. {"friends" ,S_COLOR ,m_null,AU_X,AU_Y+12*8, {"mapcolor_frnd"},NULL,NULL,NULL,NULL}, // killough 8/8/98
  2167. {"<- PREV",S_SKIP|S_PREV,m_null,AU_PREV,AU_Y+20*8, {auto_settings1},NULL,NULL,NULL,NULL},
  2168. // Final entry
  2169. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2170. };
  2171. // Setting up for the Automap screen. Turn on flags, set pointers,
  2172. // locate the first item on the screen where the cursor is allowed to
  2173. // land.
  2174. void M_Automap(int choice)
  2175. {
  2176. M_SetupNextMenu(&AutoMapDef);
  2177. setup_active = true;
  2178. setup_screen = ss_auto;
  2179. set_auto_active = true;
  2180. setup_select = false;
  2181. colorbox_active = false;
  2182. default_verify = false;
  2183. setup_gather = false;
  2184. set_menu_itemon = 0;
  2185. mult_screens_index = 0;
  2186. current_setup_menu = auto_settings[0];
  2187. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2188. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2189. }
  2190. // Data used by the color palette that is displayed for the player to
  2191. // select colors.
  2192. int color_palette_x; // X position of the cursor on the color palette
  2193. int color_palette_y; // Y position of the cursor on the color palette
  2194. byte palette_background[16*(CHIP_SIZE+1)+8];
  2195. // M_DrawColPal() draws the color palette when the user needs to select a
  2196. // color.
  2197. // phares 4/1/98: now uses a single lump for the palette instead of
  2198. // building the image out of individual paint chips.
  2199. static void M_DrawColPal(void)
  2200. {
  2201. int cpx, cpy;
  2202. // Draw a background, border, and paint chips
  2203. // proff/nicolas 09/20/98 -- changed for hi-res
  2204. // CPhipps - patch drawing updated
  2205. V_DrawNamePatch(COLORPALXORIG-5, COLORPALYORIG-5, 0, "M_COLORS", CR_DEFAULT, VPT_STRETCH);
  2206. // Draw the cursor around the paint chip
  2207. // (cpx,cpy) is the upper left-hand corner of the paint chip
  2208. cpx = COLORPALXORIG+color_palette_x*(CHIP_SIZE+1)-1;
  2209. cpy = COLORPALYORIG+color_palette_y*(CHIP_SIZE+1)-1;
  2210. // proff 12/6/98: Drawing of colorchips completly changed for hi-res, it now uses a patch
  2211. V_DrawNamePatch(cpx,cpy,0,"M_PALSEL",CR_DEFAULT,VPT_STRETCH); // PROFF_GL_FIX
  2212. }
  2213. // The drawing part of the Automap Setup initialization. Draw the
  2214. // background, title, instruction line, and items.
  2215. void M_DrawAutoMap(void)
  2216. {
  2217. inhelpscreens = true; // killough 4/6/98: Force status bar redraw
  2218. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2219. // CPhipps - patch drawing updated
  2220. V_DrawNamePatch(109, 2, 0, "M_AUTO", CR_DEFAULT, VPT_STRETCH);
  2221. M_DrawInstructions();
  2222. M_DrawScreenItems(current_setup_menu);
  2223. // If a color is being selected, need to show color paint chips
  2224. if (colorbox_active)
  2225. M_DrawColPal();
  2226. // If the Reset Button has been selected, an "Are you sure?" message
  2227. // is overlayed across everything else.
  2228. else if (default_verify)
  2229. M_DrawDefVerify();
  2230. }
  2231. /////////////////////////////
  2232. //
  2233. // The Enemies table.
  2234. #define E_X 250
  2235. #define E_Y 31
  2236. setup_menu_t enem_settings1[];
  2237. setup_menu_t* enem_settings[] =
  2238. {
  2239. enem_settings1,
  2240. NULL
  2241. };
  2242. enum {
  2243. enem_infighting,
  2244. enem_remember = 1,
  2245. enem_backing,
  2246. enem_monkeys,
  2247. enem_avoid_hazards,
  2248. enem_friction,
  2249. enem_help_friends,
  2250. #ifdef DOGS
  2251. enem_helpers,
  2252. #endif
  2253. enem_distfriend,
  2254. #ifdef DOGS
  2255. enem_dog_jumping,
  2256. #endif
  2257. enem_end
  2258. };
  2259. setup_menu_t enem_settings1[] = // Enemy Settings screen
  2260. {
  2261. // killough 7/19/98
  2262. {"Monster Infighting When Provoked",S_YESNO,m_null,E_X,E_Y+ enem_infighting*8, {"monster_infighting"},NULL,NULL,NULL,NULL},
  2263. {"Remember Previous Enemy",S_YESNO,m_null,E_X,E_Y+ enem_remember*8, {"monsters_remember"},NULL,NULL,NULL,NULL},
  2264. // killough 9/8/98
  2265. {"Monster Backing Out",S_YESNO,m_null,E_X,E_Y+ enem_backing*8, {"monster_backing"},NULL,NULL,NULL,NULL},
  2266. {"Climb Steep Stairs", S_YESNO,m_null,E_X,E_Y+enem_monkeys*8, {"monkeys"},NULL,NULL,NULL,NULL},
  2267. // killough 9/9/98
  2268. {"Intelligently Avoid Hazards",S_YESNO,m_null,E_X,E_Y+ enem_avoid_hazards*8, {"monster_avoid_hazards"},NULL,NULL,NULL,NULL},
  2269. // killough 10/98
  2270. {"Affected by Friction",S_YESNO,m_null,E_X,E_Y+ enem_friction*8, {"monster_friction"},NULL,NULL,NULL,NULL},
  2271. {"Rescue Dying Friends",S_YESNO,m_null,E_X,E_Y+ enem_help_friends*8, {"help_friends"},NULL,NULL,NULL,NULL},
  2272. #ifdef DOGS
  2273. // killough 7/19/98
  2274. {"Number Of Single-Player Helper Dogs",S_NUM|S_LEVWARN,m_null,E_X,E_Y+ enem_helpers*8, {"player_helpers"}},
  2275. // killough 8/8/98
  2276. {"Distance Friends Stay Away",S_NUM,m_null,E_X,E_Y+ enem_distfriend*8, {"friend_distance"}},
  2277. {"Allow dogs to jump down",S_YESNO,m_null,E_X,E_Y+ enem_dog_jumping*8, {"dog_jumping"}},
  2278. #endif
  2279. // Button for resetting to defaults
  2280. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2281. // Final entry
  2282. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2283. };
  2284. /////////////////////////////
  2285. // Setting up for the Enemies screen. Turn on flags, set pointers,
  2286. // locate the first item on the screen where the cursor is allowed to
  2287. // land.
  2288. void M_Enemy(int choice)
  2289. {
  2290. M_SetupNextMenu(&EnemyDef);
  2291. setup_active = true;
  2292. setup_screen = ss_enem;
  2293. set_enemy_active = true;
  2294. setup_select = false;
  2295. default_verify = false;
  2296. setup_gather = false;
  2297. mult_screens_index = 0;
  2298. current_setup_menu = enem_settings[0];
  2299. set_menu_itemon = 0;
  2300. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2301. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2302. }
  2303. // The drawing part of the Enemies Setup initialization. Draw the
  2304. // background, title, instruction line, and items.
  2305. void M_DrawEnemy(void)
  2306. {
  2307. inhelpscreens = true;
  2308. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2309. // proff/nicolas 09/20/98 -- changed for hi-res
  2310. V_DrawNamePatch(114, 2, 0, "M_ENEM", CR_DEFAULT, VPT_STRETCH);
  2311. M_DrawInstructions();
  2312. M_DrawScreenItems(current_setup_menu);
  2313. // If the Reset Button has been selected, an "Are you sure?" message
  2314. // is overlayed across everything else.
  2315. if (default_verify)
  2316. M_DrawDefVerify();
  2317. }
  2318. /////////////////////////////
  2319. //
  2320. // The General table.
  2321. // killough 10/10/98
  2322. extern int usejoystick, usemouse, default_mus_card, default_snd_card;
  2323. extern int detect_voices, realtic_clock_rate, tran_filter_pct;
  2324. setup_menu_t gen_settings1[], gen_settings2[], gen_settings3[];
  2325. setup_menu_t* gen_settings[] =
  2326. {
  2327. gen_settings1,
  2328. gen_settings2,
  2329. gen_settings3,
  2330. NULL
  2331. };
  2332. enum {
  2333. general_trans,
  2334. general_transpct,
  2335. general_fullscreen,
  2336. general_videomode,
  2337. // general_pcx,
  2338. // general_diskicon,
  2339. general_uncapped,
  2340. };
  2341. enum {
  2342. general_gl_texfilter,
  2343. general_gl_texformat,
  2344. general_flooroffset,
  2345. };
  2346. enum {
  2347. // general_sndcard,
  2348. // general_muscard,
  2349. // general_detvoices,
  2350. general_sndchan,
  2351. general_pitch
  2352. };
  2353. #define G_X 250
  2354. #define G_YA 44
  2355. #define G_YA2 (G_YA+9*8)
  2356. #define G_YA3 (G_YA2+5*8)
  2357. #define GF_X 76
  2358. static const char *videomodes[] = {"8bit","15bit","16bit",
  2359. "32bit","OpenGL", NULL};
  2360. static const char *gltexfilters[] = {"GL_NEAREST","GL_LINEAR",
  2361. "GL_LINEAR_MIPMAP_LINEAR",
  2362. NULL};
  2363. static const char *gltexformats[] = {"GL_RGBA","GL_RGB5_A1",
  2364. "GL_RGBA4", NULL};
  2365. setup_menu_t gen_settings1[] = { // General Settings screen1
  2366. {"Video" ,S_SKIP|S_TITLE, m_null, G_X, G_YA - 12,{NULL},NULL,NULL,NULL,NULL},
  2367. {"Enable Translucency", S_YESNO, m_null, G_X,
  2368. G_YA + general_trans*8, {"translucency"}, 0, 0, M_Trans,NULL},
  2369. {"Translucency filter percentage", S_NUM, m_null, G_X,
  2370. G_YA + general_transpct*8, {"tran_filter_pct"}, 0, 0, M_Trans,NULL},
  2371. {"Fullscreen Video mode", S_YESNO|S_PRGWARN, m_null, G_X,
  2372. G_YA + general_fullscreen*8, {"use_fullscreen"},NULL,NULL,NULL,NULL},
  2373. {"Video mode", S_CHOICE|S_PRGWARN, m_null, G_X,
  2374. G_YA + general_videomode*8, {"videomode"}, 0, 0, NULL, videomodes},
  2375. {"Uncapped Framerate", S_YESNO, m_null, G_X,
  2376. G_YA + general_uncapped*8, {"uncapped_framerate"},NULL,NULL,NULL,NULL},
  2377. #ifdef GL_DOOM
  2378. {"OpenGL", S_SKIP|S_TITLE, m_null, G_X, G_YA2 - 12,{NULL},NULL,NULL,NULL,NULL},
  2379. {"Texture filter", S_CHOICE|S_PRGWARN, m_null, G_X,
  2380. G_YA2 + general_gl_texfilter*8, {"gl_tex_filter_string"}, 0, 0, NULL, gltexfilters},
  2381. {"Texture format", S_CHOICE|S_PRGWARN, m_null, G_X,
  2382. G_YA2 + general_gl_texformat*8, {"gl_tex_format_string"}, 0, 0, NULL, gltexformats},
  2383. {"Item out of Floor offset", S_NUM, m_null, G_X,
  2384. G_YA2 + general_flooroffset*8, {"gl_sprite_offset"},NULL,NULL,NULL,NULL},
  2385. #endif
  2386. #if 0
  2387. {"PCX instead of BMP for screenshots", S_YESNO, m_null, G_X,
  2388. G_YA + general_pcx*8, {"screenshot_pcx"}},
  2389. #endif
  2390. #if 0 // MBF
  2391. {"Flash Icon During Disk IO", S_YESNO, m_null, G_X,
  2392. G_YA + general_diskicon*8, {"disk_icon"}},
  2393. #endif
  2394. {"Sound & Music", S_SKIP|S_TITLE, m_null, G_X, G_YA3 - 12,{NULL},NULL,NULL,NULL,NULL},
  2395. #if 0 // MBF
  2396. {"Sound Card", S_NUM|S_PRGWARN, m_null, G_X,
  2397. G_YA2 + general_sndcard*8, {"sound_card"}},
  2398. {"Music Card", S_NUM|S_PRGWARN, m_null, G_X,
  2399. G_YA2 + general_muscard*8, {"music_card"}},
  2400. {"Autodetect Number of Voices", S_YESNO|S_PRGWARN, m_null, G_X,
  2401. G_YA2 + general_detvoices*8, {"detect_voices"}},
  2402. #endif
  2403. {"Number of Sound Channels", S_NUM|S_PRGWARN, m_null, G_X,
  2404. G_YA3 + general_sndchan*8, {"snd_channels"},NULL,NULL,NULL,NULL},
  2405. {"Enable v1.1 Pitch Effects", S_YESNO, m_null, G_X,
  2406. G_YA3 + general_pitch*8, {"pitched_sounds"},NULL,NULL,NULL,NULL},
  2407. // Button for resetting to defaults
  2408. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2409. {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings2},NULL,NULL,NULL,NULL},
  2410. // Final entry
  2411. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2412. };
  2413. enum {
  2414. general_mouse,
  2415. general_joy,
  2416. general_leds
  2417. };
  2418. enum {
  2419. general_wad1,
  2420. general_wad2,
  2421. general_deh1,
  2422. general_deh2
  2423. };
  2424. enum {
  2425. general_corpse,
  2426. general_realtic,
  2427. general_smooth,
  2428. general_smoothfactor,
  2429. general_defskill,
  2430. };
  2431. #define G_YB 44
  2432. #define G_YB1 (G_YB+44)
  2433. #define G_YB2 (G_YB1+52)
  2434. static const char *gen_skillstrings[] = {
  2435. // Dummy first option because defaultskill is 1-based
  2436. "", "ITYTD", "HNTR", "HMP", "UV", "NM", NULL
  2437. };
  2438. setup_menu_t gen_settings2[] = { // General Settings screen2
  2439. {"Input Devices" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12,{NULL},NULL,NULL,NULL,NULL},
  2440. {"Enable Mouse", S_YESNO, m_null, G_X,
  2441. G_YB + general_mouse*8, {"use_mouse"},NULL,NULL,NULL,NULL},
  2442. {"Enable Joystick", S_YESNO, m_null, G_X,
  2443. G_YB + general_joy*8, {"use_joystick"},NULL,NULL,NULL,NULL},
  2444. {"Files Preloaded at Game Startup",S_SKIP|S_TITLE, m_null, G_X,
  2445. G_YB1 - 12,{NULL},NULL,NULL,NULL,NULL},
  2446. {"WAD # 1", S_FILE, m_null, GF_X, G_YB1 + general_wad1*8, {"wadfile_1"},NULL,NULL,NULL,NULL},
  2447. {"WAD #2", S_FILE, m_null, GF_X, G_YB1 + general_wad2*8, {"wadfile_2"},NULL,NULL,NULL,NULL},
  2448. {"DEH/BEX # 1", S_FILE, m_null, GF_X, G_YB1 + general_deh1*8, {"dehfile_1"},NULL,NULL,NULL,NULL},
  2449. {"DEH/BEX #2", S_FILE, m_null, GF_X, G_YB1 + general_deh2*8, {"dehfile_2"},NULL,NULL,NULL,NULL},
  2450. {"Miscellaneous" ,S_SKIP|S_TITLE, m_null, G_X, G_YB2 - 12,{NULL},NULL,NULL,NULL,NULL},
  2451. {"Maximum number of player corpses", S_NUM|S_PRGWARN, m_null, G_X,
  2452. G_YB2 + general_corpse*8, {"max_player_corpse"},NULL,NULL,NULL,NULL},
  2453. {"Game speed, percentage of normal", S_NUM|S_PRGWARN, m_null, G_X,
  2454. G_YB2 + general_realtic*8, {"realtic_clock_rate"},NULL,NULL,NULL,NULL},
  2455. {"Smooth Demo Playback", S_YESNO, m_null, G_X,
  2456. G_YB2 + general_smooth*8, {"demo_smoothturns"}, 0, 0, M_ChangeDemoSmoothTurns,NULL},
  2457. {"Smooth Demo Playback Factor", S_NUM, m_null, G_X,
  2458. G_YB2 + general_smoothfactor*8, {"demo_smoothturnsfactor"}, 0, 0, M_ChangeDemoSmoothTurns,NULL},
  2459. {"Default skill level", S_CHOICE, m_null, G_X,
  2460. G_YB2 + general_defskill*8, {"default_skill"}, 0, 0, NULL, gen_skillstrings},
  2461. {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings1},NULL,NULL,NULL,NULL},
  2462. {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings3},NULL,NULL,NULL,NULL},
  2463. // Final entry
  2464. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2465. };
  2466. enum {
  2467. general_filterwall,
  2468. general_filterfloor,
  2469. general_filtersprite,
  2470. general_filterpatch,
  2471. general_filterz,
  2472. general_filter_threshold,
  2473. general_spriteedges,
  2474. general_patchedges,
  2475. general_hom,
  2476. };
  2477. #define G_YC 44
  2478. static const char *renderfilters[] = {"none", "point", "linear", "rounded"};
  2479. static const char *edgetypes[] = {"jagged", "sloped"};
  2480. setup_menu_t gen_settings3[] = { // General Settings screen2
  2481. {"Renderer settings" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12,{NULL},NULL,NULL,NULL,NULL},
  2482. {"Filter for walls", S_CHOICE, m_null, G_X,
  2483. G_YC + general_filterwall*8, {"filter_wall"}, 0, 0, NULL, renderfilters},
  2484. {"Filter for floors/ceilings", S_CHOICE, m_null, G_X,
  2485. G_YC + general_filterfloor*8, {"filter_floor"}, 0, 0, NULL, renderfilters},
  2486. {"Filter for sprites", S_CHOICE, m_null, G_X,
  2487. G_YC + general_filtersprite*8, {"filter_sprite"}, 0, 0, NULL, renderfilters},
  2488. {"Filter for patches", S_CHOICE, m_null, G_X,
  2489. G_YC + general_filterpatch*8, {"filter_patch"}, 0, 0, NULL, renderfilters},
  2490. {"Filter for lighting", S_CHOICE, m_null, G_X,
  2491. G_YC + general_filterz*8, {"filter_z"}, 0, 0, NULL, renderfilters},
  2492. {"Drawing of sprite edges", S_CHOICE, m_null, G_X,
  2493. G_YC + general_spriteedges*8, {"sprite_edges"}, 0, 0, NULL, edgetypes},
  2494. {"Drawing of patch edges", S_CHOICE, m_null, G_X,
  2495. G_YC + general_patchedges*8, {"patch_edges"}, 0, 0, NULL, edgetypes},
  2496. {"Flashing HOM indicator", S_YESNO, m_null, G_X,
  2497. G_YC + general_hom*8, {"flashing_hom"},NULL,NULL,NULL,NULL},
  2498. {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings2},NULL,NULL,NULL,NULL},
  2499. // Final entry
  2500. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2501. };
  2502. void M_Trans(void) // To reset translucency after setting it in menu
  2503. {
  2504. general_translucency = default_translucency; //e6y: Fix for "translucency won't change until you restart the engine"
  2505. if (general_translucency)
  2506. R_InitTranMap(0);
  2507. }
  2508. void M_FullScreen(void) // To (un)set fullscreen video after menu changes
  2509. {
  2510. I_UpdateVideoMode();
  2511. V_SetPalette(0);
  2512. }
  2513. void M_ChangeDemoSmoothTurns(void)
  2514. {
  2515. if (demo_smoothturns)
  2516. gen_settings2[12].m_flags &= ~(S_SKIP|S_SELECT);
  2517. else
  2518. gen_settings2[12].m_flags |= (S_SKIP|S_SELECT);
  2519. R_SmoothPlaying_Reset(NULL);
  2520. }
  2521. // Setting up for the General screen. Turn on flags, set pointers,
  2522. // locate the first item on the screen where the cursor is allowed to
  2523. // land.
  2524. void M_General(int choice)
  2525. {
  2526. M_SetupNextMenu(&GeneralDef);
  2527. setup_active = true;
  2528. setup_screen = ss_gen;
  2529. set_general_active = true;
  2530. setup_select = false;
  2531. default_verify = false;
  2532. setup_gather = false;
  2533. mult_screens_index = 0;
  2534. current_setup_menu = gen_settings[0];
  2535. set_menu_itemon = 0;
  2536. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2537. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2538. }
  2539. // The drawing part of the General Setup initialization. Draw the
  2540. // background, title, instruction line, and items.
  2541. void M_DrawGeneral(void)
  2542. {
  2543. inhelpscreens = true;
  2544. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2545. // proff/nicolas 09/20/98 -- changed for hi-res
  2546. V_DrawNamePatch(114, 2, 0, "M_GENERL", CR_DEFAULT, VPT_STRETCH);
  2547. M_DrawInstructions();
  2548. M_DrawScreenItems(current_setup_menu);
  2549. // If the Reset Button has been selected, an "Are you sure?" message
  2550. // is overlayed across everything else.
  2551. if (default_verify)
  2552. M_DrawDefVerify();
  2553. }
  2554. /////////////////////////////
  2555. //
  2556. // The Compatibility table.
  2557. // killough 10/10/98
  2558. #define C_X 284
  2559. #define C_Y 32
  2560. #define COMP_SPC 12
  2561. #define C_NEXTPREV 131
  2562. setup_menu_t comp_settings1[], comp_settings2[], comp_settings3[];
  2563. setup_menu_t* comp_settings[] =
  2564. {
  2565. comp_settings1,
  2566. comp_settings2,
  2567. comp_settings3,
  2568. NULL
  2569. };
  2570. enum
  2571. {
  2572. compat_telefrag,
  2573. compat_dropoff,
  2574. compat_falloff,
  2575. compat_staylift,
  2576. compat_doorstuck,
  2577. compat_pursuit,
  2578. compat_vile,
  2579. compat_pain,
  2580. compat_skull,
  2581. compat_blazing,
  2582. compat_doorlight = 0,
  2583. compat_god,
  2584. compat_infcheat,
  2585. compat_zombie,
  2586. compat_skymap,
  2587. compat_stairs,
  2588. compat_floors,
  2589. compat_moveblock,
  2590. compat_model,
  2591. compat_zerotags,
  2592. compat_666 = 0,
  2593. compat_soul,
  2594. compat_maskedanim,
  2595. compat_sound
  2596. };
  2597. setup_menu_t comp_settings1[] = // Compatibility Settings screen #1
  2598. {
  2599. {"Any monster can telefrag on MAP30", S_YESNO, m_null, C_X,
  2600. C_Y + compat_telefrag * COMP_SPC, {"comp_telefrag"},NULL,NULL,NULL,NULL},
  2601. {"Some objects never hang over tall ledges", S_YESNO, m_null, C_X,
  2602. C_Y + compat_dropoff * COMP_SPC, {"comp_dropoff"},NULL,NULL,NULL,NULL},
  2603. {"Objects don't fall under their own weight", S_YESNO, m_null, C_X,
  2604. C_Y + compat_falloff * COMP_SPC, {"comp_falloff"},NULL,NULL,NULL,NULL},
  2605. {"Monsters randomly walk off of moving lifts", S_YESNO, m_null, C_X,
  2606. C_Y + compat_staylift * COMP_SPC, {"comp_staylift"},NULL,NULL,NULL,NULL},
  2607. {"Monsters get stuck on doortracks", S_YESNO, m_null, C_X,
  2608. C_Y + compat_doorstuck * COMP_SPC, {"comp_doorstuck"},NULL,NULL,NULL,NULL},
  2609. {"Monsters don't give up pursuit of targets", S_YESNO, m_null, C_X,
  2610. C_Y + compat_pursuit * COMP_SPC, {"comp_pursuit"},NULL,NULL,NULL,NULL},
  2611. {"Arch-Vile resurrects invincible ghosts", S_YESNO, m_null, C_X,
  2612. C_Y + compat_vile * COMP_SPC, {"comp_vile"},NULL,NULL,NULL,NULL},
  2613. {"Pain Elementals limited to 21 lost souls", S_YESNO, m_null, C_X,
  2614. C_Y + compat_pain * COMP_SPC, {"comp_pain"},NULL,NULL,NULL,NULL},
  2615. {"Lost souls get stuck behind walls", S_YESNO, m_null, C_X,
  2616. C_Y + compat_skull * COMP_SPC, {"comp_skull"},NULL,NULL,NULL,NULL},
  2617. {"Blazing doors make double closing sounds", S_YESNO, m_null, C_X,
  2618. C_Y + compat_blazing * COMP_SPC, {"comp_blazing"},NULL,NULL,NULL,NULL},
  2619. // Button for resetting to defaults
  2620. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2621. {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings2},NULL,NULL,NULL,NULL},
  2622. // Final entry
  2623. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2624. };
  2625. setup_menu_t comp_settings2[] = // Compatibility Settings screen #2
  2626. {
  2627. {"Tagged doors don't trigger special lighting", S_YESNO, m_null, C_X,
  2628. C_Y + compat_doorlight * COMP_SPC, {"comp_doorlight"},NULL,NULL,NULL,NULL},
  2629. {"God mode isn't absolute", S_YESNO, m_null, C_X,
  2630. C_Y + compat_god * COMP_SPC, {"comp_god"},NULL,NULL,NULL,NULL},
  2631. {"Powerup cheats are not infinite duration", S_YESNO, m_null, C_X,
  2632. C_Y + compat_infcheat * COMP_SPC, {"comp_infcheat"},NULL,NULL,NULL,NULL},
  2633. {"Dead players can exit levels", S_YESNO, m_null, C_X,
  2634. C_Y + compat_zombie * COMP_SPC, {"comp_zombie"},NULL,NULL,NULL,NULL},
  2635. {"Sky is unaffected by invulnerability", S_YESNO, m_null, C_X,
  2636. C_Y + compat_skymap * COMP_SPC, {"comp_skymap"},NULL,NULL,NULL,NULL},
  2637. {"Use exactly Doom's stairbuilding method", S_YESNO, m_null, C_X,
  2638. C_Y + compat_stairs * COMP_SPC, {"comp_stairs"},NULL,NULL,NULL,NULL},
  2639. {"Use exactly Doom's floor motion behavior", S_YESNO, m_null, C_X,
  2640. C_Y + compat_floors * COMP_SPC, {"comp_floors"},NULL,NULL,NULL,NULL},
  2641. {"Use exactly Doom's movement clipping code", S_YESNO, m_null, C_X,
  2642. C_Y + compat_moveblock * COMP_SPC, {"comp_moveblock"},NULL,NULL,NULL,NULL},
  2643. {"Use exactly Doom's linedef trigger model", S_YESNO, m_null, C_X,
  2644. C_Y + compat_model * COMP_SPC, {"comp_model"},NULL,NULL,NULL,NULL},
  2645. {"Linedef effects work with sector tag = 0", S_YESNO, m_null, C_X,
  2646. C_Y + compat_zerotags * COMP_SPC, {"comp_zerotags"},NULL,NULL,NULL,NULL},
  2647. {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings1},NULL,NULL,NULL,NULL},
  2648. {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings3},NULL,NULL,NULL,NULL},
  2649. // Final entry
  2650. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2651. };
  2652. setup_menu_t comp_settings3[] = // Compatibility Settings screen #2
  2653. {
  2654. {"All boss types can trigger tag 666 at ExM8", S_YESNO, m_null, C_X,
  2655. C_Y + compat_666 * COMP_SPC, {"comp_666"},NULL,NULL,NULL,NULL},
  2656. {"Lost souls don't bounce off flat surfaces", S_YESNO, m_null, C_X,
  2657. C_Y + compat_soul * COMP_SPC, {"comp_soul"},NULL,NULL,NULL,NULL},
  2658. {"2S middle textures do not animate", S_YESNO, m_null, C_X,
  2659. C_Y + compat_maskedanim * COMP_SPC, {"comp_maskedanim"},NULL,NULL,NULL,NULL},
  2660. {"Use exactly Doom's sound code behavior", S_YESNO, m_null, C_X,
  2661. C_Y + compat_sound * COMP_SPC, {"comp_sound"},NULL,NULL,NULL,NULL},
  2662. {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings2},NULL,NULL,NULL,NULL},
  2663. // Final entry
  2664. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2665. };
  2666. // Setting up for the Compatibility screen. Turn on flags, set pointers,
  2667. // locate the first item on the screen where the cursor is allowed to
  2668. // land.
  2669. void M_Compat(int choice)
  2670. {
  2671. M_SetupNextMenu(&CompatDef);
  2672. setup_active = true;
  2673. setup_screen = ss_comp;
  2674. set_general_active = true;
  2675. setup_select = false;
  2676. default_verify = false;
  2677. setup_gather = false;
  2678. mult_screens_index = 0;
  2679. current_setup_menu = comp_settings[0];
  2680. set_menu_itemon = 0;
  2681. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2682. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2683. }
  2684. // The drawing part of the Compatibility Setup initialization. Draw the
  2685. // background, title, instruction line, and items.
  2686. void M_DrawCompat(void)
  2687. {
  2688. inhelpscreens = true;
  2689. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2690. V_DrawNamePatch(52,2,0,"M_COMPAT", CR_DEFAULT, VPT_STRETCH);
  2691. M_DrawInstructions();
  2692. M_DrawScreenItems(current_setup_menu);
  2693. // If the Reset Button has been selected, an "Are you sure?" message
  2694. // is overlayed across everything else.
  2695. if (default_verify)
  2696. M_DrawDefVerify();
  2697. }
  2698. /////////////////////////////
  2699. //
  2700. // The Messages table.
  2701. #define M_X 230
  2702. #define M_Y 39
  2703. // killough 11/98: enumerated
  2704. enum {
  2705. mess_color_play,
  2706. mess_timer,
  2707. mess_color_chat,
  2708. mess_chat_timer,
  2709. mess_color_review,
  2710. mess_timed,
  2711. mess_hud_timer,
  2712. mess_lines,
  2713. mess_scrollup,
  2714. mess_background,
  2715. };
  2716. setup_menu_t mess_settings1[];
  2717. setup_menu_t* mess_settings[] =
  2718. {
  2719. mess_settings1,
  2720. NULL
  2721. };
  2722. setup_menu_t mess_settings1[] = // Messages screen
  2723. {
  2724. {"Message Color During Play", S_CRITEM, m_null, M_X,
  2725. M_Y + mess_color_play*8, {"hudcolor_mesg"},NULL,NULL,NULL,NULL},
  2726. #if 0
  2727. {"Message Duration During Play (ms)", S_NUM, m_null, M_X,
  2728. M_Y + mess_timer*8, {"message_timer"}},
  2729. #endif
  2730. {"Chat Message Color", S_CRITEM, m_null, M_X,
  2731. M_Y + mess_color_chat*8, {"hudcolor_chat"},NULL,NULL,NULL,NULL},
  2732. #if 0
  2733. {"Chat Message Duration (ms)", S_NUM, m_null, M_X,
  2734. M_Y + mess_chat_timer*8, {"chat_msg_timer"}},
  2735. #endif
  2736. {"Message Review Color", S_CRITEM, m_null, M_X,
  2737. M_Y + mess_color_review*8, {"hudcolor_list"},NULL,NULL,NULL,NULL},
  2738. #if 0
  2739. {"Message Listing Review is Temporary", S_YESNO, m_null, M_X,
  2740. M_Y + mess_timed*8, {"hud_msg_timed"}},
  2741. {"Message Review Duration (ms)", S_NUM, m_null, M_X,
  2742. M_Y + mess_hud_timer*8, {"hud_msg_timer"}},
  2743. #endif
  2744. {"Number of Review Message Lines", S_NUM, m_null, M_X,
  2745. M_Y + mess_lines*8, {"hud_msg_lines"},NULL,NULL,NULL,NULL},
  2746. #if 0
  2747. {"Message Listing Scrolls Upwards", S_YESNO, m_null, M_X,
  2748. M_Y + mess_scrollup*8, {"hud_msg_scrollup"}},
  2749. #endif
  2750. {"Message Background", S_YESNO, m_null, M_X,
  2751. M_Y + mess_background*8, {"hud_list_bgon"},NULL,NULL,NULL,NULL},
  2752. // Button for resetting to defaults
  2753. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2754. // Final entry
  2755. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2756. };
  2757. // Setting up for the Messages screen. Turn on flags, set pointers,
  2758. // locate the first item on the screen where the cursor is allowed to
  2759. // land.
  2760. void M_Messages(int choice)
  2761. {
  2762. M_SetupNextMenu(&MessageDef);
  2763. setup_active = true;
  2764. setup_screen = ss_mess;
  2765. set_mess_active = true;
  2766. setup_select = false;
  2767. default_verify = false;
  2768. setup_gather = false;
  2769. mult_screens_index = 0;
  2770. current_setup_menu = mess_settings[0];
  2771. set_menu_itemon = 0;
  2772. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2773. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2774. }
  2775. // The drawing part of the Messages Setup initialization. Draw the
  2776. // background, title, instruction line, and items.
  2777. void M_DrawMessages(void)
  2778. {
  2779. inhelpscreens = true;
  2780. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2781. // CPhipps - patch drawing updated
  2782. V_DrawNamePatch(103, 2, 0, "M_MESS", CR_DEFAULT, VPT_STRETCH);
  2783. M_DrawInstructions();
  2784. M_DrawScreenItems(current_setup_menu);
  2785. if (default_verify)
  2786. M_DrawDefVerify();
  2787. }
  2788. /////////////////////////////
  2789. //
  2790. // The Chat Strings table.
  2791. #define CS_X 20
  2792. #define CS_Y (31+8)
  2793. setup_menu_t chat_settings1[];
  2794. setup_menu_t* chat_settings[] =
  2795. {
  2796. chat_settings1,
  2797. NULL
  2798. };
  2799. setup_menu_t chat_settings1[] = // Chat Strings screen
  2800. {
  2801. {"1",S_CHAT,m_null,CS_X,CS_Y+ 1*8, {"chatmacro1"},NULL,NULL,NULL,NULL},
  2802. {"2",S_CHAT,m_null,CS_X,CS_Y+ 2*8, {"chatmacro2"},NULL,NULL,NULL,NULL},
  2803. {"3",S_CHAT,m_null,CS_X,CS_Y+ 3*8, {"chatmacro3"},NULL,NULL,NULL,NULL},
  2804. {"4",S_CHAT,m_null,CS_X,CS_Y+ 4*8, {"chatmacro4"},NULL,NULL,NULL,NULL},
  2805. {"5",S_CHAT,m_null,CS_X,CS_Y+ 5*8, {"chatmacro5"},NULL,NULL,NULL,NULL},
  2806. {"6",S_CHAT,m_null,CS_X,CS_Y+ 6*8, {"chatmacro6"},NULL,NULL,NULL,NULL},
  2807. {"7",S_CHAT,m_null,CS_X,CS_Y+ 7*8, {"chatmacro7"},NULL,NULL,NULL,NULL},
  2808. {"8",S_CHAT,m_null,CS_X,CS_Y+ 8*8, {"chatmacro8"},NULL,NULL,NULL,NULL},
  2809. {"9",S_CHAT,m_null,CS_X,CS_Y+ 9*8, {"chatmacro9"},NULL,NULL,NULL,NULL},
  2810. {"0",S_CHAT,m_null,CS_X,CS_Y+10*8, {"chatmacro0"},NULL,NULL,NULL,NULL},
  2811. // Button for resetting to defaults
  2812. {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL},
  2813. // Final entry
  2814. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  2815. };
  2816. // Setting up for the Chat Strings screen. Turn on flags, set pointers,
  2817. // locate the first item on the screen where the cursor is allowed to
  2818. // land.
  2819. void M_ChatStrings(int choice)
  2820. {
  2821. M_SetupNextMenu(&ChatStrDef);
  2822. setup_active = true;
  2823. setup_screen = ss_chat;
  2824. set_chat_active = true;
  2825. setup_select = false;
  2826. default_verify = false;
  2827. setup_gather = false;
  2828. mult_screens_index = 0;
  2829. current_setup_menu = chat_settings[0];
  2830. set_menu_itemon = 0;
  2831. while (current_setup_menu[set_menu_itemon++].m_flags & S_SKIP);
  2832. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  2833. }
  2834. // The drawing part of the Chat Strings Setup initialization. Draw the
  2835. // background, title, instruction line, and items.
  2836. void M_DrawChatStrings(void)
  2837. {
  2838. inhelpscreens = true;
  2839. M_DrawBackground("FLOOR4_6", 0); // Draw background
  2840. // CPhipps - patch drawing updated
  2841. V_DrawNamePatch(83, 2, 0, "M_CHAT", CR_DEFAULT, VPT_STRETCH);
  2842. M_DrawInstructions();
  2843. M_DrawScreenItems(current_setup_menu);
  2844. // If the Reset Button has been selected, an "Are you sure?" message
  2845. // is overlayed across everything else.
  2846. if (default_verify)
  2847. M_DrawDefVerify();
  2848. }
  2849. /////////////////////////////
  2850. //
  2851. // General routines used by the Setup screens.
  2852. //
  2853. static boolean shiftdown = false; // phares 4/10/98: SHIFT key down or not
  2854. // phares 4/17/98:
  2855. // M_SelectDone() gets called when you have finished entering your
  2856. // Setup Menu item change.
  2857. static void M_SelectDone(setup_menu_t* ptr)
  2858. {
  2859. ptr->m_flags &= ~S_SELECT;
  2860. ptr->m_flags |= S_HILITE;
  2861. S_StartSound(NULL,sfx_itemup);
  2862. setup_select = false;
  2863. colorbox_active = false;
  2864. if (print_warning_about_changes) // killough 8/15/98
  2865. print_warning_about_changes--;
  2866. }
  2867. // phares 4/21/98:
  2868. // Array of setup screens used by M_ResetDefaults()
  2869. static setup_menu_t **setup_screens[] =
  2870. {
  2871. keys_settings,
  2872. weap_settings,
  2873. stat_settings,
  2874. auto_settings,
  2875. enem_settings,
  2876. mess_settings,
  2877. chat_settings,
  2878. gen_settings, // killough 10/98
  2879. comp_settings,
  2880. };
  2881. // phares 4/19/98:
  2882. // M_ResetDefaults() resets all values for a setup screen to default values
  2883. //
  2884. // killough 10/98: rewritten to fix bugs and warn about pending changes
  2885. static void M_ResetDefaults(void)
  2886. {
  2887. int i; //e6y
  2888. default_t *dp;
  2889. int warn = 0;
  2890. // Look through the defaults table and reset every variable that
  2891. // belongs to the group we're interested in.
  2892. //
  2893. // killough: However, only reset variables whose field in the
  2894. // current setup screen is the same as in the defaults table.
  2895. // i.e. only reset variables really in the current setup screen.
  2896. // e6y
  2897. // Fixed crash while trying to read data past array end
  2898. // All previous versions of prboom worked only by a lucky accident
  2899. // old code: for (dp = defaults; dp->name; dp++)
  2900. for (i = 0; i < numdefaults ; i++)
  2901. {
  2902. dp = &defaults[i];
  2903. if (dp->setupscreen == setup_screen)
  2904. {
  2905. setup_menu_t **l, *p;
  2906. for (l = setup_screens[setup_screen-1]; *l; l++)
  2907. for (p = *l; !(p->m_flags & S_END); p++)
  2908. if (p->m_flags & S_HASDEFPTR ? p->var.def == dp :
  2909. p->var.m_key == dp->location.pi ||
  2910. p->m_mouse == dp->location.pi ||
  2911. p->m_joy == dp->location.pi)
  2912. {
  2913. if (IS_STRING(*dp))
  2914. free((char*)*dp->location.ppsz),
  2915. *dp->location.ppsz = strdup(dp->defaultvalue.psz);
  2916. else
  2917. *dp->location.pi = dp->defaultvalue.i;
  2918. #if 0
  2919. if (p->m_flags & (S_LEVWARN | S_PRGWARN))
  2920. warn |= p->m_flags & (S_LEVWARN | S_PRGWARN);
  2921. else
  2922. if (dp->current)
  2923. if (allow_changes())
  2924. *dp->current = *dp->location.pi;
  2925. else
  2926. warn |= S_LEVWARN;
  2927. #endif
  2928. if (p->action)
  2929. p->action();
  2930. goto end;
  2931. }
  2932. end:;
  2933. }
  2934. }
  2935. if (warn)
  2936. warn_about_changes(warn);
  2937. }
  2938. //
  2939. // M_InitDefaults()
  2940. //
  2941. // killough 11/98:
  2942. //
  2943. // This function converts all setup menu entries consisting of cfg
  2944. // variable names, into pointers to the corresponding default[]
  2945. // array entry. var.name becomes converted to var.def.
  2946. //
  2947. static void M_InitDefaults(void)
  2948. {
  2949. setup_menu_t *const *p, *t;
  2950. default_t *dp;
  2951. int i;
  2952. for (i = 0; i < ss_max-1; i++)
  2953. for (p = setup_screens[i]; *p; p++)
  2954. for (t = *p; !(t->m_flags & S_END); t++)
  2955. if (t->m_flags & S_HASDEFPTR) {
  2956. if (!(dp = M_LookupDefault(t->var.name)))
  2957. I_Error("M_InitDefaults: Couldn't find config variable %s", t->var.name);
  2958. else
  2959. (t->var.def = dp)->setup_menu = t;
  2960. }
  2961. }
  2962. //
  2963. // End of Setup Screens.
  2964. //
  2965. /////////////////////////////////////////////////////////////////////////////
  2966. /////////////////////////////////////////////////////////////////////////////
  2967. //
  2968. // Start of Extended HELP screens // phares 3/30/98
  2969. //
  2970. // The wad designer can define a set of extended HELP screens for their own
  2971. // information display. These screens should be 320x200 graphic lumps
  2972. // defined in a separate wad. They should be named "HELP01" through "HELP99".
  2973. // "HELP01" is shown after the regular BOOM Dynamic HELP screen, and ENTER
  2974. // and BACKSPACE keys move the player through the HELP set.
  2975. //
  2976. // Rather than define a set of menu definitions for each of the possible
  2977. // HELP screens, one definition is used, and is altered on the fly
  2978. // depending on what HELPnn lumps the game finds.
  2979. // phares 3/30/98:
  2980. // Extended Help Screen variables
  2981. int extended_help_count; // number of user-defined help screens found
  2982. int extended_help_index; // index of current extended help screen
  2983. menuitem_t ExtHelpMenu[] =
  2984. {
  2985. {1,"",M_ExtHelpNextScreen,0}
  2986. };
  2987. menu_t ExtHelpDef =
  2988. {
  2989. 1, // # of menu items
  2990. &ReadDef1, // previous menu
  2991. ExtHelpMenu, // menuitem_t ->
  2992. M_DrawExtHelp, // drawing routine ->
  2993. 330,181, // x,y
  2994. 0 // lastOn
  2995. };
  2996. // M_ExtHelpNextScreen establishes the number of the next HELP screen in
  2997. // the series.
  2998. void M_ExtHelpNextScreen(int choice)
  2999. {
  3000. choice = 0;
  3001. if (++extended_help_index > extended_help_count)
  3002. {
  3003. // when finished with extended help screens, return to Main Menu
  3004. extended_help_index = 1;
  3005. M_SetupNextMenu(&MainDef);
  3006. }
  3007. }
  3008. // phares 3/30/98:
  3009. // Routine to look for HELPnn screens and create a menu
  3010. // definition structure that defines extended help screens.
  3011. void M_InitExtendedHelp(void)
  3012. {
  3013. int index,i;
  3014. char namebfr[] = { "HELPnn"} ;
  3015. extended_help_count = 0;
  3016. for (index = 1 ; index < 100 ; index++) {
  3017. namebfr[4] = index/10 + 0x30;
  3018. namebfr[5] = index%10 + 0x30;
  3019. i = W_CheckNumForName(namebfr);
  3020. if (i == -1) {
  3021. if (extended_help_count) {
  3022. if (gamemode == commercial) {
  3023. ExtHelpDef.prevMenu = &ReadDef1; /* previous menu */
  3024. ReadMenu1[0].routine = M_ExtHelp;
  3025. } else {
  3026. ExtHelpDef.prevMenu = &ReadDef2; /* previous menu */
  3027. ReadMenu2[0].routine = M_ExtHelp;
  3028. }
  3029. }
  3030. return;
  3031. }
  3032. extended_help_count++;
  3033. }
  3034. }
  3035. // Initialization for the extended HELP screens.
  3036. void M_ExtHelp(int choice)
  3037. {
  3038. choice = 0;
  3039. extended_help_index = 1; // Start with first extended help screen
  3040. M_SetupNextMenu(&ExtHelpDef);
  3041. }
  3042. // Initialize the drawing part of the extended HELP screens.
  3043. void M_DrawExtHelp(void)
  3044. {
  3045. char namebfr[10] = { "HELPnn" }; // CPhipps - make it local & writable
  3046. inhelpscreens = true; // killough 5/1/98
  3047. namebfr[4] = extended_help_index/10 + 0x30;
  3048. namebfr[5] = extended_help_index%10 + 0x30;
  3049. // CPhipps - patch drawing updated
  3050. V_DrawNamePatch(0, 0, 0, namebfr, CR_DEFAULT, VPT_STRETCH);
  3051. }
  3052. //
  3053. // End of Extended HELP screens // phares 3/30/98
  3054. //
  3055. ////////////////////////////////////////////////////////////////////////////
  3056. ////////////////////////////////////////////////////////////////////////////
  3057. //
  3058. // Dynamic HELP screen // phares 3/2/98
  3059. //
  3060. // Rather than providing the static HELP screens from DOOM and its versions,
  3061. // BOOM provides the player with a dynamic HELP screen that displays the
  3062. // current settings of major key bindings.
  3063. //
  3064. // The Dynamic HELP screen is defined in a manner similar to that used for
  3065. // the Setup Screens above.
  3066. //
  3067. // M_GetKeyString finds the correct string to represent the key binding
  3068. // for the current item being drawn.
  3069. int M_GetKeyString(int c,int offset)
  3070. {
  3071. const char* s;
  3072. if (c >= 33 && c <= 126) {
  3073. // The '=', ',', and '.' keys originally meant the shifted
  3074. // versions of those keys, but w/o having to shift them in
  3075. // the game. Any actions that are mapped to these keys will
  3076. // still mean their shifted versions. Could be changed later
  3077. // if someone can come up with a better way to deal with them.
  3078. if (c == '=') // probably means the '+' key?
  3079. c = '+';
  3080. else if (c == ',') // probably means the '<' key?
  3081. c = '<';
  3082. else if (c == '.') // probably means the '>' key?
  3083. c = '>';
  3084. menu_buffer[offset++] = c; // Just insert the ascii key
  3085. menu_buffer[offset] = 0;
  3086. } else {
  3087. // Retrieve 4-letter (max) string representing the key
  3088. // cph - Keypad keys, general code reorganisation to
  3089. // make this smaller and neater.
  3090. if ((0x100 <= c) && (c < 0x200)) {
  3091. if (c == KEYD_KEYPADENTER)
  3092. s = "PADE";
  3093. else {
  3094. strcpy(&menu_buffer[offset], "PAD");
  3095. offset+=4;
  3096. menu_buffer[offset-1] = c & 0xff;
  3097. menu_buffer[offset] = 0;
  3098. }
  3099. } else if ((KEYD_F1 <= c) && (c < KEYD_F10)) {
  3100. menu_buffer[offset++] = 'F';
  3101. menu_buffer[offset++] = '1' + c - KEYD_F1;
  3102. menu_buffer[offset] = 0;
  3103. } else {
  3104. switch(c) {
  3105. case KEYD_TAB: s = "TAB"; break;
  3106. case KEYD_ENTER: s = "ENTR"; break;
  3107. case KEYD_ESCAPE: s = "ESC"; break;
  3108. case KEYD_SPACEBAR: s = "SPAC"; break;
  3109. case KEYD_BACKSPACE: s = "BACK"; break;
  3110. case KEYD_RCTRL: s = "CTRL"; break;
  3111. case KEYD_LEFTARROW: s = "LARR"; break;
  3112. case KEYD_UPARROW: s = "UARR"; break;
  3113. case KEYD_RIGHTARROW: s = "RARR"; break;
  3114. case KEYD_DOWNARROW: s = "DARR"; break;
  3115. case KEYD_RSHIFT: s = "SHFT"; break;
  3116. case KEYD_RALT: s = "ALT"; break;
  3117. case KEYD_CAPSLOCK: s = "CAPS"; break;
  3118. case KEYD_SCROLLLOCK: s = "SCRL"; break;
  3119. case KEYD_HOME: s = "HOME"; break;
  3120. case KEYD_PAGEUP: s = "PGUP"; break;
  3121. case KEYD_END: s = "END"; break;
  3122. case KEYD_PAGEDOWN: s = "PGDN"; break;
  3123. case KEYD_INSERT: s = "INST"; break;
  3124. case KEYD_DEL: s = "DEL"; break;
  3125. case KEYD_F10: s = "F10"; break;
  3126. case KEYD_F11: s = "F11"; break;
  3127. case KEYD_F12: s = "F12"; break;
  3128. case KEYD_PAUSE: s = "PAUS"; break;
  3129. default: s = "JUNK"; break;
  3130. }
  3131. if (s) { // cph - Slight code change
  3132. strcpy(&menu_buffer[offset],s); // string to display
  3133. offset += strlen(s);
  3134. }
  3135. }
  3136. }
  3137. return offset;
  3138. }
  3139. //
  3140. // The Dynamic HELP screen table.
  3141. #define KT_X1 283
  3142. #define KT_X2 172
  3143. #define KT_X3 87
  3144. #define KT_Y1 2
  3145. #define KT_Y2 118
  3146. #define KT_Y3 102
  3147. setup_menu_t helpstrings[] = // HELP screen strings
  3148. {
  3149. {"SCREEN" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y1,{NULL},NULL,NULL,NULL,NULL},
  3150. {"HELP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 1*8,{&key_help},NULL,NULL,NULL,NULL},
  3151. {"MENU" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 2*8,{&key_escape},NULL,NULL,NULL,NULL},
  3152. {"SETUP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 3*8,{&key_setup},NULL,NULL,NULL,NULL},
  3153. {"PAUSE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 4*8,{&key_pause},NULL,NULL,NULL,NULL},
  3154. {"AUTOMAP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 5*8,{&key_map},NULL,NULL,NULL,NULL},
  3155. {"SOUND VOLUME",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 6*8,{&key_soundvolume},NULL,NULL,NULL,NULL},
  3156. {"HUD" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 7*8,{&key_hud},NULL,NULL,NULL,NULL},
  3157. {"MESSAGES" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 8*8,{&key_messages},NULL,NULL,NULL,NULL},
  3158. {"GAMMA FIX" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 9*8,{&key_gamma},NULL,NULL,NULL,NULL},
  3159. {"SPY" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+10*8,{&key_spy},NULL,NULL,NULL,NULL},
  3160. {"LARGER VIEW" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+11*8,{&key_zoomin},NULL,NULL,NULL,NULL},
  3161. {"SMALLER VIEW",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+12*8,{&key_zoomout},NULL,NULL,NULL,NULL},
  3162. {"SCREENSHOT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+13*8,{&key_screenshot},NULL,NULL,NULL,NULL},
  3163. {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y2,{NULL},NULL,NULL,NULL,NULL},
  3164. {"FOLLOW MODE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 1*8,{&key_map_follow},NULL,NULL,NULL,NULL},
  3165. {"ZOOM IN" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 2*8,{&key_map_zoomin},NULL,NULL,NULL,NULL},
  3166. {"ZOOM OUT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 3*8,{&key_map_zoomout},NULL,NULL,NULL,NULL},
  3167. {"MARK PLACE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 4*8,{&key_map_mark},NULL,NULL,NULL,NULL},
  3168. {"CLEAR MARKS" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 5*8,{&key_map_clear},NULL,NULL,NULL,NULL},
  3169. {"FULL/ZOOM" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 6*8,{&key_map_gobig},NULL,NULL,NULL,NULL},
  3170. {"GRID" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 7*8,{&key_map_grid},NULL,NULL,NULL,NULL},
  3171. {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y1,{NULL},NULL,NULL,NULL,NULL},
  3172. {"FIST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 1*8,{&key_weapon1},NULL,NULL,NULL,NULL},
  3173. {"PISTOL" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 2*8,{&key_weapon2},NULL,NULL,NULL,NULL},
  3174. {"SHOTGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 3*8,{&key_weapon3},NULL,NULL,NULL,NULL},
  3175. {"CHAINGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 4*8,{&key_weapon4},NULL,NULL,NULL,NULL},
  3176. {"ROCKET" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 5*8,{&key_weapon5},NULL,NULL,NULL,NULL},
  3177. {"PLASMA" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 6*8,{&key_weapon6},NULL,NULL,NULL,NULL},
  3178. {"BFG 9000" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 7*8,{&key_weapon7},NULL,NULL,NULL,NULL},
  3179. {"CHAINSAW" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 8*8,{&key_weapon8},NULL,NULL,NULL,NULL},
  3180. {"SSG" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 9*8,{&key_weapon9},NULL,NULL,NULL,NULL},
  3181. {"BEST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+10*8,{&key_weapontoggle},NULL,NULL,NULL,NULL},
  3182. {"FIRE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+11*8,{&key_fire},&mousebfire,&joybfire,NULL,NULL},
  3183. {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y3,{NULL},NULL,NULL,NULL,NULL},
  3184. {"FORWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 1*8,{&key_up},&mousebforward,NULL,NULL,NULL},
  3185. {"BACKWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 2*8,{&key_down},NULL,NULL,NULL,NULL},
  3186. {"TURN LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 3*8,{&key_left},NULL,NULL,NULL,NULL},
  3187. {"TURN RIGHT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 4*8,{&key_right},NULL,NULL,NULL,NULL},
  3188. {"RUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 5*8,{&key_speed},0,&joybspeed,NULL,NULL},
  3189. {"STRAFE LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 6*8,{&key_strafeleft},NULL,NULL,NULL,NULL},
  3190. {"STRAFE RIGHT",S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 7*8,{&key_straferight},NULL,NULL,NULL,NULL},
  3191. {"STRAFE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 8*8,{&key_strafe},&mousebstrafe,&joybstrafe,NULL,NULL},
  3192. {"AUTORUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 9*8,{&key_autorun},NULL,NULL,NULL,NULL},
  3193. {"180 TURN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+10*8,{&key_reverse},NULL,NULL,NULL,NULL},
  3194. {"USE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+11*8,{&key_use},&mousebforward,&joybuse,NULL,NULL},
  3195. {"GAME" ,S_SKIP|S_TITLE,m_null,KT_X2,KT_Y1,{NULL},NULL,NULL,NULL,NULL},
  3196. {"SAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 1*8,{&key_savegame},NULL,NULL,NULL,NULL},
  3197. {"LOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 2*8,{&key_loadgame},NULL,NULL,NULL,NULL},
  3198. {"QUICKSAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 3*8,{&key_quicksave},NULL,NULL,NULL,NULL},
  3199. {"END GAME" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 4*8,{&key_endgame},NULL,NULL,NULL,NULL},
  3200. {"QUICKLOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 5*8,{&key_quickload},NULL,NULL,NULL,NULL},
  3201. {"QUIT" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 6*8,{&key_quit},NULL,NULL,NULL,NULL},
  3202. // Final entry
  3203. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  3204. };
  3205. #define SPACEWIDTH 4
  3206. /* cph 2006/08/06
  3207. * M_DrawString() is the old M_DrawMenuString, except that it is not tied to
  3208. * menu_buffer - no reason to force all the callers to write into one array! */
  3209. static void M_DrawString(int cx, int cy, int color, const char* ch)
  3210. {
  3211. int w;
  3212. int c;
  3213. while (*ch) {
  3214. c = *ch++; // get next char
  3215. c = toupper(c) - HU_FONTSTART;
  3216. if (c < 0 || c> HU_FONTSIZE)
  3217. {
  3218. cx += SPACEWIDTH; // space
  3219. continue;
  3220. }
  3221. w = hu_font[c].width;
  3222. if (cx + w > 320)
  3223. break;
  3224. // V_DrawpatchTranslated() will draw the string in the
  3225. // desired color, colrngs[color]
  3226. // CPhipps - patch drawing updated
  3227. V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, color, VPT_STRETCH | VPT_TRANS);
  3228. // The screen is cramped, so trim one unit from each
  3229. // character so they butt up against each other.
  3230. cx += w - 1;
  3231. }
  3232. }
  3233. // M_DrawMenuString() draws the string in menu_buffer[]
  3234. static void M_DrawMenuString(int cx, int cy, int color)
  3235. {
  3236. M_DrawString(cx, cy, color, menu_buffer);
  3237. }
  3238. // M_GetPixelWidth() returns the number of pixels in the width of
  3239. // the string, NOT the number of chars in the string.
  3240. static int M_GetPixelWidth(const char* ch)
  3241. {
  3242. int len = 0;
  3243. int c;
  3244. while (*ch) {
  3245. c = *ch++; // pick up next char
  3246. c = toupper(c) - HU_FONTSTART;
  3247. if (c < 0 || c > HU_FONTSIZE)
  3248. {
  3249. len += SPACEWIDTH; // space
  3250. continue;
  3251. }
  3252. len += hu_font[c].width;
  3253. len--; // adjust so everything fits
  3254. }
  3255. len++; // replace what you took away on the last char only
  3256. return len;
  3257. }
  3258. static void M_DrawStringCentered(int cx, int cy, int color, const char* ch)
  3259. {
  3260. M_DrawString(cx - M_GetPixelWidth(ch)/2, cy, color, ch);
  3261. }
  3262. //
  3263. // M_DrawHelp
  3264. //
  3265. // This displays the help screen
  3266. void M_DrawHelp (void)
  3267. {
  3268. inhelpscreens = true; // killough 10/98
  3269. M_DrawBackground("FLOOR4_6", 0);
  3270. M_DrawScreenItems(helpstrings);
  3271. }
  3272. //
  3273. // End of Dynamic HELP screen // phares 3/2/98
  3274. //
  3275. ////////////////////////////////////////////////////////////////////////////
  3276. enum {
  3277. prog,
  3278. prog_stub,
  3279. prog_stub1,
  3280. prog_stub2,
  3281. adcr
  3282. };
  3283. enum {
  3284. cr_prog=0,
  3285. cr_adcr=2,
  3286. };
  3287. #define CR_S 9
  3288. #define CR_X 20
  3289. #define CR_X2 50
  3290. #define CR_Y 32
  3291. #define CR_SH 9
  3292. setup_menu_t cred_settings[]={
  3293. {"Programmers",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*prog + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL},
  3294. {"Florian 'Proff' Schulze",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+1) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL},
  3295. {"Colin Phipps",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+2) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL},
  3296. {"Neil Stevens",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+3) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL},
  3297. {"Andrey Budko",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+4) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL},
  3298. {"Additional Credit To",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*adcr + CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3299. {"id Software for DOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+1)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3300. {"TeamTNT for BOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+2)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3301. {"Lee Killough for MBF",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+3)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3302. {"The DOSDoom-Team for DOSDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+4)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3303. {"Randy Heit for ZDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+5)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3304. {"Michael 'Kodak' Ryssen for DOOMGL",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+6)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3305. {"Jess Haas for lSDLDoom",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+7) + CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3306. {"all others who helped (see AUTHORS file)",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+8)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL},
  3307. {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL}
  3308. };
  3309. void M_DrawCredits(void) // killough 10/98: credit screen
  3310. {
  3311. inhelpscreens = true;
  3312. M_DrawBackground(gamemode==shareware ? "CEIL5_1" : "MFLR8_4", 0);
  3313. V_DrawNamePatch(115,9,0, "PRBOOM",CR_GOLD, VPT_TRANS | VPT_STRETCH);
  3314. M_DrawScreenItems(cred_settings);
  3315. }
  3316. static int M_IndexInChoices(const char *str, const char **choices) {
  3317. int i = 0;
  3318. while (*choices != NULL) {
  3319. if (!strcmp(str, *choices))
  3320. return i;
  3321. i++;
  3322. choices++;
  3323. }
  3324. return 0;
  3325. }
  3326. /////////////////////////////////////////////////////////////////////////////
  3327. //
  3328. // M_Responder
  3329. //
  3330. // Examines incoming keystrokes and button pushes and determines some
  3331. // action based on the state of the system.
  3332. //
  3333. boolean M_Responder (event_t* ev) {
  3334. int ch;
  3335. int i;
  3336. static int joywait = 0;
  3337. static int mousewait = 0;
  3338. ch = -1; // will be changed to a legit char if we're going to use it here
  3339. // Process joystick input
  3340. if (ev->type == ev_joystick && joywait < I_GetTime()) {
  3341. if (ev->data3 == -1)
  3342. {
  3343. ch = key_menu_up; // phares 3/7/98
  3344. joywait = I_GetTime() + 5;
  3345. }
  3346. else if (ev->data3 == 1)
  3347. {
  3348. ch = key_menu_down; // phares 3/7/98
  3349. joywait = I_GetTime() + 5;
  3350. }
  3351. if (ev->data2 == -1)
  3352. {
  3353. ch = key_menu_left; // phares 3/7/98
  3354. joywait = I_GetTime() + 2;
  3355. }
  3356. else if (ev->data2 == 1)
  3357. {
  3358. ch = key_menu_right; // phares 3/7/98
  3359. joywait = I_GetTime() + 2;
  3360. }
  3361. if (ev->data1&1)
  3362. {
  3363. ch = key_menu_enter; // phares 3/7/98
  3364. joywait = I_GetTime() + 5;
  3365. }
  3366. if (ev->data1&2)
  3367. {
  3368. ch = key_menu_backspace; // phares 3/7/98
  3369. joywait = I_GetTime() + 5;
  3370. }
  3371. // phares 4/4/98:
  3372. // Handle joystick buttons 3 and 4, and allow them to pass down
  3373. // to where key binding can eat them.
  3374. if (setup_active && set_keybnd_active) {
  3375. if (ev->data1&4) {
  3376. ch = 0; // meaningless, just to get you past the check for -1
  3377. joywait = I_GetTime() + 5;
  3378. }
  3379. if (ev->data1&8) {
  3380. ch = 0; // meaningless, just to get you past the check for -1
  3381. joywait = I_GetTime() + 5;
  3382. }
  3383. }
  3384. } else {
  3385. // Process mouse input
  3386. if (ev->type == ev_mouse && mousewait < I_GetTime()) {
  3387. // Only process mouse button input
  3388. if (ev->data1&1)
  3389. {
  3390. ch = key_menu_enter; // phares 3/7/98
  3391. mousewait = I_GetTime() + 15;
  3392. }
  3393. if (ev->data1&2)
  3394. {
  3395. ch = key_menu_backspace; // phares 3/7/98
  3396. mousewait = I_GetTime() + 15;
  3397. }
  3398. // phares 4/4/98:
  3399. // Handle mouse button 3, and allow it to pass down
  3400. // to where key binding can eat it.
  3401. if (setup_active && set_keybnd_active)
  3402. if (ev->data1&4)
  3403. {
  3404. ch = 0; // meaningless, just to get you past the check for -1
  3405. mousewait = I_GetTime() + 15;
  3406. }
  3407. }
  3408. else
  3409. // Process keyboard input
  3410. if (ev->type == ev_keydown)
  3411. {
  3412. ch = ev->data1; // phares 4/11/98:
  3413. if (ch == KEYD_RSHIFT) // For chat string processing, need
  3414. shiftdown = true; // to know when shift key is up or
  3415. } // down so you can get at the !,#,
  3416. else if (ev->type == ev_keyup) // etc. keys. Keydowns are allowed
  3417. if (ev->data1 == KEYD_RSHIFT) // past this point, but keyups aren't
  3418. shiftdown = false; // so we need to note the difference
  3419. } // here using the 'shiftdown' boolean.
  3420. if (ch == -1)
  3421. return false; // we can't use the event here
  3422. // Save Game string input
  3423. if (saveStringEnter) {
  3424. if (ch == key_menu_backspace) // phares 3/7/98
  3425. {
  3426. if (saveCharIndex > 0)
  3427. {
  3428. saveCharIndex--;
  3429. savegamestrings[saveSlot][saveCharIndex] = 0;
  3430. }
  3431. }
  3432. else if (ch == key_menu_escape) // phares 3/7/98
  3433. {
  3434. saveStringEnter = 0;
  3435. strcpy(&savegamestrings[saveSlot][0],saveOldString);
  3436. }
  3437. else if (ch == key_menu_enter) // phares 3/7/98
  3438. {
  3439. saveStringEnter = 0;
  3440. if (savegamestrings[saveSlot][0])
  3441. M_DoSave(saveSlot);
  3442. }
  3443. else
  3444. {
  3445. ch = toupper(ch);
  3446. if (ch >= 32 && ch <= 127 &&
  3447. saveCharIndex < SAVESTRINGSIZE-1 &&
  3448. M_StringWidth(savegamestrings[saveSlot]) < (SAVESTRINGSIZE-2)*8)
  3449. {
  3450. savegamestrings[saveSlot][saveCharIndex++] = ch;
  3451. savegamestrings[saveSlot][saveCharIndex] = 0;
  3452. }
  3453. }
  3454. return true;
  3455. }
  3456. // Take care of any messages that need input
  3457. if (messageToPrint) {
  3458. if (messageNeedsInput == true &&
  3459. !(ch == ' ' || ch == 'n' || ch == 'y' || ch == key_escape)) // phares
  3460. return false;
  3461. menuactive = messageLastMenuActive;
  3462. messageToPrint = 0;
  3463. if (messageRoutine)
  3464. messageRoutine(ch);
  3465. menuactive = false;
  3466. S_StartSound(NULL,sfx_swtchx);
  3467. return true;
  3468. }
  3469. /* killough 2/22/98: add support for screenshot key:
  3470. * cph 2001/02/04: no need for this to be a gameaction, just do it
  3471. */
  3472. if (ch == key_screenshot)
  3473. {
  3474. M_ScreenShot ();
  3475. // Don't eat the keypress in this case. See sf bug #1843280.
  3476. }
  3477. // If there is no active menu displayed...
  3478. if (!menuactive) { // phares
  3479. if (ch == key_autorun) // Autorun // V
  3480. {
  3481. autorun = !autorun;
  3482. return true;
  3483. }
  3484. if (ch == key_help) // Help key
  3485. {
  3486. M_StartControlPanel ();
  3487. currentMenu = &HelpDef; // killough 10/98: new help screen
  3488. itemOn = 0;
  3489. S_StartSound(NULL,sfx_swtchn);
  3490. return true;
  3491. }
  3492. if (ch == key_savegame) // Save Game
  3493. {
  3494. M_StartControlPanel();
  3495. S_StartSound(NULL,sfx_swtchn);
  3496. M_SaveGame(0);
  3497. return true;
  3498. }
  3499. if (ch == key_loadgame) // Load Game
  3500. {
  3501. M_StartControlPanel();
  3502. S_StartSound(NULL,sfx_swtchn);
  3503. M_LoadGame(0);
  3504. return true;
  3505. }
  3506. if (ch == key_soundvolume) // Sound Volume
  3507. {
  3508. M_StartControlPanel ();
  3509. currentMenu = &SoundDef;
  3510. itemOn = sfx_vol;
  3511. S_StartSound(NULL,sfx_swtchn);
  3512. return true;
  3513. }
  3514. if (ch == key_quicksave) // Quicksave
  3515. {
  3516. S_StartSound(NULL,sfx_swtchn);
  3517. M_QuickSave();
  3518. return true;
  3519. }
  3520. if (ch == key_endgame) // End game
  3521. {
  3522. S_StartSound(NULL,sfx_swtchn);
  3523. M_EndGame(0);
  3524. return true;
  3525. }
  3526. if (ch == key_messages) // Toggle messages
  3527. {
  3528. M_ChangeMessages(0);
  3529. S_StartSound(NULL,sfx_swtchn);
  3530. return true;
  3531. }
  3532. if (ch == key_quickload) // Quickload
  3533. {
  3534. S_StartSound(NULL,sfx_swtchn);
  3535. M_QuickLoad();
  3536. return true;
  3537. }
  3538. if (ch == key_quit) // Quit DOOM
  3539. {
  3540. S_StartSound(NULL,sfx_swtchn);
  3541. M_QuitDOOM(0);
  3542. return true;
  3543. }
  3544. if (ch == key_gamma) // gamma toggle
  3545. {
  3546. usegamma++;
  3547. if (usegamma > 4)
  3548. usegamma = 0;
  3549. players[consoleplayer].message =
  3550. usegamma == 0 ? s_GAMMALVL0 :
  3551. usegamma == 1 ? s_GAMMALVL1 :
  3552. usegamma == 2 ? s_GAMMALVL2 :
  3553. usegamma == 3 ? s_GAMMALVL3 :
  3554. s_GAMMALVL4;
  3555. V_SetPalette(0);
  3556. return true;
  3557. }
  3558. if (ch == key_zoomout) // zoom out
  3559. {
  3560. if ((automapmode & am_active) || chat_on)
  3561. return false;
  3562. M_SizeDisplay(0);
  3563. S_StartSound(NULL,sfx_stnmov);
  3564. return true;
  3565. }
  3566. if (ch == key_zoomin) // zoom in
  3567. { // jff 2/23/98
  3568. if ((automapmode & am_active) || chat_on) // allow
  3569. return false; // key_hud==key_zoomin
  3570. M_SizeDisplay(1); // ^
  3571. S_StartSound(NULL,sfx_stnmov); // |
  3572. return true; // phares
  3573. }
  3574. if (ch == key_hud) // heads-up mode
  3575. {
  3576. if ((automapmode & am_active) || chat_on) // jff 2/22/98
  3577. return false; // HUD mode control
  3578. if (screenSize<8) // function on default F5
  3579. while (screenSize<8 || !hud_displayed) // make hud visible
  3580. M_SizeDisplay(1); // when configuring it
  3581. else
  3582. {
  3583. hud_displayed = 1; //jff 3/3/98 turn hud on
  3584. hud_active = (hud_active+1)%3; // cycle hud_active
  3585. if (!hud_active) //jff 3/4/98 add distributed
  3586. {
  3587. hud_distributed = !hud_distributed; // to cycle
  3588. HU_MoveHud(); //jff 3/9/98 move it now to avoid glitch
  3589. }
  3590. }
  3591. return true;
  3592. }
  3593. /* killough 10/98: allow key shortcut into Setup menu */
  3594. if (ch == key_setup) {
  3595. M_StartControlPanel();
  3596. S_StartSound(NULL,sfx_swtchn);
  3597. M_SetupNextMenu(&SetupDef);
  3598. return true;
  3599. }
  3600. }
  3601. // Pop-up Main menu?
  3602. if (!menuactive)
  3603. {
  3604. if (ch == key_escape) // phares
  3605. {
  3606. M_StartControlPanel ();
  3607. S_StartSound(NULL,sfx_swtchn);
  3608. return true;
  3609. }
  3610. return false;
  3611. }
  3612. // phares 3/26/98 - 4/11/98:
  3613. // Setup screen key processing
  3614. if (setup_active) {
  3615. setup_menu_t* ptr1= current_setup_menu + set_menu_itemon;
  3616. setup_menu_t* ptr2 = NULL;
  3617. // phares 4/19/98:
  3618. // Catch the response to the 'reset to default?' verification
  3619. // screen
  3620. if (default_verify)
  3621. {
  3622. if (toupper(ch) == 'Y') {
  3623. M_ResetDefaults();
  3624. default_verify = false;
  3625. M_SelectDone(ptr1);
  3626. }
  3627. else if (toupper(ch) == 'N') {
  3628. default_verify = false;
  3629. M_SelectDone(ptr1);
  3630. }
  3631. return true;
  3632. }
  3633. // Common processing for some items
  3634. if (setup_select) { // changing an entry
  3635. if (ch == key_menu_escape) // Exit key = no change
  3636. {
  3637. M_SelectDone(ptr1); // phares 4/17/98
  3638. setup_gather = false; // finished gathering keys, if any
  3639. return true;
  3640. }
  3641. if (ptr1->m_flags & S_YESNO) // yes or no setting?
  3642. {
  3643. if (ch == key_menu_enter) {
  3644. *ptr1->var.def->location.pi = !*ptr1->var.def->location.pi; // killough 8/15/98
  3645. // phares 4/14/98:
  3646. // If not in demoplayback, demorecording, or netgame,
  3647. // and there's a second variable in var2, set that
  3648. // as well
  3649. // killough 8/15/98: add warning messages
  3650. if (ptr1->m_flags & (S_LEVWARN | S_PRGWARN))
  3651. warn_about_changes(ptr1->m_flags & // killough 10/98
  3652. (S_LEVWARN | S_PRGWARN));
  3653. else
  3654. M_UpdateCurrent(ptr1->var.def);
  3655. if (ptr1->action) // killough 10/98
  3656. ptr1->action();
  3657. }
  3658. M_SelectDone(ptr1); // phares 4/17/98
  3659. return true;
  3660. }
  3661. if (ptr1->m_flags & S_CRITEM)
  3662. {
  3663. if (ch != key_menu_enter)
  3664. {
  3665. ch -= 0x30; // out of ascii
  3666. if (ch < 0 || ch > 9)
  3667. return true; // ignore
  3668. *ptr1->var.def->location.pi = ch;
  3669. }
  3670. if (ptr1->action) // killough 10/98
  3671. ptr1->action();
  3672. M_SelectDone(ptr1); // phares 4/17/98
  3673. return true;
  3674. }
  3675. if (ptr1->m_flags & S_NUM) // number?
  3676. {
  3677. if (setup_gather) { // gathering keys for a value?
  3678. /* killough 10/98: Allow negatives, and use a more
  3679. * friendly input method (e.g. don't clear value early,
  3680. * allow backspace, and return to original value if bad
  3681. * value is entered).
  3682. */
  3683. if (ch == key_menu_enter) {
  3684. if (gather_count) { // Any input?
  3685. int value;
  3686. gather_buffer[gather_count] = 0;
  3687. value = atoi(gather_buffer); // Integer value
  3688. if ((ptr1->var.def->minvalue != UL &&
  3689. value < ptr1->var.def->minvalue) ||
  3690. (ptr1->var.def->maxvalue != UL &&
  3691. value > ptr1->var.def->maxvalue))
  3692. warn_about_changes(S_BADVAL);
  3693. else {
  3694. *ptr1->var.def->location.pi = value;
  3695. /* killough 8/9/98: fix numeric vars
  3696. * killough 8/15/98: add warning message
  3697. */
  3698. if (ptr1->m_flags & (S_LEVWARN | S_PRGWARN))
  3699. warn_about_changes(ptr1->m_flags &
  3700. (S_LEVWARN | S_PRGWARN));
  3701. else
  3702. M_UpdateCurrent(ptr1->var.def);
  3703. if (ptr1->action) // killough 10/98
  3704. ptr1->action();
  3705. }
  3706. }
  3707. M_SelectDone(ptr1); // phares 4/17/98
  3708. setup_gather = false; // finished gathering keys
  3709. return true;
  3710. }
  3711. if (ch == key_menu_backspace && gather_count) {
  3712. gather_count--;
  3713. return true;
  3714. }
  3715. if (gather_count >= MAXGATHER)
  3716. return true;
  3717. if (!isdigit(ch) && ch != '-')
  3718. return true; // ignore
  3719. /* killough 10/98: character-based numerical input */
  3720. gather_buffer[gather_count++] = ch;
  3721. }
  3722. return true;
  3723. }
  3724. if (ptr1->m_flags & S_CHOICE) // selection of choices?
  3725. {
  3726. if (ch == key_menu_left) {
  3727. if (ptr1->var.def->type == def_int) {
  3728. int value = *ptr1->var.def->location.pi;
  3729. value = value - 1;
  3730. if ((ptr1->var.def->minvalue != UL &&
  3731. value < ptr1->var.def->minvalue))
  3732. value = ptr1->var.def->minvalue;
  3733. if ((ptr1->var.def->maxvalue != UL &&
  3734. value > ptr1->var.def->maxvalue))
  3735. value = ptr1->var.def->maxvalue;
  3736. if (*ptr1->var.def->location.pi != value)
  3737. S_StartSound(NULL,sfx_pstop);
  3738. *ptr1->var.def->location.pi = value;
  3739. }
  3740. if (ptr1->var.def->type == def_str) {
  3741. int old_value, value;
  3742. old_value = M_IndexInChoices(*ptr1->var.def->location.ppsz,
  3743. ptr1->selectstrings);
  3744. value = old_value - 1;
  3745. if (value < 0)
  3746. value = 0;
  3747. if (old_value != value)
  3748. S_StartSound(NULL,sfx_pstop);
  3749. *ptr1->var.def->location.ppsz = ptr1->selectstrings[value];
  3750. }
  3751. }
  3752. if (ch == key_menu_right) {
  3753. if (ptr1->var.def->type == def_int) {
  3754. int value = *ptr1->var.def->location.pi;
  3755. value = value + 1;
  3756. if ((ptr1->var.def->minvalue != UL &&
  3757. value < ptr1->var.def->minvalue))
  3758. value = ptr1->var.def->minvalue;
  3759. if ((ptr1->var.def->maxvalue != UL &&
  3760. value > ptr1->var.def->maxvalue))
  3761. value = ptr1->var.def->maxvalue;
  3762. if (*ptr1->var.def->location.pi != value)
  3763. S_StartSound(NULL,sfx_pstop);
  3764. *ptr1->var.def->location.pi = value;
  3765. }
  3766. if (ptr1->var.def->type == def_str) {
  3767. int old_value, value;
  3768. old_value = M_IndexInChoices(*ptr1->var.def->location.ppsz,
  3769. ptr1->selectstrings);
  3770. value = old_value + 1;
  3771. if (ptr1->selectstrings[value] == NULL)
  3772. value = old_value;
  3773. if (old_value != value)
  3774. S_StartSound(NULL,sfx_pstop);
  3775. *ptr1->var.def->location.ppsz = ptr1->selectstrings[value];
  3776. }
  3777. }
  3778. if (ch == key_menu_enter) {
  3779. // phares 4/14/98:
  3780. // If not in demoplayback, demorecording, or netgame,
  3781. // and there's a second variable in var2, set that
  3782. // as well
  3783. // killough 8/15/98: add warning messages
  3784. if (ptr1->m_flags & (S_LEVWARN | S_PRGWARN))
  3785. warn_about_changes(ptr1->m_flags & // killough 10/98
  3786. (S_LEVWARN | S_PRGWARN));
  3787. else
  3788. M_UpdateCurrent(ptr1->var.def);
  3789. if (ptr1->action) // killough 10/98
  3790. ptr1->action();
  3791. M_SelectDone(ptr1); // phares 4/17/98
  3792. }
  3793. return true;
  3794. }
  3795. }
  3796. // Key Bindings
  3797. if (set_keybnd_active) // on a key binding setup screen
  3798. if (setup_select) // incoming key or button gets bound
  3799. {
  3800. if (ev->type == ev_joystick)
  3801. {
  3802. int oldbutton,group;
  3803. boolean search = true;
  3804. if (!ptr1->m_joy)
  3805. return true; // not a legal action here (yet)
  3806. // see if the button is already bound elsewhere. if so, you
  3807. // have to swap bindings so the action where it's currently
  3808. // bound doesn't go dead. Since there is more than one
  3809. // keybinding screen, you have to search all of them for
  3810. // any duplicates. You're only interested in the items
  3811. // that belong to the same group as the one you're changing.
  3812. oldbutton = *ptr1->m_joy;
  3813. group = ptr1->m_group;
  3814. if (ev->data1 & 1)
  3815. ch = 0;
  3816. else if (ev->data1 & 2)
  3817. ch = 1;
  3818. else if (ev->data1 & 4)
  3819. ch = 2;
  3820. else if (ev->data1 & 8)
  3821. ch = 3;
  3822. else
  3823. return true;
  3824. for (i = 0 ; keys_settings[i] && search ; i++)
  3825. for (ptr2 = keys_settings[i] ; !(ptr2->m_flags & S_END) ; ptr2++)
  3826. if (ptr2->m_group == group && ptr1 != ptr2)
  3827. if (ptr2->m_flags & S_KEY && ptr2->m_joy)
  3828. if (*ptr2->m_joy == ch)
  3829. {
  3830. *ptr2->m_joy = oldbutton;
  3831. search = false;
  3832. break;
  3833. }
  3834. *ptr1->m_joy = ch;
  3835. }
  3836. else if (ev->type == ev_mouse)
  3837. {
  3838. int oldbutton,group;
  3839. boolean search = true;
  3840. if (!ptr1->m_mouse)
  3841. return true; // not a legal action here (yet)
  3842. // see if the button is already bound elsewhere. if so, you
  3843. // have to swap bindings so the action where it's currently
  3844. // bound doesn't go dead. Since there is more than one
  3845. // keybinding screen, you have to search all of them for
  3846. // any duplicates. You're only interested in the items
  3847. // that belong to the same group as the one you're changing.
  3848. oldbutton = *ptr1->m_mouse;
  3849. group = ptr1->m_group;
  3850. if (ev->data1 & 1)
  3851. ch = 0;
  3852. else if (ev->data1 & 2)
  3853. ch = 1;
  3854. else if (ev->data1 & 4)
  3855. ch = 2;
  3856. else
  3857. return true;
  3858. for (i = 0 ; keys_settings[i] && search ; i++)
  3859. for (ptr2 = keys_settings[i] ; !(ptr2->m_flags & S_END) ; ptr2++)
  3860. if (ptr2->m_group == group && ptr1 != ptr2)
  3861. if (ptr2->m_flags & S_KEY && ptr2->m_mouse)
  3862. if (*ptr2->m_mouse == ch)
  3863. {
  3864. *ptr2->m_mouse = oldbutton;
  3865. search = false;
  3866. break;
  3867. }
  3868. *ptr1->m_mouse = ch;
  3869. }
  3870. else // keyboard key
  3871. {
  3872. int oldkey,group;
  3873. boolean search = true;
  3874. // see if 'ch' is already bound elsewhere. if so, you have
  3875. // to swap bindings so the action where it's currently
  3876. // bound doesn't go dead. Since there is more than one
  3877. // keybinding screen, you have to search all of them for
  3878. // any duplicates. You're only interested in the items
  3879. // that belong to the same group as the one you're changing.
  3880. // if you find that you're trying to swap with an action
  3881. // that has S_KEEP set, you can't bind ch; it's already
  3882. // bound to that S_KEEP action, and that action has to
  3883. // keep that key.
  3884. oldkey = *ptr1->var.m_key;
  3885. group = ptr1->m_group;
  3886. for (i = 0 ; keys_settings[i] && search ; i++)
  3887. for (ptr2 = keys_settings[i] ; !(ptr2->m_flags & S_END) ; ptr2++)
  3888. if (ptr2->m_flags & (S_KEY|S_KEEP) &&
  3889. ptr2->m_group == group &&
  3890. ptr1 != ptr2)
  3891. if (*ptr2->var.m_key == ch)
  3892. {
  3893. if (ptr2->m_flags & S_KEEP)
  3894. return true; // can't have it!
  3895. *ptr2->var.m_key = oldkey;
  3896. search = false;
  3897. break;
  3898. }
  3899. *ptr1->var.m_key = ch;
  3900. }
  3901. M_SelectDone(ptr1); // phares 4/17/98
  3902. return true;
  3903. }
  3904. // Weapons
  3905. if (set_weapon_active) // on the weapons setup screen
  3906. if (setup_select) // changing an entry
  3907. {
  3908. if (ch != key_menu_enter)
  3909. {
  3910. ch -= '0'; // out of ascii
  3911. if (ch < 1 || ch > 9)
  3912. return true; // ignore
  3913. // Plasma and BFG don't exist in shareware
  3914. // killough 10/98: allow it anyway, since this
  3915. // isn't the game itself, just setting preferences
  3916. // see if 'ch' is already assigned elsewhere. if so,
  3917. // you have to swap assignments.
  3918. // killough 11/98: simplified
  3919. for (i = 0; (ptr2 = weap_settings[i]); i++)
  3920. for (; !(ptr2->m_flags & S_END); ptr2++)
  3921. if (ptr2->m_flags & S_WEAP &&
  3922. *ptr2->var.def->location.pi == ch && ptr1 != ptr2)
  3923. {
  3924. *ptr2->var.def->location.pi = *ptr1->var.def->location.pi;
  3925. goto end;
  3926. }
  3927. end:
  3928. *ptr1->var.def->location.pi = ch;
  3929. }
  3930. M_SelectDone(ptr1); // phares 4/17/98
  3931. return true;
  3932. }
  3933. // Automap
  3934. if (set_auto_active) // on the automap setup screen
  3935. if (setup_select) // incoming key
  3936. {
  3937. if (ch == key_menu_down)
  3938. {
  3939. if (++color_palette_y == 16)
  3940. color_palette_y = 0;
  3941. S_StartSound(NULL,sfx_itemup);
  3942. return true;
  3943. }
  3944. if (ch == key_menu_up)
  3945. {
  3946. if (--color_palette_y < 0)
  3947. color_palette_y = 15;
  3948. S_StartSound(NULL,sfx_itemup);
  3949. return true;
  3950. }
  3951. if (ch == key_menu_left)
  3952. {
  3953. if (--color_palette_x < 0)
  3954. color_palette_x = 15;
  3955. S_StartSound(NULL,sfx_itemup);
  3956. return true;
  3957. }
  3958. if (ch == key_menu_right)
  3959. {
  3960. if (++color_palette_x == 16)
  3961. color_palette_x = 0;
  3962. S_StartSound(NULL,sfx_itemup);
  3963. return true;
  3964. }
  3965. if (ch == key_menu_enter)
  3966. {
  3967. *ptr1->var.def->location.pi = color_palette_x + 16*color_palette_y;
  3968. M_SelectDone(ptr1); // phares 4/17/98
  3969. colorbox_active = false;
  3970. return true;
  3971. }
  3972. }
  3973. // killough 10/98: consolidate handling into one place:
  3974. if (setup_select &&
  3975. set_enemy_active | set_general_active | set_chat_active |
  3976. set_mess_active | set_status_active | set_compat_active)
  3977. {
  3978. if (ptr1->m_flags & S_STRING) // creating/editing a string?
  3979. {
  3980. if (ch == key_menu_backspace) // backspace and DEL
  3981. {
  3982. if (chat_string_buffer[chat_index] == 0)
  3983. {
  3984. if (chat_index > 0)
  3985. chat_string_buffer[--chat_index] = 0;
  3986. }
  3987. // shift the remainder of the text one char left
  3988. else
  3989. strcpy(&chat_string_buffer[chat_index],
  3990. &chat_string_buffer[chat_index+1]);
  3991. }
  3992. else if (ch == key_menu_left) // move cursor left
  3993. {
  3994. if (chat_index > 0)
  3995. chat_index--;
  3996. }
  3997. else if (ch == key_menu_right) // move cursor right
  3998. {
  3999. if (chat_string_buffer[chat_index] != 0)
  4000. chat_index++;
  4001. }
  4002. else if ((ch == key_menu_enter) ||
  4003. (ch == key_menu_escape))
  4004. {
  4005. *ptr1->var.def->location.ppsz = chat_string_buffer;
  4006. M_SelectDone(ptr1); // phares 4/17/98
  4007. }
  4008. // Adding a char to the text. Has to be a printable
  4009. // char, and you can't overrun the buffer. If the
  4010. // chat string gets larger than what the screen can hold,
  4011. // it is dealt with when the string is drawn (above).
  4012. else if ((ch >= 32) && (ch <= 126))
  4013. if ((chat_index+1) < CHAT_STRING_BFR_SIZE)
  4014. {
  4015. if (shiftdown)
  4016. ch = shiftxform[ch];
  4017. if (chat_string_buffer[chat_index] == 0)
  4018. {
  4019. chat_string_buffer[chat_index++] = ch;
  4020. chat_string_buffer[chat_index] = 0;
  4021. }
  4022. else
  4023. chat_string_buffer[chat_index++] = ch;
  4024. }
  4025. return true;
  4026. }
  4027. M_SelectDone(ptr1); // phares 4/17/98
  4028. return true;
  4029. }
  4030. // Not changing any items on the Setup screens. See if we're
  4031. // navigating the Setup menus or selecting an item to change.
  4032. if (ch == key_menu_down)
  4033. {
  4034. ptr1->m_flags &= ~S_HILITE; // phares 4/17/98
  4035. do
  4036. if (ptr1->m_flags & S_END)
  4037. {
  4038. set_menu_itemon = 0;
  4039. ptr1 = current_setup_menu;
  4040. }
  4041. else
  4042. {
  4043. set_menu_itemon++;
  4044. ptr1++;
  4045. }
  4046. while (ptr1->m_flags & S_SKIP);
  4047. M_SelectDone(ptr1); // phares 4/17/98
  4048. return true;
  4049. }
  4050. if (ch == key_menu_up)
  4051. {
  4052. ptr1->m_flags &= ~S_HILITE; // phares 4/17/98
  4053. do
  4054. {
  4055. if (set_menu_itemon == 0)
  4056. do
  4057. set_menu_itemon++;
  4058. while(!((current_setup_menu + set_menu_itemon)->m_flags & S_END));
  4059. set_menu_itemon--;
  4060. }
  4061. while((current_setup_menu + set_menu_itemon)->m_flags & S_SKIP);
  4062. M_SelectDone(current_setup_menu + set_menu_itemon); // phares 4/17/98
  4063. return true;
  4064. }
  4065. if (ch == key_menu_enter)
  4066. {
  4067. int flags = ptr1->m_flags;
  4068. // You've selected an item to change. Highlight it, post a new
  4069. // message about what to do, and get ready to process the
  4070. // change.
  4071. //
  4072. // killough 10/98: use friendlier char-based input buffer
  4073. if (flags & S_NUM)
  4074. {
  4075. setup_gather = true;
  4076. print_warning_about_changes = false;
  4077. gather_count = 0;
  4078. }
  4079. else if (flags & S_COLOR)
  4080. {
  4081. int color = *ptr1->var.def->location.pi;
  4082. if (color < 0 || color > 255) // range check the value
  4083. color = 0; // 'no show' if invalid
  4084. color_palette_x = *ptr1->var.def->location.pi & 15;
  4085. color_palette_y = *ptr1->var.def->location.pi >> 4;
  4086. colorbox_active = true;
  4087. }
  4088. else if (flags & S_STRING)
  4089. {
  4090. // copy chat string into working buffer; trim if needed.
  4091. // free the old chat string memory and replace it with
  4092. // the (possibly larger) new memory for editing purposes
  4093. //
  4094. // killough 10/98: fix bugs, simplify
  4095. chat_string_buffer = malloc(CHAT_STRING_BFR_SIZE);
  4096. strncpy(chat_string_buffer,
  4097. *ptr1->var.def->location.ppsz, CHAT_STRING_BFR_SIZE);
  4098. // guarantee null delimiter
  4099. chat_string_buffer[CHAT_STRING_BFR_SIZE-1] = 0;
  4100. // set chat table pointer to working buffer
  4101. // and free old string's memory.
  4102. free((char*)*ptr1->var.def->location.ppsz);
  4103. *ptr1->var.def->location.ppsz = chat_string_buffer;
  4104. chat_index = 0; // current cursor position in chat_string_buffer
  4105. }
  4106. else if (flags & S_RESET)
  4107. default_verify = true;
  4108. ptr1->m_flags |= S_SELECT;
  4109. setup_select = true;
  4110. S_StartSound(NULL,sfx_itemup);
  4111. return true;
  4112. }
  4113. if ((ch == key_menu_escape) || (ch == key_menu_backspace))
  4114. {
  4115. if (ch == key_menu_escape) // Clear all menus
  4116. M_ClearMenus();
  4117. else // key_menu_backspace = return to Setup Menu
  4118. if (currentMenu->prevMenu)
  4119. {
  4120. currentMenu = currentMenu->prevMenu;
  4121. itemOn = currentMenu->lastOn;
  4122. S_StartSound(NULL,sfx_swtchn);
  4123. }
  4124. ptr1->m_flags &= ~(S_HILITE|S_SELECT);// phares 4/19/98
  4125. setup_active = false;
  4126. set_keybnd_active = false;
  4127. set_weapon_active = false;
  4128. set_status_active = false;
  4129. set_auto_active = false;
  4130. set_enemy_active = false;
  4131. set_mess_active = false;
  4132. set_chat_active = false;
  4133. colorbox_active = false;
  4134. default_verify = false; // phares 4/19/98
  4135. set_general_active = false; // killough 10/98
  4136. set_compat_active = false; // killough 10/98
  4137. HU_Start(); // catch any message changes // phares 4/19/98
  4138. S_StartSound(NULL,sfx_swtchx);
  4139. return true;
  4140. }
  4141. // Some setup screens may have multiple screens.
  4142. // When there are multiple screens, m_prev and m_next items need to
  4143. // be placed on the appropriate screen tables so the user can
  4144. // move among the screens using the left and right arrow keys.
  4145. // The m_var1 field contains a pointer to the appropriate screen
  4146. // to move to.
  4147. if (ch == key_menu_left)
  4148. {
  4149. ptr2 = ptr1;
  4150. do
  4151. {
  4152. ptr2++;
  4153. if (ptr2->m_flags & S_PREV)
  4154. {
  4155. ptr1->m_flags &= ~S_HILITE;
  4156. mult_screens_index--;
  4157. current_setup_menu = ptr2->var.menu;
  4158. set_menu_itemon = 0;
  4159. print_warning_about_changes = false; // killough 10/98
  4160. while (current_setup_menu[set_menu_itemon++].m_flags&S_SKIP);
  4161. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  4162. S_StartSound(NULL,sfx_pstop); // killough 10/98
  4163. return true;
  4164. }
  4165. }
  4166. while (!(ptr2->m_flags & S_END));
  4167. }
  4168. if (ch == key_menu_right)
  4169. {
  4170. ptr2 = ptr1;
  4171. do
  4172. {
  4173. ptr2++;
  4174. if (ptr2->m_flags & S_NEXT)
  4175. {
  4176. ptr1->m_flags &= ~S_HILITE;
  4177. mult_screens_index++;
  4178. current_setup_menu = ptr2->var.menu;
  4179. set_menu_itemon = 0;
  4180. print_warning_about_changes = false; // killough 10/98
  4181. while (current_setup_menu[set_menu_itemon++].m_flags&S_SKIP);
  4182. current_setup_menu[--set_menu_itemon].m_flags |= S_HILITE;
  4183. S_StartSound(NULL,sfx_pstop); // killough 10/98
  4184. return true;
  4185. }
  4186. }
  4187. while (!(ptr2->m_flags & S_END));
  4188. }
  4189. } // End of Setup Screen processing
  4190. // From here on, these navigation keys are used on the BIG FONT menus
  4191. // like the Main Menu.
  4192. if (ch == key_menu_down) // phares 3/7/98
  4193. {
  4194. do
  4195. {
  4196. if (itemOn+1 > currentMenu->numitems-1)
  4197. itemOn = 0;
  4198. else
  4199. itemOn++;
  4200. S_StartSound(NULL,sfx_pstop);
  4201. }
  4202. while(currentMenu->menuitems[itemOn].status==-1);
  4203. return true;
  4204. }
  4205. if (ch == key_menu_up) // phares 3/7/98
  4206. {
  4207. do
  4208. {
  4209. if (!itemOn)
  4210. itemOn = currentMenu->numitems-1;
  4211. else
  4212. itemOn--;
  4213. S_StartSound(NULL,sfx_pstop);
  4214. }
  4215. while(currentMenu->menuitems[itemOn].status==-1);
  4216. return true;
  4217. }
  4218. if (ch == key_menu_left) // phares 3/7/98
  4219. {
  4220. if (currentMenu->menuitems[itemOn].routine &&
  4221. currentMenu->menuitems[itemOn].status == 2)
  4222. {
  4223. S_StartSound(NULL,sfx_stnmov);
  4224. currentMenu->menuitems[itemOn].routine(0);
  4225. }
  4226. return true;
  4227. }
  4228. if (ch == key_menu_right) // phares 3/7/98
  4229. {
  4230. if (currentMenu->menuitems[itemOn].routine &&
  4231. currentMenu->menuitems[itemOn].status == 2)
  4232. {
  4233. S_StartSound(NULL,sfx_stnmov);
  4234. currentMenu->menuitems[itemOn].routine(1);
  4235. }
  4236. return true;
  4237. }
  4238. if (ch == key_menu_enter) // phares 3/7/98
  4239. {
  4240. if (currentMenu->menuitems[itemOn].routine &&
  4241. currentMenu->menuitems[itemOn].status)
  4242. {
  4243. currentMenu->lastOn = itemOn;
  4244. if (currentMenu->menuitems[itemOn].status == 2)
  4245. {
  4246. currentMenu->menuitems[itemOn].routine(1); // right arrow
  4247. S_StartSound(NULL,sfx_stnmov);
  4248. }
  4249. else
  4250. {
  4251. currentMenu->menuitems[itemOn].routine(itemOn);
  4252. S_StartSound(NULL,sfx_pistol);
  4253. }
  4254. }
  4255. //jff 3/24/98 remember last skill selected
  4256. // killough 10/98 moved to skill-specific functions
  4257. return true;
  4258. }
  4259. if (ch == key_menu_escape) // phares 3/7/98
  4260. {
  4261. currentMenu->lastOn = itemOn;
  4262. M_ClearMenus ();
  4263. S_StartSound(NULL,sfx_swtchx);
  4264. return true;
  4265. }
  4266. if (ch == key_menu_backspace) // phares 3/7/98
  4267. {
  4268. currentMenu->lastOn = itemOn;
  4269. // phares 3/30/98:
  4270. // add checks to see if you're in the extended help screens
  4271. // if so, stay with the same menu definition, but bump the
  4272. // index back one. if the index bumps back far enough ( == 0)
  4273. // then you can return to the Read_Thisn menu definitions
  4274. if (currentMenu->prevMenu)
  4275. {
  4276. if (currentMenu == &ExtHelpDef)
  4277. {
  4278. if (--extended_help_index == 0)
  4279. {
  4280. currentMenu = currentMenu->prevMenu;
  4281. extended_help_index = 1; // reset
  4282. }
  4283. }
  4284. else
  4285. currentMenu = currentMenu->prevMenu;
  4286. itemOn = currentMenu->lastOn;
  4287. S_StartSound(NULL,sfx_swtchn);
  4288. }
  4289. return true;
  4290. }
  4291. else
  4292. {
  4293. for (i = itemOn+1;i < currentMenu->numitems;i++)
  4294. if (currentMenu->menuitems[i].alphaKey == ch)
  4295. {
  4296. itemOn = i;
  4297. S_StartSound(NULL,sfx_pstop);
  4298. return true;
  4299. }
  4300. for (i = 0;i <= itemOn;i++)
  4301. if (currentMenu->menuitems[i].alphaKey == ch)
  4302. {
  4303. itemOn = i;
  4304. S_StartSound(NULL,sfx_pstop);
  4305. return true;
  4306. }
  4307. }
  4308. return false;
  4309. }
  4310. //
  4311. // End of M_Responder
  4312. //
  4313. /////////////////////////////////////////////////////////////////////////////
  4314. /////////////////////////////////////////////////////////////////////////////
  4315. //
  4316. // General Routines
  4317. //
  4318. // This displays the Main menu and gets the menu screens rolling.
  4319. // Plus a variety of routines that control the Big Font menu display.
  4320. // Plus some initialization for game-dependant situations.
  4321. void M_StartControlPanel (void)
  4322. {
  4323. // intro might call this repeatedly
  4324. if (menuactive)
  4325. return;
  4326. //jff 3/24/98 make default skill menu choice follow -skill or defaultskill
  4327. //from command line or config file
  4328. //
  4329. // killough 10/98:
  4330. // Fix to make "always floating" with menu selections, and to always follow
  4331. // defaultskill, instead of -skill.
  4332. NewDef.lastOn = defaultskill - 1;
  4333. default_verify = 0; // killough 10/98
  4334. menuactive = 1;
  4335. currentMenu = &MainDef; // JDC
  4336. itemOn = currentMenu->lastOn; // JDC
  4337. print_warning_about_changes = false; // killough 11/98
  4338. }
  4339. //
  4340. // M_Drawer
  4341. // Called after the view has been rendered,
  4342. // but before it has been blitted.
  4343. //
  4344. // killough 9/29/98: Significantly reformatted source
  4345. //
  4346. void M_Drawer (void)
  4347. {
  4348. inhelpscreens = false;
  4349. // Horiz. & Vertically center string and print it.
  4350. // killough 9/29/98: simplified code, removed 40-character width limit
  4351. if (messageToPrint)
  4352. {
  4353. /* cph - strdup string to writable memory */
  4354. char *ms = strdup(messageString);
  4355. char *p = ms;
  4356. int y = 100 - M_StringHeight(messageString)/2;
  4357. while (*p)
  4358. {
  4359. char *string = p, c;
  4360. while ((c = *p) && *p != '\n')
  4361. p++;
  4362. *p = 0;
  4363. M_WriteText(160 - M_StringWidth(string)/2, y, string);
  4364. y += hu_font[0].height;
  4365. if ((*p = c))
  4366. p++;
  4367. }
  4368. free(ms);
  4369. }
  4370. else
  4371. if (menuactive)
  4372. {
  4373. int x,y,max,i;
  4374. if (currentMenu->routine)
  4375. currentMenu->routine(); // call Draw routine
  4376. // DRAW MENU
  4377. x = currentMenu->x;
  4378. y = currentMenu->y;
  4379. max = currentMenu->numitems;
  4380. for (i=0;i<max;i++)
  4381. {
  4382. if (currentMenu->menuitems[i].name[0])
  4383. V_DrawNamePatch(x,y,0,currentMenu->menuitems[i].name,
  4384. CR_DEFAULT, VPT_STRETCH);
  4385. y += LINEHEIGHT;
  4386. }
  4387. // DRAW SKULL
  4388. // CPhipps - patch drawing updated
  4389. V_DrawNamePatch(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,0,
  4390. skullName[whichSkull], CR_DEFAULT, VPT_STRETCH);
  4391. }
  4392. }
  4393. //
  4394. // M_ClearMenus
  4395. //
  4396. // Called when leaving the menu screens for the real world
  4397. void M_ClearMenus (void)
  4398. {
  4399. menuactive = 0;
  4400. print_warning_about_changes = 0; // killough 8/15/98
  4401. default_verify = 0; // killough 10/98
  4402. // if (!netgame && usergame && paused)
  4403. // sendpause = true;
  4404. }
  4405. //
  4406. // M_SetupNextMenu
  4407. //
  4408. void M_SetupNextMenu(menu_t *menudef)
  4409. {
  4410. currentMenu = menudef;
  4411. itemOn = currentMenu->lastOn;
  4412. }
  4413. /////////////////////////////
  4414. //
  4415. // M_Ticker
  4416. //
  4417. void M_Ticker (void)
  4418. {
  4419. if (--skullAnimCounter <= 0)
  4420. {
  4421. whichSkull ^= 1;
  4422. skullAnimCounter = 8;
  4423. }
  4424. }
  4425. /////////////////////////////
  4426. //
  4427. // Message Routines
  4428. //
  4429. void M_StartMessage (const char* string,MessageRoutineFunction routine,boolean input)
  4430. {
  4431. messageLastMenuActive = menuactive;
  4432. messageToPrint = 1;
  4433. messageString = string;
  4434. messageRoutine = routine;
  4435. messageNeedsInput = input;
  4436. menuactive = true;
  4437. return;
  4438. }
  4439. void M_StopMessage(void)
  4440. {
  4441. menuactive = messageLastMenuActive;
  4442. messageToPrint = 0;
  4443. }
  4444. /////////////////////////////
  4445. //
  4446. // Thermometer Routines
  4447. //
  4448. //
  4449. // M_DrawThermo draws the thermometer graphic for Mouse Sensitivity,
  4450. // Sound Volume, etc.
  4451. //
  4452. // proff/nicolas 09/20/98 -- changed for hi-res
  4453. // CPhipps - patch drawing updated
  4454. //
  4455. void M_DrawThermo(int x,int y,int thermWidth,int thermDot )
  4456. {
  4457. int xx;
  4458. int i;
  4459. /*
  4460. * Modification By Barry Mead to allow the Thermometer to have vastly
  4461. * larger ranges. (the thermWidth parameter can now have a value as
  4462. * large as 200. Modified 1-9-2000 Originally I used it to make
  4463. * the sensitivity range for the mouse better. It could however also
  4464. * be used to improve the dynamic range of music and sound affect
  4465. * volume controls for example.
  4466. */
  4467. int horizScaler; //Used to allow more thermo range for mouse sensitivity.
  4468. thermWidth = (thermWidth > 200) ? 200 : thermWidth; //Clamp to 200 max
  4469. horizScaler = (thermWidth > 23) ? (200 / thermWidth) : 8; //Dynamic range
  4470. xx = x;
  4471. V_DrawNamePatch(xx, y, 0, "M_THERML", CR_DEFAULT, VPT_STRETCH);
  4472. xx += 8;
  4473. for (i=0;i<thermWidth;i++)
  4474. {
  4475. V_DrawNamePatch(xx, y, 0, "M_THERMM", CR_DEFAULT, VPT_STRETCH);
  4476. xx += horizScaler;
  4477. }
  4478. xx += (8 - horizScaler); /* make the right end look even */
  4479. V_DrawNamePatch(xx, y, 0, "M_THERMR", CR_DEFAULT, VPT_STRETCH);
  4480. V_DrawNamePatch((x+8)+thermDot*horizScaler,y,0,"M_THERMO",CR_DEFAULT,VPT_STRETCH);
  4481. }
  4482. //
  4483. // Draw an empty cell in the thermometer
  4484. //
  4485. void M_DrawEmptyCell (menu_t* menu,int item)
  4486. {
  4487. // CPhipps - patch drawing updated
  4488. V_DrawNamePatch(menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
  4489. "M_CELL1", CR_DEFAULT, VPT_STRETCH);
  4490. }
  4491. //
  4492. // Draw a full cell in the thermometer
  4493. //
  4494. void M_DrawSelCell (menu_t* menu,int item)
  4495. {
  4496. // CPhipps - patch drawing updated
  4497. V_DrawNamePatch(menu->x - 10, menu->y+item*LINEHEIGHT - 1, 0,
  4498. "M_CELL2", CR_DEFAULT, VPT_STRETCH);
  4499. }
  4500. /////////////////////////////
  4501. //
  4502. // String-drawing Routines
  4503. //
  4504. //
  4505. // Find string width from hu_font chars
  4506. //
  4507. int M_StringWidth(const char* string)
  4508. {
  4509. int i, c, w = 0;
  4510. for (i = 0;(size_t)i < strlen(string);i++)
  4511. w += (c = toupper(string[i]) - HU_FONTSTART) < 0 || c >= HU_FONTSIZE ?
  4512. 4 : hu_font[c].width;
  4513. return w;
  4514. }
  4515. //
  4516. // Find string height from hu_font chars
  4517. //
  4518. int M_StringHeight(const char* string)
  4519. {
  4520. int i, h, height = h = hu_font[0].height;
  4521. for (i = 0;string[i];i++) // killough 1/31/98
  4522. if (string[i] == '\n')
  4523. h += height;
  4524. return h;
  4525. }
  4526. //
  4527. // Write a string using the hu_font
  4528. //
  4529. void M_WriteText (int x,int y,const char* string)
  4530. {
  4531. int w;
  4532. const char* ch;
  4533. int c;
  4534. int cx;
  4535. int cy;
  4536. ch = string;
  4537. cx = x;
  4538. cy = y;
  4539. while(1) {
  4540. c = *ch++;
  4541. if (!c)
  4542. break;
  4543. if (c == '\n') {
  4544. cx = x;
  4545. cy += 12;
  4546. continue;
  4547. }
  4548. c = toupper(c) - HU_FONTSTART;
  4549. if (c < 0 || c>= HU_FONTSIZE) {
  4550. cx += 4;
  4551. continue;
  4552. }
  4553. w = hu_font[c].width;
  4554. if (cx+w > SCREENWIDTH)
  4555. break;
  4556. // proff/nicolas 09/20/98 -- changed for hi-res
  4557. // CPhipps - patch drawing updated
  4558. V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH);
  4559. cx+=w;
  4560. }
  4561. }
  4562. /////////////////////////////
  4563. //
  4564. // Initialization Routines to take care of one-time setup
  4565. //
  4566. // phares 4/08/98:
  4567. // M_InitHelpScreen() clears the weapons from the HELP
  4568. // screen that don't exist in this version of the game.
  4569. void M_InitHelpScreen(void)
  4570. {
  4571. setup_menu_t* src;
  4572. src = helpstrings;
  4573. while (!(src->m_flags & S_END)) {
  4574. if ((strncmp(src->m_text,"PLASMA",6) == 0) && (gamemode == shareware))
  4575. src->m_flags = S_SKIP; // Don't show setting or item
  4576. if ((strncmp(src->m_text,"BFG",3) == 0) && (gamemode == shareware))
  4577. src->m_flags = S_SKIP; // Don't show setting or item
  4578. if ((strncmp(src->m_text,"SSG",3) == 0) && (gamemode != commercial))
  4579. src->m_flags = S_SKIP; // Don't show setting or item
  4580. src++;
  4581. }
  4582. }
  4583. //
  4584. // M_Init
  4585. //
  4586. void M_Init(void)
  4587. {
  4588. M_InitDefaults(); // killough 11/98
  4589. currentMenu = &MainDef;
  4590. menuactive = 0;
  4591. itemOn = currentMenu->lastOn;
  4592. whichSkull = 0;
  4593. skullAnimCounter = 10;
  4594. screenSize = screenblocks - 3;
  4595. messageToPrint = 0;
  4596. messageString = NULL;
  4597. messageLastMenuActive = menuactive;
  4598. quickSaveSlot = -1;
  4599. // Here we could catch other version dependencies,
  4600. // like HELP1/2, and four episodes.
  4601. switch(gamemode)
  4602. {
  4603. case commercial:
  4604. // This is used because DOOM 2 had only one HELP
  4605. // page. I use CREDIT as second page now, but
  4606. // kept this hack for educational purposes.
  4607. MainMenu[readthis] = MainMenu[quitdoom];
  4608. MainDef.numitems--;
  4609. MainDef.y += 8;
  4610. NewDef.prevMenu = &MainDef;
  4611. ReadDef1.routine = M_DrawReadThis1;
  4612. ReadDef1.x = 330;
  4613. ReadDef1.y = 165;
  4614. ReadMenu1[0].routine = M_FinishReadThis;
  4615. break;
  4616. case registered:
  4617. // Episode 2 and 3 are handled,
  4618. // branching to an ad screen.
  4619. // killough 2/21/98: Fix registered Doom help screen
  4620. // killough 10/98: moved to second screen, moved up to the top
  4621. ReadDef2.y = 15;
  4622. case shareware:
  4623. // We need to remove the fourth episode.
  4624. EpiDef.numitems--;
  4625. break;
  4626. case retail:
  4627. // We are fine.
  4628. default:
  4629. break;
  4630. }
  4631. M_InitHelpScreen(); // init the help screen // phares 4/08/98
  4632. M_InitExtendedHelp(); // init extended help screens // phares 3/30/98
  4633. M_ChangeDemoSmoothTurns();
  4634. }
  4635. //
  4636. // End of General Routines
  4637. //
  4638. /////////////////////////////////////////////////////////////////////////////