From 29be45b198fd5ef407e475ec7696f416acb9686b Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 17 Dec 2012 00:33:47 +0000 Subject: [PATCH] Added preliminary easter-egg mode. It still needs a icon (battle mode used atm), and a better easter egg model (atm bunny from snow mountain, ... whith turns out has lost the black nose). One track has easter eggs added (math class). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12281 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/gui/mode_easter.png | Bin 0 -> 11769 bytes data/items.xml | 2 + data/models/easter_egg-icon.png | Bin 0 -> 30346 bytes data/models/easter_egg.b3d | Bin 0 -> 21475 bytes data/stk_config.xml | 5 +- sources.cmake | 2 + src/ide/vc9/supertuxkart.vcproj | 8 + src/items/item.cpp | 43 +++- src/items/item.hpp | 4 +- src/items/item_manager.cpp | 2 +- src/items/projectile_manager.cpp | 2 +- src/karts/controller/ai_properties.cpp | 8 +- src/karts/moveable.cpp | 3 + src/modes/easter_egg_hunt.cpp | 203 ++++++++++++++++++ src/modes/easter_egg_hunt.hpp | 74 +++++++ src/modes/linear_world.cpp | 24 +-- src/modes/three_strikes_battle.cpp | 16 +- src/modes/world.cpp | 2 +- src/race/race_manager.cpp | 3 + src/race/race_manager.hpp | 28 ++- .../dialogs/race_paused_dialog.cpp | 2 +- src/states_screens/race_gui_base.cpp | 15 +- src/states_screens/race_gui_base.hpp | 10 +- src/states_screens/race_setup_screen.cpp | 39 +++- src/states_screens/tracks_screen.cpp | 6 + src/tracks/check_lap.cpp | 8 +- src/tracks/track.cpp | 86 +++++--- src/tracks/track.hpp | 19 +- 28 files changed, 500 insertions(+), 114 deletions(-) create mode 100644 data/gui/mode_easter.png create mode 100644 data/models/easter_egg-icon.png create mode 100644 data/models/easter_egg.b3d create mode 100644 src/modes/easter_egg_hunt.cpp create mode 100755 src/modes/easter_egg_hunt.hpp diff --git a/data/gui/mode_easter.png b/data/gui/mode_easter.png new file mode 100644 index 0000000000000000000000000000000000000000..08e2d4ee3baf01259fe320e09ea1b7d5fee83387 GIT binary patch literal 11769 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iXe^ z76}U?y8s#g~k%e`B+aj&@ILP8A~k_Q9`0gM3? zAYen1M@xXvF%W7Xl$X##Gsb{1*rvGPDtD{PvU-=c-#hP*m8D&6k#;2;Iq}iwem>e; zX6DZMoigXloq^MInoiScI!&kPH2pV{Xz%)fi~-YyP#1z24`culr@O7&v$aMb4@t=u zsaHPC&CM+g82|(O3><}`z64A;-Jz#4Nf+?9D4T8Np0cv04gp|5zkb&X$y0#wbO-*& zP!5{z{G6hky+HvmuwTDlBYDkV33|Pr$jHdkUD?gaYPI5YI{jTL*K6t-hl+}h`31nx zzJ2?On8wV~PVeh;AtgidL> zzjsP+di3nc#&5pyti4xFUF~aL8emXH|I4J1Zyf*Kt5+{R{Pa^4MG4q=M`!4LYB+T5QffDB#8p>M&F5cG`0!tY zzm%Ut20UcvjsSlF8`2S`gw*~{yi<_28-&Cpz$C!fe0csgXe!R#yD4729JQgr4GbZe zIBBvcRP=f&M*t`u@7LS&eG?Otf;PVJ(Z_L=mU{J3&F5d@C@)7!iL<&IdvP(2iVB={ z^=K|jgfL|a=|BbI&^I1Tz&3?29i6myy z1k!H4k>aOTwOrF|HXJ3TI7&(bzMw8Hj)?yKi5@+QsLWABWoDv_kMFh&IoW_R2tQ00 z{z0IV$F)@88ua0`wqg5@fKO-+XUk(fF1-}Z;iTmG7lOI@-d=899gVwoVcE44rP)TA z`}QGf)F>jxjwSlcGf`q=yP<@i9H1ElC?bgTdz{dB!1CyWwL8#Q-*meaH*ZEU8i<%Oh3F-hpdUN-Ct=75FR4v2hV(Q<)~=wozlB!Jw_m5KSX%P>rx=B)?2nkn+9)i+|%+33Ic3^c9Xdo`~Xgz5tXuphd}D1^y` zwA+2IMGP5=F(ZTIrAx79Wl_3fC9xM@Ow{!09wx#}^wg_?B%@cm|L)~>~R z=y2E_E_pfV^qm9bMwek<>UU&{sS=nwG$7MJy6A(z+ zBZm#8Y4;wV^U0T7)Lbh>j2eacp@*n`@g*#4*OGAa&FGVpeV#F;rDMGKB9bn?2wPqr zHEY*W^U){B#)h!ES0E%E_Ci7Rm%{%WRYimR9AXDaO5|`gX^@D%LHEA-;o&OUDd*ulMluS(QGzyh)!cy^P zFCuzktBN%b9!%c{?nNky-*B60)F^tbdIo3lQ7V=#!mV#h<%0gCAAIAXB&hT{VS9J(ty z`u+7`8n$i&sSz`IGU)Ze8)-5TcjHYsva+bT=N?ScrV)MRRS2^=VB-{%i5^Rr5<6!$ z6%YRvH8;0ozF}@o%b+;s`lT4Y{)+nh@4F7yF9LKcgKAHM&Nty{NJR#J-9Y9%2tfdK;saOUhe z4836)rZZ>J`0#@mKOaKG4L6`9^$0xt(d$WCxsuxWIIQo!+m0uwVcoQmsGpzHI({BM zf%qGiQTx{ivETJ4H)v0oXv&i=;o(v{!@w{i>{7Ds%XPf^>fdQ>@b=_ON=n$jZ$GO) zSxx5X(JWoIjMSH2!S?dY)cpD?w3%m;bla^6eSl^OLEO?Cps^AAXP*TJ;M&i;003Z^ zGL@Lz9OSAea4f&ATQcOt0ZoSP1Zt`plB!ZQji;V^id9cP<-`28l(lCMw=Q4Ko`VO8 zShkF~zx)}wZ40^QoQrkCH-XhI5Oec#^aF#>Pqci!9_PV>z9Wra{tuBh8_MSII+L{R zgenfll$^L^bWk7Q@XyaB|EA@XJ^um?8#kd=RRwMQv#VCIe%-nbW71}`asR#da$x^{ zl+4j2z40dc_;~XEbT7xQy$)AJh2O>tlZohCZwnIfbDM$M#~$(3VnPu0z=K4*^*W-a zx{I0835JC9aOi*vgn$-9m>3`b3n26O?{UM1k-8@fXIUB6y?d$u`fF<5ew&81U*J4& z0IjMDeSCaNGG^n34ZQW{o1q78G>zT6_b_kXJd6<$L`OsH&v?{r3@7RhTDC z@QEEL$;qhs1!x8ND94i@f|mak0cv3(LV{`XWN!?Z%_t@l&NZuXO`6h0c0hI?bKaqfA0KLtB!p2ovLeu)Ms9p6m_N+ZfDY4t_yz{_rHclhPlsg&{bB28X@f&NXI^1_|rF_>wx0VOOiR70j7Chq?3S6CE8* zc1||${_AbZ%F2B1UAyKpF8swsL`6jrJ9jp=9j$0}Su9jN{x}VmG}Ja0b6DO1r68H(JxrTzD}Sg^186z6B3dILQ&65BP`f!X}i zM{B~WwsRE+HUakFIeUFd3Lt1|Y~sif-z?s&S+kfsZyu_qp=uhMrlF}S5#|VPz5RA{ ze#YUuckM(X(Wj*#Os2qoLtP!Vf4@)Towwua0P}+a*xIF z02EaXj-2>-B$9&sd^A6~>4l3IH#6PMcvV$fz>t!f%9t^}6F72n^FV@7bQn@oPhK!& z`?izMkPaS!^9SL0DIq6=f=Etu6iBG6tM_|-;J|^+Om{Qh4TRQXfS+-EeO+x!V|86Q z@2?%w?b{nZQ#!$rjsdERGD+ctf`e*+$S5QdtKAYXYNx51e|shIYXYoRYfHt#bn?DT zS1QVpP6rqa-NwFm*%wSQcwVX#8Xy`Z#6Qjl*yov; z*q9bc&>9*~T4!f#uy4c04%qiVN9Uy6f8gfiDN*Fq97!rwUwc-l$@km#x*tLp* z8}$)X2|<(HaZ(u~!%9Wdsjuil0)Q)!Jv@^Yzz$%N#pqEJ&~)$wsy_3JI4qV4I@nCPO5T=}lOKAjN28-mkAb z=?ppPKnukQbQyyKzZgHw@cQ&-2ec%PTLvNMvNB-)P}+N=Zp! z`yZ~*;?5sVo#hJk|ylaqbKe_2jvQ04<%aN&h0ih|TM8UtvEP)G$1D>`;7I(8~L z4l6o5$0SjT!Ugl@viRz2+#?d%4L=4u39GOK1b|(qW2atEs;1IIlYVW5{qwcxMvMSp z>9S?qb>|&8!uaZE?ASAydFCvnlr(3#g$lhtS5ESTi6e$XMLSdhx!{R4hJSaAn zsWYZCd O3tq`?#E=sOw2;3GkR}uFnvF;y&`U{gP0~x#=q)vRsTwgzV!!!@flDsI zoSI5{S{m0aUCOhoR{4z#2BNgIG_GH^%sr~mG-`sRlpBPgUJ+C)3Y9{kLQyDJ1jRz3 zA;8=Koe&I+i(}&CNlg6NIrQq)tHTWa<6U`aWAtOdGXz~>L4jP2fXzX~`Hs4TD zQO@=sw*he7^*0a`8`JHjJRIEUgCS+&z8)X;tV^dQjYuB!6`CVF4!jK_DPpZq` z)j*Rn3;=}d^c;UGHZG2tvt|cxuSXTb&sxxlrgR-c)~;ED&1xgP2OO<{(voAL=iR%V z6Ir{LW&9t$ji%P#>_K)m$&O+QyS{)dGFn~F&PARU!k$|F~PCo z690((i6p$Kv5C668XV2Dw)6%)X0sWS$xK8<1X0mZ7z_qXCR2<5)7FPkR2k8Z29TWa z4;;E!N^Za97AzJEFFf}wPp*2_XJxF8H090L|3O2212)AiT!+v{&& z?)>>3em*ZZhtEG-LuwLScP^NXl9ByjZ(cr)4Gly`N1wQNlC9Cxs;WvNBFvDIE~v*TEsrknP+jcp=Y_J^#WBiEmyHpvhw4$;Th%f&1>EGuirPUWR#6cprPcUT!RbTHGVPveYnU-vrkuhM-X*z)gric2^jR?8Spe4 z1?NqNx7Jm$;p_FxnKv)w_o}I?#%i;WIXaVpgZk5*DEQ~$$ZqzjY{wciVd6w~?cBlF zI|WxPl$i8z?a$#iXKQTUFW9^v3Q7SX8J+KThMuPXu1z`@NFO&uR&Mpa_^Y z!hOi*bI0p$o96J;em&yhmS0F7`e!3|ue^iX?pVRF;lus5-QjSsZOayp6&I16oz1qb zt@9+toN)$&2M<0)0D$afyMlE56Rh4Ty)j3aIZ|x%vgaK(ac$SglyKQxsH%gPKda*I zJMW-h{{i&v*O!EZ1nhP@l@*ob=jBpWS&8Z=|1omZsBXvn_Cvv4#E_rDVT_56p{~(} z)H=@O!1uW|#qtYa&KP)kjpV!ix#Z<~FPUpL3I?Z12Biv865*xK+=X89%S*ZKjyvd% z)J`Z^c3;U4(lkxeXl!gCDH`u(^4ejtY^Pc&A+sMmb%Vg_fWk6Cbpr??Nlg@_^#DZ( z8m;iF2i*l+e90x;cE=qjeRy{QH9+VLIoWjZzyYjQ8rq-In>Mm=Dk~s;sPF)l*LZ@T)n( z#{|6l4Qx5s@%Pdx?gf`UyTZ3yL<=&W|5UPJ4`hxW&5FD4>ekHfqz}-&NYgaF`*str z|NRxJYihV+zF=s28)iwkbQYu}2}-M>&H`HVa@t?-hP+Z==Kt|mFn$n7Df};>?r|{6b%Y5Xx>8}*Xo5PDo=-jejs^%Gc<8~C6373q0)VD!6c-nfpPx^D zULJY5IUG840GrjF6E_(IznB46FOc-<;W54sqOJi}Zlup1e+BXgYoa zL;k#?tUTCT2n!c2^t;jKX#jLmy^FksSZ~P>IErXK_sJIbKTCdj=_#c}PYD1hib8sNA1?sh ze7@kS`J#FM9MP)MW&7&-$T7J49~wuFdEavO1i>FK6_^bE&4<@eu}wYuiX;ZTp5e{k zNt`OAoGJ~y=l%zH@UM?Daq?t@5Ip^%~u*qDNhN<@00`pz>uLsS#j4Nc=XAq7<k56FM>^Y>Qrm}bMKEB^)=TNa^?ik@l zbW3DUG&_CnBQ;5IDGI7$RZr5kKcI{%@7Ow@hf-e+#D$tp;X7l7T&oN}^P&Q=2pZ_I; zs_Q5dJoQ_J4_7MOeUZY1fz7^y27^-sf4;1>J5&w+w#Lt94<2UWIIyH9m_J6LN1VbN zuf4{hg9kgfXv1j}&}oW`i{p>?+($;=3_ji}*_qS6y7rp2rnTNPDnpQ#)Ec=vS}DDl z>}I^LkAVce0=J(haJpRFy8LF!O3VCCUGq{Ro!ub23&3>B0{|d0GLjo^ycvM^zt@5? z*`Fj!4<_qGYiEw=BfOaG&mZud{&?mv!4RX=`^#$2h)En z000IL8A?P%1iSNOKqfm~!6kX)K1pHoPHZLv-10M>50m|A5l@g@f0m9V(-e-ClbY_04XpWOb;z4ac`XDT z#u#AIFMa#DItKRC*j*rLu!7AAdL2ZYV8TE_Vzi)tFTv~)3Q;BxmG4pK_Xj1P@75SH zbSQJ?&84okj>{o zd)G4B&n>|w_v<|#Nc6l%(TsyMxHcNc#2fNAEH2utiBp3Gcl9 zPvW8k^G3Cu1K{qK2tE92hK^s&2tJP9) zeeB=2pM(4N^TQGEZF5{M7r(voDqeo=HHMEE-a)2|zzK*pSA&76T@xTAs^?8nQIRC~ zOroi&iTb*FELICPn+=!4fy?D;$)hWZKv8rU40;SkBSwP>y}^K?`Dl+E&E+{APFyYr zHk%EH(}~nH3{OCguW3|{=c8(6CPWbvevSTV$%AkEs zS)Kbw@7}#V?v*XW(djd1Fn#8XmL?V-JxW1A0Y{G(akS_t|91m{9pFL|n|Di@q{4i)7U z0Bp&YeDtHnjy#D=*!NXAc`K>vY*D5%!6YOTr@&$}qDmH|V=?`>7tmMa-KY7}>_ zT#3P8KuY)T=U#Y$L4yXhs>)*}VfIDfy%7C>VBLC;#bu@5)rgc5hvwwn(zRavT2rxs z?R9$tY#tTHI)N>ALxv*V!VlhL2)3&|DRKX*tf=ye08X4ViE$IgF=+4*V%uyqVYOIz z@o#_QqYppi?zbf`U1LC}cq^LHTFDFRH6kM-xciTPLQ!;H&5KV+;E^Yv==VO6a(X*QZ%7A%?-O-g>zYXR4! zT}+|%7)`3xr_Ps-zQec?_xiVWp>G)B9X}QUl#6Un&4j>o5fn(Rzmj_<^N+XwkJz|a zABMN}uFVk<+8<#lU$5eDNtWJpJ-t&?`~p8NE{?yy{yKlT z{{a>)UffboV2khV%UDz^`DD6*E2ZtfkH6X?rX*?s{X9L2P`wLLJk52Una@7iCI!=F}Ky6i^2{%Sp+?9^D8 z*}9fs)=`ZO2Q~Wk>&MT|IX7r#t#7}6yzt7)Z5&wPx2;a;WM{)Zw$^2FpectUdkI>Y zS-UB5W4WX6HRyy}Gr3$YREOr*|JYKwo3ylEUF8Hy!q9W=$aI)s3JXZBzhYzK7(HeT zyLRlL)&lX7ZXQ1Or3)$H`eiqu=oFuK?x#u$7MP!Fm(n=A^QNHABVOxG!gAaoWmOj`2$mDfYdw1-I>MJlF@zO zrLR?Vio$hEZwO7>HB+UthL0-0;*09#K#f)Hl%t-p1hsZnt01a(P zL_t)U(_6;$$JI`>p9er%WwNHA=#LKlrTMc9Pj3=^=Vt*h*WRQD8qCD zr3d;tpRf{sOlBwd+zmr3#m2gqkULzeaimmYjxck@RaXU;7(ZI+pe2WOjXy9vaS--W zM{}fFgdpt-vl1q9VbWRjX;$x^D%!K8BaQjIlJ`Dydre`*kZZj(!Y}$S;G-j7VRPEO z%)s#Y0sg@pvJ>bri=^XB37*gvU7=oQLf1vrEgEnpvBnraIlP`&V>C-A{1OG>w|p7uh7my*iw=+z z2v5R;gDJe!ihm#(jjbC}FI&FcJ=Z}7_c`pUgFojy&+jJwhDkj~x12vzliLgccY?^D z)FWVi;xw*JUxG<7Hc#*JPgV9>{&x8PaNy+r%v(q@#e3|uDgydS)6&K=Ep2SOj1FVD z_~v1t2+sfZnbM9T@&l%@O+`DI#Mqb^#*H7(@DU>zK74pkh8%bH9?5xyTPI$_#Gb8N zEUea(ACpL6+u^EfMII+c}`tl9c0*e(LG$ zH~97Fi@cZ*u(fm#HP-rO=g-f4J^>e}EaakI3j>TU+&6z)xt+IiJ|W4Jz+>ZAK)s7c z9)5_OJ9hZpX(cHsiOVj(f~nJ{h3t5To(yVZ17vtH-!M%@J08SI&`MvHeMjHqbmsP% z;&b`MJ^yk`zwlq=_=J)CPue-n%=a~MHTF90JMaue4JBMR;8GT(PA4lXi^m^*BN-LFGD%e!LgSXCo+~?Z2 z#Xs_G(T{E`EToU;Z&Hjb>-RtI4^7&1f|QciazEsw@^uJ9iCM|wy0VE_L8Jo4~E zIGr7fDQx)W8>A-PyRG?gyfvv&=qTloHIE~<{?;jNf8Vyt^m2wuoET{iW6R`|c?>Y8C*N z54wzA5y><*HuCHP~8-aUBbwvmk_L|`} z49jag%2S8lAlFjVa({v`mMIBikrF=q;6tjbs=|sS{@lWV$xAZxBiGvSYtwbCJG8oO-+2gew}Z;!eHQ>^Uh=9q=`7}b~bI; z$olo`eH_Dvh6cV~{|yTkE@X(gKM)uIHoY@+4bYtyUlAKlspt z3?DJFrG?`sOl0&KV|n7y$9%N%wym2vYrz6~>63$Ykt0+M(CP$s?mKo7AZFiHVCqV( zw7F~-4yQ9{NLLEcs+-ze-(7i--IWKua|3=rlo6Qn(u;K0nr#(!` ztXZ?!wq+}uHg5E~|HzRe*d2Cy8WMxPo890H9ROWHQg)Kje!+BNw9<~U{YbSnI3xlL z^JF`5|Msr;HYXt^l$DqJG-vMId8n%D^GXuQ+FIs^zE6E!J-vIUV0Id?x%@4WFOg2Q^8k3X?C%`3<#`nD-9QC}ArXDK zD)~avjlJovDK_xCU90z_~v;?i6wiUD1l{fAVS3zzD0n-Cwz zRbsRGpJJxd>5x)lR!yk3IuG`=s!7f1UvNWOA3$|zXm$dTePLP|+Yn;Fecr<1&# zTvSy<)ihL9MO9TaRYg-Z4jnq|x9!onnbxHxCqOt;WiAKT}CpufR2x+t~G^G*{2(3(RzDElJ8Wl<{?x|dT z`uM8!k3asnnc*s$b{q&APN$1Ct3UC%KQc0sq~s)|l+-shy7^=C;Em1A6D2^LDI@@B zE^kI_j#h-J&0662|HVz^rxXCDoiQ0<(qXDlN&d!0RIch?CqCE+*#{);0mOYAs&<>v z;U4P*9H;NU`<9PB{0NszMO8I4RmJYG^YTkCkei$9bN|p`!&^oj)eZGtQtt+WifUKU zJ9M4*0aS-{&qtR*9Pehkqq@{n3IK`miQM}8+j;!4$55;;V)r|V&K6ixbyzcWIAcRt zC&5quc&62MmLA~zf%6$QY#7PO$y8QWdOiNm+y7+q58snHdJHa?gB{zqQ&Cajx2hR4 zX97^%R8FI%sns`YGh^7GbpZgR(~U0ttWedq1ElNJ+iYUwppiWG(BnMu^3xRU%|UTU zqViot<-2gk3GBUe*m@|q;+4Q30e675m+qt1-ax!5hQ()}%^R=3?sHFJVF87O1wqS6 zOHXI)*fRjwU3SpTn*bDObQYoyAls;Vw|dbWnvX-Moq_-Wh>wfs-rN4fJ@?k7W}&tQkdSgD~{x*!hF+t`CW_QSp^#*ZoR8c&~sl#!mnoy+b(O3BWwU3{_e zOY#n7<7}{@xWH7VVk-0SkIVvRtiTm1P$LywQ35p*G?Rj6^ez8`BVTgf;JL(`Vz}=5 z8+iD^KL=FvzHtn}uP(cs{sRUAuqA&d+1WXmof5?cx<-k(E|y?Au8}K>>|bwKy9cC^m`7CUMU?RDJZU zW)!Fkq7Y>PhnR^Mba=WHNF2udig<6YUOY`d@3K6Jc!>x*qSW394@fCP?|LG zFpb;Rf5){8E(ahXA%Q>q>3>=O)jGafw~n$h?+uKMMk5m@Oyv9ve?f9`YvL#8XfBh^ zoQ_d%ASNn?0e$*0q|YFtqoTc@f8!soc>_d8X&Vh7_Iv8_+?-s$9WXm%60Zzx2I2@-rb_$cr z<>HyApY+Z!B0p`>1fFLT;}dMa*~d>*S5>iR_ily_A4Y84X^B78sJOV8M;>~Rg9r9| zhG?3EUjM6_nwom>ofoAW*tg$CU|L(-G-Bi^`t|FN!Kgpov)!DW4i|-m`RvWg@|i{^ zkT+%*6g=DdyA2J=$QYmsWh;<$x-0*~d=KR6?1F-GJ)<^0k-)=+g}Is{<^egUyX-%T z{%LVKFCoaHqh2(+SFflhv-u$qOWXJgr|Hz9G9ksy*@b!U_}2>UQ2+k@hbo$O87Nah zjtAmT_i4AMT#4Kvgji>8ih65b#lFVCW+6lx*<)mMLqvn&bRTz5iiwG7+P81t>9PB1 b>KOe$%~d6>|BU?v00000NkvXXu0mjf=$0sy literal 0 HcmV?d00001 diff --git a/data/items.xml b/data/items.xml index 8c1b19905..32c1110f2 100644 --- a/data/items.xml +++ b/data/items.xml @@ -9,5 +9,7 @@ handled as one, so list it here --> + + diff --git a/data/models/easter_egg-icon.png b/data/models/easter_egg-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ed0fe91c21c42dd2637c618eaab5e44acc8892 GIT binary patch literal 30346 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 literal 0 HcmV?d00001 diff --git a/data/models/easter_egg.b3d b/data/models/easter_egg.b3d new file mode 100644 index 0000000000000000000000000000000000000000..7e44c955aace438d6e28cb59a7ea4207b766296a GIT binary patch literal 21475 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 literal 0 HcmV?d00001 diff --git a/data/stk_config.xml b/data/stk_config.xml index 018c465fb..2a0264751 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -110,8 +110,9 @@ - + Order: giftbox, banana, big-nitro, small-nitro, bubble-gum, trigger, + nolok-bubble-gum, easter egg --> + diff --git a/sources.cmake b/sources.cmake index 98bf4e1cd..63924f065 100644 --- a/sources.cmake +++ b/sources.cmake @@ -121,6 +121,7 @@ src/main.cpp src/main_loop.cpp src/modes/cutscene_world.cpp src/modes/demo_world.cpp +src/modes/easter_egg_hunt.cpp src/modes/follow_the_leader.cpp src/modes/game_tutorial.cpp src/modes/linear_world.cpp @@ -367,6 +368,7 @@ src/karts/skidding_properties.hpp src/main_loop.hpp src/modes/cutscene_world.hpp src/modes/demo_world.hpp +src/modes/easter_egg_hunt.hpp src/modes/follow_the_leader.hpp src/modes/game_tutorial.hpp src/modes/linear_world.hpp diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index a7021c81f..39fe03e28 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -700,6 +700,10 @@ RelativePath="..\..\modes\demo_world.cpp" > + + @@ -1886,6 +1890,10 @@ RelativePath="..\..\modes\demo_world.hpp" > + + diff --git a/src/items/item.cpp b/src/items/item.cpp index 83996fb5e..bd4d3f109 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -24,6 +24,7 @@ #include "graphics/irr_driver.hpp" #include "graphics/lod_node.hpp" #include "karts/abstract_kart.hpp" +#include "modes/easter_egg_hunt.hpp" #include "modes/three_strikes_battle.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" @@ -109,16 +110,23 @@ void Item::initItem(ItemType type, const Vec3 &xyz) m_deactive_time = 0; m_time_till_return = 0.0f; // not strictly necessary, see isCollected() m_emitter = NULL; - m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER); - m_disappear_counter = m_type==ITEM_BUBBLEGUM - ? stk_config->m_bubble_gum_counter - : -1 ; + m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER) && + (type!=ITEM_EASTER_EGG); + switch(m_type) + { + case ITEM_BUBBLEGUM: + m_disappear_counter = stk_config->m_bubble_gum_counter; break; + case ITEM_EASTER_EGG: + m_disappear_counter = -1; break; + default: + m_disappear_counter = -1; + } // Now determine in which quad this item is, and its distance // from the center within this quad. m_graph_node = QuadGraph::UNKNOWN_SECTOR; QuadGraph* currentQuadGraph = QuadGraph::get(); - // Check that QuadGraph exist ( it might not in battle mode for eg) + // Check that QuadGraph exist (it might not in battle mode for eg) if (currentQuadGraph != NULL) { QuadGraph::get()->findRoadSector(xyz, &m_graph_node); @@ -236,9 +244,15 @@ void Item::reset() m_collected = false; m_time_till_return = 0.0f; m_deactive_time = 0.0f; - m_disappear_counter = m_type==ITEM_BUBBLEGUM - ? stk_config->m_bubble_gum_counter - : -1 ; + switch(m_type) + { + case ITEM_BUBBLEGUM: + m_disappear_counter = stk_config->m_bubble_gum_counter; break; + case ITEM_EASTER_EGG: + m_disappear_counter = -1; break; + default: + m_disappear_counter = -1; + } if(m_original_type!=ITEM_NONE) { setType(m_original_type); @@ -319,7 +333,18 @@ void Item::collected(const AbstractKart *kart, float t) { m_collected = true; m_event_handler = kart; - if(m_type==ITEM_BUBBLEGUM && m_disappear_counter>0) + if(m_type==ITEM_EASTER_EGG) + { + m_time_till_return=99999; + EasterEggHunt *world = dynamic_cast(World::getWorld()); + assert(world); + world->collectedEasterEgg(kart); + if (m_node != NULL) + { + m_node->setVisible(false); + } + } + else if(m_type==ITEM_BUBBLEGUM && m_disappear_counter>0) { m_disappear_counter --; // Deactivates the item for a certain amount of time. It is used to diff --git a/src/items/item.hpp b/src/items/item.hpp index bd577ac94..7ce352796 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -73,7 +73,9 @@ public: ITEM_NITRO_SMALL, ITEM_BUBBLEGUM, ITEM_BUBBLEGUM_NOLOK, - + + /** For easter egg mode only. */ + ITEM_EASTER_EGG, /** An invisible item that can be used to trigger some behavior when * approaching a point */ diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp index 5f56cf09e..f6c51bda0 100644 --- a/src/items/item_manager.cpp +++ b/src/items/item_manager.cpp @@ -77,8 +77,8 @@ void ItemManager::loadDefaultItemMeshes() item_names[Item::ITEM_NITRO_BIG ] = "nitro-big"; item_names[Item::ITEM_NITRO_SMALL] = "nitro-small"; item_names[Item::ITEM_TRIGGER ] = "trigger"; - item_names[Item::ITEM_BUBBLEGUM_NOLOK] = "bubblegum-nolok"; + item_names[Item::ITEM_EASTER_EGG ] = "easter-egg"; const std::string file_name = file_manager->getDataFile("items.xml"); const XMLNode *root = file_manager->createXMLTree(file_name); diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp index f8e4f25ef..cdb75dde9 100644 --- a/src/items/projectile_manager.cpp +++ b/src/items/projectile_manager.cpp @@ -85,7 +85,7 @@ void ProjectileManager::update(float dt) he = next; } // Update this hit effect. If it can be removed, remove it. - if((*he)->updateAndDelete(dt)) + else if((*he)->updateAndDelete(dt)) { delete *he; HitEffects::iterator next = m_active_hit_effects.erase(he); diff --git a/src/karts/controller/ai_properties.cpp b/src/karts/controller/ai_properties.cpp index 2cc8366ba..fb2ccfd5d 100644 --- a/src/karts/controller/ai_properties.cpp +++ b/src/karts/controller/ai_properties.cpp @@ -27,13 +27,7 @@ float AIProperties::UNDEFINED = -99.9f; */ AIProperties::AIProperties(RaceManager::Difficulty difficulty) { - switch(difficulty) - { - case RaceManager::DIFFICULTY_EASY: m_ident="easy"; break; - case RaceManager::DIFFICULTY_MEDIUM: m_ident="medium"; break; - case RaceManager::DIFFICULTY_HARD: m_ident="hard"; break; - default: m_ident=""; break; - } + m_ident = race_manager->getDifficultyAsString(difficulty); m_max_item_angle = UNDEFINED; m_max_item_angle_high_speed = UNDEFINED; diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp index 112672762..30ceaee6a 100644 --- a/src/karts/moveable.cpp +++ b/src/karts/moveable.cpp @@ -69,6 +69,9 @@ void Moveable::updateGraphics(float dt, const Vec3& offset_xyz, Vec3 xyz=getXYZ()+offset_xyz; m_node->setPosition(xyz.toIrrVector()); btQuaternion r_all = getRotation()*rotation; + if(btFuzzyZero(r_all.getX()) && btFuzzyZero(r_all.getY()-0.70710677f) && + btFuzzyZero(r_all.getZ()) && btFuzzyZero(r_all.getW()-0.70710677f) ) + r_all.setX(0.000001f); Vec3 hpr; hpr.setHPR(r_all); m_node->setRotation(hpr.toIrrHPR()); diff --git a/src/modes/easter_egg_hunt.cpp b/src/modes/easter_egg_hunt.cpp new file mode 100644 index 000000000..5104bd09c --- /dev/null +++ b/src/modes/easter_egg_hunt.cpp @@ -0,0 +1,203 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "modes/easter_egg_hunt.hpp" + +#include "io/file_manager.hpp" +#include "karts/abstract_kart.hpp" +#include "tracks/track.hpp" + +//----------------------------------------------------------------------------- +/** Constructor. Sets up the clock mode etc. + */ +EasterEggHunt::EasterEggHunt() : WorldWithRank() +{ + WorldStatus::setClockMode(CLOCK_CHRONO); + m_use_highscores = false; + m_eggs_found = 0; +} // EasterEggHunt + +//----------------------------------------------------------------------------- +/** Initialises the easer egg hunt. + */ +void EasterEggHunt::init() +{ + WorldWithRank::init(); + m_display_rank = false; + + // check for possible problems if AI karts were incorrectly added + if(getNumKarts() > race_manager->getNumPlayers()) + { + fprintf(stderr, "No AI exists for this game mode\n"); + exit(1); + } + + const unsigned int kart_amount = m_karts.size(); + m_eggs_collected.resize(m_karts.size(), 0); + +} // EasterEggHunt + +//----------------------------------------------------------------------------- +/** Destructor. Clears all internal data structures, and removes the tire mesh + * from the mesh cache. + */ +EasterEggHunt::~EasterEggHunt() +{ +} // ~EasterEggHunt + +//----------------------------------------------------------------------------- +/** Check if a file easter_eggs.xml exists in the track directory, and if so + * loads that file and makes the easter egg mode available for this track. +*/ +void EasterEggHunt::readData(const std::string &filename) +{ + XMLNode *easter = file_manager->createXMLTree(filename); + if(!easter) + return; + + if(easter->getName()!="EasterEggHunt") + { + printf("Can't load easter egg file '%s' - no EasterEggHunt element.", + filename); + delete easter; + return; + } + + const XMLNode *data = NULL; + std::string difficulty_name; + RaceManager::Difficulty diff = race_manager->getDifficulty(); + for(unsigned int i=0; igetDifficultyAsString(diff); + data = easter->getNode(difficulty_name); + if(data) break; + diff = (RaceManager::Difficulty)(diff+1); + if(diff==RaceManager::DIFFICULTY_LAST) + diff = RaceManager::DIFFICULTY_FIRST; + } + if(!data) + { + delete easter; + return; + } + + m_time_limit = 9999; + data->get("time-limit", &m_time_limit); + + m_number_of_eggs = 0; + for(unsigned int i=0; igetNumNodes(); i++) + { + const XMLNode *egg = data->getNode(i); + if(egg->getName()!="easter-egg") + { + printf("Unknown node '%s' in easter egg level '%s' - ignored.\n", + egg->getName().c_str(), difficulty_name.c_str()); + continue; + } + World::getTrack()->itemCommand(egg); + m_number_of_eggs++; + } // for i getWorldKartId()]++; + m_eggs_found++; +} // collectedEasterEgg + +//----------------------------------------------------------------------------- +/** Update the world and the track. + * \param dt Time step size. + */ +void EasterEggHunt::update(float dt) +{ + WorldWithRank::update(dt); + WorldWithRank::updateTrack(dt); +} // update + +//----------------------------------------------------------------------------- +/** The hunt is over once all eggs are found. + */ +bool EasterEggHunt::isRaceOver() +{ + if(m_eggs_found == m_number_of_eggs) + return true; + if(m_time<0) + return true; + return false; +} // isRaceOver + +//----------------------------------------------------------------------------- +/** Called then a battle is restarted. + */ +void EasterEggHunt::restartRace() +{ + WorldWithRank::restartRace(); + + for(unsigned int i=0; i *info) +{ + const unsigned int kart_amount = getNumKarts(); + for(unsigned int i = 0; i < kart_amount ; i++) + { + RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i]; + std::ostringstream o; + //I18n: number of collected eggs / overall number of eggs + rank_info.m_text = StringUtils::insertValues(_("Eggs: %d / %d"), + m_eggs_collected[i], + m_number_of_eggs); + rank_info.m_color = video::SColor(255, 255, 255, 255); + } +} // getKartDisplayInfo + +//----------------------------------------------------------------------------- +/** Moves a kart to its rescue position. + * \param kart The kart that was rescued. + */ +void EasterEggHunt::moveKartAfterRescue(AbstractKart* kart) +{ + int start_position = kart->getInitialPosition(); + btTransform start_pos = getTrack()->getStartTransform(start_position-1); + + kart->getBody()->setCenterOfMassTransform(start_pos); + +} // moveKartAfterRescue diff --git a/src/modes/easter_egg_hunt.hpp b/src/modes/easter_egg_hunt.hpp new file mode 100755 index 000000000..980e9c238 --- /dev/null +++ b/src/modes/easter_egg_hunt.hpp @@ -0,0 +1,74 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef EASTER_EGG_HUNT_HPP +#define EASTER_EGG_HUNT_HPP + +#include "modes/world_with_rank.hpp" +#include "states_screens/race_gui_base.hpp" + +#include +#include + +class AbstractKart; + +/** + * \brief An implementation of World to provide an easter egg hunt like mode + * \ingroup modes + */ +class EasterEggHunt: public WorldWithRank +{ +private: + /** Keeps track of how many eggs each kart has found. */ + std::vector m_eggs_collected; + + /** A time limit for the hunt. */ + float m_time_limit; + + /** Overall number of easter eggs. */ + int m_number_of_eggs; + + /** Number of eggs found so far. */ + int m_eggs_found; +public: + EasterEggHunt(); + virtual ~EasterEggHunt(); + + virtual void init(); + + virtual bool isRaceOver(); + + // overriding World methods + virtual void restartRace(); + + virtual bool raceHasLaps(){ return false; } + virtual void moveKartAfterRescue(AbstractKart* kart); + + virtual const std::string& getIdent() const; + + virtual void update(float dt); + virtual void getKartsDisplayInfo( + std::vector *info); + + void updateKartRanks(); + void collectedEasterEgg(const AbstractKart *kart); + void readData(const std::string &filename); +}; // EasterEggHunt + + +#endif diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 238bafaa0..ef0db49fc 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -422,9 +422,7 @@ void LinearWorld::getKartsDisplayInfo( AbstractKart* kart = m_karts[i]; // reset color - rank_info.r = 1.0; - rank_info.g = 1.0; - rank_info.b = 1.0; + rank_info.m_color = video::SColor(255, 255, 255, 255); rank_info.lap = -1; if(kart->isEliminated()) continue; @@ -486,12 +484,15 @@ void LinearWorld::getKartsDisplayInfo( if(kart_info.m_race_lap>=numLaps) { // kart is finished, display in green - rank_info.g = rank_info.b = 0; + rank_info.m_color.setGreen(0); + rank_info.m_color.setBlue(0); } else if(kart_info.m_race_lap>=0 && numLaps>1) { - rank_info.g = rank_info.b = - 1.0f-(float)kart_info.m_race_lap/((float)numLaps-1.0f); + int col = (int)(255*(1.0f-(float)kart_info.m_race_lap + /((float)numLaps-1.0f) )); + rank_info.m_color.setBlue(col); + rank_info.m_color.setGreen(col); } } // next kart @@ -561,22 +562,15 @@ void LinearWorld::moveKartAfterRescue(AbstractKart* kart) info.getSector()->rescue(); int sector = info.getSector()->getCurrentGraphNode(); - kart->setXYZ( QuadGraph::get() - ->getQuadOfNode(sector).getCenter()); - - btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(sector) ); - kart->setRotation(heading); // A certain epsilon is added here to the Z coordinate, in case // that the drivelines are somewhat under the track. Otherwise, the // kart might be placed a little bit under the track, triggering // a rescue, ... (experimentally found value) float epsilon = 0.5f * kart->getKartHeight(); - + const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(sector).getCenter(); btTransform pos; - pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, - 0)); + pos.setOrigin(xyz+btVector3(0, kart->getKartHeight() + epsilon,0)); pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), m_track->getAngle(sector))); diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index 47432066e..522d142f6 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -438,24 +438,16 @@ void ThreeStrikesBattle::getKartsDisplayInfo( switch(m_kart_info[i].m_lives) { case 3: - rank_info.r = 0.0; - rank_info.g = 1.0; - rank_info.b = 0.0; + rank_info.m_color = video::SColor(255, 0, 255, 0); break; case 2: - rank_info.r = 1.0; - rank_info.g = 0.9f; - rank_info.b = 0.0; + rank_info.m_color = video::SColor(255, 255, 229, 0); break; case 1: - rank_info.r = 1.0; - rank_info.g = 0.0; - rank_info.b = 0.0; + rank_info.m_color = video::SColor(255, 255, 0, 0); break; case 0: - rank_info.r = 0.5; - rank_info.g = 0.5; - rank_info.b = 0.5; + rank_info.m_color = video::SColor(128, 128, 128, 0); break; } diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 03bf54af1..6d35d1c02 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -138,7 +138,7 @@ void World::init() // Load the track models - this must be done before the karts so that the // karts can be positioned properly on (and not in) the tracks. - m_track->loadTrackModel(this, race_manager->getReverseTrack()); + m_track->loadTrackModel(race_manager->getReverseTrack()); for(unsigned int i=0; igetMajorMode() != RaceManager::MAJOR_MODE_SINGLE) + if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX) { GUIEngine::RibbonWidget* choice_ribbon = getWidget("choiceribbon"); diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp index bc9040b95..758084b85 100644 --- a/src/states_screens/race_gui_base.cpp +++ b/src/states_screens/race_gui_base.cpp @@ -807,14 +807,15 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) int lap = info.lap; // In battle mode there is no distance along track etc. - if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES) + if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES || + race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG) { x = x_base; y = previous_y+ICON_PLAYER_WIDTH+2; } else { - LinearWorld *linear_world = (LinearWorld*)(World::getWorld()); + LinearWorld *linear_world = (LinearWorld*)(World::getWorld()); float distance = linear_world->getDistanceDownTrackForKart(kart_id) + linear_world->getTrack()->getTrackLength()*lap; @@ -870,15 +871,12 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) if (m_kart_display_infos[kart_id].m_text.size() > 0) { - video::SColor color = video::SColor(255, - (int)(255*info.r), - (int)(255*info.g), - (int)(255*info.b) ); core::rect pos(x+ICON_PLAYER_WIDTH, y+5, x+ICON_PLAYER_WIDTH, y+5); core::stringw s=info.m_text.c_str(); - font->draw(s.c_str(), pos, color, false, false, NULL, true /* ignore RTL */); + font->draw(s.c_str(), pos, info.m_color, false, false, NULL, + true /* ignore RTL */); } if (info.special_title.size() > 0) @@ -887,7 +885,8 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) core::rect pos(x+ICON_PLAYER_WIDTH, y+5, x+ICON_PLAYER_WIDTH, y+5); core::stringw s(info.special_title.c_str()); - font->draw(s.c_str(), pos, color, false, false, NULL, true /* ignore RTL */); + font->draw(s.c_str(), pos, info.m_color, false, false, NULL, + true /* ignore RTL */); } // draw icon diff --git a/src/states_screens/race_gui_base.hpp b/src/states_screens/race_gui_base.hpp index 72331cf26..bbe6ad4a5 100644 --- a/src/states_screens/race_gui_base.hpp +++ b/src/states_screens/race_gui_base.hpp @@ -53,16 +53,16 @@ public: */ struct KartIconDisplayInfo { - /** text to display next to icon, if any */ + /** Text to display next to icon, if any. */ core::stringw m_text; - /** text color, if any text */ - float r, g, b; + /** Text color, if any text. */ + video::SColor m_color; - /** if this kart has a special title, e.g. "leader" in follow-the-leader */ + /** If this kart has a special title, e.g. "leader" in follow-the-leader. */ core::stringw special_title; - /** Current lap of this kart, or -1 if irrelevant */ + /** Current lap of this kart, or -1 if irrelevant. */ int lap; }; // KartIconDisplayInfo diff --git a/src/states_screens/race_setup_screen.cpp b/src/states_screens/race_setup_screen.cpp index 970dd4895..1f74655af 100644 --- a/src/states_screens/race_setup_screen.cpp +++ b/src/states_screens/race_setup_screen.cpp @@ -29,10 +29,11 @@ #include "states_screens/race_setup_screen.hpp" -const int CONFIG_CODE_NORMAL = 0; +const int CONFIG_CODE_NORMAL = 0; const int CONFIG_CODE_TIMETRIAL = 1; -const int CONFIG_CODE_FTL = 2; -const int CONFIG_CODE_3STRIKES = 3; +const int CONFIG_CODE_FTL = 2; +const int CONFIG_CODE_3STRIKES = 3; +const int CONFIG_CODE_EASTER = 4; using namespace GUIEngine; DEFINE_SCREEN_SINGLETON( RaceSetupScreen ); @@ -53,19 +54,19 @@ public: // game mode changed!! m_parent->onGameModeChanged(); } -}; +}; // GameModeRibbonListener // ----------------------------------------------------------------------------- RaceSetupScreen::RaceSetupScreen() : Screen("racesetup.stkgui") { -} +} // RaceSetupScreen // ----------------------------------------------------------------------------- void RaceSetupScreen::loadedFromFile() { -} +} // loadedFromFile // ----------------------------------------------------------------------------- @@ -127,6 +128,13 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con race_manager->setNumKarts( race_manager->getNumLocalPlayers() ); // no AI karts; StateManager::get()->pushScreen( ArenasScreen::getInstance() ); } + else if (selectedMode == IDENT_EASTER) + { + race_manager->setMinorMode(RaceManager::MINOR_MODE_EASTER_EGG); + UserConfigParams::m_game_mode = CONFIG_CODE_EASTER; + race_manager->setNumKarts( race_manager->getNumLocalPlayers() ); // no AI karts; + StateManager::get()->pushScreen( TracksScreen::getInstance() ); + } else if (selectedMode == "locked") { unlock_manager->playLockSound(); @@ -142,7 +150,7 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con { StateManager::get()->escapePressed(); } -} +} // eventCallback // ----------------------------------------------------------------------------- @@ -167,7 +175,7 @@ void RaceSetupScreen::onGameModeChanged() { kartamount->setActivated(); } -} +} // onGameModeChanged // ----------------------------------------------------------------------------- @@ -228,7 +236,15 @@ void RaceSetupScreen::init() name4 += _("Hit others with weapons until they lose all their lives. (Only in multiplayer games)"); w2->addItem( name4, IDENT_STRIKES, RaceManager::getIconOf(RaceManager::MINOR_MODE_3_STRIKES)); } - + { + irr::core::stringw name1 = irr::core::stringw( + RaceManager::getNameOf(RaceManager::MINOR_MODE_EASTER_EGG)) + L"\n"; + //FIXME: avoid duplicating descriptions from the help menu! + name1 += _("Find all Easter Eggs"); + + w2->addItem( name1, IDENT_EASTER, + RaceManager::getIconOf(RaceManager::MINOR_MODE_EASTER_EGG)); + } w2->updateItemDisplay(); @@ -247,10 +263,13 @@ void RaceSetupScreen::init() case CONFIG_CODE_3STRIKES : w2->setSelection(IDENT_STRIKES, PLAYER_ID_GAME_MASTER, true); break; + case CONFIG_CODE_EASTER : + w2->setSelection(IDENT_EASTER, PLAYER_ID_GAME_MASTER, true); + break; } m_mode_listener = new GameModeRibbonListener(this); w2->registerHoverListener(m_mode_listener); -} +} // init // ----------------------------------------------------------------------------- diff --git a/src/states_screens/tracks_screen.cpp b/src/states_screens/tracks_screen.cpp index 391872cea..d84ad71e3 100644 --- a/src/states_screens/tracks_screen.cpp +++ b/src/states_screens/tracks_screen.cpp @@ -286,6 +286,9 @@ void TracksScreen::buildTrackList() for (int n=0; ngetTrack( n ); + if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG + && !curr->hasEasterEggs()) + continue; if (curr->isArena()) continue; if (curr->isInternal()) continue; @@ -313,6 +316,9 @@ void TracksScreen::buildTrackList() for (int n=0; ngetTrack( curr_group[n] ); + if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG + && !curr->hasEasterEggs()) + continue; if (curr->isArena()) continue; if (curr->isInternal()) continue; diff --git a/src/tracks/check_lap.cpp b/src/tracks/check_lap.cpp index 20d636de0..3471107d7 100644 --- a/src/tracks/check_lap.cpp +++ b/src/tracks/check_lap.cpp @@ -60,8 +60,12 @@ void CheckLap::reset(const Track &track) bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx) { float track_length = World::getWorld()->getTrack()->getTrackLength(); - float current_distance = - ((LinearWorld*)World::getWorld())->getDistanceDownTrackForKart(indx); + LinearWorld *lin_world = dynamic_cast(World::getWorld()); + // Can happen if a non-lap based race mode is used with a scene file that + // has check defined. + if(!lin_world) + return false; + float current_distance = lin_world->getDistanceDownTrackForKart(indx); bool result =(m_previous_distance[indx]>0.95f*track_length && current_distance<7.0f); if(UserConfigParams::m_check_debug && result) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a314a368e..f03baf38f 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -47,6 +47,7 @@ using namespace irr; #include "items/item.hpp" #include "items/item_manager.hpp" #include "modes/linear_world.hpp" +#include "modes/easter_egg_hunt.hpp" #include "modes/world.hpp" #include "physics/physical_object.hpp" #include "physics/physics.hpp" @@ -92,6 +93,7 @@ Track::Track(const std::string &filename) m_enable_push_back = true; m_reverse_available = false; m_is_arena = false; + m_has_easter_eggs = false; m_is_cutscene = false; m_camera_far = 1000.0f; m_mini_map = NULL; @@ -354,6 +356,9 @@ void Track::loadTrackInfo() m_screenshot = m_root+"/"+m_screenshot; delete root; + std::string dir = StringUtils::getPath(m_filename); + std::string easter_name = dir+"/easter_eggs.xml"; + m_has_easter_eggs = file_manager->fileExists(easter_name); } // loadTrackInfo //----------------------------------------------------------------------------- @@ -1238,9 +1243,7 @@ void Track::createWater(const XMLNode &node) * \param mode_id Which of the modes of a track to use. This determines which * scene, quad, and graph file to load. */ - -void Track::loadTrackModel(World* parent, bool reverse_track, - unsigned int mode_id ) +void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) { if(!m_reverse_available) { @@ -1390,7 +1393,8 @@ void Track::loadTrackModel(World* parent, bool reverse_track, createWater(*node); } else if(name=="banana" || name=="item" || - name=="small-nitro" || name=="big-nitro") + name=="small-nitro" || name=="big-nitro" || + name=="easter-egg" ) { // will be handled later } @@ -1420,7 +1424,9 @@ void Track::loadTrackModel(World* parent, bool reverse_track, } else if(name=="checks") { - CheckManager::get()->load(*node); + // Easter egg hunts don't have laps. + if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_EASTER_EGG) + CheckManager::get()->load(*node); } else if (name=="particle-emitter") { @@ -1543,7 +1549,7 @@ void Track::loadTrackModel(World* parent, bool reverse_track, } //} m_track_object_manager->enableFog(m_use_fog); - + // Sky dome and boxes support // -------------------------- if(m_sky_type==SKY_DOME && m_sky_textures.size() > 0) @@ -1573,8 +1579,8 @@ void Track::loadTrackModel(World* parent, bool reverse_track, } else if(m_sky_type==SKY_COLOR) { - parent->setClearBackBuffer(true); - parent->setClearbackBufferColor(m_sky_color); + World::getWorld()->setClearBackBuffer(true); + World::getWorld()->setClearbackBufferColor(m_sky_color); } @@ -1609,25 +1615,12 @@ void Track::loadTrackModel(World* parent, bool reverse_track, for(unsigned int i=0; igetNumNodes(); i++) { const XMLNode *node = root->getNode(i); - const std::string name = node->getName(); - if (name=="banana" || name=="item" || - name=="small-nitro" || name=="big-nitro") + const std::string &name = node->getName(); + if (name=="banana" || name=="item" || + name=="small-nitro" || name=="big-nitro" || + name=="easter-egg" ) { - Item::ItemType type; - if (name=="banana" ) type = Item::ITEM_BANANA; - else if(name=="item" ) type = Item::ITEM_BONUS_BOX; - else if(name=="small-nitro") type = Item::ITEM_NITRO_SMALL; - else type = Item::ITEM_NITRO_BIG; - Vec3 xyz; - // Set some kind of default in case Z is not defined in the file - // (with the new track exporter it always is defined anyway). - // Z is the height from which the item is dropped on the track. - xyz.setY(1000); - node->getXYZ(&xyz); - bool drop=true; - node->get("drop", &drop); - // Height is needed if bit 2 (for z) is not set - itemCommand(xyz, type, drop); + itemCommand(node); } } // for igetNumNodes() @@ -1645,7 +1638,8 @@ void Track::loadTrackModel(World* parent, bool reverse_track, { printf("WARNING: no check lines found in track '%s'.\n", m_ident.c_str()); - printf("Lap counting will not work, and start positions might be incorrect.\n"); + printf("Lap counting will not work, and start positions might be " + "incorrect.\n"); } if(UserConfigParams::logMemory()) @@ -1654,10 +1648,18 @@ void Track::loadTrackModel(World* parent, bool reverse_track, irr_driver->getSceneManager()->getMeshCache()->getMeshCount(), irr_driver->getVideoDriver()->getTextureCount()); - if (World::getWorld()->useChecklineRequirements()) + World *world = World::getWorld(); + if (world->useChecklineRequirements()) { QuadGraph::get()->computeChecklineRequirements(); } + + EasterEggHunt *easter_world = dynamic_cast(world); + if(easter_world) + { + std::string dir = StringUtils::getPath(m_filename); + easter_world->readData(dir+"/easter_eggs.xml"); + } } // loadTrackModel //----------------------------------------------------------------------------- @@ -1804,14 +1806,38 @@ void Track::handleSky(const XMLNode &xml_node, const std::string &filename) * \param drop True if the item Z position should be determined based on * the track topology. */ -void Track::itemCommand(const Vec3 &xyz, Item::ItemType type, - bool drop) +void Track::itemCommand(const XMLNode *node) { + const std::string &name = node->getName(); + + Item::ItemType type; + if (name=="banana" ) type = Item::ITEM_BANANA; + else if(name=="item" ) type = Item::ITEM_BONUS_BOX; + else if(name=="small-nitro") type = Item::ITEM_NITRO_SMALL; + else if(name=="easter-egg" ) type = Item::ITEM_EASTER_EGG; + else type = Item::ITEM_NITRO_BIG; + Vec3 xyz; + // Set some kind of default in case Y is not defined in the file + // (with the new track exporter it always is defined anyway). + // Y is the height from which the item is dropped on the track. + xyz.setY(1000); + node->getXYZ(&xyz); + bool drop=true; + node->get("drop", &drop); + // Some modes (e.g. time trial) don't have any bonus boxes if(type==Item::ITEM_BONUS_BOX && !World::getWorld()->haveBonusBoxes()) return; + // Only do easter eggs in easter egg mode. + if(type==Item::ITEM_EASTER_EGG && + !(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG)) + { + printf("Found easter egg in non-easter-egg mode - ignored.\n"); + return; + } + Vec3 loc(xyz); // if only 2d coordinates are given, let the item fall from very high if(drop) diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index a53b8982a..925a63285 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -227,6 +227,9 @@ private: Vec3 m_aabb_max; /** True if this track is an arena. */ bool m_is_arena; + + /** True if this track has easter eggs. */ + bool m_has_easter_eggs; bool m_is_cutscene; @@ -358,8 +361,6 @@ private: std::vector m_all_curves; void loadTrackInfo(); - void itemCommand(const Vec3 &xyz, Item::ItemType item_type, - bool drop); void loadQuadGraph(unsigned int mode_id, const bool reverse); void convertTrackToBullet(scene::ISceneNode *node); bool loadMainTrack(const XMLNode &node); @@ -386,7 +387,9 @@ public: void update(float dt); void reset(); void adjustForFog(scene::ISceneNode *node); - void adjustForFog(scene::IMesh* mesh, scene::ISceneNode* parent_scene_node); + void adjustForFog(scene::IMesh* mesh, + scene::ISceneNode* parent_scene_node); + void itemCommand(const XMLNode *node); const core::vector3df& getSunRotation(); /** Sets the current ambient color for a kart with index k. */ void setAmbientColor(const video::SColor &color, @@ -394,6 +397,8 @@ public: void handleExplosion(const Vec3 &pos, const PhysicalObject *mp, bool secondary_hits=true) const; + void loadTrackModel (bool reverse_track = false, + unsigned int mode_id=0); std::vector< std::vector > buildHeightMap(); // ------------------------------------------------------------------------ @@ -402,11 +407,11 @@ public: // ------------------------------------------------------------------------ const core::dimension2du& getMiniMapSize() const { return m_mini_map_size; } // ------------------------------------------------------------------------ - bool isArena () const { return m_is_arena; } + /** Returns true if this track has an arena mode. */ + bool isArena() const { return m_is_arena; } // ------------------------------------------------------------------------ - void loadTrackModel (World* parent, - bool reverse_track = false, - unsigned int mode_id=0); + /** Returns true if this track has easter eggs. */ + bool hasEasterEggs() const { return m_has_easter_eggs; } // ------------------------------------------------------------------------ void addMusic (MusicInformation* mi) {m_music.push_back(mi); }