123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184 |
- /*
- * Copyright (c) 2003-onwards Shaven Puppy Ltd
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'Shaven Puppy' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package worm;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import net.puppygames.applet.Area;
- import net.puppygames.applet.Game;
- import net.puppygames.applet.GameInputStream;
- import net.puppygames.applet.GameOutputStream;
- import net.puppygames.applet.GameState;
- import net.puppygames.applet.MiniGame;
- import net.puppygames.applet.RoamingFile;
- import net.puppygames.applet.effects.LabelEffect;
- import net.puppygames.applet.screens.DialogScreen;
- import net.puppygames.steam.Steam;
- import net.puppygames.steam.SteamException;
- import org.lwjgl.input.Keyboard;
- import org.lwjgl.input.Mouse;
- import org.lwjgl.util.Color;
- import org.lwjgl.util.Point;
- import org.lwjgl.util.ReadableColor;
- import org.lwjgl.util.ReadablePoint;
- import org.lwjgl.util.ReadableRectangle;
- import org.lwjgl.util.Rectangle;
- import worm.buildings.BuildingFeature;
- import worm.effects.ArrowEffect;
- import worm.entities.Building;
- import worm.entities.Capacitor;
- import worm.entities.Factory;
- import worm.entities.Gidrah;
- import worm.entities.Saucer;
- import worm.entities.Smartbomb;
- import worm.entities.Turret;
- import worm.entities.Unit;
- import worm.features.GidrahFeature;
- import worm.features.HintFeature;
- import worm.features.LevelFeature;
- import worm.features.MedalFeature;
- import worm.features.RankFeature;
- import worm.features.ResearchFeature;
- import worm.features.StoryFeature;
- import worm.features.WorldFeature;
- import worm.generator.BaseMapGenerator;
- import worm.powerups.BatteryPowerupFeature;
- import worm.powerups.BezerkPowerupFeature;
- import worm.powerups.CapacitorPowerupFeature;
- import worm.powerups.CoolingTowerPowerupFeature;
- import worm.powerups.FreezePowerupFeature;
- import worm.powerups.MoneyPowerupFeature;
- import worm.powerups.PowerupFeature;
- import worm.powerups.ReactorPowerupFeature;
- import worm.powerups.RepairPowerupFeature;
- import worm.powerups.ResourcePowerupFeature;
- import worm.powerups.ScannerPowerupFeature;
- import worm.powerups.ShieldGeneratorPowerupFeature;
- import worm.powerups.ShieldPowerupFeature;
- import worm.powerups.SmartbombPowerupFeature;
- import worm.screens.CompleteGameScreen;
- import worm.screens.CompleteXmasScreen;
- import worm.screens.GameScreen;
- import worm.screens.IntermissionScreen;
- import worm.screens.MenuScreen;
- import worm.screens.NewWorldScreen;
- import worm.screens.ResearchScreen;
- import worm.screens.SelectEndlessLevelScreen;
- import worm.screens.SelectLevelScreen;
- import worm.screens.SelectSandboxLevelScreen;
- import worm.screens.SelectSurvivalLevelScreen;
- import worm.screens.SelectWorldScreen;
- import worm.screens.StoryScreen;
- import worm.screens.SurvivalMenuScreen;
- import worm.screens.XmasMenuScreen;
- import worm.tiles.Crystal;
- import worm.tiles.Exclude;
- import com.shavenpuppy.jglib.Resources;
- import com.shavenpuppy.jglib.interpolators.CosineInterpolator;
- import com.shavenpuppy.jglib.interpolators.LinearInterpolator;
- import com.shavenpuppy.jglib.interpolators.SineInterpolator;
- import com.shavenpuppy.jglib.resources.MappedColor;
- import com.shavenpuppy.jglib.resources.ResourceArray;
- import com.shavenpuppy.jglib.util.Util;
- /**
- * The entire game state during play
- */
- public class WormGameState extends GameState {
- private static final long serialVersionUID = 3L;
- private static final Rectangle TEMPBOUNDS = new Rectangle();
- private static final ArrayList<Entity> BUILD_COLLISIONS = new ArrayList<Entity>();
- public static final int GAME_MODE_CAMPAIGN = 0;
- public static final int GAME_MODE_ENDLESS = 1;
- public static final int GAME_MODE_SURVIVAL = 2;
- public static final int GAME_MODE_SANDBOX = 3;
- public static final int GAME_MODE_XMAS = 4;
- /** Mouse dragging speed */
- private static final float MOUSE_DRAG_SPEED = 2.0f;
- /** Absolute max map size in tiles */
- public static final int ABS_MAX_SIZE = 96;
- /** Absolute max map width in pixels */
- public static final int MAP_WIDTH = ABS_MAX_SIZE * MapRenderer.TILE_SIZE;
- /** Absolute max map height in pixels */
- public static final int MAP_HEIGHT = MAP_WIDTH;
- /** Map resolution - defines the grid size upon which we place buildings */
- public static final int MAP_RESOLUTION = MapRenderer.TILE_SIZE / 4;
- /** Maximum number of gidrahs allowed */
- public static final int MAX_GIDRAHS = 160;
- /** Number of levels in a world */
- public static final int LEVELS_IN_WORLD = 10;
- /** Number of worlds */
- public static final int NUM_WORLDS = 5;
- /** Number of levels */
- public static final int MAX_LEVELS = LEVELS_IN_WORLD * NUM_WORLDS;
- /** Duration in ticks that we wait after save is initiated */
- private static final int SAVE_DURATION = 45;
- /** End of level duration, in ticks */
- private static final int END_OF_LEVEL_DURATION = 30 * 60;
- /** Wait a few seconds delay, after a boss is killed */
- private static final int WAIT_A_FEW_SECONDS_DELAY = 5 * 60;
- /** Endgame duration, ticks */
- private static final int END_OF_GAME_DURATION = 420;
- /** After this interval (ticks), we warn about crystals that aren't being mined */
- private static final int UNMINED_WARNING_TIME = 600;
- /** After this interval (ticks) of nothing happening, we mention the fast forward button */
- private static final int INTERESTING_INTERVAL = 500;
- /** Right mouse button drag sensitivity */
- private static final int RMB_DRAG_SENSITIVITY = 3;
- /** Game configuration */
- private final GameConfiguration config;
- private static final ArrayList<Capacitor> TEMP_CAPACITORS = new ArrayList<Capacitor>();
- /*
- * Transient data
- */
- /** Save game stuff */
- private transient int saveTick;
- private transient boolean saving;
- /** Xmas reset */
- private transient boolean xmasReset;
- /**
- * Meta state - holds all the information that should be saved on a level-by-level basis, not the actual in-play state, in
- * a campaign game
- */
- public static class MetaState implements Serializable {
- private static final long serialVersionUID = 3L;
- private static final int MAX_RANDOM = 30;
- private static final int MAX_DEFAULT_RANDOM = 24;
- private static final int MAX_EXOTIC_RANDOM = 6;
- private static final int MAX_CRAPPY_RANDOM = 10;
- /** Game mode */
- private final int gameMode;
- /** A map of stats (Strings to Integers) */
- private final Map<String, Integer> stats = new HashMap<String, Integer>();
- /** Powerups: a Map of PowerupFeatures to Integers, which is the number of each of that sort of powerup the player has. Or null for 0. */
- private final Map<PowerupFeature, Integer> powerups = new HashMap<PowerupFeature, Integer>();
- /** Medals: a Map of MedalFeatures to Integers */
- private final Map<MedalFeature, Integer> medals = new HashMap<MedalFeature, Integer>();
- /** Total score for all medals */
- private int score;
- /** Current rank */
- private RankFeature rank;
- /** Which BuildingFeatures have been researched (Strings - from BuildingFeature.getID()) */
- private final HashSet<String> researched = new HashSet<String>();
- /** Money */
- private int money;
- /** Number of attempts at current level so far */
- private int attempts;
- /** Level index */
- private int level = 0;
- /** World */
- private WorldFeature world;
- /** Level */
- private LevelFeature levelFeature;
- /** Base difficulty, usually negative as player starts to lose */
- private float difficulty = 0.0f;
- /** Survival params */
- private SurvivalParams survivalParams;
- /** Sandbox params */
- private SandboxParams sandboxParams;
- /** Powerups shuffle */
- private ArrayList<Integer> shuffle;
- private ArrayList<Integer> crappyShuffle;
- private ArrayList<Integer> randomShuffle;
- private ArrayList<Integer> exoticShuffle;
- /** Resources */
- private Map<BuildingFeature, Integer> availableStock;
- public MetaState(int gameMode) {
- this.gameMode = gameMode;
- reset();
- }
- public void bonusMoney(int amount) {
- money += amount;
- }
- public int getAvailableStock(BuildingFeature bf) {
- if (availableStock == null) {
- availableStock = new HashMap<BuildingFeature, Integer>();
- }
- Integer ret = availableStock.get(bf);
- if (ret == null) {
- return 0;
- } else {
- return ret.intValue();
- }
- }
- public void addAvailableStock(BuildingFeature bf, int n) {
- int current = getAvailableStock(bf);
- if (current == -1) {
- // Hmm.
- assert false;
- return;
- }
- current = Math.min(bf.getMaxAvailable(), Math.max(0, current + n));
- availableStock.put(bf, new Integer(current));
- }
- void reset() {
- stats.clear();
- powerups.clear();
- medals.clear();
- researched.clear();
- if (availableStock == null) {
- availableStock = new HashMap<BuildingFeature, Integer>();
- } else {
- availableStock.clear();
- }
- switch (gameMode) {
- case GAME_MODE_SURVIVAL:
- if (survivalParams != null) {
- money = GameConfiguration.getInstance().getSurvivalInitialMoney()[survivalParams.getWorld().getIndex()];
- }
- break;
- case GAME_MODE_XMAS:
- money = GameConfiguration.getInstance().getXmasInitialMoney();
- break;
- default:
- money = GameConfiguration.getInstance().getNormalInitialMoney();
- break;
- }
- score = 0;
- rank = RankFeature.getRank(0);
- shuffle = new ArrayList<Integer>(MAX_RANDOM);
- randomShuffle = new ArrayList<Integer>(MAX_DEFAULT_RANDOM);
- crappyShuffle = new ArrayList<Integer>(MAX_CRAPPY_RANDOM);
- exoticShuffle = new ArrayList<Integer>(MAX_EXOTIC_RANDOM);
- }
- private int addStat(String stat, int n) {
- Integer current = stats.get(stat);
- if (current == null) {
- current = Integer.valueOf(n);
- } else {
- current = Integer.valueOf(current.intValue() + n);
- }
- stats.put(stat, current);
- return current.intValue();
- }
- private static String getPath(int level, int gameMode) {
- return Game.getPlayerDirectoryPrefix() + "metastate_" + level + "_"+gameMode+".ser";
- }
- public static MetaState load(int level, int gameMode) throws Exception {
- GameInputStream gis = null;
- ObjectInputStream ois = null;
- try {
- String path = getPath(level, gameMode);
- RoamingFile file = new RoamingFile(path);
- if (!file.exists()) {
- throw new FileNotFoundException("The save game file "+path+" was not found");
- }
- gis = new GameInputStream(path);
- ois = new ObjectInputStream(gis);
- MetaState ret = (MetaState) ois.readObject();
- Resources.dequeue();
- if (ret.shuffle == null || ret.exoticShuffle == null || ret.randomShuffle == null || ret.crappyShuffle == null) {
- ret.shuffle = new ArrayList<Integer>(MAX_RANDOM);
- ret.randomShuffle = new ArrayList<Integer>(MAX_DEFAULT_RANDOM);
- ret.crappyShuffle = new ArrayList<Integer>(MAX_CRAPPY_RANDOM);
- ret.exoticShuffle = new ArrayList<Integer>(MAX_EXOTIC_RANDOM);
- }
- if (ret.availableStock == null) {
- ret.availableStock = new HashMap<BuildingFeature, Integer>();
- }
- return ret;
- } finally {
- try {
- if (gis != null) {
- gis.close();
- }
- } catch (IOException e) {
- }
- }
- }
- public void save() throws Exception {
- GameOutputStream gos = null;
- ObjectOutputStream oos = null;
- try {
- gos = new GameOutputStream(getPath(level, gameMode));
- oos = new ObjectOutputStream(gos);
- oos.writeObject(this);
- oos.flush();
- gos.flush();
- } finally {
- try {
- gos.close();
- } catch (IOException e) {
- }
- }
- }
- public int getMoney() {
- return money;
- }
- public void bonusPowerup(PowerupFeature powerup, int amount) {
- Integer current = powerups.get(powerup);
- if (current == null) {
- current = Integer.valueOf(amount);
- } else {
- current = Integer.valueOf(current.intValue() + amount);
- }
- powerups.put(powerup, current);
- }
- private PowerupFeature getCrappyPowerup() {
- if (crappyShuffle.size() == 0) {
- for (int i = 0; i < MAX_CRAPPY_RANDOM; i ++) {
- crappyShuffle.add(new Integer(i));
- }
- Collections.shuffle(crappyShuffle);
- }
- Integer i = crappyShuffle.remove(crappyShuffle.size() - 1);
- switch (i.intValue()) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- return MoneyPowerupFeature.getInstance(50);
- default:
- return getPowerup();
- }
- }
- private PowerupFeature getRandomPowerup() {
- if (randomShuffle.size() == 0) {
- for (int i = 0; i < MAX_DEFAULT_RANDOM; i ++) {
- randomShuffle.add(new Integer(i));
- }
- Collections.shuffle(randomShuffle);
- }
- Integer i = randomShuffle.remove(randomShuffle.size() - 1);
- switch (i.intValue()) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- return MoneyPowerupFeature.getInstance(50);
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- return MoneyPowerupFeature.getInstance(100);
- case 12:
- case 13:
- case 14:
- case 15:
- return MoneyPowerupFeature.getInstance(250);
- case 16:
- case 17:
- case 18:
- return MoneyPowerupFeature.getInstance(500);
- case 19:
- case 20:
- case 21:
- return getPowerup();
- default:
- return getExoticPowerup();
- }
- }
- /**
- * @return an exotic powerup
- */
- private PowerupFeature getExoticPowerup() {
- if (gameMode == GAME_MODE_SURVIVAL || gameMode == GAME_MODE_XMAS || level < 4) {
- return getPowerup();
- }
- PowerupFeature ret = null;
- do {
- if (exoticShuffle.size() == 0) {
- for (int i = 0; i < MAX_EXOTIC_RANDOM; i ++) {
- exoticShuffle.add(new Integer(i));
- }
- Collections.shuffle(exoticShuffle);
- }
- Integer i = exoticShuffle.remove(exoticShuffle.size() - 1);
- WormGameState gameState = Worm.getGameState();
- switch (i.intValue()) {
- case 0:
- if (gameState.isResearched(ResearchFeature.BATTERY)) {
- ret = BatteryPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- case 1:
- if (gameState.isResearched(ResearchFeature.CAPACITOR)) {
- ret = CapacitorPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- case 2:
- if (gameState.isResearched(ResearchFeature.COOLINGTOWER)) {
- ret = CoolingTowerPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- case 3:
- if (gameState.isResearched(ResearchFeature.REACTOR)) {
- ret = ReactorPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- case 4:
- if (gameState.isResearched(ResearchFeature.SHIELDGENERATOR)) {
- ret = ShieldGeneratorPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- case 5:
- if (gameState.isResearched(ResearchFeature.SCANNER)) {
- ret = ScannerPowerupFeature.getInstance();
- } else {
- ret = getCrappyPowerup();
- }
- break;
- default:
- assert false;
- return null;
- }
- } while (!ret.isAvailable());
- return ret;
- }
- /**
- * @return a non-exotic powerup
- */
- private PowerupFeature getPowerup() {
- if (shuffle.size() == 0) {
- for (int i = 0; i < MAX_RANDOM; i ++) {
- shuffle.add(new Integer(i));
- }
- Collections.shuffle(shuffle);
- }
- Integer i = shuffle.remove(shuffle.size() - 1);
- WormGameState gameState = Worm.getGameState();
- switch (i.intValue()) {
- case 0:
- case 1:
- case 2:
- return BezerkPowerupFeature.getInstance();
- case 3:
- case 4:
- case 5:
- return RepairPowerupFeature.getInstance();
- case 6:
- case 7:
- case 8:
- return ShieldPowerupFeature.getInstance();
- case 9:
- case 10:
- case 11:
- return SmartbombPowerupFeature.getInstance();
- case 12:
- case 13:
- case 14:
- return FreezePowerupFeature.getInstance();
- case 15:
- case 16:
- case 17:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.MINES)) {
- return ResourcePowerupFeature.getInstance("mines.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 18:
- case 19:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.CLUSTERMINES)) {
- return ResourcePowerupFeature.getInstance("clustermines.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 20:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.BLASTMINES)) {
- return ResourcePowerupFeature.getInstance("blastmines.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 21:
- case 22:
- case 23:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.CONCRETE)) {
- return ResourcePowerupFeature.getInstance("concrete.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 24:
- case 25:
- case 26:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.STEEL)) {
- return ResourcePowerupFeature.getInstance("steel.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 27:
- case 28:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.TITANIUM)) {
- return ResourcePowerupFeature.getInstance("titanium.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- case 29:
- if ((gameState.getGameMode() == WormGameState.GAME_MODE_SURVIVAL || gameState.getGameMode() == WormGameState.GAME_MODE_XMAS) && gameState.isResearched(ResearchFeature.NANOMESH)) {
- return ResourcePowerupFeature.getInstance("nanomesh.powerup");
- } else {
- return getPowerup(); // Recurse
- }
- default:
- assert false;
- return null;
- }
- }
- }
- /*
- * Game state
- */
- /** Current metastate */
- private MetaState metaState;
- /** Current map */
- private GameMap map;
- /** Spawn points */
- private final ArrayList<SpawnPoint> spawnPoints = new ArrayList<SpawnPoint>();
- /** Debugging aid */
- private transient boolean forceDifficulty;
- /** Current total difficulty */
- private float currentDifficulty;
- /** Powerup difficulty */
- private float powerupDifficulty;
- /** Whether to begin the level */
- private boolean beginLevel;
- /** Money at start of level */
- private int startingMoney;
- /** Factories */
- private int factories, totalFactories;
- /** Warehouses */
- private int warehouses;
- /** Shield generators */
- private int shieldGenerators;
- /** Autoloaders */
- private int autoloaders;
- /** Spawners */
- private int spawners;
- /** Are we alive? */
- private boolean alive = true;
- /** Freeze tick */
- private int freezeTick;
- /** Shield tick */
- private int shieldTick;
- /** Capacitor boost */
- private int capacitorBoost;
- /** Cooling boost */
- private int coolingBoost;
- /** Battery boost */
- private int batteryBoost;
- /** Reactor boost */
- private int reactorBoost;
- /** Scanner boost */
- private int scannerBoost;
- /** Shield boost: extra hitpoints for all buildings */
- private int shieldBoost;
- /** Level duration */
- private int levelDuration;
- /** Aliens spawned */
- private int aliensSpawnedValue, aliensSpawnedAtLevelEnd;
- /** Aliens vanquished value */
- private int aliensVanquishedValue, aliensVanquishedSinceEndOfLevel;
- /** Last story index */
- private int currentStoryIndex;
- /** Something interesting happened this many ticks ago */
- private int somethingInterestingHappenedTick;
- /** Last hovered entity */
- private Entity lastHovered;
- /** Total value of buildings created on this level */
- private int valueOfBuiltBuildings;
- /** Number of buildings made this level */
- private int numberOfBuildingsMade;
- /** Total value of buildings destroyed by gidrahs on this level */
- private int valueOfDestroyedBuildings;
- /** Number of buildings destroyed this level */
- private int numberOfBuildingsDestroyed;
- /** Have any buildings been damaged on this level? (for Pristine medal) */
- private boolean anyDamaged;
- /** Number of crystal buildings */
- private int crystals, initialCrystals;
- /** The base */
- private Building base;
- /** Entities */
- private final ArrayList<Entity> entities = new ArrayList<Entity>();
- /** All the gidrahs currently on the level */
- private final ArrayList<Gidrah> gidrahs = new ArrayList<Gidrah>();
- /** All the bosses currently on the level */
- private final ArrayList<Gidrah> bosses = new ArrayList<Gidrah>();
- /** All the units currently on the level */
- private final ArrayList<Unit> units = new ArrayList<Unit>();
- /** All the buildings currently on the level */
- private final ArrayList<Building> buildings = new ArrayList<Building>();
- /** All the saucers currently on the level */
- private final ArrayList<Saucer> saucers = new ArrayList<Saucer>();
- /** Medals earned during play this level */
- private final Set<MedalFeature> medalsThisLevel = new HashSet<MedalFeature>();
- /** Armed capacitors */
- private final ArrayList<Capacitor> armedCapacitors = new ArrayList<Capacitor>();
- /** Event hint seq number */
- private int eventHintSeq;
- /** Unmined crystals warning */
- private int unminedTick;
- /** Game state interface */
- private final GameStateInterface gameStateInterface = new GameStateInterface() {
- private static final long serialVersionUID = 1L;
- @Override
- public void addToGidrahs(Gidrah gidrah) {
- gidrahs.add(gidrah);
- if (gidrah.getFeature().isBoss()) {
- bosses.add(gidrah);
- addStat(Stats.BOSSES_SPAWNED, 1);
- }
- if (gidrah.getFeature().isAngry()) {
- addStat(Stats.ANGRY_SPAWNED, 1);
- }
- if (gidrah.getFeature().isGidlet()) {
- addStat(Stats.GIDLETS_SPAWNED, 1);
- }
- aliensSpawnedValue += gidrah.getFeature().getValue();
- addStat(Stats.ALIENS_SPAWNED, 1);
- }
- @Override
- public void addToUnits(Unit unit) {
- units.add(unit);
- }
- @Override
- public void addToBuildings(Building building) {
- buildings.add(building);
- if (building.isCity()) {
- base = building;
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void addToSaucers(Saucer saucer) {
- saucers.add(saucer);
- onSomethingInterestingHappened();
- }
- @Override
- public void removeFromBuildings(Building building) {
- buildings.remove(building);
- onSomethingInterestingHappened();
- }
- @Override
- public void removeFromGidrahs(Gidrah gidrah) {
- gidrahs.remove(gidrah);
- aliensVanquishedValue += gidrah.getFeature().getValue();
- if (!isLevelActive()) {
- aliensVanquishedSinceEndOfLevel += gidrah.getFeature().getValue();
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void removeFromUnits(Unit unit) {
- units.remove(unit);
- }
- @Override
- public void removeFromSaucers(Saucer saucer) {
- saucers.remove(saucer);
- }
- @Override
- public void buffBatteries() {
- batteryBoost ++;
- onSomethingInterestingHappened();
- }
- @Override
- public void buffScanners() {
- scannerBoost ++;
- onSomethingInterestingHappened();
- }
- @Override
- public void buffCapacitors() {
- capacitorBoost ++;
- onSomethingInterestingHappened();
- }
- @Override
- public void buffCoolingTowers() {
- coolingBoost ++;
- onSomethingInterestingHappened();
- }
- @Override
- public void buffReactors() {
- reactorBoost ++;
- onSomethingInterestingHappened();
- }
- @Override
- public void buffShieldGenerators() {
- shieldBoost ++;
- for (Building building : buildings) {
- building.addShieldBoost();
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void repairFully() {
- for (Building building : buildings) {
- building.repairFully();
- }
- if (metaState.addStat(Stats.REPAIRS_USED, 1) == 5) {
- awardMedal(Medals.JIMLL_FIX_IT);
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void setSmartbombMode() {
- setBuilding(null);
- mode = Mode.MODE_SMARTBOMB;
- onSomethingInterestingHappened();
- }
- @Override
- public void freeze(int duration) {
- // Freeze all the gidrahs!
- freezeTick += duration;
- GameScreen.instance.onFreezeTimerIncreased(freezeTick);
- if (metaState.addStat(Stats.FREEZES_USED, 1) == 5) {
- awardMedal(Medals.TOILET_BREAK);
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void bezerk(int duration) {
- bezerkTick += duration;
- GameScreen.getInstance().onBezerkTimerIncreased(bezerkTick);
- // Bezerk turrets reload instantly
- for (Building building : buildings) {
- building.onBezerk();
- }
- if (metaState.addStat(Stats.BEZERKS_USED, 1) == 5) {
- awardMedal(Medals.SHORT_TEMPERED);
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void invulnerable(int duration) {
- shieldTick += duration;
- GameScreen.getInstance().onShieldTimerIncreased(shieldTick);
- if (metaState.addStat(Stats.SHIELDS_USED, 1) == 5) {
- awardMedal(Medals.BATFINK);
- }
- onSomethingInterestingHappened();
- }
- @Override
- public void addMoney(int delta) {
- WormGameState.this.addMoney(delta);
- onSomethingInterestingHappened();
- }
- @Override
- public int getAvailableStock(BuildingFeature bf) {
- return WormGameState.this.getAvailableStock(bf);
- }
- @Override
- public void addAvailableStock(BuildingFeature bf, int n) {
- WormGameState.this.addAvailableStock(bf, n);
- }
- };
- /** Ticks */
- private int tick, totalTicks, saucerTick, levelTick, bezerkTick, survivalSpawnPointTick, crystalTick;
- /** Next saucer at... */
- private int nextSaucer;
- /** Contains a shuffle bag of crystal sizes (Integers), valued between 1 and 3 inclusive */
- private final ArrayList<Integer> survivalCrystals = new ArrayList<Integer>();
- /** Survival mode: next boss at this tick */
- private int survivalNextBossTick;
- /** Survival mode: next crystal at this tick */
- private int survivalNextCrystalTick;
- /** Survival mode: next survival spawn point count increase at this tick */
- private int survivalNextSpawnPointTick;
- /** Survival mode: survival spawn point interval */
- private int survivalSpawnPointInterval;
- /** Number of survival spawnpoints that there should be */
- private int numSurvivalSpawnPoints;
- /** Survival mode gidrah unlock levels */
- private final int[] survivalGidrahUnlock = new int[] {1, 0, 0, 0};
- /** Survival mode gidrah unlock levels */
- private final int[] survivalGidrahUnlockNext = new int[] {0, 0, 0, 0};
- /** Survival mode gidrah kill counts */
- private final int[] survivalGidrahKills = new int[] {0, 0, 0, 0};
- /** Whether mouse button was down last tick */
- private transient boolean leftMouseWasDown, rightMouseWasDown;
- /** Wait for mouse button to be released */
- private transient boolean waitForMouse;
- /** Building we want to build */
- private transient BuildingFeature building;
- /** Build entity */
- private transient Building buildEntity;
- /** Things we've clicked on */
- private transient ArrayList<Entity> clicked;
- /** Back button runnable */
- private transient Runnable backButtonRunnable;
- /** RMB scroll */
- private transient boolean rmbScroll;
- /** Unmined crystals */
- private final ArrayList<Building> unminedCrystalList = new ArrayList<Building>();
- /** Game phase */
- private int phase;
- private static final int PHASE_NORMAL = 0;
- private static final int PHASE_END_OF_GAME = 1;
- private static final int PHASE_WAIT_FOR_GIDRAHS = 2;
- private static final int PHASE_WAIT_A_FEW_SECONDS = 3;
- /** Rush mode */
- private boolean rush;
- /** Whether we've expired the demo */
- private boolean demoExpired;
- /** Survival boss counter (earth, moon, mars, etc) */
- private int survivalBoss;
- /** Survival boss ticker */
- private int survivalBossTick;
- /** Input mode (see {@link Mode} */
- private int mode;
- /** Scroll origin */
- private transient int scrollOriginX, scrollOriginY;
- /** Are we in range of a capacitor? */
- private transient boolean capacitorRange;
- /** RMB drag sensor */
- private transient int rmbDragSensor;
- /** Hint map maps HintFeatures to Integers, which is the number of times that hint has been shown in sequence */
- private final Map<HintFeature, Integer> hintMap = new HashMap<HintFeature, Integer>();
- /** Stories for this level */
- private transient List<StoryFeature> currentStories;
- /** Survival init params */
- private SurvivalParams survivalParams;
- /** Sandbox init params */
- private SandboxParams sandboxParams;
- /** Suppress medals display on game screen */
- private boolean suppressMedals;
- /** Awesome awarded this level */
- private boolean awesome;
- /** Number of attempts */
- private transient int attempts;
- /**
- * Gidrah spawn point
- */
- private class SpawnPoint implements Serializable {
- private static final long serialVersionUID = 1L;
- int tileX, tileY, type, subType;
- final boolean edge;
- /** Gidrah generator tick */
- private int gidrahTick;
- /** Waiting for spawn point to clear */
- private int waitingToSpawn;
- /** Gidrah position indicator */
- private int gidrahsSpawned;
- /** Spawn boss */
- private GidrahFeature boss;
- /** Stop spawning */
- private boolean stop;
- /** More aliens please */
- private int moreAliens;
- /** Effect */
- private transient ArrowEffect arrowEffect;
- SpawnPoint(int tileX, int tileY, int type, boolean edge) {
- this.tileX = tileX;
- this.tileY = tileY;
- this.type = type;
- this.edge = edge;
- gidrahTick = Util.random(getInitialLevelDelay(map.getWidth(), map.getHeight()), getInitialLevelDelay(map.getWidth(), map.getHeight()) + 600);
- waitingToSpawn = 0;
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- chooseType();
- }
- reinit();
- }
- void spawnBoss(GidrahFeature boss) {
- this.boss = boss;
- waitingToSpawn = 0;
- }
- @Override
- public boolean equals(Object obj) {
- return obj != null && obj instanceof SpawnPoint && ((SpawnPoint) obj).tileX == tileX && ((SpawnPoint) obj).tileY == tileY && ((SpawnPoint) obj).type == type;
- }
- @Override
- public int hashCode() {
- return (tileX ^ tileY << 16) * (type + 1);
- }
- /**
- * Tick the spawnpoint. Returns true if still active
- * @return
- */
- boolean tick() {
- if (!base.isAlive()) {
- // No base?
- return !stop;
- }
- if (getGameMode() == GAME_MODE_XMAS) {
- if (levelTick % Xmas.BOSS_INTERVAL == 0 && levelTick > 0) {
- // Every 5 minutes spawn a boss
- type = 2;
- } else if (levelTick % Xmas.ANGRY_INTERVAL == 0 && levelTick > 0 && type == 0) {
- type = 1;
- }
- }
- if (gidrahs.size() >= MAX_GIDRAHS) {
- return !stop;
- }
- if (freezeTick > 0) {
- return !stop;
- }
- if (getGameMode() != GAME_MODE_SURVIVAL) {
- if (crystals == 0 && !isLevelActive()) {
- return !stop;
- }
- }
- if (waitingToSpawn > 0) {
- waitingToSpawn --;
- if (waitingToSpawn == 0) {
- spawnGidrah();
- }
- } else {
- if (stop) {
- return false;
- }
- if (boss != null) {
- spawnGidrah();
- stop = true;
- arrowEffect.remove();
- arrowEffect = null;
- } else if (--gidrahTick <= 0) {
- // Get next item
- gidrahsSpawned ++;
- // xmas mode: continuous stream
- if (getGameMode() == GAME_MODE_XMAS) {
- spawnGidrah();
- } else {
- if (gidrahsSpawned >= getWaveLength()) {
- // We've got to the end. Go into a very long delay and start again at the beginning
- gidrahTick = getLongGidrahDelay();
- gidrahsSpawned = 0;
- // In Survival we move the spawnpoint around, and choose a new alien to spawn
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- moveSpawnPoint();
- } else {
- moreAliens = Math.min(3, moreAliens + 1);
- }
- } else {
- spawnGidrah();
- }
- }
- }
- }
- return true;
- }
- void moveSpawnPoint() {
- int ox = 0, oy = 0;
- if (tileX == -1) {
- tileY += Util.random(-2, 2);
- ox = 1;
- oy = 0;
- } else if (tileX == getMap().getWidth()) {
- tileY += Util.random(-2, 2);
- ox = 1;
- oy = 0;
- } else if (tileY == -1) {
- tileX += Util.random(-2, -2);
- ox = 0;
- oy = 1;
- } else if (tileY == getMap().getHeight()) {
- tileX += Util.random(-2, -2);
- ox = 0;
- oy = -1;
- }
- for (int z = 0; z < GameMap.LAYERS; z ++) {
- Tile t = getMap().getTile(tileX + ox, tileY + oy, z);
- if (t == null || t.isImpassable() || t.isSolid()) {
- // Zap!
- stop = true;
- remove();
- return;
- }
- }
- arrowEffect.setSpawnLocation(tileX, tileY);
- // Choose a new type
- chooseType();
- }
- void chooseType() {
- assert getGameMode() == GAME_MODE_SURVIVAL;
- int maxType = 0;
- for (int i = survivalGidrahUnlock.length; -- i >= 0; ) {
- if (survivalGidrahUnlock[i] != 0) {
- maxType = i;
- break;
- }
- }
- type = Util.random(0, maxType);
- subType = Util.random(0, Math.min(getNumTypes(type) - 1, survivalGidrahUnlock[type] - 1));
- }
- int getNumTypes(int type) {
- assert getGameMode() == GAME_MODE_SURVIVAL;
- return Res.getSurvivalGidrahs(type).getNumResources();
- }
- int getWaveLength() {
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- return getLevelInWorld() / 3 + 10 + moreAliens - Math.min(9, type * 3);
- case GAME_MODE_ENDLESS:
- return metaState.level / LEVELS_IN_WORLD + 10 + moreAliens - Math.min(9, type * 3);
- case GAME_MODE_SURVIVAL:
- return config.getSurvivalWaveLength() - Math.max(0, type * 3 - Math.max(0, getLevelTick() - config.getSurvivalWaveLengthTimeOffset()) / config.getSurvivalWaveLengthTimeAdjust());
- case GAME_MODE_XMAS:
- assert false;
- return -1; // Constant stream
- case GAME_MODE_SANDBOX:
- return metaState.level / LEVELS_IN_WORLD + 10 + moreAliens - Math.min(9, type * 3);
- default:
- assert false : "Unknown game mode " + metaState.gameMode;
- return 1;
- }
- }
- void spawnGidrah() {
- if (map.isOccupied(tileX, tileY)) {
- if (metaState.gameMode == GAME_MODE_XMAS) {
- waitingToSpawn = 1;
- } else {
- waitingToSpawn = config.getSpawnDelay();
- }
- } else {
- waitingToSpawn = 0;
- if (boss != null) {
- boss.spawn(GameScreen.getInstance(), tileX, tileY, 0);
- boss = null;
- gidrahTick = Util.random(getInitialLevelDelay(map.getWidth(), map.getHeight()), getInitialLevelDelay(map.getWidth(), map.getHeight()) + 600);
- } else {
- GidrahFeature gf;
- if (getGameMode() == GAME_MODE_XMAS) {
- // Choose gidrah based on level duration so far
- float ratio = levelTick == getLevelDuration() ? 0.99999f : (float) levelTick / (float) getLevelDuration();
- int gidIndex = Util.random(0, (int) LinearInterpolator.instance.interpolate(0.0f, Res.getXmasGidrahs().getNumResources(), ratio));
- switch (type) {
- case 0: // Ordinary gid
- gf = (GidrahFeature) Res.getXmasGidrahs().getResource(gidIndex);
- break;
- case 1: // Angry gid
- gf = (GidrahFeature) Res.getXmasAngryGidrahs().getResource(gidIndex);
- type = 0;
- break;
- case 2: // Boss
- gf = Res.getXmasBoss(survivalBoss ++);
- doBossWarning(1);
- // Stop when last boss made
- if (survivalBoss == Xmas.MAX_BOSSES) {
- stop = true;
- }
- type = 0;
- break;
- default:
- assert false;
- return;
- }
- } else if ((getGameMode() == GAME_MODE_SURVIVAL || metaState.level > 2) && gidrahsSpawned == 1) {
- // Maybe an angry gidrah at the head of the column?
- if (Util.random() < getDifficulty()) {
- gf = getAngryGidrah(type, subType);
- } else {
- gf = getGidrah(type, subType);
- }
- } else {
- gf = getGidrah(type, subType);
- }
- gf.spawn(GameScreen.getInstance(), tileX, tileY, type);
- gidrahTick = 1;
- }
- }
- }
- int getLongGidrahDelay() {
- switch (getGameMode()) {
- case GAME_MODE_SURVIVAL:
- return config.getLongDelay() + (int) LinearInterpolator.instance.interpolate(config.getSpawnpointDelayAdjust() * 5.0f, 0.0f, getDifficulty());
- case GAME_MODE_XMAS:
- return 0; // No delay
- default:
- return getShortGidrahDelay() * 2;
- }
- }
- int getShortGidrahDelay() {
- return config.getLongDelay() + Math.max(0, spawnPoints.size() - metaState.level / LEVELS_IN_WORLD) * config.getSpawnpointDelayAdjust();
- }
- void reinit() {
- arrowEffect = new ArrowEffect(tileX, tileY);
- arrowEffect.spawn(GameScreen.getInstance());
- arrowEffect.setOffset(null);
- }
- void remove() {
- if (arrowEffect != null) {
- arrowEffect.remove();
- arrowEffect = null;
- }
- map.clearItem(tileX, tileY);
- stop = true;
- }
- }
- /**
- * C'tor
- */
- public WormGameState(int mode) {
- this.config = GameConfiguration.getInstance();
- this.metaState = new MetaState(mode);
- reset();
- }
- private GidrahFeature getAngryGidrah(int type, int subType) {
- assert getGameMode() != GAME_MODE_XMAS;
- switch (getGameMode()) {
- case GAME_MODE_SURVIVAL:
- return (GidrahFeature) Res.getSurvivalAngryGidrahs(type).getResource(subType);
- default:
- return getLevelFeature().getAngryGidrah(type);
- }
- }
- private GidrahFeature getGidrah(int type, int subType) {
- assert getGameMode() != GAME_MODE_XMAS;
- switch (getGameMode()) {
- case GAME_MODE_SURVIVAL:
- return (GidrahFeature) Res.getSurvivalGidrahs(type).getResource(subType);
- default:
- return getLevelFeature().getGidrah(type);
- }
- }
- /**
- * Repair all the buildings by one shield
- */
- public void repair() {
- for (Iterator<Building> i = buildings.iterator(); i.hasNext(); ) {
- i.next().repair();
- }
- }
- /**
- * Get the player's money
- * @return int
- */
- public int getMoney() {
- return metaState.money;
- }
- /**
- * Adjust the player's money
- * @param moneyDelta The amount of money to adjust the player's purse by
- */
- public void addMoney(int moneyDelta) {
- metaState.money += moneyDelta;
- if (metaState.money < 0) {
- metaState.money = 0;
- }
- }
- /**
- * Add an entity to the game
- * @param entity
- */
- public void addEntity(Entity entity) {
- entities.add(entity);
- // Now get the entity to add itself to the appropriate list
- entity.addToGameState(gameStateInterface);
- }
- /**
- * Add a powerup
- * @param powerup
- * @param doSound TODO
- */
- public void addPowerup(PowerupFeature powerup, boolean doSound) {
- Integer num = metaState.powerups.get(powerup);
- int n;
- if (num == null) {
- n = 1;
- } else {
- n = num.intValue() + 1;
- }
- metaState.powerups.put(powerup, new Integer(n));
- if (doSound && powerup != null) {
- Game.allocateSound(powerup.getCollectSound());
- }
- calcPowerupDifficulty();
- GameScreen.onPowerupsUpdated();
- }
- private void calcPowerupDifficulty() {
- powerupDifficulty = 0.0f;
- for (PowerupFeature pf : metaState.powerups.keySet()) {
- powerupDifficulty += pf.getDifficulty();
- }
- }
- /**
- * Remove a powerup
- * @param powerup
- */
- public void removePowerup(PowerupFeature powerup) {
- Integer num = metaState.powerups.get(powerup);
- int n;
- if (num == null) {
- assert false;
- return;
- } else {
- n = num.intValue() - 1;
- }
- if (n == 0) {
- metaState.powerups.remove(powerup);
- } else {
- metaState.powerups.put(powerup, new Integer(n));
- }
- calcPowerupDifficulty();
- GameScreen.onPowerupsUpdated();
- }
- /**
- * Return the number of powerups of this type the player has
- * @param powerup
- * @return int
- */
- public int getNumPowerups(PowerupFeature powerup) {
- Integer num = metaState.powerups.get(powerup);
- if (num == null) {
- return 0;
- } else {
- return num.intValue();
- }
- }
- /**
- * Use a powerup
- * @param powerup
- */
- public void usePowerup(PowerupFeature powerup) {
- if (getNumPowerups(powerup) == 0) {
- return;
- }
- removePowerup(powerup);
- Game.allocateSound(powerup.getCollectSound());
- powerup.activate(gameStateInterface);
- }
- /**
- * Remove an entity from the game
- * @param entity
- */
- public void removeEntity(Entity entity) {
- // We don't actually remove the entity from entities list here; that occurs
- // for us in checkCollisions().
- // Now get the entity to remove itself from the appropriate list
- entity.removeFromGameState(gameStateInterface);
- }
- /**
- * Cleanup
- */
- public void cleanup() {
- for (int i = 0; i < entities.size(); i ++) {
- Entity e = entities.get(i);
- if (e.isActive()) {
- e.remove();
- }
- }
- Entity.reset();
- System.gc();
- }
- /**
- * Adjust the number of factories in play
- * @param n
- */
- public void addFactories(int n) {
- factories += n;
- if (n > 0) {
- totalFactories += n;
- }
- beginLevel = true;
- assert factories >= 0;
- }
- public void addCrystals(int n) {
- crystals += n;
- if (crystals == 0 && getGameMode() != GAME_MODE_SURVIVAL && getGameMode() != GAME_MODE_XMAS) {
- // Mined all crystals before timer expires?
- if (levelTick < getLevelDuration() && beginLevel) {
- awardMedal(Medals.EFFICIENT);
- }
- }
- }
- public void addInitialCrystals(int n) {
- initialCrystals += n;
- }
- /**
- * @return the number of factories in play
- */
- public int getFactories() {
- return factories;
- }
- public int getAutoloaders() {
- return autoloaders;
- }
- public int getWarehouses() {
- return warehouses;
- }
- public void addWarehouses(int n) {
- warehouses += n;
- }
- public int getShieldGenerators() {
- return shieldGenerators;
- }
- public void addShieldGenerators(int n) {
- shieldGenerators += n;
- }
- public void addAutoloaders(int n) {
- autoloaders += n;
- }
- /**
- * Adjust the number of spawners in play
- * @param n
- */
- public void addSpawners(int n) {
- spawners += n;
- beginLevel = true;
- assert spawners >= 0;
- }
- /**
- * @return the number of spawners in play
- */
- public int getSpawners() {
- return spawners;
- }
- /**
- * @return Returns the tick.
- */
- public int getTick() {
- return tick;
- }
- /**
- * @return Returns the totalTicks.
- */
- public int getTotalTicks() {
- return totalTicks;
- }
- /**
- * Reset the total tick count
- */
- public void resetTotalTicks() {
- totalTicks = 0;
- }
- /**
- * Is the player still "alive"?
- * @return true if the player hasn't lost a base
- */
- public boolean isAlive() {
- return alive;
- }
- /**
- * Called when a base is destroyed or built
- */
- public void addBases(int n) {
- if (n == -1) {
- kill();
- }
- }
- /**
- * Are we playing the game?
- * @return true if we're in PHASE_NORMAL or WAIT_FOR_GIDRAHS
- */
- public boolean isPlaying() {
- return phase == PHASE_NORMAL || phase == PHASE_WAIT_FOR_GIDRAHS;
- }
- /**
- * @return true if we're in rush mode
- */
- public boolean isRushActive() {
- return rush;
- }
- /**
- * End the level
- */
- private void endLevel() {
- GameScreen.onEndLevel();
- // Cancel build mode
- setBuilding(null);
- // Shut down etc.
- shutdownFactories();
- if (metaState.level == 19 && !Game.isRegistered()) {
- expireDemo();
- } else {
- // And open the intermission screen
- suppressMedals = true;
- IntermissionScreen.show();
- }
- }
- public static int getDifficultyAdjust(int level, int gameMode) {
- return Worm.getExtraLevelData(Game.getPlayerSlot(), level, gameMode, "diff", 0);
- }
- public static void setDifficultyAdjust(int level, int gameMode, int diff) {
- Worm.setExtraLevelData(level, gameMode, "diff", diff);
- }
- /**
- * Checks for new medals at the end of the level. Right now, can create up to *9* medals, which will have to be listed on the
- * {@link IntermissionScreen}. Check what got created with {@link #getMedalsEarnedThisLevel()}, which could have a whole bunch
- * more medals in it!
- */
- public void checkForNewMedals() {
- if (base.isAlive() && base.getHitPoints() <= 4) {
- awardMedal(Medals.TAPE_AND_STRING);
- }
- if (metaState.gameMode == GAME_MODE_CAMPAIGN) {
- // Award various medals
- int diff = getDifficultyAdjust(metaState.level, GAME_MODE_CAMPAIGN);
- if (diff == 0) {
- // Gold!
- awardMedal(Medals.GOLD);
- } else if (diff == 1) {
- // Silver!
- awardMedal(Medals.SILVER);
- } else if (diff == 2) {
- // Bronze!
- awardMedal(Medals.BRONZE);
- }
- boolean good = false;
- if (getLevel() == 9) {
- good = true;
- awardMedal(Medals.EARTH_COMPLETE);
- for (int i = 0; i < 10; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- good = false;
- break;
- }
- }
- } else if (getLevel() == 19) {
- good = true;
- awardMedal(Medals.MOON_COMPLETE);
- for (int i = 10; i < 20; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- good = false;
- break;
- }
- }
- } else if (getLevel() == 29) {
- good = true;
- awardMedal(Medals.MARS_COMPLETE);
- for (int i = 20; i < 30; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- good = false;
- break;
- }
- }
- } else if (getLevel() == 39) {
- good = true;
- awardMedal(Medals.SATURN_COMPLETE);
- for (int i = 30; i < 40; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- good = false;
- break;
- }
- }
- } else if (getLevel() == 49) {
- good = true;
- awardMedal(Medals.TITAN_COMPLETE);
- for (int i = 40; i < 50; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- good = false;
- break;
- }
- }
- if (good) {
- boolean reallyGood = true;
- for (int i = 0; i < 50; i ++) {
- if (getDifficultyAdjust(i, metaState.gameMode) > 0) {
- reallyGood = false;
- break;
- }
- }
- if (reallyGood) {
- awardMedal(Medals.PERFECT_GAME);
- }
- }
- }
- if (good) {
- awardMedal(Medals.PERFECT_WORLD);
- }
- }
- if (!anyDamaged) {
- awardMedal(Medals.PRISTINE);
- } else if (valueOfDestroyedBuildings == 0) {
- awardMedal(Medals.CAREFUL);
- } else if ((float) numberOfBuildingsDestroyed / (float) numberOfBuildingsMade >= 0.9f) {
- awardMedal(Medals.SKIN_OF_YOUR_TEETH);
- }
- if (getMoney() - startingMoney >= 15000) {
- awardMedal(Medals.SHORT_ARMS_DEEP_POCKETS);
- } else if (getMoney() - startingMoney >= 10000) {
- awardMedal(Medals.TIGHT_FISTED);
- } else if (getMoney() - startingMoney >= 5000) {
- awardMedal(Medals.THRIFTY);
- }
- if (getMoney() >= 50000) {
- awardMedal(Medals.HOARDED_$50000);
- } else if (getMoney() >= 25000) {
- awardMedal(Medals.HOARDED_$25000);
- } else if (getMoney() >= 10000) {
- awardMedal(Medals.HOARDED_$10000);
- } else if (getMoney() >= 5000) {
- awardMedal(Medals.HOARDED_$5000);
- }
- }
- /**
- * Store the state of play at the end of a level so it's ready to be used by the next level
- */
- public void checkPoint() {
- metaState.level ++;
- if (Worm.getMaxLevel(metaState.gameMode) < metaState.level) {
- Worm.setMaxLevel(metaState.level, metaState.gameMode);
- }
- Worm.setExtraLevelData(metaState.level, metaState.gameMode, "money", metaState.money);
- int diff = getDifficultyAdjust(metaState.level, metaState.gameMode);
- if (diff > 0) {
- setDifficultyAdjust(metaState.level, metaState.gameMode, diff - 1);
- }
- try {
- metaState.save();
- } catch (Exception e) {
- e.printStackTrace(System.err);
- }
- // Just be sure...
- Game.flushPrefs();
- metaState.level --;
- }
- /**
- * End the game
- */
- private void endGame() {
- setBuilding(null);
- phase = PHASE_END_OF_GAME;
- tick = 0;
- }
- /**
- * Sell a building
- * @param building
- */
- public void sell(Building building) {
- building.destroy(true);
- SFX.sold();
- LabelEffect le = new LabelEffect(net.puppygames.applet.Res.getTinyFont(), "$"+building.getSalePrice(), ReadableColor.WHITE, new Color(255, 255, 100), 30, 10);
- le.setAcceleration(0.0f, -0.025f);
- le.setVelocity(0.0f, 1.0f);
- le.setLocation(building.getMapX() + building.getCollisionX(), building.getMapY() + building.getFeature().getBounds().getHeight());
- le.spawn(GameScreen.getInstance());
- addMoney(building.getSalePrice());
- Worm.getGameState().flagHint(Hints.DRAGSELL);
- if (building.isWorthAttacking()) {
- addStat(Stats.SOLD, 1);
- }
- addAvailableStock(building.getFeature(), 1);
- // If selling stuff when there are no gidrahs and level ended, there's no point...
- if (beginLevel && gidrahs.size() == 0) {
- flagHint(Hints.DONTSELL);
- }
- }
- /**
- * Get the level duration, in ticks
- * @return int
- */
- public int getLevelDuration() {
- return levelDuration;
- }
- private void calcLevelDuration(int w, int h) {
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- float min, max; // In seconds
- switch (getLevel() / LEVELS_IN_WORLD) {
- case 0: // Earth
- min = 30.0f;
- max = 90.0f;
- break;
- case 1: // Moon
- min = 90.0f;
- max = 150.0f;
- break;
- case 2: // Mars
- min = 150.0f;
- max = 210.0f;
- break;
- case 3: // Saturn
- min = 210.0f;
- max = 270.0f;
- break;
- case 4: // Titan
- min = 270.0f;
- max = 300.0f;
- break;
- default:
- assert false : "Bad world for campaign: "+metaState.level;
- min = max = 300.0f;
- }
- levelDuration = (int) LinearInterpolator.instance.interpolate(min, max, getLevelInWorld() / (LEVELS_IN_WORLD - 1.0f)) * 60 + getInitialLevelDelay(w, h); // *60 converts seconds to ticks
- return;
- case GAME_MODE_ENDLESS:
- levelDuration = getInitialLevelDelay(w, h) + getLevel() * 300 + 1800; // 5 seconds per level
- return;
- case GAME_MODE_SURVIVAL:
- case GAME_MODE_SANDBOX:
- levelDuration = -1;
- return;
- case GAME_MODE_XMAS:
- levelDuration = Xmas.DURATION;
- return;
- default:
- assert false : "Unknown game mode "+metaState.gameMode;
- return;
- }
- }
- /**
- * @return time in ticks to delay before starting enemy spawning
- */
- private int getInitialLevelDelay(int w, int h) {
- if (metaState.level < 4 && getGameMode() != GAME_MODE_SURVIVAL && getGameMode() != GAME_MODE_XMAS) {
- return 0;
- }
- return (int) (Math.sqrt(w * h) * config.getInitialLevelDelayFactor());
- }
- /**
- * Get the current level tick
- * @return int
- */
- public int getLevelTick() {
- return levelTick;
- }
- /**
- * Quantize a coordinate to the map resolution
- * @param coord
- * @return a quantized coordinate
- */
- public static float quantize(float coord) {
- return (float) ((int) coord / MAP_RESOLUTION) * MAP_RESOLUTION;
- }
- private void tickSurvivalBosses() {
- survivalBossTick ++;
- if (survivalBossTick > survivalNextBossTick) {
- survivalBossTick = 0;
- survivalNextBossTick += config.getSurvivalBossIntervalAdjust();
- createSurvivalBosses();
- }
- }
- /**
- * Ticks all the spawnpoints.
- * @return true if any spawnpoint is still active
- */
- private boolean tickSpawnPoints() {
- // Survival mode: occasionally create a new spawnpoint
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- survivalSpawnPointTick ++;
- if (survivalSpawnPointTick >= survivalNextSpawnPointTick) {
- survivalSpawnPointInterval += config.getSurvivalSpawnpointSpawnIntervalAdjust();
- survivalNextSpawnPointTick += survivalSpawnPointInterval;
- numSurvivalSpawnPoints = Math.min(config.getBaseMaxSurvivalSpawnpoints() + getMap().getWidth() / config.getSurvivalSpawnpointsPerMapSize(), numSurvivalSpawnPoints + 1);
- }
- while (spawnPoints.size() < numSurvivalSpawnPoints) {
- createSurvivalSpawnPoint();
- }
- }
- boolean active = false;
- for (int i = 0; i < spawnPoints.size(); ) {
- SpawnPoint sp = spawnPoints.get(i);
- boolean wasActive = sp.tick();
- active |= wasActive;
- if (!wasActive) {
- sp.remove();
- spawnPoints.remove(i);
- } else {
- i ++;
- }
- }
- return active;
- }
- /**
- * Is the mouse pointer in range of a capacitor?
- * @return boolean
- */
- public boolean inRangeOfCapacitor() {
- return capacitorRange;
- }
- /**
- * Check for clicking and set the mouse pointer to the right animation for whatever's going on
- */
- private void checkMouse() {
- if (GameScreen.getInstance().isBlocked()) {
- return;
- }
- if (GameScreen.isSomethingElseGrabbingMouse()) {
- return;
- }
- // Ignore mouse on active areas, unless grabbed
- int mouseX = GameScreen.getInstance().getMouseX();
- int mouseY = GameScreen.getInstance().getMouseY();
- List<Area> areasUnderMouse = GameScreen.getInstance().getAreasUnder(mouseX, mouseY);
- if (GameScreen.getInstance().getGrabbed() == null) {
- for (Area area : areasUnderMouse) {
- if (area.isFocusable()) {
- if (buildEntity != null) {
- buildEntity.setVisible(false);
- }
- Worm.setMouseAppearance(Res.getMousePointer());
- return;
- }
- }
- }
- if (buildEntity != null && !buildEntity.isVisible()) {
- buildEntity.setVisible(true);
- }
- float x = mouseX - GameScreen.getSpriteOffset().getX();
- float y = mouseY - GameScreen.getSpriteOffset().getY();
- int n = entities.size();
- Entity hovered = null;
- if (clicked == null) {
- clicked = new ArrayList<Entity>(8);
- } else {
- clicked.clear();
- }
- for (int i = 0; i < n; i ++) {
- Entity entity = entities.get(i);
- if (entity.isTouching(x, y)) {
- if (entity.isClickable()) {
- clicked.add(entity);
- hovered = entity;
- } else if (hovered == null && entity.isHoverable()) {
- hovered = entity;
- }
- }
- }
- // Check range of capacitors
- capacitorRange = false;
- TEMP_CAPACITORS.clear();
- for (int i = 0; i < buildings.size(); i ++) {
- Building b = buildings.get(i);
- if (b.isAlive() && b instanceof Capacitor) {
- Capacitor capacitor = (Capacitor) b;
- if (b.getDistanceTo(x, y) <= capacitor.getZapRadius()) {
- capacitorRange = true;
- TEMP_CAPACITORS.add(capacitor);
- }
- }
- }
- if (mode == Mode.MODE_BUILD) {
- buildEntity.setLocation(quantize(x - building.getBounds().getX() - building.getBounds().getWidth() / 2 + MAP_RESOLUTION / 2), quantize(y - building.getBounds().getY() - building.getBounds().getHeight() / 2 + MAP_RESOLUTION / 2));
- }
- boolean auxDown = false;
- int count = Mouse.getButtonCount();
- for (int i = 2; i < count; i ++) {
- if (Mouse.isButtonDown(i)) {
- auxDown = true;
- break;
- }
- }
- if (Mouse.isButtonDown(0)) {
- if (waitForMouse) {
- return;
- }
- GameScreen.onMapGrabbedMouse(true);
- switch (mode) {
- case Mode.MODE_SELL:
- case Mode.MODE_NORMAL:
- case Mode.MODE_BUILD:
- case Mode.MODE_DRAG:
- // Left mouse down in Normal mode. If we're over something, we click on it unless in "no click" mode. If we're not over something, and in capacitor range,
- // we enter zap mode. If we're outside capacitor range, we set "no click" mode.
- if (clicked.size() > 0) {
- if (leftMouseWasDown) {
- // But we're in "no click" mode...
- return;
- }
- // Ok, enter no click mode
- if (mode != Mode.MODE_DRAG) {
- leftMouseWasDown = true;
- }
- // Hovering over something. Pick the first one and let that decide what mouse pointer to use.
- Worm.setMouseAppearance(clicked.get(0).getMousePointer(true));
- boolean fire = false, maybeSelect = false;
- for (Iterator<Entity> i = clicked.iterator(); i.hasNext(); ) {
- Entity clickable = i.next();
- switch (clickable.onClicked(mode)) {
- case ClickAction.IGNORE:
- maybeSelect = true;
- continue;
- case ClickAction.DRAG:
- // Allow dragging over factories & turrets. Unless in build mode.
- if (mode == Mode.MODE_BUILD) {
- waitForMouse = true;
- leftMouseWasDown = true;
- } else {
- mode = Mode.MODE_DRAG;
- leftMouseWasDown = false;
- }
- return;
- case ClickAction.CONSUME:
- if (mode == Mode.MODE_SELL) {
- // Allow drag
- leftMouseWasDown = false;
- waitForMouse = false;
- } else {
- waitForMouse = true;
- leftMouseWasDown = true;
- }
- return;
- case ClickAction.FIRE:
- if (mode == Mode.MODE_NORMAL) {
- fire = true;
- } else {
- // Build or drag mode; don't zap
- }
- break;
- }
- }
- if (!fire && mode == Mode.MODE_NORMAL) {
- if (maybeSelect) {
- mode = Mode.MODE_SCROLL;
- Worm.setMouseAppearance(Res.getMousePointerGrab());
- scrollOriginX = mouseX;
- scrollOriginY = mouseY;
- }
- return;
- }
- } else {
- if (mode == Mode.MODE_DRAG) {
- Worm.setMouseAppearance(Res.getMousePointer());
- }
- }
- if (mode == Mode.MODE_DRAG || mode == Mode.MODE_SELL || mode == Mode.MODE_SCROLL || mode == Mode.MODE_SELECT) {
- return;
- }
- if (mode == Mode.MODE_BUILD) {
- build();
- break;
- }
- if (!capacitorRange) {
- leftMouseWasDown = true;
- Worm.setMouseAppearance(Res.getMousePointer());
- if (mode == Mode.MODE_NORMAL) {
- // Go into scroll mode
- mode = Mode.MODE_SCROLL;
- scrollOriginX = mouseX;
- scrollOriginY = mouseY;
- leftMouseWasDown = true;
- Worm.setMouseAppearance(Res.getMousePointerGrab());
- }
- return;
- } else {
- leftMouseWasDown = true;
- mode = Mode.MODE_ZAP;
- armedCapacitors.clear();
- armedCapacitors.addAll(TEMP_CAPACITORS);
- }
- // Intentional fall-through
- case Mode.MODE_ZAP:
- // LMB down in ZAP mode. If we are inside capacitor range,
- // fire. Otherwise do nothing.
- for (int i = 0; i < armedCapacitors.size(); i ++) {
- Capacitor capacitor = armedCapacitors.get(i);
- if (capacitor.isAlive()) {
- capacitor.zap(x, y);
- }
- }
- if (armedCapacitors.size() == 0) {
- mode = Mode.MODE_NORMAL;
- }
- if (clicked.size() > 0) {
- Worm.setMouseAppearance(clicked.get(0).getMousePointer(true));
- } else if (isBezerk()) {
- Worm.setMouseAppearance(capacitorRange ? Res.getMousePointerBezerkOffTarget() : Res.getMousePointerBezerkOutOfRange());
- } else {
- Worm.setMouseAppearance(capacitorRange ? Res.getMousePointerOffTarget() : Res.getMousePointerOutOfRange());
- }
- break;
- case Mode.MODE_SMARTBOMB:
- // Boooooooooom!
- Smartbomb bomb = new Smartbomb(x, y);
- bomb.spawn(GameScreen.getInstance());
- mode = Mode.MODE_NORMAL;
- Worm.setMouseAppearance(Res.getMousePointerOffTarget()); // That'll probably change immediately next frame
- waitForMouse = true;
- if (metaState.addStat(Stats.SMARTBOMBS_USED, 1) == 5) {
- awardMedal(Medals.THE_ONLY_WAY_TO_BE_SURE);
- }
- break;
- case Mode.MODE_SCROLL:
- // Scroll the screen around under the mouse
- int dx = scrollOriginX - mouseX;
- int dy = scrollOriginY - mouseY;
- scrollOriginX = mouseX;
- scrollOriginY = mouseY;
- GameScreen.getInstance().scroll(dx * MOUSE_DRAG_SPEED, dy * MOUSE_DRAG_SPEED);
- break;
- case Mode.MODE_SELECT:
- // Do nothing
- return;
- default:
- assert false;
- }
- } else if (auxDown) {
- // Sell!
- GameScreen.onMapGrabbedMouse(true);
- for (Iterator<Entity> i = clicked.iterator(); i.hasNext(); ) {
- Entity entity = i.next();
- if (entity instanceof Building) {
- Building building = (Building) entity;
- if (building.canSell()) {
- sell(building);
- }
- }
- }
- } else {
- GameScreen.onMapGrabbedMouse(false);
- boolean rmbDown = Mouse.getButtonCount() > 1 && Mouse.isButtonDown(1) || Game.wasKeyPressed(Keyboard.KEY_ESCAPE);
- if (rmbDown) {
- if (waitForMouse) {
- return;
- }
- if (!rightMouseWasDown) {
- scrollOriginX = mouseX;
- scrollOriginY = mouseY;
- rmbDragSensor = 0;
- }
- leftMouseWasDown = false;
- rightMouseWasDown = true;
- int dx = scrollOriginX - mouseX;
- int dy = scrollOriginY - mouseY;
- scrollOriginX = mouseX;
- scrollOriginY = mouseY;
- if (dx != 0 || dy != 0) {
- rmbDragSensor ++;
- if (rmbDragSensor > RMB_DRAG_SENSITIVITY) {
- GameScreen.getInstance().scroll(dx * MOUSE_DRAG_SPEED, dy * MOUSE_DRAG_SPEED);
- rmbScroll = true;
- Worm.setMouseAppearance(Res.getMousePointerGrab());
- }
- }
- } else {
- if (rightMouseWasDown && !rmbScroll) {
- // It was a RMB click. Cancel building / selling / blowing stuff up. Or pick up whatever building is under the mouse to build.
- switch (mode) {
- case Mode.MODE_BUILD:
- setBuilding(null);
- rightMouseWasDown = false;
- return;
- case Mode.MODE_SELL:
- setSellMode(false);
- rightMouseWasDown = false;
- return;
- case Mode.MODE_DRAG:
- case Mode.MODE_NORMAL:
- case Mode.MODE_SELECT:
- case Mode.MODE_ZAP:
- for (Iterator<Entity> i = clicked.iterator(); i.hasNext(); ) {
- Entity clickable = i.next();
- if (clickable instanceof Building) {
- BuildingFeature bf = ((Building) clickable).getFeature();
- if (bf.isAvailable()) {
- clickable.onLeave(mode);
- lastHovered = null;
- setBuilding(bf);
- rightMouseWasDown = false;
- return;
- }
- }
- }
- break;
- case Mode.MODE_SMARTBOMB:
- // Cancel the smartbomb and return it to the stores
- addPowerup(SmartbombPowerupFeature.getInstance(), false);
- mode = Mode.MODE_NORMAL;
- rightMouseWasDown = false;
- return;
- case Mode.MODE_SCROLL:
- break;
- default:
- assert false;
- }
- }
- rmbScroll = false;
- rightMouseWasDown = false;
- leftMouseWasDown = false;
- waitForMouse = false;
- if (mode == Mode.MODE_BUILD) {
- if (canBuild(false)) {
- Worm.setMouseAppearance(Res.getMousePointer());
- } else {
- Worm.setMouseAppearance(Res.getMousePointerCantBuild());
- }
- } else if (hovered != null) {
- Worm.setMouseAppearance(hovered.getMousePointer(false));
- if (lastHovered != hovered) {
- if (lastHovered != null) {
- lastHovered.onLeave(mode);
- }
- lastHovered = hovered;
- hovered.onHovered(mode);
- }
- } else {
- if (lastHovered != null) {
- lastHovered.onLeave(mode);
- lastHovered = null;
- }
- if (mode == Mode.MODE_SMARTBOMB) {
- Worm.setMouseAppearance(Res.getMousePointerSmartbomb());
- } else if (mode == Mode.MODE_SELL) {
- Worm.setMouseAppearance(Res.getMousePointerSellOff());
- } else if (isBezerk()) {
- Worm.setMouseAppearance(capacitorRange ? Res.getMousePointerBezerkOffTarget() : Res.getMousePointerBezerkOutOfRange());
- } else {
- Worm.setMouseAppearance(capacitorRange ? Res.getMousePointerOffTarget() : Res.getMousePointerOutOfRange());
- }
- }
- if (mode == Mode.MODE_ZAP || mode == Mode.MODE_DRAG || mode == Mode.MODE_SCROLL || mode == Mode.MODE_SELECT) {
- mode = Mode.MODE_NORMAL;
- }
- }
- }
- }
- /**
- * Can the build entity be drawn where it is?
- * @param doingBuild If we're actually attempting to build
- * @return true if we can build here
- */
- private boolean canBuild(boolean doingBuild) {
- // Can we build?
- if (!buildEntity.canBuild()) {
- return false;
- }
- // Don't allow us to overlap with any solid entities
- buildEntity.getBounds(TEMPBOUNDS);
- // Ensure no part of the building is on a tile that can't be built upon or off the map
- if (TEMPBOUNDS.getX() < 0 || TEMPBOUNDS.getY() < 0 || TEMPBOUNDS.getX() + TEMPBOUNDS.getWidth() >= map.getWidth() * MapRenderer.TILE_SIZE || TEMPBOUNDS.getY() + TEMPBOUNDS.getHeight() >= map.getHeight() * MapRenderer.TILE_SIZE) {
- return false;
- }
- for (int y = TEMPBOUNDS.getY() / MapRenderer.TILE_SIZE; y <= (TEMPBOUNDS.getY() + TEMPBOUNDS.getHeight() - 1) / MapRenderer.TILE_SIZE; y ++) {
- for (int x = TEMPBOUNDS.getX() / MapRenderer.TILE_SIZE; x <= (TEMPBOUNDS.getX() + TEMPBOUNDS.getWidth() - 1) / MapRenderer.TILE_SIZE; x ++) {
- for (int z = 0; z < GameMap.LAYERS; z ++) {
- Tile tile = map.getTile(x, y, z);
- if (tile != null && (tile.isSolid() || tile.isImpassable())) {
- return false;
- }
- }
- }
- }
- Entity.getCollisions(TEMPBOUNDS, BUILD_COLLISIONS);
- int n = BUILD_COLLISIONS.size();
- for (int i = 0; i < n; i ++) {
- Entity entity = BUILD_COLLISIONS.get(i);
- if (entity.isActive() && entity.canCollide() && entity.isTouching(buildEntity) && !buildEntity.canBuildOnTopOf(entity)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Build a building at the specified location.
- * @param x
- * @param y
- */
- private void build() {
- // Make all buildings paintable
- //waitForMouse = !building.isPaintable();
- if (!canBuild(true)) {
- return;
- }
- // Unfortunately need to do these nice cheap checks after canBuild check, to prevent double labels being drawn
- if (!isBuildingAvailable()) {
- SFX.insufficientFunds();
- waitForMouse = true;
- LabelEffect le = new LabelEffect(net.puppygames.applet.Res.getTinyFont(), Game.getMessage("ultraworm.wormgamestate.no_longer_available"), ReadableColor.WHITE, ReadableColor.CYAN, 120, 60);
- le.setAcceleration(0.0f, -0.003125f);
- le.setVelocity(0.0f, 0.5f);
- le.setLocation(buildEntity.getMapX() + buildEntity.getCollisionX(), buildEntity.getMapY() + buildEntity.getFeature().getBounds().getHeight());
- le.spawn(GameScreen.getInstance());
- setBuilding(null);
- waitForMouse = true;
- GameScreen.getInstance().enableBuildings();
- return;
- }
- int cost = building.getShopValue();
- if (getMoney() < cost) {
- SFX.insufficientFunds();
- waitForMouse = true;
- LabelEffect le = new LabelEffect(net.puppygames.applet.Res.getTinyFont(), Game.getMessage("ultraworm.wormgamestate.insufficient_funds")+" $"+(cost - getMoney()), ReadableColor.WHITE, ReadableColor.CYAN, 30, 10);
- le.setAcceleration(0.0f, -0.025f);
- le.setVelocity(0.0f, 1.0f);
- le.setLocation(buildEntity.getMapX() + buildEntity.getCollisionX(), buildEntity.getMapY() + buildEntity.getFeature().getBounds().getHeight());
- le.spawn(GameScreen.getInstance());
- waitForMouse = true;
- return;
- }
- // Demolish any entities we're building on top of
- int damage = 0;
- ArrayList<Entity> ents = new ArrayList<Entity>(entities);
- for (Iterator<Entity> i = ents.iterator(); i.hasNext(); ) {
- Entity entity = i.next();
- if (entity != buildEntity && entity.canBeCrushed() && entity.isTouching(buildEntity) && buildEntity.canBuildOnTopOf(entity)) {
- damage += entity.crush();
- }
- }
- // Create the building
- Building b = building.build((int) buildEntity.getMapX(), (int) buildEntity.getMapY());
- if (damage > 0) {
- b.damage(damage);
- }
- // Record the cost
- b.setCost(cost);
- // Pay the price
- addMoney(-cost);
- if (!(b.isBarricade() || b.isMineField())) {
- valueOfBuiltBuildings += cost;
- numberOfBuildingsMade ++;
- addStat(Stats.BUILDINGS_BUILT, 1);
- addStat(Stats.VALUE_OF_BUILDINGS_BUILT, cost);
- }
- LabelEffect le = new LabelEffect(net.puppygames.applet.Res.getTinyFont(), "$"+cost, ReadableColor.WHITE, ReadableColor.CYAN, 30, 10);
- le.setAcceleration(0.0f, -0.025f);
- le.setVelocity(0.0f, 1.0f);
- le.setLocation(buildEntity.getMapX() + buildEntity.getCollisionX(), buildEntity.getMapY() + buildEntity.getFeature().getBounds().getHeight());
- le.spawn(GameScreen.getInstance());
- Worm.getGameState().flagHint(Hints.DRAGBUILD);
- SFX.build();
- if (building.getNumAvailable() != 0) {
- GameScreen.getInstance().enableBuildings();
- }
- }
- /**
- * Puts us in Build Mode and sets the building that we wish to build, or cancels build mode if building is null
- * @param building
- */
- public void setBuilding(BuildingFeature building) {
- if (buildEntity != null) {
- buildEntity.remove();
- buildEntity = null;
- }
- if (building == null) {
- // Leave "build mode"
- mode = Mode.MODE_NORMAL;
- this.building = null;
- } else {
- if (mode == Mode.MODE_SMARTBOMB) {
- // Return the active smartbomb to the stash
- addPowerup(SmartbombPowerupFeature.getInstance(), false);
- }
- // Go into "build mode"
- mode = Mode.MODE_BUILD;
- this.building = building;
- // Create the build entity
- float x = quantize(GameScreen.getInstance().getMouseX() - GameScreen.getSpriteOffset().getX()), y = quantize(GameScreen.getInstance().getMouseY() - GameScreen.getSpriteOffset().getY());
- buildEntity = building.ghost(quantize(x - building.getBounds().getX() - building.getBounds().getWidth() / 2 + MAP_RESOLUTION / 2), quantize(y - building.getBounds().getY() - building.getBounds().getHeight() / 2 + MAP_RESOLUTION / 2));
- }
- waitForMouse = true;
- }
- public void setSellMode(boolean sellMode) {
- if (sellMode) {
- if (mode == Mode.MODE_SMARTBOMB) {
- // Cancel the smartbomb and return it to the stores
- addPowerup(SmartbombPowerupFeature.getInstance(), true);
- } else if (mode == Mode.MODE_BUILD) {
- setBuilding(null);
- }
- mode = Mode.MODE_SELL;
- } else {
- mode = building == null ? Mode.MODE_NORMAL : Mode.MODE_BUILD;
- }
- }
- public boolean isSelling() {
- return mode == Mode.MODE_SELL;
- }
- private void tickEndOfGame() {
- if (tick == END_OF_GAME_DURATION) {
- // Game over! This puts up teh Game Over dialog. Or goes to the title screen if we've expired the demo.
- if (demoExpired) {
- MiniGame.endGame();
- } else {
- MiniGame.gameOver();
- }
- }
- }
- /**
- * Expire the demo
- */
- private void expireDemo() {
- if (demoExpired) {
- return;
- }
- String msg =
- getGameMode() == GAME_MODE_CAMPAIGN
- ? Game.getMessage("ultraworm.wormgamestate.completed_campaign_demo")
- : Game.getMessage("ultraworm.wormgamestate.completed_endless_demo");
- Res.getResearchNagDialog().doModal("): DEMO EXPIRED :(", msg, new Runnable() {
- @Override
- public void run() {
- if (Res.getResearchNagDialog().getOption() == DialogScreen.OK_OPTION) {
- MiniGame.buy(true);
- } else {
- LabelEffect nagEffect = new LabelEffect(net.puppygames.applet.Res.getBigFont(), "): ): "+Game.getMessage("ultraworm.wormgamestate.demo_expired")+" :( :(", ReadableColor.YELLOW, ReadableColor.RED, 160, 240);
- nagEffect.setLocation(Game.getWidth() / 2, Game.getHeight() / 2 + 32);
- nagEffect.setVisible(true);
- nagEffect.spawn(GameScreen.getInstance());
- nagEffect.setOffset(null);
- Game.getLocalPreferences().putBoolean("showregister", true);
- phase = PHASE_END_OF_GAME;
- tick = 0;
- demoExpired = true;
- }
- }
- });
- }
- /**
- * @return true if player is using bezerk weapon
- */
- public boolean isBezerk() {
- return bezerkTick > 0;
- }
- /**
- * @return true if we've got a smartbomb loaded
- */
- public boolean isSmartbombMode() {
- return mode == Mode.MODE_SMARTBOMB;
- }
- public void handleESC() {
- if (isBuilding()) {
- setBuilding(null);
- } else if (isSelling()) {
- setSellMode(false);
- } else if (!saving && !GameScreen.getInstance().isBlocked()) {
- // Open ingame menu
- switch (getGameMode()) {
- case GAME_MODE_SURVIVAL:
- SurvivalMenuScreen.show(SurvivalMenuScreen.MENU_GAME_MODE);
- break;
- case GAME_MODE_XMAS:
- XmasMenuScreen.show(SurvivalMenuScreen.MENU_GAME_MODE);
- break;
- default:
- MenuScreen.show(MenuScreen.MENU_GAME_MODE);
- break;
- }
- }
- }
- /**
- * Tick, called every frame that the game is playing
- */
- public void tick() {
- // // Check for escape to save the game and quit, or cancel building
- // if (Game.wasKeyPressed(Keyboard.KEY_ESCAPE)) {
- // }
- if (saving && isAlive()) {
- saveTick ++;
- if (saveTick >= SAVE_DURATION) {
- MiniGame.saveGame();
- return;
- }
- }
- // Do colours & animation syncs
- LevelFeature lf = getLevelFeature();
- if (lf == null) {
- return;
- }
- getLevelFeature().getColors().tick();
- // If the shops open do nothing else
- if (GameScreen.getInstance().isBlocked() || GameScreen.getInstance().isShowingPausedHint()) {
- return;
- }
- tick ++;
- totalTicks ++;
- calcCurrentDifficulty();
- // Tick all entities, cull dead ones
- tickEntities();
- if (freezeTick > 0) {
- freezeTick --;
- }
- if (bezerkTick > 0) {
- bezerkTick --;
- }
- if (shieldTick > 0) {
- shieldTick --;
- }
- if (isAlive()) {
- checkMouse();
- }
- if (Game.DEBUG) {
- if (Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
- try {
- Thread.sleep(20);
- } catch (Exception e) {
- }
- }
- if (Game.wasKeyPressed(Keyboard.KEY_M)) {
- metaState.money = Util.random(1, 100) * 100;
- // addMoney(10000);
- }
- if (Game.wasKeyPressed(Keyboard.KEY_R)) {
- Map<String, ResearchFeature> research = ResearchFeature.getResearch();
- for (String id : research.keySet()) {
- setResearched(id);
- }
- GameScreen.getInstance().enableBuildings();
- for (PowerupFeature pf : PowerupFeature.getPowerups()) {
- addPowerup(pf, false);
- }
- for (Iterator<BuildingFeature> i = BuildingFeature.getBuildings().iterator(); i.hasNext(); ) {
- BuildingFeature bf = i.next();
- if (bf.isAvailable()) {
- int num = bf.getNumAvailable();
- if (num > 0) {
- addAvailableStock(bf, num);
- }
- }
- }
- // chaz hack! powerup topup for testing
- //for (int i = 0; i < 5; i ++) {
- // addPowerup(PowerupFeature.getPowerup());
- //}
- }
- if (Game.wasKeyPressed(Keyboard.KEY_PERIOD)) {
- Saucer saucer = new Saucer();
- saucer.spawn(GameScreen.getInstance());
- }
- // if (Worm.wasKeyPressed(Keyboard.KEY_S)) {
- // gameStateInterface.invulnerable(200);
- // }
- if (Game.wasKeyPressed(Keyboard.KEY_L)) {
- endLevel();
- return;
- }
- if (Game.wasKeyPressed(Keyboard.KEY_C)) {
- CompleteGameScreen.show();
- return;
- }
- if (Game.wasKeyPressed(Keyboard.KEY_X)) {
- CompleteXmasScreen.show();
- return;
- }
- }
- switch (phase) {
- case PHASE_NORMAL:
- tickNormal();
- break;
- case PHASE_WAIT_FOR_GIDRAHS:
- tickWaitForGidrahs();
- break;
- case PHASE_END_OF_GAME:
- tickEndOfGame();
- break;
- case PHASE_WAIT_A_FEW_SECONDS:
- tickWaitAFewSeconds();
- break;
- default:
- assert false;
- }
- Entity.checkCollisions();
- // Now cull inactive entities
- for (int i = 0; i < entities.size(); ) {
- Entity src = entities.get(i);
- if (!src.isActive()) {
- entities.remove(i);
- } else {
- i ++;
- }
- }
- updateEntities();
- }
- /**
- * Clears the collision quadtree and then ticks each entity in turn, placing it back in the quadtree once it has
- * been ticked.
- */
- private void tickEntities() {
- Unit.resetTotalThinkTime();
- Gidrah.resetTotalThinkTime();
- for (int i = 0; i < entities.size(); ) {
- Entity e = entities.get(i);
- if (e.isActive()) {
- e.tick();
- }
- if (e.isActive()) {
- i ++;
- } else {
- entities.remove(i);
- }
- }
- }
- /**
- * Update all the entities
- */
- private void updateEntities() {
- for (int i = 0; i < entities.size(); i ++ ) {
- Entity entity = entities.get(i);
- try {
- entity.update();
- } catch (Exception ex) {
- System.err.println("Error updating entity "+entity);
- ex.printStackTrace(System.err);
- entity.remove();
- }
- }
- }
- /**
- * Normal gameplay: make the gidrahs spawn, and the occasional saucer.
- */
- private void tickNormal() {
- // Dead? Game over!
- if (!isAlive()) {
- endGame();
- return;
- }
- if (Game.DEBUG) {
- if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD1)) {
- forceDifficulty = true;
- currentDifficulty = 0.0f;
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD2)) {
- forceDifficulty = true;
- currentDifficulty = 0.5f;
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD3)) {
- forceDifficulty = true;
- currentDifficulty = 1.0f;
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD0)) {
- forceDifficulty = false;
- calcCurrentDifficulty();
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD4)) {
- createSurvivalBosses();
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD5)) {
- crystalTick = 1;
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD6)) {
- setBuilding((BuildingFeature) Resources.get("building.generic.tangleweb"));
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD7)) {
- CompleteGameScreen.show();
- return;
- } else if (Game.wasKeyPressed(Keyboard.KEY_NUMPAD8)) {
- levelTick += 3600;
- }
- }
- boolean xmas = getGameMode() == GAME_MODE_XMAS;
- // Has the level ended?
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- // No, it's survival mode, and goes on forever and starts right away
- levelTick ++;
- tickSurvivalBosses();
- tickSpawnPoints();
- doCrystals();
- doSaucers();
- } else if (levelTick < getLevelDuration()) {
- if (beginLevel) {
- levelTick ++;
- if (xmas) {
- doCrystals();
- }
- checkUnminedCrystals();
- tickSpawnPoints();
- doSaucers();
- if (levelTick == getLevelDuration()) {
- aliensSpawnedAtLevelEnd = aliensSpawnedValue;
- rush = true;
- if (!xmas) {
- removeSpawnPoints();
- }
- }
- checkInterestingThingsHappening();
- // Maybe do hints
- HintFeature[] events = getLevelFeature().getEvents();
- if (events != null) {
- if (events.length > eventHintSeq) {
- if (events[eventHintSeq].getSeconds() * 60 <= levelTick) {
- flagHint(events[eventHintSeq ++]);
- }
- }
- }
- } else if (getMoney() < 250) {
- beginLevel = true;
- }
- } else {
- waitForGidrahs();
- }
- if (Game.DEBUG && tick % 240 == 0) {
- System.out.println(gidrahs.size()+" gidrahs, difficulty "+getDifficulty()+", valueSpawned="+aliensSpawnedValue+" vanquished="+aliensVanquishedValue);
- }
- }
- /**
- * @return true if the gidrahs have started their advance
- */
- public boolean isLevelStarted() {
- return beginLevel;
- }
- private void checkUnminedCrystals() {
- if (unminedCrystalList.size() == 0) {
- unminedTick = 0;
- } else {
- unminedTick ++;
- if (unminedTick == UNMINED_WARNING_TIME) {
- Worm.getGameState().flagHint(Hints.UNMINED);
- unminedTick = 0;
- }
- }
- }
- /**
- * @return the number of unmined crystals
- */
- public int getNumUnminedCrystals() {
- return unminedCrystalList.size();
- }
- private void checkInterestingThingsHappening() {
- // Interesting stuff happened?
- somethingInterestingHappenedTick ++;
- if (somethingInterestingHappenedTick > INTERESTING_INTERVAL && unminedCrystalList.size() == 0 ) {
- flagHint(Hints.FASTFORWARD);
- somethingInterestingHappenedTick = 0;
- }
- }
- private void removeSpawnPoints() {
- for (Iterator<SpawnPoint> i = spawnPoints.iterator(); i.hasNext(); ) {
- SpawnPoint s = i.next();
- s.remove();
- }
- spawnPoints.clear();
- }
- /**
- * Wait for all the gidrahs to die at the end of a level.
- */
- private void tickWaitForGidrahs() {
- // No bases left? Game over!
- if (!isAlive()) {
- endGame();
- return;
- }
- if (gidrahs.size() == 0) {
- if (getGameMode() == GAME_MODE_XMAS) {
- // Wait until spawnpoint is gone
- if (spawnPoints.size() > 0) {
- tickSpawnPoints();
- return;
- }
- }
- // Wait until (all crystals are mined / factory not available) and gidrahs and bosses are dead
- int n = bosses.size();
- for (int i = 0; i < n; i ++) {
- Gidrah boss = bosses.get(i);
- if (boss.isActive()) {
- return;
- }
- }
- bosses.clear();
- // Yay! level complete. Wait a few seconds.
- waitAFewSeconds();
- return;
- } else {
- if (Game.DEBUG && tick % 240 == 0) {
- System.out.println(gidrahs.size()+" gidrahs, difficulty "+getDifficulty());
- }
- tickSpawnPoints();
- checkInterestingThingsHappening();
- }
- }
- private void waitAFewSeconds() {
- tick = 0;
- rush = false;
- phase = PHASE_WAIT_A_FEW_SECONDS;
- // Collect any powerups
- for (Saucer saucer : new ArrayList<Saucer>(saucers)) {
- saucer.onClicked(Mode.MODE_NORMAL);
- }
- }
- private void tickWaitAFewSeconds() {
- if (tick == WAIT_A_FEW_SECONDS_DELAY) {
- endLevel();
- }
- }
- /**
- * Spawns the bosses
- */
- private void spawnBosses() {
- // Spawn the boss at some of the spawnpoints.
- int n = 0;
- ArrayList<SpawnPoint> sp = new ArrayList<SpawnPoint>(spawnPoints);
- Collections.shuffle(sp);
- ResourceArray bosses = LevelFeature.getLevel(metaState.level).getBosses();
- for (int i = 0; i < bosses.getNumResources() && n < sp.size(); ) {
- SpawnPoint bossSpawnPoint = sp.get(n ++);
- if (bossSpawnPoint.edge) {
- bossSpawnPoint.spawnBoss((GidrahFeature) bosses.getResource(i));
- i ++;
- }
- }
- doBossWarning(bosses.getNumResources());
- }
- private void doBossWarning(int numBosses) {
- // TODO: sfx
- LabelEffect challengeEffect = new LabelEffect(net.puppygames.applet.Res.getBigFont(), Game.getMessage("ultraworm.wormgamestate.extreme_danger"), ReadableColor.YELLOW, ReadableColor.RED, 60, 240);
- challengeEffect.setLocation(Game.getWidth() / 2, Game.getHeight() / 2 + 40);
- challengeEffect.setVisible(true);
- challengeEffect.spawn(GameScreen.getInstance());
- challengeEffect.setOffset(null);
- LabelEffect challengeEffect2 = new LabelEffect(net.puppygames.applet.Res.getSmallFont(), (numBosses > 1 ? Game.getMessage("ultraworm.wormgamestate.large_enemies_approaching") : Game.getMessage("ultraworm.wormgamestate.large_enemy_approaching")), ReadableColor.YELLOW, ReadableColor.RED,
- 60, 240);
- challengeEffect2.setLocation(Game.getWidth() / 2, Game.getHeight() / 2);
- challengeEffect2.setVisible(true);
- challengeEffect2.spawn(GameScreen.getInstance());
- challengeEffect2.setDelay(120);
- challengeEffect2.setOffset(null);
- }
- private void shutdownFactories() {
- boolean doSound = false;
- for (int i = 0; i < buildings.size(); i ++) {
- Building b = buildings.get(i);
- if (b.isActive()) {
- if (b instanceof Factory) {
- doSound |= ((Factory) b).isMining();
- }
- b.onEndLevel();
- }
- }
- if (doSound) {
- SFX.factoryShutdown();
- }
- }
- private void waitForGidrahs() {
- phase = PHASE_WAIT_FOR_GIDRAHS;
- tick = 0;
- }
- /**
- * Activate a powerup
- * @param powerup
- */
- public void activatePowerup(PowerupFeature powerup) {
- powerup.activate(gameStateInterface);
- }
- /**
- * Every now and again, launch a saucer.
- */
- private void doSaucers() {
- saucerTick ++;
- if (saucerTick > nextSaucer) {
- saucerTick = 0;
- if (getGameMode() != GAME_MODE_SURVIVAL && getGameMode() != GAME_MODE_XMAS) {
- nextSaucer += config.getNextSaucerInterval();
- }
- Saucer saucer = new Saucer();
- saucer.spawn(GameScreen.getInstance());
- }
- }
- /**
- * Every now and again, spawn a crystal.
- */
- private void doCrystals() {
- crystalTick --;
- if (crystalTick <= 0) {
- if (survivalCrystals.size() == 0) {
- // Refill the shuffle bag
- for (int i = 0; i < 3; i ++) {
- survivalCrystals.add(new Integer(1));
- }
- for (int i = 0; i < 2; i ++) {
- survivalCrystals.add(new Integer(2));
- }
- for (int i = 0; i < 1; i ++) {
- survivalCrystals.add(new Integer(3));
- }
- Collections.shuffle(survivalCrystals);
- }
- Integer size = survivalCrystals.remove(survivalCrystals.size() - 1);
- Crystal crystalDefinition = getLevelFeature().getScenery().getCrystal(size.intValue());
- int width = crystalDefinition.getWidth();
- int height = crystalDefinition.getHeight();
- int tileX, tileY;
- // Choose a spot some way from the base depending on difficulty
- float minDistance = 10.0f;
- float maxDistance = getMap().getWidth() * 0.45f;
- float ratio = (float) Math.random();
- float distance = LinearInterpolator.instance.interpolate
- (
- CosineInterpolator.instance.interpolate(minDistance, maxDistance, ratio),
- SineInterpolator.instance.interpolate(minDistance, maxDistance, ratio),
- getDifficulty()
- );
- double angle = Math.random() * Math.PI * 2.0;
- tileX = getBase().getTileX() + (int) (Math.cos(angle) * distance);
- tileY = getBase().getTileY() + (int) (Math.sin(angle) * distance);
- for (int x = 0; x < width; x ++) {
- for (int y = 0; y < height; y ++) {
- if (getMap().isOccupied(x + tileX, y + tileY)) {
- return;
- }
- if (getMap().isAttacking(x + tileX, y + tileY)) {
- return;
- }
- for (int z = 0; z < GameMap.LAYERS; z ++) {
- Tile t = getMap().getTile(x + tileX, y + tileY, z);
- if (t == null || t.isImpassable() || t.isSolid()) {
- return;
- }
- }
- }
- }
- ReadableRectangle bounds = new Rectangle(tileX * MapRenderer.TILE_SIZE, tileY * MapRenderer.TILE_SIZE, width * MapRenderer.TILE_SIZE, height * MapRenderer.TILE_SIZE);
- for (Iterator<Entity> i = entities.iterator(); i.hasNext(); ) {
- Entity entity = i.next();
- if (entity.isActive() && entity.isSolid() && entity.canCollide() && entity.isTouching(bounds)) {
- return;
- }
- }
- // Write excludes
- for (int x = 0; x < width; x ++) {
- for (int y = 0; y < height; y ++) {
- Exclude.getInstance().toMap(getMap(), x + tileX, y + tileY, false);
- }
- }
- EntitySpawningFeature esf = crystalDefinition.getCrystalFeature();
- esf.spawn(tileX, tileY);
- crystalTick = survivalNextCrystalTick * size.intValue();
- survivalNextCrystalTick += getGameMode() == GAME_MODE_SURVIVAL ? config.getSurvivalCrystalIntervalAdjust() : config.getXmasCrystalIntervalAdjust();
- }
- }
- /**
- * @return the game mode
- */
- public int getGameMode() {
- return metaState.gameMode;
- }
- /**
- * Init for a new game
- */
- @Override
- public void init() {
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- if (Worm.getMaxWorld() == 0) {
- SelectLevelScreen sls = (SelectLevelScreen) Resources.get("select.level.screen.0");
- sls.open();
- } else {
- SelectWorldScreen.show();
- }
- break;
- case GAME_MODE_ENDLESS:
- SelectEndlessLevelScreen.show();
- break;
- case GAME_MODE_SURVIVAL:
- SelectSurvivalLevelScreen.show();
- break;
- case GAME_MODE_SANDBOX:
- SelectSandboxLevelScreen.show();
- break;
- case GAME_MODE_XMAS:
- initXmas(true);
- break;
- default:
- assert false : "Unknown game mode "+mode;
- }
- }
- /**
- * Initialise a Christmas mode game (instead of calling {@link #doInit(int)})
- */
- private void initXmas(boolean reset) {
- System.out.println("Initialising Xmas Mode");
- waitForMouse = true;
- xmasReset = reset;
- if (reset) {
- metaState = null;
- metaState = new MetaState(GAME_MODE_XMAS);
- } else {
- metaState.reset();
- }
- GameScreen.beginGame(this);
- beginLevel();
- initXmasResearch();
- doInitMessages(Game.getMessage("ultraworm.wormgamestate.init_xmas1"), Game.getMessage("ultraworm.wormgamestate.init_xmas2"));
- }
- /**
- * Initialise a survival mode game (instead of calling {@link #doInit(int)})
- */
- private void initSurvival(boolean reset) {
- System.out.println("Initialising Survival Mode");
- waitForMouse = true;
- if (reset) {
- metaState = null;
- metaState = new MetaState(GAME_MODE_SURVIVAL);
- } else {
- metaState.reset();
- }
- GameScreen.beginGame(this);
- beginLevel();
- initSurvivalResearch();
- doInitMessages(Game.getMessage("ultraworm.wormgamestate.init_survival1"), Game.getMessage("ultraworm.wormgamestate.init_survival2"));
- }
- /**
- * Initialise a sandbox mode game (instead of calling {@link #doInit(int)})
- */
- private void initSandbox() {
- System.out.println("Initialising Sandbox Mode");
- waitForMouse = true;
- metaState = null;
- metaState = new MetaState(GAME_MODE_SANDBOX);
- GameScreen.beginGame(this);
- beginLevel();
- //initSurvivalResearch();
- //doInitMessages(Game.getMessage("ultraworm.wormgamestate.init_sandbox1"), Game.getMessage("ultraworm.wormgamestate.init_sandbox2"));
- doInitMessages("SANDBOX TEST", "No really, just a test!");
- }
- /**
- * Begin a new game at the specified level
- * @param level
- */
- public void doInit(int level) {
- System.out.println("DoInit: "+level);
- waitForMouse = true;
- if (level == 0) {
- // Research the default researchy things
- metaState = new MetaState(metaState.gameMode);
- initDefaultResearch();
- } else {
- // Load research and powerups etc we had last time
- try {
- metaState = MetaState.load(level, metaState.gameMode);
- } catch (Exception e) {
- e.printStackTrace(System.err);
- metaState = new MetaState(metaState.gameMode);
- initDefaultResearch();
- }
- }
- GameScreen.beginGame(this);
- if (Game.isRegistered()) {
- awardMedal(Medals.REGISTERED);
- }
- beginLevel();
- doInitMessages(Game.getMessage("ultraworm.wormgamestate.init1"), Game.getMessage("ultraworm.wormgamestate.init2"));
- }
- /**
- * Begin a Survival game with the specified characteristics
- */
- public void doInit(SurvivalParams survivalParams) {
- this.survivalParams = survivalParams;
- System.out.println("DoInit: "+survivalParams);
- initSurvival(survivalParams.getGenerateNew());
- if (Game.isRegistered()) {
- awardMedal(Medals.REGISTERED);
- }
- }
- /**
- * @return the survival parameters, if we're in survival mode
- */
- public SurvivalParams getSurvivalParams() {
- return survivalParams;
- }
- private void initDefaultResearch() {
- for (ResearchFeature rf : ResearchFeature.getResearch().values()) {
- if (rf.isDefaultAvailable()) {
- setResearched(rf.getID());
- }
- }
- }
- private void initSurvivalResearch() {
- MetaState tempMetaState;
- try {
- tempMetaState = MetaState.load(survivalParams.getWorld().getIndex() * LEVELS_IN_WORLD + LEVELS_IN_WORLD, GAME_MODE_CAMPAIGN);
- for (String s : tempMetaState.researched) {
- setResearched(s);
- }
- } catch (Exception e) {
- e.printStackTrace(System.err);
- initDefaultResearch();
- return;
- }
- }
- private void initXmasResearch() {
- for (String s : Xmas.RESEARCH) {
- setResearched(s);
- }
- }
- /**
- * Begin a Sandbox game with the specified characteristics
- */
- public void doInit(SandboxParams sandboxParams) {
- this.sandboxParams = sandboxParams;
- System.out.println("DoInit: "+sandboxParams);
- initSandbox();
- }
- /**
- * We've completed the game!
- */
- private void completeGame() {
- if (getGameMode() == GAME_MODE_XMAS) {
- CompleteXmasScreen.show();
- } else {
- CompleteGameScreen.show();
- }
- }
- /**
- * Go to the next level. If we run out of levels, we complete the game.
- */
- public void nextLevel() {
- metaState.level ++;
- if (getGameMode() == GAME_MODE_XMAS) {
- completeGame();
- return;
- }
- if (getGameMode() == GAME_MODE_ENDLESS || getLevel() < MAX_LEVELS) {
- beginLevel();
- } else {
- completeGame();
- }
- }
- /**
- * Initialise a level. We need to load the game map, remove any entities, spawn the buildings, make a note of the spawn points on
- * the map, etc.
- */
- public void beginLevel() {
- System.out.println("Beginning level "+metaState.gameMode+"/"+metaState.level);
- WorldFeature newWorld;
- StoryFeature[] sf;
- reset();
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- // Set the level
- metaState.levelFeature = LevelFeature.getLevel(metaState.level);
- // We might have changed worlds
- newWorld = getLevelFeature().getWorld();
- if (newWorld != getWorld()) {
- setWorld(newWorld);
- return;
- }
- currentStoryIndex = 0;
- sf = getLevelFeature().getStories();
- currentStories = new ArrayList<StoryFeature>(sf.length);
- for (StoryFeature element : sf) {
- if (element.qualifies()) {
- currentStories.add(element);
- }
- }
- suppressMedals = false;
- showStoryScreen();
- break;
- case GAME_MODE_ENDLESS:
- // Generate a random level
- metaState.levelFeature = LevelFeature.generateEndless(metaState.level);
- // We might have changed worlds
- newWorld = getLevelFeature().getWorld();
- if (newWorld != getWorld()) {
- setWorld(newWorld);
- }
- currentStoryIndex = 0;
- sf = getLevelFeature().getStories();
- currentStories = new ArrayList<StoryFeature>(sf.length);
- for (StoryFeature element : sf) {
- if (element.qualifies()) {
- currentStories.add(element);
- }
- }
- suppressMedals = false;
- showStoryScreen();
- break;
- case GAME_MODE_SURVIVAL:
- if (survivalParams.getGenerateNew()) {
- // Generate a random level
- metaState.levelFeature = LevelFeature.generateSurvival(survivalParams);
- } else {
- // Use last level
- }
- metaState.difficulty = survivalParams.getDifficulty();
- metaState.survivalParams = survivalParams;
- metaState.reset();
- // We might have changed worlds
- newWorld = getLevelFeature().getWorld();
- if (newWorld != getWorld()) {
- setWorld(newWorld);
- }
- currentStoryIndex = 0;
- sf = getLevelFeature().getStories();
- currentStories = new ArrayList<StoryFeature>(sf.length);
- for (StoryFeature element : sf) {
- if (element.qualifies()) {
- currentStories.add(element);
- }
- }
- suppressMedals = false;
- showStoryScreen();
- break;
- case GAME_MODE_SANDBOX:
- // Generate a random level
- metaState.levelFeature = LevelFeature.generateEndless(metaState.level);
- // We might have changed worlds
- newWorld = getLevelFeature().getWorld();
- if (newWorld != getWorld()) {
- setWorld(newWorld);
- }
- suppressMedals = true;
- beginLevel2();
- break;
- case GAME_MODE_XMAS:
- // Generate a random level
- metaState.levelFeature = LevelFeature.generateXmas();
- metaState.difficulty = 0.0f;
- metaState.reset();
- // We might have changed worlds
- newWorld = getLevelFeature().getWorld();
- if (newWorld != getWorld()) {
- setWorld(newWorld);
- }
- currentStoryIndex = 0;
- sf = getLevelFeature().getStories();
- currentStories = new ArrayList<StoryFeature>(sf.length);
- for (StoryFeature element : sf) {
- if (element.qualifies()) {
- currentStories.add(element);
- }
- }
- suppressMedals = false;
- showStoryScreen();
- break;
- default:
- assert false : "Unknown game mode "+metaState.gameMode;
- }
- }
- private void nextStoryScreen() {
- if (++currentStoryIndex >= currentStories.size()) {
- StoryScreen.tidyUp("story.screen."+getWorld().getUntranslated());
- // Open research screen, unless this is level 0 or survival mode or sandbox mode, in which case jump straight into the action
- if (getLevel() == 0 || getGameMode() == GAME_MODE_SURVIVAL || getGameMode() == GAME_MODE_SANDBOX) {
- beginLevel2();
- } else {
- showResearchScreen();
- }
- } else {
- // Open next story screen
- showStoryScreen();
- }
- }
- private void previousStoryScreen() {
- if (--currentStoryIndex == -1) {
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- // Go to level select screen of current world
- StoryScreen.tidyUp("story.screen."+getWorld().getUntranslated());
- showLevelSelectScreen();
- break;
- case GAME_MODE_ENDLESS:
- case GAME_MODE_SURVIVAL:
- showLevelSelectScreen();
- break;
- case GAME_MODE_SANDBOX:
- showLevelSelectScreen();
- break;
- case GAME_MODE_XMAS:
- net.puppygames.applet.screens.TitleScreen.show();
- break;
- default:
- assert false : "Shouldn't be here: "+metaState.gameMode;
- }
- } else {
- // Open previous story
- showStoryScreen();
- }
- }
- public void showLevelSelectScreen() {
- switch (metaState.gameMode) {
- case GAME_MODE_CAMPAIGN:
- SelectLevelScreen sls = (SelectLevelScreen) Resources.get("select.level.screen."+metaState.level / LEVELS_IN_WORLD);
- sls.open();
- break;
- case GAME_MODE_ENDLESS:
- SelectEndlessLevelScreen.show();
- break;
- case GAME_MODE_SURVIVAL:
- SelectSurvivalLevelScreen.show();
- break;
- case GAME_MODE_SANDBOX:
- SelectSandboxLevelScreen.show();
- break;
- case GAME_MODE_XMAS:
- net.puppygames.applet.screens.TitleScreen.show();
- break;
- default:
- assert false : "Shouldn't be here: "+metaState.gameMode;
- }
- }
- public void showResearchScreen() {
- ResearchScreen.show
- (
- new Runnable() {
- @Override
- public void run() {
- previousStoryScreen();
- }
- },
- new Runnable() {
- @Override
- public void run() {
- Worm.getGameState().beginLevel2();
- }
- }
- );
- }
- private void showStoryScreen() {
- StoryScreen.show
- (
- "story.screen."+getWorld().getUntranslated(),
- currentStoryIndex == 0,
- currentStories.get(currentStoryIndex),
- new Runnable() {
- @Override
- public void run() {
- previousStoryScreen();
- }
- },
- new Runnable() {
- @Override
- public void run() {
- nextStoryScreen();
- }
- }
- );
- }
- public void setMap(GameMap newMap) {
- this.map = newMap;
- }
- /**
- * Reinforcements!
- */
- private void reinforcements() {
- for (Iterator<BuildingFeature> i = BuildingFeature.getBuildings().iterator(); i.hasNext(); ) {
- BuildingFeature bf = i.next();
- if (bf.isAvailable()) {
- int num = bf.getNumAvailable();
- if (num > 0) {
- addAvailableStock(bf, num);
- }
- }
- }
- }
- /**
- * Begin the level with the specified map.
- */
- public void beginLevel2() {
- // Increase available stock of everything (barricades and mines)
- reinforcements();
- // Ensure all entities are removed first
- for (Iterator<Entity> i = entities.iterator(); i.hasNext(); ) {
- Entity entity = i.next();
- entity.remove();
- }
- entities.clear();
- // Init gids stuff at start of level
- Gidrah.init();
- phase = PHASE_NORMAL;
- rush = false;
- levelTick = 0;
- tick = 0;
- beginLevel = !isResearched(ResearchFeature.FACTORY) || getMoney() < 250 || metaState.gameMode == GAME_MODE_SURVIVAL || metaState.gameMode == GAME_MODE_XMAS;
- nextSaucer = config.getSaucerInterval();
- System.out.println("MODE: "+metaState.gameMode+"\nPHASE: "+phase);
- // Reset buffs
- scannerBoost = 0;
- batteryBoost = 0;
- reactorBoost = 0;
- coolingBoost = 0;
- shieldBoost = isResearched(ResearchFeature.NANOHARDENING) ? 1 : 0;
- capacitorBoost = isResearched(ResearchFeature.IONISATION) ? 1 : 0;
- // Reset counters
- factories = 0;
- warehouses = 0;
- autoloaders = 0;
- shieldGenerators = 0;
- spawners = 0;
- crystals = 0;
- initialCrystals = 0;
- // Reset powerups
- bezerkTick = 0;
- shieldTick = 0;
- freezeTick = 0;
- // Reset buildings value
- anyDamaged = false;
- valueOfBuiltBuildings = 0;
- valueOfDestroyedBuildings = 0;
- // Reset aliens spawned value
- aliensVanquishedValue = 0;
- aliensSpawnedValue = 0;
- // Clear medals earned this level
- medalsThisLevel.clear();
- awesome = false;
- // Remember starting money
- startingMoney = metaState.money;
- attempts = Worm.getExtraLevelData(Game.getPlayerSlot(), metaState.level, metaState.gameMode, "attempts", 0);
- System.out.println("Number of attempts at this level so far: "+attempts);
- // Adjust difficulty by number of attempts
- calcBasicDifficulty();
- calcPowerupDifficulty();
- System.out.println("Base difficulty "+metaState.difficulty);
- // How long's the level?
- calcLevelDuration(map.getWidth(), map.getHeight());
- // Clear everything out
- unminedCrystalList.clear();
- Entity.reset();
- System.gc();
- // Sort out the map
- initMap();
- // Open the game screen
- GameScreen.onBeginLevel();
- // Maybe spawn bosses
- ResourceArray bosses = metaState.levelFeature.getBosses();
- if (bosses != null && bosses.getNumResources() > 0) {
- spawnBosses();
- }
- // Reset event sequence
- eventHintSeq = 0;
- leftMouseWasDown = true;
- waitForMouse = true;
- // Research medals
- if (metaState.gameMode != GAME_MODE_SURVIVAL && metaState.gameMode != GAME_MODE_XMAS) {
- Map<String, List<String>> medalGroups = ResearchFeature.getMedalGroups();
- for (Entry<String, List<String>> entry : medalGroups.entrySet()) {
- String medal = entry.getKey();
- List<String> researchRequired = entry.getValue();
- synchronized (metaState.researched) {
- if (metaState.researched.containsAll(researchRequired)) {
- awardMedal(medal);
- }
- }
- }
- }
- }
- /**
- * Calculates base difficulty and research difficulty
- */
- public void calcBasicDifficulty() {
- if (metaState.gameMode == GAME_MODE_SURVIVAL) {
- metaState.difficulty = survivalParams.getDifficulty();
- return;
- } else if (metaState.gameMode == GAME_MODE_XMAS) {
- metaState.difficulty = 0.0f;
- return;
- }
- int diff = getDifficultyAdjust(getLevel(), getGameMode());
- metaState.difficulty = diff * config.getDifficultyAdjustmentFactor();
- // Central base levels - offset difficulty
- float offset = BaseMapGenerator.isBaseCentralForLevel(metaState.level, metaState.gameMode) ? config.getCentralDifficultyAdjustPerLevel() * metaState.level : 0.0f;
- // Endless mode: gets a bit harder every level after level 50...
- if (metaState.gameMode == GAME_MODE_ENDLESS && metaState.level > MAX_LEVELS) {
- offset -= (metaState.level - MAX_LEVELS) * config.getEndlessDifficultyCreep();
- }
- metaState.difficulty -= offset;
- System.out.println("BASIC DIFFICULTY "+getBasicDifficulty()+" (was offset by "+offset+")");
- }
- /**
- * @return the basic level difficulty (≥ 0.0f)
- */
- public float getBasicDifficulty() {
- return Math.max(0.0f, metaState.difficulty + (config.getBankFactor() * getMoney()) / (config.getDifficultyFactor() + config.getDifficultyFactorPerLevel() * getLevel()));
- }
- /**
- * Initialise the map generated in the story screen
- */
- private void initMap() {
- // Clear away the old spawn points
- spawnPoints.clear();
- // Have we been here before?
- MapProcessor processor = new MapProcessor() {
- @Override
- public void addSpawnPoint(int x, int y, int type, boolean edge) {
- SpawnPoint sp = new SpawnPoint(x, y, type, edge);
- assert !spawnPoints.contains(sp);
- spawnPoints.add(sp);
- }
- @Override
- public void createBase(int x, int y) {
- getWorld().getBase().build(x * MapRenderer.TILE_SIZE, y * MapRenderer.TILE_SIZE);
- }
- @Override
- public void spawnEntity(EntitySpawningFeature feature, int tileX, int tileY) {
- // Spawn the entity...
- Entity e = feature.spawn(tileX, tileY);
- e.update();
- // Remove from the map?
- if (feature.removeAfterSpawn()) {
- getMap().clearItem(tileX, tileY);
- }
- }
- };
- // Process the map one tile at a time.
- for (int y = 0; y < map.getHeight(); y ++) {
- for (int x = 0; x < map.getWidth(); x ++) {
- for (int z = 0; z < GameMap.LAYERS; z ++) {
- Tile t = map.getTile(x, y, z);
- t.process(processor, x, y);
- }
- }
- }
- // Survival mode: create spawn point.
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- createSurvivalSpawnPoint();
- }
- }
- private ReadablePoint getEdgePoint() {
- int edge = getGameMode() == GAME_MODE_XMAS ? 0 : Util.random(0, 9); // Bias away from south: only 1/10 edges are picked from south
- boolean blocked;
- int x, y, ox, oy, count = 0;
- do {
- count ++;
- blocked = false;
- switch (edge) {
- case 0: // North
- case 1:
- case 2:
- x = Util.random(1, getMap().getWidth() - 2);
- y = getMap().getHeight() - 1;
- ox = 0;
- oy = 1;
- break;
- case 3: // East
- case 4:
- case 5:
- y = Util.random(1, getMap().getHeight() - 2);
- x = getMap().getWidth() - 1;
- ox = 1;
- oy = 0;
- break;
- case 6: // West
- case 7:
- case 8:
- y = Util.random(1, getMap().getHeight() - 2);
- x = 0;
- ox = -1;
- oy = 0;
- break;
- case 9: // South
- x = Util.random(1, getMap().getWidth() - 2);
- y = 0;
- ox = 0;
- oy = -1;
- break;
- default:
- assert false;
- return new Point();
- }
- for (int z = 0; z < GameMap.LAYERS; z ++) {
- Tile t = getMap().getTile(x, y, z);
- if (t.isImpassable() || t.isSolid()) {
- blocked = true;
- break;
- }
- }
- } while (blocked && count < 50);
- return new Point(x + ox, y + oy);
- }
- /**
- * Creates a brand new survival mode spawnpoint by finding an empty tile on the edge of the map.
- */
- private void createSurvivalSpawnPoint() {
- ReadablePoint edgePoint = getEdgePoint();
- if (edgePoint == null) {
- return;
- }
- spawnPoints.add(new SpawnPoint(edgePoint.getX(), edgePoint.getY(), 0, true));
- }
- /**
- * Hack for Earth-only survival / xmas bosses
- * @param n
- * @return
- */
- private static String survivalBoss(int n) {
- StringBuilder sb = new StringBuilder(n);
- for (int i = 0; i < n; i ++) {
- sb.append('0');
- }
- return sb.toString();
- }
- /**
- * Spawns survival mode bosses
- */
- private void createSurvivalBosses() {
- // Get best world player has seen...
- int bestWorldIndex = Math.min(WorldFeature.getNumWorlds() - 1, Worm.getMaxLevel(GAME_MODE_CAMPAIGN) / LEVELS_IN_WORLD);
- int numBossTypes = Math.min(WorldFeature.getWorld(bestWorldIndex).getSurvivalMaxBoss() + 1, Res.getNumSurvivalBosses());
- String s = numBossTypes == 1 ? survivalBoss(survivalBoss) : Integer.toString(survivalBoss, numBossTypes);
- for (int i = 0; i < s.length(); i ++) {
- ReadablePoint edgePoint = getEdgePoint();
- GidrahFeature bossFeature = Res.getSurvivalBoss(s.charAt(i) - '0');
- if (bossFeature != null) {
- bossFeature.spawn(GameScreen.getInstance(), edgePoint.getX(), edgePoint.getY(), 0);
- }
- }
- survivalBoss ++;
- doBossWarning(s.length());
- reinforcements();
- }
- /**
- * @return the current map
- */
- public GameMap getMap() {
- return map;
- }
- private void setWorld(WorldFeature newWorld) {
- assert newWorld != null;
- if (metaState.world == newWorld) {
- return;
- }
- metaState.world = newWorld;
- // Put up a New World screen in campaign mode
- if (metaState.gameMode == GAME_MODE_CAMPAIGN) {
- NewWorldScreen nw = (NewWorldScreen) Resources.get("newworld.screen."+getWorld().getUntranslated());
- nw.open();
- }
- }
- private void doInitMessages(String big, String small) {
- LabelEffect newLevelEffect = new LabelEffect(net.puppygames.applet.Res.getBigFont(), big, ReadableColor.WHITE, ReadableColor.RED, 40, 160);
- newLevelEffect.setLocation(Game.getWidth() / 2, Game.getHeight() / 2 + 60);
- newLevelEffect.setVisible(true);
- newLevelEffect.spawn(GameScreen.getInstance());
- newLevelEffect.setOffset(null);
- LabelEffect hintEffect = new LabelEffect(net.puppygames.applet.Res.getSmallFont(), small, ReadableColor.WHITE, ReadableColor.RED, 40, 160);
- hintEffect.setDelay(30);
- hintEffect.setLocation(Game.getWidth() / 2, Game.getHeight() / 2 + 20);
- hintEffect.setVisible(true);
- hintEffect.spawn(GameScreen.getInstance());
- hintEffect.setOffset(null);
- }
- @Override
- public void reinit() {
- GameScreen.beginGame(this);
- doInitMessages(Game.getMessage("ultraworm.wormgamestate.reinit1"), Game.getMessage("ultraworm.wormgamestate.reinit2"));
- waitForMouse = true;
- if (mode == Mode.MODE_BUILD) {
- setBuilding(building);
- }
- // Process entities
- for (Iterator<Entity> i = entities.iterator(); i.hasNext(); ) {
- Entity entity = i.next();
- entity.respawn(GameScreen.getInstance());
- }
- // And spawnpoints
- for (Iterator<SpawnPoint> i = spawnPoints.iterator(); i.hasNext(); ) {
- SpawnPoint sp = i.next();
- sp.reinit();
- }
- GameScreen.onBeginLevel();
- if (!isAlive()) {
- MiniGame.endGame();
- }
- }
- /**
- * @return Returns the entities.
- */
- public ArrayList<Entity> getEntities() {
- return entities;
- }
- /**
- * @return Returns the buildings
- */
- public ArrayList<Building> getBuildings() {
- return buildings;
- }
- /**
- * @return Returns the gidrahs
- */
- public ArrayList<Gidrah> getGidrahs() {
- return gidrahs;
- }
- /**
- * @return all the saucers
- */
- public ArrayList<Saucer> getSaucers() {
- return saucers;
- }
- /**
- * Called when it's game over time
- */
- public void onGameOver() {
- if (phase == PHASE_END_OF_GAME) {
- return;
- }
- phase = PHASE_END_OF_GAME;
- tick = 0;
- // Stop building
- setBuilding(null);
- }
- /**
- * Freeze the gidrahs!
- * @param duration
- */
- public void freeze(int duration) {
- freezeTick += duration;
- GameScreen.getInstance().onFreezeTimerIncreased(freezeTick);
- }
- /**
- * Called whenever a gidrah is killed. This removes the gidrah from the gidrahs list,
- * updates stats, and awards medals appropriately
- * @param gidrah The gidrah that was killed
- * @param causeOfDeath For stats and medals purposes
- */
- public void onGidrahKilled(Gidrah gidrah, int causeOfDeath) {
- gidrahs.remove(gidrah);
- switch (causeOfDeath) {
- case CauseOfDeath.ATTACK:
- return;
- case CauseOfDeath.DISRUPTOR:
- case CauseOfDeath.BULLET:
- case CauseOfDeath.LASER:
- metaState.addStat(Stats.ALIENS_SHOT, 1);
- break;
- case CauseOfDeath.CAPACITOR:
- int fried = metaState.addStat(Stats.ALIENS_FRIED, 1);
- if (fried == 100) {
- awardMedal(Medals.FRIED_100);
- } else if (fried == 250) {
- awardMedal(Medals.FRIED_250);
- } else if (fried == 500) {
- awardMedal(Medals.FRIED_500);
- }
- break;
- case CauseOfDeath.CRUSHED:
- int crushed = metaState.addStat(Stats.ALIENS_CRUSHED, 1);
- if (crushed == 25) {
- awardMedal(Medals.CRUSHED_25);
- } else if (crushed == 50) {
- awardMedal(Medals.CRUSHED_50);
- } else if (crushed == 100) {
- awardMedal(Medals.CRUSHED_100);
- }
- break;
- case CauseOfDeath.EXPLOSION:
- int exploded = metaState.addStat(Stats.ALIENS_BLOWN_UP, 1);
- if (exploded == 100) {
- awardMedal(Medals.EXPLODED_100);
- } else if (exploded == 250) {
- awardMedal(Medals.EXPLODED_250);
- } else if (exploded == 500) {
- awardMedal(Medals.EXPLODED_500);
- }
- break;
- case CauseOfDeath.SMARTBOMB:
- int nuked = metaState.addStat(Stats.ALIENS_SMARTBOMBED, 1);
- if (nuked == 50) {
- awardMedal(Medals.NUKED_50);
- } else if (nuked == 100) {
- awardMedal(Medals.NUKED_100);
- } else if (nuked == 250) {
- awardMedal(Medals.NUKED_250);
- }
- break;
- case CauseOfDeath.GRID_BUG:
- // Bah
- return;
- default:
- assert false : "Unknown cause of death "+causeOfDeath;
- break;
- }
- int vanquished = metaState.addStat(Stats.ALIENS_VANQUISHED, 1);
- if (vanquished == 100) {
- awardMedal(Medals.VANQUISHED_100);
- } else if (vanquished == 250) {
- awardMedal(Medals.VANQUISHED_250);
- } else if (vanquished == 500) {
- awardMedal(Medals.VANQUISHED_500);
- } else if (vanquished == 1000) {
- awardMedal(Medals.VANQUISHED_1000);
- } else if (vanquished == 2500) {
- awardMedal(Medals.VANQUISHED_2500);
- } else if (vanquished == 5000) {
- awardMedal(Medals.VANQUISHED_5000);
- } else if (vanquished == 10000) {
- awardMedal(Medals.VANQUISHED_10000);
- }
- // Survival mode: gidrah deaths unlocks more gidrahs
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- if (gidrah.getFeature().isBoss() || gidrah.getFeature().isGidlet()) {
- // Not bosses or gidlets
- } else {
- int type = gidrah.getType();
- survivalGidrahKills[type] += gidrah.getFeature().isAngry() ? 10 : 1;
- if (survivalGidrahKills[type] >= survivalGidrahUnlockNext[type]) {
- int bestWorldIndex = Math.min(WorldFeature.getNumWorlds() - 1, Worm.getMaxLevel(GAME_MODE_CAMPAIGN) / LEVELS_IN_WORLD);
- if (type < survivalGidrahUnlock.length - 2 && survivalGidrahUnlock[type + 1] == 0) {
- // Unlock next type first. If there is one.
- int max = WorldFeature.getWorld(bestWorldIndex).getSurvivalMaxType(type + 1);
- if (max != -1) {
- survivalGidrahUnlock[type + 1] = 1;
- } else {
- metaState.difficulty += config.getSurvivalDifficultyAdjuster();
- }
- } else {
- int max = WorldFeature.getWorld(bestWorldIndex).getSurvivalMaxType(type);
- if (max > survivalGidrahUnlock[type]) {
- survivalGidrahUnlock[type] ++;
- } else {
- metaState.difficulty += config.getSurvivalDifficultyAdjuster();;
- }
- }
- survivalGidrahUnlockNext[type] += survivalGidrahUnlockNext[type] + config.getSurvivalGidrahUnlockIntervalAdjust()[type];
- }
- }
- }
- }
- /**
- * Marks a building type as having been researched
- * @param type
- */
- public void setResearched(String type) {
- synchronized (metaState.researched) {
- if (metaState.researched.add(type)) {
- (ResearchFeature.getResearch().get(type)).onResearched();
- }
- }
- }
- /**
- * Marks a building type as having NOT been researched
- * @param type
- */
- public void setUnresearched(String type) {
- synchronized (metaState.researched) {
- if (metaState.researched.remove(type)) {
- (ResearchFeature.getResearch().get(type)).onUnresearched();
- }
- }
- }
- /**
- * Is the specified ResearchItem researched?
- * @param type
- * @return
- */
- public boolean isResearched(String type) {
- return metaState.researched.contains(type);
- }
- /**
- * @return
- */
- public boolean isBuilding() {
- return building != null;
- }
- /**
- * @return the building we're building, or null, if we're not building
- */
- public BuildingFeature getBuilding() {
- return building;
- }
- /**
- * @return the cost of the current building
- */
- public int getBuildingCost() {
- return building.getShopValue();
- }
- /**
- * @return true if the building we're trying to build is still available to build
- */
- public boolean isBuildingAvailable() {
- return building.isAvailable() && building.isEnabledInShop();
- }
- /**
- * @return the name of the current building
- */
- public String getBuildingName() {
- return building.getTitle();
- }
- /**
- * @return current level index, 0 based
- */
- public int getLevel() {
- return metaState.level;
- }
- /**
- * @return the level in the world (0..LEVELS_IN_WORLD or so)
- */
- public int getLevelInWorld() {
- return metaState.level % LEVELS_IN_WORLD;
- }
- /**
- * @return current world feature
- */
- public WorldFeature getWorld() {
- return metaState.world;
- }
- /**
- * @return current level feature
- */
- public LevelFeature getLevelFeature() {
- return metaState.levelFeature;
- }
- /**
- * Calculates and returns a difficulty value based on level number in the world.
- * @return a float value between 0.0f (very easy) and 1.0f (very hard)
- */
- public float getDifficulty() {
- return currentDifficulty;
- }
- private void calcCurrentDifficulty() {
- if (forceDifficulty) {
- System.out.println("Difficulty forced to "+currentDifficulty);
- return;
- }
- float ret = 0.0f;
- float attenuate = 1.0f;
- float irate = 0.0f;
- boolean survival = getGameMode() == GAME_MODE_SURVIVAL;
- boolean xmas = getGameMode() == GAME_MODE_XMAS;
- // And then attenuate this difficulty by how badly the player is being kicked in:
- if (!survival && !xmas && valueOfDestroyedBuildings > 0 && valueOfBuiltBuildings > config.getBuiltBuildingsValueThreshold()) {
- float slaughterAttenuation = 1.0f;
- // Attenuate the attenuation by the aliens losses when level is ended
- if (!isLevelActive() && aliensSpawnedAtLevelEnd > 0 && aliensVanquishedSinceEndOfLevel > 0) {
- slaughterAttenuation = 1.0f - Math.min(1.0f, Math.max(0.0f, (float) aliensVanquishedSinceEndOfLevel / (float ) aliensSpawnedAtLevelEnd));
- }
- attenuate = 1.0f - Math.min(1.0f, Math.max(0.0f, (float) valueOfDestroyedBuildings / (float ) valueOfBuiltBuildings)) * slaughterAttenuation;
- }
- // Calculate total money in-play
- float total = getMoney() * config.getBankFactor();
- for (int i = buildings.size(); -- i >= 0; ) {
- Building b = buildings.get(i);
- if (b.isAlive()) {
- total += b.getCost();
- irate += b.getAgitation();
- }
- }
- // For every $DIFFICULTY_FACTOR in play add 1.0 difficulty
- switch (getGameMode()) {
- case GAME_MODE_SURVIVAL:
- total += valueOfDestroyedBuildings; // It never gets easier :)
- ret += total / config.getSurvivalModeDifficultyFactors()[survivalParams.getWorld().getIndex()];
- break;
- case GAME_MODE_XMAS:
- total += valueOfDestroyedBuildings;
- ret += total / config.getXmasDifficultyFactor();
- break;
- default:
- ret += total / (config.getDifficultyFactor() + config.getDifficultyFactorPerLevel() * getLevel());
- ret *= attenuate;
- break;
- }
- // Add difficulty for powerups...
- currentDifficulty += powerupDifficulty * attenuate;
- // Finally, adjust by base difficulty offset
- float attemptsDifficulty = Worm.getAutoDifficulty() ? config.getDifficultyAttempts()[Math.min(config.getDifficultyAttempts().length -1, attempts)] : 0.0f;
- currentDifficulty = Math.max(0.0f, irate + ret + metaState.difficulty + attemptsDifficulty);
- }
- public int getResearchHash() {
- return metaState.researched.hashCode();
- }
- /**
- * Kill the player
- */
- public void kill() {
- alive = false;
- }
- /**
- * Quit the game
- */
- public void quit() {
- MiniGame.endGame();
- }
- private void reset() {
- alive = true;
- rush = false;
- mode = Mode.MODE_NORMAL;
- beginLevel = false;
- startingMoney = 500;
- somethingInterestingHappenedTick = 0;
- crystals = 0;
- for (int i = entities.size(); --i >= 0; ) {
- (entities.get(i)).remove();
- }
- entities.clear();
- for (int i = spawnPoints.size(); --i >= 0; ) {
- (spawnPoints.get(i)).remove();
- }
- spawnPoints.clear();
- gidrahs.clear();
- bosses.clear();
- units.clear();
- buildings.clear();
- saucers.clear();
- medalsThisLevel.clear();
- armedCapacitors.clear();
- unminedCrystalList.clear();
- tick = 0;
- totalTicks = 0;
- saucerTick = 0;
- levelTick = 0;
- bezerkTick = 0;
- survivalSpawnPointTick = 0;
- crystalTick = 0;
- survivalCrystals.clear();
- survivalNextBossTick = config.getSurvivalBossInterval();
- survivalNextCrystalTick = 0;
- survivalNextSpawnPointTick = 0;
- survivalSpawnPointInterval = config.getSurvivalSpawnpointSpawnInterval();
- numSurvivalSpawnPoints = 1;
- survivalGidrahUnlock[0] = 1;
- survivalGidrahUnlock[1] = 0;
- survivalGidrahUnlock[2] = 0;
- survivalGidrahUnlock[3] = 0;
- survivalGidrahUnlockNext[0] = config.getSurvivalGidrahUnlockInterval()[0];
- survivalGidrahUnlockNext[1] = config.getSurvivalGidrahUnlockInterval()[1];
- survivalGidrahUnlockNext[2] = config.getSurvivalGidrahUnlockInterval()[2];
- survivalGidrahUnlockNext[3] = config.getSurvivalGidrahUnlockInterval()[3];
- survivalGidrahKills[0] = 0;
- survivalGidrahKills[1] = 0;
- survivalGidrahKills[2] = 0;
- survivalGidrahKills[3] = 0;
- survivalBoss = 0;
- survivalBossTick = 0;
- GameScreen.getInstance().removeAllTickables();
- }
- /**
- * Restart the level
- */
- public void restart() {
- if (metaState.gameMode != GAME_MODE_SURVIVAL && metaState.gameMode != GAME_MODE_XMAS) {
- int attempts = Worm.getExtraLevelData(Game.getPlayerSlot(), metaState.level, metaState.gameMode, "attempts", 0);
- Worm.setExtraLevelData(metaState.level, metaState.gameMode, "attempts", attempts + 1);
- }
- reset();
- doInit(metaState.level);
- }
- private void removeCrystals() {
- // Remove crystals properly so the exclude tiles are removed
- for (Building b : buildings) {
- if (b instanceof CrystalResource) {
- ((CrystalResource) b).clearMap();
- }
- }
- }
- public void restartSurvival(boolean generateNew) {
- removeCrystals();
- reset();
- survivalParams.setGenerateNew(generateNew);
- doInit(survivalParams);
- }
- public void restartXmas(boolean generateNew) {
- removeCrystals();
- reset();
- initXmas(generateNew);
- }
- /**
- * Make the current level easier next time it's played
- */
- public void easier() {
- int diff = getDifficultyAdjust(metaState.level, metaState.gameMode);
- setDifficultyAdjust(metaState.level, metaState.gameMode, diff + 1);
- if (metaState.gameMode == GAME_MODE_CAMPAIGN || metaState.gameMode == GAME_MODE_ENDLESS) {
- // Reset attempts count
- Worm.setExtraLevelData(metaState.level, metaState.gameMode, "attempts", 0);
- }
- }
- /**
- * Save and quit
- */
- public void save() {
- saving = true;
- saveTick = 0;
- LabelEffect saveEffect = new LabelEffect(net.puppygames.applet.Res.getBigFont(), Game.getMessage("ultraworm.wormgamestate.saving_game"), new MappedColor("gui-bright"), new MappedColor("gui-dark"), SAVE_DURATION / 2, SAVE_DURATION / 2);
- saveEffect.setLocation(Game.getWidth() / 2, Game.getHeight() / 2);
- saveEffect.setVisible(true);
- saveEffect.spawn(GameScreen.getInstance());
- saveEffect.setOffset(null);
- }
- public int getCapacitorBoost() {
- return capacitorBoost;
- }
- public int getBatteryBoost() {
- return batteryBoost;
- }
- public int getShieldBoost() {
- return shieldBoost;
- }
- public int getReactorBoost() {
- return reactorBoost;
- }
- public int getScannerBoost() {
- return scannerBoost;
- }
- public int getCoolingBoost() {
- return coolingBoost;
- }
- public void flagHint(String hintName) {
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- // No hints in survival mode
- return;
- }
- HintFeature hint = HintFeature.getHint(hintName);
- if (hint == null) {
- return;
- }
- flagHint(hint);
- }
- private void flagHint(HintFeature hintFeature) {
- if (hintFeature.getMinLevel() > 0 && metaState.level <= hintFeature.getMinLevel()) {
- return;
- }
- if (hintFeature.getMaxLevel() > 0 && metaState.level > hintFeature.getMaxLevel()) {
- return;
- }
- GameScreen.getInstance().showHint(hintFeature);
- }
- public int getHintSequence(HintFeature hintFeature) {
- if (hintFeature.getText() != null) {
- // It's a medal hint
- return 0;
- }
- Integer seq = hintMap.get(hintFeature);
- if (seq == null) {
- seq = new Integer(0);
- }
- int seqValue = seq.intValue();
- if (seqValue == -1) {
- // Hint suppressed
- return -1;
- }
- if (hintFeature.isRandom()) {
- return Util.random(0, hintFeature.getHints().getNumResources() - 1);
- }
- if (seqValue == hintFeature.getHints().getNumResources()) {
- // No hints left
- return -1;
- }
- hintMap.put(hintFeature, new Integer(seqValue + 1));
- return seqValue;
- }
- public void suppressHint(String hint) {
- HintFeature hint2 = HintFeature.getHint(hint);
- if (hint2 == null) {
- System.out.println("Hint "+hint+" not defined");
- return;
- }
- suppressHint(hint2);
- }
- public void suppressHint(HintFeature hintFeature) {
- hintMap.put(hintFeature, new Integer(-1));
- GameScreen.getInstance().dequeueHint(hintFeature);
- }
- /**
- * @return the number of active Units
- */
- public int getNumUnits() {
- return units.size();
- }
- /**
- * Called when a building is destroyed by aliens
- * @param b
- */
- public void onBuildingDestroyed(Building b, boolean deliberate) {
- if (b.isWorthAttacking()) {
- if (!deliberate) {
- valueOfDestroyedBuildings += b.getFeature().getInitialValue();
- numberOfBuildingsDestroyed ++;
- if (b.isCity()) {
- GameScreen.instance.zoom(b.getMapX() + b.getCollisionX() - Game.getWidth() / 2, b.getMapY() + b.getCollisionY() - Game.getHeight() / 2);
- }
- int totalBuildingsDestroyed = addStat(Stats.BUILDINGS_DESTROYED, 1);
- if (totalBuildingsDestroyed == 10) {
- awardMedal(Medals.CARELESS);
- } else if (totalBuildingsDestroyed == 25) {
- awardMedal(Medals.RASH);
- } else if (totalBuildingsDestroyed == 50) {
- awardMedal(Medals.RECKLESS);
- } else if (totalBuildingsDestroyed == 100) {
- awardMedal(Medals.NEGLIGENT);
- }
- addStat(Stats.VALUE_OF_BUILDINGS_DESTROYED, b.getFeature().getInitialValue());
- } else {
- valueOfBuiltBuildings -= b.getFeature().getInitialValue();
- }
- }
- }
- /**
- * Called when any building worth attacking takes actual damage
- */
- public void onBuildingDamaged() {
- anyDamaged = true;
- }
- /**
- * Is the level still active? This is the case when we're in {@link #PHASE_NORMAL} phase and either it's a survival mode game
- * (the level is always active), or the timer's still timing.
- * @return true if the level is still active
- */
- public boolean isLevelActive() {
- return phase == PHASE_NORMAL && (metaState.gameMode == GAME_MODE_SURVIVAL || levelTick < getLevelDuration());
- }
- public Building getBase() {
- return base;
- }
- public Building getNextUnminedCrystal() {
- if (unminedCrystalList.size() == 0) {
- return null;
- }
- Building ret = unminedCrystalList.remove(0);
- unminedCrystalList.add(ret);
- return ret;
- }
- public void addUnminedCrystal(Building crystal) {
- unminedCrystalList.add(crystal);
- }
- public void removeUnminedCrystal(Building crystal) {
- unminedCrystalList.remove(crystal);
- }
- public int getBezerkTick() {
- return bezerkTick;
- }
- public int getFreezeTick() {
- return freezeTick;
- }
- public int getShieldTick() {
- return shieldTick;
- }
- public int getAvailableStock(BuildingFeature bf) {
- return metaState.getAvailableStock(bf);
- }
- public void addAvailableStock(BuildingFeature bf, int n) {
- metaState.addAvailableStock(bf, n);
- GameScreen.getInstance().enableBuildings();
- }
- public float getGidrahDeathRatio() {
- if (aliensSpawnedAtLevelEnd == 0) {
- return 0.0f;
- }
- return (float) aliensVanquishedSinceEndOfLevel / (float) aliensSpawnedAtLevelEnd;
- }
- private void onSomethingInterestingHappened() {
- somethingInterestingHappenedTick = 0;
- }
- /**
- * @return an unmodifiable map of the medals
- */
- public Map<MedalFeature, Integer> getMedals() {
- return Collections.unmodifiableMap(metaState.medals);
- }
- /**
- * Award a medal
- * @param medal
- * @return a MedalFeature if the medal was awarded, null if not
- */
- public MedalFeature awardMedal(String medal) {
- MedalFeature mf = MedalFeature.getMedals().get(medal);
- if (mf == null) {
- if (Game.DEBUG) {
- System.out.println("Warning: medal "+medal+" not found");
- }
- return null;
- }
- Integer n = metaState.medals.get(mf);
- if (n == null) {
- n = Integer.valueOf(1);
- } else {
- if (mf.isRepeatable()) {
- n = Integer.valueOf(n.intValue() + 1);
- } else {
- return null;
- }
- }
- metaState.score += mf.getPoints();
- addMoney(mf.getMoney());
- RankFeature newRank = RankFeature.getRank(metaState.score);
- boolean storeSteamStats = false;
- if (newRank != metaState.rank) {
- System.out.println("New Rank: "+newRank.getTitle());
- metaState.rank = newRank;
- addMoney(newRank.getPoints() / 10);
- if (!suppressMedals) {
- GameScreen.getInstance().showHint(newRank.getHint());
- }
- SFX.newRank();
- if (Game.isUsingSteam() && Steam.isCreated() && Steam.isSteamRunning()) {
- try {
- Steam.getUserStats().setAchievement(newRank.getName());
- } catch (SteamException e) {
- System.err.println("Failed to set achievement "+newRank.getName()+" due to "+e);
- }
- storeSteamStats = true;
- }
- }
- metaState.medals.put(mf, n);
- System.out.println("Awarded "+medal+" ("+n+")");
- if (mf.isSteam() && Game.isUsingSteam() && Steam.isCreated() && Steam.isSteamRunning()) {
- try {
- Steam.getUserStats().setAchievement(mf.getName());
- storeSteamStats = true;
- } catch (SteamException e) {
- System.err.println("Failed to set achievement "+mf.getName()+" due to "+e);
- }
- }
- // Update medals earned this level too
- if (!mf.getSuppressHint()) {
- medalsThisLevel.add(mf);
- }
- // Now, if we're currently playing a level, pop up a hint saying what they just got
- if (phase != PHASE_END_OF_GAME && !mf.getSuppressHint() && !suppressMedals) {
- if (mf.getHint() != null) {
- if (Game.DEBUG) {
- System.out.println("Queued hint "+mf.getHint());
- }
- GameScreen.getInstance().showHint(mf.getHint());
- if (mf.isRepeatable()) {
- SFX.medalAwarded();
- } else {
- SFX.achievementUnlocked();
- }
- } else {
- System.out.println("Medal "+mf+" doesn't have a hint!");
- }
- }
- // Store steam stats
- if (storeSteamStats) {
- try {
- Steam.getUserStats().storeStats();
- } catch (SteamException e) {
- System.err.println("Failed to store steam stats due to "+e);
- }
- }
- return mf;
- }
- /**
- * @return the total score for all awarded medals
- */
- public int getScore() {
- return metaState.score;
- }
- /**
- * @return an unmodifiable map of all the medals earned in this level
- */
- public Set<MedalFeature> getMedalsEarnedThisLevel() {
- return Collections.unmodifiableSet(medalsThisLevel);
- }
- public RankFeature getRank() {
- return metaState.rank;
- }
- /**
- * Gets the value of a stat
- * @param stat
- * @return
- */
- public int getStat(String stat) {
- return addStat(stat, 0);
- }
- /**
- * Add a value to a stat
- * @param stat
- * @param n
- * @return the new stat value
- */
- public int addStat(String stat, int n) {
- return metaState.addStat(stat, n);
- }
- /**
- * @return text for the story screen in Endless mode
- */
- public String getStatsText() {
- boolean showAllStats = false;
- StringBuilder sb = new StringBuilder(256);
- if (getGameMode() == GAME_MODE_SURVIVAL) {
- sb.append(Game.getMessage("ultraworm.wormgamestate.stats_survival"));
- } else if (getGameMode() == GAME_MODE_XMAS) {
- if (getLevel() == 0) {
- // Goes in the ZX bot at the start...
- sb.append(Game.getMessage("ultraworm.wormgamestate.stats_xmas"));
- } else {
- // Goes on the Xmas victory screen at the end
- sb.append("{font:smallfont.glfont color:text-bold}");
- sb.append(Game.getMessage("ultraworm.wormgamestate.xmas.battle_statistics"));
- sb.append("{font:tinyfont.glfont}\n\n");
- int angry = getStat(Stats.ANGRY_SPAWNED);
- int bosses = getStat(Stats.BOSSES_SPAWNED);
- int gidlets = getStat(Stats.GIDLETS_SPAWNED);
- int spawned = getStat(Stats.ALIENS_SPAWNED);
- sb.append("{color:text-bold}"+spawned+" "+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_spawned"));
- if (angry > 0 || bosses > 0 || gidlets > 0 || showAllStats) {
- sb.append("\n\t\t {color:text}");
- int normal = spawned - (angry + gidlets + bosses);
- boolean addSpace = false;
- if (normal > 0 || showAllStats) {
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.normal_sized_aliens")+": "+normal);
- addSpace = true;
- }
- if (angry > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.large_sized_aliens")+": "+angry);
- addSpace = true;
- }
- if (gidlets > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.tiny_sized_aliens")+": "+gidlets);
- addSpace = true;
- }
- if (bosses > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.bosses")+": "+bosses);
- }
- }
- int vanquished = getStat(Stats.ALIENS_VANQUISHED);
- sb.append("\n{color:text-bold}"+vanquished+" "+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_vanquished"));
- int shot = getStat(Stats.ALIENS_SHOT);
- if (vanquished != shot || showAllStats) {
- int vanquishedCount = 1;
- sb.append("\n\t\t {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_shot")+": "+shot);
- int crushed = getStat(Stats.ALIENS_CRUSHED);
- if (crushed > 0 || showAllStats) {
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_crushed")+": "+crushed);
- vanquishedCount++;
- }
- int blownUp = getStat(Stats.ALIENS_BLOWN_UP);
- if (blownUp > 0 || showAllStats) {
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_blown_up")+": "+blownUp);
- vanquishedCount++;
- }
- int fried = getStat(Stats.ALIENS_FRIED);
- if (fried > 0 || showAllStats) {
- vanquishedCount++;
- if (vanquishedCount>3) {
- vanquishedCount=0;
- sb.append("\n\t\t");
- }
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_fried")+": "+fried);
- }
- int nuked = getStat(Stats.ALIENS_SMARTBOMBED);
- if (nuked > 0 || showAllStats) {
- vanquishedCount++;
- if (vanquishedCount>3) {
- vanquishedCount=0;
- sb.append("\n\t\t");
- }
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.aliens_nuked")+": "+nuked);
- }
- }
- int alienAttacksOnBuildings = getStat(Stats.ALIEN_ATTACKS_ON_BUILDINGS);
- if (alienAttacksOnBuildings > 0 || showAllStats) {
- String msg = Game.getMessage("ultraworm.wormgamestate.xmas.alien_attacks");
- msg = msg.replace("[num]", String.valueOf(alienAttacksOnBuildings));
- msg = msg.replace("[value]", String.valueOf(getStat(Stats.VALUE_OF_BUILDINGS_DESTROYED)));
- sb.append(msg);
- }
- sb.append("\n{color:text-bold}"+getStat(Stats.BUILDINGS_BUILT)+" "+Game.getMessage("ultraworm.wormgamestate.xmas.buildings_built"));
- sb.append("\n\t\t {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.buildings_destroyed")+": "+getStat(Stats.BUILDINGS_DESTROYED));
- int recycled = getStat(Stats.RECYCLED);
- int sold = getStat(Stats.SOLD);
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.buildings_sold")+": "+sold);
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.xmas.buildings_recycled")+": "+recycled);
- int buildCosts = getStat(Stats.VALUE_OF_BUILDINGS_BUILT);
- sb.append("\n {color:text-bold}\\$"+buildCosts+" "+Game.getMessage("ultraworm.wormgamestate.xmas.money_spent"));
- }
- } else if (getLevel() == 0) {
- sb.append(Game.getMessage("ultraworm.wormgamestate.stats_level0"));
- } else {
- sb.append("{font:smallfont.glfont color:text-bold}");
- sb.append(Game.getMessage("ultraworm.wormgamestate.battle_statistics"));
- sb.append("{font:tinyfont.glfont}\n\n");
- int angry = getStat(Stats.ANGRY_SPAWNED);
- int bosses = getStat(Stats.BOSSES_SPAWNED);
- int gidlets = getStat(Stats.GIDLETS_SPAWNED);
- int spawned = getStat(Stats.ALIENS_SPAWNED);
- sb.append("{color:text-bold}"+spawned+" "+Game.getMessage("ultraworm.wormgamestate.aliens_spawned"));
- if (angry > 0 || bosses > 0 || gidlets > 0 || showAllStats) {
- sb.append("\n\t\t {color:text}");
- int normal = spawned - (angry + gidlets + bosses);
- boolean addSpace = false;
- if (normal > 0 || showAllStats) {
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.normal_sized_aliens")+": "+normal);
- addSpace = true;
- }
- if (angry > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.large_sized_aliens")+": "+angry);
- addSpace = true;
- }
- if (gidlets > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.tiny_sized_aliens")+": "+gidlets);
- addSpace = true;
- }
- if (bosses > 0 || showAllStats) {
- if (addSpace) {
- sb.append(' ');
- }
- sb.append("{color:text}"+Game.getMessage("ultraworm.wormgamestate.bosses")+": "+bosses);
- }
- }
- int vanquished = getStat(Stats.ALIENS_VANQUISHED);
- sb.append("\n{color:text-bold}"+vanquished+" "+Game.getMessage("ultraworm.wormgamestate.aliens_vanquished"));
- int shot = getStat(Stats.ALIENS_SHOT);
- if (vanquished != shot || showAllStats) {
- int vanquishedCount = 1;
- sb.append("\n\t\t {color:text}"+Game.getMessage("ultraworm.wormgamestate.aliens_shot")+": "+shot);
- int crushed = getStat(Stats.ALIENS_CRUSHED);
- if (crushed > 0 || showAllStats) {
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.aliens_crushed")+": "+crushed);
- vanquishedCount++;
- }
- int blownUp = getStat(Stats.ALIENS_BLOWN_UP);
- if (blownUp > 0 || showAllStats) {
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.aliens_blown_up")+": "+blownUp);
- vanquishedCount++;
- }
- int fried = getStat(Stats.ALIENS_FRIED);
- if (fried > 0 || showAllStats) {
- vanquishedCount++;
- if (vanquishedCount>3) {
- vanquishedCount=0;
- sb.append("\n\t\t");
- }
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.aliens_fried")+": "+fried);
- }
- int nuked = getStat(Stats.ALIENS_SMARTBOMBED);
- if (nuked > 0 || showAllStats) {
- vanquishedCount++;
- if (vanquishedCount>3) {
- vanquishedCount=0;
- sb.append("\n\t\t");
- }
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.aliens_nuked")+": "+nuked);
- }
- }
- int alienAttacksOnBuildings = getStat(Stats.ALIEN_ATTACKS_ON_BUILDINGS);
- if (alienAttacksOnBuildings > 0 || showAllStats) {
- String msg = Game.getMessage("ultraworm.wormgamestate.alien_attacks");
- msg = msg.replace("[num]", String.valueOf(alienAttacksOnBuildings));
- msg = msg.replace("[value]", String.valueOf(getStat(Stats.VALUE_OF_BUILDINGS_DESTROYED)));
- sb.append(msg);
- }
- sb.append("\n{color:text-bold}"+getStat(Stats.BUILDINGS_BUILT)+" "+Game.getMessage("ultraworm.wormgamestate.buildings_built"));
- sb.append("\n\t\t {color:text}"+Game.getMessage("ultraworm.wormgamestate.buildings_destroyed")+": "+getStat(Stats.BUILDINGS_DESTROYED));
- int recycled = getStat(Stats.RECYCLED);
- int sold = getStat(Stats.SOLD);
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.buildings_sold")+": "+sold);
- sb.append(" {color:text}"+Game.getMessage("ultraworm.wormgamestate.buildings_recycled")+": "+recycled);
- int buildCosts = getStat(Stats.VALUE_OF_BUILDINGS_BUILT);
- sb.append("\n {color:text-bold}\\$"+buildCosts+" "+Game.getMessage("ultraworm.wormgamestate.money_spent"));
- }
- return sb.toString();
- }
- public void setAwesome() {
- awesome = true;
- }
- public boolean isAwesome() {
- return awesome;
- }
- public int getCrystals() {
- return crystals;
- }
- public int getInitialCrystals() {
- return initialCrystals;
- }
- public PowerupFeature getCrappyPowerup() {
- return metaState.getCrappyPowerup();
- }
- public PowerupFeature getRandomPowerup() {
- return metaState.getRandomPowerup();
- }
- /**
- * @return an exotic powerup
- */
- public PowerupFeature getExoticPowerup() {
- return metaState.getExoticPowerup();
- }
- /**
- * @return a non-exotic powerup
- */
- public PowerupFeature getPowerup() {
- return metaState.getPowerup();
- }
- /**
- * @return an analysis of what went wrong
- */
- public String getAnalysis() {
- boolean lotsOfMoneyLeft = getMoney() > 750 * (getLevel() / LEVELS_IN_WORLD);
- int numBuildings = 0;
- int numTurrets = 0;
- for (Building b : getBuildings()) {
- if (b.canSell()) {
- numBuildings ++;
- }
- if (b instanceof Turret) {
- numTurrets ++;
- }
- }
- boolean lotsOfBuildings = numBuildings > getLevel();
- boolean lotsOfRefineries = totalFactories >= initialCrystals * 3;
- boolean lotsOfTurrets = numTurrets > spawnPoints.size() * 1.5f + getWorld().getIndex();
- boolean hasUnrefinedCrystals = unminedCrystalList.size() > 0;
- boolean lotsOfAliensSlain = aliensVanquishedValue > aliensSpawnedValue * 0.75 && aliensSpawnedValue > 1000;
- boolean lotsDestroyed = (float) valueOfDestroyedBuildings / (float) valueOfBuiltBuildings > 0.5f;
- boolean hasPowerups = false;
- for (Integer i : metaState.powerups.values()) {
- if (i > 0) {
- hasPowerups = true;
- break;
- }
- }
- class Message implements Comparable<Message> {
- int priority;
- String msg;
- public Message(int priority, String msg) {
- this.priority = priority;
- this.msg = msg;
- }
- @Override
- public int compareTo(Message o) {
- if (o.priority > priority) {
- return 1;
- } else if (o.priority < priority) {
- return -1;
- } else {
- return 0;
- }
- }
- }
- List<Message> messages = new ArrayList<Message>();
- if (!lotsOfTurrets) {
- messages.add(new Message(700, Game.getMessage("ultraworm.wormgamestate.hint1")));
- }
- if (lotsDestroyed) {
- messages.add(new Message(800, Game.getMessage("ultraworm.wormgamestate.hint2")));
- } else if (valueOfBuiltBuildings > 2500) {
- messages.add(new Message(600, Game.getMessage("ultraworm.wormgamestate.hint3")));
- }
- if (!lotsOfAliensSlain && lotsOfRefineries) {
- messages.add(new Message(200, Game.getMessage("ultraworm.wormgamestate.hint4")));
- }
- if (hasUnrefinedCrystals) {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint5")));
- }
- if (!lotsOfRefineries && (getLevel() > 4 || getGameMode() == GAME_MODE_SURVIVAL)) {
- messages.add(new Message(900, Game.getMessage("ultraworm.wormgamestate.hint6")));
- }
- if (hasPowerups) {
- messages.add(new Message(500, Game.getMessage("ultraworm.wormgamestate.hint7")));
- }
- if (!lotsOfMoneyLeft) {
- if (lotsOfBuildings) {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint8")));
- } else {
- if (isResearched(ResearchFeature.CONCRETE)) {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint9")));
- } else if (isResearched(ResearchFeature.TANGLEWEB)) {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint10")));
- } else if (isResearched(ResearchFeature.MINES)) {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint11")));
- } else {
- messages.add(new Message(100, Game.getMessage("ultraworm.wormgamestate.hint12")));
- }
- }
- } else {
- messages.add(new Message(1000, Game.getMessage("ultraworm.wormgamestate.hint13")));
- }
- if (getLevelFeature().getBosses() != null) {
- if (getLevelFeature().getBosses().getNumResources() == 1) {
- messages.add(new Message(900, Game.getMessage("ultraworm.wormgamestate.hint14")));
- } else {
- messages.add(new Message(900, Game.getMessage("ultraworm.wormgamestate.hint15")));
- }
- }
- StringBuilder sb = new StringBuilder(256);
- sb.append("{color:text-bold}");
- sb.append(Game.getMessage("ultraworm.wormgamestate.battle_analysis"));
- sb.append(":{color:text}");
- Collections.sort(messages);
- int count = 0;
- for (Message m : messages) {
- sb.append("\n\t\t");
- sb.append(m.msg);
- if (++ count == 3) {
- break;
- }
- }
- return sb.toString();
- }
- public float getScavengeRate() {
- int rate = Worm.getGameState().isResearched(ResearchFeature.FINETUNING) ? 1 : 0;
- rate += Worm.getGameState().isResearched(ResearchFeature.EXTRACTION) ? 1 : 0;
- return config.getScavengeRate()[rate];
- }
- // public MapGeneratorParams getMapGeneratorParams() {
- // return new MapGeneratorParams( this.getBasicDifficulty(), this.getGameMode(), this.getLevel(), this.getLevelFeature(), this.getLevelInWorld(), this.getMoney(), this.getResearchHash(), this.getWorld() );
- // }
- /**
- * Hax! This returns true if we want the level generator thread to generate a new level, or false if not.
- * @return
- * @see #initXmas(boolean)
- */
- public boolean isXmasReset() {
- return xmasReset;
- }
- }
|