From 31cea8ea8929a87acc5c6c45136a40ea9352b59f Mon Sep 17 00:00:00 2001 From: XProger Date: Tue, 20 Sep 2016 02:24:53 +0300 Subject: [PATCH] #13 activation triggers for doors & switches --- bin/OpenLara.exe | Bin 45568 -> 45568 bytes src/camera.h | 3 +- src/controller.h | 301 +++++++++++++-------------------------- src/debug.h | 27 +++- src/format.h | 202 +++++++++++++++++++++++--- src/lara.h | 94 ++++++++++-- src/level.h | 28 +++- src/utils.h | 4 +- src/win/OpenLara.vcxproj | 1 + 9 files changed, 423 insertions(+), 237 deletions(-) diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index 8f8991c3888216b2393c776c738486669d982974..3fb7f56eff5ffcd0d91103dcdb372c13413fafea 100644 GIT binary patch delta 16833 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 T<*0o_!?sy$`zO8iC*6Mo^N`2l delta 16230 zcmc(G4_Fk})%WbOiyK^=!7NH-Rn#RRf`Wl08cegOyWpSIMFn=1e?~z>6cTsUD7e}M z;$|HGO`1QgNzEI5o3_3UDQPgNQ9vUYQ$=GFOiabbq+_uuiPUTe&Ah)ev!H4Ee&6#w z-}gKp4|ndl=bn4+x#yg@_uPADw_eq5y{g?kUDLVe;hDahH_!j>x6dB=d>|F>yYzVj z%2|#5pTC8?aNnn&{{s2%|DOE$n+o0ApKn8c_6zstjY|Hgk}q7fyo`7-p+BdMVdiPV znCgFgm^XmyV!|{-HAaTn3(Ob=t7Q(0cWCl7Tg7FXrJ757#>Ebw>?zskL8X5W9vsqM z@voXO_a?;vY(N@?^bFE%e^!REPF}IhvkbWA#wpsfnms9oy*gI2UF39QH3eddZkjEJ zzrO7{qhlDsW^~G4gHXrx%d+#Nk}-1h_694X;>uom-^w^8la^uJ?o-Fh8QEhoQj(q! zy}I!!Q$bnR?1|uQT$q6F_G?f2Sj*dg) zyfPhCGgRHGR?E>ARPdeYm%aMmcM(mVVC#1-lHySBlyrFVJ^mA>^shZ)pPtivCk_p_ zjC<`VhRNlF(mD{IZyxc%J z%7>J4@5^K$Dj%Wz<->R?3gbN%E-#gnA@o!}+#i%ZL!6|j*``iLQuXDe2a{tiDW zXUfbSP)ZCQQj?0X5F(Bc{|SWuL=23sQ&spLf$)U;_fwbA35~*#bdB~>pZKofZf)A$IQQul_QCwKB?h3JdySBM|CA!N;zSC?BNQYrc<~rJ3)E&<`TT z5;HMt{Hb}9hBHF}x#gNbrXi4Nl%w-S%b1B8kGNn=il$oJI%ecZB5;;#jG);on~m^ZoCtxTIOm;yMj&2}mO7>eOBXd19}1sqq~Y*IB) z0o(O}qeqTTIR}@J19lzXCO9qyZ2bWT-r%}kIl3R_&6B-GzOy`RksO@{LSz-d3U!yh z!-SAm#=yIQGoQ02Fk9ayB;&a=R9m(Wy-4n>vg~#*lGnpKiqUkDm_0Vyw~N0lr@he8 zNF1rgiJF=IZ*|qzl%fG$eXkD%TLz*ZbaIF~x%w$}q7cQPY2f~9kOpduG=D)|X>S{$ z5~bRO3a4Bcod7bv#+V5rzpSbL@K_gQ5eg0RgM(!LHeDc0SgPA5Q|s!_iujX-OZm?V zS`7?dTR09VRlUm5E5LTZ9>Gr=?}@vh;m%xm67@W>Qk-NN zlU4>~z&;)Hf6;3;8}dja<(Cy{Nn6u}EtC1vdD5qAF$n*vB;!(?8kz3G0u%}U1>(+|f;-j^1T^7H!jDPShr9v^BXA_Z z0hK$UEfQ(NpTx!SiP{g=5GT!O@!9yhHRvaPLZoL6_45!lT(w60B7TxKc8xgt?pWXE zKan!v3g)m=w}jjL$>7+`f<2C!{jmZo%xO7Auv?r`xWX=h@NW;|lbq5c3LXk@N(Tv# z_uGJlEhY6-dEAn(|IF@g`TF9}_H0Q%(5u*V_poT)t=`fE`&4ROSRsCNckINYs9EhW zge$rqFx0V2gThT0>{cSbt3n)mPpt0=kSl|k^*!rvywzZqV9%lk=T}2IIQP7|Q=XyO zPX4s?ACR|O8<;BCQF2PJ5rHz?#ZD;|b%NbR_~!@l`A+Fw6a;%Q;kN-aVVI^RJagMX zrAy);?isKB=wtEAd&Z8vn;QR5I;p=TCMQHk*L^%Vx(dNwMZ7PUi|&NjiH~3yP=+aB z_uR6S^%l8Dux}*tpO%X+Cd4N9p+-?gH7P?kpuKNC8suLs)Nf^Im`=%AE>22{H8+IX z)Yk(4JslqUNF00b_@u`{5U4+b+BcanA{k&?sj?O7w}&{MUL~%%H}?L-0ggLD90vut zCnQLC;3(Az^}9nYH&aV<8mdYB`ltW3;fEL15uhQ}3H8r~8YZq1BPYhD@@T2(seYf* zbU?(wt#(u))b9_q`=m@`pb#ILM3kacT>jWBn&)$FiP`r{j^8NzQ@~7D* z#wpal2O6i84FQy;Q>gC%g1q2c5DE1cLZzWA$tRYt9$?)WVm&xtul#Uu@9SYy8q1qP)YbB-Dyi)vi(u1yaa7%4Y{n%Zap2@9ShGoXlpUZDBg<**^ zOQTUMuaA?WmE0mlDtUsWSMur7KR=*)tMm^gpC$cG$+M)-J`f+8WcIaDaf4YprsNi> zNy(F>SCu?X`h}8Dmwv9~v!rL0e4eyR$rnpcDtW%-Q}Pwk1|_eMDwW(LtyJ=Asfh9> zdV8eB3P`Rk&8BAl6IQv299BwKYRCtr6a^%Qlj0Td6#_>oAbE|%Dj@lTq*K5n1b*{J z>V|ABeW8G4Qt49#Bx6dQ3P@Iw{s3^S+|)&ItAZxAOHBa%C(?>2m^dz;OZj+YoD$b* z<>57=7w6PiMWKic2bx_DL3J#8)e~z!| z=g;ys)3z(gGS)PHc#9mtzIr)e;NRtKG25;XvZXJgDC{Gk?AAg-*QpH9#E5ZOQ?yyF z;-aj%lMSAp|VYv2SGQ0t<}D!UGF9w#m?zX^^2f{#+o>R9bh6 ztuy|~>8|AIuVleY|UD#oAH9lP4V3arLWDff8;?FpxkN*j++oZQh zOX;m1U1=aw%iFr9Wg4pEc*k||fw>bVaQq1V3}0lRJ!wHuUdZvM`GTv7?dhjk;m5=^ zr$?-wo1}4wznts#;biGJpTW`T5BmSwZek2j;1G1}v~=H#O*xF=Rf;j)qi~?2fTnKN zAJp>UUcKxzcZbQ&I46HbI?yM}was3Z59iOw&ICg30Sd$6=bKxu=nHvk8rw8W6JF4& z!)wIpuXk8|>QREr9>e1_A<7;jJCg!-69xbQj5HEwz;2WmrUdLTVhZg!~T4h zg%!+MKAa&n2j*Egtl?(XU#f*UkKO4%uH{>^*xC#@DzdksHDps!iEIjGp7mLt;S0-R zn&B7x8{`+)qJhUjTTHq=&f`QMTv$7MEG)g<`v`k%rWTuucz-a=13xx;SZ5hSEwkV7 zDK0gptcM(ICKz?o!HV6A1C`L+6NL=}`S$>3JVB7g| z?9QK{I(;6-w~Gg~5bEdQ+}E~HtEMovNolpU+QPzP*C?#|Sl_Xpyxg)b>iy*JV5?b{ zI2^S>1Z$Rb=`96eDrMK6WtX0UigDNzWlcf(B;Ug>Z6h2Sk|11>0Je+6VVcPom}N-{EVd-TFez*;t^YJvLk#v?@K63W)+z znvH%G&;l$WI3UpJU-)X!F1_k+v!K+C%8_isC5XJjVqus54L~QG@CRfP(mV?horI3B z`vi|AO&Lo5MKoFfM{>0T$i!ik>m8)`(c3)BRHe`9crLc2VUZ!xq2Hx9p`m$}1ol`9 zvZO^$0M4=w(&nbuQI&78;wS^6naPAOm^p)dExn!H@l(9X(1ef0$qy>X(UIZAA@*xH z!4PsJoEoUFl1|MG=<$(n!S;;w=|5yyoj!1!`6az8X)4Wh$_nM;smh$1R*>y^HwGRrwobdw5Hx_;>*@NAyG>Nu^rQMMkXO8S{X ztuUj;JJiNGL17D7CUPF$MdWl=nKVBMk0IIo88Gf}Qu7{q+1*gM+Xt6&p97ACu1_N` zA`5f^P%O}@h>Ax62~B-RIl8ELm5P!wF*eY|cwdl&PXgyN=po5QOI5RAYj;X9sM%I? zfo4p$P6xM#>1{N=`3bPQ;|7~g1${mQW|LdkAO9JIaf?}jZfq&uW)eQL9{TbtTkw6yVw#cP#=;%hnS z5w(g^Xtd(w-0|AQt>VJm9fMdL=1RGV+MRu3bl%gN9`RRs58?S)p5KR+htDu6v;1{4 zpN(KCnCtJ;uyxNtfSVbnaJF`*3TdJ9Xf-zDM$bZbo-x2gVnKm5-0uR;m<5Z#p%j&7 z%tC9OXB6F+!pE+AaM8e0ZjMI0f>f| z;6o*}p-&>BnA@ueLp5p0aSzdh-5A|Nu)H5VLE&Vi0h6@nK@*OCj~BQMtMEk1fF7)D zLW|^XP-b;SQ?`C-yi(-G3f`+X*kPQbmrdw^EDPvVQrx%Xfd>_9)}W=r$dzFw8xp76 z=BZxk{a014J?Ilt)V^0m1`FV zNiiW`qXm#=D;I_ql>@s*(HQk1e{W%v32*CJkNCc)I}%me0pDqb?-1>5D}pT$&DLfW zik(ZxYg1aq{-rTlx9>B+pXPy#tnRyr`}eD8wu+jaMSEanijM<&fA`Fl{_}ny@8Buw8GnT@Sr4 zLj(s|s7S{q?tZP3ON53qXq_1@l(B{QA6Fk^;4Cx zxF|S5grdxs$Ni;gOn0xMvjp*c;gm%S{*xr+lshY2Lb1uVez%)_@{j6kGB-t-X`yO$ zzTlRE7q@&W9$YSb+1-xIHXd@ju~xae4iY74zi4DemQL|o&I*sBCCzn$r^PD=z8vL{ z@UUIS1dl~(E?&YUCL8Bie3-J5b<&a6*lzJ~(LE6tuVJA-jhoPy#cM^gG?F;Ecs!oj z#iJ4~g%%CyYdZ$IUe}=M*522=4U2>9^F-D*d+xyT@aLb4V)2u>_l{jQ8P7S(#zx~} zm%k`@r8fT|hGFzb!e*mbzigRivnVYqn7A1N<&Q4LP94LEu0{@GprWf(ROAjd*Y6W6 zA5ELMS$Q)&17xnz6-u>BX$cOIwITAS#XmfHe-amB^Fz9=#A5S2(&28Eo7nMaLR6|e z?e`=oyYnd$b)89EzI@V>j+Yd(DYI zoLx6iq4S^Q($yYzJOSN_Ez8Gi4>96r%TH+U|4;GPE9`fMf}Skg>u>>EFn!Mb#+U%AQ;d^ zSPLzy=?KeHoBc)(S6!T1aC1l< zn3>$fLl7i0nZwT-G9w8XIDNY;Y>KfpkM`J#`G zEODQD;LXnSR-7xp`72od6j^h(Y6HgwA=9MX$5YI$%nzKS6EZ2K9?0dmG*H6S##wd3 z#$af+6}(RalLh~#24gc&z-YLV18M^|2IAvvucL%lgR6N3z^4Gbhww;-+PZ-F7O;)H zqZR1}oA5~pUjS;(b{I&sb(LJegKR*7Gm%D>1lfeo08?jF<6c8tZAa7w5DMs;PUzo7 zW3auaHY535J?i^Ng1Nfb1nQV1aCtFMLZCyp(z65HTqP17*t;oY=-qV<)j8ltn}nzm zXuw^9{#}1XDnMVZHP?YJcn7=P57eVA%p7`OWi0zNy)*YvV^@u3&HScexoeHWRJ z-LW4=!|4`(md>{}()pHBvE7ENc`_*Oq_UktrqL;_-6zXW+3tjC)mU74bN$y5i+hcV zO9bWh27Cb|`L2B=%ViB<-!|kB;-kQZ#Zt!4)OE+$8k%3-`YM3_5(()#QV))3j2J{_ zF;u57Lmi}7Xabq8woDw0Ju?HgippHEt!)Qb({^Eoj;=yMx z7BkkwOrVWfH}yVxg~E;7qjKj0DmQN1(_;0S`!r?Zt7{(iy$s8MySk_Ck&YDsN9`=#$x|Q?k*1u!09U>k&xj5=;+6e?gp#p zvdj3OShdy^UIA=ImH5p#LCJ$dnE zw{;AhZ-xhyt5Vu2zxO7C00)r|n{3~>ejIP>#Q7&KTgmmhhfj07=ZRFvl-MZBo`8Y_ z3gqxv5+dN_7HV>Vnhd|yrd@5*F7BwBGQP}-fX^u{g3-&lx0v%VQjeSO!`yx2pc5PL zqL;*npdx4{a!$2O2wBvz=YiqJC>N?P>MpCxxqD zK2g*uI1UiAere$g;+n_iXcJn+Hy=yU#=RhRKNjb6@$^|2Ki4JQ^Y_7HAFM&y*$C(` z%kW=HM_$9aB9A+2z^XFtC@oFp34x=uU6(eaM>l;;n9H|IcOS#yl9q4d&jjkRU&WE5 z77lkt+J+m0!RuRgXDS*7luHI&?D}xG+=AeTJ%)q%JJ?-2(ay6vv5l>L0gzw9uKXB) zEKhP4TXzLe`C@4ZI^{dvI90Db0SpO=PfY6Hm*uvw3(Z#MT7yb=SsbLJ6Z;Td;VnA2 zyN?()4G?-ZhKL?gh%9jb?v?(aY0D%2;D{}y{$R|O`~AUKPl`Y2@aCaq&0xzrLoFGl zWf`^9@|OcIlA5|FfOO#xNdJiY!o{k{M9bTPyrVzhilKAy7PA!>zW81wUAZD>cbxwY zb3F}1iU1?hIVZnC%=z|QX*-Vf_+a2Doj~y?i^K~ai+1u}vCotB=+!+~ch<*9mneTg z`lC|RNq#(le6l`V1+u6N)P-~AHodlm(nf+Tt7Zt=?ciKSCv zBd28Cg?AxMI)E1FJ@qC=6eS1@q|DAn%NztV(8|fclh@G{U$&yciHy`xrZ70YQ(>@N zVZeo&qgrV`;#cBh8%D)fE0jA_O3S~c{P34z!-fY(nOkX!!}dvy2J~@C*&Q9%Drz?V zD8d6(;BCa0kBzf8MrgF3{!+|&;zt^n`1BLWYd`#g4)fUBZIBdhaG36G_|v6#WDXZ> zuQ;V-BixpAAEhWwc-xAB+&GAeV@lM95MO*AN^%6*rVJy0R@qw9d3a&uMpcB!&>mfR z>8048ic>Z%)Huc3O+VJ|dQLQKo}%6QhM2y2g?7{%;!B%HN9=|U_>HbWmP>5k{BSrG z%aa<1R%dI55G>vES8;jGbcnvc#^XEKh|489@57yF*w@|fDbXi=W|1p6nk7FBEjYGH zn~@{>017&oualT(l!;~-(fs%)3OwIHg?v=-UJh+k!VlF-5N?&+w+OdNsUQ^UoRbu* zqO$8n#k|F;m8(>Avvdk*a4ImtBaR4S^Ohe)q&}&j=o?gnFTqz44qfLM`4-xL&WRCf z@VR6Md^v`9n}x@wqj5&e!In?;VJ;l4^TF=<_$~zD1qDQGlbcg(*kdy|3XP!rX7xZr zA5#9m9FVBnYrY06C-)@HhuDK~jxNQt?Bqywy^OLM>8NV+5X^nm>Xhub6sjGp_!4h1 zwY~bU701wmePbr>H0BP+#0VO%QIV@@CYMO7_WfD#3%=#~uWN$rQeU%>rBS|aE$qRS zvrf>}nP5F!&tVC?DcCh=dh+?Nzrl-?(@S|~KKp7;KL#0g=Q)J6`8~KK#peoeeJ?(` z_KsnjW|~^M^kJE40j$+cS-4o3IRY1ziE4+h;=*=8epuK!Nib*N1}X#mC0s%2a1R2o z3!nivB>+3wW8v)5j{!Ba$Ly$Y28dH5JC^i(3F{_`9UvF~zBO*;B@~Dao!tKkvXsyP zHZen7;QC0pV?n?H9Jt!GY6rwN)B~}NP}4fwN{PpSf6=z8$-;ZawB#TdyF*z%`{$ z1lZ`vsQA>;+eIrfcn>>uYiAj~&m0*R*x601n!4PovGxDsE` z5pY~cJr&3~5%9v3qDtPYJGEsUK1Qj$IU}g?-07FBKH+T|A*L(7hrI6~YP6m^%Q-$M z{Elke{$}e9gm^(1V_`p}My^%$0B8>EeBOx>!UX6b2fD^9gNLI>T8-%!qL;kKd)xV% z3v9v#wuxn%^1kC+S|pwS3LB443&eT;kw&;Dc}EM|Wc-m>>7T5*B);e$F$~+cOGDdX zSYmorZ1pEtU!hJ8QMm!EZAL&k3vB-i((CvQM4!^7_b~PQI-3C3;&P7QQ9~2iBupU_ zYZK=P-hD8{aiM01P?xXFJawIzD1mEr4p^8DP3d4FN}*sA5P9aGfFnT`+HvILCXXvP zBL2KK) zaY)@5-wFlWhQ`$GWe^J0K&g$~*i}c>d6aTg!Bzxw{*vvC|KLVokd;x^Wm1{8z%;&tc?FtWSyx_;;OB{!`*hb$1naI;9?pGHeFncSOVI zoKO}pzwLs~-^%%I{W_?i(P zQOapuX?n{R({u2efeGBBm?6Ji_Tq#eTZbq|5C@krjR&?*&_oyE`mK97@24t_GLbWsxNO!q5 zFISqdSvkwem4*Ot=jG+%1(SxU$TALdn3PKu2y&tYM=!-kFMbY&-rkoPXr?p8Qp$1BDx_;p zh}FWPNltWfu>cbW&f0N~AKE<99tL+{2n6X4Ox=I$O}N_-W@xW$5Uo2$j2Zl$$}rw` zHGrF1n}q4Q+Y)jb&(0e23233NnXP+3i!VK&hE9dL1afx#R-#>u+_iX&`r;O1X3R%) zLDIV;Ra`zfo^RKd{~bx}?u9dNwZO&I5=?+_*=Jh(EkBYnc8M2ur{Mk2?-{Rk?G*3bvnl#H4Copi+?HqH=Ro^A z;8Dd-h==!NY7Xz+8?Rj=i1+NR*Om(6t9vJm_^%yU<<5JCB0iO)Uq{RC>2mZAQQAA# z=OHs#VH5%1Jkam6K0eAYXYordC+s)NGF6T~1bTclFg0)3j3kspk{%VVLI9vN`=o6n- z(03K4a!qQp)9Hjv^YBBg{a}R`Fc!t>DAuAF0(S$vR)mI<9z4_A*!qRUrJcGD{pdYGvD#@)ef9iNqFEBmKd?) z=`@R#2Qro}^!uA=gvY1WEf z0Z>}fi?={N{UXR6A& z4e~5#Dx@t{fpsN#r+mO!puq(GewvrCha84j_`N^T=F#*RO?vnNn`*c`Iob*lNEn!F zA3$VBkQEiCHY;D_V&;;k_%jT;avgT3IQQHFk+2Rys?diDO0~9Jt5z3P$>M#_Bxy%I zCKf+4LK{;ho_;1)6rV9`PgRMpJrkpSrxKV{?WU@|&ziKGD#a1cj*Xs4JiUfMIKE^L z{i4NQDb9IT^bKogn0|bk@dbUJfxj~+@heTF2BZT>&mh$zZA2uv zIH%}G3I}`v`3U3*NN*th2huZ0+mSXQRUj=v%0im@4jqu-Z#z1_fTTq-AtfL^fRu%_ z7-O9@xs}Z6M_2onw2pinUKs#DM-_ivXGoe zE~H|l3Z#ulwMe^>_9IyuKl$0Np}ui(>&lj`D0v)w*Ad@waaE63u6%sinh?UfcJ!<|%nRuF~s?dqgP@@K{$>vV7IDin!%# zsA&WPe5}HJ+1gcWmU&iHu8mt>xn|9>wQ99k{);8PEeoy8^DZ_06gj0A{)a?$FCj&_ zt&9zc+AYerGPm;>TJe9x!#BvJCkeVuv@(g)zt3<$C>D(WonZefp@yuqGEc37O$zaw zzarQR={V9`#V9YcGIuuE|NUO8 zKP&%#|6Vt)KlFhnHeR3i_$p6{9WODnLYrCQS>#!f1$RcVaqe$gG>ygD9hxD3A8uvN X-3i4<55aoHSfj0tQyR`{v<&m#HrX5D diff --git a/src/camera.h b/src/camera.h index 6141712..32ea547 100644 --- a/src/camera.h +++ b/src/camera.h @@ -225,7 +225,8 @@ struct Camera : Controller { pos = pos.lerp(destPos, min(1.0f, Core::deltaTime * 2.0f)); - FloorInfo info = getFloorInfo((int)pos.x, (int)pos.z); + TR::Level::FloorInfo info; + level->getFloorInfo(room, (int)pos.x, (int)pos.z, info); if (info.roomNext != 255) room = info.roomNext; diff --git a/src/controller.h b/src/controller.h index 44fcd27..ab9ee1e 100644 --- a/src/controller.h +++ b/src/controller.h @@ -26,7 +26,7 @@ struct Controller { WALK = 1 << 6, ACTION = 1 << 7, WEAPON = 1 << 8, - DEATH = 1 << 11 }; + DEATH = 1 << 9 }; float animTime; int animIndex; @@ -41,12 +41,20 @@ struct Controller { float turnTime; - Controller(TR::Level *level, int entity) : level(level), entity(entity), velocity(0.0f), animTime(0.0f), animPrevFrame(0), health(100), turnTime(0.0f) { + struct Action { + TR::Action action; + int value; + + Action(TR::Action action, int value) : action(action), value(value) {} + } nextAction; + + Controller(TR::Level *level, int entity) : level(level), entity(entity), velocity(0.0f), animTime(0.0f), animPrevFrame(0), health(100), turnTime(0.0f), nextAction(TR::Action::NONE, 0) { TR::Entity &e = getEntity(); pos = vec3((float)e.x, (float)e.y, (float)e.z); angle = vec3(0.0f, e.rotation / 16384.0f * PI * 0.5f, 0.0f); stand = STAND_GROUND; animIndex = getModel().animation; + state = level->anims[animIndex].state; } void updateEntity() { @@ -90,29 +98,6 @@ struct Controller { return getEntity().room; } - TR::Room::Sector& getSector(int roomIndex, int x, int z, int &dx, int &dz) const { - ASSERT(roomIndex >= 0 && roomIndex < level->roomsCount); - TR::Room &room = level->rooms[roomIndex]; - - int sx = x - room.info.x; - int sz = z - room.info.z; - - sx = clamp(sx, 0, (room.xSectors - 1) << 10); - sz = clamp(sz, 0, (room.zSectors - 1) << 10); - - dx = sx & 1023; // mod 1024 - dz = sz & 1023; - sx >>= 10; // div 1024 - sz >>= 10; - - return room.sectors[sx * room.zSectors + sz]; - } - - TR::Room::Sector& getSector(int &dx, int &dz) const { - TR::Entity &entity = getEntity(); - return getSector(entity.room, entity.x, entity.z, dx, dz); - } - int setAnimation(int index, int frame = -1) { animIndex = index; TR::Animation &anim = level->anims[animIndex]; @@ -150,7 +135,7 @@ struct Controller { int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ, int &delta) const { int dx, dz; - TR::Room::Sector &s = getSector(getEntity().room, fromX, fromZ, dx, dz); + TR::Room::Sector &s = level->getSector(getEntity().room, fromX, fromZ, dx, dz); if (s.boxIndex == 0xFFFF) return NO_OVERLAP; @@ -179,108 +164,9 @@ struct Controller { return floor; } - struct FloorInfo { - int floor, ceiling; - int roomNext, roomBelow, roomAbove; - int floorIndex; - }; - - FloorInfo getFloorInfo(int x, int z) { - return getFloorInfo(getRoomIndex(), x, z); - } - - FloorInfo getFloorInfo(int roomIndex, int x, int z) { - int dx, dz; - TR::Room::Sector &s = getSector(roomIndex, x, z, dx, dz); - - FloorInfo info; - info.floor = 256 * (int)s.floor; - info.ceiling = 256 * (int)s.ceiling; - info.roomNext = 255; - info.roomBelow = s.roomBelow; - info.roomAbove = s.roomAbove; - info.floorIndex = s.floorIndex; - - if (!s.floorIndex) return info; - - TR::FloorData *fd = &level->floors[s.floorIndex]; - TR::FloorData::Command cmd; - - do { - cmd = (*fd++).cmd; - - switch (cmd.func) { - - case TR::FD_PORTAL : - info.roomNext = (*fd++).data; - break; - - case TR::FD_FLOOR : // floor & ceiling - case TR::FD_CEILING : { - TR::FloorData::Slant slant = (*fd++).slant; - int sx = (int)slant.x; - int sz = (int)slant.z; - if (cmd.func == TR::FD_FLOOR) { - info.floor -= sx * (sx > 0 ? (dx - 1024) : dx) >> 2; - info.floor -= sz * (sz > 0 ? (dz - 1024) : dz) >> 2; - } else { - info.ceiling -= sx * (sx < 0 ? (dx - 1024) : dx) >> 2; - info.ceiling += sz * (sz > 0 ? (dz - 1024) : dz) >> 2; - } - break; - } - - case TR::FD_TRIGGER : { - TR::FloorData::TriggerInfo info = (*fd++).triggerInfo; - TR::FloorData::TriggerCommand trigCmd; - do { - trigCmd = (*fd++).triggerCmd; // trigger action - switch (trigCmd.func) { - case 0 : - /* - if (getEntity().id == 0 && cmd.sub == 2) { - TR::Entity &e = level->entities[trigCmd.args]; - for (int i = 0; i < level->modelsCount; i++) - if (e.id == level->models[i].id) { - TR::Animation *anim = &level->anims[level->models[i].animation]; - for (int j = 0; j < anim->scCount; j++) - LOG("state: %d\n", anim->state); - break; - } - }*/ - break; // activate item - case 1 : break; // switch to camera - case 2 : break; // camera delay - case 3 : break; // flip map - case 4 : break; // flip on - case 5 : break; // flip off - case 6 : break; // look at item - case 7 : break; // end level - case 8 : break; // play soundtrack - case 9 : break; // special hadrdcode trigger - case 10 : break; // secret found - case 11 : break; // clear bodies - case 12 : break; // flyby camera sequence - case 13 : break; // play cutscene - } - // .. - } while (!trigCmd.end); - break; - } - - case TR::FD_KILL : - health = 0; - break; - - default : LOG("unknown func: %d\n", cmd.func); - } - - } while (!cmd.end); - - return info; - } - void playSound(int id) const { + // LOG("play sound %d\n", id); + int16 a = level->soundsMap[id]; TR::SoundInfo &b = level->soundsInfo[a]; if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) { @@ -314,7 +200,8 @@ struct Controller { void collide() { TR::Entity &entity = getEntity(); - FloorInfo info = getFloorInfo(entity.x, entity.z); + TR::Level::FloorInfo info; + level->getFloorInfo(entity.room, entity.x, entity.z, info); if (info.roomNext != 0xFF) entity.room = info.roomNext; @@ -345,6 +232,16 @@ struct Controller { } } + void activateNext() { // activate next entity (for triggers) + if (nextAction.action == TR::Action::NONE) return; + + Controller *controller = (Controller*)level->entities[nextAction.value].controller; + nextAction.action = TR::Action::NONE; + if (controller) + controller->activate(); + } + + virtual void activate() {} virtual void updateVelocity() {} virtual void move() {} virtual Stand getStand() { return STAND_AIR; } @@ -381,93 +278,97 @@ struct Controller { } virtual void updateBegin() { - animTime += Core::deltaTime; mask = getInputMask(); state = getState(stand = getStand()); } virtual void updateEnd() { - int frameIndex = int(animTime * 30.0f); - TR::Animation *anim = &level->anims[animIndex]; - bool endFrame = frameIndex > anim->frameEnd - anim->frameStart; - - // apply animation commands - int16 *ptr = &level->commands[anim->animCommand]; - - for (int i = 0; i < anim->acCount; i++) { - int cmd = *ptr++; - switch (cmd) { - case TR::ANIM_CMD_MOVE : { // cmd position - int16 sx = *ptr++; - int16 sy = *ptr++; - int16 sz = *ptr++; - if (endFrame) { - pos = pos + vec3(sx, sy, sz).rotateY(angle.y); - updateEntity(); - LOG("move: %d %d %d\n", (int)sx, (int)sy, (int)sz); - } - break; - } - case TR::ANIM_CMD_SPEED : { // cmd jump speed - int16 sy = *ptr++; - int16 sz = *ptr++; - if (endFrame) { - LOG("jump: %d %d\n", (int)sy, (int)sz); - velocity.x = sinf(angleExt) * sz; - velocity.y = sy; - velocity.z = cosf(angleExt) * sz; - stand = STAND_AIR; - } - break; - } - case TR::ANIM_CMD_EMPTY : // empty hands - break; - case TR::ANIM_CMD_KILL : // kill - break; - case TR::ANIM_CMD_SOUND : { // play sound - int frame = (*ptr++); - int id = (*ptr++) & 0x3FFF; - int idx = frame - anim->frameStart; - - if (idx > animPrevFrame && idx <= frameIndex) { - playSound(id); - // LOG("play sound %d\n", getEntity().id); - } - break; - } - case TR::ANIM_CMD_SPECIAL : // special commands - if (frameIndex != animPrevFrame && frameIndex + anim->frameStart == ptr[0]) { - switch (ptr[1]) { - case TR::ANIM_CMD_SPECIAL_FLIP : angle.y = angle.y + PI; break; - case TR::ANIM_CMD_SPECIAL_BUBBLE : /* playSound(TR::SND_BUBBLE); */ break; - case TR::ANIM_CMD_SPECIAL_CTRL : LOG("water out ?\n"); break; - default : LOG("unknown special cmd %d\n", (int)ptr[1]); - } - } - ptr += 2; - break; - default : - LOG("unknown animation command %d\n", cmd); - } - } - - if (endFrame) // if animation is end - switch to next - setAnimation(anim->nextAnimation, anim->nextFrame); - else - animPrevFrame = frameIndex; - - updateVelocity(); move(); collide(); - updateEntity(); } virtual void updateState() {} + + virtual void updateAnimation(bool commands) { + int frameIndex = int((animTime += Core::deltaTime) * 30.0f); + TR::Animation *anim = &level->anims[animIndex]; + bool endFrame = frameIndex > anim->frameEnd - anim->frameStart; + + // apply animation commands + if (commands) { + int16 *ptr = &level->commands[anim->animCommand]; + + for (int i = 0; i < anim->acCount; i++) { + int cmd = *ptr++; + switch (cmd) { + case TR::ANIM_CMD_MOVE : { // cmd position + int16 sx = *ptr++; + int16 sy = *ptr++; + int16 sz = *ptr++; + if (endFrame) { + pos = pos + vec3(sx, sy, sz).rotateY(angle.y); + updateEntity(); + LOG("move: %d %d %d\n", (int)sx, (int)sy, (int)sz); + } + break; + } + case TR::ANIM_CMD_SPEED : { // cmd jump speed + int16 sy = *ptr++; + int16 sz = *ptr++; + if (endFrame) { + LOG("jump: %d %d\n", (int)sy, (int)sz); + velocity.x = sinf(angleExt) * sz; + velocity.y = sy; + velocity.z = cosf(angleExt) * sz; + stand = STAND_AIR; + } + break; + } + case TR::ANIM_CMD_EMPTY : // empty hands + break; + case TR::ANIM_CMD_KILL : // kill + break; + case TR::ANIM_CMD_SOUND : { // play sound + int frame = (*ptr++); + int id = (*ptr++) & 0x3FFF; + int idx = frame - anim->frameStart; + + if (idx > animPrevFrame && idx <= frameIndex) { + if (getEntity().id != ENTITY_ENEMY_BAT) // temporary mute the bat + playSound(id); + } + break; + } + case TR::ANIM_CMD_SPECIAL : // special commands + if (frameIndex != animPrevFrame && frameIndex + anim->frameStart == ptr[0]) { + switch (ptr[1]) { + case TR::ANIM_CMD_SPECIAL_FLIP : angle.y = angle.y + PI; break; + case TR::ANIM_CMD_SPECIAL_BUBBLE : /* playSound(TR::SND_BUBBLE); */ break; + case TR::ANIM_CMD_SPECIAL_CTRL : LOG("water out ?\n"); break; + default : LOG("unknown special cmd %d\n", (int)ptr[1]); + } + } + ptr += 2; + break; + default : + LOG("unknown animation command %d\n", cmd); + } + } + } + + if (endFrame) { // if animation is end - switch to next + setAnimation(anim->nextAnimation, anim->nextFrame); + activateNext(); + } else + animPrevFrame = frameIndex; + } virtual void update() { updateBegin(); updateState(); + updateAnimation(true); + updateVelocity(); updateEnd(); } }; diff --git a/src/debug.h b/src/debug.h index 4d98db8..337a758 100644 --- a/src/debug.h +++ b/src/debug.h @@ -340,7 +340,7 @@ namespace Debug { bool current = (int)p.x == x && (int)p.z == z; debugFloor(level, f, c, s.floorIndex, s.boxIndex, current); - + /* if (current && s.boxIndex != 0xFFFF && level.boxes[s.boxIndex].overlap != 0xFFFF) { glDisable(GL_DEPTH_TEST); glColor4f(0.0f, 1.0f, 0.0f, 0.25f); @@ -349,6 +349,7 @@ namespace Debug { debugOverlaps(level, s.boxIndex); glEnable(GL_DEPTH_TEST); } + */ } } @@ -394,6 +395,16 @@ namespace Debug { Core::setBlending(bmAlpha); } + void entities(const TR::Level &level) { + for (int i = 0; i < level.entitiesCount; i++) { + TR::Entity &e = level.entities[i]; + + char buf[255]; + sprintf(buf, "%d", (int)e.id); + Debug::Draw::text(vec3(e.x, e.y, e.z), vec4(0.8, 0.0, 0.0, 1), buf); + } + } + void lights(const TR::Level &level) { // int roomIndex = level.entities[lara->entity].room; // int lightIndex = getLightIndex(lara->pos, roomIndex); @@ -471,7 +482,7 @@ namespace Debug { int fSize = sizeof(TR::AnimFrame) + m.mCount * sizeof(uint16) * 2; TR::Animation *anim = controller ? &level.anims[controller->animIndex] : &level.anims[m.animation]; - TR::AnimFrame *frame = (TR::AnimFrame*)&level.frameData[anim->frameOffset + (controller ? int((controller->animTime * 30.0f / anim->frameRate)) * fSize : 0) >> 1]; + TR::AnimFrame *frame = (TR::AnimFrame*)&level.frameData[(anim->frameOffset + (controller ? int((controller->animTime * 30.0f / anim->frameRate)) * fSize : 0) >> 1)]; //mat4 m; //m.identity(); @@ -528,6 +539,18 @@ namespace Debug { } } + void info(const TR::Level &level, const TR::Entity &entity) { + char buf[255]; + sprintf(buf, "DIP = %d, TRI = %d", Core::stats.dips, Core::stats.tris); + Debug::Draw::text(vec2(16, 16), vec4(1.0f), buf); + sprintf(buf, "pos = (%d, %d, %d), room = %d", entity.x, entity.y, entity.z, entity.room); + Debug::Draw::text(vec2(16, 32), vec4(1.0f), buf); + + TR::Level::FloorInfo info; + level.getFloorInfo(entity.room, entity.x, entity.z, info); + sprintf(buf, "floor = %d, roomBelow = %d, roomAbove = %d, height = %d", info.floorIndex, info.roomBelow, info.roomAbove, info.floor - info.ceiling); + Debug::Draw::text(vec2(16, 48), vec4(1.0f), buf); + } } } diff --git a/src/format.h b/src/format.h index 5ad186a..ec415ad 100644 --- a/src/format.h +++ b/src/format.h @@ -39,14 +39,46 @@ namespace TR { SND_BUBBLE = 37, }; + enum { + TRIGGER_ACTIVATE = 0, + TRIGGER_PAD = 1, + TRIGGER_SWITCH = 2, + TRIGGER_KEY = 3, + TRIGGER_PICKUP = 4, + TRIGGER_HEAVY = 5, + TRIGGER_ANTIPAD = 6, + TRIGGER_COMBAT = 7, + TRIGGER_DUMMY = 8, + TRIGGER_ANTI = 9 + }; + + enum Action { + NONE = -1, // no action + ACTIVATE = 0, // activate item + CAMERA_SWITCH = 1, // switch to camera + CAMERA_DELAY = 2, // camera delay + FLIP_MAP = 3, // flip map + FLIP_ON = 4, // flip on + FLIP_OFF = 5, // flip off + LOOK_AT = 6, // look at item + END = 7, // end level + SOUNDTRACK = 8, // play soundtrack + HARDCODE = 9, // special hadrdcode trigger + SECRET = 10, // secret found + CLEAR_BODIES = 11, // clear bodies + CAMERA_FLYBY = 12, // flyby camera sequence + CUTSCENE = 13, // play cutscene + }; + + #define DATA_PORTAL 0x01 #define DATA_FLOOR 0x02 #define DATA_CEILING 0x03 - #define ENTITY_FLAG_CLEAR 0x0080 #define ENTITY_FLAG_VISIBLE 0x0100 - #define ENTITY_FLAG_MASK 0x3E00 + #define ENTITY_FLAG_ACTIVE 0x3E00 + #define ENTITY_LARA 0 #define ENTITY_LARA_CUT 77 @@ -71,25 +103,41 @@ namespace TR { #define ENTITY_ENEMY_MUMMY 24 #define ENTITY_ENEMY_LARSON 27 - #define ENTITY_CRYSTAL 83 + #define ENTITY_BLADE 36 - #define ENTITY_MEDIKIT_SMALL 93 - #define ENTITY_MEDIKIT_BIG 94 + #define ENTITY_CRYSTAL 83 - #define ENTITY_VIEW_TARGET 169 + #define ENTITY_MEDIKIT_SMALL 93 + #define ENTITY_MEDIKIT_BIG 94 - #define ENTITY_TRAP_FLOOR 35 - #define ENTITY_TRAP_SPIKES 37 - #define ENTITY_TRAP_STONE 38 - #define ENTITY_TRAP_DART 40 + #define ENTITY_TRAP_FLOOR 35 + #define ENTITY_TRAP_SPIKES 37 + #define ENTITY_TRAP_STONE 38 + #define ENTITY_TRAP_DART 40 - #define ENTITY_SWITCH 55 + #define ENTITY_SWITCH 55 + #define ENTITY_SWITCH_WATER 56 - #define ENTITY_GUN_SHOTGUN 85 + #define ENTITY_DOOR_1 57 + #define ENTITY_DOOR_2 58 + #define ENTITY_DOOR_3 59 + #define ENTITY_DOOR_4 60 + #define ENTITY_DOOR_BIG_1 61 + #define ENTITY_DOOR_BIG_2 62 + #define ENTITY_DOOR_5 63 + #define ENTITY_DOOR_6 64 + #define ENTITY_DOOR_FLOOR_1 65 + #define ENTITY_DOOR_FLOOR_2 66 - #define ENTITY_AMMO_UZI 91 - #define ENTITY_AMMO_SHOTGUN 89 - #define ENTITY_AMMO_MAGNUM 90 + #define ENTITY_GUN_SHOTGUN 85 + + #define ENTITY_AMMO_UZI 91 + #define ENTITY_AMMO_SHOTGUN 89 + #define ENTITY_AMMO_MAGNUM 90 + + #define ENTITY_HOLE_PUZZLE 118 + #define ENTITY_HOLE_KEY 137 + #define ENTITY_VIEW_TARGET 169 #pragma pack(push, 1) @@ -306,8 +354,8 @@ namespace TR { }; struct AnimFrame { - MinMax box; - TR::Vertex pos; // Starting offset for this model + MinMax box; + Vertex pos; // Starting offset for this model int16 aCount; uint16 angles[0]; // angle frames in YXZ order @@ -579,7 +627,7 @@ namespace TR { // lights r.lights = new Room::Light[stream.read(r.lightsCount)]; for (int i = 0; i < r.lightsCount; i++) { - TR::Room::Light &light = r.lights[i]; + Room::Light &light = r.lights[i]; stream.read(light.x); stream.read(light.y); stream.read(light.z); @@ -711,13 +759,127 @@ namespace TR { delete[] soundOffsets; } - TR::StaticMesh* getMeshByID(int id) const { // TODO: map this + // common methods + + StaticMesh* getMeshByID(int id) const { // TODO: map this for (int i = 0; i < staticMeshesCount; i++) if (staticMeshes[i].id == id) return &staticMeshes[i]; return NULL; } - }; + + struct FloorInfo { + int floor, ceiling; + int roomNext, roomBelow, roomAbove; + int floorIndex; + bool kill; + int trigger; + FloorData::TriggerInfo trigInfo; + FloorData::TriggerCommand trigCmd[16]; + int trigCmdCount; + }; + + Room::Sector& getSector(int roomIndex, int x, int z, int &dx, int &dz) const { + ASSERT(roomIndex >= 0 && roomIndex < roomsCount); + Room &room = rooms[roomIndex]; + + int sx = x - room.info.x; + int sz = z - room.info.z; + + sx = clamp(sx, 0, (room.xSectors - 1) * 1024); + sz = clamp(sz, 0, (room.zSectors - 1) * 1024); + + dx = sx % 1024; + dz = sz % 1024; + sx /= 1024; + sz /= 1024; + + return room.sectors[sx * room.zSectors + sz]; + } + + void getFloorInfo(int roomIndex, int x, int z, FloorInfo &info) const { + int dx, dz; + Room::Sector &s = getSector(roomIndex, x, z, dx, dz); + + info.floor = 256 * (int)s.floor; + info.ceiling = 256 * (int)s.ceiling; + info.roomNext = 255; + info.roomBelow = s.roomBelow; + info.roomAbove = s.roomAbove; + info.floorIndex = s.floorIndex; + info.kill = false; + info.trigger = -1; + info.trigCmdCount = 0; + + if (!s.floorIndex) return; + + FloorData *fd = &floors[s.floorIndex]; + FloorData::Command cmd; + + do { + cmd = (*fd++).cmd; + + switch (cmd.func) { + + case FD_PORTAL : + info.roomNext = (*fd++).data; + break; + + case FD_FLOOR : // floor & ceiling + case FD_CEILING : { + FloorData::Slant slant = (*fd++).slant; + int sx = (int)slant.x; + int sz = (int)slant.z; + if (cmd.func == FD_FLOOR) { + info.floor -= sx * (sx > 0 ? (dx - 1024) : dx) >> 2; + info.floor -= sz * (sz > 0 ? (dz - 1024) : dz) >> 2; + } else { + info.ceiling -= sx * (sx < 0 ? (dx - 1024) : dx) >> 2; + info.ceiling += sz * (sz > 0 ? (dz - 1024) : dz) >> 2; + } + break; + } + + case FD_TRIGGER : { + info.trigger = cmd.sub; + info.trigCmdCount = 0; + info.trigInfo = (*fd++).triggerInfo; + FloorData::TriggerCommand trigCmd; + do { + trigCmd = (*fd++).triggerCmd; // trigger action + info.trigCmd[info.trigCmdCount++] = trigCmd; + switch (trigCmd.func) { + case 0 : break; // activate item + case 1 : break; // switch to camera + case 2 : break; // camera delay + case 3 : break; // flip map + case 4 : break; // flip on + case 5 : break; // flip off + case 6 : break; // look at item + case 7 : break; // end level + case 8 : break; // play soundtrack + case 9 : break; // special hadrdcode trigger + case 10 : break; // secret found + case 11 : break; // clear bodies + case 12 : break; // flyby camera sequence + case 13 : break; // play cutscene + } + // .. + } while (!trigCmd.end); + break; + } + + case FD_KILL : + info.kill = true; + break; + + default : LOG("unknown func: %d\n", cmd.func); + } + + } while (!cmd.end); + } + + }; // struct Level } #endif \ No newline at end of file diff --git a/src/lara.h b/src/lara.h index d999853..f87403f 100644 --- a/src/lara.h +++ b/src/lara.h @@ -99,7 +99,7 @@ struct Lara : Controller { // level 2 (pool) pos = vec3(70067, -256, 29104); angle = vec3(0.0f, -0.68f, 0.0f); - getEntity().room = 15; + getEntity().room = 15; */ /* // level 2 (wolf) @@ -129,8 +129,9 @@ struct Lara : Controller { bool waterOut(int &outState) { vec3 dst = pos + getDir() * 32.0f; - FloorInfo infoCur = getFloorInfo((int)pos.x, (int)pos.z), - infoDst = getFloorInfo(infoCur.roomAbove, (int)dst.x, (int)dst.z); + TR::Level::FloorInfo infoCur, infoDst; + level->getFloorInfo(getEntity().room, (int)pos.x, (int)pos.z, infoCur), + level->getFloorInfo(infoCur.roomAbove, (int)dst.x, (int)dst.z, infoDst); if (infoDst.roomBelow == 0xFF && pos.y - infoDst.floor <= 256) { // possibility check if (!setState(STATE_STOP)) { // can't set water out state @@ -151,6 +152,77 @@ struct Lara : Controller { return false; } + void performTrigger() { + TR::Entity &e = getEntity(); + TR::Level::FloorInfo info; + level->getFloorInfo(e.room, e.x, e.z, info); + + if (!info.trigCmdCount) return; // has no trigger + bool isActive = (level->entities[info.trigCmd[0].args].flags & ENTITY_FLAG_ACTIVE); + if (info.trigInfo.once == 1 && (level->entities[info.trigCmd[0].args].flags & ENTITY_FLAG_ACTIVE)) return; // once trigger is already activated + + int actionState = 0; + switch (info.trigger) { + case TR::TRIGGER_ACTIVATE : + if (isActive) return; + actionState = state; + break; + case TR::TRIGGER_PAD : + if (stand != STAND_GROUND || isActive) return; + actionState = state; + break; + case TR::TRIGGER_SWITCH : + if (mask & ACTION) { + actionState = isActive ? STATE_SWITCH_OFF : STATE_SWITCH_ON; + } else + return; + break; + case TR::TRIGGER_KEY : + if (isActive) return; + if (mask & ACTION) + // if (entity.id == ENTITY_PUZZLE_1) + // actionState = STATE_USE_PUZZLE; + // else + actionState = STATE_USE_KEY; + else + return; + break; + case TR::TRIGGER_PICKUP : + if ((mask & ACTION) && stand == STAND_GROUND) + actionState = STATE_PICK_UP; + else + return; + break; + default : + return; + } + + // try to activate Lara state + if (!setState(actionState)) return; + + // build trigger activation chain + for (int i = 0; i < info.trigCmdCount; i++) { + if (info.trigCmd[i].func != TR::Action::ACTIVATE) continue; // TODO: other trigger types + Controller *controller = (Controller*)level->entities[info.trigCmd[i].args].controller; + if (!controller) { + LOG("! next activation entity %d has no controller\n", level->entities[info.trigCmd[i].args].id); + playSound(2); + return; + } else + controller->nextAction = (i < info.trigCmdCount - 1) ? Action(TR::Action::ACTIVATE, info.trigCmd[i + 1].args) : Action(TR::Action::NONE, 0); + } + + if (info.trigCmd[0].func != TR::Action::ACTIVATE) return; // see above TODO + + // activate first entity in chain + Controller *controller = (Controller*)level->entities[info.trigCmd[0].args].controller; + if (info.trigger == TR::TRIGGER_KEY) { + nextAction = controller->nextAction; + controller->nextAction.action = TR::Action::NONE; + } else + controller->activate(); + } + virtual Stand getStand() { if (stand == STAND_ONWATER && state != STATE_DIVE && state != STATE_STOP) return stand; @@ -161,7 +233,8 @@ struct Lara : Controller { int extra = isMovingState(state) ? 256 : 0; TR::Entity &e = getEntity(); - FloorInfo info = getFloorInfo(e.x, e.z); + TR::Level::FloorInfo info; + level->getFloorInfo(e.room, e.x, e.z, info); if (info.roomBelow == 0xFF && e.y + extra >= info.floor) return STAND_GROUND; @@ -235,7 +308,7 @@ struct Lara : Controller { if (mask & FORTH) return STATE_RUN; if (mask & BACK) return STATE_FAST_BACK; if (mask & LEFT) return turnTime < FAST_TURN_TIME ? STATE_TURN_LEFT : STATE_FAST_TURN; - if (mask & RIGHT) return turnTime < FAST_TURN_TIME ? STATE_TURN_RIGHT : STATE_FAST_TURN; + if (mask & RIGHT) return turnTime < FAST_TURN_TIME ? STATE_TURN_RIGHT : STATE_FAST_TURN; return STATE_STOP; } @@ -249,6 +322,7 @@ struct Lara : Controller { } if (mask & JUMP) return STATE_SWIM; + return (state == STATE_SWIM || velocity.y > GLIDE_SPEED) ? STATE_GLIDE : STATE_TREAD; } @@ -306,6 +380,8 @@ struct Lara : Controller { } virtual void updateState() { + performTrigger(); + TR::Animation *anim = &level->anims[animIndex]; int fCount = anim->frameEnd - anim->frameStart; @@ -340,7 +416,6 @@ struct Lara : Controller { } else lState = false; #endif - // calculate turn tilt if (state == STATE_RUN && (mask & (LEFT | RIGHT))) { if (mask & LEFT) angle.z -= Core::deltaTime * TURN_TILT; @@ -401,7 +476,7 @@ struct Lara : Controller { case STATE_SURF_RIGHT : angleExt += PI * 0.5f; break; - } + } } virtual void updateVelocity() { @@ -467,7 +542,8 @@ struct Lara : Controller { vec3 p = pos; pos = pos + offset; - FloorInfo info = getFloorInfo((int)pos.x, (int)pos.z); + TR::Level::FloorInfo info; + level->getFloorInfo(getEntity().room, (int)pos.x, (int)pos.z, info); int delta; int d = getOverlap((int)p.x, (int)p.y, (int)p.z, (int)pos.x, (int)pos.z, delta); @@ -518,7 +594,7 @@ struct Lara : Controller { case STAND_ONWATER : break; } - } else + } else updateEntity(); } }; diff --git a/src/level.h b/src/level.h index 578cc2c..68236ad 100644 --- a/src/level.h +++ b/src/level.h @@ -7,6 +7,7 @@ #include "lara.h" #include "enemy.h" #include "camera.h" +#include "trigger.h" #ifdef _DEBUG #include "debug.h" @@ -72,6 +73,25 @@ struct Level { case ENTITY_ENEMY_LARSON : entity.controller = new Enemy(&level, i); break; + case ENTITY_DOOR_1 : + case ENTITY_DOOR_2 : + case ENTITY_DOOR_3 : + case ENTITY_DOOR_4 : + case ENTITY_DOOR_5 : + case ENTITY_DOOR_6 : + case ENTITY_DOOR_BIG_1 : + case ENTITY_DOOR_BIG_2 : + case ENTITY_DOOR_FLOOR_1 : + case ENTITY_DOOR_FLOOR_2 : + case ENTITY_BLADE : + entity.controller = new Trigger(&level, i, true); + break; + case ENTITY_SWITCH : + case ENTITY_SWITCH_WATER : + case ENTITY_HOLE_PUZZLE : + case ENTITY_HOLE_KEY : + entity.controller = new Trigger(&level, i, false); + break; } } @@ -360,7 +380,7 @@ struct Level { if (fIndexB == 0) { nextAnim = &level.anims[anim->nextAnimation]; - fIndexB = (anim->nextFrame - nextAnim->frameStart) / anim->frameRate; + fIndexB = (anim->nextFrame - nextAnim->frameStart) / nextAnim->frameRate; } else nextAnim = anim; @@ -553,10 +573,12 @@ struct Level { #ifdef _DEBUG Debug::begin(); - // Debug::Level::rooms(level, lara->pos, lara->getEntity().room); + Debug::Level::rooms(level, lara->pos, lara->getEntity().room); // Debug::Level::lights(level); // Debug::Level::portals(level); - Debug::Level::meshes(level); + // Debug::Level::meshes(level); + Debug::Level::entities(level); + Debug::Level::info(level, lara->getEntity()); Debug::end(); #endif } diff --git a/src/utils.h b/src/utils.h index 58edb44..f5e8adc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -19,8 +19,8 @@ #else #define ASSERT(expr) -// #define LOG(...) ((void)0) - #define LOG(...) printf(__VA_ARGS__) + #define LOG(...) ((void)0) +// #define LOG(...) printf(__VA_ARGS__) #endif diff --git a/src/win/OpenLara.vcxproj b/src/win/OpenLara.vcxproj index 0e72818..22d45ab 100644 --- a/src/win/OpenLara.vcxproj +++ b/src/win/OpenLara.vcxproj @@ -109,6 +109,7 @@ +