From c5936c9e9ee19d9231efcffbbefd1d4647b0e1bd Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 24 Sep 2009 02:51:07 +0000 Subject: [PATCH 001/241] - Smaller sprites SVN r1873 (trunk) --- wadsrc/static/sprites/PLS1A0.png | Bin 329 -> 329 bytes wadsrc/static/sprites/PLS1C0.png | Bin 329 -> 329 bytes wadsrc/static/sprites/PLS1G0.png | Bin 579 -> 575 bytes wadsrc/static/sprites/PLS2C0.png | Bin 297 -> 292 bytes wadsrc/static/sprites/PLS2D0.png | Bin 253 -> 250 bytes wadsrc/static/sprites/amrka0.png | Bin 234 -> 234 bytes wadsrc/static/sprites/iceca0.png | Bin 202 -> 193 bytes wadsrc/static/sprites/icecb0.png | Bin 193 -> 189 bytes wadsrc/static/sprites/icecc0.png | Bin 163 -> 155 bytes wadsrc/static/sprites/icecd0.png | Bin 120 -> 118 bytes wadsrc/static/sprites/rsmka0.png | Bin 406 -> 376 bytes wadsrc/static/sprites/rsmkb0.png | Bin 403 -> 388 bytes wadsrc/static/sprites/rsmkc0.png | Bin 575 -> 550 bytes wadsrc/static/sprites/rsmkd0.png | Bin 399 -> 380 bytes wadsrc/static/sprites/rsmke0.png | Bin 261 -> 255 bytes wadsrc/static/sprites/sgrna5.png | Bin 226 -> 225 bytes wadsrc/static/sprites/sgrna6a4.png | Bin 269 -> 267 bytes wadsrc/static/sprites/sgrna7a3.png | Bin 261 -> 192 bytes wadsrc/static/sprites/sgrna8a2.png | Bin 251 -> 198 bytes wadsrc/static/sprites/tlgla0.png | Bin 159 -> 152 bytes wadsrc/static/sprites/tlglb0.png | Bin 159 -> 152 bytes wadsrc/static/sprites/tlglc0.png | Bin 159 -> 152 bytes wadsrc/static/sprites/tlgld0.png | Bin 159 -> 152 bytes wadsrc/static/sprites/tlgle0.png | Bin 159 -> 152 bytes 24 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/sprites/PLS1A0.png b/wadsrc/static/sprites/PLS1A0.png index 029d0bc75d1f903a2d912beb0b7842ad3f02e11b..303e203c7331e9eb16bf3c3da40e8aad1656c648 100644 GIT binary patch delta 190 zcmX@fbdqVpPV533pc`M+L_O}zNcC6l1_n=8KbLh*2~7ZFNmM=HtF~MQdW!Z50eitFa3Bx@Ze*1EnDtC?RYW`T>ZO}xw7PBkoj zF)Mf7^?9dvczgaf`5tAw_Fi-FlNI-Eqk?df#JUU|{fc^>bP0l+XkK=^tC^ diff --git a/wadsrc/static/sprites/PLS1C0.png b/wadsrc/static/sprites/PLS1C0.png index 029d0bc75d1f903a2d912beb0b7842ad3f02e11b..303e203c7331e9eb16bf3c3da40e8aad1656c648 100644 GIT binary patch delta 190 zcmX@fbdqVpPV533pc`M+L_O}zNcC6l1_n=8KbLh*2~7ZFNmM=HtF~MQdW!Z50eitFa3Bx@Ze*1EnDtC?RYW`T>ZO}xw7PBkoj zF)Mf7^?9dvczgaf`5tAw_Fi-FlNI-Eqk?df#JUU|{fc^>bP0l+XkK=^tC^ diff --git a/wadsrc/static/sprites/PLS1G0.png b/wadsrc/static/sprites/PLS1G0.png index df4e1f6d425030ae4c2b2a8bad7dc6efd1b729ce..e3a1629d8e729caa2f501cfd40a089e5a6aed796 100644 GIT binary patch delta 480 zcmX@ivY%x_X8l1=7srr_IMxG({?hCcY!8+jmcKt061LhoeTqwx>)N9=K?l~XYx?-h zt6~5Cc*X-uSr{A~tXf$Z8hn;%FkD#DcCtr|!D_W*ztMIchRyTVoEJ0RK3$Th>)hX8 zJFN9C&&W0omJE>JV=K?sJ~>QlF>Bzp+3&3bIv6HbKiX~UVtlxs!P>&^*84{Hw_>hq zb!O*RGi(YpxWlkusz2u$k=L9JrL(;q_2P9H9vCUF*vRP6U$pbJz?*G3+6-qhJboTz zYnbBqLPuvgFT;(rwsXC|lNlA9jZ3Co&fCk%urW^baR1Z4f($3?O|Bk0y^&$V*R_&U zkNy0#mGMF9x#cq^eXM-N#!!EKx^7fpeGC(W|MR?OrJv1_6kC+JQVO7mmb@MO;!RfR&91G}#p z84I+DHAwF_W@c#E|LEzlS;30it|@=`e($pO-MdUFs~CUhe_t#Y$IYQJt^WVd$jY@b z!2yz9uiq9}*vzll!g_d%RqxNJ`pQoRu7N@CmUYioes9bW6!bdm)7G>!riNKdF8OR> pU@)55$iR?L#mLCOP|S4Tzb#*%RhdSG0|NsCgQu&X%Q~loCII_=(GLIs delta 484 zcmdnba+qa8X8lo57srr_xY&z^+0u?8t`CL1t+$toZdYo}PL#gW<+3Ag!`3|WBcHa3 z=e+#)_ki}11N}9NNsswA-{s)h9_uoH%W5oeI;kIpc5sV28^@^)9xF0q0Hf#{$ z2<7#$Hf!B*Sgw`va)QK8%~cmXBw4P-9CEww;c9pxO>e7VH{*q(rpA4$jt!j2{PQjp zJrCF;Wx8#iu+D^s6YGQ|Wg3kS7<^~z@jMW@dG4KNrm&j^>u>4SE}Cm7P$6SiZu?R{ z;+RND_dVQ$CZcc{^sh(H4?482KHiKzZAvf2J+;kyU5#zTTNqK ze4$)!{{GbFLtlgXe4LXe@GdmpH}6ryhDUx<@Ate5Wh>{-eG|D@X}YR$Y;&Kp7^8w= z=@-vrk02Jt+1}azR=(L4|7gRqOtS`w+_I4G(sB0=u0HK5nk<@^x9yIlE|y2N4V$4UX5@0Z_C$bwK|St8Uq6ZgQu&X%Q~loCIDat4O}^5AF&hUV<>|MK$j-sb;j&(3yN_h(>emY4q@AKxEu zUeCa=-kG62-1xt}{p9N8a)0ggVEb@q6hwQvIEGZju{N~wGCK+!v8m=cFVgaFbq|AuDuct*w`)omME`SM)@hXc zcW&SMVv($A$E?&o3qC&-7VqEGov~9@>t>F_@k>RwHeF}XI=k#@7emS4I~T1P3SM!4 aV1LZUJf$UP&Rhlt1_n=8KbLh*2~7Y+rdWjl delta 225 zcmZ3&w32CpeqwXBcYUz_at4O}^5AF&hUV<>|MK$j-sb;j&(3yNuV-LrmY4q@AKxEu z?$5xm-kG62-1xt}{p9N8a)0gX3=H|<&ZooK(}V59osHK|um8Wfx;)OJM%O1qX6c)s}@#kF)%PNc)I$ztaD0e0sxN0VR8Tf diff --git a/wadsrc/static/sprites/PLS2D0.png b/wadsrc/static/sprites/PLS2D0.png index b5be3aaf1f12f317a878e9ce1d5f97a3159f31f1..a3850aba6528e447569883fdeb0f68a8aaa62bfd 100644 GIT binary patch delta 154 zcmey%_=|CZ1SbbG0|NsOM{31H#gO^}PZ!6Kid(jQjzWhOc$lxU8EpIa|Ngp6A=wRK zCz!2nZF1_DDLR$?^Ze-zThkct@)%tH?w2q{XF<@)!gO}yUGIvrdKw>x#RtD=?N!{V zz@-`SW3_Ys2D@eUsp9nyw+K|;UMlBQ+YV#cm5O8}aJa6e{mTiaS6f}6Q zevM^Zx$_&FF(>D;XVXj4il4}R?qn`0Tax-XtGS^$%vSb|#op{~mM=q$Wc}l=u3HdM zE`IXnk`={W{cEN~Ce8l4zI*fL?Gi>Tu}?llFzvW`{R;CP$=MC&|HZ{LwPTo<3NSD* Pa58wh`njxgN@xNAZTdpL diff --git a/wadsrc/static/sprites/amrka0.png b/wadsrc/static/sprites/amrka0.png index c95d00afeae69ed14c5b85900acfac42286eb877..159fe75c282921ca1d46780629e74f471419ea9a 100644 GIT binary patch delta 103 zcmaFG_=<5tSHi8>K2ISAMGofBGV?$Gv)%U?S}xUQ_2l%_@ToAko29@nR{i>HB`cHv zp+*zQycECX*Q!qVc4ZuvI<#zhnS8(7{rx)kpU&T@pMTQY-uDLcDz+khLk0#022WQ% Jmvv4FO#okiDB}PC delta 103 zcmaFG_=<5tS3+EDpS#cj1s>)?-7A0oZ)Geh`nGNH#I;2moPQc{&6g{=+orc>M~RH; z+e5uewclz?vtjsff=m0^iGqYLxtq6TuRRw(t@>x$zve3!MtjdNz`Np1_lOC LS3j3^P6G5rMS4XqXH3%GgQtP1RnLUWMF7>VZXEF#Q8b~1_lOCS3j3^P6%W0)i=wTfFpVwRFA tuY^RL00|SGntDnm{r-UW|PRJwh diff --git a/wadsrc/static/sprites/icecc0.png b/wadsrc/static/sprites/icecc0.png index d8f4a3786512a239748f8a685e5f90ef18b6b247..8865d990947ebe99542fda4fc962c7b67832643e 100644 GIT binary patch delta 64 zcmZ3?IGb^T1SbnK0|Ud_w;bOlD*EY&d%8G=aL6VnB={sHB&?Zn?tns?kO~6>pBs}x UGXJ}K3=9kmp00i_>zopr09pSM-~a#s delta 72 zcmbQuxR`N*1SbbG0|P^b?9=ZP75z-)JzX3_D&klVY~*E7;9xnhpXq!2b(RYri>i($ d>YJYVZP(7uD)?jFF9rq%22WQ%mvv4FO#o3%83O|K)!OXzGuxiybjfsjzssf%ajv*Cs$q6ZmDG3Q_ObiSr3_MYSC%!Q-Ffe$! L`njxgN@xNAq3RDk diff --git a/wadsrc/static/sprites/rsmka0.png b/wadsrc/static/sprites/rsmka0.png index cee476cd1086713c7b80826b28bb55b0fd7372ff..761e0917098045c068c8ca7e4c9153c3c3989a1a 100644 GIT binary patch delta 279 zcmbQn{DWzN1SbbG0|SHWW&LFn6~pQoUVFMYhE&`tofIw99Khim{hpiYcYHo`QvTe& zpO>A53TmdFdGl4}zR_(qYrKxA0x~ zxk0+@McC)d-5!74uVjktW?n3`eYYkf!=bhM&1<%@q^|AB-n-N))RUX($l3*dUe{Sa z*ZZxGuwo9=Td1LKJ9D;6)>O0pM7vv+?Q6YwEBS&`Tff~qAMu1`t>Nq`1wBh9s6KIs z6+36ym%L}DkNduL*@v_k`#(%l{qxtWc!JSP>28LWo8d{%E55Jue9?Vmt!4FG;S-m3 nh<3l?+HreZ#*hD{cFi{g7B{n-buln7FnGH9xvXP$N@xNAfTDZ| delta 309 zcmeytG>v(J1SbnK0|P^Y@}cDu6~pQoIXzt*Ln`8Y`!{ACHV|lIZ4JokU&=4=Vjla8 z8zP(9e(-i3^cPU&zhL3@{KTm%E2ou8a>+`m@Ur&rYJauTuj!ws{P+L==SpZ6>rCa0 z*UXxmbZv%6KL73S91p8!$Zg+!BV1lT_P`9`S51}YXPAF=zm%{(uB_R1_iMgzrzPv| z)=M^h?wI^p$0D1ICUz)48E}l2J%l-M?&)&>pb7DOe%FSa#oQjj9Pi^>9{O^ZC_@rjzKC}I2 zk9T|NTJn_lb`=^v-rDHkFiY&av7?*)gBPajoSrM*RMFTf|G-pfq}uv;$Xx?#ejN-zn(6RAr-flPKp*ftia)#E5h<^|AQh<&n;{J zeeqKhE~?N!vZOLL~dXW=>LPW(y=T;3~~Zs?kusMeOil->BG z-bC`~xp_;B=Xjr3BFo-1cjH~-7rxnRbu~OUI=!$~++~$zyJ(Z!59Ol$_hv1BCMR>g znK#y=sbT(_nUR0YuM}z-yA^2dnRIUYls{IF_+=JepL1F1>DyzRjjyJ}3Ln2KFpbso z*i|n1DXqL#eXZ~BtX*UJHg%WAhc%Xrx-b2<98WzWn!ojcK6|QhbiVxZX)jt9zEgMDv#qaV*}}YKDy56Jbys|?yL{uz&NbC{p7E>Ceztw7 zvyvju_V0Vw)Zd-ozy6osY)!={jBaU&Bu^uujAj4; diff --git a/wadsrc/static/sprites/rsmkc0.png b/wadsrc/static/sprites/rsmkc0.png index 17b121bf96cc07256e40638a4b0a764dcd7fd686..3e952cdba97ade70efd5bfecf4964af5655040cf 100644 GIT binary patch delta 456 zcmdnbvW#Vd1SbbG0|SGl!y0hdp5at`+to zeW&Qg1p=$S#^mO%ZH)EWw?JX-lsj(cQm=$t@^O$ahn&*#zm@gwI-~(kW{(g=8m-u4KNom0bT3JNzIMuGWfO^p)iWFC zrre$%mb>v(&()T$JwIAG)=PX*wm)3;McYSX%Hj0?^=|}TpW`!S3ozKl{3AHv=9TG- zODy^-CSKkA#`)jFgyq38^F$lxYB+4OyqNQ1K1+$|B+<83XD>=vEY5!^eYVN0W>(-Y zOZ~-ZKh$3LuDzUfdPcQ$&Z8Th!E-<`?|WXeQ;yt=$>FZs8v%)?a(p zi>Kr{SLo0A94bB6grO}@HoSJPRyyD1-Ic%DB@fs1ubpdN_Vu3i@A|vGU&Xh!$#Ne% TeK(YWfq}u()z4*}Q$iB}saV~J delta 481 zcmZ3+vY%yw1SbnK0|UdKjqGP9Du&c=^>lFzsff#+u)lAyfk1n#i+bu`mF27bG=jW- zP0`Sfd%*CK!C{4;RpOeE@HHa6cXL{kmoHrK@z>KlAF~;EZ)@)V`DM2Kk?F-PId?ql zL`wCJ_5JSe^VsXde7EAez>7AWogRXhFJ69Wo8#FWc*CZD2imi`+F~Q~c%uie5o7Vmkek++2`t(_T#CFf1cd0gQHPI=71=q3!qK-8N z8E}O%y!2SWe!%G1>?fN1>!yWWId*>kKfZL0w=QAzSs_1PPg3YIj^SDsXxr`|XSK|A z;_Df4B?}f+Ut4r)sjyogx7+y{ir2$Z`yapI-nh*5R(9dj@BH}-_X%=W((v?1_lOCS3j3^P6yo4x<&Kj}@5|xOu+IFB$rsA% z=Hxz5JU@At!pECwHGF$la`ep1Y4Z!LR_}UN_s`n@N$iR58q)4wBS4-}}E z?=w?c9p%1#+d1`Z)i*7F)qHiC$F203Vodyes>5MYI*9ste?O*!)cPz z`eSu>^A6vf@AR;d3O)a$-%kw<9chO(d*RiMAQp(*$@b5Q!zpFJ_@liW3F)%PNc)I$z JtaD0e0s!UGe=Pt2 diff --git a/wadsrc/static/sprites/rsmke0.png b/wadsrc/static/sprites/rsmke0.png index 930b30a589fd62619477705862499d082c95a19b..9d5652bd2556813eb6da09cb0fe703238d6dd2f5 100644 GIT binary patch delta 156 zcmZo=`p-B)f|G-pfq}uBG5*y=#qjzfPZ!6Kid$zdZWKIVz`=arh@pbwxB2FJvU?n^ zd}L=`{@NpS`Ub&!g+2}b&JL&Q)(3mdKI;Vst0Ao%`8vpghJWIsz!7srr_IM#+%!3GC`Bb(IUulRCbi}{8DvxIF8*Rg5tCpATW-|gbA r%zQ6-EOfKYP1eB6zmun7#KWV{an^LB{Ts5(QF{W delta 86 zcmaFJ_=s`BWPdA97srr_INoDN84oxJFgZk6cSiqT+jgCYVRjl*af|+xXt}9U$@{B! sKDv6}m?!*nRgpkM^bd8@O^o)&#f)VSmhYP%kYlZEbC>udnay?Ci|Ipsud2tgJkJ`tYjk@e Q0|Nttr>mdKI;Vst02v-k1^@s6 delta 213 zcmeBX>SdbXP_M48Zf$L?udnay>>M5*?##d-EiHZj{(WU-Wnp3A=;-Kf28Qk1wPx) zF{C0+_lzeWvm+0a!{e>jZ>s`YmGFUokE6R2P5X*FvlB z@8=60tG2n2x9w)$u_Na{@;#X|l{K`eh_AiFfZ0^ZUvE0g5hu>Au32l>{$tjg%KTGM TY25<`1_lOCS3j3^P60zVl7oSPf#J@#2E&Pp;`K}=L4Lsu3}utgS}-s$q3iF@VN$>chnK8hup^q(WqoN~o&HtXSa)%WXIr$hE7&sX` MUHx3vIVCg!0C@~H)Bpeg delta 225 zcmX@W*vd3Pl7pFnf#IC9{{4xH;`L4eJ|V6Q3=G!R*3Qn(;o;%g+1bg-$@=>G_4W1Y z>gwCKZ;y_So<4oLva+(YwDjuLtGm0qFJHcV|Ni~SlP3!c3m-pz+~427JndWr0|NtN zNswPKgTu2MX$%Yuv7RoDAr*0^r`*LF95|RSTv&Gd>%Z`+2cO4JWN~mgbL7ezQ!&3Z zwFcAO_s$#FPvP*tpSAXN)%)LtXBOwP1YUh}Uu~Ufn$jVsM7DWBTCArfj!yJeJavCg hkVMBfuKzvaDLgEvIoJ6WF)%PNc)I$ztaD0e0stC@TL=IE diff --git a/wadsrc/static/sprites/sgrna8a2.png b/wadsrc/static/sprites/sgrna8a2.png index 5bbf9da782bbf180aece27f24000e8e9c03b704b..10bfa946276a3b3fee068dc1bd690e4f46598007 100644 GIT binary patch delta 162 zcmey(c#Ls^BnJZn1H)BW1@DQ9;`K}=L4Lsu3}utgS}-s$WP7?ehH%L09$YAR#DIt8 z!0Uqn0S^{%S*&2<;pO3F-q*seskBsLnaFmbbhX_KMbdvQs(cfFuig19s@V6gdgC6u z*zy-8E4JQp%eJk&`bYR7&r+kwQl%VeeqMr(6R$E>Pu!>}J3CVI=(a~Ja>tJ<@7%(_ S{>NRAb39%BT-G@yGywq4*F6yc delta 215 zcmX@c_?vNpBnLAC1H+35kD~E@N`}_MR zCnpOF3r9ysOG`^npFVy6{{79(&Dq)6_wV1|zI}Usetvy@{f?ZpbOr_n#*!evU@!`6Fl*{7{`?{`|#v@Eyqi=&LYSBgtVkbj6~kjSoYdd25r)46^yexJqc V6?IJ51Scai0|P^E_?vYT6*c`VJzX3_IIbrrFfhKJm%_%je1RBS+Y3*JY2gzb zn42e_FJ|L-U=qWmvd2V1;>TW|hBaCW-It3wU4$6om^hdJw@I{OU|?YIboFyt=akR{ E03cl;00000 delta 105 zcmbQiIG=HX1SbbG0|P^Yd*A(uikhJgo-U3d6}MXZ7`Ye}IF8);Zy(FXY`WsGSVd1) zdPA`io0Gzwr%R_A>$dd0V0tw9C&%oyLYKI*roIrn6ZUu4FKce+9){RP2L5LZ3=9mO Lu6{1-oD!M<#APRa diff --git a/wadsrc/static/sprites/tlglb0.png b/wadsrc/static/sprites/tlglb0.png index 829a255268ac497f67edd0d0180d23ca031b5e82..de3dccc3424a9cf5512e8487cffaf4517c7ad662 100644 GIT binary patch delta 98 zcmbQwID>J51Scai0|P^E_?vYT6*c`VJzX3_IIbrrFfhKJm%_%je1RBS+Y3*JY2gzb zn42e_FJ|L-U=qWmvd2V1;>TW|hBaCW-It3wU4$6om^hdJw@I{OU|?YIboFyt=akR{ E03cl;00000 delta 105 zcmbQiIG=HX1SbbG0|P^Yd*A(uikhJgo-U3d6}MXZ7`Ye}IF8);Zy(FXY`WsGSVd1) zdPA`io0Gzwr%R_A>$dd0V0tw9C&%oyLYKI*roIrn6ZUu4FKce+9){RP2L5LZ3=9mO Lu6{1-oD!M<#APRa diff --git a/wadsrc/static/sprites/tlglc0.png b/wadsrc/static/sprites/tlglc0.png index 829a255268ac497f67edd0d0180d23ca031b5e82..de3dccc3424a9cf5512e8487cffaf4517c7ad662 100644 GIT binary patch delta 98 zcmbQwID>J51Scai0|P^E_?vYT6*c`VJzX3_IIbrrFfhKJm%_%je1RBS+Y3*JY2gzb zn42e_FJ|L-U=qWmvd2V1;>TW|hBaCW-It3wU4$6om^hdJw@I{OU|?YIboFyt=akR{ E03cl;00000 delta 105 zcmbQiIG=HX1SbbG0|P^Yd*A(uikhJgo-U3d6}MXZ7`Ye}IF8);Zy(FXY`WsGSVd1) zdPA`io0Gzwr%R_A>$dd0V0tw9C&%oyLYKI*roIrn6ZUu4FKce+9){RP2L5LZ3=9mO Lu6{1-oD!M<#APRa diff --git a/wadsrc/static/sprites/tlgld0.png b/wadsrc/static/sprites/tlgld0.png index 829a255268ac497f67edd0d0180d23ca031b5e82..de3dccc3424a9cf5512e8487cffaf4517c7ad662 100644 GIT binary patch delta 98 zcmbQwID>J51Scai0|P^E_?vYT6*c`VJzX3_IIbrrFfhKJm%_%je1RBS+Y3*JY2gzb zn42e_FJ|L-U=qWmvd2V1;>TW|hBaCW-It3wU4$6om^hdJw@I{OU|?YIboFyt=akR{ E03cl;00000 delta 105 zcmbQiIG=HX1SbbG0|P^Yd*A(uikhJgo-U3d6}MXZ7`Ye}IF8);Zy(FXY`WsGSVd1) zdPA`io0Gzwr%R_A>$dd0V0tw9C&%oyLYKI*roIrn6ZUu4FKce+9){RP2L5LZ3=9mO Lu6{1-oD!M<#APRa diff --git a/wadsrc/static/sprites/tlgle0.png b/wadsrc/static/sprites/tlgle0.png index 829a255268ac497f67edd0d0180d23ca031b5e82..de3dccc3424a9cf5512e8487cffaf4517c7ad662 100644 GIT binary patch delta 98 zcmbQwID>J51Scai0|P^E_?vYT6*c`VJzX3_IIbrrFfhKJm%_%je1RBS+Y3*JY2gzb zn42e_FJ|L-U=qWmvd2V1;>TW|hBaCW-It3wU4$6om^hdJw@I{OU|?YIboFyt=akR{ E03cl;00000 delta 105 zcmbQiIG=HX1SbbG0|P^Yd*A(uikhJgo-U3d6}MXZ7`Ye}IF8);Zy(FXY`WsGSVd1) zdPA`io0Gzwr%R_A>$dd0V0tw9C&%oyLYKI*roIrn6ZUu4FKce+9){RP2L5LZ3=9mO Lu6{1-oD!M<#APRa From 6a5ab0edc0b79ffe93831ec4266a82ecf7fd7245 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Sep 2009 02:27:48 +0000 Subject: [PATCH 002/241] - Fixed: FMultiPatchTexture::CopyTrueColorPixels() should clear the buffer first before drawing into it if the copy op passed to it is OP_OVERWRITE. FTexture::FillBuffer() sets this to erase whatever texture might have been in the space it is going into. SVN r1874 (trunk) --- docs/rh-log.txt | 6 ++++++ src/textures/bitmap.cpp | 14 ++++++++++++++ src/textures/bitmap.h | 1 + src/textures/multipatchtexture.cpp | 7 ++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ac304a52d..a5bee140a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +September 24, 2009 +- Fixed: FMultiPatchTexture::CopyTrueColorPixels() should clear the buffer + first before drawing into it if the copy op passed to it is OP_OVERWRITE. + FTexture::FillBuffer() sets this to erase whatever texture might have been + in the space it is going into. + September 22, 2009 - Added a technique to try and minimize input lag with vsync enabled: Two surfaces are alternately locked for read-only access each frame, forcing diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index 913aa507e..f1d78c478 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -477,3 +477,17 @@ void FBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int sr } } +//=========================================================================== +// +// Clear buffer +// +//=========================================================================== +void FBitmap::Zero() +{ + BYTE *buffer = data; + for (int y = 0; y < Height; ++y) + { + memset(buffer, 0, Width*4); + buffer += Pitch; + } +} diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 04bd580cd..35bdf62a2 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -116,6 +116,7 @@ public: return data; } + void Zero(); virtual void CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL); diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 4b9bd5e1b..66c5276a3 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -550,7 +550,12 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i if (w < 0 || w > Width) w = Width; if (h < 0 || h > Height) h = Height; - for(int i=0;iop == OP_OVERWRITE) + { + bmp->Zero(); + } + + for(int i = 0; i < NumParts; i++) { int ret = -1; From 2ad438d696028630c30c0252cc047acce9a8d05a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Sep 2009 02:54:13 +0000 Subject: [PATCH 003/241] - Changed P_XYMovement() to not call P_SlideMove() if the act of being blocked changed the actor's velocity. I'm not entirely happy with this, but it gets push-activated force fields to work. SVN r1875 (trunk) --- docs/rh-log.txt | 3 +++ src/p_lnspec.cpp | 4 +++- src/p_mobj.cpp | 57 +++++++++++++++++++++++++++++------------------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a5bee140a..5d758f967 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ September 24, 2009 +- Changed P_XYMovement() to not call P_SlideMove() if the act of being + blocked changed the actor's velocity. I'm not entirely happy with this, + but it gets push-activated force fields to work. - Fixed: FMultiPatchTexture::CopyTrueColorPixels() should clear the buffer first before drawing into it if the copy op passed to it is OP_OVERWRITE. FTexture::FillBuffer() sets this to erase whatever texture might have been diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 17333f7d7..14585e016 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2796,7 +2796,9 @@ FUNC(LS_ForceField) if (it != NULL) { P_DamageMobj (it, NULL, NULL, 16, NAME_None); - P_ThrustMobj (it, it->angle + ANGLE_180, 0x7D000); + angle_t an = (it->angle + ANGLE_180) >> ANGLETOFINESHIFT; + it->velx = FixedMul(0x7D000, finecosine[an]); + it->vely = FixedMul(0x7D000, finesine[an]); } return true; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b070adef1..8449924ef 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1736,6 +1736,8 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) */ // [RH] If walking on a slope, stay on the slope // killough 3/15/98: Allow objects to drop off + fixed_t startvelx = mo->velx, startvely = mo->vely; + if (!P_TryMove (mo, ptryx, ptryy, true, walkplane, tm)) { // blocked move @@ -1759,35 +1761,44 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) { mo->velz = WATER_JUMP_SPEED; } - if (player && (i_compatflags & COMPATF_WALLRUN)) + // If the blocked move executed any push specials that changed the + // actor's velocity, do not attempt to slide. + if (mo->velx == startvelx && mo->vely == startvely) { - // [RH] Here is the key to wall running: The move is clipped using its full speed. - // If the move is done a second time (because it was too fast for one move), it - // is still clipped against the wall at its full speed, so you effectively - // execute two moves in one tic. - P_SlideMove (mo, mo->velx, mo->vely, 1); + if (player && (i_compatflags & COMPATF_WALLRUN)) + { + // [RH] Here is the key to wall running: The move is clipped using its full speed. + // If the move is done a second time (because it was too fast for one move), it + // is still clipped against the wall at its full speed, so you effectively + // execute two moves in one tic. + P_SlideMove (mo, mo->velx, mo->vely, 1); + } + else + { + P_SlideMove (mo, onestepx, onestepy, totalsteps); + } + if ((mo->velx | mo->vely) == 0) + { + steps = 0; + } + else + { + if (!player || !(i_compatflags & COMPATF_WALLRUN)) + { + xmove = mo->velx; + ymove = mo->vely; + onestepx = xmove / steps; + onestepy = ymove / steps; + P_CheckSlopeWalk (mo, xmove, ymove); + } + startx = mo->x - Scale (xmove, step, steps); + starty = mo->y - Scale (ymove, step, steps); + } } else - { - P_SlideMove (mo, onestepx, onestepy, totalsteps); - } - if ((mo->velx | mo->vely) == 0) { steps = 0; } - else - { - if (!player || !(i_compatflags & COMPATF_WALLRUN)) - { - xmove = mo->velx; - ymove = mo->vely; - onestepx = xmove / steps; - onestepy = ymove / steps; - P_CheckSlopeWalk (mo, xmove, ymove); - } - startx = mo->x - Scale (xmove, step, steps); - starty = mo->y - Scale (ymove, step, steps); - } } else { // slide against another actor From d816747c7e6736c6d6338c0b4ddcecfa9da3113f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Sep 2009 03:07:20 +0000 Subject: [PATCH 004/241] - Fixed: "give health" without an amount would set your health to IDDQD health instead of the player class's maximum. - Fixed: A_CStaffCheck() assumed the player's max health was 100 instead of getting checking for the true maximum. SVN r1876 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_hexen/a_clericstaff.cpp | 9 +++++---- src/m_cheat.cpp | 14 +++++++++----- src/p_lnspec.cpp | 4 +--- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5d758f967..f78b398ee 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ September 24, 2009 +- Fixed: "give health" without an amount would set your health to IDDQD health + instead of the player class's maximum. +- Fixed: A_CStaffCheck() assumed the player's max health was 100 instead + of getting checking for the true maximum. - Changed P_XYMovement() to not call P_SlideMove() if the act of being blocked changed the actor's velocity. I'm not entirely happy with this, but it gets push-activated force fields to work. diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index 220dc55e7..38018071c 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -46,9 +46,9 @@ int ACStaffMissile::DoSpecialDamage (AActor *target, int damage) DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) { - AActor *pmo; + APlayerPawn *pmo; int damage; - int newLife; + int newLife, max; angle_t angle; int slope; int i; @@ -63,6 +63,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) pmo = player->mo; damage = 20+(pr_staffcheck()&15); + max = pmo->GetMaxHealth(); for (i = 0; i < 3; i++) { angle = pmo->angle+i*(ANG45/16); @@ -76,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) && (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE)))) { newLife = player->health+(damage>>3); - newLife = newLife > 100 ? 100 : newLife; + newLife = newLife > max ? max : newLife; if (newLife > player->health) { pmo->health = player->health = newLife; @@ -99,7 +100,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER) { newLife = player->health+(damage>>4); - newLife = newLife > 100 ? 100 : newLife; + newLife = newLife > max ? max : newLife; pmo->health = player->health = newLife; P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index bcf36d45d..508043f47 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -52,7 +52,7 @@ void cht_DoCheat (player_t *player, int cheat) { - static const PClass *BeholdPowers[9] = + static const PClass * const BeholdPowers[9] = { RUNTIME_CLASS(APowerInvulnerable), RUNTIME_CLASS(APowerStrength), @@ -631,10 +631,14 @@ void cht_Give (player_t *player, const char *name, int amount) } else { - if (player->mo) - player->mo->health = deh.GodHealth; - - player->health = deh.GodHealth; + if (player->mo != NULL) + { + player->health = player->mo->health = player->mo->GetMaxHealth(); + } + else + { + player->health = deh.GodHealth; + } } if (!giveall) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 14585e016..17333f7d7 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2796,9 +2796,7 @@ FUNC(LS_ForceField) if (it != NULL) { P_DamageMobj (it, NULL, NULL, 16, NAME_None); - angle_t an = (it->angle + ANGLE_180) >> ANGLETOFINESHIFT; - it->velx = FixedMul(0x7D000, finecosine[an]); - it->vely = FixedMul(0x7D000, finesine[an]); + P_ThrustMobj (it, it->angle + ANGLE_180, 0x7D000); } return true; } From 3ff95001f538a2ff40c1cc22a89f4979d715bbb5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Sep 2009 22:15:56 +0000 Subject: [PATCH 005/241] - fixed: The changes for new colormap handling in FMultipatchtexture were incomplete. Some code was still checking Blend.r instead of the full variable for colormap indices. SVN r1879 (trunk) --- src/textures/multipatchtexture.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 66c5276a3..2f83edd3f 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -576,9 +576,9 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i else { PalEntry b = Parts[i].Blend; - if (b.a == 0 && b.r != BLEND_NONE) + if (b.a == 0 && b != BLEND_NONE) { - info.blend = EBlend(b.r); + info.blend = EBlend(b.d); } else if (b.a != 0) { From 23c0f2416046126a0fceb9e28643d502f3d3d605 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Sep 2009 22:28:55 +0000 Subject: [PATCH 006/241] - Fixed: The multitexture composition code was missing a NULL pointer check. SVN r1880 (trunk) --- src/textures/multipatchtexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 2f83edd3f..722d8aad3 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -550,7 +550,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i if (w < 0 || w > Width) w = Width; if (h < 0 || h > Height) h = Height; - if (inf->op == OP_OVERWRITE) + if (inf != NULL && inf->op == OP_OVERWRITE) { bmp->Zero(); } From e846e5e50fc0b4f769a7783be540e5307f2649de Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 27 Sep 2009 02:01:24 +0000 Subject: [PATCH 007/241] - idclev and hxvisit are no longer considered cheats, however, they are still invalid for net games. hxvisit was erroneously accepted for net games before, which it shouldn't have, since it's basically idclev for Hexen. SVN r1881 (trunk) --- docs/rh-log.txt | 5 +++++ src/c_cmds.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f78b398ee..d44d88588 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +September 26, 2009 +- idclev and hxvisit are no longer considered cheats, however, they are still + invalid for net games. hxvisit was erroneously accepted for net games + before, which it shouldn't have, since it's basically idclev for Hexen. + September 24, 2009 - Fixed: "give health" without an amount would set your health to IDDQD health instead of the player class's maximum. diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index ed27e2d27..4e0aa8b32 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -253,7 +253,7 @@ CCMD (chase) CCMD (idclev) { - if (CheckCheatmode () || netgame) + if (netgame) return; if ((argv.argc() > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1]) @@ -291,7 +291,7 @@ CCMD (idclev) CCMD (hxvisit) { - if (CheckCheatmode ()) + if (netgame) return; if ((argv.argc() > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1]) From c801bb7f49c752839e6e448f02fd36e3a9c6375c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 27 Sep 2009 02:13:28 +0000 Subject: [PATCH 008/241] - Added a check for SPAC_AnyCross to P_TestActivateLine() before the "monster" activation checks. They are actually non-player checks and interfered with SPAC_AnyCross. SVN r1882 (trunk) --- docs/rh-log.txt | 3 +++ src/p_spec.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index d44d88588..1483d0b83 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ September 26, 2009 +- Added a check for SPAC_AnyCross to P_TestActivateLine() before the "monster" + activation checks. They are actually non-player checks and interfered with + SPAC_AnyCross. - idclev and hxvisit are no longer considered cheats, however, they are still invalid for net games. hxvisit was erroneously accepted for net games before, which it shouldn't have, since it's basically idclev for Hexen. diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 8f092fc9d..82d91489d 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -311,7 +311,10 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType) return false; } } - + if (activationType == SPAC_AnyCross && (lineActivation & activationType)) + { + return true; + } if (mo && !mo->player && !(mo->flags & MF_MISSILE) && !(line->flags & ML_MONSTERSCANACTIVATE) && From 1eb4241663fb9d2770fdaf5d7371db13279751f5 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 27 Sep 2009 02:31:03 +0000 Subject: [PATCH 009/241] - Fixed: R_DrawPSprite() did not initialize the colormap for the targeter vissprites. SVN r1883 (trunk) --- docs/rh-log.txt | 2 ++ src/asm_ia32/tmap.asm | 4 ---- src/r_things.cpp | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1483d0b83..29d38e45d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ September 26, 2009 +- Fixed: R_DrawPSprite() did not initialize the colormap for the targeter + vissprites. - Added a check for SPAC_AnyCross to P_TestActivateLine() before the "monster" activation checks. They are actually non-player checks and interfered with SPAC_AnyCross. diff --git a/src/asm_ia32/tmap.asm b/src/asm_ia32/tmap.asm index e6658f20f..e4c477598 100644 --- a/src/asm_ia32/tmap.asm +++ b/src/asm_ia32/tmap.asm @@ -623,10 +623,6 @@ rdcp1: sub edi,SPACEFILLER4 cmp BYTE [CPU+66],byte 5 jg rdcploop2 -; need 12 bytes of filler to make it aligned - db 0x8D,0x80,0,0,0,0 ; lea eax,[eax+00000000] - db 0x8D,0xBF,0,0,0,0 ; lea edi,[edi+00000000] - align 16 ; The registers should now look like this: diff --git a/src/r_things.cpp b/src/r_things.cpp index 3e9b8b0b3..be5499e3e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1699,6 +1699,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_ else { VisPSpritesBaseColormap[pspnum] = basecolormap; + vis->colormap = basecolormap->Maps; vis->RenderStyle = STYLE_Normal; } From c628ac48cd2d7536d7239028c9d972981a4a1963 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Sep 2009 07:17:51 +0000 Subject: [PATCH 010/241] - Fixed: G_QueueBody was not notifying the translation that it was changed. SVN r1884 (trunk) --- docs/rh-log.txt | 6 ++++++ src/g_game.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 29d38e45d..0e7730d9c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +September 27, 2009 (Changes by Graf Zahl) +- Fixed: G_QueueBody was not notifying the translation that it was changed. +- Fixed: The multitexture composition code was missing a NULL pointer check. +- fixed: The changes for new colormap handling in FMultipatchtexture were incomplete. + Some code was still checking Blend.r instead of the full variable for colormap indices. + September 26, 2009 - Fixed: R_DrawPSprite() did not initialize the colormap for the targeter vissprites. diff --git a/src/g_game.cpp b/src/g_game.cpp index 43587bb08..c617f9804 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1506,6 +1506,7 @@ static void G_QueueBody (AActor *body) { *translationtables[TRANSLATION_PlayerCorpses][modslot] = *TranslationToTable(body->Translation); body->Translation = TRANSLATION(TRANSLATION_PlayerCorpses,modslot); + translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative(); } bodyqueslot++; From f2c77c5f084fc620c986ff1df3a9114457eab98a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Sep 2009 20:54:46 +0000 Subject: [PATCH 011/241] - Fixed: Floor and ceiling huggers' velocity was wrong when used with P_SpawnPlayerMissile. - Fixed: When hitting a voodoo doll the real player needs to be checked for invulnerability. SVN r1885 (trunk) --- docs/rh-log.txt | 4 ++++ src/p_interaction.cpp | 6 ++++-- src/p_mobj.cpp | 14 +++++++------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0e7730d9c..b6b563dc2 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ September 27, 2009 (Changes by Graf Zahl) +- Fixed: Floor and ceiling huggers' velocity was wrong when used with + P_SpawnPlayerMissile. +- Fixed: When hitting a voodoo doll the real player needs to be checked for + invulnerability. - Fixed: G_QueueBody was not notifying the translation that it was changed. - Fixed: The multitexture composition code was missing a NULL pointer check. - fixed: The changes for new colormap handling in FMultipatchtexture were incomplete. diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b508d8f55..a062281f9 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1088,6 +1088,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage // if (player) { + //Added by MC: Lets bots look allround for enemies if they survive an ambush. if (player->isbot) { @@ -1103,8 +1104,9 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage if (!(flags & DMG_FORCED)) { - if (damage < TELEFRAG_DAMAGE && ((target->flags2 & MF2_INVULNERABLE) || - (target->player->cheats & CF_GODMODE))) + // check the real player, not a voodoo doll here for invulnerability effects + if (damage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) || + (player->cheats & CF_GODMODE))) { // player is invulnerable, so don't hurt him return; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8449924ef..7d2f4c58d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5177,16 +5177,16 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, vz = -finesine[pitch>>ANGLETOFINESHIFT]; speed = MissileActor->Speed; - MissileActor->velx = FixedMul (vx, speed); - MissileActor->vely = FixedMul (vy, speed); + FVector3 vec(vx, vy, vz); + if (MissileActor->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)) { - MissileActor->velz = 0; - } - else - { - MissileActor->velz = FixedMul (vz, speed); + vec.Z = 0; } + vec.Resize(speed); + MissileActor->velx = (fixed_t)vec.X; + MissileActor->vely = (fixed_t)vec.Y; + MissileActor->velz = (fixed_t)vec.Z; if (MissileActor->flags4 & MF4_SPECTRAL) MissileActor->health = -1; From 6d357b84b47eb797ff340c07bcbd1469ad4f26f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Sep 2009 15:55:57 +0000 Subject: [PATCH 012/241] - Added Gez's A_Blast submission. SVN r1886 (trunk) --- docs/rh-log.txt | 3 + src/g_hexen/a_blastradius.cpp | 224 ++++++++---------- wadsrc/static/actors/actor.txt | 1 + wadsrc/static/actors/constants.txt | 13 + wadsrc/static/actors/hexen/blastradius.txt | 4 +- wadsrc/static/actors/{doom => shared}/dog.txt | 25 +- wadsrc/static/decorate.txt | 2 +- 7 files changed, 134 insertions(+), 138 deletions(-) rename wadsrc/static/actors/{doom => shared}/dog.txt (56%) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b6b563dc2..a631d1213 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +September 28, 2009 (Changes by Graf Zahl) +- Added Gez's A_Blast submission. + September 27, 2009 (Changes by Graf Zahl) - Fixed: Floor and ceiling huggers' velocity was wrong when used with P_SpawnPlayerMissile. diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index bbc9af2d2..6e3b0052b 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -8,87 +8,21 @@ #include "s_sound.h" */ +/* For reference, the default values: #define BLAST_RADIUS_DIST 255*FRACUNIT #define BLAST_SPEED 20*FRACUNIT #define BLAST_FULLSTRENGTH 255 +*/ // Disc of Repulsion -------------------------------------------------------- -class AArtiBlastRadius : public AInventory -{ - DECLARE_CLASS (AArtiBlastRadius, AInventory) -public: - bool Use (bool pickup); -protected: - void BlastActor (AActor *victim, fixed_t strength); -}; - -IMPLEMENT_CLASS (AArtiBlastRadius) - -//========================================================================== -// -// AArtiBlastRadius :: Activate -// -// Blast all actors away -// -//========================================================================== - -bool AArtiBlastRadius::Use (bool pickup) -{ - AActor *mo; - TThinkerIterator iterator; - fixed_t dist; - - S_Sound (Owner, CHAN_AUTO, "BlastRadius", 1, ATTN_NORM); - P_NoiseAlert (Owner, Owner); - - while ( (mo = iterator.Next ()) ) - { - if ((mo == Owner) || (mo->flags2 & MF2_BOSS)) - { // Not a valid monster - continue; - } - if ((mo->flags & MF_ICECORPSE) || (mo->flags3 & MF3_CANBLAST)) - { - // Let these special cases go - } - else if ((mo->flags3 & MF3_ISMONSTER) && (mo->health <= 0)) - { - continue; - } - else if (!(mo->flags3 & MF3_ISMONSTER) && - !(mo->player) && - !(mo->flags & MF_MISSILE) && - !(mo->flags3 & MF3_CANBLAST) && - !(mo->flags6 & MF6_TOUCHY)) - { // Must be monster, player, missile, or touchy - continue; - } - if (mo->flags2 & MF2_DORMANT) - { - continue; // no dormant creatures - } - if (mo->flags3 & MF3_DONTBLAST) - { // A few things that would normally be blastable should not be blasted - continue; - } - dist = P_AproxDistance (Owner->x - mo->x, Owner->y - mo->y); - if (dist > BLAST_RADIUS_DIST) - { // Out of range - continue; - } - BlastActor (mo, BLAST_FULLSTRENGTH); - } - return true; -} - //========================================================================== // // AArtiBlastRadius :: BlastActor // //========================================================================== -void AArtiBlastRadius::BlastActor (AActor *victim, fixed_t strength) +void BlastActor (AActor *victim, fixed_t strength, fixed_t speed, AActor * Owner, const PClass * blasteffect) { angle_t angle,ang; AActor *mo; @@ -101,72 +35,116 @@ void AArtiBlastRadius::BlastActor (AActor *victim, fixed_t strength) angle = R_PointToAngle2 (Owner->x, Owner->y, victim->x, victim->y); angle >>= ANGLETOFINESHIFT; - if (strength < BLAST_FULLSTRENGTH) + victim->velx = FixedMul (speed, finecosine[angle]); + victim->vely = FixedMul (speed, finesine[angle]); + + // Spawn blast puff + ang = R_PointToAngle2 (victim->x, victim->y, Owner->x, Owner->y); + ang >>= ANGLETOFINESHIFT; + x = victim->x + FixedMul (victim->radius+FRACUNIT, finecosine[ang]); + y = victim->y + FixedMul (victim->radius+FRACUNIT, finesine[ang]); + z = victim->z - victim->floorclip + (victim->height>>1); + mo = Spawn (blasteffect, x, y, z, ALLOW_REPLACE); + if (mo) { - victim->velx = FixedMul (strength, finecosine[angle]); - victim->vely = FixedMul (strength, finesine[angle]); - if (victim->player) + mo->velx = victim->velx; + mo->vely = victim->vely; + } + if (victim->flags & MF_MISSILE) + { + // [RH] Floor and ceiling huggers should not be blasted vertically. + if (!(victim->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) { - // Players handled automatically - } - else - { - victim->flags2 |= MF2_BLASTED; + victim->velz = 8*FRACUNIT; + mo->velz = victim->velz; } } - else // full strength blast from artifact + else { - if (victim->flags & MF_MISSILE) - { -#if 0 - if (victim->IsKindOf (RUNTIME_CLASS(AMageStaffFX2))) - { // Reflect to originator - victim->special1 = (int)victim->target; - victim->target = Owner; - } -#endif - } - victim->velx = FixedMul (BLAST_SPEED, finecosine[angle]); - victim->vely = FixedMul (BLAST_SPEED, finesine[angle]); - - // Spawn blast puff - ang = R_PointToAngle2 (victim->x, victim->y, Owner->x, Owner->y); - ang >>= ANGLETOFINESHIFT; - x = victim->x + FixedMul (victim->radius+FRACUNIT, finecosine[ang]); - y = victim->y + FixedMul (victim->radius+FRACUNIT, finesine[ang]); - z = victim->z - victim->floorclip + (victim->height>>1); - mo = Spawn ("BlastEffect", x, y, z, ALLOW_REPLACE); - if (mo) - { - mo->velx = victim->velx; - mo->vely = victim->vely; - } + victim->velz = (1000 / victim->Mass) << FRACBITS; + } + if (victim->player) + { + // Players handled automatically + } + else + { + victim->flags2 |= MF2_BLASTED; + } + if (victim->flags6 & MF6_TOUCHY) + { // Touchy objects die when blasted + victim->flags6 &= ~MF6_ARMED; // Disarm + P_DamageMobj(victim, Owner, Owner, victim->health, NAME_Melee, DMG_FORCED); + } +} + +enum +{ + BF_USEAMMO = 1, + BF_DONTWARN = 2, + BF_AFFECTBOSSES = 4, +}; + +//========================================================================== +// +// AArtiBlastRadius :: Activate +// +// Blast all actors away +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS (AActor, A_Blast) +{ + ACTION_PARAM_START(6); + ACTION_PARAM_INT (blastflags, 0); + ACTION_PARAM_FIXED(strength, 1); + ACTION_PARAM_FIXED(radius, 2); + ACTION_PARAM_FIXED(speed, 3); + ACTION_PARAM_CLASS(blasteffect, 4); + ACTION_PARAM_SOUND(blastsound, 5); + + AActor *mo; + TThinkerIterator iterator; + fixed_t dist; + + if (self->player && (blastflags & BF_USEAMMO)) + { + AWeapon * weapon = self->player->ReadyWeapon; + if (!weapon->DepleteAmmo(weapon->bAltFire)) + return; + } + + S_Sound (self, CHAN_AUTO, blastsound, 1, ATTN_NORM); + + if (!(blastflags & BF_DONTWARN)) P_NoiseAlert (self, self); - if (victim->flags & MF_MISSILE) - { - // [RH] Floor and ceiling huggers should not be blasted vertically. - if (!(victim->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))) - { - victim->velz = 8*FRACUNIT; - mo->velz = victim->velz; - } + while ( (mo = iterator.Next ()) ) + { + if ((mo == self) || ((mo->flags2 & MF2_BOSS) && !(blastflags & BF_AFFECTBOSSES)) + || (mo->flags2 & MF2_DORMANT) || (mo->flags3 & MF3_DONTBLAST)) + { // Not a valid monster: originator, boss, dormant, or otherwise protected + continue; } - else + if ((mo->flags & MF_ICECORPSE) || (mo->flags3 & MF3_CANBLAST)) { - victim->velz = (1000 / victim->Mass) << FRACBITS; + // Let these special cases go } - if (victim->player) + else if ((mo->flags3 & MF3_ISMONSTER) && (mo->health <= 0)) { - // Players handled automatically + continue; } - else - { - victim->flags2 |= MF2_BLASTED; + else if (!(mo->player) && + !(mo->flags & MF_MISSILE) && + !(mo->flags3 & (MF3_ISMONSTER|MF3_CANBLAST)) && + !(mo->flags6 & (MF6_TOUCHY|MF6_VULNERABLE))) + { // Must be monster, player, missile, touchy or vulnerable + continue; } - if (victim->flags6 & MF6_TOUCHY) - { // Touchy objects die when blasted - victim->flags6 &= ~MF6_ARMED; // Disarm - P_DamageMobj(victim, Owner, Owner, victim->health, NAME_Melee, DMG_FORCED); + dist = P_AproxDistance (self->x - mo->x, self->y - mo->y); + if (dist > radius) + { // Out of range + continue; } + BlastActor (mo, strength, speed, self, blasteffect); } } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index b644b3511..429038de2 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -227,6 +227,7 @@ ACTOR Actor native //: Thinker action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); action native A_Burst(class chunktype); + action native A_Blast(int flags = 0, int strength = 255, int radius = 255, float speed = 20, class blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); action native A_RadiusThrust(int force = 128, int distance = -1, bool affectsource = true); action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10); action native A_Stop(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 4761152be..a3b619a0c 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -71,6 +71,11 @@ const int RGF_NOPIERCING = 2; const int MSF_Standard = 0; const int MSF_Classic = 1; +// Flags for A_Blast +const int BF_USEAMMO = 1; +const int BF_DONTWARN = 2; +const int BF_AFFECTBOSSES = 4; + // Activation flags enum { @@ -82,6 +87,14 @@ enum THINGSPEC_MissileTrigger = 16, THINGSPEC_ClearSpecial = 32, }; +// Shorter aliases for same +const int AF_Default = 0; +const int AF_ThingActs = 1; +const int AF_ThingTargets = 2; +const int AF_TriggerTargets = 4; +const int AF_MonsterTrigger = 8; +const int AF_MissileTrigger = 16; +const int AF_ClearSpecial = 32; // constants for A_PlaySound enum diff --git a/wadsrc/static/actors/hexen/blastradius.txt b/wadsrc/static/actors/hexen/blastradius.txt index 5c5e05613..7e4259cf8 100644 --- a/wadsrc/static/actors/hexen/blastradius.txt +++ b/wadsrc/static/actors/hexen/blastradius.txt @@ -1,5 +1,5 @@ -ACTOR ArtiBlastRadius : Inventory 10110 native +ACTOR ArtiBlastRadius : CustomInventory 10110 { Game Hexen SpawnID 74 @@ -15,6 +15,8 @@ ACTOR ArtiBlastRadius : Inventory 10110 native Spawn: BLST ABCDEFGH 4 Bright Loop + Use: + TNT1 A 0 A_Blast } } diff --git a/wadsrc/static/actors/doom/dog.txt b/wadsrc/static/actors/shared/dog.txt similarity index 56% rename from wadsrc/static/actors/doom/dog.txt rename to wadsrc/static/actors/shared/dog.txt index 0feb393f5..439060d41 100644 --- a/wadsrc/static/actors/doom/dog.txt +++ b/wadsrc/static/actors/shared/dog.txt @@ -1,20 +1,19 @@ ACTOR MBFHelperDog 888 { - Game Doom Health 500 - Speed 10 + Speed 10 PainChance 180 - Radius 12 - Height 28 - Mass 100 - Monster - +JUMPDOWN - ActiveSound "dog/active" - AttackSound "dog/attack" - DeathSound "dog/death" - PainSound "dog/pain" - SeeSound "dog/sight" - Obituary "$OB_DOG" + Radius 12 + Height 28 + Mass 100 + Monster + +JUMPDOWN + ActiveSound "dog/active" + AttackSound "dog/attack" + DeathSound "dog/death" + PainSound "dog/pain" + SeeSound "dog/sight" + Obituary "$OB_DOG" States { Spawn: diff --git a/wadsrc/static/decorate.txt b/wadsrc/static/decorate.txt index ba3bf4b7e..465ce3287 100644 --- a/wadsrc/static/decorate.txt +++ b/wadsrc/static/decorate.txt @@ -28,6 +28,7 @@ #include "actors/shared/setcolor.txt" #include "actors/shared/sectoraction.txt" #include "actors/shared/action.txt" +#include "actors/shared/dog.txt" #include "actors/doom/doomplayer.txt" #include "actors/doom/possessed.txt" @@ -45,7 +46,6 @@ #include "actors/doom/spidermaster.txt" #include "actors/doom/keen.txt" #include "actors/doom/bossbrain.txt" -#include "actors/doom/dog.txt" #include "actors/doom/deadthings.txt" #include "actors/doom/doomammo.txt" From 9aab795c1805fc8c1c7b5a5f7004af4bf47c716d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Sep 2009 15:59:20 +0000 Subject: [PATCH 013/241] - Added BHS's death special flags submission. SVN r1887 (trunk) --- docs/rh-log.txt | 1 + src/actor.h | 2 ++ src/p_interaction.cpp | 12 +++++++++--- src/thingdef/thingdef_parse.cpp | 2 ++ wadsrc/static/actors/constants.txt | 2 ++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a631d1213..59654d890 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ September 28, 2009 (Changes by Graf Zahl) +- Added BHS's death special flags submission. - Added Gez's A_Blast submission. September 27, 2009 (Changes by Graf Zahl) diff --git a/src/actor.h b/src/actor.h index b490aeade..c2b0ef1a8 100644 --- a/src/actor.h +++ b/src/actor.h @@ -442,6 +442,8 @@ enum EThingSpecialActivationType THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile THINGSPEC_ClearSpecial = 32, // Clears special after successful activation + THINGSPEC_NoDeathSpecial = 64, // Don't activate special on death + THINGSPEC_TriggerActs = 128, // The trigger is the activator of the special (overrides LEVEL_ACTOWNSPECIAL Hexen hack) }; // [RH] Like msecnode_t, but for the blockmap diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index a062281f9..6b52bdd38 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -420,10 +420,16 @@ void AActor::Die (AActor *source, AActor *inflictor) // the activator of the script. // New: In Hexen, the thing that died is the activator, // so now a level flag selects who the activator gets to be. - if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER))) + if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER)) && !(activationtype & THINGSPEC_NoDeathSpecial)) { - LineSpecials[special] (NULL, level.flags & LEVEL_ACTOWNSPECIAL - ? this : source, false, args[0], args[1], args[2], args[3], args[4]); + // Activation flags override LEVEL_ACTOWNSPECIAL if set. + AActor *activator = (activationtype & THINGSPEC_TriggerActs ? source : + (activationtype & THINGSPEC_ThingActs ? this : (level.flags & LEVEL_ACTOWNSPECIAL ? this : source))); + if (activationtype & THINGSPEC_ThingTargets) + this->target = source; + if (activationtype & THINGSPEC_TriggerTargets) + source->target = this; + LineSpecials[special] (NULL, activator, false, args[0], args[1], args[2], args[3], args[4]); special = 0; } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index a4bde9259..6d83627aa 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -463,6 +463,8 @@ static int ParseThingActivation (FScanner &sc) { "THINGSPEC_MonsterTrigger", THINGSPEC_MonsterTrigger}, { "THINGSPEC_MissileTrigger", THINGSPEC_MissileTrigger}, { "THINGSPEC_ClearSpecial", THINGSPEC_ClearSpecial}, + { "THINGSPEC_NoDeathSpecial", THINGSPEC_NoDeathSpecial}, + { "THINGSPEC_TriggerActs", THINGSPEC_TriggerActs}, { NULL, 0 } }; diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index a3b619a0c..033920d90 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -86,6 +86,8 @@ enum THINGSPEC_MonsterTrigger = 8, THINGSPEC_MissileTrigger = 16, THINGSPEC_ClearSpecial = 32, + THINGSPEC_NoDeathSpecial = 64, + THINGSPEC_TriggerActs = 128, }; // Shorter aliases for same const int AF_Default = 0; From ed8f1ec8db43b18437538f7af95a9e5fdb781a1b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 30 Sep 2009 04:44:14 +0000 Subject: [PATCH 014/241] - Fixed: Alt+F4 no longer quit the program. SVN r1888 (trunk) --- docs/rh-log.txt | 3 +++ src/textures/multipatchtexture.cpp | 7 +++---- src/win32/i_input.cpp | 5 +++++ src/win32/i_keyboard.cpp | 5 +++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 59654d890..78d78bce5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +September 29, 2009 +- Fixed: Alt+F4 no longer quit the program. + September 28, 2009 (Changes by Graf Zahl) - Added BHS's death special flags submission. - Added Gez's A_Blast submission. diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 722d8aad3..f1d9aee83 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -570,7 +570,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i // Using a translation forces downconversion to the base palette ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, - w-Parts[i].OriginX, h-Parts[i].OriginY, + Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight(), Parts[i].Rotate, Parts[i].Translation, &info); } else @@ -601,7 +601,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i } ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, - w-Parts[i].OriginX, h-Parts[i].OriginY, + Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight(), Parts[i].Rotate, &info); } } @@ -617,8 +617,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0); bmp->CopyPixelDataRGB( x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(), - MIN(w-Parts[i].OriginX, bmp1.GetWidth()), - MIN(h-Parts[i].OriginY, bmp1.GetHeight()), + bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf); } } diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 48aa2b4d8..7ee8f138f 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -431,6 +431,11 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ToggleFullscreen = !ToggleFullscreen; } + // Pressing Alt+F4 quits the program. + if (wParam == VK_F4 && !(lParam & 0x40000000)) + { + PostQuitMessage(0); + } break; case WM_SYSCOMMAND: diff --git a/src/win32/i_keyboard.cpp b/src/win32/i_keyboard.cpp index 47419d541..8e1488fc3 100644 --- a/src/win32/i_keyboard.cpp +++ b/src/win32/i_keyboard.cpp @@ -121,7 +121,8 @@ FKeyboard::~FKeyboard() // // FKeyboard :: CheckAndSetKey // -// Returns true if the key was already in the desired, false if it wasn't. +// Returns true if the key was already in the desired state, false if it +// wasn't. // //========================================================================== @@ -437,7 +438,7 @@ bool FRawKeyboard::GetDevice() // Convert scan codes to DirectInput key codes. For the most part, this is // straight forward: Scan codes without any prefix are passed unmodified. // Scan codes with an 0xE0 prefix byte are generally passed by ORing them -// with 0x80. And scan codes with an 0xE1 prefix are the annowing Pause key +// with 0x80. And scan codes with an 0xE1 prefix are the annoying Pause key // which will generate another scan code that looks like Num Lock. // // This is a bit complicated only because the state of PC key codes is a bit From 7e4504f9d6d1110ff6542b126522ea6aad6f7bab Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Sep 2009 10:41:24 +0000 Subject: [PATCH 015/241] - Fixed: Coordinate handling for multipatch texture compositing was not correct for true color. Instead of using a clipping rectangle on the destination it tried to alter the source offsets which produced incorrect results for mirrored or rotated patches. SVN r1889 (trunk) --- docs/rh-log.txt | 6 +++ src/r_data.h | 4 +- src/textures/bitmap.cpp | 75 ++++++++++++++++++++++-------- src/textures/bitmap.h | 43 +++++++++++++++-- src/textures/ddstexture.cpp | 9 ++-- src/textures/jpegtexture.cpp | 13 ++---- src/textures/multipatchtexture.cpp | 28 +++++------ src/textures/pcxtexture.cpp | 11 ++--- src/textures/pngtexture.cpp | 15 +++--- src/textures/texture.cpp | 17 +++---- src/textures/textures.h | 4 +- src/textures/tgatexture.cpp | 31 ++++++------ src/textures/warptexture.cpp | 4 +- 13 files changed, 158 insertions(+), 102 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 78d78bce5..4faa65303 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +September 30, 2009 (Changes by Graf Zahl) +- Fixed: Coordinate handling for multipatch texture compositing was not correct + for true color. Instead of using a clipping rectangle on the destination it + tried to alter the source offsets which produced incorrect results for + mirrored or rotated patches. + September 29, 2009 - Fixed: Alt+F4 no longer quit the program. diff --git a/src/r_data.h b/src/r_data.h index 65a7f9740..acd70284d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -49,7 +49,7 @@ public: FWarpTexture (FTexture *source); ~FWarpTexture (); - virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w=-1, int h=-1, int rotate=0, FCopyInfo *inf = NULL); + virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); const BYTE *GetColumn (unsigned int column, const Span **spans_out); const BYTE *GetPixels (); void Unload (); @@ -93,8 +93,6 @@ public: void Unload (); bool CheckModified (); void RenderView (AActor *viewpoint, int fov); - void RenderGLView(AActor *viewpoint, int fov); - void NeedUpdate() { bNeedsUpdate=true; } protected: DSimpleCanvas *Canvas; diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index f1d78c478..20dfd38bd 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -280,7 +280,7 @@ static const CopyFunc copyfuncs[][9]={ // Clips the copy area for CopyPixelData functions // //=========================================================================== -bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, +bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, const BYTE *&patch, int &srcwidth, int &srcheight, int &pstep_x, int &pstep_y, int rotate) { @@ -290,6 +290,7 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, int step_x; int step_y; + assert(cr != NULL); // First adjust the settings for the intended rotation switch (rotate) { @@ -362,35 +363,71 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, pstep_y = step_y; // clip source rectangle to destination - if (originx<0) + if (originx < cr->x) { - srcwidth+=originx; - patch-=originx*step_x; - originx=0; + int skip = cr->x - originx; + + srcwidth -= skip; + patch +=skip * step_x; + originx = cr->x; if (srcwidth<=0) return false; } - if (originx+srcwidth>texwidth) + if (originx + srcwidth > cr->x + cr->width) { - srcwidth=texwidth-originx; + srcwidth = cr->x + cr->width - originx; if (srcwidth<=0) return false; } - if (originy<0) + if (originy < cr->y) { - srcheight+=originy; - patch-=originy*step_y; - originy=0; - if (srcheight<=0) return false; + int skip = cr->y - originy; + + srcheight -= skip; + patch += skip*step_y; + originy = cr->y; + if (srcheight <= 0) return false; } - if (originy+srcheight>texheight) + if (originy + srcheight > cr->y + cr->height) { - srcheight=texheight-originy; - if (srcheight<=0) return false; + srcheight = cr->y + cr->height - originy; + if (srcheight <= 0) return false; } + return true; } +//=========================================================================== +// +// +// +//=========================================================================== + +bool FClipRect::Intersect(int ix, int iy, int iw, int ih) +{ + if (ix > x) + { + width -= (ix-x); + x = ix; + } + else + { + iw -= (x-ix); + } + if (iy > y) + { + height -= (iy-y); + y = iy; + } + else + { + ih -= (x-ih); + } + if (iw < width) width = iw; + if (ih < height) height = ih; + return width > 0 && height > 0; +} + //=========================================================================== // // True Color texture copy function @@ -399,7 +436,7 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, void FBitmap::CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf) { - if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) + if (ClipCopyPixelRect(&ClipRect, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) { BYTE *buffer = data + 4 * originx + Pitch * originy; int op = inf==NULL? OP_COPY : inf->op; @@ -460,7 +497,7 @@ static const CopyPalettedFunc copypalettedfuncs[]= void FBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf) { - if (ClipCopyPixelRect(Width, Height, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) + if (ClipCopyPixelRect(&ClipRect, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) { BYTE *buffer = data + 4*originx + Pitch*originy; PalEntry penew[256]; @@ -485,9 +522,9 @@ void FBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int sr void FBitmap::Zero() { BYTE *buffer = data; - for (int y = 0; y < Height; ++y) + for (int y = ClipRect.y; y < ClipRect.height; ++y) { - memset(buffer, 0, Width*4); + memset(buffer + ClipRect.x, 0, ClipRect.width*4); buffer += Pitch; } } diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 35bdf62a2..4bd7f32bb 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -41,6 +41,13 @@ struct FCopyInfo; +struct FClipRect +{ + int x, y, width, height; + + bool Intersect(int ix, int iy, int iw, int ih); +}; + class FBitmap { protected: @@ -49,6 +56,8 @@ protected: int Height; int Pitch; bool FreeBuffer; + FClipRect ClipRect; + public: FBitmap() @@ -57,6 +66,7 @@ public: Width = Height = 0; Pitch = 0; FreeBuffer = false; + ClipRect.x = ClipRect.y = ClipRect.width = ClipRect.height = 0; } FBitmap(BYTE *buffer, int pitch, int width, int height) @@ -67,6 +77,9 @@ public: Width = width; Height = height; FreeBuffer = false; + ClipRect.x = ClipRect.y = 0; + ClipRect.width = width; + ClipRect.height = height; } virtual ~FBitmap() @@ -88,6 +101,9 @@ public: Height = h; data = new BYTE[4*w*h]; FreeBuffer = true; + ClipRect.x = ClipRect.y = 0; + ClipRect.width = w; + ClipRect.height = h; return data != NULL; } @@ -116,8 +132,29 @@ public: return data; } + void SetClipRect(FClipRect &clip) + { + ClipRect = clip; + } + + void IntersectClipRect(FClipRect &clip) + { + ClipRect.Intersect(clip.x, clip.y, clip.width, clip.height); + } + + void IntersectClipRect(int cx, int cy, int cw, int ch) + { + ClipRect.Intersect(cx, cy, cw, ch); + } + + const FClipRect &GetClipRect() const + { + return ClipRect; + } + void Zero(); + virtual void CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL); virtual void CopyPixelData(int originx, int originy, const BYTE * patch, int srcwidth, int srcheight, @@ -126,9 +163,9 @@ public: }; -bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, - const BYTE *&patch, int &srcwidth, int &srcheight, - int &step_x, int &step_y, int rotate); +bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy, + const BYTE *&patch, int &srcwidth, int &srcheight, + int &step_x, int &step_y, int rotate); //=========================================================================== // diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp index 82b96db05..3d68c4177 100644 --- a/src/textures/ddstexture.cpp +++ b/src/textures/ddstexture.cpp @@ -182,7 +182,7 @@ protected: void DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL); void DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); friend class FTexture; @@ -874,7 +874,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu // //=========================================================================== -int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { FWadLump lump = Wads.OpenLumpNum (SourceLump); @@ -899,11 +899,8 @@ int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer); } - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - // All formats decompress to RGBA. - bmp->CopyPixelDataRGB(x, y, TexBuffer, w, h, 4, Width*4, rotate, CF_RGBA, inf); + bmp->CopyPixelDataRGB(x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf); delete [] TexBuffer; return -1; } diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 5e41af22f..7a45e6001 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -168,7 +168,7 @@ public: const BYTE *GetPixels (); void Unload (); FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); protected: @@ -445,7 +445,7 @@ void FJPEGTexture::MakeTexture () // //=========================================================================== -int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { PalEntry pe[256]; @@ -460,9 +460,6 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, cinfo.err->error_exit = JPEG_ErrorExit; jpeg_create_decompress(&cinfo); - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - try { FLumpSourceMgr sourcemgr(&lump, &cinfo); @@ -491,18 +488,18 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, switch (cinfo.out_color_space) { case JCS_RGB: - bmp->CopyPixelDataRGB(x, y, buff, w, h, + bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf); break; case JCS_GRAYSCALE: for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map - bmp->CopyPixelData(x, y, buff, w, h, + bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height, 1, cinfo.output_width, rotate, pe, inf); break; case JCS_CMYK: - bmp->CopyPixelDataRGB(x, y, buff, w, h, + bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf); break; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index f1d9aee83..984135e97 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -158,7 +158,7 @@ public: void Unload (); virtual void SetFrontSkyLayer (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); int GetSourceLump() { return DefinitionLump; } protected: @@ -542,13 +542,15 @@ void FMultiPatchTexture::MakeTexture () // //=========================================================================== -int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { int retv = -1; FCopyInfo info; - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; + // When compositing a multipatch texture with multipatch parts + // drawing must be restricted to the actual area which is covered by this texture. + FClipRect saved_cr = bmp->GetClipRect(); + bmp->IntersectClipRect(x, y, Width, Height); if (inf != NULL && inf->op == OP_OVERWRITE) { @@ -568,10 +570,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i if (Parts[i].Translation != NULL) { // Using a translation forces downconversion to the base palette - ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, - x+Parts[i].OriginX, y+Parts[i].OriginY, - Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight(), - Parts[i].Rotate, Parts[i].Translation, &info); + ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); } else { @@ -599,10 +598,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i info.blend = BLEND_OVERLAY; } } - ret = Parts[i].Texture->CopyTrueColorPixels(bmp, - x+Parts[i].OriginX, y+Parts[i].OriginY, - Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight(), - Parts[i].Rotate, &info); + ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); } } else @@ -615,15 +611,15 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, i if (bmp1.Create(Parts[i].Texture->GetWidth(), Parts[i].Texture->GetHeight())) { Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0); - bmp->CopyPixelDataRGB( - x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(), - bmp1.GetWidth(), bmp1.GetHeight(), - 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf); + bmp->CopyPixelDataRGB(x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(), + bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf); } } if (ret > retv) retv = ret; } + // Restore previous clipping rectangle. + bmp->SetClipRect(saved_cr); return retv; } diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index 283550a95..a3b72c488 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -91,7 +91,7 @@ public: void Unload (); FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); protected: @@ -543,7 +543,7 @@ void FPCXTexture::MakeTexture() // //=========================================================================== -int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { PalEntry pe[256]; PCXHeader header; @@ -556,9 +556,6 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i bitcount = header.bitsPerPixel * header.numColorPlanes; - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - if (bitcount < 24) { Pixels = new BYTE[Width*Height]; @@ -600,13 +597,13 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i lump.Seek(sizeof(header), SEEK_SET); ReadPCX8bits (Pixels, lump, &header); } - bmp->CopyPixelData(x, y, Pixels, w, h, 1, Width, rotate, pe, inf); + bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf); } else { Pixels = new BYTE[Width*Height * 3]; ReadPCX24bits (Pixels, lump, &header, 3); - bmp->CopyPixelDataRGB(x, y, Pixels, w, h, 3, Width*3, rotate, CF_RGB, inf); + bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB, inf); } delete [] Pixels; return 0; diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index f612681e5..d1fe3e8f5 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -58,7 +58,7 @@ public: const BYTE *GetPixels (); void Unload (); FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); protected: @@ -583,7 +583,7 @@ void FPNGTexture::MakeTexture () // //=========================================================================== -int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? PalEntry pe[256]; @@ -593,9 +593,6 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i int pixwidth = Width * bpp[ColorType]; int transpal = false; - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - if (SourceLump >= 0) { lump = new FWadLump(Wads.OpenLumpNum(SourceLump)); @@ -654,20 +651,20 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i { case 0: case 3: - bmp->CopyPixelData(x, y, Pixels, w, h, 1, Width, rotate, pe, inf); + bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf); break; case 2: - bmp->CopyPixelDataRGB(x, y, Pixels, w, h, 3, pixwidth, rotate, CF_RGB, inf); + bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB, inf); break; case 4: - bmp->CopyPixelDataRGB(x, y, Pixels, w, h, 2, pixwidth, rotate, CF_IA, inf); + bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA, inf); transpal = -1; break; case 6: - bmp->CopyPixelDataRGB(x, y, Pixels, w, h, 4, pixwidth, rotate, CF_RGBA, inf); + bmp->CopyPixelDataRGB(x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA, inf); transpal = -1; break; diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 8125c56b2..df680a507 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -316,8 +316,9 @@ void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int y int srcheight = Height; int step_x = Height; int step_y = 1; + FClipRect cr = {0, 0, dwidth, dheight}; - if (ClipCopyPixelRect(dwidth, dheight, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate)) + if (ClipCopyPixelRect(&cr, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate)) { dest += ypos + dheight * xpos; if (translation == NULL) @@ -498,7 +499,7 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt) { FCopyInfo inf = {OP_OVERWRITE, }; FBitmap bmp(buff, pitch, pitch/4, height); - CopyTrueColorPixels(&bmp, 0, 0, -1, -1, 0, &inf); + CopyTrueColorPixels(&bmp, 0, 0, 0, &inf); break; } @@ -519,23 +520,19 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt) // //=========================================================================== -int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { PalEntry *palette = screen->GetPalette(); for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - bmp->CopyPixelData(x, y, GetPixels(), w, h, Height, 1, rotate, palette, inf); + bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); for(int i=1;i<256;i++) palette[i].a = 0; return 0; } -int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int w, int h, int rotate, FRemapTable *remap, FCopyInfo *inf) +int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap, FCopyInfo *inf) { PalEntry *palette = remap->Palette; - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - bmp->CopyPixelData(x, y, GetPixels(), w, h, Height, 1, rotate, palette, inf); + bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); return 0; } diff --git a/src/textures/textures.h b/src/textures/textures.h index c96da0648..06d373f1f 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -151,8 +151,8 @@ public: // Returns the whole texture, stored in column-major order virtual const BYTE *GetPixels () = 0; - virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w=-1, int h=-1, int rotate=0, FCopyInfo *inf = NULL); - int CopyTrueColorTranslated(FBitmap *bmp, int x, int y,int w, int h, int rotate, FRemapTable *remap, FCopyInfo *inf = NULL); + virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); + int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap, FCopyInfo *inf = NULL); virtual bool UseBasePalette(); virtual int GetSourceLump() { return SourceLump; } virtual FTexture *GetRedirect(bool wantwarped); diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 41bbb11b8..3e30a13d1 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -86,7 +86,7 @@ public: void Unload (); FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf = NULL); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); protected: @@ -487,12 +487,12 @@ void FTGATexture::MakeTexture () // //=========================================================================== -int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { PalEntry pe[256]; FWadLump lump = Wads.OpenLumpNum (SourceLump); TGAHeader hdr; - WORD wr; + WORD w; BYTE r,g,b,a; BYTE * sbuffer; int transval = 0; @@ -500,9 +500,6 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i lump.Read(&hdr, sizeof(hdr)); lump.Seek(hdr.id_len, SEEK_CUR); - if (w < 0 || w > Width) w = Width; - if (h < 0 || h > Height) h = Height; - hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); hdr.cm_first = LittleShort(hdr.cm_first); @@ -517,10 +514,10 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i { case 15: case 16: - lump >> wr; - r = (wr & 0x001F) << 3; - g = (wr & 0x03E0) >> 2; - b = (wr & 0x7C00) >> 7; + lump >> w; + r = (w & 0x001F) << 3; + g = (w & 0x03E0) >> 2; + b = (w & 0x7C00) >> 7; a = 255; break; @@ -575,7 +572,7 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i switch (hdr.img_type & 7) { case 1: // paletted - bmp->CopyPixelData(x, y, ptr, w, h, step_x, Pitch, rotate, pe, inf); + bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf); break; case 2: // RGB @@ -583,21 +580,21 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i { case 15: case 16: - bmp->CopyPixelDataRGB(x, y, ptr, w, h, step_x, Pitch, rotate, CF_RGB555, inf); + bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555, inf); break; case 24: - bmp->CopyPixelDataRGB(x, y, ptr, w, h, step_x, Pitch, rotate, CF_BGR, inf); + bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf); break; case 32: if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel { - bmp->CopyPixelDataRGB(x, y, ptr, w, h, step_x, Pitch, rotate, CF_BGR, inf); + bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR, inf); } else { - bmp->CopyPixelDataRGB(x, y, ptr, w, h, step_x, Pitch, rotate, CF_BGRA, inf); + bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA, inf); transval = -1; } break; @@ -612,11 +609,11 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i { case 8: for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // gray map - bmp->CopyPixelData(x, y, ptr, w, h, step_x, Pitch, rotate, pe, inf); + bmp->CopyPixelData(x, y, ptr, Width, Height, step_x, Pitch, rotate, pe, inf); break; case 16: - bmp->CopyPixelDataRGB(x, y, ptr, w, h, step_x, Pitch, rotate, CF_I16, inf); + bmp->CopyPixelDataRGB(x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16, inf); break; default: diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 8d6469779..f87688ea1 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -242,8 +242,8 @@ FTexture *FWarpTexture::GetRedirect(bool wantwarped) // //========================================================================== -int FWarpTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, int rotate, FCopyInfo *inf) +int FWarpTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { - return SourcePic->CopyTrueColorPixels(bmp, x, y, w, h, rotate, inf); + return SourcePic->CopyTrueColorPixels(bmp, x, y, rotate, inf); } From 59d932b972e405f33b7341098580e5ded0a3916c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 1 Oct 2009 14:54:29 +0000 Subject: [PATCH 016/241] - Fixed some GCC warnings. - fixed: The BossCube could be blocked by floors and ceiling resulting in incorrect movement. I changed it so that A_BrainSpit now sets the MF5_NOINTERACTION flag for anything it spawns that has the MF_NOCLIP flag. For travelling cubes active collision detection makes no sense and only causes problems. This should also make the boss brain work in the other games which previously were excluded by a game mode check in the movement code. - fixed: ACS's GetUserVariable did not work for the script activator. - fixed: Moving floors could be blocked by 2 actors without MF2_PASSMOBJ overlapping each other (common mapping bug, check Herian 2 MAP30.) SVN r1891 (trunk) --- docs/rh-log.txt | 13 +++++++++++++ src/dthinker.cpp | 2 +- src/g_doom/a_bossbrain.cpp | 4 ++++ src/g_shared/a_decals.cpp | 6 +++--- src/p_acs.cpp | 6 ++++-- src/p_map.cpp | 14 ++++++++++++++ src/p_mobj.cpp | 10 ++++++---- 7 files changed, 45 insertions(+), 10 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4faa65303..f309fde3b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,16 @@ +October 1, 2009 (Changes by Graf Zahl) +- Fixed some GCC warnings. +- fixed: The BossCube could be blocked by floors and ceiling resulting + in incorrect movement. I changed it so that A_BrainSpit now sets the + MF5_NOINTERACTION flag for anything it spawns that has the MF_NOCLIP + flag. For travelling cubes active collision detection makes no sense + and only causes problems. This should also make the boss brain + work in the other games which previously were excluded by a game mode + check in the movement code. +- fixed: ACS's GetUserVariable did not work for the script activator. +- fixed: Moving floors could be blocked by 2 actors without MF2_PASSMOBJ + overlapping each other (common mapping bug, check Herian 2 MAP30.) + September 30, 2009 (Changes by Graf Zahl) - Fixed: Coordinate handling for multipatch texture compositing was not correct for true color. Instead of using a clipping rectangle on the destination it diff --git a/src/dthinker.cpp b/src/dthinker.cpp index d7df8abc3..3074aca99 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -203,7 +203,7 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad) // before the crash - which is not the case with all other options. //DestroyAllThinkers(); - I_FatalError(err.GetMessage()); + I_FatalError("%s", err.GetMessage()); throw; } bSerialOverride = false; diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 7764f2ecd..47374e617 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -103,6 +103,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit) // spawn brain missile spit = P_SpawnMissile (self, targ, spawntype); + // Boss cubes should move freely to their destination so it's + // probably best to disable all collision detection for them. + if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION; + if (spit != NULL) { spit->target = targ; diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 77c036ba8..d8620f2dc 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -357,7 +357,7 @@ fixed_t DBaseDecal::GetRealZ (const side_t *wall) const void DBaseDecal::CalcFracPos (side_t *wall, fixed_t x, fixed_t y) { - line_t *line = line = wall->linedef; + line_t *line = wall->linedef; vertex_t *v1, *v2; if (line->sidedef[0] == wall) @@ -390,7 +390,7 @@ void DBaseDecal::CalcFracPos (side_t *wall, fixed_t x, fixed_t y) static void GetWallStuff (side_t *wall, vertex_t *&v1, fixed_t &ldx, fixed_t &ldy) { - line_t *line = line = wall->linedef; + line_t *line = wall->linedef; if (line->sidedef[0] == wall) { v1 = line->v1; @@ -412,7 +412,7 @@ static fixed_t Length (fixed_t dx, fixed_t dy) static side_t *NextWall (const side_t *wall) { - line_t *line = line = wall->linedef;; + line_t *line = wall->linedef; if (line->sidedef[0] == wall) { diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 3f24ad0ed..456c5553b 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3118,12 +3118,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) } case ACSF_GetUserVariable: + { if (args[1] >= 0 && args[1] < 10) { - activator = SingleActorFromTID(args[0], NULL); - return activator != NULL? activator->uservar[args[1]] : 0; + AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL); + return a != NULL? a->uservar[args[1]] : 0; } else return 0; + } default: diff --git a/src/p_map.cpp b/src/p_map.cpp index 09dbf076b..8bd38498c 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4323,6 +4323,13 @@ void P_FindAboveIntersectors (AActor *actor) { // Don't clip against self continue; } + if (!((thing->flags2 | actor->flags2) & MF2_PASSMOBJ) && !((thing->flags3 | actor->flags3) & MF3_ISMONSTER)) + { + // Don't bother if both things don't have MF2_PASSMOBJ set and aren't monsters. + // These things would always block each other which in nearly every situation is + // not what is wanted here. + continue; + } if (thing->z >= actor->z && thing->z <= actor->z + actor->height) { // Thing intersects above the base @@ -4365,6 +4372,13 @@ void P_FindBelowIntersectors (AActor *actor) { // Don't clip against self continue; } + if (!((thing->flags2 | actor->flags2) & MF2_PASSMOBJ) && !((thing->flags3 | actor->flags3) & MF3_ISMONSTER)) + { + // Don't bother if both things don't have MF2_PASSMOBJ set and aren't monsters. + // These things would always block each other which in nearly every situation is + // not what is wanted here. + continue; + } if (thing->z + thing->height <= actor->z + actor->height && thing->z + thing->height > actor->z) { // Thing intersects below the base diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7d2f4c58d..3cb95148e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2177,8 +2177,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz) // teleported the actor so it is no longer below the floor. if (mo->z <= mo->floorz) { - if ((mo->flags & MF_MISSILE) && - (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP))) + // old code for boss cube disabled + //if ((mo->flags & MF_MISSILE) && (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP))) + + if (mo->flags & MF_MISSILE) { mo->z = mo->floorz; if (mo->BounceFlags & BOUNCE_Floors) @@ -2289,8 +2291,8 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz) } if (mo->velz > 0) mo->velz = 0; - if (mo->flags & MF_MISSILE && - (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP))) + if (mo->flags & MF_MISSILE) + //&& (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP))) { if (mo->flags3 & MF3_CEILINGHUGGER) { From 4add2809a35a4b8e97f641bcb33a6f25ff71461c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Oct 2009 09:21:37 +0000 Subject: [PATCH 017/241] - fixed: Savegames stored the global fixed light levels when saving a player. SVN r1893 (trunk) --- docs/rh-log.txt | 3 +++ src/p_user.cpp | 12 +++++++++--- src/r_things.cpp | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f309fde3b..a38147619 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +October 2, 2009 (Changes by Graf Zahl) +- fixed: Savegames stored the global fixed light levels when saving a player. + October 1, 2009 (Changes by Graf Zahl) - Fixed some GCC warnings. - fixed: The BossCube could be blocked by floors and ceiling resulting diff --git a/src/p_user.cpp b/src/p_user.cpp index 014d837d4..7b6e34048 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2514,19 +2514,25 @@ void player_t::Serialize (FArchive &arc) int fixedmap; arc << fixedmap; fixedcolormap = NOFIXEDCOLORMAP; - fixedlightlev = -1; + fixedlightlevel = -1; if (fixedmap >= NUMCOLORMAPS) { fixedcolormap = fixedmap - NUMCOLORMAPS; } else if (fixedmap > 0) { - fixedlightlev = fixedmap; + fixedlightlevel = fixedmap; } } + else if (SaveVersion < 1893) + { + int ll; + arc << fixedcolormap << ll; + fixedlightlevel = ll; + } else { - arc << fixedcolormap << fixedlightlev; + arc << fixedcolormap << fixedlightlevel; } arc << morphTics << MorphedPlayerClass diff --git a/src/r_things.cpp b/src/r_things.cpp index be5499e3e..5f88793e6 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1857,7 +1857,7 @@ void R_DrawRemainingPlayerSprites() DTA_RenderStyle, vis->RenderStyle, DTA_FillColor, vis->FillColor, DTA_SpecialColormap, special, - DTA_ColorOverlay, overlay, + DTA_ColorOverlay, overlay.d, DTA_ColormapStyle, usecolormapstyle ? &colormapstyle : NULL, TAG_DONE); } From 3d8d176087d9975824ed6fbbca182ca8b8e93e1c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Oct 2009 17:07:11 +0000 Subject: [PATCH 018/241] - Added Gez's MageWandMissile customization patch but moved the new functionality into the FastProjectile base class and removed the native MageWandMissile class, using the generic functionality instead. - Fixed: GetReplacement and GetReplacee always checked the skill definitions, even if they weren't supposed to be used. It was also missing a range check for 'gameskill'. SVN r1894 (trunk) --- docs/rh-log.txt | 8 ++++ src/g_hexen/a_magelightning.cpp | 6 +-- src/g_hexen/a_magewand.cpp | 26 ------------- src/g_shared/a_fastprojectile.cpp | 15 ++++++++ src/info.cpp | 50 +++++++++++++++---------- src/namedef.h | 3 ++ wadsrc/static/actors/hexen/magewand.txt | 3 +- 7 files changed, 60 insertions(+), 51 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a38147619..ab1d13ce0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +October 3, 2009 (Changes by Graf Zahl) +- Added Gez's MageWandMissile customization patch but moved the new functionality + into the FastProjectile base class and removed the native MageWandMissile + class, using the generic functionality instead. +- Fixed: GetReplacement and GetReplacee always checked the skill definitions, + even if they weren't supposed to be used. It was also missing a range check + for 'gameskill'. + October 2, 2009 (Changes by Graf Zahl) - fixed: Savegames stored the global fixed light levels when saving a player. diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 7231514b9..9953cf1d0 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -208,8 +208,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningClip) DEFINE_ACTION_FUNCTION(AActor, A_LightningZap) { - const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None)); - if (lightning == NULL) lightning = PClass::FindClass("LightningZap"); + const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_LightningZap)); AActor *mo; fixed_t deltaZ; @@ -326,8 +325,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic) DEFINE_ACTION_FUNCTION(AActor, A_LastZap) { - const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None)); - if (lightning == NULL) lightning = PClass::FindClass("LightningZap"); + const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_LightningZap)); AActor *mo; diff --git a/src/g_hexen/a_magewand.cpp b/src/g_hexen/a_magewand.cpp index b5d2aaa0f..ab58f7ff8 100644 --- a/src/g_hexen/a_magewand.cpp +++ b/src/g_hexen/a_magewand.cpp @@ -17,32 +17,6 @@ static FRandom pr_smoke ("MWandSmoke"); void A_MWandAttack (AActor *actor); -// Wand Missile ------------------------------------------------------------- - -class AMageWandMissile : public AFastProjectile -{ - DECLARE_CLASS(AMageWandMissile, AFastProjectile) -public: - void Effect (); -}; - -IMPLEMENT_CLASS (AMageWandMissile) - -void AMageWandMissile::Effect () -{ - fixed_t hitz; - - //if (pr_smoke() < 128) // [RH] I think it looks better if it's consistent - { - hitz = z-8*FRACUNIT; - if (hitz < floorz) - { - hitz = floorz; - } - Spawn ("MageWandSmoke", x, y, hitz, ALLOW_REPLACE); - } -} - //============================================================================ // // A_MWandAttack diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 0127ed0d7..d3924a17e 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -113,5 +113,20 @@ void AFastProjectile::Tick () void AFastProjectile::Effect() { + //if (pr_smoke() < 128) // [RH] I think it looks better if it's consistent + { + FName name = (ENamedName) this->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None); + if (name != NAME_None) + { + fixed_t hitz = z-8*FRACUNIT; + if (hitz < floorz) + { + hitz = floorz; + } + + const PClass *trail = PClass::FindClass(name); + Spawn (trail, x, y, hitz, ALLOW_REPLACE); + } + } } diff --git a/src/info.cpp b/src/info.cpp index aeb89e8c9..116d4e603 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -168,17 +168,22 @@ void FActorInfo::RegisterIDs () FActorInfo *FActorInfo::GetReplacement (bool lookskill) { - FName skillrepname = AllSkills[gameskill].GetReplacement(this->Class->TypeName); - if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) + FName skillrepname; + + if (lookskill && AllSkills.Size() > (unsigned)gameskill) { - Printf("Warning: incorrect actor name in definition of skill %s: \n\ - class %s is replaced by inexistent class %s\n\ - Skill replacement will be ignored for this actor.\n", - AllSkills[gameskill].Name.GetChars(), - this->Class->TypeName.GetChars(), skillrepname.GetChars()); - AllSkills[gameskill].SetReplacement(this->Class->TypeName, NAME_None); - AllSkills[gameskill].SetReplacedBy(skillrepname, NAME_None); - lookskill = false; skillrepname = NAME_None; + skillrepname = AllSkills[gameskill].GetReplacement(this->Class->TypeName); + if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) + { + Printf("Warning: incorrect actor name in definition of skill %s: \n" + "class %s is replaced by non-existent class %s\n" + "Skill replacement will be ignored for this actor.\n", + AllSkills[gameskill].Name.GetChars(), + this->Class->TypeName.GetChars(), skillrepname.GetChars()); + AllSkills[gameskill].SetReplacement(this->Class->TypeName, NAME_None); + AllSkills[gameskill].SetReplacedBy(skillrepname, NAME_None); + lookskill = false; skillrepname = NAME_None; + } } if (Replacement == NULL && (!lookskill || skillrepname == NAME_None)) { @@ -211,17 +216,22 @@ FActorInfo *FActorInfo::GetReplacement (bool lookskill) FActorInfo *FActorInfo::GetReplacee (bool lookskill) { - FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); - if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) + FName skillrepname; + + if (lookskill && AllSkills.Size() > (unsigned)gameskill) { - Printf("Warning: incorrect actor name in definition of skill %s: \ - inexistent class %s is replaced by class %s\n\ - Skill replacement will be ignored for this actor.\n", - AllSkills[gameskill].Name.GetChars(), - skillrepname.GetChars(), this->Class->TypeName.GetChars()); - AllSkills[gameskill].SetReplacedBy(this->Class->TypeName, NAME_None); - AllSkills[gameskill].SetReplacement(skillrepname, NAME_None); - lookskill = false; + FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); + if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) + { + Printf("Warning: incorrect actor name in definition of skill %s: \n" + "non-existent class %s is replaced by class %s\n" + "Skill replacement will be ignored for this actor.\n", + AllSkills[gameskill].Name.GetChars(), + skillrepname.GetChars(), this->Class->TypeName.GetChars()); + AllSkills[gameskill].SetReplacedBy(this->Class->TypeName, NAME_None); + AllSkills[gameskill].SetReplacement(skillrepname, NAME_None); + lookskill = false; + } } if (Replacee == NULL && (!lookskill || skillrepname == NAME_None)) { diff --git a/src/namedef.h b/src/namedef.h index 8510cd95b..a00ca93f5 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -129,6 +129,9 @@ xx(FWeapQuietus) xx(CWeapWraithverge) xx(MWeapBloodscourge) +// Misc Hexen classes +xx(LightningZap) + // Ammo and weapon names for the Strife status bar xx(ClipOfBullets) xx(PoisonBolts) diff --git a/wadsrc/static/actors/hexen/magewand.txt b/wadsrc/static/actors/hexen/magewand.txt index c3608b5d2..ebb8e2ca1 100644 --- a/wadsrc/static/actors/hexen/magewand.txt +++ b/wadsrc/static/actors/hexen/magewand.txt @@ -46,7 +46,7 @@ ACTOR MageWandSmoke // Wand Missile ------------------------------------------------------------- -ACTOR MageWandMissile : FastProjectile native +ACTOR MageWandMissile : FastProjectile { Speed 184 Radius 12 @@ -54,6 +54,7 @@ ACTOR MageWandMissile : FastProjectile native Damage 2 +RIPPER +CANNOTPUSH +NODAMAGETHRUST +SPAWNSOUNDSOURCE + MissileType "MageWandSmoke" SeeSound "MageWandFire" States { From 5c105c0cad12c28e0943a2d5ff4cbc715bcf9ca6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 Oct 2009 17:52:49 +0000 Subject: [PATCH 019/241] - forgot something. SVN r1895 (trunk) --- src/g_hexen/a_magewand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_hexen/a_magewand.cpp b/src/g_hexen/a_magewand.cpp index ab58f7ff8..0a28fc7b3 100644 --- a/src/g_hexen/a_magewand.cpp +++ b/src/g_hexen/a_magewand.cpp @@ -27,6 +27,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_MWandAttack) { AActor *mo; - mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(AMageWandMissile)); + mo = P_SpawnPlayerMissile (self, PClass::FindClass("MageWandMissile")); S_Sound (self, CHAN_WEAPON, "MageWandFire", 1, ATTN_NORM); } From 0006013531e98fc9a1e78530521a9b2eeb637784 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Oct 2009 11:46:51 +0000 Subject: [PATCH 020/241] - Fixed: The conversation code tried to get the player's tag instead of the NPC's he is talking to when it had no given name. SVN r1896 (trunk) --- docs/rh-log.txt | 4 ++++ src/p_conversation.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ab1d13ce0..bd38a2da3 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +October 4, 2009 (Changes by Graf Zahl) +- Fixed: The conversation code tried to get the player's tag instead of the + NPC's he is talking to when it had no given name. + October 3, 2009 (Changes by Graf Zahl) - Added Gez's MageWandMissile customization patch but moved the new functionality into the FastProjectile base class and removed the native MageWandMissile diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 94feffe95..23147343b 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -875,7 +875,7 @@ static void DrawConversationMenu () } else { - speakerName = cp->mo->GetTag("Person"); + speakerName = cp->ConversationNPC->GetTag("Person"); } // Dim the screen behind the dialogue (but only if there is no backdrop). From a6c387ecefeda19c8b308da47f88bcca603a9479 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 4 Oct 2009 22:48:01 +0000 Subject: [PATCH 021/241] - Deleted a_magewand.cpp because it only contained unused code. SVN r1897 (trunk) --- docs/rh-log.txt | 1 + src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_magewand.cpp | 32 -- zdoom.vcproj | 778 +++++++++++++++++------------------- 4 files changed, 372 insertions(+), 440 deletions(-) delete mode 100644 src/g_hexen/a_magewand.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bd38a2da3..2bfcf1955 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 4, 2009 (Changes by Graf Zahl) +- Deleted a_magewand.cpp because it only contained unused code. - Fixed: The conversation code tried to get the player's tag instead of the NPC's he is talking to when it had no given name. diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index ff6b56202..387e9fcc6 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -44,7 +44,6 @@ #include "a_magecone.cpp" #include "a_magelightning.cpp" #include "a_magestaff.cpp" -#include "a_magewand.cpp" #include "a_pig.cpp" #include "a_serpent.cpp" #include "a_spike.cpp" diff --git a/src/g_hexen/a_magewand.cpp b/src/g_hexen/a_magewand.cpp deleted file mode 100644 index 0a28fc7b3..000000000 --- a/src/g_hexen/a_magewand.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -#include "actor.h" -#include "gi.h" -#include "m_random.h" -#include "s_sound.h" -#include "d_player.h" -#include "a_action.h" -#include "p_local.h" -#include "a_action.h" -#include "p_pspr.h" -#include "gstrings.h" -#include "a_hexenglobal.h" -#include "thingdef/thingdef.h" -*/ - -static FRandom pr_smoke ("MWandSmoke"); - -void A_MWandAttack (AActor *actor); - -//============================================================================ -// -// A_MWandAttack -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_MWandAttack) -{ - AActor *mo; - - mo = P_SpawnPlayerMissile (self, PClass::FindClass("MageWandMissile")); - S_Sound (self, CHAN_WEAPON, "MageWandFire", 1, ATTN_NORM); -} diff --git a/zdoom.vcproj b/zdoom.vcproj index 71cd5eaf0..2a33a2c6b 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -1860,14 +1868,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -2057,14 +2057,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -2075,6 +2067,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - - - - - - - - - - - - - - - + + + - - - @@ -5387,6 +5343,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -5665,7 +5629,7 @@ /> Date: Thu, 8 Oct 2009 04:03:32 +0000 Subject: [PATCH 022/241] - Since I am currently without a primary video card and stuck with this Mobility Radeon 9000 (on a PCI card, no less!), I have decided to give the PS14 support some loving: D3D windowed gamma now works on these cards using a texture lookup for the gamma table. Sadly, this halves my framerate, so setting gamma to 1 will skip the gamma correction, as it was before, for full speed. (On my 8800 GT, the gamma correction was free.) SVN r1898 (trunk) --- docs/rh-log.txt | 8 ++ src/win32/fb_d3d9.cpp | 102 +++++++++++++++--- src/win32/win32iface.h | 7 +- wadsrc/static/shaders/d3d/shaders.ps | 17 +++ .../shaders/d3d/sm14/GammaCorrection.pso | Bin 0 -> 460 bytes wadsrc/static/shaders/d3d/sm14/build.bat | 2 +- 6 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 wadsrc/static/shaders/d3d/sm14/GammaCorrection.pso diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2bfcf1955..8e7041a9e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +October 7, 2009 +- Since I am currently without a primary video card and stuck with this + Mobility Radeon 9000 (on a PCI card, no less!), I have decided to give the + PS14 support some loving: D3D windowed gamma now works on these cards using + a texture lookup for the gamma table. Sadly, this halves my framerate, so + setting gamma to 1 will skip the gamma correction, as it was before, for + full speed. (On my 8800 GT, the gamma correction was free.) + October 4, 2009 (Changes by Graf Zahl) - Deleted a_magewand.cpp because it only contained unused code. - Fixed: The conversation code tried to get the player's tag instead of the diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 562abf13d..71fcca21b 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -273,10 +273,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) ScreenshotSurface = NULL; FinalWipeScreen = NULL; PaletteTexture = NULL; + GammaTexture = NULL; for (int i = 0; i < NUM_SHADERS; ++i) { Shaders[i] = NULL; } + GammaShader = NULL; BlockSurface[0] = NULL; BlockSurface[1] = NULL; FBFormat = D3DFMT_UNKNOWN; @@ -416,12 +418,17 @@ void D3DFB::SetInitialState() CurPixelShader = NULL; memset(Constant, 0, sizeof(Constant)); - Texture[0] = NULL; - Texture[1] = NULL; - D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP); - D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP); + for (int i = 0; i < countof(Texture); ++i) + { + Texture[i] = NULL; + D3DDevice->SetSamplerState(i, D3DSAMP_ADDRESSU, (i == 1 && SM14) ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP); + D3DDevice->SetSamplerState(i, D3DSAMP_ADDRESSV, (i == 1 && SM14) ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP); + if (i > 1) + { + // Set linear filtering for the SM14 gamma texture. + D3DDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + } + } NeedGammaUpdate = true; NeedPalUpdate = true; @@ -534,6 +541,7 @@ bool D3DFB::CreateResources() { return false; } + CreateGammaTexture(); CreateBlockSurfaces(); return true; } @@ -549,7 +557,7 @@ bool D3DFB::CreateResources() bool D3DFB::LoadShaders() { - static const char *const models[] = { "30/", "20/", "14/" }; + static const char models[][4] = { "30/", "20/", "14/" }; FString shaderdir, shaderpath; int model, i, lump; @@ -568,7 +576,7 @@ bool D3DFB::LoadShaders() { FMemLump data = Wads.ReadLump(lump); if (FAILED(D3DDevice->CreatePixelShader((DWORD *)data.GetMem(), &Shaders[i])) && - i != SHADER_GammaCorrection && i != SHADER_BurnWipe) + i < SHADER_BurnWipe) { break; } @@ -607,6 +615,7 @@ void D3DFB::ReleaseResources () { SAFE_RELEASE( Shaders[i] ); } + GammaShader = NULL; if (ScreenWipe != NULL) { delete ScreenWipe; @@ -782,6 +791,19 @@ bool D3DFB::CreatePaletteTexture () return true; } +bool D3DFB::CreateGammaTexture () +{ + // If this fails, you just won't get gamma correction in a window + // on SM14 cards. + assert(GammaTexture == NULL); + if (SM14) + { + return SUCCEEDED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &GammaTexture, NULL)); + } + return false; +} + bool D3DFB::CreateVertexes () { VertexPos = -1; @@ -992,8 +1014,20 @@ void D3DFB::Update () LOG("SetGammaRamp\n"); D3DDevice->SetGammaRamp(0, D3DSGR_CALIBRATE, &ramp); } + else + { + if (igamma != 1) + { + UpdateGammaTexture(igamma); + GammaShader = Shaders[SHADER_GammaCorrection]; + } + else + { + GammaShader = NULL; + } + } psgamma[2] = psgamma[1] = psgamma[0] = igamma; - psgamma[3] = 1; + psgamma[3] = 0.5; // For SM14 version D3DDevice->SetPixelShaderConstantF(PSCONST_Gamma, psgamma, 1); } @@ -1105,7 +1139,7 @@ void D3DFB::Draw3DPart(bool copy3d) D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, vid_hwaalines); assert(OldRenderTarget == NULL); if (TempRenderTexture != NULL && - ((Windowed && Shaders[SHADER_GammaCorrection] && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling)) + ((Windowed && GammaShader && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling)) { IDirect3DSurface9 *targetsurf; if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf))) @@ -1196,12 +1230,50 @@ void D3DFB::DoWindowedGamma() D3DDevice->SetRenderTarget(0, OldRenderTarget); D3DDevice->SetFVF(D3DFVF_FBVERTEX); SetTexture(0, TempRenderTexture); - SetPixelShader(Shaders[(Windowed && Shaders[SHADER_GammaCorrection]) ? SHADER_GammaCorrection : SHADER_NormalColor]); + SetPixelShader(Windowed && GammaShader ? GammaShader : Shaders[SHADER_NormalColor]); + if (SM14 && Windowed && GammaShader) + { + SetTexture(2, GammaTexture); + SetTexture(3, GammaTexture); + SetTexture(4, GammaTexture); + } SetAlphaBlend(D3DBLENDOP(0)); EnableAlphaTest(FALSE); D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); OldRenderTarget->Release(); OldRenderTarget = NULL; + if (SM14 && Windowed && GammaShader) + { +// SetTexture(0, GammaTexture); +// SetPixelShader(Shaders[SHADER_NormalColor]); +// D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); + } + } +} + +//========================================================================== +// +// D3DFB :: UpdateGammaTexture +// +// Updates the gamma texture used by the PS14 shader. We only use the first +// half of the texture so that we needn't worry about imprecision causing +// it to grab from the border. +// +//========================================================================== + +void D3DFB::UpdateGammaTexture(float igamma) +{ + D3DLOCKED_RECT lockrect; + + if (GammaTexture != NULL && SUCCEEDED(GammaTexture->LockRect(0, &lockrect, NULL, 0))) + { + BYTE *pix = (BYTE *)lockrect.pBits; + for (int i = 0; i <= 128; ++i) + { + pix[i*4+2] = pix[i*4+1] = pix[i*4] = BYTE(255.f * powf(i / 128.f, igamma)); + pix[i*4+3] = 255; + } + GammaTexture->UnlockRect(0); } } @@ -1221,6 +1293,9 @@ void D3DFB::UploadPalette () // is similarly affected, which basically means that all Shader Model // 1.4 cards suffer from this problem, since they all use some variant // of the ATI R200. + // + // [Oh, gee. Looking over the old documentation, I guess this is + // documented that PS 1.x cards don't have a lot of precision.] skipat = SM14 ? 256 - 8 : 256; for (i = 0; i < skipat; ++i, pix += 4) @@ -3395,6 +3470,7 @@ void D3DFB::SetPixelShader(IDirect3DPixelShader9 *shader) void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture) { + assert(tnum >= 0 && tnum < countof(Texture)); if (Texture[tnum] != texture) { Texture[tnum] = texture; @@ -3402,8 +3478,6 @@ void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture) } } -CVAR(Float, pal, 0.5f, 0) -CVAR(Float, pc, 255.f, 0) void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR border_color) { if (SM14) @@ -3430,7 +3504,7 @@ void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR bo // The constant register c2 is used to hold the multiplier in the // x part and the adder in the y part. float fcount = 1 / float(count); - SetConstant(PSCONST_PaletteMod, pc * fcount, pal * fcount, 0, 0); + SetConstant(PSCONST_PaletteMod, 255 * fcount, 0.5f * fcount, 0, 0); } SetTexture(1, texture); } diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index e4c21a015..bd2c7bb81 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -336,9 +336,10 @@ private: void CreateBlockSurfaces(); bool CreateFBTexture(); bool CreatePaletteTexture(); - bool CreateGrayPaletteTexture(); + bool CreateGammaTexture(); bool CreateVertexes(); void UploadPalette(); + void UpdateGammaTexture(float igamma); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); void CalcFullscreenCoords (FBVERTEX verts[4], bool viewarea_only, bool can_double, D3DCOLOR color0, D3DCOLOR color1) const; bool Reset(); @@ -381,7 +382,7 @@ private: float Constant[3][4]; D3DCOLOR CurBorderColor; IDirect3DPixelShader9 *CurPixelShader; - IDirect3DTexture9 *Texture[2]; + IDirect3DTexture9 *Texture[5]; PalEntry SourcePalette[256]; D3DCOLOR BorderColor; @@ -415,6 +416,7 @@ private: IDirect3DTexture9 *FBTexture; IDirect3DTexture9 *TempRenderTexture; IDirect3DTexture9 *PaletteTexture; + IDirect3DTexture9 *GammaTexture; IDirect3DTexture9 *ScreenshotTexture; IDirect3DSurface9 *ScreenshotSurface; @@ -429,6 +431,7 @@ private: enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType; IDirect3DPixelShader9 *Shaders[NUM_SHADERS]; + IDirect3DPixelShader9 *GammaShader; IDirect3DSurface9 *BlockSurface[2]; IDirect3DSurface9 *OldRenderTarget; diff --git a/wadsrc/static/shaders/d3d/shaders.ps b/wadsrc/static/shaders/d3d/shaders.ps index 3039c7e2a..a650cd84a 100644 --- a/wadsrc/static/shaders/d3d/shaders.ps +++ b/wadsrc/static/shaders/d3d/shaders.ps @@ -1,5 +1,10 @@ sampler2D Image : register(s0); sampler1D Palette : register(s1); +#if PS14 +sampler1D Gamma1 : register(s2); +sampler1D Gamma2 : register(s3); +sampler1D Gamma3 : register(s4); +#endif float4 PaletteMod : register(c2); float4 Weights : register(c6); // RGB->Gray weighting { 77/256.0, 143/256.0, 37/256.0, 1 } @@ -100,7 +105,19 @@ float4 InGameColormap(float2 tex_coord : TEXCOORD0, float4 color : COLOR0, float float4 GammaCorrection(float2 tex_coord : TEXCOORD0) : COLOR { float4 color = tex2D(Image, tex_coord); +#if !PS14 color.rgb = pow(color.rgb, Gamma.rgb); +#else + // On PS14 targets, we can only sample once from each sampler + // per stage. Fortunately, we have 16 samplers to play with, + // so we can just set three of them to the gamma texture and + // use one for each component. Unfortunately, all these + // texture lookups are probably not as efficient as the pow() + // solution that later targets make possible. + color.r = tex1D(Gamma1, color.r * Gamma.w).r; + color.g = tex1D(Gamma2, color.g * Gamma.w).g; + color.b = tex1D(Gamma3, color.b * Gamma.w).b; +#endif return color; } diff --git a/wadsrc/static/shaders/d3d/sm14/GammaCorrection.pso b/wadsrc/static/shaders/d3d/sm14/GammaCorrection.pso new file mode 100644 index 0000000000000000000000000000000000000000..8abf541bc11754a15864d31fcba36720eaa402cd GIT binary patch literal 460 zcmZQ!{Qv*oe^&w|MiJW%7GpsX+Xoh70E-=g>UB@d%}r!jy_%5$q#vRl zBn1{XWLV9@z|Fu2h9FS}2C%phgfeFE%uP&BWnf|80jpqyC}AiljyH@qVerjNF3K;? zPb*Q-2+~w=F?NZtR0z&UOi3+LaL&&y$jnJCQn1uBG}SXVx70H*Ffd?Py?V71*bM## z28JgaK;gm2zzzzA26l%33qX8kFh3N|X94q9f%y>o85 Date: Thu, 8 Oct 2009 07:30:20 +0000 Subject: [PATCH 023/241] - fixed: Teleport_EndGame did not set the end sequence name properly. SVN r1899 (trunk) --- docs/rh-log.txt | 3 +++ src/g_level.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 8e7041a9e..5290e897a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +October 8, 2009 (Changes by Graf Zahl) +- fixed: Teleport_EndGame did not set the end sequence name properly. + October 7, 2009 - Since I am currently without a primary video card and stuck with this Mobility Radeon 9000 (on a PCI card, no less!), I have decided to give the diff --git a/src/g_level.cpp b/src/g_level.cpp index bb0b9b48c..948e89b63 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -168,7 +168,7 @@ static void SetEndSequence (char *nextmap, int type) newseq.EndType = type; seqnum = (int)EndSequences.Push (newseq); } - mysnprintf(nextmap, sizeof(nextmap), "enDSeQ%04x", (WORD)seqnum); + mysnprintf(nextmap, 11, "enDSeQ%04x", (WORD)seqnum); } //========================================================================== From 0c2288a010c1d449eb25c86b894e9c1c62e3cbf9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 Oct 2009 17:43:50 +0000 Subject: [PATCH 024/241] - Added a PainThreshold actor property. SVN r1900 (trunk) --- docs/rh-log.txt | 1 + src/actor.h | 1 + src/p_interaction.cpp | 73 +++++++++++++++------------- src/p_mobj.cpp | 5 ++ src/thingdef/thingdef_properties.cpp | 10 ++++ 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5290e897a..17b6e5c25 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 8, 2009 (Changes by Graf Zahl) +- Added a PainThreshold actor property. - fixed: Teleport_EndGame did not set the end sequence name properly. October 7, 2009 diff --git a/src/actor.h b/src/actor.h index c2b0ef1a8..8260b8fbf 100644 --- a/src/actor.h +++ b/src/actor.h @@ -842,6 +842,7 @@ public: fixed_t MaxDropOffHeight, MaxStepHeight; SDWORD Mass; SWORD PainChance; + int PainThreshold; FNameNoInit DamageType; FState *SpawnState; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 6b52bdd38..8c0246555 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1268,49 +1268,54 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage } } - pc = target->GetClass()->ActorInfo->PainChances; - painchance = target->PainChance; - if (pc != NULL) - { - BYTE * ppc = pc->CheckKey(mod); - if (ppc != NULL) - { - painchance = *ppc; - } - } -dopain: if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) && - !G_SkillProperty(SKILLP_NoPain) && (pr_damagemobj() < painchance || - (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))) && !(target->flags & MF_SKULLFLY)) + !G_SkillProperty(SKILLP_NoPain) && !(target->flags & MF_SKULLFLY)) { - if (mod == NAME_Electric) + + pc = target->GetClass()->ActorInfo->PainChances; + painchance = target->PainChance; + if (pc != NULL) { - if (pr_lightning() < 96) + BYTE * ppc = pc->CheckKey(mod); + if (ppc != NULL) + { + painchance = *ppc; + } + } + + if ((damage > target->PainThreshold && pr_damagemobj() < painchance) || + (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))) + { +dopain: + if (mod == NAME_Electric) + { + if (pr_lightning() < 96) + { + justhit = true; + FState * painstate = target->FindState(NAME_Pain, mod); + if (painstate != NULL) target->SetState (painstate); + } + else + { // "electrocute" the target + target->renderflags |= RF_FULLBRIGHT; + if ((target->flags3 & MF3_ISMONSTER) && pr_lightning() < 128) + { + target->Howl (); + } + } + } + else { justhit = true; FState * painstate = target->FindState(NAME_Pain, mod); if (painstate != NULL) target->SetState (painstate); - } - else - { // "electrocute" the target - target->renderflags |= RF_FULLBRIGHT; - if ((target->flags3 & MF3_ISMONSTER) && pr_lightning() < 128) + if (mod == NAME_PoisonCloud) { - target->Howl (); - } - } - } - else - { - justhit = true; - FState * painstate = target->FindState(NAME_Pain, mod); - if (painstate != NULL) target->SetState (painstate); - if (mod == NAME_PoisonCloud) - { - if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128) - { - target->Howl (); + if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128) + { + target->Howl (); + } } } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3cb95148e..a8975a5cd 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -301,6 +301,11 @@ void AActor::Serialize (FArchive &arc) << Score << Tag; + if (SaveVersion >= 1900) + { + arc << PainThreshold; + } + for(int i=0; i<10; i++) arc << uservar[i]; if (arc.IsStoring ()) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 92e259f0c..66e7cdc6f 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -363,6 +363,16 @@ DEFINE_PROPERTY(painchance, ZI, Actor) } } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(painthreshold, I, Actor) +{ + PROP_INT_PARM(id, 0); + + defaults->PainThreshold = id; +} + //========================================================================== // //========================================================================== From 09866b2cff77d8081ea751cdd9b3350f64362003 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 8 Oct 2009 23:44:50 +0000 Subject: [PATCH 025/241] - Reinstated the off-by-one check in D3DFB from r399. I thought I could get by at just fixing it at a specific value, since the supply of SM14 cards isn't all that diverse and all from ATI, but apparently Radeon 8500s and 9000s have different precision levels in their pixel shaders. See bug report - Removed unused variables FBFormat and PalFormat. SVN r1901 (trunk) --- docs/rh-log.txt | 7 ++ src/win32/fb_d3d9.cpp | 152 +++++++++++++++++++++++++++++++++++------ src/win32/win32iface.h | 4 +- 3 files changed, 142 insertions(+), 21 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 17b6e5c25..a5a3ff96f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +October 8, 2009 +- Reinstated the off-by-one check in D3DFB from r399. I thought I could get by + at just fixing it at a specific value, since the supply of SM14 cards isn't + all that diverse and all from ATI, but apparently Radeon 8500s and 9000s + have different precision levels in their pixel shaders. See bug report + + October 8, 2009 (Changes by Graf Zahl) - Added a PainThreshold actor property. - fixed: Teleport_EndGame did not set the end sequence name properly. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 71fcca21b..a776144ea 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -281,8 +281,6 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) GammaShader = NULL; BlockSurface[0] = NULL; BlockSurface[1] = NULL; - FBFormat = D3DFMT_UNKNOWN; - PalFormat = D3DFMT_UNKNOWN; VSync = vid_vsync; BlendingRect.left = 0; BlendingRect.top = 0; @@ -298,6 +296,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) QuadExtra = new BufferedQuad[MAX_QUAD_BATCH]; Packs = NULL; PixelDoubling = 0; + SkipAt = -1; Gamma = 1.0; FlashColor0 = 0; @@ -787,7 +786,6 @@ bool D3DFB::CreatePaletteTexture () { return false; } - PalFormat = D3DFMT_A8R8G8B8; return true; } @@ -1277,28 +1275,144 @@ void D3DFB::UpdateGammaTexture(float igamma) } } +//========================================================================== +// +// D3DFB :: DoOffByOneCheck +// +// Pixel Shader 1.x does not have enough precision to properly map a "color" +// from the source texture to an index in the palette texture. The best we +// can do is use 255 pixels of the palette and get the 256th from the +// texture border color. This routine determines which pixel of the texture +// is skipped so that we don't use it for palette data. +// +//========================================================================== + +void D3DFB::DoOffByOneCheck () +{ + IDirect3DSurface9 *savedrendertarget; + IDirect3DSurface9 *testsurf, *readsurf; + D3DLOCKED_RECT lockrect; + RECT testrect = { 0, 0, 256, 1 }; + float texright = 256.f / float(FBWidth); + float texbot = 1.f / float(FBHeight); + FBVERTEX verts[4] = + { + { -0.5f, -0.5f, 0.5f, 1.f, 0, ~0, 0.f, 0.f }, + { 255.5f, -0.5f, 0.5f, 1.f, 0, ~0, texright, 0.f }, + { 255.5f, 0.5f, 0.5f, 1.f, 0, ~0, texright, texbot }, + { -0.5f, 0.5f, 0.5f, 1.f, 0, ~0, 0.f, texbot } + }; + int i, c; + + if (SkipAt >= 0) + { + return; + } + + // Create an easily recognizable R3G3B2 palette. + if (SUCCEEDED(PaletteTexture->LockRect(0, &lockrect, NULL, 0))) + { + BYTE *pal = (BYTE *)(lockrect.pBits); + for (i = 0; i < 256; ++i) + { + pal[i*4+0] = (i & 0x03) << 6; // blue + pal[i*4+1] = (i & 0x1C) << 3; // green + pal[i*4+2] = (i & 0xE0); // red; + pal[i*4+3] = 255; + } + PaletteTexture->UnlockRect (0); + } + else + { + return; + } + // Prepare a texture with values 0-256. + if (SUCCEEDED(FBTexture->LockRect(0, &lockrect, &testrect, 0))) + { + for (i = 0; i < 256; ++i) + { + ((BYTE *)lockrect.pBits)[i] = i; + } + FBTexture->UnlockRect(0); + } + else + { + return; + } + // Create a render target that we can draw it to. + if (FAILED(D3DDevice->GetRenderTarget(0, &savedrendertarget))) + { + return; + } + if (FAILED(D3DDevice->CreateRenderTarget(256, 1, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &testsurf, NULL))) + { + return; + } + if (FAILED(D3DDevice->CreateOffscreenPlainSurface(256, 1, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &readsurf, NULL))) + { + testsurf->Release(); + return; + } + if (FAILED(D3DDevice->SetRenderTarget(0, testsurf))) + { + testsurf->Release(); + readsurf->Release(); + return; + } + // Write it to the render target using the pixel shader. + D3DDevice->BeginScene(); + D3DDevice->SetTexture(0, FBTexture); + D3DDevice->SetTexture(1, PaletteTexture); + D3DDevice->SetFVF(D3DFVF_FBVERTEX); + D3DDevice->SetPixelShader(Shaders[SHADER_NormalColorPal]); + SetConstant(PSCONST_PaletteMod, 1.f, 0.5f / 256.f, 0, 0); + D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); + D3DDevice->EndScene(); + D3DDevice->SetRenderTarget(0, savedrendertarget); + savedrendertarget->Release(); + // Now read it back and see where it skips an entry + if (SUCCEEDED(D3DDevice->GetRenderTargetData(testsurf, readsurf)) && + SUCCEEDED(readsurf->LockRect(&lockrect, &testrect, D3DLOCK_READONLY))) + { + const BYTE *pix = (const BYTE *)lockrect.pBits; + for (i = 0; i < 256; ++i, pix += 4) + { + c = (pix[0] >> 6) | // blue + ((pix[1] >> 5) << 2) | // green + ((pix[2] >> 5) << 5); // red + if (c != i) + { + break; + } + } + } + readsurf->UnlockRect(); + readsurf->Release(); + testsurf->Release(); + SkipAt = i; +} + void D3DFB::UploadPalette () { D3DLOCKED_RECT lockrect; - if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) + if (SkipAt < 0) + { + if (SM14) + { + DoOffByOneCheck(); + } + else + { + SkipAt = 256; + } + } + if (SUCCEEDED(PaletteTexture->LockRect(0, &lockrect, NULL, 0))) { BYTE *pix = (BYTE *)lockrect.pBits; - int i, skipat; + int i; - // It is impossible to get the Radeon 9000 to do the proper palette - // lookup. It *will* skip at least one entry in the palette. So we - // let it and have it look at the texture border color for color 255. - // I assume that every other card based on a related graphics chipset - // is similarly affected, which basically means that all Shader Model - // 1.4 cards suffer from this problem, since they all use some variant - // of the ATI R200. - // - // [Oh, gee. Looking over the old documentation, I guess this is - // documented that PS 1.x cards don't have a lot of precision.] - skipat = SM14 ? 256 - 8 : 256; - - for (i = 0; i < skipat; ++i, pix += 4) + for (i = 0; i < SkipAt; ++i, pix += 4) { pix[0] = SourcePalette[i].b; pix[1] = SourcePalette[i].g; @@ -1314,7 +1428,7 @@ void D3DFB::UploadPalette () pix[2] = SourcePalette[i].r; pix[3] = 255; } - PaletteTexture->UnlockRect (0); + PaletteTexture->UnlockRect(0); BorderColor = D3DCOLOR_XRGB(SourcePalette[255].r, SourcePalette[255].g, SourcePalette[255].b); } } diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index bd2c7bb81..6c7c066b7 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -338,6 +338,7 @@ private: bool CreatePaletteTexture(); bool CreateGammaTexture(); bool CreateVertexes(); + void DoOffByOneCheck(); void UploadPalette(); void UpdateGammaTexture(float igamma); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); @@ -391,14 +392,13 @@ private: int FlashAmount; int TrueHeight; int PixelDoubling; + int SkipAt; int LBOffsetI; float LBOffset; float Gamma; bool UpdatePending; bool NeedPalUpdate; bool NeedGammaUpdate; - D3DFORMAT FBFormat; - D3DFORMAT PalFormat; int FBWidth, FBHeight; bool VSync; RECT BlendingRect; From 18c1b2685ff7b2f173d3801d881dcd3526d6696c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Oct 2009 06:38:56 +0000 Subject: [PATCH 026/241] - fixed: AAmbientSound::Serialize was adjusting its timer value for savegames even when it was set to a 'don't check' value. SVN r1902 (trunk) --- docs/rh-log.txt | 4 ++++ src/s_advsound.cpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a5a3ff96f..1e6b1e883 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +October 9, 2009 (Changes by Graf Zahl) +- fixed: AAmbientSound::Serialize was adjusting its timer value for savegames + even when it was set to a 'don't check' value. + October 8, 2009 - Reinstated the off-by-one check in D3DFB from r399. I thought I could get by at just fixing it at a specific value, since the supply of SM14 cards isn't diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 31d2d94f2..11c541f45 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -1917,11 +1917,34 @@ void AAmbientSound::Serialize (FArchive &arc) Super::Serialize (arc); arc << bActive; - int checktime = NextCheck - gametic; - arc << checktime; - if (arc.IsLoading ()) + if (SaveVersion < 1902) { - NextCheck = checktime + gametic; + arc << NextCheck; + NextCheck += gametic; + if (NextCheck < 0) NextCheck = INT_MAX; + } + else + { + if (arc.IsStoring()) + { + if (NextCheck != INT_MAX) + { + int checktime = NextCheck - gametic; + arc << checktime; + } + else + { + arc << NextCheck; + } + } + else + { + arc << NextCheck; + if (checktime != INT_MAX) + { + NextCheck += gametic; + } + } } } From 19ef8399a8b70cc3e9ea45800fdc37455650d8f5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Oct 2009 20:18:31 +0000 Subject: [PATCH 027/241] - added a NULL pointer check to fog spawning in unmorphing code. - fixed: frozen corpses need to be treated as solid by z-movement code. - fixed previous commit. SVN r1903 (trunk) --- docs/rh-log.txt | 2 ++ src/g_shared/a_morph.cpp | 5 ++++- src/p_map.cpp | 23 +++++++++++++++++++---- src/s_advsound.cpp | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1e6b1e883..c819c3897 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ October 9, 2009 (Changes by Graf Zahl) +- added a NULL pointer check to fog spawning in unmorphing code. +- fixed: frozen corpses need to be treated as solid by z-movement code. - fixed: AAmbientSound::Serialize was adjusting its timer value for savegames even when it was set to a 'don't check' value. diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index f12c36aef..917ae5a92 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -314,7 +314,10 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, } angle = mo->angle >> ANGLETOFINESHIFT; - Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); + if (exit_flash != NULL) + { + Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); + } mo->SetupWeaponSlots(); // Use original class's weapon slots. beastweap = player->ReadyWeapon; if (player->PremorphWeapon != NULL) diff --git a/src/p_map.cpp b/src/p_map.cpp index 8bd38498c..fe7f5f790 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1441,10 +1441,15 @@ bool P_TestMobjZ (AActor *actor, bool quick, AActor **pOnmobj) { // Can't hit thing continue; } - if (thing->flags & (MF_SPECIAL|MF_NOCLIP|MF_CORPSE)) - { // [RH] Corpses and specials and noclippers don't block moves + if (thing->flags & (MF_SPECIAL|MF_NOCLIP)) + { // [RH] Specials and noclippers don't block moves continue; } + if (thing->flags & (MF_CORPSE)) + { // Corpses need a few more checks + if (!(actor->flags & MF_ICECORPSE)) + continue; + } if (!(thing->flags4 & MF4_ACTLIKEBRIDGE) && (actor->flags & MF_SPECIAL)) { // [RH] Only bridges block pickup items continue; @@ -4315,10 +4320,15 @@ void P_FindAboveIntersectors (AActor *actor) { // Can't hit thing continue; } - if (thing->flags & (MF_CORPSE|MF_SPECIAL)) + if (thing->flags & (MF_SPECIAL)) { // [RH] Corpses and specials don't block moves continue; } + if (thing->flags & (MF_CORPSE)) + { // Corpses need a few more checks + if (!(actor->flags & MF_ICECORPSE)) + continue; + } if (thing == actor) { // Don't clip against self continue; @@ -4364,10 +4374,15 @@ void P_FindBelowIntersectors (AActor *actor) { // Can't hit thing continue; } - if (thing->flags & (MF_CORPSE|MF_SPECIAL)) + if (thing->flags & (MF_SPECIAL)) { // [RH] Corpses and specials don't block moves continue; } + if (thing->flags & (MF_CORPSE)) + { // Corpses need a few more checks + if (!(actor->flags & MF_ICECORPSE)) + continue; + } if (thing == actor) { // Don't clip against self continue; diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 11c541f45..14742f55d 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -1940,7 +1940,7 @@ void AAmbientSound::Serialize (FArchive &arc) else { arc << NextCheck; - if (checktime != INT_MAX) + if (NextCheck != INT_MAX) { NextCheck += gametic; } From 819158a8fe01d98ae0ab98e280e2937748cc157a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Oct 2009 20:35:07 +0000 Subject: [PATCH 028/241] - Added Gez's thing activation submission. SVN r1904 (trunk) --- docs/rh-log.txt | 1 + src/actor.h | 25 ++++--- src/p_interaction.cpp | 14 ++-- src/p_lnspec.cpp | 32 +++++++-- src/p_lnspec.h | 1 + src/p_map.cpp | 100 +++++++++++++++++++-------- src/p_mobj.cpp | 8 ++- src/thingdef/thingdef_parse.cpp | 3 + src/thingdef/thingdef_properties.cpp | 2 +- 9 files changed, 131 insertions(+), 55 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c819c3897..db03561a9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 9, 2009 (Changes by Graf Zahl) +- Added Gez's thing activation submission. - added a NULL pointer check to fog spawning in unmorphing code. - fixed: frozen corpses need to be treated as solid by z-movement code. - fixed: AAmbientSound::Serialize was adjusting its timer value for savegames diff --git a/src/actor.h b/src/actor.h index 8260b8fbf..f595e5206 100644 --- a/src/actor.h +++ b/src/actor.h @@ -431,19 +431,23 @@ enum EBounceFlags }; -// Used to affect the logic for MF5_USESPECIAL and MF6_BUMPSPECIAL +// Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL // "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it enum EThingSpecialActivationType { - THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator - THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special - THINGSPEC_ThingTargets = 2, // The thing changes its target to the trigger - THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing - THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster - THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile - THINGSPEC_ClearSpecial = 32, // Clears special after successful activation - THINGSPEC_NoDeathSpecial = 64, // Don't activate special on death - THINGSPEC_TriggerActs = 128, // The trigger is the activator of the special (overrides LEVEL_ACTOWNSPECIAL Hexen hack) + THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator + THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special + THINGSPEC_ThingTargets = 1<<1, // The thing changes its target to the trigger + THINGSPEC_TriggerTargets = 1<<2, // The trigger changes its target to the thing + THINGSPEC_MonsterTrigger = 1<<3, // The thing can be triggered by a monster + THINGSPEC_MissileTrigger = 1<<4, // The thing can be triggered by a projectile + THINGSPEC_ClearSpecial = 1<<5, // Clears special after successful activation + THINGSPEC_NoDeathSpecial = 1<<6, // Don't activate special on death + THINGSPEC_TriggerActs = 1<<7, // The trigger is the activator of the special + // (overrides LEVEL_ACTOWNSPECIAL Hexen hack) + THINGSPEC_Activate = 1<<8, // The thing is activated when triggered + THINGSPEC_Deactivate = 1<<9, // The thing is deactivated when triggered + THINGSPEC_Switch = 1<<10, // The thing is alternatively activated and deactivated when triggered }; // [RH] Like msecnode_t, but for the blockmap @@ -807,6 +811,7 @@ public: fixed_t pushfactor; int lastpush; int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL + int lastbump; // Last time the actor was bumped, used to control BUMPSPECIAL int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything. FNameNoInit Tag; // Strife's tag name. FIXME: should be case sensitive! diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 8c0246555..0602226f8 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -420,17 +420,11 @@ void AActor::Die (AActor *source, AActor *inflictor) // the activator of the script. // New: In Hexen, the thing that died is the activator, // so now a level flag selects who the activator gets to be. - if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER)) && !(activationtype & THINGSPEC_NoDeathSpecial)) + // Everything is now moved to P_ActivateThingSpecial(). + if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER)) + && !(activationtype & THINGSPEC_NoDeathSpecial)) { - // Activation flags override LEVEL_ACTOWNSPECIAL if set. - AActor *activator = (activationtype & THINGSPEC_TriggerActs ? source : - (activationtype & THINGSPEC_ThingActs ? this : (level.flags & LEVEL_ACTOWNSPECIAL ? this : source))); - if (activationtype & THINGSPEC_ThingTargets) - this->target = source; - if (activationtype & THINGSPEC_TriggerTargets) - source->target = this; - LineSpecials[special] (NULL, activator, false, args[0], args[1], args[2], args[3], args[4]); - special = 0; + P_ActivateThingSpecial(this, source, true); } if (CountsAsKill()) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 17333f7d7..f0f2faf1d 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1061,6 +1061,30 @@ FUNC(LS_HealThing) return it ? true : false; } +// So that things activated/deactivated by ACS or DECORATE *and* by +// the BUMPSPECIAL or USESPECIAL flags work correctly both ways. +void DoActivateThing(AActor * thing, AActor * activator) +{ + if (thing->activationtype & THINGSPEC_Activate) + { + thing->activationtype &= ~THINGSPEC_Activate; // Clear flag + if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching + thing->activationtype |= THINGSPEC_Deactivate; + } + thing->Activate (activator); +} + +void DoDeactivateThing(AActor * thing, AActor * activator) +{ + if (thing->activationtype & THINGSPEC_Deactivate) + { + thing->activationtype &= ~THINGSPEC_Deactivate; // Clear flag + if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching + thing->activationtype |= THINGSPEC_Activate; + } + thing->Deactivate (activator); +} + FUNC(LS_Thing_Activate) // Thing_Activate (tid) { @@ -1076,7 +1100,7 @@ FUNC(LS_Thing_Activate) // Actor might remove itself as part of activation, so get next // one before activating it. AActor *temp = iterator.Next (); - actor->Activate (it); + DoActivateThing(actor, it); actor = temp; count++; } @@ -1085,7 +1109,7 @@ FUNC(LS_Thing_Activate) } else if (it != NULL) { - it->Activate(it); + DoActivateThing(it, it); return true; } return false; @@ -1106,7 +1130,7 @@ FUNC(LS_Thing_Deactivate) // Actor might removes itself as part of deactivation, so get next // one before we activate it. AActor *temp = iterator.Next (); - actor->Deactivate (it); + DoDeactivateThing(actor, it); actor = temp; count++; } @@ -1115,7 +1139,7 @@ FUNC(LS_Thing_Deactivate) } else if (it != NULL) { - it->Deactivate(it); + DoDeactivateThing(it, it); return true; } return false; diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 495947243..2f5a67810 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -196,5 +196,6 @@ typedef int (*lnSpecFunc)(struct line_t *line, extern lnSpecFunc LineSpecials[256]; int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL); +bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false); #endif //__P_LNSPEC_H__ diff --git a/src/p_map.cpp b/src/p_map.cpp index fe7f5f790..3f04ce0d1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -837,24 +837,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // Check for MF6_BUMPSPECIAL // By default, only players can activate things by bumping into them - if ((thing->flags6 & MF6_BUMPSPECIAL)) + if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL) + || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER)) + || ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE)) + ) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away { - if (((tm.thing->player != NULL) - || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (thing->flags3 & MF3_ISMONSTER)) - || ((thing->activationtype & THINGSPEC_MissileTrigger) && (thing->flags & MF_MISSILE)) - )) - { // Target switching mechanism - if (thing->activationtype & THINGSPEC_ThingTargets) thing->target = tm.thing; - if (thing->activationtype & THINGSPEC_TriggerTargets) tm.thing->target = thing; - // Run the special - - int res = LineSpecials[thing->special] (NULL, - ((thing->activationtype & THINGSPEC_ThingActs) ? thing : tm.thing), // Who triggers? - false, thing->args[0], thing->args[1], thing->args[2], thing->args[3], thing->args[4]); - - if (thing->activationtype & THINGSPEC_ClearSpecial && res) thing->special = 0; - - } + if (P_ActivateThingSpecial(thing, tm.thing)) + thing->lastbump = level.maptime + TICRATE; } // Check for skulls slamming into things @@ -3775,18 +3764,9 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline // Check for puzzle item use or USESPECIAL flag // Extended to use the same activationtype mechanism as BUMPSPECIAL does if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == UsePuzzleItem) - { // Target switching mechanism - if (in->d.thing->activationtype & THINGSPEC_ThingTargets) in->d.thing->target = usething; - if (in->d.thing->activationtype & THINGSPEC_TriggerTargets) usething->target = in->d.thing; - // Run the special - if (LineSpecials[in->d.thing->special] (NULL, // Who triggers? - ((in->d.thing->activationtype & THINGSPEC_ThingActs) ? in->d.thing : usething), false, - in->d.thing->args[0], in->d.thing->args[1], in->d.thing->args[2], - in->d.thing->args[3], in->d.thing->args[4])) - { - if (in->d.thing->activationtype & THINGSPEC_ClearSpecial) in->d.thing->special = 0; + { + if (P_ActivateThingSpecial(in->d.thing, usething)) return true; - } } // Dead things can't talk. if (in->d.thing->health <= 0) @@ -5180,3 +5160,67 @@ static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puf } } } + +//============================================================================= +// +// P_ActivateThingSpecial +// +// Handles the code for things activated by death, USESPECIAL or BUMPSPECIAL +// +//============================================================================= + +bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) +{ + bool res = false; + + // Target switching mechanism + if (thing->activationtype & THINGSPEC_ThingTargets) thing->target = trigger; + if (thing->activationtype & THINGSPEC_TriggerTargets) trigger->target = thing; + + // State change mechanism. The thing needs to be not dead and to have at least one of the relevant flags + if (!death && (thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate|THINGSPEC_Switch))) + { + // If a switchable thing does not know whether it should be activated + // or deactivated, the default is to activate it. + if ((thing->activationtype & THINGSPEC_Switch) + && !(thing->activationtype & (THINGSPEC_Activate|THINGSPEC_Deactivate))) + { + thing->activationtype |= THINGSPEC_Activate; + } + // Can it be activated? + if (thing->activationtype & THINGSPEC_Activate) + { + thing->activationtype &= ~THINGSPEC_Activate; // Clear flag + if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching + thing->activationtype |= THINGSPEC_Deactivate; + thing->Activate(trigger); + res = true; + } + // If not, can it be deactivated? + else if (thing->activationtype & THINGSPEC_Deactivate) + { + thing->activationtype &= ~THINGSPEC_Deactivate; // Clear flag + if (thing->activationtype & THINGSPEC_Switch) // Set other flag if switching + thing->activationtype |= THINGSPEC_Activate; + thing->Deactivate(trigger); + res = true; + } + } + + // Run the special, if any + if (thing->special) + { + res = !! LineSpecials[thing->special] (NULL, + // TriggerActs overrides the level flag, which only concerns thing activated by death + (((death && level.flags & LEVEL_ACTOWNSPECIAL && !(thing->activationtype & THINGSPEC_TriggerActs)) + || (thing->activationtype & THINGSPEC_ThingActs)) // Who triggers? + ? thing : trigger), + false, thing->args[0], thing->args[1], thing->args[2], thing->args[3], thing->args[4]); + + // Clears the special if it was run on thing's death or if flag is set. + if (death || (thing->activationtype & THINGSPEC_ClearSpecial && res)) thing->special = 0; + } + + // Returns the result + return res; +} diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a8975a5cd..31972de47 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -300,6 +300,10 @@ void AActor::Serialize (FArchive &arc) << Species << Score << Tag; + if (SaveVersion >= 1904) + { + arc << lastpush << lastbump; + } if (SaveVersion >= 1900) { @@ -3670,7 +3674,7 @@ void AActor::Activate (AActor *activator) if (flags2 & MF2_DORMANT) { flags2 &= ~MF2_DORMANT; - FState *state = FindState("Active"); + FState *state = FindState(NAME_Active); if (state != NULL) { SetState(state); @@ -3690,7 +3694,7 @@ void AActor::Deactivate (AActor *activator) if (!(flags2 & MF2_DORMANT)) { flags2 |= MF2_DORMANT; - FState *state = FindState("Inactive"); + FState *state = FindState(NAME_Inactive); if (state != NULL) { SetState(state); diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 6d83627aa..7a84a3ed8 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -465,6 +465,9 @@ static int ParseThingActivation (FScanner &sc) { "THINGSPEC_ClearSpecial", THINGSPEC_ClearSpecial}, { "THINGSPEC_NoDeathSpecial", THINGSPEC_NoDeathSpecial}, { "THINGSPEC_TriggerActs", THINGSPEC_TriggerActs}, + { "THINGSPEC_Activate", THINGSPEC_Activate}, + { "THINGSPEC_Deactivate", THINGSPEC_Deactivate}, + { "THINGSPEC_Switch", THINGSPEC_Switch}, { NULL, 0 } }; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 66e7cdc6f..faa9fba46 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1072,7 +1072,7 @@ DEFINE_PROPERTY(projectile, 0, Actor) //========================================================================== DEFINE_PROPERTY(activation, N, Actor) { - // How the thing behaves when activated with MF5_USESPECIAL or MF6_BUMPSPECIAL + // How the thing behaves when activated by death, USESPECIAL or BUMPSPECIAL PROP_INT_PARM(val, 0); defaults->activationtype = val; } From 4a81f55fb0763ba3d23abf429292a20984e6106b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Oct 2009 20:54:28 +0000 Subject: [PATCH 029/241] - Added Gez's seeker missile submission. SVN r1905 (trunk) --- docs/rh-log.txt | 1 + src/actor.h | 4 +- src/g_hexen/a_clericholy.cpp | 30 ----------- src/g_hexen/a_hexenglobal.h | 1 - src/g_hexen/a_magestaff.cpp | 36 ------------- src/g_raven/a_minotaur.cpp | 43 --------------- src/g_raven/ravenshared.h | 1 - src/p_mobj.cpp | 69 ++++++++++++++++-------- src/thingdef/thingdef_codeptr.cpp | 14 ++++- src/thingdef/thingdef_data.cpp | 6 ++- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/constants.txt | 5 ++ wadsrc/static/actors/hexen/magestaff.txt | 1 + 13 files changed, 74 insertions(+), 139 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index db03561a9..08263f075 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 9, 2009 (Changes by Graf Zahl) +- Added Gez's seeker missile submission. - Added Gez's thing activation submission. - added a NULL pointer check to fog spawning in unmorphing code. - fixed: frozen corpses need to be treated as solid by z-movement code. diff --git a/src/actor.h b/src/actor.h index f595e5206..587297f77 100644 --- a/src/actor.h +++ b/src/actor.h @@ -217,7 +217,7 @@ enum MF3_CRASHED = 0x00200000, // Actor entered its crash state MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles) MF3_AVOIDMELEE = 0x00800000, // Avoids melee attacks (same as MBF's monster_backing but must be explicitly set) - /* = 0x01000000, */ + MF3_SCREENSEEKER = 0x01000000, // Fails the IsOkayToAttack test if potential target is outside player FOV MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact MF3_BLOODLESSIMPACT = 0x08000000, // Projectile does not leave blood @@ -608,7 +608,7 @@ public: virtual bool SpecialBlastHandling (AActor *source, fixed_t strength); // Called by RoughBlockCheck - virtual bool IsOkayToAttack (AActor *target); + bool IsOkayToAttack (AActor *target); // Plays the actor's ActiveSound if its voice isn't already making noise. void PlayActiveSound (); diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index 6ad6522c3..01d13931c 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -145,36 +145,6 @@ bool AHolySpirit::SpecialBlastHandling (AActor *source, fixed_t strength) return true; } -bool AHolySpirit::IsOkayToAttack (AActor *link) -{ - if ((link->flags3&MF3_ISMONSTER || - (link->player && link != target)) - && !(link->flags2&MF2_DORMANT)) - { - if (target != NULL && link->IsFriend(target)) - { - return false; - } - if (!(link->flags & MF_SHOOTABLE)) - { - return false; - } - if (multiplayer && !deathmatch && link->player && target != NULL && target->player) - { - return false; - } - if (link == target) - { - return false; - } - else if (P_CheckSight (this, link)) - { - return true; - } - } - return false; -} - //============================================================================ // // A_CHolyAttack2 diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h index a942998fe..a20827774 100644 --- a/src/g_hexen/a_hexenglobal.h +++ b/src/g_hexen/a_hexenglobal.h @@ -9,7 +9,6 @@ class AHolySpirit : public AActor public: bool Slam (AActor *thing); bool SpecialBlastHandling (AActor *source, fixed_t strength); - bool IsOkayToAttack (AActor *link); }; class AFighterWeapon : public AWeapon diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 76610f693..2316edde3 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -88,7 +88,6 @@ class AMageStaffFX2 : public AActor DECLARE_CLASS(AMageStaffFX2, AActor) public: int SpecialMissileHit (AActor *victim); - bool IsOkayToAttack (AActor *link); bool SpecialBlastHandling (AActor *source, fixed_t strength); }; @@ -106,41 +105,6 @@ int AMageStaffFX2::SpecialMissileHit (AActor *victim) return -1; } -bool AMageStaffFX2::IsOkayToAttack (AActor *link) -{ - if (((link->flags3 & MF3_ISMONSTER) || link->player) && !(link->flags2 & MF2_DORMANT)) - { - if (!(link->flags & MF_SHOOTABLE)) - { - return false; - } - if (multiplayer && !deathmatch && link->player && target->player) - { - return false; - } - if (link == target) - { - return false; - } - if (target != NULL && target->IsFriend(link)) - { - return false; - } - if (P_CheckSight (this, link)) - { - AActor *master = target; - angle_t angle = R_PointToAngle2 (master->x, master->y, - link->x, link->y) - master->angle; - angle >>= 24; - if (angle>226 || angle<30) - { - return true; - } - } - } - return false; -} - bool AMageStaffFX2::SpecialBlastHandling (AActor *source, fixed_t strength) { // Reflect to originator diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp index 3dc9e141a..0958edb83 100644 --- a/src/g_raven/a_minotaur.cpp +++ b/src/g_raven/a_minotaur.cpp @@ -82,49 +82,6 @@ void AMinotaurFriend::Serialize (FArchive &arc) arc << StartTime; } -bool AMinotaurFriend::IsOkayToAttack (AActor *link) -{ - if ((link->flags3 & MF3_ISMONSTER) && (link != tracer)) - { - if (!((link->flags ^ flags) & MF_FRIENDLY)) - { // Don't attack friends - if (link->flags & MF_FRIENDLY) - { - if (!deathmatch || link->FriendPlayer == 0 || FriendPlayer == 0 || - link->FriendPlayer != FriendPlayer) - { - return false; - } - } - else - { - return false; - } - } - if (!(link->flags&MF_SHOOTABLE)) - { - return false; - } - if (link->flags2&MF2_DORMANT) - { - return false; - } - if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == tracer)) - { - return false; - } - if (multiplayer && !deathmatch && link->player) - { - return false; - } - if (P_CheckSight (this, link)) - { - return true; - } - } - return false; -} - void AMinotaurFriend::Die (AActor *source, AActor *inflictor) { Super::Die (source, inflictor); diff --git a/src/g_raven/ravenshared.h b/src/g_raven/ravenshared.h index 7afd75947..fb9edf279 100644 --- a/src/g_raven/ravenshared.h +++ b/src/g_raven/ravenshared.h @@ -20,7 +20,6 @@ class AMinotaurFriend : public AMinotaur public: int StartTime; - bool IsOkayToAttack (AActor *target); void Die (AActor *source, AActor *inflictor); bool OkayToSwitchTarget (AActor *other); void BeginPlay (); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 31972de47..e898fd687 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2693,36 +2693,59 @@ void AActor::PlayActiveSound () bool AActor::IsOkayToAttack (AActor *link) { - if (player) // Minotaur looking around player + if (!(player // Original AActor::IsOkayToAttack was only for players + // || (flags & MF_FRIENDLY) // Maybe let friendly monsters use the function as well? + || (flags5 & MF5_SUMMONEDMONSTER) // AMinotaurFriend has its own version, generalized to other summoned monsters + || (flags2 & MF2_SEEKERMISSILE))) // AHolySpirit and AMageStaffFX2 as well, generalized to other seeker missiles + { // Normal monsters and other actors always return false. + return false; + } + // Standard things to eliminate: an actor shouldn't attack itself, + // or a non-shootable, dormant, non-player-and-non-monster actor. + if (link == this) return false; + if (!(link->player||(link->flags3 & MF3_ISMONSTER)))return false; + if (!(link->flags & MF_SHOOTABLE)) return false; + if (link->flags2 & MF2_DORMANT) return false; + + // An actor shouldn't attack friendly actors. The reference depends + // on the type of actor: for a player's actor, itself; for a projectile, + // its target; and for a summoned minion, its tracer. + AActor * Friend = NULL; + if (player) Friend = this; + else if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer; + else if (flags2 & MF2_SEEKERMISSILE) Friend = target; + else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo; + + // Friend checks + if (link == Friend) return false; + if (Friend == NULL) return false; + if (Friend->IsFriend(link)) return false; + if ((link->flags5 & MF5_SUMMONEDMONSTER) // No attack against minions on the same side + && (link->tracer == Friend)) return false; + if (multiplayer && !deathmatch // No attack against fellow players in coop + && link->player && Friend->player) return false; + if (((flags & link->flags) & MF_FRIENDLY) // No friendly infighting amongst minions + && IsFriend(link)) return false; + + // Now that all the actor checks are made, the line of sight can be checked + if (P_CheckSight (this, link)) { - if ((link->flags3 & MF3_ISMONSTER) || (link->player && (link != this))) + // AMageStaffFX2::IsOkayToAttack had an extra check here, generalized with a flag, + // to only allow the check to succeed if the enemy was in a ~84° FOV of the player + if (flags3 & MF3_SCREENSEEKER) { - if (IsFriend(link)) - { - return false; - } - if (!(link->flags & MF_SHOOTABLE)) - { - return false; - } - if (link->flags2 & MF2_DORMANT) - { - return false; - } - if ((link->flags5 & MF5_SUMMONEDMONSTER) && (link->tracer == this)) - { - return false; - } - if (multiplayer && !deathmatch && link->player) - { - return false; - } - if (P_CheckSight (this, link)) + angle_t angle = R_PointToAngle2(Friend->x, + Friend->y, link->x, link->y) - Friend->angle; + angle >>= 24; + if (angle>226 || angle<30) { return true; } } + // Other actors are not concerned by this check + else return true; } + // The sight check was failed, or the angle wasn't right for a screenseeker return false; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 39a08cacd..934a0b9b5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -342,12 +342,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StopSoundEx) // Generic seeker missile function // //========================================================================== +static FRandom pr_seekermissile ("SeekerMissile"); +enum +{ + SMF_LOOK = 1, +}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SeekerMissile) { - ACTION_PARAM_START(2); + ACTION_PARAM_START(5); ACTION_PARAM_INT(ang1, 0); ACTION_PARAM_INT(ang2, 1); + ACTION_PARAM_INT(flags, 2); + ACTION_PARAM_INT(chance, 3); + ACTION_PARAM_INT(distance, 4); + if ((flags & SMF_LOOK) && (self->tracer == 0) && (pr_seekermissile()tracer = P_RoughMonsterSearch (self, distance); + } P_SeekerMissile(self, clamp(ang1, 0, 90) * ANGLE_1, clamp(ang2, 0, 90) * ANGLE_1); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 7c7ee2259..89741fca6 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -92,6 +92,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags), DEFINE_FLAG(MF, STEALTH, AActor, flags), DEFINE_FLAG(MF, ICECORPSE, AActor, flags), + DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2), DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2), DEFINE_FLAG(MF2, DONTSEEKINVISIBLE, AActor, flags2), @@ -121,6 +122,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF2, DORMANT, AActor, flags2), DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2), DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2), + DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3), DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3), DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3), @@ -141,13 +143,15 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF3, NOTARGET, AActor, flags3), DEFINE_FLAG(MF3, DONTGIB, AActor, flags3), DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3), - DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3), DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3), + DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3), + DEFINE_FLAG(MF3, SCREENSEEKER, AActor, flags3), DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3), DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3), DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3), DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3), DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3), + DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4), DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4), DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4), diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 429038de2..b80078769 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -178,7 +178,7 @@ ACTOR Actor native //: Thinker action native A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was... action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0); action native A_StopSoundEx(coerce name slot); - action native A_SeekerMissile(int threshold, int turnmax); + action native A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); action native A_Jump(int chance = 256, state label, ...); action native A_CustomMissile(class missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0); action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class pufftype = "BulletPuff", float range = 0, bool aimfacing = false); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 033920d90..fda6fd5a6 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -76,6 +76,9 @@ const int BF_USEAMMO = 1; const int BF_DONTWARN = 2; const int BF_AFFECTBOSSES = 4; +// Flags for A_SeekerMissile +const int SMF_LOOK = 1; + // Activation flags enum { @@ -97,6 +100,8 @@ const int AF_TriggerTargets = 4; const int AF_MonsterTrigger = 8; const int AF_MissileTrigger = 16; const int AF_ClearSpecial = 32; +const int AF_NoDeathSpecial = 64; +const int AF_TriggerActs = 128; // constants for A_PlaySound enum diff --git a/wadsrc/static/actors/hexen/magestaff.txt b/wadsrc/static/actors/hexen/magestaff.txt index 4b1887f55..e402e57c0 100644 --- a/wadsrc/static/actors/hexen/magestaff.txt +++ b/wadsrc/static/actors/hexen/magestaff.txt @@ -125,6 +125,7 @@ ACTOR MageStaffFX2 native DamageType "Fire" Projectile +SEEKERMISSILE + +SCREENSEEKER +EXTREMEDEATH DeathSound "MageStaffExplode" From 4529108b8f5f6c94ff29696acd71f088c6c2877b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Oct 2009 12:42:57 +0000 Subject: [PATCH 030/241] - Added MF6_NOTRIGGER flag that disables all line actions for an actor. SVN r1907 (trunk) --- docs/rh-log.txt | 3 +++ src/actor.h | 1 + src/p_acs.cpp | 7 +++++++ src/p_enemy.cpp | 14 +++++++++----- src/p_map.cpp | 30 ++++++++++++++++++++++-------- src/thingdef/thingdef_data.cpp | 1 + 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 08263f075..f50aec69f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +October 10, 2009 (Changes by Graf Zahl) +- Added MF6_NOTRIGGER flag that disables all line actions for an actor. + October 9, 2009 (Changes by Graf Zahl) - Added Gez's seeker missile submission. - Added Gez's thing activation submission. diff --git a/src/actor.h b/src/actor.h index 587297f77..0b9605def 100644 --- a/src/actor.h +++ b/src/actor.h @@ -316,6 +316,7 @@ enum MF6_ARMED = 0x00002000, // From MBF: Object is armed (for MF6_TOUCHY objects) MF6_FALLING = 0x00004000, // From MBF: Object is falling (for pseudotorque simulation) MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect + MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions // --- mobj.renderflags --- diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 456c5553b..91c471bb6 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2428,6 +2428,7 @@ enum APROP_Species = 20, APROP_NameTag = 21, APROP_Score = 22, + APROP_Notrigger = 23, }; // These are needed for ACS's APROP_RenderStyle @@ -2519,6 +2520,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) if (value) actor->flags3 |= MF3_NOTARGET; else actor->flags3 &= ~MF3_NOTARGET; break; + case APROP_Notrigger: + if (value) actor->flags6 |= MF6_NOTRIGGER; else actor->flags6 &= ~MF6_NOTRIGGER; + break; + case APROP_JumpZ: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) static_cast(actor)->JumpZ = value; @@ -2638,6 +2643,7 @@ int DLevelScript::GetActorProperty (int tid, int property) case APROP_Frightened: return !!(actor->flags4 & MF4_FRIGHTENED); case APROP_Friendly: return !!(actor->flags & MF_FRIENDLY); case APROP_Notarget: return !!(actor->flags3 & MF3_NOTARGET); + case APROP_Notrigger: return !!(actor->flags6 & MF6_NOTRIGGER); case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn))) { return static_cast(actor)->MaxHealth; @@ -2694,6 +2700,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_Frightened: case APROP_Friendly: case APROP_Notarget: + case APROP_Notrigger: return (GetActorProperty(tid, property) == (!!value)); // Strings are not covered by GetActorProperty, so make the check here diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 7e3bb0b26..d25ae3de0 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -583,15 +583,19 @@ bool P_Move (AActor *actor) line_t *ld; int good = 0; - while (spechit.Pop (ld)) + if (!(actor->flags6 & MF6_NOTRIGGER)) { - // [RH] let monsters push lines, as well as use them - if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_Use)) || - ((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_Push))) + while (spechit.Pop (ld)) { - good |= ld == actor->BlockingLine ? 1 : 2; + // [RH] let monsters push lines, as well as use them + if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_Use)) || + ((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_Push))) + { + good |= ld == actor->BlockingLine ? 1 : 2; + } } } + else spechit.Clear(); return good && ((pr_opendoor() >= 203) ^ (good & 1)); } else diff --git a/src/p_map.cpp b/src/p_map.cpp index 3f04ce0d1..e8c401bc1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1519,7 +1519,7 @@ void P_FakeZMovement (AActor *mo) static void CheckForPushSpecial (line_t *line, int side, AActor *mobj) { - if (line->special) + if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) { if (mobj->flags2 & MF2_PUSHWALL) { @@ -1795,7 +1795,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, // see if the line was crossed side = P_PointOnLineSide (thing->x, thing->y, ld); oldside = P_PointOnLineSide (oldx, oldy, ld); - if (side != oldside && ld->special) + if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER)) { if (thing->player) { @@ -3231,12 +3231,20 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)); + AActor *puffDefaults = GetDefaultByType (pufftype); + + int tflags; + if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky; + else tflags = TRACE_NoSky|TRACE_Impact; + if (!Trace (t1->x, t1->y, shootz, t1->Sector, vx, vy, vz, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, t1, trace, - TRACE_NoSky|TRACE_Impact, hitGhosts ? CheckForGhost : CheckForSpectral)) + tflags, hitGhosts ? CheckForGhost : CheckForSpectral)) { // hit nothing - AActor *puffDefaults = GetDefaultByType (pufftype); - if (puffDefaults->ActiveSound) + if (puffDefaults == NULL) + { + } + else if (puffDefaults->ActiveSound) { // Play miss sound S_Sound (t1, CHAN_WEAPON, puffDefaults->ActiveSound, 1, ATTN_NORM); } @@ -3629,22 +3637,28 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color start.Y = FIXED2FLOAT(y1); start.Z = FIXED2FLOAT(shootz); + int flags; + + AActor *puffDefaults = puffclass == NULL? NULL : GetDefaultByType (puffclass); + + if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) flags = 0; + else flags = TRACE_PCross|TRACE_Impact; + if (pierce) { Trace (x1, y1, shootz, source->Sector, vx, vy, vz, 8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, - TRACE_PCross|TRACE_Impact, ProcessRailHit); + flags, ProcessRailHit); } else { Trace (x1, y1, shootz, source->Sector, vx, vy, vz, 8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, - TRACE_PCross|TRACE_Impact, ProcessNoPierceRailHit); + flags, ProcessNoPierceRailHit); } // Hurt anything the trace hit unsigned int i; - AActor *puffDefaults = puffclass == NULL? NULL : GetDefaultByType (puffclass); FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType; // used as damage inflictor diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 89741fca6..f4f782464 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -223,6 +223,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, CANJUMP, AActor, flags6), DEFINE_FLAG(MF6, JUMPDOWN, AActor, flags6), DEFINE_FLAG(MF6, VULNERABLE, AActor, flags6), + DEFINE_FLAG(MF6, NOTRIGGER, AActor, flags6), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 9dfef79702173c686ef820ff8766b7880e65989b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Oct 2009 17:44:50 +0000 Subject: [PATCH 031/241] - fixed: puff checks for MF6_NOTRIGGER need to resolve actor replacements. SVN r1909 (trunk) --- src/am_map.cpp | 196 ++++++++++++++++++++++++++++++++++++++++- src/p_map.cpp | 234 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 374 insertions(+), 56 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index e2b62e124..da5a495ef 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -413,14 +413,24 @@ void AM_getIslope (mline_t *ml, islope_t *is) } */ +//============================================================================= +// +// called by the coordinate drawer +// +//============================================================================= + void AM_GetPosition(fixed_t &x, fixed_t &y) { x = (m_x + m_w/2) << FRACTOMAPBITS; y = (m_y + m_h/2) << FRACTOMAPBITS; } + +//============================================================================= // // // +//============================================================================= + void AM_activateNewScale () { m_x += m_w/2; @@ -433,9 +443,12 @@ void AM_activateNewScale () m_y2 = m_y + m_h; } +//============================================================================= // // // +//============================================================================= + void AM_saveScaleAndLoc () { old_m_x = m_x; @@ -444,9 +457,12 @@ void AM_saveScaleAndLoc () old_m_h = m_h; } +//============================================================================= // // // +//============================================================================= + void AM_restoreScaleAndLoc () { m_w = old_m_w; @@ -469,9 +485,12 @@ void AM_restoreScaleAndLoc () scale_ftom = MapDiv(MAPUNIT, scale_mtof); } +//============================================================================= // // adds a marker at the current location // +//============================================================================= + bool AM_addMark () { if (marknums[0].isValid()) @@ -484,10 +503,13 @@ bool AM_addMark () return false; } +//============================================================================= // // Determines bounding box of all vertices, // sets global variables controlling zoom range. // +//============================================================================= + static void AM_findMinMaxBoundaries () { min_x = min_y = FIXED_MAX; @@ -515,6 +537,12 @@ static void AM_findMinMaxBoundaries () AM_calcMinMaxMtoF(); } +//============================================================================= +// +// +// +//============================================================================= + static void AM_calcMinMaxMtoF() { fixed_t a = MapDiv (SCREENWIDTH << MAPBITS, max_w); @@ -524,6 +552,12 @@ static void AM_calcMinMaxMtoF() max_scale_mtof = MapDiv (SCREENHEIGHT << MAPBITS, 2*PLAYERRADIUS); } +//============================================================================= +// +// +// +//============================================================================= + static void AM_ClipRotatedExtents (fixed_t pivotx, fixed_t pivoty) { if (am_rotate == 0 || (am_rotate == 2 && !viewactive)) @@ -588,6 +622,12 @@ static void AM_ClipRotatedExtents (fixed_t pivotx, fixed_t pivoty) m_y2 = m_y + m_h; } +//============================================================================= +// +// +// +//============================================================================= + static void AM_ScrollParchment (fixed_t dmapx, fixed_t dmapy) { mapxstart -= MulScale12 (dmapx, scale_mtof); @@ -614,9 +654,12 @@ static void AM_ScrollParchment (fixed_t dmapx, fixed_t dmapy) } } +//============================================================================= // // // +//============================================================================= + void AM_changeWindowLoc () { if (0 != (m_paninc.x | m_paninc.y)) @@ -646,9 +689,12 @@ void AM_changeWindowLoc () } +//============================================================================= // // // +//============================================================================= + void AM_initVariables () { int pnum; @@ -694,6 +740,11 @@ static void GetComponents (int color, DWORD *palette, float &r, float &g, float } */ +//============================================================================= +// +// +// +//============================================================================= static void AM_initColors (bool overlayed) { @@ -840,9 +891,12 @@ static void AM_initColors (bool overlayed) lastpal = palette; } +//============================================================================= // // // +//============================================================================= + void AM_loadPics () { int i; @@ -859,6 +913,12 @@ void AM_loadPics () mapback = TexMan.CheckForTexture(autopage, FTexture::TEX_MiscPatch); } +//============================================================================= +// +// +// +//============================================================================= + bool AM_clearMarks () { for (int i = AM_NUMMARKPOINTS-1; i >= 0; i--) @@ -867,9 +927,12 @@ bool AM_clearMarks () return marknums[0].isValid(); } +//============================================================================= // // called right after the level has been loaded // +//============================================================================= + void AM_LevelInit () { leveljuststarted = 0; @@ -883,9 +946,12 @@ void AM_LevelInit () scale_ftom = MapDiv(MAPUNIT, scale_mtof); } +//============================================================================= // // // +//============================================================================= + void AM_Stop () { automapactive = false; @@ -894,9 +960,12 @@ void AM_Stop () viewactive = true; } +//============================================================================= // // // +//============================================================================= + void AM_Start () { if (!stopped) AM_Stop(); @@ -907,27 +976,36 @@ void AM_Start () +//============================================================================= // // set the window scale to the maximum size // +//============================================================================= + void AM_minOutWindowScale () { scale_mtof = min_scale_mtof; scale_ftom = MapDiv(MAPUNIT, scale_mtof); } +//============================================================================= // // set the window scale to the minimum size // +//============================================================================= + void AM_maxOutWindowScale () { scale_mtof = max_scale_mtof; scale_ftom = MapDiv(MAPUNIT, scale_mtof); } +//============================================================================= // // Called right after the resolution has changed // +//============================================================================= + void AM_NewResolution() { fixed_t oldmin = min_scale_mtof; @@ -949,11 +1027,23 @@ void AM_NewResolution() } +//============================================================================= +// +// +// +//============================================================================= + CCMD (togglemap) { gameaction = ga_togglemap; } +//============================================================================= +// +// +// +//============================================================================= + void AM_ToggleMap () { if (gamestate != GS_LEVEL) @@ -983,9 +1073,12 @@ void AM_ToggleMap () } } +//============================================================================= // // Handle events (user inputs) in automap mode // +//============================================================================= + bool AM_Responder (event_t *ev) { bool rc; @@ -1110,9 +1203,12 @@ bool AM_Responder (event_t *ev) } +//============================================================================= // // Zooming // +//============================================================================= + void AM_changeWindowScale () { // Change the scaling multipliers @@ -1126,9 +1222,12 @@ void AM_changeWindowScale () } +//============================================================================= // // // +//============================================================================= + void AM_doFollowPlayer () { fixed_t sx, sy; @@ -1156,6 +1255,12 @@ void AM_doFollowPlayer () } } +//============================================================================= +// +// +// +//============================================================================= + static void AM_ToggleFollowPlayer() { followplayer = !followplayer; @@ -1163,9 +1268,12 @@ static void AM_ToggleFollowPlayer() Printf ("%s\n", GStrings(followplayer ? "AMSTR_FOLLOWON" : "AMSTR_FOLLOWOFF")); } +//============================================================================= // // Updates on Game Tick // +//============================================================================= + void AM_Ticker () { if (!automapactive) @@ -1186,9 +1294,12 @@ void AM_Ticker () } +//============================================================================= // // Clear automap frame buffer. // +//============================================================================= + void AM_clearFB (const AMColor &color) { if (!mapback.isValid() || !am_drawmapback) @@ -1217,6 +1328,7 @@ void AM_clearFB (const AMColor &color) } +//============================================================================= // // Automap clipping of lines. // @@ -1224,6 +1336,8 @@ void AM_clearFB (const AMColor &color) // faster reject and precalculated slopes. If the speed is needed, // use a hash algorithm to handle the common cases. // +//============================================================================= + bool AM_clipMline (mline_t *ml, fline_t *fl) { enum { @@ -1345,9 +1459,12 @@ bool AM_clipMline (mline_t *ml, fline_t *fl) #undef DOOUTCODE +//============================================================================= // // Clip lines, draw visible parts of lines. // +//============================================================================= + void AM_drawMline (mline_t *ml, const AMColor &color) { fline_t fl; @@ -1358,11 +1475,12 @@ void AM_drawMline (mline_t *ml, const AMColor &color) } } - - +//============================================================================= // // Draws flat (floor/ceiling tile) aligned grid lines. // +//============================================================================= + void AM_drawGrid (const AMColor &color) { fixed_t x, y; @@ -1425,6 +1543,12 @@ void AM_drawGrid (const AMColor &color) } } +//============================================================================= +// +// +// +//============================================================================= + static bool AM_CheckSecret(line_t *line) { if (line->frontsector != NULL) @@ -1445,10 +1569,15 @@ static bool AM_CheckSecret(line_t *line) } return false; } + + +//============================================================================= // // Determines visible lines, draws them. // This is LineDef based, not LineSeg based. // +//============================================================================= + void AM_drawWalls (bool allmap) { int i; @@ -1556,10 +1685,13 @@ void AM_drawWalls (bool allmap) } +//============================================================================= // // Rotation in 2D. // Used to rotate player arrow line character. // +//============================================================================= + void AM_rotate (fixed_t *x, fixed_t *y, angle_t a) { fixed_t tmpx; @@ -1570,6 +1702,12 @@ void AM_rotate (fixed_t *x, fixed_t *y, angle_t a) *x = tmpx; } +//============================================================================= +// +// +// +//============================================================================= + void AM_rotatePoint (fixed_t *x, fixed_t *y) { fixed_t pivotx = m_x + m_w/2; @@ -1581,6 +1719,12 @@ void AM_rotatePoint (fixed_t *x, fixed_t *y) *y += pivoty; } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawLineCharacter ( const mline_t *lineguy, @@ -1627,6 +1771,12 @@ AM_drawLineCharacter } } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawPlayers () { mpoint_t pt; @@ -1723,6 +1873,12 @@ void AM_drawPlayers () } } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawThings () { AMColor color; @@ -1777,6 +1933,12 @@ void AM_drawThings () } } +//============================================================================= +// +// +// +//============================================================================= + static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust, INTBOOL flip, fixed_t xscale, fixed_t yscale, int translation, fixed_t alpha, DWORD fillcolor, FRenderStyle renderstyle) { @@ -1803,6 +1965,12 @@ static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust, TAG_DONE); } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawMarks () { for (int i = 0; i < AM_NUMMARKPOINTS; i++) @@ -1815,6 +1983,12 @@ void AM_drawMarks () } } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawAuthorMarkers () { // [RH] Draw any actors derived from AMapMarker on the automap. @@ -1876,11 +2050,23 @@ void AM_drawAuthorMarkers () } } +//============================================================================= +// +// +// +//============================================================================= + void AM_drawCrosshair (const AMColor &color) { screen->DrawPixel(f_w/2, (f_h+1)/2, color.Index, color.RGB); } +//============================================================================= +// +// +// +//============================================================================= + void AM_Drawer () { if (!automapactive) @@ -1928,6 +2114,12 @@ void AM_Drawer () AM_drawMarks(); } +//============================================================================= +// +// +// +//============================================================================= + void AM_SerializeMarkers(FArchive &arc) { arc << markpointnum; diff --git a/src/p_map.cpp b/src/p_map.cpp index e8c401bc1..65ff3be78 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -161,6 +161,12 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos } +//========================================================================== +// +// +// +//========================================================================== + void P_GetFloorCeilingZ(FCheckPosition &tmf, bool get) { sector_t *sec; @@ -278,6 +284,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) } } +//========================================================================== // // TELEPORT MOVE // @@ -291,6 +298,9 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) // move was made, so the height checking I added for 1.13 could // potentially erroneously indicate the move was okay if the thing // was being teleported between two non-overlapping height ranges. +// +//========================================================================== + bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag) { FCheckPosition tmf; @@ -389,12 +399,15 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr return true; } +//========================================================================== // // [RH] P_PlayerStartStomp // // Like P_TeleportMove, but it doesn't move anything, and only monsters and other // players get telefragged. // +//========================================================================== + void P_PlayerStartStomp (AActor *actor) { AActor *th; @@ -425,6 +438,12 @@ void P_PlayerStartStomp (AActor *actor) } } +//========================================================================== +// +// +// +//========================================================================== + inline fixed_t secfriction (const sector_t *sec) { fixed_t friction = Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction; @@ -437,12 +456,15 @@ inline fixed_t secmovefac (const sector_t *sec) return movefactor != 0 ? movefactor : sec->movefactor; } +//========================================================================== // // killough 8/28/98: // // P_GetFriction() // // Returns the friction associated with a particular mobj. +// +//========================================================================== int P_GetFriction (const AActor *mo, int *frictionfactor) { @@ -511,11 +533,15 @@ int P_GetFriction (const AActor *mo, int *frictionfactor) return friction; } +//========================================================================== +// // phares 3/19/98 // P_GetMoveFactor() returns the value by which the x,y // movements are multiplied to add to player movement. // // killough 8/28/98: rewritten +// +//========================================================================== int P_GetMoveFactor (const AActor *mo, int *frictionp) { @@ -550,10 +576,14 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp) // MOVEMENT ITERATOR FUNCTIONS // +//========================================================================== +// // // PIT_CheckLine // Adjusts tmfloorz and tmceilingz as lines are contacted // +// +//========================================================================== static // killough 3/26/98: make static bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm) @@ -1130,40 +1160,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) =============================================================================== */ -//---------------------------------------------------------------------------- -// -// FUNC P_TestMobjLocation -// -// Returns true if the mobj is not blocked by anything at its current -// location, otherwise returns false. -// -//---------------------------------------------------------------------------- - -bool P_TestMobjLocation (AActor *mobj) -{ - int flags; - - flags = mobj->flags; - mobj->flags &= ~MF_PICKUP; - if (P_CheckPosition(mobj, mobj->x, mobj->y)) - { // XY is ok, now check Z - mobj->flags = flags; - fixed_t z = mobj->z; - if (mobj->flags2 & MF2_FLOATBOB) - { - z -= FloatBobOffsets[(mobj->FloatBobPhase + level.maptime - 1) & 63]; - } - if ((z < mobj->floorz) || (z + mobj->height > mobj->ceilingz)) - { // Bad Z - return false; - } - return true; - } - mobj->flags = flags; - return false; -} - - +//========================================================================== // // P_CheckPosition // This is purely informative, nothing is modified @@ -1187,6 +1184,9 @@ bool P_TestMobjLocation (AActor *mobj) // numspeciallines // AActor *BlockingMobj = pointer to thing that blocked position (NULL if not // blocked, or blocked by a line). +// +//========================================================================== + bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm) { sector_t *newsec; @@ -1373,6 +1373,40 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y) return P_CheckPosition(thing, x, y, tm); } +//---------------------------------------------------------------------------- +// +// FUNC P_TestMobjLocation +// +// Returns true if the mobj is not blocked by anything at its current +// location, otherwise returns false. +// +//---------------------------------------------------------------------------- + +bool P_TestMobjLocation (AActor *mobj) +{ + int flags; + + flags = mobj->flags; + mobj->flags &= ~MF_PICKUP; + if (P_CheckPosition(mobj, mobj->x, mobj->y)) + { // XY is ok, now check Z + mobj->flags = flags; + fixed_t z = mobj->z; + if (mobj->flags2 & MF2_FLOATBOB) + { + z -= FloatBobOffsets[(mobj->FloatBobPhase + level.maptime - 1) & 63]; + } + if ((z < mobj->floorz) || (z + mobj->height > mobj->ceilingz)) + { // Bad Z + return false; + } + return true; + } + mobj->flags = flags; + return false; +} + + //============================================================================= // // P_CheckOnmobj(AActor *thing) @@ -1541,11 +1575,14 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj) } } +//========================================================================== // // P_TryMove // Attempt to move to a new position, // crossing special lines unless MF_TELEPORT is set. // +//========================================================================== + bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, int dropoff, // killough 3/15/98: allow dropoff as option const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor @@ -1920,10 +1957,12 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, +//========================================================================== // // P_CheckMove // Similar to P_TryMove but doesn't actually move the actor. Used for polyobject crushing // +//========================================================================== bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) { @@ -1999,10 +2038,13 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) +//========================================================================== // // SLIDE MOVE // Allows the player to slide along any angled walls. // +//========================================================================== + struct FSlide { fixed_t bestslidefrac; @@ -2025,12 +2067,15 @@ struct FSlide bool BounceWall (AActor *mo); }; +//========================================================================== // // P_HitSlideLine // Adjusts the xmove / ymove // so that the next move will slide along the wall. // If the floor is icy, then you can bounce off a wall. // phares // +//========================================================================== + void FSlide::HitSlideLine (line_t* ld) { int side; @@ -2164,9 +2209,12 @@ void FSlide::HitSlideLine (line_t* ld) } +//========================================================================== // // PTR_SlideTraverse // +//========================================================================== + void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy) { FLineOpening open; @@ -2255,6 +2303,7 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ +//========================================================================== // // P_SlideMove // @@ -2264,6 +2313,8 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_ // // This is a kludgy mess. // +//========================================================================== + void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) { fixed_t leadx, leady; @@ -2691,6 +2742,12 @@ bool P_BounceWall (AActor *mo) return slide.BounceWall(mo); } +//========================================================================== +// +// +// +//========================================================================== + extern FRandom pr_bounce; bool P_BounceActor (AActor *mo, AActor * BlockingMobj) { @@ -3065,6 +3122,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e // P_AimLineAttack // //============================================================================ + fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable) { fixed_t x2; @@ -3154,15 +3212,11 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p } -/* -================= -= -= P_LineAttack -= -= if damage == 0, it is just a test trace that will leave linetarget set -= -================= -*/ +//========================================================================== +// +// +// +//========================================================================== static bool CheckForGhost (FTraceResults &res) { @@ -3198,6 +3252,14 @@ static bool CheckForSpectral (FTraceResults &res) return false; } +//========================================================================== +// +// P_LineAttack +// +// if damage == 0, it is just a test trace that will leave linetarget set +// +//========================================================================== + AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, bool ismeleeattack) { @@ -3231,7 +3293,8 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)); - AActor *puffDefaults = GetDefaultByType (pufftype); + // Need to check defaults of replacement here + AActor *puffDefaults = GetDefaultByType(pufftype->ActorInfo->GetReplacement()->Class); int tflags; if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky; @@ -3416,6 +3479,12 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, return NULL; } +//========================================================================== +// +// +// +//========================================================================== + void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, angle_t angle, int pitch) { if (!cl_bloodsplats) @@ -3505,6 +3574,12 @@ void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch) target, angle, pitch); } +//========================================================================== +// +// +// +//========================================================================== + void P_TraceBleed (int damage, AActor *target, AActor *missile) { int pitch; @@ -3530,6 +3605,12 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile) pitch); } +//========================================================================== +// +// +// +//========================================================================== + void P_TraceBleed (int damage, AActor *target) { if (target != NULL) @@ -3542,9 +3623,12 @@ void P_TraceBleed (int damage, AActor *target) } } +//========================================================================== // // [RH] Rail gun stuffage // +//========================================================================== + struct SRailHit { AActor *HitActor; @@ -3574,6 +3658,12 @@ static bool ProcessRailHit (FTraceResults &res) return true; } +//========================================================================== +// +// +// +//========================================================================== + static bool ProcessNoPierceRailHit (FTraceResults &res) { if (res.HitType != TRACE_HitActor) @@ -3596,6 +3686,12 @@ static bool ProcessNoPierceRailHit (FTraceResults &res) return false; } +//========================================================================== +// +// +// +//========================================================================== + void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent, const PClass *puffclass, bool pierce) { fixed_t vx, vy, vz; @@ -3639,7 +3735,8 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color int flags; - AActor *puffDefaults = puffclass == NULL? NULL : GetDefaultByType (puffclass); + AActor *puffDefaults = puffclass == NULL? + NULL : GetDefaultByType (puffclass->ActorInfo->GetReplacement()->Class); if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) flags = 0; else flags = TRACE_PCross|TRACE_Impact; @@ -3718,9 +3815,12 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color P_DrawRailTrail (source, start, end, color1, color2, maxdiff, silent); } +//========================================================================== // // [RH] P_AimCamera // +//========================================================================== + CVAR (Float, chase_height, -8.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Float, chase_dist, 90.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -3758,9 +3858,11 @@ void P_AimCamera (AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &Camer } +//========================================================================== // // USE LINES // +//========================================================================== bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline) { @@ -3885,6 +3987,8 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline return false; } +//========================================================================== +// // Returns false if a "oof" sound should be made because of a blocking // linedef. Makes 2s middles which are impassable, as well as 2s uppers // and lowers which block the player, cause the sound effect when the @@ -3894,6 +3998,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline // // by Lee Killough // +//========================================================================== bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) { @@ -3905,7 +4010,7 @@ bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) line_t *ld = in->d.line; FLineOpening open; - // [GrafZahl] de-obfuscated. Was I the only one who was unable to makes sense out of + // [GrafZahl] de-obfuscated. Was I the only one who was unable to make sense out of // this convoluted mess? if (ld->special) continue; if (ld->flags&(ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)) return true; @@ -3918,14 +4023,13 @@ bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) return false; } -/* -================ -= -= P_UseLines -= -= Looks for special lines in front of the player to activate -================ -*/ +//========================================================================== +// +// P_UseLines +// +// Looks for special lines in front of the player to activate +// +//========================================================================== void P_UseLines (player_t *player) { @@ -4028,9 +4132,13 @@ bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType) return false; } +//========================================================================== // // RADIUS ATTACK // +// +//========================================================================== + // [RH] Damage scale to apply to thing that shot the missile. static float selfthrustscale; @@ -4043,10 +4151,13 @@ CUSTOM_CVAR (Float, splashfactor, 1.f, CVAR_SERVERINFO) selfthrustscale = 1.f / self; } +//========================================================================== // // P_RadiusAttack // Source is the creature that caused the explosion at spot. // +//========================================================================== + void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod, bool DamageSource, bool bombdodamage, int fulldamagedistance) { @@ -4222,6 +4333,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b } } +//========================================================================== // // SECTOR HEIGHT CHANGING // After modifying a sector's floor or ceiling height, @@ -4240,6 +4352,8 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b // DOOM crushing behavior set crushchange to 10 or -1 // if no crushing is desired. // +//========================================================================== + struct FChangePosition { @@ -5131,6 +5245,12 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) } } +//========================================================================== +// +// +// +//========================================================================== + void SpawnShootDecal (AActor *t1, const FTraceResults &trace) { FDecalBase *decalbase = NULL; @@ -5150,6 +5270,12 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace) } } +//========================================================================== +// +// +// +//========================================================================== + static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff, fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz) { From efd3e7f94e421902d5e26d08a126a5ad8abc6c60 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 Oct 2009 08:25:07 +0000 Subject: [PATCH 032/241] - added better earthquake functions for ACS and DECORATE. SVN r1912 (trunk) --- docs/rh-log.txt | 3 +++ src/g_shared/a_quake.cpp | 24 ++++++++++++++++-------- src/g_shared/a_sharedglobal.h | 2 +- src/p_acs.cpp | 6 +++++- src/p_lnspec.cpp | 2 +- src/p_spec.h | 2 +- src/thingdef/thingdef_codeptr.cpp | 17 +++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f50aec69f..21ddc8fe1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +October 15, 2009 (Changes by Graf Zahl) +- added better earthquake functions for ACS and DECORATE. + October 10, 2009 (Changes by Graf Zahl) - Added MF6_NOTRIGGER flag that disables all line actions for an actor. diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 58c9b83d6..c53605333 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -33,14 +33,14 @@ DEarthquake::DEarthquake() //========================================================================== DEarthquake::DEarthquake (AActor *center, int intensity, int duration, - int damrad, int tremrad) + int damrad, int tremrad, FSoundID quakesound) : DThinker(STAT_EARTHQUAKE) { - m_QuakeSFX = "world/quake"; + m_QuakeSFX = quakesound; m_Spot = center; // Radii are specified in tile units (64 pixels) - m_DamageRadius = damrad << (FRACBITS+6); - m_TremorRadius = tremrad << (FRACBITS+6); + m_DamageRadius = damrad << (FRACBITS); + m_TremorRadius = tremrad << (FRACBITS); m_Intensity = intensity; m_Countdown = duration; } @@ -56,7 +56,15 @@ void DEarthquake::Serialize (FArchive &arc) Super::Serialize (arc); arc << m_Spot << m_Intensity << m_Countdown << m_TremorRadius << m_DamageRadius; - m_QuakeSFX = "world/quake"; + + if (SaveVersion >= 1912) + { + arc << m_QuakeSFX; + } + else + { + m_QuakeSFX = "world/quake"; + } } //========================================================================== @@ -158,7 +166,7 @@ int DEarthquake::StaticGetQuakeIntensity (AActor *victim) // //========================================================================== -bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad) +bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) { AActor *center; bool res = false; @@ -169,7 +177,7 @@ bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int { if (activator != NULL) { - new DEarthquake(activator, intensity, duration, damrad, tremrad); + new DEarthquake(activator, intensity, duration, damrad, tremrad, quakesfx); return true; } } @@ -179,7 +187,7 @@ bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int while ( (center = iterator.Next ()) ) { res = true; - new DEarthquake (center, intensity, duration, damrad, tremrad); + new DEarthquake (center, intensity, duration, damrad, tremrad, quakesfx); } } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 11752234e..798f314e3 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -128,7 +128,7 @@ class DEarthquake : public DThinker DECLARE_CLASS (DEarthquake, DThinker) HAS_OBJECT_POINTERS public: - DEarthquake (AActor *center, int intensity, int duration, int damrad, int tremrad); + DEarthquake (AActor *center, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); void Serialize (FArchive &arc); void Tick (); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 91c471bb6..2e8f0050d 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2899,6 +2899,7 @@ enum EACSFunctions ACSF_SetActorVelocity, ACSF_SetUserVariable, ACSF_GetUserVariable, + ACSF_Radius_Quake2, }; int DLevelScript::SideFromID(int id, int side) @@ -3133,7 +3134,10 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) } else return 0; } - + + case ACSF_Radius_Quake2: + P_StartQuake(activator, args[0], args[1], args[2], args[3], args[4], FBehavior::StaticLookupString(args[5])); + break; default: break; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index f0f2faf1d..e5d2c78fc 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1736,7 +1736,7 @@ FUNC(LS_Light_Stop) FUNC(LS_Radius_Quake) // Radius_Quake (intensity, duration, damrad, tremrad, tid) { - return P_StartQuake (it, arg4, arg0, arg1, arg2, arg3); + return P_StartQuake (it, arg4, arg0, arg1, arg2*64, arg3*64, "world/quake"); } FUNC(LS_UsePuzzleItem) diff --git a/src/p_spec.h b/src/p_spec.h index 7f2dc4b38..b47f9aa9d 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -981,6 +981,6 @@ void P_DoDeferedScripts (void); // // [RH] p_quake.c // -bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad); +bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); #endif diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 934a0b9b5..d8ac6ef69 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2931,6 +2931,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Turn) self->angle += angle; } +//=========================================================================== +// +// A_Quake +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) +{ + ACTION_PARAM_START(5); + ACTION_PARAM_INT(intensity, 0); + ACTION_PARAM_INT(duration, 1); + ACTION_PARAM_INT(damrad, 2); + ACTION_PARAM_INT(tremrad, 3); + ACTION_PARAM_SOUND(sound, 4); + P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound); +} + //=========================================================================== // // A_LineEffect diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index b80078769..10bd40ea7 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -262,6 +262,7 @@ ACTOR Actor native //: Thinker action native A_SetArg(int pos, int value); action native A_SetUserVar(int pos, int value); action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0); + action native A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); States { From ce2e85c7b2ab3380a9acd6ae5f40c13230fc5568 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 Oct 2009 20:09:22 +0000 Subject: [PATCH 033/241] - added ACS CheckActprClass function - fixed: When a blasted actor collided with another one this other actor's DONTBLAST flag was not checked. - added a global DamageFactor actor property. All damage this actor takes is multiplied by this factor in addition to damage type specific damage factors. SVN r1915 (trunk) --- docs/rh-log.txt | 5 +++++ src/actor.h | 1 + src/p_acs.cpp | 15 +++++++++++++++ src/p_interaction.cpp | 2 ++ src/p_map.cpp | 3 ++- src/p_mobj.cpp | 4 ++++ src/thingdef/thingdef_properties.cpp | 19 +++++++++++++------ 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 21ddc8fe1..4e0901290 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,9 @@ October 15, 2009 (Changes by Graf Zahl) +- added ACS CheckActprClass function +- fixed: When a blasted actor collided with another one this other actor's + DONTBLAST flag was not checked. +- added a global DamageFactor actor property. All damage this actor takes is multiplied + by this factor in addition to damage type specific damage factors. - added better earthquake functions for ACS and DECORATE. October 10, 2009 (Changes by Graf Zahl) diff --git a/src/actor.h b/src/actor.h index 0b9605def..2c3b80108 100644 --- a/src/actor.h +++ b/src/actor.h @@ -850,6 +850,7 @@ public: SWORD PainChance; int PainThreshold; FNameNoInit DamageType; + fixed_t DamageFactor; FState *SpawnState; FState *SeeState; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2e8f0050d..f7a5ef070 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2429,6 +2429,7 @@ enum APROP_NameTag = 21, APROP_Score = 22, APROP_Notrigger = 23, + APROP_DamageFactor = 24, }; // These are needed for ACS's APROP_RenderStyle @@ -2593,6 +2594,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) actor->Tag = FBehavior::StaticLookupString(value); break; + case APROP_DamageFactor: + actor->DamageFactor = value; + break; + default: // do nothing. break; @@ -2625,6 +2630,7 @@ int DLevelScript::GetActorProperty (int tid, int property) case APROP_Health: return actor->health; case APROP_Speed: return actor->Speed; case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead? + case APROP_DamageFactor:return actor->DamageFactor; case APROP_Alpha: return actor->alpha; case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style) { // Check for a legacy render style that matches. @@ -2685,6 +2691,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_Health: case APROP_Speed: case APROP_Damage: + case APROP_DamageFactor: case APROP_Alpha: case APROP_RenderStyle: case APROP_Gravity: @@ -2900,6 +2907,7 @@ enum EACSFunctions ACSF_SetUserVariable, ACSF_GetUserVariable, ACSF_Radius_Quake2, + ACSF_CheckActorClass, }; int DLevelScript::SideFromID(int id, int side) @@ -3139,6 +3147,13 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) P_StartQuake(activator, args[0], args[1], args[2], args[3], args[4], FBehavior::StaticLookupString(args[5])); break; + case ACSF_CheckActorClass: + { + AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL); + return a->GetClass()->TypeName == FName(FBehavior::StaticLookupString(args[1])); + } + + default: break; } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 0602226f8..22d8cdc81 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1009,6 +1009,8 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage if (damage <= 0) return; } } + damage = FixedMul(damage, target->DamageFactor); + if (damage <= 0) return; damage = target->TakeSpecialDamage (inflictor, source, damage, mod); } diff --git a/src/p_map.cpp b/src/p_map.cpp index 65ff3be78..644f599c6 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -886,8 +886,9 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // Check for blasted thing running into another if ((tm.thing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE)) { - if (!(thing->flags2 & MF2_BOSS) && (thing->flags3 & MF3_ISMONSTER)) + if (!(thing->flags2 & MF2_BOSS) && (thing->flags3 & MF3_ISMONSTER) && !(thing->flags3 & MF3_DONTBLAST)) { + // ideally this should take the mass factor into account thing->velx += tm.thing->velx; thing->vely += tm.thing->vely; if ((thing->velx + thing->vely) > 3*FRACUNIT) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e898fd687..2285b9f9a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -309,6 +309,10 @@ void AActor::Serialize (FArchive &arc) { arc << PainThreshold; } + if (SaveVersion >= 1914) + { + arc << DamageFactor; + } for(int i=0; i<10; i++) arc << uservar[i]; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index faa9fba46..2908eab65 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -924,18 +924,25 @@ DEFINE_PROPERTY(damagetype, S, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(damagefactor, SF, Actor) +DEFINE_PROPERTY(damagefactor, ZF, Actor) { PROP_STRING_PARM(str, 0); PROP_FIXED_PARM(id, 1); - if (info->DamageFactors == NULL) info->DamageFactors=new DmgFactors; + if (str == NULL) + { + defaults->DamageFactor = id; + } + else + { + if (info->DamageFactors == NULL) info->DamageFactors=new DmgFactors; - FName dmgType; - if (!stricmp(str, "Normal")) dmgType = NAME_None; - else dmgType=str; + FName dmgType; + if (!stricmp(str, "Normal")) dmgType = NAME_None; + else dmgType=str; - (*info->DamageFactors)[dmgType]=id; + (*info->DamageFactors)[dmgType]=id; + } } //========================================================================== From 34a4738b746b7a83cb9388e6fc498763e2bd60ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 Oct 2009 21:12:31 +0000 Subject: [PATCH 034/241] - forgot damagefactor setting in Actor class. SVN r1916 (trunk) --- wadsrc/static/actors/actor.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 10bd40ea7..8b58ab28d 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -17,6 +17,7 @@ ACTOR Actor native //: Thinker BounceCount -1 FloatSpeed 4 Gravity 1 + DamageFactor 1.0 PushFactor 0.25 // Variables for the expression evaluator From 8b27bd14347c6cc3b316ecb85ebcde0a31b29596 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 Oct 2009 16:04:19 +0000 Subject: [PATCH 035/241] - added 'defaultterrain' option to terrain parser for mods that want to have a different default terrain than a generic solid surface. - added format char processing to A_Print(Bold) and all printable messages that can be defined in DECORATE. - Fixed: The railgun code ignored MF3_ALWAYSPUFF. - added desaturated translations. - added optional state parameters to A_ReFire and A_GunFlash and A_CountdownArg. SVN r1921 (trunk) --- docs/rh-log.txt | 11 ++- src/c_console.cpp | 4 +- src/g_doom/a_doomweaps.cpp | 2 +- src/p_map.cpp | 10 ++- src/p_pspr.cpp | 47 ++++++++---- src/p_pspr.h | 2 +- src/p_terrain.cpp | 58 ++++++++------- src/p_terrain.h | 25 +++++-- src/r_translate.cpp | 91 ++++++++++++++++++++++- src/r_translate.h | 1 + src/thingdef/thingdef_codeptr.cpp | 13 +++- src/thingdef/thingdef_parse.cpp | 6 +- src/thingdef/thingdef_properties.cpp | 8 +- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/shared/inventory.txt | 4 +- 15 files changed, 219 insertions(+), 65 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4e0901290..a3f584964 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,5 +1,14 @@ +October 16, 2009 (Changes by Graf Zahl) +- added 'defaultterrain' option to terrain parser for mods that want to have + a different default terrain than a generic solid surface. +- added format char processing to A_Print(Bold) and all printable messages + that can be defined in DECORATE. +- Fixed: The railgun code ignored MF3_ALWAYSPUFF. +- added desaturated translations. +- added optional state parameters to A_ReFire and A_GunFlash and A_CountdownArg. + October 15, 2009 (Changes by Graf Zahl) -- added ACS CheckActprClass function +- added ACS CheckActorClass function - fixed: When a blasted actor collided with another one this other actor's DONTBLAST flag was not checked. - added a global DamageFactor actor property. All damage this actor takes is multiplied diff --git a/src/c_console.cpp b/src/c_console.cpp index 0cf2d9bce..ef06baa6a 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1824,8 +1824,8 @@ CCMD (echo) int last = argv.argc()-1; for (int i = 1; i <= last; ++i) { - strbin (argv[i]); - Printf ("%s%s", argv[i], i!=last ? " " : "\n"); + FString formatted = strbin1 (argv[i]); + Printf ("%s%s", formatted.GetChars(), i!=last ? " " : "\n"); } } diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index fcd6ea3a0..3cf59f16e 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -252,7 +252,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LoadShotgun2) DEFINE_ACTION_FUNCTION(AActor, A_CloseShotgun2) { S_Sound (self, CHAN_WEAPON, "weapons/sshotc", 1, ATTN_NORM); - CALL_ACTION(A_ReFire, self); + A_ReFire (self); } diff --git a/src/p_map.cpp b/src/p_map.cpp index 644f599c6..f225ef0e6 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3767,6 +3767,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color for (i = 0; i < RailHits.Size (); i++) { fixed_t x, y, z; + bool spawnpuff; x = x1 + FixedMul (RailHits[i].Distance, vx); y = y1 + FixedMul (RailHits[i].Distance, vy); @@ -3775,13 +3776,15 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color if ((RailHits[i].HitActor->flags & MF_NOBLOOD) || (RailHits[i].HitActor->flags2 & (MF2_DORMANT|MF2_INVULNERABLE))) { - if (puffclass != NULL) P_SpawnPuff (source, puffclass, x, y, z, source->angle - ANG90, 1, PF_HITTHING); + spawnpuff = puffclass != NULL; } else { + spawnpuff = (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF); P_SpawnBlood (x, y, z, source->angle - ANG180, damage, RailHits[i].HitActor); P_TraceBleed (damage, x, y, z, RailHits[i].HitActor, source->angle, pitch); } + if (spawnpuff) P_SpawnPuff (source, puffclass, x, y, z, source->angle - ANG90, 1, PF_HITTHING); P_DamageMobj (RailHits[i].HitActor, thepuff? thepuff:source, source, damage, damagetype, DMG_INFLICTOR_IS_PUFF); } @@ -3789,6 +3792,11 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color if (trace.HitType == TRACE_HitWall) { SpawnShootDecal (source, trace); + if (puffclass != NULL && puffDefaults->flags3 & MF3_ALWAYSPUFF) + { + P_SpawnPuff (source, puffclass, trace.X, trace.Y, trace.Z, source->angle - ANG90, 1, 0); + } + } if (trace.HitType == TRACE_HitFloor && trace.CrossedWater == NULL && diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index ee287a8f1..0b464aab2 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -206,7 +206,7 @@ void P_BringUpWeapon (player_t *player) // //--------------------------------------------------------------------------- -void P_FireWeapon (player_t *player) +void P_FireWeapon (player_t *player, FState *state) { AWeapon *weapon; @@ -225,7 +225,11 @@ void P_FireWeapon (player_t *player) player->mo->PlayAttacking (); weapon->bAltFire = false; - P_SetPsprite (player, ps_weapon, weapon->GetAtkState(!!player->refire)); + if (state == NULL) + { + state = weapon->GetAtkState(!!player->refire); + } + P_SetPsprite (player, ps_weapon, state); if (!(weapon->WeaponFlags & WIF_NOALERT)) { P_NoiseAlert (player->mo, player->mo, false); @@ -238,7 +242,7 @@ void P_FireWeapon (player_t *player) // //--------------------------------------------------------------------------- -void P_FireWeaponAlt (player_t *player) +void P_FireWeaponAlt (player_t *player, FState *state) { AWeapon *weapon; @@ -258,8 +262,12 @@ void P_FireWeaponAlt (player_t *player) player->mo->PlayAttacking (); weapon->bAltFire = true; + if (state == NULL) + { + state = weapon->GetAltAtkState(!!player->refire); + } - P_SetPsprite (player, ps_weapon, weapon->GetAltAtkState(!!player->refire)); + P_SetPsprite (player, ps_weapon, state); if (!(weapon->WeaponFlags & WIF_NOALERT)) { P_NoiseAlert (player->mo, player->mo, false); @@ -456,7 +464,7 @@ void P_CheckWeaponFire (player_t *player) if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) { player->attackdown = true; - P_FireWeapon (player); + P_FireWeapon (player, NULL); return; } } @@ -465,7 +473,7 @@ void P_CheckWeaponFire (player_t *player) if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) { player->attackdown = true; - P_FireWeaponAlt (player); + P_FireWeaponAlt (player, NULL); return; } } @@ -507,7 +515,15 @@ void P_CheckWeaponSwitch (player_t *player) // //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AInventory, A_ReFire) +DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_ReFire) +{ + ACTION_PARAM_START(1) + ACTION_PARAM_STATE(state, 0); + + A_ReFire(self, state); +} + +void A_ReFire(AActor *self, FState *state) { player_t *player = self->player; @@ -520,14 +536,14 @@ DEFINE_ACTION_FUNCTION(AInventory, A_ReFire) && player->PendingWeapon == WP_NOCHANGE && player->health) { player->refire++; - P_FireWeapon (player); + P_FireWeapon (player, state); } else if ((player->cmd.ucmd.buttons&BT_ALTATTACK) && player->ReadyWeapon->bAltFire && player->PendingWeapon == WP_NOCHANGE && player->health) { player->refire++; - P_FireWeaponAlt (player); + P_FireWeaponAlt (player, state); } else { @@ -661,8 +677,11 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) // // A_GunFlash // -DEFINE_ACTION_FUNCTION(AInventory, A_GunFlash) +DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { + ACTION_PARAM_START(1) + ACTION_PARAM_STATE(flash, 0); + player_t *player = self->player; if (NULL == player) @@ -671,9 +690,11 @@ DEFINE_ACTION_FUNCTION(AInventory, A_GunFlash) } player->mo->PlayAttacking2 (); - FState * flash=NULL; - if (player->ReadyWeapon->bAltFire) flash = player->ReadyWeapon->FindState(NAME_AltFlash); - if (flash == NULL) flash = player->ReadyWeapon->FindState(NAME_Flash); + if (flash == NULL) + { + if (player->ReadyWeapon->bAltFire) flash = player->ReadyWeapon->FindState(NAME_AltFlash); + if (flash == NULL) flash = player->ReadyWeapon->FindState(NAME_Flash); + } P_SetPsprite (player, ps_flash, flash); } diff --git a/src/p_pspr.h b/src/p_pspr.h index 849816537..90a57b555 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -95,6 +95,6 @@ void DoReadyWeaponToFire(AActor * self, bool primary = true, bool secondary = tr void DoReadyWeaponToSwitch(AActor * self); DECLARE_ACTION(A_Raise) -DECLARE_ACTION(A_ReFire) +void A_ReFire(AActor *self, FState *state = NULL); #endif // __P_PSPR_H__ diff --git a/src/p_terrain.cpp b/src/p_terrain.cpp index dbb187530..a2750fbea 100644 --- a/src/p_terrain.cpp +++ b/src/p_terrain.cpp @@ -63,7 +63,8 @@ enum EOuterKeywords OUT_IFHERETIC, OUT_IFHEXEN, OUT_IFSTRIFE, - OUT_ENDIF + OUT_ENDIF, + OUT_DEFAULTTERRAIN }; enum ETerrainKeywords @@ -125,6 +126,7 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw void *fields, const char *type, FName name); static void ParseDamage (FScanner &sc, int keyword, void *fields); static void ParseFriction (FScanner &sc, int keyword, void *fields); +static void ParseDefault (FScanner &sc); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -133,6 +135,7 @@ static void ParseFriction (FScanner &sc, int keyword, void *fields); FTerrainTypeArray TerrainTypes; TArray Splashes; TArray Terrains; +WORD DefaultTerrainType; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -146,6 +149,7 @@ static const char *OuterKeywords[] = "ifhexen", "ifstrife", "endif", + "defaultterrain", NULL }; @@ -222,27 +226,7 @@ static FGenericParse TerrainParser[] = { GEN_Bool, {theoffsetof(FTerrainDef, AllowProtection)} }, }; -/* -struct -{ - char *name; - int type; - bool Heretic; -} - TerrainTypeDefs[] = -{ - { "FLTWAWA1", FLOOR_WATER, true }, - { "FLTFLWW1", FLOOR_WATER, true }, - { "FLTLAVA1", FLOOR_LAVA, true }, - { "FLATHUH1", FLOOR_LAVA, true }, - { "FLTSLUD1", FLOOR_SLUDGE, true }, - { "X_005", FLOOR_WATER, false }, - { "X_001", FLOOR_LAVA, false }, - { "X_009", FLOOR_SLUDGE, false }, - { "F_033", FLOOR_ICE, false }, - { "END", -1 } -}; -*/ + // CODE -------------------------------------------------------------------- @@ -258,9 +242,9 @@ void P_InitTerrainTypes () int lump; int size; - size = (TexMan.NumTextures()+1)*sizeof(BYTE); + size = (TexMan.NumTextures()+1); TerrainTypes.Resize(size); - memset (&TerrainTypes[0], 0, size); + TerrainTypes.Clear(); MakeDefaultTerrain (); @@ -343,6 +327,10 @@ static void ParseOuter (FScanner &sc) ParseFloor (sc); break; + case OUT_DEFAULTTERRAIN: + ParseDefault (sc); + break; + case OUT_IFDOOM: if (!(gameinfo.gametype & GAME_DoomChex)) { @@ -676,7 +664,27 @@ static void ParseFloor (FScanner &sc) Printf ("Unknown terrain %s\n", sc.String); terrain = 0; } - TerrainTypes[picnum] = terrain; + TerrainTypes.Set(picnum.GetIndex(), terrain); +} + +//========================================================================== +// +// ParseFloor +// +//========================================================================== + +static void ParseDefault (FScanner &sc) +{ + int terrain; + + sc.MustGetString (); + terrain = FindTerrain (sc.String); + if (terrain == -1) + { + Printf ("Unknown terrain %s\n", sc.String); + terrain = 0; + } + DefaultTerrainType = terrain; } //========================================================================== diff --git a/src/p_terrain.h b/src/p_terrain.h index 087087afe..d2933b687 100644 --- a/src/p_terrain.h +++ b/src/p_terrain.h @@ -39,25 +39,36 @@ struct PClass; -// This is just a wrapper class so that I don't have to expose FTextureID's implementation -// to anything that doesn't really need it. +extern WORD DefaultTerrainType; + + class FTerrainTypeArray { public: - TArray Types; + TArray Types; - BYTE &operator [](FTextureID tex) + WORD operator [](FTextureID tex) const { - return Types[tex.GetIndex()]; + WORD type = Types[tex.GetIndex()]; + return type == 0xffff? DefaultTerrainType : type; } - BYTE &operator [](int texnum) + WORD operator [](int texnum) const { - return Types[texnum]; + WORD type = Types[texnum]; + return type == 0xffff? DefaultTerrainType : type; } void Resize(unsigned newsize) { Types.Resize(newsize); } + void Clear() + { + memset (&Types[0], 0xff, Types.Size()*sizeof(WORD)); + } + void Set(int index, int value) + { + Types[index] = value; + } }; extern FTerrainTypeArray TerrainTypes; diff --git a/src/r_translate.cpp b/src/r_translate.cpp index 212253288..afd35cf29 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -396,9 +396,48 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in // //---------------------------------------------------------------------------- +void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b1, float r2, float g2, float b2) +{ + r1 = clamp(r1, 0.0f, 2.0f); + g1 = clamp(g1, 0.0f, 2.0f); + b1 = clamp(b1, 0.0f, 2.0f); + r2 = clamp(r2, 0.0f, 2.0f); + g2 = clamp(g2, 0.0f, 2.0f); + b2 = clamp(b2, 0.0f, 2.0f); + + r2 -= r1; + g2 -= g1; + b2 -= b1; + r1 *= 255; + g1 *= 255; + b1 *= 255; + + for(int c=start; c < end; c++) + { + double intensity = (GPalette.BaseColors[c].r * 77 + + GPalette.BaseColors[c].g * 143 + + GPalette.BaseColors[c].b * 37) / 256.0; + + PalEntry pe = PalEntry( MIN(255, int(r1 + intensity*r2)), + MIN(255, int(g1 + intensity*g2)), + MIN(255, int(b1 + intensity*b2))); + + Remap[c] = ColorMatcher.Pick(pe); + Palette[c] = pe; + Palette[c].a = c==0? 0:255; + } +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + void FRemapTable::AddToTranslation(const char * range) { int start,end; + bool desaturated = false; FScanner sc; sc.OpenMem("translation", range, int(strlen(range))); @@ -412,7 +451,15 @@ void FRemapTable::AddToTranslation(const char * range) sc.MustGetToken(TK_IntConst); end = sc.Number; sc.MustGetToken('='); - if (!sc.CheckToken('[')) + if (start < 0 || start > 255 || end < 0 || end > 255) + { + sc.ScriptError("Palette index out of range"); + return; + } + + sc.MustGetAnyToken(); + + if (sc.TokenType != '[' && sc.TokenType != '%') { int pal1,pal2; @@ -423,7 +470,7 @@ void FRemapTable::AddToTranslation(const char * range) pal2 = sc.Number; AddIndexRange(start, end, pal1, pal2); } - else + else if (sc.TokenType == '[') { // translation using RGB values int r1,g1,b1,r2,g2,b2; @@ -456,6 +503,46 @@ void FRemapTable::AddToTranslation(const char * range) AddColorRange(start, end, r1, g1, b1, r2, g2, b2); } + else if (sc.TokenType == '%') + { + // translation using RGB values + float r1,g1,b1,r2,g2,b2; + + sc.MustGetToken('['); + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + r1 = float(sc.Float); + sc.MustGetToken(','); + + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + g1 = float(sc.Float); + sc.MustGetToken(','); + + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + b1 = float(sc.Float); + sc.MustGetToken(']'); + sc.MustGetToken(':'); + sc.MustGetToken('['); + + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + r2 = float(sc.Float); + sc.MustGetToken(','); + + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + g2 = float(sc.Float); + sc.MustGetToken(','); + + sc.MustGetAnyToken(); + if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst); + b2 = float(sc.Float); + sc.MustGetToken(']'); + + AddDesaturation(start, end, r1, g1, b1, r2, g2, b2); + } } catch (CRecoverableError &err) { diff --git a/src/r_translate.h b/src/r_translate.h index 098edb699..730dac541 100644 --- a/src/r_translate.h +++ b/src/r_translate.h @@ -38,6 +38,7 @@ struct FRemapTable void Serialize(FArchive &ar); void AddIndexRange(int start, int end, int pal1, int pal2); void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2); + void AddDesaturation(int start, int end, float r1,float g1, float b1, float r2, float g2, float b2); void AddToTranslation(const char * range); int StoreTranslation(); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d8ac6ef69..cf9e56e8e 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1699,7 +1699,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print) con_midtime = time; } - C_MidPrint(font != NULL ? font : SmallFont, text); + FString formatted = strbin1(text); + C_MidPrint(font != NULL ? font : SmallFont, formatted.GetChars()); con_midtime = saved; } } @@ -1729,7 +1730,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold) con_midtime = time; } - C_MidPrintBold(font != NULL ? font : SmallFont, text); + FString formatted = strbin1(text); + C_MidPrintBold(font != NULL ? font : SmallFont, formatted.GetChars()); con_midtime = saved; } @@ -1987,8 +1989,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_KillSiblings) //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_INT(cnt, 0); + ACTION_PARAM_STATE(state, 1); if (cnt<0 || cnt>=5) return; if (!self->args[cnt]--) @@ -2003,7 +2006,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CountdownArg) } else { - self->SetState(self->FindState(NAME_Death)); + // can't use "Death" as default parameter with current DECORATE parser. + if (state == NULL) state = self->FindState(NAME_Death); + self->SetState(state); } } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 7a84a3ed8..ddc0c8eb9 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -592,11 +592,15 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau // fall through case 'S': - case 'T': sc.MustGetString(); conv.s = strings[strings.Reserve(1)] = sc.String; break; + case 'T': + sc.MustGetString(); + conv.s = strings[strings.Reserve(1)] = strbin1(sc.String); + break; + case 'C': if (sc.CheckNumber ()) { diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 2908eab65..6226bd0df 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -186,7 +186,7 @@ int MatchString (const char *in, const char **strings) //========================================================================== // //========================================================================== -DEFINE_INFO_PROPERTY(game, T, Actor) +DEFINE_INFO_PROPERTY(game, S, Actor) { PROP_STRING_PARM(str, 0); if (!stricmp(str, "Doom")) @@ -1302,7 +1302,7 @@ DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory) //========================================================================== // //========================================================================== -DEFINE_CLASS_PROPERTY(pickupmessage, S, Inventory) +DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory) { PROP_STRING_PARM(str, 0); info->Class->Meta.SetMetaString(AIMETA_PickupMessage, str); @@ -1354,7 +1354,7 @@ DEFINE_CLASS_PROPERTY(givequest, I, Inventory) //========================================================================== // //========================================================================== -DEFINE_CLASS_PROPERTY(lowmessage, IS, Health) +DEFINE_CLASS_PROPERTY(lowmessage, IT, Health) { PROP_INT_PARM(i, 0); PROP_STRING_PARM(str, 1); @@ -1383,7 +1383,7 @@ DEFINE_CLASS_PROPERTY(number, I, PuzzleItem) //========================================================================== // //========================================================================== -DEFINE_CLASS_PROPERTY(failmessage, S, PuzzleItem) +DEFINE_CLASS_PROPERTY(failmessage, T, PuzzleItem) { PROP_STRING_PARM(str, 0); info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, str); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 8b58ab28d..fbbab0a40 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -224,7 +224,7 @@ ACTOR Actor native //: Thinker action native A_JumpIfInTargetInventory(class itemtype, int amount, state label); action native A_GiveToTarget(class itemtype, int amount = 0); action native A_TakeFromTarget(class itemtype, int amount = 0); - action native A_CountdownArg(int argnum); + action native A_CountdownArg(int argnum, state targstate = ""); action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); action native A_Burst(class chunktype); diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index ca73cab29..659bab632 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -36,10 +36,10 @@ ACTOR Inventory native action native A_BFGsound(); action native A_FireBFG(); action native A_FireOldBFG(); - action native A_ReFire(); + action native A_ReFire(state flash = ""); action native A_ClearReFire(); action native A_CheckReload(); - action native A_GunFlash(); + action native A_GunFlash(state flash = ""); action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff"); action native A_CheckForReload(int counter, state label, bool dontincrement = false); action native A_ResetReloadCounter(); From bbcd6ed5f9d337dcefd6c424417c1fcb9c4711e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Oct 2009 07:05:34 +0000 Subject: [PATCH 036/241] - fixed: The desaturation translation addition broke parsing of palette index based translations. SVN r1925 (trunk) --- docs/rh-log.txt | 3 +++ src/r_translate.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a3f584964..232cff329 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +October 17, 2009 (Changes by Graf Zahl) +- fixed: The translation addition broke parsing of palette index based translations. + October 16, 2009 (Changes by Graf Zahl) - added 'defaultterrain' option to terrain parser for mods that want to have a different default terrain than a generic solid surface. diff --git a/src/r_translate.cpp b/src/r_translate.cpp index afd35cf29..bd1e7bfd4 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -463,7 +463,7 @@ void FRemapTable::AddToTranslation(const char * range) { int pal1,pal2; - sc.MustGetToken(TK_IntConst); + sc.TokenMustBe(TK_IntConst); pal1 = sc.Number; sc.MustGetToken(':'); sc.MustGetToken(TK_IntConst); From 0c39b5c66afc42308d1f7e22d4ff890709e4e758 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Oct 2009 11:30:44 +0000 Subject: [PATCH 037/241] - Fixed: The rail sound used the shooter's position for calculating the sound origin but should use the camera position instead to get the correct position for the closest point along the trail. - Fixed: Explosions no longer caused splashes. - Fixed: Copying translations to lower decals had the shade color check wrong. - Fixed: Waggling floors did not move attached geometry. - Cleaned up p_floor.cpp so that related parts of the code are grouped together. SVN r1926 (trunk) --- docs/rh-log.txt | 7 + src/g_doom/a_fatso.cpp | 5 +- src/g_heretic/a_hereticartifacts.cpp | 5 +- src/g_shared/a_decals.cpp | 5 +- src/g_strife/a_thingstoblowup.cpp | 5 +- src/p_effect.cpp | 22 +- src/p_enemy.cpp | 5 +- src/p_floor.cpp | 469 +++++++++++------- src/p_local.h | 3 +- src/p_mobj.cpp | 23 +- src/thingdef/thingdef_codeptr.cpp | 10 +- wadsrc/static/actors/strife/strifeweapons.txt | 1 + 12 files changed, 341 insertions(+), 219 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 232cff329..4c19865e9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,11 @@ October 17, 2009 (Changes by Graf Zahl) +- Fixed: The rail sound used the shooter's position for calculating the sound origin + but should use the camera position instead to get the correct position for + the closest point along the trail. +- Fixed: Explosions no longer caused splashes. +- Fixed: Copying translations to lower decals had the shade color check wrong. +- Fixed: Waggling floors did not moved attached geometry. +- Cleaned up p_floor.cpp so that related parts of the code are grouped together. - fixed: The translation addition broke parsing of palette index based translations. October 16, 2009 (Changes by Graf Zahl) diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index e9dfa98e3..484df58ca 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -135,10 +135,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true); - if (self->z <= self->floorz + (128<RenderStyle = STYLE_Add; self->alpha = FRACUNIT; P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true); - if (self->z <= self->floorz + (128<LowerDecal) { - int lowercolor = color; + int lowercolor; const FDecalTemplate * tpl_low = tpl->LowerDecal->GetDecal(); // If the default color of the lower decal is the same as the main decal's // apply the custom color as well. - if (tpl->ShadeColor == tpl_low->ShadeColor) lowercolor=0; + if (tpl->ShadeColor != tpl_low->ShadeColor) lowercolor=0; + else lowercolor = color; StaticCreate (tpl_low, x, y, z, wall, ffloor, lowercolor); } DImpactDecal::CheckMax(); diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index 52cb1d3e5..9727bccd1 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -74,10 +74,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode512) { self->target->player->extralight = 5; } - if (self->z <= self->floorz + (512<RenderStyle = STYLE_Add; diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 19b623b38..79de562c1 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -472,17 +472,33 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end } else { + // Only consider sound in 2D (for now, anyway) // [BB] You have to devide by lengthsquared here, not multiply with it. - r = ((start.Y - FIXED2FLOAT(mo->y)) * (-dir.Y) - - (start.X - FIXED2FLOAT(mo->x)) * (dir.X)) / lengthsquared; + + r = ((start.Y - FIXED2FLOAT(viewy)) * (-dir.Y) - (start.X - FIXED2FLOAT(viewx)) * (dir.X)) / lengthsquared; + r = clamp(r, 0., 1.); dirz = dir.Z; dir.Z = 0; point = start + r * dir; dir.Z = dirz; - S_Sound (FLOAT2FIXED(point.X), FLOAT2FIXED(point.Y), mo->z, +#if 0 + Printf("Start = (%1.4f,%1.4f), End = (%1.4f,%1.4f), Dir =(%1.4f,%1.4f), View = (%1.4f,%1.4f), Point = (%1.4f,%1.4f), r=%1.4f\n", + start.X, start.Y, end.X, end.Y, dir.X, dir.Y, FIXED2FLOAT(viewx), FIXED2FLOAT(viewy), + point.X, point.Y, r); + + FVector3 _start = start; + FVector3 _end = end; + FVector3 view(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy), 0); + point.Z = _start.Z = _end.Z = 0; + + Printf("S: %1.4f, E: %1.4f, H: %1.4f P: %1.4f\n", + (_start-view).Length(), (_end-view).Length(), (((_start+_end)/2)-view).Length(), (point-view).Length()); +#endif + + S_Sound (FLOAT2FIXED(point.X), FLOAT2FIXED(point.Y), viewz, CHAN_WEAPON, sound, 1, ATTN_NORM); } } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index d25ae3de0..300d70a0f 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2986,10 +2986,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Detonate) { int damage = self->GetMissileDamage (0, 1); P_RadiusAttack (self, self->target, damage, damage, self->DamageType, true); - if (self->z <= self->floorz + (damage << FRACBITS)) - { - P_HitFloor (self); - } + P_CheckSplash(self, damage<seqType >= 0) + { + SN_StartSequence (sec, CHAN_FLOOR, sec->seqType, SEQ_PLATFORM, 0); + } + else + { + SN_StartSequence (sec, CHAN_FLOOR, "Floor", 0); + } +} + + +//========================================================================== // // FLOORS // +//========================================================================== IMPLEMENT_CLASS (DFloor) @@ -60,71 +82,12 @@ void DFloor::Serialize (FArchive &arc) << m_Hexencrush; } -IMPLEMENT_POINTY_CLASS (DElevator) - DECLARE_POINTER(m_Interp_Floor) - DECLARE_POINTER(m_Interp_Ceiling) -END_POINTERS - -DElevator::DElevator () -{ -} - -void DElevator::Serialize (FArchive &arc) -{ - Super::Serialize (arc); - arc << m_Type - << m_Direction - << m_FloorDestDist - << m_CeilingDestDist - << m_Speed - << m_Interp_Floor - << m_Interp_Ceiling; -} - -void DElevator::Destroy() -{ - if (m_Interp_Ceiling != NULL) - { - m_Interp_Ceiling->DelRef(); - m_Interp_Ceiling = NULL; - } - if (m_Interp_Floor != NULL) - { - m_Interp_Floor->DelRef(); - m_Interp_Floor = NULL; - } - Super::Destroy(); -} - -IMPLEMENT_POINTY_CLASS (DWaggleBase) - DECLARE_POINTER(m_Interpolation) -END_POINTERS - -IMPLEMENT_CLASS (DFloorWaggle) -IMPLEMENT_CLASS (DCeilingWaggle) - -DWaggleBase::DWaggleBase () -{ -} - -void DWaggleBase::Serialize (FArchive &arc) -{ - Super::Serialize (arc); - arc << m_OriginalDist - << m_Accumulator - << m_AccDelta - << m_TargetScale - << m_Scale - << m_ScaleDelta - << m_Ticker - << m_State - << m_Interpolation; -} - - +//========================================================================== // -// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) +// MOVE A FLOOR TO ITS DESTINATION (UP OR DOWN) // +//========================================================================== + void DFloor::Tick () { EResult res; @@ -238,62 +201,11 @@ void DFloor::Tick () } } +//========================================================================== // -// T_MoveElevator() // -// Move an elevator to it's destination (up or down) -// Called once per tick for each moving floor. // -// Passed an elevator_t structure that contains all pertinent info about the -// move. See P_SPEC.H for fields. -// No return. -// -// jff 02/22/98 added to support parallel floor/ceiling motion -// -void DElevator::Tick () -{ - EResult res; - - fixed_t oldfloor, oldceiling; - - oldfloor = m_Sector->floorplane.d; - oldceiling = m_Sector->ceilingplane.d; - - if (m_Direction < 0) // moving down - { - res = MoveFloor (m_Speed, m_FloorDestDist, m_Direction); - if (res == ok || res == pastdest) - { - res = MoveCeiling (m_Speed, m_CeilingDestDist, m_Direction); - if (res == crushed) - { - MoveFloor (m_Speed, oldfloor, -m_Direction); - } - } - } - else // up - { - res = MoveCeiling (m_Speed, m_CeilingDestDist, m_Direction); - if (res == ok || res == pastdest) - { - res = MoveFloor (m_Speed, m_FloorDestDist, m_Direction); - if (res == crushed) - { - MoveCeiling (m_Speed, oldceiling, -m_Direction); - } - } - } - - if (res == pastdest) // if destination height acheived - { - // make floor stop sound - SN_StopSequence (m_Sector); - - m_Sector->floordata = NULL; //jff 2/22/98 - m_Sector->ceilingdata = NULL; //jff 2/22/98 - Destroy (); // remove elevator from actives - } -} +//========================================================================== void DFloor::SetFloorChangeType (sector_t *sec, int change) { @@ -315,37 +227,35 @@ void DFloor::SetFloorChangeType (sector_t *sec, int change) } } -static void StartFloorSound (sector_t *sec) -{ - if (sec->seqType >= 0) - { - SN_StartSequence (sec, CHAN_FLOOR, sec->seqType, SEQ_PLATFORM, 0); - } - else - { - SN_StartSequence (sec, CHAN_FLOOR, "Floor", 0); - } -} +//========================================================================== +// +// +// +//========================================================================== void DFloor::StartFloorSound () { ::StartFloorSound (m_Sector); } -void DElevator::StartFloorSound () -{ - ::StartFloorSound (m_Sector); -} +//========================================================================== +// +// +// +//========================================================================== DFloor::DFloor (sector_t *sec) : DMovingFloor (sec) { } +//========================================================================== // // HANDLE FLOOR TYPES // [RH] Added tag, speed, height, crush, change params. // +//========================================================================== + bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag, fixed_t speed, fixed_t height, int crush, int change, bool hexencrush) { @@ -601,10 +511,14 @@ manual_floor: return rtn; } +//========================================================================== +// // [RH] // EV_FloorCrushStop // Stop a floor from crushing! // +//========================================================================== + bool EV_FloorCrushStop (int tag) { int secnum = -1; @@ -624,61 +538,11 @@ bool EV_FloorCrushStop (int tag) return true; } +//========================================================================== // -// EV_DoChange() +// Linear tag search to emulate stair building from Doom.exe // -// Handle pure change types. These change floor texture and sector type -// by trigger or numeric model without moving the floor. -// -// The linedef causing the change and the type of change is passed -// Returns true if any sector changes -// -// jff 3/15/98 added to better support generalized sector types -// [RH] Added tag parameter. -// -bool EV_DoChange (line_t *line, EChange changetype, int tag) -{ - int secnum; - bool rtn; - sector_t *sec; - sector_t *secm; - - secnum = -1; - rtn = false; - // change all sectors with the same tag as the linedef - while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) - { - sec = §ors[secnum]; - - rtn = true; - - // handle trigger or numeric change type - FTextureID oldpic = sec->GetTexture(sector_t::floor); - - switch(changetype) - { - case trigChangeOnly: - if (line) - { // [RH] if no line, no change - sec->SetTexture(sector_t::floor, line->frontsector->GetTexture(sector_t::floor)); - sec->special = (sec->special & SECRET_MASK) | (line->frontsector->special & ~SECRET_MASK); - } - break; - case numChangeOnly: - secm = sec->FindModelFloorSector (sec->CenterFloor()); - if (secm) - { // if no model, no change - sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor)); - sec->special = secm->special; - } - break; - default: - break; - } - } - return rtn; -} - +//========================================================================== static int P_FindSectorFromTagLinear (int tag, int start) { @@ -689,6 +553,7 @@ static int P_FindSectorFromTagLinear (int tag, int start) return -1; } +//========================================================================== // // BUILD A STAIRCASE! // [RH] Added stairsize, srcspeed, delay, reset, igntxt, usespecials parameters @@ -696,6 +561,8 @@ static int P_FindSectorFromTagLinear (int tag, int start) // by its special. If usespecials is 2, each sector stays in "sync" with // the others. // +//========================================================================== + bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt, int usespecials) @@ -897,7 +764,12 @@ manual_stair: return rtn; } +//========================================================================== +// // [RH] Added pillarspeed and slimespeed parameters +// +//========================================================================== + bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed) { sector_t* s1; @@ -966,6 +838,21 @@ bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed) return rtn; } +//========================================================================== +// +// Elevators +// +//========================================================================== + +IMPLEMENT_POINTY_CLASS (DElevator) + DECLARE_POINTER(m_Interp_Floor) + DECLARE_POINTER(m_Interp_Ceiling) +END_POINTERS + +DElevator::DElevator () +{ +} + DElevator::DElevator (sector_t *sec) : Super (sec) { @@ -975,6 +862,111 @@ DElevator::DElevator (sector_t *sec) m_Interp_Ceiling = sec->SetInterpolation(sector_t::CeilingMove, true); } +void DElevator::Serialize (FArchive &arc) +{ + Super::Serialize (arc); + arc << m_Type + << m_Direction + << m_FloorDestDist + << m_CeilingDestDist + << m_Speed + << m_Interp_Floor + << m_Interp_Ceiling; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DElevator::Destroy() +{ + if (m_Interp_Ceiling != NULL) + { + m_Interp_Ceiling->DelRef(); + m_Interp_Ceiling = NULL; + } + if (m_Interp_Floor != NULL) + { + m_Interp_Floor->DelRef(); + m_Interp_Floor = NULL; + } + Super::Destroy(); +} + +//========================================================================== +// +// T_MoveElevator() +// +// Move an elevator to it's destination (up or down) +// Called once per tick for each moving floor. +// +// Passed an elevator_t structure that contains all pertinent info about the +// move. See P_SPEC.H for fields. +// No return. +// +// jff 02/22/98 added to support parallel floor/ceiling motion +// +//========================================================================== + +void DElevator::Tick () +{ + EResult res; + + fixed_t oldfloor, oldceiling; + + oldfloor = m_Sector->floorplane.d; + oldceiling = m_Sector->ceilingplane.d; + + if (m_Direction < 0) // moving down + { + res = MoveFloor (m_Speed, m_FloorDestDist, m_Direction); + if (res == ok || res == pastdest) + { + res = MoveCeiling (m_Speed, m_CeilingDestDist, m_Direction); + if (res == crushed) + { + MoveFloor (m_Speed, oldfloor, -m_Direction); + } + } + } + else // up + { + res = MoveCeiling (m_Speed, m_CeilingDestDist, m_Direction); + if (res == ok || res == pastdest) + { + res = MoveFloor (m_Speed, m_FloorDestDist, m_Direction); + if (res == crushed) + { + MoveCeiling (m_Speed, oldceiling, -m_Direction); + } + } + } + + if (res == pastdest) // if destination height acheived + { + // make floor stop sound + SN_StopSequence (m_Sector); + + m_Sector->floordata = NULL; //jff 2/22/98 + m_Sector->ceilingdata = NULL; //jff 2/22/98 + Destroy (); // remove elevator from actives + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void DElevator::StartFloorSound () +{ + ::StartFloorSound (m_Sector); +} + +//========================================================================== // // EV_DoElevator // @@ -985,6 +977,8 @@ DElevator::DElevator (sector_t *sec) // jff 2/22/98 new type to move floor and ceiling in parallel // [RH] Added speed, tag, and height parameters and new types. // +//========================================================================== + bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype, fixed_t speed, fixed_t height, int tag) { @@ -1071,6 +1065,96 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype, } +//========================================================================== +// +// EV_DoChange() +// +// Handle pure change types. These change floor texture and sector type +// by trigger or numeric model without moving the floor. +// +// The linedef causing the change and the type of change is passed +// Returns true if any sector changes +// +// jff 3/15/98 added to better support generalized sector types +// [RH] Added tag parameter. +// +//========================================================================== + +bool EV_DoChange (line_t *line, EChange changetype, int tag) +{ + int secnum; + bool rtn; + sector_t *sec; + sector_t *secm; + + secnum = -1; + rtn = false; + // change all sectors with the same tag as the linedef + while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) + { + sec = §ors[secnum]; + + rtn = true; + + // handle trigger or numeric change type + FTextureID oldpic = sec->GetTexture(sector_t::floor); + + switch(changetype) + { + case trigChangeOnly: + if (line) + { // [RH] if no line, no change + sec->SetTexture(sector_t::floor, line->frontsector->GetTexture(sector_t::floor)); + sec->special = (sec->special & SECRET_MASK) | (line->frontsector->special & ~SECRET_MASK); + } + break; + case numChangeOnly: + secm = sec->FindModelFloorSector (sec->CenterFloor()); + if (secm) + { // if no model, no change + sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor)); + sec->special = secm->special; + } + break; + default: + break; + } + } + return rtn; +} + + +//========================================================================== +// +// +// +//========================================================================== + +IMPLEMENT_POINTY_CLASS (DWaggleBase) + DECLARE_POINTER(m_Interpolation) +END_POINTERS + +IMPLEMENT_CLASS (DFloorWaggle) +IMPLEMENT_CLASS (DCeilingWaggle) + +DWaggleBase::DWaggleBase () +{ +} + +void DWaggleBase::Serialize (FArchive &arc) +{ + Super::Serialize (arc); + arc << m_OriginalDist + << m_Accumulator + << m_AccDelta + << m_TargetScale + << m_Scale + << m_ScaleDelta + << m_Ticker + << m_State + << m_Interpolation; +} + //========================================================================== // // WaggleBase @@ -1096,6 +1180,12 @@ void DWaggleBase::Destroy() Super::Destroy(); } +//========================================================================== +// +// +// +//========================================================================== + void DWaggleBase::DoWaggle (bool ceiling) { secplane_t *plane; @@ -1159,7 +1249,12 @@ void DWaggleBase::DoWaggle (bool ceiling) FixedMul (FloatBobOffsets[(m_Accumulator>>FRACBITS)&63], m_Scale)); m_Sector->ChangePlaneTexZ(pos, plane->HeightDiff (dist)); dist = plane->HeightDiff (dist); - P_ChangeSector (m_Sector, true, dist, ceiling, false); + + // Interesting: Hexen passes 'true' for the crunch parameter which really is crushing damage here... + // Also, this does not reset the move if it blocks. + P_Scroll3dMidtex(m_Sector, 1, dist, ceiling); + P_MoveLinkedSectors(m_Sector, 1, dist, ceiling); + P_ChangeSector (m_Sector, 1, dist, ceiling, false); } //========================================================================== @@ -1176,7 +1271,7 @@ DFloorWaggle::DFloorWaggle (sector_t *sec) : Super (sec) { sec->floordata = this; - m_Interpolation = sec->SetInterpolation(sector_t::FloorMove, false); + m_Interpolation = sec->SetInterpolation(sector_t::FloorMove, true); } void DFloorWaggle::Tick () @@ -1198,7 +1293,7 @@ DCeilingWaggle::DCeilingWaggle (sector_t *sec) : Super (sec) { sec->ceilingdata = this; - m_Interpolation = sec->SetInterpolation(sector_t::CeilingMove, false); + m_Interpolation = sec->SetInterpolation(sector_t::CeilingMove, true); } void DCeilingWaggle::Tick () diff --git a/src/p_local.h b/src/p_local.h index 71a662fb7..0be5c11e0 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -403,7 +403,8 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile ver void P_TraceBleed (int damage, AActor *target); // random direction version void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false, const PClass *puff = NULL, bool pierce = true); // [RH] Shoot a railgun bool P_HitFloor (AActor *thing); -bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false); +bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true); +void P_CheckSplash(AActor *self, fixed_t distance); bool P_CheckMissileSpawn (AActor *missile); void P_PlaySpawnSound(AActor *missile, AActor *spawner); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2285b9f9a..5a00bcc1f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4618,7 +4618,7 @@ int P_GetThingFloorType (AActor *thing) // Returns true if hit liquid and splashed, false if not. //--------------------------------------------------------------------------- -bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool checkabove) +bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool checkabove, bool alert) { if (thing->flags2 & MF2_FLOATBOB || thing->flags3 & MF3_DONTSPLASH) return false; @@ -4716,7 +4716,7 @@ foundone: { mo = Spawn (splash->SplashBase, x, y, z, ALLOW_REPLACE); } - if (thing->player && !splash->NoAlert) + if (thing->player && !splash->NoAlert && alert) { P_NoiseAlert (thing, thing, true); } @@ -4793,6 +4793,25 @@ bool P_HitFloor (AActor *thing) return P_HitWater (thing, m->m_sector); } +//--------------------------------------------------------------------------- +// +// P_CheckSplash +// +// Checks for splashes caused by explosions +// +//--------------------------------------------------------------------------- + +void P_CheckSplash(AActor *self, fixed_t distance) +{ + if (self->z <= self->floorz + (distance<floorsector == self->Sector) + { + // Explosion splashes never alert monsters. This is because A_Explode has + // a separate parameter for that so this would get in the way of proper + // behavior. + P_HitWater (self, self->Sector, self->x, self->y, self->floorz, false, false); + } +} + //--------------------------------------------------------------------------- // // FUNC P_CheckMissileSpawn diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index cf9e56e8e..481b6e04c 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -609,10 +609,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode) } P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource, true, fulldmgdistance); - if (self->z <= self->floorz + (distance<target != NULL && self->target->player != NULL) { validcount++; @@ -637,10 +634,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusThrust) if (distance <= 0) distance = force; P_RadiusAttack (self, self->target, force, distance, self->DamageType, affectSource, false); - if (self->z <= self->floorz + (distance< Date: Sat, 17 Oct 2009 15:12:18 +0000 Subject: [PATCH 038/241] - Fixed: 3DMidtex checks were treating the Null texture as a valid texture. SVN r1927 (trunk) --- docs/rh-log.txt | 6 +++--- src/p_3dmidtex.cpp | 1 + src/p_effect.cpp | 16 +--------------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4c19865e9..ad60418f0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,7 +1,7 @@ October 17, 2009 (Changes by Graf Zahl) -- Fixed: The rail sound used the shooter's position for calculating the sound origin - but should use the camera position instead to get the correct position for - the closest point along the trail. +- Fixed: 3DMidtex checks were treating the Null texture as a valid texture. +- Fixed: The rail sound's position was not clamped to the actual range between + the trail's start and end point. - Fixed: Explosions no longer caused splashes. - Fixed: Copying translations to lower decals had the shade color check wrong. - Fixed: Waggling floors did not moved attached geometry. diff --git a/src/p_3dmidtex.cpp b/src/p_3dmidtex.cpp index 94df21d8c..39186ae9f 100644 --- a/src/p_3dmidtex.cpp +++ b/src/p_3dmidtex.cpp @@ -219,6 +219,7 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, fixed_t *ptextop, f side_t *side = line->sidedef[sideno]; FTextureID texnum = side->GetTexture(side_t::mid); + if (!texnum.isValid()) return false; FTexture * tex= TexMan(texnum); if (!tex) return false; diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 79de562c1..8a4d5bb1f 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -476,7 +476,7 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end // Only consider sound in 2D (for now, anyway) // [BB] You have to devide by lengthsquared here, not multiply with it. - r = ((start.Y - FIXED2FLOAT(viewy)) * (-dir.Y) - (start.X - FIXED2FLOAT(viewx)) * (dir.X)) / lengthsquared; + r = ((start.Y - FIXED2FLOAT(mo->y)) * (-dir.Y) - (start.X - FIXED2FLOAT(mo->x)) * (dir.X)) / lengthsquared; r = clamp(r, 0., 1.); dirz = dir.Z; @@ -484,20 +484,6 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end point = start + r * dir; dir.Z = dirz; -#if 0 - Printf("Start = (%1.4f,%1.4f), End = (%1.4f,%1.4f), Dir =(%1.4f,%1.4f), View = (%1.4f,%1.4f), Point = (%1.4f,%1.4f), r=%1.4f\n", - start.X, start.Y, end.X, end.Y, dir.X, dir.Y, FIXED2FLOAT(viewx), FIXED2FLOAT(viewy), - point.X, point.Y, r); - - FVector3 _start = start; - FVector3 _end = end; - FVector3 view(FIXED2FLOAT(viewx), FIXED2FLOAT(viewy), 0); - point.Z = _start.Z = _end.Z = 0; - - Printf("S: %1.4f, E: %1.4f, H: %1.4f P: %1.4f\n", - (_start-view).Length(), (_end-view).Length(), (((_start+_end)/2)-view).Length(), (point-view).Length()); -#endif - S_Sound (FLOAT2FIXED(point.X), FLOAT2FIXED(point.Y), viewz, CHAN_WEAPON, sound, 1, ATTN_NORM); } From 8390184839fa61df1651bbf50ff406ea07037606 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 Oct 2009 14:08:32 +0000 Subject: [PATCH 039/241] - fixed: FMultiPatchTexture::MakeTexture was missing a range check for the special colormap index. SVN r1928 (trunk) --- docs/rh-log.txt | 4 ++++ src/textures/multipatchtexture.cpp | 2 +- src/textures/texture.cpp | 1 + src/textures/texturemanager.cpp | 7 ++++++- src/textures/textures.h | 8 ++++++++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ad60418f0..44f80a49c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +October 18, 2009 (Changes by Graf Zahl) +- fixed: FMultiPatchTexture::MakeTexture was missing a range check for the + special colormap index. + October 17, 2009 (Changes by Graf Zahl) - Fixed: 3DMidtex checks were treating the Null texture as a valid texture. - Fixed: The rail sound's position was not clamped to the actual range between diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 984135e97..34956dff7 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -429,7 +429,7 @@ BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork) return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap; default: - if (blend >= BLEND_SPECIALCOLORMAP1) + if (blend >= BLEND_SPECIALCOLORMAP1 && blend < BLEND_SPECIALCOLORMAP1 + SpecialColormaps.Size()) { return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap; } diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index df680a507..690a59421 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -146,6 +146,7 @@ FTexture::FTexture (const char *name, int lumpnum) bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL) { + id.SetInvalid(); if (name != NULL) { uppercopy(Name, name); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 7a66a7202..2d3e2fc9f 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -320,7 +320,7 @@ FTextureID FTextureManager::AddTexture (FTexture *texture) int trans = Textures.Push (hasher); Translation.Push (trans); if (bucket >= 0) HashFirst[bucket] = trans; - return FTextureID(trans); + return (texture->id = FTextureID(trans)); } //========================================================================== @@ -365,10 +365,15 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b newtexture->UseType = oldtexture->UseType; Textures[index].Texture = newtexture; + newtexture->id = oldtexture->id; if (free) { delete oldtexture; } + else + { + oldtexture->id.SetInvalid(); + } } //========================================================================== diff --git a/src/textures/textures.h b/src/textures/textures.h index 06d373f1f..0f595b5cb 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -100,6 +100,7 @@ public: fixed_t yScale; int SourceLump; + FTextureID id; union { @@ -156,6 +157,7 @@ public: virtual bool UseBasePalette(); virtual int GetSourceLump() { return SourceLump; } virtual FTexture *GetRedirect(bool wantwarped); + FTextureID GetID() const { return id; } virtual void Unload () = 0; @@ -278,6 +280,12 @@ public: return Textures[Translation[texnum.texnum]].Texture; } + FTexture *ByIndexTranslated(int i) + { + if (unsigned(i) >= Textures.Size()) return NULL; + return Textures[Translation[i]].Texture; + } + void SetTranslation (FTextureID fromtexnum, FTextureID totexnum) { if ((size_t)fromtexnum.texnum < Translation.Size()) From 788f17323cca15f3ce22ab48dbc57e4b10d80977 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 19 Oct 2009 17:17:06 +0000 Subject: [PATCH 040/241] - fixed: Setting the first state's duration of a fast projectile to 0 caused an underflow and blocked all further state changes. SVN r1929 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_shared/a_fastprojectile.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 44f80a49c..39c76062e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +October 19, 2009 (Changes by Graf Zahl) +- fixed: Setting the first state's duration of a fast projectile to 0 caused + an underflow and blocked all further state changes. + October 18, 2009 (Changes by Graf Zahl) - fixed: FMultiPatchTexture::MakeTexture was missing a range check for the special colormap index. diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index d3924a17e..fe97e6a53 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -99,7 +99,7 @@ void AFastProjectile::Tick () // Advance the state if (tics != -1) { - tics--; + if (tics > 0) tics--; while (!tics) { if (!SetState (state->GetNextState ())) From 1c9b6930874a4e14ab4314bf4787120a57e86d01 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 24 Oct 2009 04:39:36 +0000 Subject: [PATCH 041/241] - Fixed drawing of wide high resolution skies. (At least for the samples I received. I'm not convinced that it's yet fixed for the general case.) SVN r1930 (trunk) --- docs/rh-log.txt | 4 ++++ src/r_anim.cpp | 4 ++-- src/r_plane.cpp | 17 ++++++++++------- src/r_sky.cpp | 10 ++++------ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 39c76062e..ed25d858d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +October 23, 2009 +- Fixed drawing of wide high resolution skies. (At least for the samples I + received. I'm not convinced that it's yet fixed for the general case.) + October 19, 2009 (Changes by Graf Zahl) - fixed: Setting the first state's duration of a fast projectile to 0 caused an underflow and blocked all further state changes. diff --git a/src/r_anim.cpp b/src/r_anim.cpp index 22c85c50d..43e3b50a3 100644 --- a/src/r_anim.cpp +++ b/src/r_anim.cpp @@ -834,6 +834,6 @@ void R_UpdateAnimations (DWORD mstime) // Scroll the sky double ms = (double)mstime * FRACUNIT; - sky1pos = fixed_t(fmod (ms * level.skyspeed1, double(TexMan[sky1texture]->GetWidth() << FRACBITS))); - sky2pos = fixed_t(fmod (ms * level.skyspeed2, double(TexMan[sky2texture]->GetWidth() << FRACBITS))); + sky1pos = fixed_t(fmod (ms * level.skyspeed1, double(TexMan[sky1texture]->GetScaledWidth() << FRACBITS))); + sky2pos = fixed_t(fmod (ms * level.skyspeed2, double(TexMan[sky2texture]->GetScaledWidth() << FRACBITS))); } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 69af40223..d177241c6 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -764,17 +764,16 @@ static int skycolplace; // Get a column of sky when there is only one sky texture. static const BYTE *R_GetOneSkyColumn (FTexture *fronttex, int x) { - angle_t column = MulScale16 (frontxScale, viewangle + xtoviewangle[x]); - - return fronttex->GetColumn ((((column^skyflip) >> sky1shift) + frontpos) >> FRACBITS, NULL); + angle_t column = (viewangle + xtoviewangle[x]) ^ skyflip; + return fronttex->GetColumn (MulScale32((column >> sky1shift) + frontpos, frontxScale), NULL); } // Get a column of sky when there are two overlapping sky textures static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x) { - DWORD ang = (viewangle + xtoviewangle[x])^skyflip; - DWORD angle1 = (((DWORD)MulScale16 (frontxScale, ang) >> sky1shift) + frontpos) >> FRACBITS; - DWORD angle2 = (((DWORD)MulScale16 (backxScale, ang) >> sky2shift) + backpos) >> FRACBITS; + DWORD ang = (viewangle + xtoviewangle[x]) ^ skyflip; + DWORD angle1 = (DWORD)MulScale32((ang >> sky1shift) + frontpos, frontxScale); + DWORD angle2 = (DWORD)MulScale32((ang >> sky2shift) + backpos, backxScale); // Check if this column has already been built. If so, there's // no reason to waste time building it again. @@ -825,7 +824,6 @@ static void R_DrawSky (visplane_t *pl) dc_iscale = skyiscale >> skystretch; clearbuf (swall+pl->minx, pl->maxx-pl->minx+1, dc_iscale<<2); - rw_offset = frontpos; if (MirrorFlags & RF_XFLIP) { @@ -1328,6 +1326,11 @@ void R_DrawSkyPlane (visplane_t *pl) skyflip = l->args[2] ? 0u : ~0u; } } +// frontpos = FixedMul(frontpos, frontskytex->xScale/2); + if (backskytex != NULL) + { + backpos = FixedMul(backpos, backskytex->xScale); + } bool fakefixed = false; if (fixedcolormap) diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 76e4d9d62..0ef9b259f 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -115,11 +115,9 @@ void R_InitSkyMap () } // The (standard Doom) sky map is 256*128*4 maps. - sky1shift = 22+skystretch-16; - sky2shift = 22+skystretch-16; - if (skytex1->WidthBits >= 9) - sky1shift -= skystretch; - if (skytex2->WidthBits >= 9) - sky2shift -= skystretch; + int swidth = skytex1->GetScaledWidth(); + sky1shift = 22 - 16 + (skystretch && swidth < 512) - (swidth >= 1024 && skytex1->xScale >= 4*FRACUNIT); + swidth = skytex2->GetScaledWidth(); + sky2shift = 22 - 16 + (skystretch && swidth < 512) - (swidth >= 1024 && skytex2->xScale >= 4*FRACUNIT); } From 1a6d7b6ecaef994e6b1a5e0cce3c9abdbbf99742 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 24 Oct 2009 05:02:49 +0000 Subject: [PATCH 042/241] - Fixed: When giving completely new ammo, the backpack did not clamp the amount given to the ammo's max amount. SVN r1931 (trunk) --- docs/rh-log.txt | 2 ++ src/g_shared/a_pickups.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ed25d858d..93e4428c8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ October 23, 2009 +- Fixed: When giving completely new ammo, the backpack did not clamp the + amount given to the ammo's max amount. - Fixed drawing of wide high resolution skies. (At least for the samples I received. I'm not convinced that it's yet fixed for the general case.) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index e9d9e2003..eb0037793 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1569,7 +1569,7 @@ void ABackpackItem::Serialize (FArchive &arc) AInventory *ABackpackItem::CreateCopy (AActor *other) { // Find every unique type of ammo. Give it to the player if - // he doesn't have it already, and double it's maximum capacity. + // he doesn't have it already, and double its maximum capacity. for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { const PClass *type = PClass::m_Types[i]; @@ -1588,7 +1588,14 @@ AInventory *ABackpackItem::CreateCopy (AActor *other) { // The player did not have the ammo. Add it. ammo = static_cast(Spawn (type, 0, 0, 0, NO_REPLACE)); ammo->Amount = bDepleted ? 0 : amount; - if (ammo->BackpackMaxAmount > ammo->MaxAmount) ammo->MaxAmount = ammo->BackpackMaxAmount; + if (ammo->BackpackMaxAmount > ammo->MaxAmount) + { + ammo->MaxAmount = ammo->BackpackMaxAmount; + } + if (ammo->Amount > ammo->MaxAmount) + { + ammo->Amount = ammo->MaxAmount; + } ammo->AttachToOwner (other); } else From f40462dfb49988c20b5197514d596e84891fa47d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 24 Oct 2009 23:42:58 +0000 Subject: [PATCH 043/241] - Rewrote wide sky texture scaling again. This time, it should work for any size textures at any scale. I also tried doing sky scrolling on the sky cylinder, but that didn't look so good, so I left it in screen space. SVN r1932 (trunk) --- docs/rh-log.txt | 5 +++++ src/r_anim.cpp | 4 ++-- src/r_plane.cpp | 36 ++++++++++++++++++++---------------- src/r_sky.cpp | 31 +++++++++++++++++++++++-------- src/r_sky.h | 4 ++-- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 93e4428c8..e719c3193 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +October 24, 2009 +- Rewrote wide sky texture scaling again. This time, it should work for any + size textures at any scale. I also tried doing sky scrolling on the sky + cylinder, but that didn't look so good, so I left it in screen space. + October 23, 2009 - Fixed: When giving completely new ammo, the backpack did not clamp the amount given to the ammo's max amount. diff --git a/src/r_anim.cpp b/src/r_anim.cpp index 43e3b50a3..c4ed59850 100644 --- a/src/r_anim.cpp +++ b/src/r_anim.cpp @@ -834,6 +834,6 @@ void R_UpdateAnimations (DWORD mstime) // Scroll the sky double ms = (double)mstime * FRACUNIT; - sky1pos = fixed_t(fmod (ms * level.skyspeed1, double(TexMan[sky1texture]->GetScaledWidth() << FRACBITS))); - sky2pos = fixed_t(fmod (ms * level.skyspeed2, double(TexMan[sky2texture]->GetScaledWidth() << FRACBITS))); + sky1pos = ms * level.skyspeed1; + sky2pos = ms * level.skyspeed2; } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index d177241c6..7b263a35c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -745,8 +745,8 @@ inline void R_MakeSpans (int x, int t1, int b1, int t2, int b2, void (*mapfunc)( static FTexture *frontskytex, *backskytex; static angle_t skyflip; static int frontpos, backpos; -static fixed_t frontxScale, backxScale; static fixed_t frontyScale; +static fixed_t frontcyl, backcyl; int frontiScale; extern fixed_t swall[MAXWIDTH]; @@ -765,15 +765,15 @@ static int skycolplace; static const BYTE *R_GetOneSkyColumn (FTexture *fronttex, int x) { angle_t column = (viewangle + xtoviewangle[x]) ^ skyflip; - return fronttex->GetColumn (MulScale32((column >> sky1shift) + frontpos, frontxScale), NULL); + return fronttex->GetColumn((MulScale16(column, frontcyl) + frontpos) >> FRACBITS, NULL); } // Get a column of sky when there are two overlapping sky textures static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x) { DWORD ang = (viewangle + xtoviewangle[x]) ^ skyflip; - DWORD angle1 = (DWORD)MulScale32((ang >> sky1shift) + frontpos, frontxScale); - DWORD angle2 = (DWORD)MulScale32((ang >> sky2shift) + backpos, backxScale); + DWORD angle1 = (DWORD)((MulScale16(ang, frontcyl) + frontpos) >> FRACBITS); + DWORD angle2 = (DWORD)((MulScale16(ang, backcyl) + backpos) >> FRACBITS); // Check if this column has already been built. If so, there's // no reason to waste time building it again. @@ -848,12 +848,6 @@ static void R_DrawSky (visplane_t *pl) rw_pic = frontskytex; rw_offset = 0; - frontxScale = rw_pic->xScale; - if (backskytex != NULL) - { - backxScale = backskytex->xScale; - } - frontyScale = rw_pic->yScale; dc_texturemid = MulScale16 (skytexturemid/*-viewz*/, frontyScale); @@ -1250,6 +1244,7 @@ ADD_STAT(skyboxes) void R_DrawSkyPlane (visplane_t *pl) { FTextureID sky1tex, sky2tex; + double frontdpos, backdpos; if ((level.flags & LEVEL_SWAPSKIES) && !(level.flags & LEVEL_DOUBLESKY)) { @@ -1272,15 +1267,18 @@ void R_DrawSkyPlane (visplane_t *pl) else backskytex = NULL; skyflip = 0; - frontpos = sky1pos; - backpos = sky2pos; + frontdpos = sky1pos; + backdpos = sky2pos; + frontcyl = sky1cyl; + backcyl = sky2cyl; } else if (pl->sky == PL_SKYFLAT) { // use sky2 frontskytex = TexMan(sky2tex); backskytex = NULL; + frontcyl = sky2cyl; skyflip = 0; - frontpos = sky2pos; + frontdpos = sky2pos; } else { // MBF's linedef-controlled skies @@ -1313,7 +1311,7 @@ void R_DrawSkyPlane (visplane_t *pl) // to allow sky rotation as well as careful positioning. // However, the offset is scaled very small, so that it // allows a long-period of sky rotation. - frontpos = (-s->GetTextureXOffset(pos)) >> 6; + frontdpos = (-s->GetTextureXOffset(pos)) >> 6; // Vertical offset allows careful sky positioning. dc_texturemid = s->GetTextureYOffset(pos) - 28*FRACUNIT; @@ -1324,12 +1322,18 @@ void R_DrawSkyPlane (visplane_t *pl) // to make it easier to use the new feature, while to still // allow old sky textures to be used. skyflip = l->args[2] ? 0u : ~0u; + + frontcyl = MAX(frontskytex->GetWidth(), frontskytex->xScale >> (16 - 10)); + if (skystretch && frontskytex->GetScaledWidth() < 512) + { + frontcyl >>= 1; + } } } -// frontpos = FixedMul(frontpos, frontskytex->xScale/2); + frontpos = int(fmod(frontdpos, double(sky1cyl * 65536.0))); if (backskytex != NULL) { - backpos = FixedMul(backpos, backskytex->xScale); + backpos = int(fmod(backdpos, double(sky2cyl * 65536.0))); } bool fakefixed = false; diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 0ef9b259f..904e80291 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -47,9 +47,8 @@ int skystretch; fixed_t skyheight; fixed_t skyiscale; -int sky1shift, sky2shift; -fixed_t sky1pos=0, sky1speed=0; -fixed_t sky2pos=0, sky2speed=0; +fixed_t sky1cyl, sky2cyl; +double sky1pos, sky2pos; // [RH] Stretch sky texture if not taller than 128 pixels? CUSTOM_CVAR (Bool, r_stretchsky, true, CVAR_ARCHIVE) @@ -114,10 +113,26 @@ void R_InitSkyMap () skyscale = Scale (skyscale, 2048, FieldOfView); } - // The (standard Doom) sky map is 256*128*4 maps. - int swidth = skytex1->GetScaledWidth(); - sky1shift = 22 - 16 + (skystretch && swidth < 512) - (swidth >= 1024 && skytex1->xScale >= 4*FRACUNIT); - swidth = skytex2->GetScaledWidth(); - sky2shift = 22 - 16 + (skystretch && swidth < 512) - (swidth >= 1024 && skytex2->xScale >= 4*FRACUNIT); + // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, + // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, + // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of + // the texture as the cylinder's circumfrence. + sky1cyl = MAX(skytex1->GetWidth(), skytex1->xScale >> (16 - 10)); + sky2cyl = MAX(skytex2->GetWidth(), skytex2->xScale >> (16 - 10)); + + // If we are stretching short skies, we also stretch them horizontally by halving the + // circumfrence of the sky cylinder, unless the texture is 512 or more pixels wide, + // in which case we only stretch it vertically. + if (skystretch) + { + if (skytex1->GetScaledWidth() < 512) + { + sky1cyl >>= 1; + } + if (skytex2->GetScaledWidth() < 512) + { + sky2cyl >>= 1; + } + } } diff --git a/src/r_sky.h b/src/r_sky.h index b29deb61b..468b9738f 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -24,11 +24,11 @@ #include "textures/textures.h" -extern int sky1shift, sky2shift; extern FTextureID skyflatnum; +extern fixed_t sky1cyl, sky2cyl; extern FTextureID sky1texture, sky2texture; -extern fixed_t sky1pos, sky2pos; +extern double sky1pos, sky2pos; extern fixed_t skytexturemid; extern int skystretch; extern fixed_t skyiscale; From 19b23f2cf31de74f3c1f71ed82322e997ec7ec38 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 25 Oct 2009 02:19:51 +0000 Subject: [PATCH 044/241] - Removed the Actor uservar array and replaced it with user-defined variables. A_SetUserVar/SetUserVariable/GetUserVariable now take a variable name instead of an array index. A_SetUserArray/SetUserArray/GetUserArray have been added to access elements in user-defined arrays. SVN r1933 (trunk) --- docs/rh-log.txt | 4 + src/actor.h | 1 - src/dobject.cpp | 82 ++++++++++++++++++ src/dobject.h | 1 + src/dobjtype.cpp | 17 +++- src/dobjtype.h | 6 +- src/farchive.cpp | 8 +- src/p_acs.cpp | 120 +++++++++++++++++++++++++-- src/p_mobj.cpp | 8 +- src/sc_man.h | 1 + src/sc_man_scanner.re | 1 + src/thingdef/thingdef_codeptr.cpp | 67 +++++++++++++-- src/thingdef/thingdef_expression.cpp | 1 - src/thingdef/thingdef_parse.cpp | 79 ++++++++++++++++-- wadsrc/static/actors/actor.txt | 6 +- 15 files changed, 374 insertions(+), 28 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e719c3193..3764a67d4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ October 24, 2009 +- Removed the Actor uservar array and replaced it with user-defined variables. + A_SetUserVar/SetUserVariable/GetUserVariable now take a variable name + instead of an array index. A_SetUserArray/SetUserArray/GetUserArray + have been added to access elements in user-defined arrays. - Rewrote wide sky texture scaling again. This time, it should work for any size textures at any scale. I also tried doing sky scrolling on the sky cylinder, but that didn't look so good, so I left it in screen space. diff --git a/src/actor.h b/src/actor.h index 2c3b80108..730b9006f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -789,7 +789,6 @@ public: int tid; // thing identifier int special; // special int args[5]; // special arguments - int uservar[10]; // user variables, accessible by DECORATE and ACS AActor *inext, **iprev;// Links to other mobjs in same bucket TObjPtr goal; // Monster's goal if not chasing anything diff --git a/src/dobject.cpp b/src/dobject.cpp index d71f87ed7..0ccdd130b 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -506,6 +506,88 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) return changed; } +void DObject::SerializeUserVars(FArchive &arc) +{ + PSymbolTable *symt; + FName varname; + DWORD count, j; + int *varloc; + + if (SaveVersion < 1933) + { + return; + } + + symt = &GetClass()->Symbols; + + if (arc.IsStoring()) + { + // Write all user variables. + for (; symt != NULL; symt = symt->ParentSymbolTable) + { + for (unsigned i = 0; i < symt->Symbols.Size(); ++i) + { + PSymbol *sym = symt->Symbols[i]; + if (sym->SymbolType == SYM_Variable) + { + PSymbolVariable *var = static_cast(sym); + if (var->bUserVar) + { + count = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1; + varloc = (int *)(reinterpret_cast(this) + var->offset); + + arc << var->SymbolName; + arc.WriteCount(count); + for (j = 0; j < count; ++j) + { + arc << varloc[j]; + } + } + } + } + } + // Write terminator. + varname = NAME_None; + arc << varname; + } + else + { + // Read user variables until 'None' is encountered. + arc << varname; + while (varname != NAME_None) + { + PSymbol *sym = symt->FindSymbol(varname, true); + DWORD wanted = 0; + + if (sym != NULL && sym->SymbolType == SYM_Variable) + { + PSymbolVariable *var = static_cast(sym); + + if (var->bUserVar) + { + wanted = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1; + varloc = (int *)(reinterpret_cast(this) + var->offset); + } + } + count = arc.ReadCount(); + for (j = 0; j < MIN(wanted, count); ++j) + { + arc << varloc[j]; + } + if (wanted < count) + { + // Ignore remaining values from archive. + for (; j < count; ++j) + { + int foo; + arc << foo; + } + } + arc << varname; + } + } +} + void DObject::Serialize (FArchive &arc) { ObjectFlags |= OF_SerialSuccess; diff --git a/src/dobject.h b/src/dobject.h index 39ccbc576..a2354aa80 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -456,6 +456,7 @@ public: inline bool IsKindOf (const PClass *base) const; inline bool IsA (const PClass *type) const; + void SerializeUserVars(FArchive &arc); virtual void Serialize (FArchive &arc); // For catching Serialize functions in derived classes diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 03eecc7a9..2243023d0 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -118,7 +118,7 @@ void PClass::StaticFreeData (PClass *type) { if (type->Defaults != NULL) { - delete[] type->Defaults; + M_Free(type->Defaults); type->Defaults = NULL; } type->FreeStateList (); @@ -281,7 +281,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size) type->Meta = Meta; // Set up default instance of the new class. - type->Defaults = new BYTE[size]; + type->Defaults = (BYTE *)M_Malloc(size); memcpy (type->Defaults, Defaults, Size); if (size > Size) { @@ -315,6 +315,19 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size) return type; } +// Add bytes to the end of this class. Returns the +// previous size of the class. +unsigned int PClass::Extend(unsigned int extension) +{ + assert(this->bRuntimeClass); + + unsigned int oldsize = Size; + Size += extension; + Defaults = (BYTE *)M_Realloc(Defaults, Size); + memset(Defaults + oldsize, 0, extension); + return oldsize; +} + // Like FindClass but creates a placeholder if no class // is found. CreateDerivedClass will automatcally fill in // the placeholder when the actual class is defined. diff --git a/src/dobjtype.h b/src/dobjtype.h index 88defaefe..dd35e7e47 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -46,8 +46,9 @@ struct PSymbolConst : public PSymbol struct PSymbolVariable : public PSymbol { FExpressionType ValueType; - int size; + //int size; intptr_t offset; + bool bUserVar; PSymbolVariable(FName name) : PSymbol(name, SYM_Variable) {} }; @@ -113,6 +114,8 @@ public: private: PSymbolTable *ParentSymbolTable; TArray Symbols; + + friend class DObject; }; // Meta-info for every class derived from DObject --------------------------- @@ -143,6 +146,7 @@ struct PClass void InsertIntoHash (); DObject *CreateNew () const; PClass *CreateDerivedClass (FName name, unsigned int size); + unsigned int Extend(unsigned int extension); void InitializeActorInfo (); void BuildFlatPointers (); void FreeStateList(); diff --git a/src/farchive.cpp b/src/farchive.cpp index f8992b81c..9497bc50e 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -3,7 +3,7 @@ ** Implements an archiver for DObject serialization. ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2009 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -1074,6 +1074,7 @@ FArchive &FArchive::WriteObject (DObject *obj) WriteClass (type); // Printf ("Make class %s (%u)\n", type->Name, m_File->Tell()); MapObject (obj); + obj->SerializeUserVars (*this); obj->Serialize (*this); obj->CheckIfSerialized (); } @@ -1105,6 +1106,7 @@ FArchive &FArchive::WriteObject (DObject *obj) WriteCount (m_TypeMap[type->ClassIndex].toArchive); // Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell()); MapObject (obj); + obj->SerializeUserVars (*this); obj->Serialize (*this); obj->CheckIfSerialized (); } @@ -1160,6 +1162,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype) // stored in the archive. AActor *tempobj = static_cast(type->CreateNew ()); MapObject (obj != NULL ? obj : tempobj); + tempobj->SerializeUserVars (*this); tempobj->Serialize (*this); tempobj->CheckIfSerialized (); // If this player is not present anymore, keep the new body @@ -1187,6 +1190,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype) // Printf ("New class: %s (%u)\n", type->Name, m_File->Tell()); obj = type->CreateNew (); MapObject (obj); + obj->SerializeUserVars (*this); obj->Serialize (*this); obj->CheckIfSerialized (); break; @@ -1201,6 +1205,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype) AActor *tempobj = static_cast(type->CreateNew ()); MapObject (obj != NULL ? obj : tempobj); + tempobj->SerializeUserVars (*this); tempobj->Serialize (*this); tempobj->CheckIfSerialized (); if (obj != NULL) @@ -1225,6 +1230,7 @@ FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype) // Printf ("Use class: %s (%u)\n", type->Name, m_File->Tell()); obj = type->CreateNew (); MapObject (obj); + obj->SerializeUserVars (*this); obj->Serialize (*this); obj->CheckIfSerialized (); break; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index f7a5ef070..a0d2811ad 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2908,6 +2908,8 @@ enum EACSFunctions ACSF_GetUserVariable, ACSF_Radius_Quake2, ACSF_CheckActorClass, + ACSF_SetUserArray, + ACSF_GetUserArray, }; int DLevelScript::SideFromID(int id, int side) @@ -2942,6 +2944,67 @@ int DLevelScript::LineFromID(int id) } } +static void SetUserVariable(AActor *self, FName varname, int index, int value) +{ + PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true); + int max; + PSymbolVariable *var; + + if (sym == NULL || sym->SymbolType != SYM_Variable || + !(var = static_cast(sym))->bUserVar) + { + return; + } + if (var->ValueType.Type == VAL_Int) + { + max = 1; + } + else if (var->ValueType.Type == VAL_Array && var->ValueType.BaseType == VAL_Int) + { + max = var->ValueType.size; + } + else + { + return; + } + // Set the value of the specified user variable. + if (index >= 0 && index < max) + { + ((int *)(reinterpret_cast(self) + var->offset))[index] = value; + } +} + +static int GetUserVariable(AActor *self, FName varname, int index) +{ + PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true); + int max; + PSymbolVariable *var; + + if (sym == NULL || sym->SymbolType != SYM_Variable || + !(var = static_cast(sym))->bUserVar) + { + return 0; + } + if (var->ValueType.Type == VAL_Int) + { + max = 1; + } + else if (var->ValueType.Type == VAL_Array && var->ValueType.BaseType == VAL_Int) + { + max = var->ValueType.size; + } + else + { + return 0; + } + // Get the value of the specified user variable. + if (index >= 0 && index < max) + { + return ((int *)(reinterpret_cast(self) + var->offset))[index]; + } + return 0; +} + int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) { AActor *actor; @@ -3109,23 +3172,24 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_SetUserVariable: { int cnt = 0; - if (args[1] >= 0 && args[1] < 10) + FName varname(FBehavior::StaticLookupString(args[1]), true); + if (varname != NAME_None) { if (args[0] == 0) { if (activator != NULL) { - activator->uservar[args[1]] = args[2]; + SetUserVariable(activator, varname, 0, args[2]); } cnt++; } else { - TActorIterator iterator (args[0]); + TActorIterator iterator(args[0]); - while ( (actor = iterator.Next ()) ) + while ( (actor = iterator.Next()) ) { - actor->uservar[args[1]] = args[2]; + SetUserVariable(actor, varname, 0, args[2]); cnt++; } } @@ -3135,12 +3199,52 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetUserVariable: { - if (args[1] >= 0 && args[1] < 10) + FName varname(FBehavior::StaticLookupString(args[1]), true); + if (varname != NAME_None) { AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL); - return a != NULL? a->uservar[args[1]] : 0; + return a != NULL ? GetUserVariable(a, varname, 0) : 0; } - else return 0; + return 0; + } + + case ACSF_SetUserArray: + { + int cnt = 0; + FName varname(FBehavior::StaticLookupString(args[1]), true); + if (varname != NAME_None) + { + if (args[0] == 0) + { + if (activator != NULL) + { + SetUserVariable(activator, varname, args[2], args[3]); + } + cnt++; + } + else + { + TActorIterator iterator(args[0]); + + while ( (actor = iterator.Next()) ) + { + SetUserVariable(actor, varname, args[2], args[3]); + cnt++; + } + } + } + return cnt; + } + + case ACSF_GetUserArray: + { + FName varname(FBehavior::StaticLookupString(args[1]), true); + if (varname != NAME_None) + { + AActor *a = args[0] == 0 ? (AActor *)activator : SingleActorFromTID(args[0], NULL); + return a != NULL ? GetUserVariable(a, varname, args[2]) : 0; + } + return 0; } case ACSF_Radius_Quake2: diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5a00bcc1f..f03bdbd46 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -314,7 +314,13 @@ void AActor::Serialize (FArchive &arc) arc << DamageFactor; } - for(int i=0; i<10; i++) arc << uservar[i]; + // Skip past uservar array in old savegames + if (SaveVersion < 1933) + { + int foo; + for (int i = 0; i < 10; ++i) + arc << foo; + } if (arc.IsStoring ()) { diff --git a/src/sc_man.h b/src/sc_man.h index cffc07e5d..1e5dc289d 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -175,6 +175,7 @@ enum TK_Exec, TK_DefaultProperties, TK_Native, + TK_Var, TK_Out, TK_Ref, TK_Event, diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 904e9b7d5..ff0945db3 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -109,6 +109,7 @@ std2: 'exec' { RET(TK_Exec); } 'defaultproperties' { RET(TK_DefaultProperties); } 'native' { RET(TK_Native); } + 'var' { RET(TK_Var); } 'out' { RET(TK_Out); } 'ref' { RET(TK_Ref); } 'event' { RET(TK_Event); } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 481b6e04c..c5410ef6c 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1742,6 +1742,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) Printf("%s\n", text); } +//=========================================================================== +// +// A_LogInt +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LogInt) +{ + ACTION_PARAM_START(1); + ACTION_PARAM_INT(num, 0); + Printf("%d\n", num); +} + //=========================================================================== // // A_SetTranslucent @@ -2900,21 +2913,63 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecial) //=========================================================================== // -// A_SetVar +// A_SetUserVar // //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar) { ACTION_PARAM_START(2); - ACTION_PARAM_INT(pos, 0); + ACTION_PARAM_NAME(varname, 0); ACTION_PARAM_INT(value, 1); - if (pos < 0 || pos > 9) + PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true); + PSymbolVariable *var; + + if (sym == NULL || sym->SymbolType != SYM_Variable || + !(var = static_cast(sym))->bUserVar || + var->ValueType.Type != VAL_Int) + { + Printf("%s is not a user variable in class %s\n", varname.GetChars(), + self->GetClass()->TypeName.GetChars()); return; - - // Set the value of the specified arg - self->uservar[pos] = value; + } + // Set the value of the specified user variable. + *(int *)(reinterpret_cast(self) + var->offset) = value; +} + +//=========================================================================== +// +// A_SetUserArray +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray) +{ + ACTION_PARAM_START(3); + ACTION_PARAM_NAME(varname, 0); + ACTION_PARAM_INT(pos, 1); + ACTION_PARAM_INT(value, 2); + + PSymbol *sym = self->GetClass()->Symbols.FindSymbol(varname, true); + PSymbolVariable *var; + + if (sym == NULL || sym->SymbolType != SYM_Variable || + !(var = static_cast(sym))->bUserVar || + var->ValueType.Type != VAL_Array || var->ValueType.BaseType != VAL_Int) + { + Printf("%s is not a user array in class %s\n", varname.GetChars(), + self->GetClass()->TypeName.GetChars()); + return; + } + if (pos < 0 || pos >= var->ValueType.size) + { + Printf("%d is out of bounds in array %s in class %s\n", pos, varname.GetChars(), + self->GetClass()->TypeName.GetChars()); + return; + } + // Set the value of the specified user array at index pos. + ((int *)(reinterpret_cast(self) + var->offset))[pos] = value; } //=========================================================================== diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index d68ecfcd6..eee2b3608 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -78,7 +78,6 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor) DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor) DEFINE_MEMBER_VARIABLE(Damage, AActor) DEFINE_MEMBER_VARIABLE(Score, AActor) -DEFINE_MEMBER_VARIABLE(uservar, AActor) //========================================================================== // diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index ddc0c8eb9..cc9b3284c 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -248,13 +248,13 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls) //========================================================================== // -// ActorConstDef +// ParseNativeVariable // -// Parses a constant definition. +// Parses a native variable declaration. // //========================================================================== -static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) +static void ParseNativeVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) { FExpressionType valuetype; @@ -319,6 +319,7 @@ static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) PSymbolVariable *sym = new PSymbolVariable(symname); sym->offset = vi->address; // todo sym->ValueType = valuetype; + sym->bUserVar = false; if (symt->AddSymbol (sym) == NULL) { @@ -328,6 +329,70 @@ static void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) } } +//========================================================================== +// +// ParseUserVariable +// +// Parses a user variable declaration. +// +//========================================================================== + +static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) +{ + FExpressionType valuetype; + + // Only non-native classes may have user variables. + if (!cls->bRuntimeClass) + { + sc.ScriptError("Native classes may not have user variables"); + } + + // Read the type and make sure it's int. + sc.MustGetAnyToken(); + if (sc.TokenType == TK_Int) + { + valuetype = VAL_Int; + } + else + { + sc.ScriptError("User variables must be of type int"); + } + + sc.MustGetToken(TK_Identifier); + // For now, restrict user variables to those that begin with "user_" to guarantee + // no clashes with internal member variable names. + if (sc.StringLen < 6 || strnicmp("user_", sc.String, 5) != 0) + { + sc.ScriptError("User variable names must begin with \"user_\""); + } + + FName symname = sc.String; + if (sc.CheckToken('[')) + { + FxExpression *expr = ParseExpression(sc, cls); + int maxelems = expr->EvalExpression(NULL).GetInt(); + delete expr; + sc.MustGetToken(']'); + if (maxelems <= 0) + { + sc.ScriptError("Array size must be positive"); + } + valuetype.MakeArray(maxelems); + } + sc.MustGetToken(';'); + + PSymbolVariable *sym = new PSymbolVariable(symname); + sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1)); + sym->ValueType = valuetype; + sym->bUserVar = true; + if (symt->AddSymbol(sym) == NULL) + { + delete sym; + sc.ScriptError ("'%s' is already defined in '%s'.", + symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); + } +} + //========================================================================== // // Parses a flag name @@ -1064,7 +1129,11 @@ static void ParseActor(FScanner &sc) break; case TK_Native: - ParseVariable (sc, &info->Class->Symbols, info->Class); + ParseNativeVariable (sc, &info->Class->Symbols, info->Class); + break; + + case TK_Var: + ParseUserVariable (sc, &info->Class->Symbols, info->Class); break; case TK_Identifier: @@ -1125,7 +1194,7 @@ void ParseDecorate (FScanner &sc) break; case TK_Native: - ParseVariable(sc, &GlobalSymbols, NULL); + ParseNativeVariable(sc, &GlobalSymbols, NULL); break; case ';': diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index fbbab0a40..51513e10c 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -27,7 +27,6 @@ ACTOR Actor native //: Thinker native fixed_t alpha; native angle_t angle; native int args[5]; - native int uservar[10]; native fixed_t ceilingz; native fixed_t floorz; native int health; @@ -47,6 +46,7 @@ ACTOR Actor native //: Thinker native fixed_t momy; // alias for vely native fixed_t momz; // alias for velz native int score; + // Meh, MBF redundant functions. Only for DeHackEd support. action native A_Turn(float angle = 0); action native A_LineEffect(int boomspecial = 0, int tag = 0); @@ -195,6 +195,7 @@ ACTOR Actor native //: Thinker action native A_Print(string whattoprint, float time = 0, string fontname = ""); action native A_PrintBold(string whattoprint, float time = 0, string fontname = ""); action native A_Log(string whattoprint); + action native A_LogInt(int whattoprint); action native A_SetTranslucent(float alpha, int style = 0); action native A_FadeIn(float reduce = 0.1); action native A_FadeOut(float reduce = 0.1, bool remove = true); @@ -261,7 +262,8 @@ ACTOR Actor native //: Thinker action native A_ScaleVelocity(float scale); action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); action native A_SetArg(int pos, int value); - action native A_SetUserVar(int pos, int value); + action native A_SetUserVar(name varname, int value); + action native A_SetUserArray(name varname, int index, int value); action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0); action native A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); From cc2b0b0dcf3939df104b9604705e3051522ddfe6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 25 Oct 2009 15:26:19 +0000 Subject: [PATCH 045/241] - made max. view pitch a property of the renderer so that it's overridable without changing game code. - made SpawningMapThing an argument of AActor::StaticSpawn instead of a global variable. - added a stub to the DECORATE parser for defining dynamic lights directly in DECORATE. This is needed so that ZDoom remains compatible with any DECORATE which uses this GZDoom feature in the future. SVN r1935 (trunk) --- docs/rh-log.txt | 9 +++++++ src/actor.h | 2 +- src/d_player.h | 3 --- src/g_level.cpp | 18 ++++++++++++++ src/info.h | 2 ++ src/m_options.cpp | 2 +- src/p_3dfloors.cpp | 1 + src/p_mobj.cpp | 10 ++++---- src/p_user.cpp | 6 ++--- src/r_data.h | 1 + src/r_main.cpp | 8 +++---- src/thingdef/thingdef_states.cpp | 15 ++++++++++++ src/v_video.cpp | 41 ++++++++++++++++++++++++++++++++ src/v_video.h | 9 +++++++ 14 files changed, 109 insertions(+), 18 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 3764a67d4..905f27326 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +October 24, 2009 (Changes by Graf Zahl) +- made max. view pitch a property of the renderer so that it's overridable without + changing game code. +- made SpawningMapThing an argument of AActor::StaticSpawn instead of a global + variable. +- added a stub to the DECORATE parser for defining dynamic lights directly + in DECORATE. This is needed so that ZDoom remains compatible with any DECORATE + which uses this GZDoom feature in the future. + October 24, 2009 - Removed the Actor uservar array and replaced it with user-defined variables. A_SetUserVar/SetUserVariable/GetUserVariable now take a variable name diff --git a/src/actor.h b/src/actor.h index 730b9006f..8dbfdf194 100644 --- a/src/actor.h +++ b/src/actor.h @@ -547,7 +547,7 @@ public: void Serialize (FArchive &arc); - static AActor *StaticSpawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement); + static AActor *StaticSpawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement, bool SpawningMapThing = false); inline AActor *GetDefault () const { diff --git a/src/d_player.h b/src/d_player.h index fa936b552..b23d0616d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -414,9 +414,6 @@ void P_CheckPlayerSprites(); #define CROUCHSPEED (FRACUNIT/12) -#define MAX_DN_ANGLE 56 // Max looking down angle -#define MAX_UP_ANGLE 32 // Max looking up angle - // [GRB] Custom player classes enum diff --git a/src/g_level.cpp b/src/g_level.cpp index 948e89b63..a2bd300ed 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -84,6 +84,16 @@ #include "g_hub.h" +#ifndef STAT +#define STAT_NEW(map) +#define STAT_END(newl) +#define STAT_SAVE(arc, hub) +#else +void STAT_NEW(const char *lev); +void STAT_END(const char *newl); +void STAT_SAVE(FArchive &arc, bool hubload); +#endif + EXTERN_CVAR (Float, sv_gravity) EXTERN_CVAR (Float, sv_aircontrol) EXTERN_CVAR (Int, disableautosave) @@ -495,6 +505,8 @@ void G_InitNew (const char *mapname, bool bTitleLevel) // force players to be initialized upon first level load for (i = 0; i < MAXPLAYERS; i++) players[i].playerstate = PST_ENTER; // [BC] + + STAT_NEW(mapname); } usergame = !bTitleLevel; // will be set false if a demo @@ -596,6 +608,8 @@ void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nex FBehavior::StaticStartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true); unloading = false; + STAT_END(nextlevel); + if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) { if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster)) @@ -1389,6 +1403,8 @@ void G_AirControlChanged () void G_SerializeLevel (FArchive &arc, bool hubLoad) { int i = level.totaltime; + + screen->StartSerialize(arc); arc << level.flags << level.flags2 @@ -1507,6 +1523,8 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) } } } + screen->EndSerialize(arc); + STAT_SAVE(arc, hubLoad); } //========================================================================== diff --git a/src/info.h b/src/info.h index 5e06bcc10..da248b9ce 100644 --- a/src/info.h +++ b/src/info.h @@ -59,6 +59,7 @@ struct FState long Misc2; // Was changed to BYTE, reverted to long for MBF compat BYTE Frame; BYTE DefineFlags; // Unused byte so let's use it during state creation. + short Light; FState *NextState; actionf_p ActionFunc; int ParameterIndex; @@ -211,5 +212,6 @@ extern FDoomEdMap DoomEdMap; int GetSpriteIndex(const char * spritename); TArray &MakeStateNameList(const char * fname); +void AddStateLight(FState *state, const char *lname); #endif // __INFO_H__ diff --git a/src/m_options.cpp b/src/m_options.cpp index 8048b52ea..ac297a2f2 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -346,7 +346,7 @@ menu_t JoystickConfigMenu = * *=======================================*/ -static menuitem_t ControlsItems[] = +menuitem_t ControlsItems[] = { { redtext,"ENTER to change, BACKSPACE to clear", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index d1509c649..b9b82a566 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -130,6 +130,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag if (ffloor->top.plane->a || ffloor->top.plane->b || ffloor->bottom.plane->a || ffloor->bottom.plane->b) { ffloor->alpha = FRACUNIT; + ffloor->flags &= ~FF_ADDITIVETRANS; } sec->e->XFloor.ffloors.Push(ffloor); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f03bdbd46..9b9824264 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -85,7 +85,6 @@ EXTERN_CVAR (Int, cl_rockettrails) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static bool SpawningMapThing; static FRandom pr_explodemissile ("ExplodeMissile"); FRandom pr_bounce ("Bounce"); static FRandom pr_reflect ("Reflect"); @@ -560,6 +559,7 @@ bool AActor::SetState (FState *newstate) newstate = newstate->GetNextState(); } while (tics == 0); + screen->StateChanged(this); return true; } @@ -619,6 +619,7 @@ bool AActor::SetStateNF (FState *newstate) newstate = newstate->GetNextState(); } while (tics == 0); + screen->StateChanged(this); return true; } @@ -3459,7 +3460,7 @@ bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash) // //========================================================================== -AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t iz, replace_t allowreplacement) +AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t iz, replace_t allowreplacement, bool SpawningMapThing) { if (type == NULL) { @@ -3623,6 +3624,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t { level.total_items++; } + screen->StateChanged(actor); return actor; } @@ -4339,9 +4341,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) else z = ONFLOORZ; - SpawningMapThing = true; - mobj = Spawn (i, x, y, z, NO_REPLACE); - SpawningMapThing = false; + mobj = AActor::StaticSpawn (i, x, y, z, NO_REPLACE, true); if (z == ONFLOORZ) mobj->z += mthing->z; diff --git a/src/p_user.cpp b/src/p_user.cpp index 7b6e34048..374442a18 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2156,13 +2156,11 @@ void P_PlayerThink (player_t *player) player->mo->pitch -= look; if (look > 0) { // look up - if (player->mo->pitch < -ANGLE_1*MAX_UP_ANGLE) - player->mo->pitch = -ANGLE_1*MAX_UP_ANGLE; + player->mo->pitch = MAX(player->mo->pitch, screen->GetMaxViewPitch(false)); } else { // look down - if (player->mo->pitch > ANGLE_1*MAX_DN_ANGLE) - player->mo->pitch = ANGLE_1*MAX_DN_ANGLE; + player->mo->pitch = MIN(player->mo->pitch, screen->GetMaxViewPitch(true)); } } } diff --git a/src/r_data.h b/src/r_data.h index acd70284d..487860e58 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -93,6 +93,7 @@ public: void Unload (); bool CheckModified (); void RenderView (AActor *viewpoint, int fov); + void NeedUpdate() { bNeedsUpdate=true; } protected: DSimpleCanvas *Canvas; diff --git a/src/r_main.cpp b/src/r_main.cpp index e5caada3d..bcec61c73 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -852,11 +852,11 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi // Avoid overflowing viewpitch (can happen when a netgame is stalled) if (viewpitch + delta <= viewpitch) { - viewpitch = +ANGLE_1*MAX_DN_ANGLE; + viewpitch = screen->GetMaxViewPitch(true); } else { - viewpitch = MIN(viewpitch + delta, +ANGLE_1*MAX_DN_ANGLE); + viewpitch = MIN(viewpitch + delta, screen->GetMaxViewPitch(true)); } } else if (delta < 0) @@ -864,11 +864,11 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi // Avoid overflowing viewpitch (can happen when a netgame is stalled) if (viewpitch + delta >= viewpitch) { - viewpitch = -ANGLE_1*MAX_UP_ANGLE; + viewpitch = screen->GetMaxViewPitch(false); } else { - viewpitch = MAX(viewpitch + delta, -ANGLE_1*MAX_UP_ANGLE); + viewpitch = MAX(viewpitch + delta, screen->GetMaxViewPitch(false)); } } } diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index d7252c419..c04193718 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -55,6 +55,7 @@ #include "i_system.h" #include "colormatcher.h" #include "thingdef_exp.h" +#include "version.h" //========================================================================== //*** @@ -258,6 +259,20 @@ do_stop: sc.MustGetStringName(")"); continue; } + if (sc.Compare("LIGHT")) + { + sc.MustGetStringName("("); + do + { + sc.MustGetString(); + #ifdef DYNLIGHT + AddStateLight(&state, sc.String); + #endif + } + while (sc.CheckString(",")); + sc.MustGetStringName(")"); + continue; + } // Make the action name lowercase to satisfy the gperf hashers strlwr (sc.String); diff --git a/src/v_video.cpp b/src/v_video.cpp index acd481f68..ca8eb7fdc 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1269,7 +1269,48 @@ void DFrameBuffer::DrawRemainingPlayerSprites() R_DrawRemainingPlayerSprites(); } +//=========================================================================== +// +// notify the renderer that an actor has changed state +// +//=========================================================================== +void DFrameBuffer::StateChanged(AActor *actor) +{ +} + +//=========================================================================== +// +// notify the renderer that serialization of the curent level is about to start/end +// +//=========================================================================== + +void DFrameBuffer::StartSerialize(FArchive &arc) +{ +} + +void DFrameBuffer::EndSerialize(FArchive &arc) +{ +} + +//=========================================================================== +// +// Get max. view angle (renderer specific information so it goes here now) +// +//=========================================================================== +#define MAX_DN_ANGLE 56 // Max looking down angle +#define MAX_UP_ANGLE 32 // Max looking up angle + +int DFrameBuffer::GetMaxViewPitch(bool down) +{ + return down? MAX_DN_ANGLE*ANGLE_1 : -MAX_UP_ANGLE*ANGLE_1; +} + +//=========================================================================== +// +// +// +//=========================================================================== FNativePalette::~FNativePalette() { diff --git a/src/v_video.h b/src/v_video.h index a6f30a43a..3109901bb 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -351,6 +351,15 @@ public: // draws player sprites with hardware acceleration (only useful for software rendering) virtual void DrawRemainingPlayerSprites(); + // notifies the renderer that an actor has changed state. + virtual void StateChanged(AActor *actor); + + // notify the renderer that serialization of the curent level is about to start/end + virtual void StartSerialize(FArchive &arc); + virtual void EndSerialize(FArchive &arc); + + virtual int GetMaxViewPitch(bool down); + bool Accel2D; // If true, 2D drawing can be accelerated. // Begin 2D drawing operations. This is like Update, but it doesn't end From 7e2e62fd5c4f1c8798069af2e957818bed4f91d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 25 Oct 2009 19:39:43 +0000 Subject: [PATCH 046/241] - fixed: sector_t::GetHeightSec checked the wrong MoreFlags. SVN r1936 (trunk) --- docs/rh-log.txt | 1 + src/r_defs.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 905f27326..6df94d23d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 24, 2009 (Changes by Graf Zahl) +- fixed: sector_t::GetHeightSec checked the wrong MoreFlags. - made max. view pitch a property of the renderer so that it's overridable without changing game code. - made SpawningMapThing an argument of AActor::StaticSpawn instead of a global diff --git a/src/r_defs.h b/src/r_defs.h index 88f4e98a8..623e475c4 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -588,7 +588,7 @@ struct sector_t sector_t *GetHeightSec() const { - return (MoreFlags & SECF_IGNOREHEIGHTSEC)? NULL : heightsec; + return (heightsec && !(heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))? heightsec : NULL; } void ChangeLightLevel(int newval) From 5ab4159e76b034066ad123454323b97812f95944 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 25 Oct 2009 23:12:00 +0000 Subject: [PATCH 047/241] - fixed damage calculation for OLDRADIUSDMG case of P_RadiusAttack. SVN r1937 (trunk) --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index f225ef0e6..8dcbe70fa 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4328,7 +4328,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b if (P_CheckSight (thing, bombspot, 1)) { // OK to damage; target is in direct path dist = clamp(dist - fulldamagedistance, 0, dist); - int damage = Scale (bombdamage, bombdistance-dist, bombdistance-fulldamagedistance); + int damage = Scale (bombdamage, bombdistance-dist, bombdistance); damage = (int)((float)damage * splashfactor); damage = Scale(damage, thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT), FRACUNIT); From be3bb0093ad09c7f0c00fb8585df58b2fa8669ef Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 27 Oct 2009 01:53:47 +0000 Subject: [PATCH 048/241] - Fixed: R_RenderDecal() must save various Wall globals, because the originals may still be needed. In particular, when drawing a seg with a midtexture is split by foreground geometry, the first drawseg generated from it will have the correct WallSZ1,2 values, but subsequent ones will have whatever R_RenderDecal() left behind. These values are used to calculate the upper and lower bounds of the midtexture. (Ironically, my work to Build-ify things had done away with these globals, but that's gone now.) SVN r1938 (trunk) --- docs/rh-log.txt | 9 +++++++++ src/r_segs.cpp | 46 +++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6df94d23d..fb81752b3 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +October 26, 2009 +- Fixed: R_RenderDecal() must save various Wall globals, because the originals + may still be needed. In particular, when drawing a seg with a midtexture is + split by foreground geometry, the first drawseg generated from it will have + the correct WallSZ1,2 values, but subsequent ones will have whatever + R_RenderDecal() left behind. These values are used to calculate the upper + and lower bounds of the midtexture. (Ironically, my work to Build-ify things + had done away with these globals, but that's gone now.) + October 24, 2009 (Changes by Graf Zahl) - fixed: sector_t::GetHeightSec checked the wrong MoreFlags. - made max. view pitch a property of the renderer so that it's overridable without diff --git a/src/r_segs.cpp b/src/r_segs.cpp index e58d042ab..d913f56c1 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2246,6 +2246,15 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // to a wall, we use the wall's angle instead of the decal's. This is // pretty much the same as what R_AddLine() does. + fixed_t savetx1, savetx2, savety1, savety2, savesz1, savesz2; + + savetx1 = WallTX1; + savetx2 = WallTX2; + savety1 = WallTY1; + savety2 = WallTY2; + savesz1 = WallSZ1; + savesz2 = WallSZ2; + x2 = WallSpriteTile->GetWidth(); x1 = WallSpriteTile->LeftOffset; x2 = x2 - x1; @@ -2277,43 +2286,43 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, if (WallTX1 >= -WallTY1) { - if (WallTX1 > WallTY1) return; // left edge is off the right side - if (WallTY1 == 0) return; + if (WallTX1 > WallTY1) goto done; // left edge is off the right side + if (WallTY1 == 0) goto done; x1 = (centerxfrac + Scale (WallTX1, centerxfrac, WallTY1)) >> FRACBITS; if (WallTX1 >= 0) x1 = MIN (viewwidth, x1+1); // fix for signed divide WallSZ1 = WallTY1; } else { - if (WallTX2 < -WallTY2) return; // wall is off the left side + if (WallTX2 < -WallTY2) goto done; // wall is off the left side fixed_t den = WallTX1 - WallTX2 - WallTY2 + WallTY1; - if (den == 0) return; + if (den == 0) goto done; x1 = 0; WallSZ1 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 + WallTY1, den); } if (WallSZ1 < TOO_CLOSE_Z) - return; + goto done; if (WallTX2 <= WallTY2) { - if (WallTX2 < -WallTY2) return; // right edge is off the left side - if (WallTY2 == 0) return; + if (WallTX2 < -WallTY2) goto done; // right edge is off the left side + if (WallTY2 == 0) goto done; x2 = (centerxfrac + Scale (WallTX2, centerxfrac, WallTY2)) >> FRACBITS; if (WallTX2 >= 0) x2 = MIN (viewwidth, x2+1); // fix for signed divide WallSZ2 = WallTY2; } else { - if (WallTX1 > WallTY1) return; // wall is off the right side + if (WallTX1 > WallTY1) goto done; // wall is off the right side fixed_t den = WallTY2 - WallTY1 - WallTX2 + WallTX1; - if (den == 0) return; + if (den == 0) goto done; x2 = viewwidth; WallSZ2 = WallTY1 + Scale (WallTY2 - WallTY1, WallTX1 - WallTY1, den); } if (x1 >= x2 || x1 > clipper->x2 || x2 <= clipper->x1 || WallSZ2 < TOO_CLOSE_Z) - return; + goto done; if (MirrorFlags & RF_XFLIP) { @@ -2340,7 +2349,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { if (pass != 0) { - return; + goto done; } mceilingclip = walltop; mfloorclip = wallbottom; @@ -2361,7 +2370,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, case RF_CLIPUPPER: if (pass != 0) { - return; + goto done; } mceilingclip = walltop; mfloorclip = ceilingclip; @@ -2370,7 +2379,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, case RF_CLIPMID: if (curline->backsector != NULL && pass != 2) { - return; + goto done; } mceilingclip = openings + clipper->sprtopclip - clipper->x1; mfloorclip = openings + clipper->sprbottomclip - clipper->x1; @@ -2379,7 +2388,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, case RF_CLIPLOWER: if (pass != 0) { - return; + goto done; } mceilingclip = floorclip; mfloorclip = wallbottom; @@ -2400,7 +2409,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, } if (x1 >= x2) { - return; + goto done; } swap (x1, WallSX1); @@ -2523,6 +2532,13 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, hcolfunc_post4 = rt_map4cols; R_FinishSetPatchStyle (); +done: + WallTX1 = savetx1; + WallTX2 = savetx2; + WallTY1 = savety1; + WallTY2 = savety2; + WallSZ1 = savesz1; + WallSZ2 = savesz2; } static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) From 750659a82e64dac26b0185715c11b49e3eccbf7d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 27 Oct 2009 02:43:00 +0000 Subject: [PATCH 049/241] - Added new sound sequence ACS functions: SoundSequenceOnActor(int tid, string seqname); SoundSequenceOnSector(int tag, string seqname, int location); SoundSequenceOnPolyobj(int polynum, string seqname); SoundSequenceOnSector takes an extra parameter that specifies where in the sector the sound comes from (floor, ceiling, interior, or all of it). See the SECSEQ defines in zdefs.acs. SVN r1939 (trunk) --- docs/rh-log.txt | 7 ++++++ src/p_acs.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- src/p_local.h | 1 + src/po_man.cpp | 43 +++++++++++++++++------------------ 4 files changed, 88 insertions(+), 23 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fb81752b3..c81a2fb8e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,11 @@ October 26, 2009 +- Added new sound sequence ACS functions: + SoundSequenceOnActor(int tid, string seqname); + SoundSequenceOnSector(int tag, string seqname, int location); + SoundSequenceOnPolyobj(int polynum, string seqname); + SoundSequenceOnSector takes an extra parameter that specifies where in the + sector the sound comes from (floor, ceiling, interior, or all of it). See + the SECSEQ defines in zdefs.acs. - Fixed: R_RenderDecal() must save various Wall globals, because the originals may still be needed. In particular, when drawing a seg with a midtexture is split by foreground geometry, the first drawseg generated from it will have diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a0d2811ad..c6f4791c4 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2910,6 +2910,9 @@ enum EACSFunctions ACSF_CheckActorClass, ACSF_SetUserArray, ACSF_GetUserArray, + ACSF_SoundSequenceOnActor, + ACSF_SoundSequenceOnSector, + ACSF_SoundSequenceOnPolyobj, }; int DLevelScript::SideFromID(int id, int side) @@ -3257,6 +3260,61 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) return a->GetClass()->TypeName == FName(FBehavior::StaticLookupString(args[1])); } + case ACSF_SoundSequenceOnActor: + { + const char *seqname = FBehavior::StaticLookupString(args[1]); + if (seqname != NULL) + { + if (args[0] == 0) + { + if (activator != NULL) + { + SN_StartSequence(activator, seqname, 0); + } + } + else + { + FActorIterator it(args[0]); + AActor *actor; + + while ( (actor = it.Next()) ) + { + SN_StartSequence(actor, seqname, 0); + } + } + } + } + break; + + case ACSF_SoundSequenceOnSector: + { + const char *seqname = FBehavior::StaticLookupString(args[1]); + int space = args[2] < CHAN_FLOOR || args[2] > CHAN_INTERIOR ? CHAN_FULLHEIGHT : args[2]; + if (seqname != NULL) + { + int secnum = -1; + + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + SN_StartSequence(§ors[secnum], args[2], seqname, 0); + } + } + } + break; + + case ACSF_SoundSequenceOnPolyobj: + { + const char *seqname = FBehavior::StaticLookupString(args[1]); + if (seqname != NULL) + { + FPolyObj *poly = PO_GetPolyobj(args[0]); + if (poly != NULL) + { + SN_StartSequence(poly, seqname, 0); + } + } + } + break; default: break; @@ -5083,7 +5141,7 @@ int DLevelScript::RunScript () lookup = FBehavior::StaticLookupString (STACK(1)); if (lookup != NULL) { - if (activationline) + if (activationline != NULL) { SN_StartSequence (activationline->frontsector, CHAN_FULLHEIGHT, lookup, 0); } diff --git a/src/p_local.h b/src/p_local.h index 0be5c11e0..4d37bc8de 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -517,6 +517,7 @@ bool PO_RotatePolyobj (int num, angle_t angle); void PO_Init (); bool PO_Busy (int polyobj); void PO_ClosestPoint(const FPolyObj *poly, fixed_t ox, fixed_t oy, fixed_t &x, fixed_t &y, seg_t **seg); +struct FPolyObj *PO_GetPolyobj(int polyNum); // // P_SPEC diff --git a/src/po_man.cpp b/src/po_man.cpp index d88c67589..ebafff46f 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -120,7 +120,6 @@ void PO_Init (void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static FPolyObj *GetPolyobj (int polyNum); static int GetPolyobjMirror (int poly); static void UpdateSegBBox (seg_t *seg); static void RotatePt (int an, fixed_t *x, fixed_t *y, fixed_t startSpotX, @@ -184,7 +183,7 @@ DPolyAction::DPolyAction (int polyNum) void DPolyAction::Destroy() { - FPolyObj *poly = GetPolyobj (m_PolyObj); + FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (poly->specialdata == NULL || poly->specialdata == this) { @@ -197,7 +196,7 @@ void DPolyAction::Destroy() void DPolyAction::SetInterpolation () { - FPolyObj *poly = GetPolyobj (m_PolyObj); + FPolyObj *poly = PO_GetPolyobj (m_PolyObj); m_Interpolation = poly->SetInterpolation(); } @@ -278,7 +277,7 @@ void DRotatePoly::Tick () m_Dist -= absSpeed; if (m_Dist == 0) { - FPolyObj *poly = GetPolyobj (m_PolyObj); + FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (poly->specialdata == this) { poly->specialdata = NULL; @@ -307,7 +306,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, DRotatePoly *pe; FPolyObj *poly; - if ( (poly = GetPolyobj(polyNum)) ) + if ( (poly = PO_GetPolyobj(polyNum)) ) { if (poly->specialdata && !overRide) { // poly is already moving @@ -338,9 +337,9 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, poly->specialdata = pe; SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); - while ( (mirror = GetPolyobjMirror( polyNum)) ) + while ( (mirror = GetPolyobjMirror(polyNum)) ) { - poly = GetPolyobj(mirror); + poly = PO_GetPolyobj(mirror); if (poly == NULL) { I_Error ("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); @@ -390,7 +389,7 @@ void DMovePoly::Tick () m_Dist -= absSpeed; if (m_Dist <= 0) { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); if (poly->specialdata == this) { poly->specialdata = NULL; @@ -421,7 +420,7 @@ bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, FPolyObj *poly; angle_t an; - if ( (poly = GetPolyobj(polyNum)) ) + if ( (poly = PO_GetPolyobj(polyNum)) ) { if (poly->specialdata && !overRide) { // poly is already moving @@ -455,7 +454,7 @@ bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, while ( (mirror = GetPolyobjMirror(polyNum)) ) { - poly = GetPolyobj(mirror); + poly = PO_GetPolyobj(mirror); if (poly && poly->specialdata && !overRide) { // mirroring poly is already in motion break; @@ -493,7 +492,7 @@ void DPolyDoor::Tick () { if (!--m_Tics) { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); SN_StartSequence (poly, poly->seqType, SEQ_DOOR, m_Close); } return; @@ -507,7 +506,7 @@ void DPolyDoor::Tick () m_Dist -= absSpeed; if (m_Dist <= 0) { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); SN_StopSequence (poly); if (!m_Close) { @@ -531,7 +530,7 @@ void DPolyDoor::Tick () } else { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); if (poly->crush || !m_Close) { // continue moving if the poly is a crusher, or is opening return; @@ -560,7 +559,7 @@ void DPolyDoor::Tick () m_Dist -= absSpeed; if (m_Dist <= 0) { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); SN_StopSequence (poly); if (!m_Close) { @@ -581,7 +580,7 @@ void DPolyDoor::Tick () } else { - poly = GetPolyobj (m_PolyObj); + poly = PO_GetPolyobj (m_PolyObj); if(poly->crush || !m_Close) { // continue moving if the poly is a crusher, or is opening return; @@ -614,7 +613,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, DPolyDoor *pd; FPolyObj *poly; - if( (poly = GetPolyobj(polyNum)) ) + if( (poly = PO_GetPolyobj(polyNum)) ) { if (poly->specialdata) { // poly is already moving @@ -649,7 +648,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, while ( (mirror = GetPolyobjMirror (polyNum)) ) { - poly = GetPolyobj (mirror); + poly = PO_GetPolyobj (mirror); if (poly && poly->specialdata) { // mirroring poly is already in motion break; @@ -683,11 +682,11 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, //========================================================================== // -// GetPolyobj +// PO_GetPolyobj // //========================================================================== -static FPolyObj *GetPolyobj (int polyNum) +FPolyObj *PO_GetPolyobj (int polyNum) { int i; @@ -844,7 +843,7 @@ bool PO_MovePolyobj (int num, int x, int y, bool force) { FPolyObj *po; - if (!(po = GetPolyobj (num))) + if (!(po = PO_GetPolyobj (num))) { I_Error ("PO_MovePolyobj: Invalid polyobj number: %d\n", num); } @@ -954,7 +953,7 @@ bool PO_RotatePolyobj (int num, angle_t angle) FPolyObj *po; bool blocked; - if(!(po = GetPolyobj(num))) + if(!(po = PO_GetPolyobj(num))) { I_Error("PO_RotatePolyobj: Invalid polyobj number: %d\n", num); } @@ -1662,7 +1661,7 @@ bool PO_Busy (int polyobj) { FPolyObj *poly; - poly = GetPolyobj (polyobj); + poly = PO_GetPolyobj (polyobj); if (poly == NULL || poly->specialdata == NULL) { return false; From efaa26959ef957fcf1b634788a4370c99b96418b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 27 Oct 2009 03:59:29 +0000 Subject: [PATCH 050/241] - Changes to both A_MonsterRail() and A_CustomRailgun(): Save actor's pitch, use a larger aiming range, and ignore non-targets in P_AimLineAttack(). - Added another parameter to P_AimLineAttack(): A target to be aimed at. If this is non-NULL, then all actors between the shooter and the target will be ignored. SVN r1941 (trunk) --- docs/rh-log.txt | 5 ++++ src/p_enemy.cpp | 5 +++- src/p_local.h | 2 +- src/p_map.cpp | 42 +++++++++++++++++-------------- src/thingdef/thingdef_codeptr.cpp | 7 +++--- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c81a2fb8e..34083d457 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,9 @@ October 26, 2009 +- Changes to both A_MonsterRail() and A_CustomRailgun(): Save actor's pitch, + use a larger aiming range, and ignore non-targets in P_AimLineAttack(). +- Added another parameter to P_AimLineAttack(): A target to be aimed at. If + this is non-NULL, then all actors between the shooter and the target will + be ignored. - Added new sound sequence ACS functions: SoundSequenceOnActor(int tid, string seqname); SoundSequenceOnSector(int tag, string seqname, int location); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 300d70a0f..08bd6af83 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2703,6 +2703,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) if (!self->target) return; + fixed_t saved_pitch = self->pitch; + // [RH] Andy Baker's stealth monsters if (self->flags & MF_STEALTH) { @@ -2716,7 +2718,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) self->target->x, self->target->y); - self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE); + self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, NULL, ANGLE_1*60, false, false, false, self->target); // Let the aim trail behind the player self->angle = R_PointToAngle2 (self->x, @@ -2730,6 +2732,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) } P_RailAttack (self, self->GetMissileDamage (0, 1), 0); + self->pitch = saved_pitch; } DEFINE_ACTION_FUNCTION(AActor, A_Scream) diff --git a/src/p_local.h b/src/p_local.h index 4d37bc8de..31096fb8c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -394,7 +394,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false); bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset); -fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false, bool checknonshootable = false); +fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false, bool checknonshootable = false, AActor *target=NULL); AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, bool ismelee = false); AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, bool ismelee = false); void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch); diff --git a/src/p_map.cpp b/src/p_map.cpp index 8dcbe70fa..de3653a0e 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2801,7 +2801,7 @@ struct aim_t bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in); #endif - void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable = false); + void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable = false, AActor *target=NULL); }; @@ -2918,7 +2918,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in) // //============================================================================ -void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable) +void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable, AActor *target) { FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS); intercept_t *in; @@ -2973,6 +2973,9 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e if (th == shootthing) continue; // can't shoot self + if (target != NULL && th != target) + continue; // only care about target, and you're not it + if (!checknonshootable) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags { if (!(th->flags&MF_SHOOTABLE)) @@ -3084,8 +3087,8 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e if (sv_smartaim < 2) { // friends don't aim at friends (except players), at least not first - thing_friend=th; - pitch_friend=thingpitch; + thing_friend = th; + pitch_friend = thingpitch; } } else if (!(th->flags3&MF3_ISMONSTER) && th->player == NULL) @@ -3093,27 +3096,27 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e if (sv_smartaim < 3) { // don't autoaim at barrels and other shootable stuff unless no monsters have been found - thing_other=th; - pitch_other=thingpitch; + thing_other = th; + pitch_other = thingpitch; } } else { - linetarget=th; - aimpitch=thingpitch; + linetarget = th; + aimpitch = thingpitch; return; } } else { - linetarget=th; - aimpitch=thingpitch; + linetarget = th; + aimpitch = thingpitch; return; } if (checknonshootable) { - linetarget=th; - aimpitch=thingpitch; + linetarget = th; + aimpitch = thingpitch; } } } @@ -3124,7 +3127,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e // //============================================================================ -fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable) +fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable, AActor *target) { fixed_t x2; fixed_t y2; @@ -3193,22 +3196,23 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p } #endif - aim.AimTraverse (t1->x, t1->y, x2, y2, checknonshootable); + aim.AimTraverse (t1->x, t1->y, x2, y2, checknonshootable, target); if (!aim.linetarget) { if (aim.thing_other) { - aim.linetarget=aim.thing_other; - aim.aimpitch=aim.pitch_other; + aim.linetarget = aim.thing_other; + aim.aimpitch = aim.pitch_other; } else if (aim.thing_friend) { - aim.linetarget=aim.thing_friend; - aim.aimpitch=aim.pitch_friend; + aim.linetarget = aim.thing_friend; + aim.aimpitch = aim.pitch_friend; } } - if (pLineTarget) *pLineTarget = aim.linetarget; + if (pLineTarget) + *pLineTarget = aim.linetarget; return aim.linetarget ? aim.aimpitch : t1->pitch; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index c5410ef6c..34ef23486 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1182,6 +1182,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) fixed_t saved_x = self->x; fixed_t saved_y = self->y; angle_t saved_angle = self->angle; + fixed_t saved_pitch = self->pitch; if (aim && self->target == NULL) { @@ -1198,15 +1199,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) if (aim) { - self->angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y); - } - - self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE); + self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, NULL, ANGLE_1*60, false, false, false, self->target); // Let the aim trail behind the player if (aim) @@ -1242,6 +1240,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) self->x = saved_x; self->y = saved_y; self->angle = saved_angle; + self->pitch = saved_pitch; } //=========================================================================== From 1c3de335851f619d0905c9f861ac12bdfe58553c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 27 Oct 2009 04:16:55 +0000 Subject: [PATCH 051/241] - Make A_MonsterRail() and A_CustomRailgun() aim at the target anyway even if P_AimLineAttack() decides it has no chance of hitting. SVN r1942 (trunk) --- docs/rh-log.txt | 4 +++- src/p_enemy.cpp | 11 ++++++++++- src/thingdef/thingdef_codeptr.cpp | 13 +++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 34083d457..1d85b790d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,6 +1,8 @@ October 26, 2009 - Changes to both A_MonsterRail() and A_CustomRailgun(): Save actor's pitch, - use a larger aiming range, and ignore non-targets in P_AimLineAttack(). + use a larger aiming range, ignore non-targets in P_AimLineAttack(), and + aim at the target anyway even if P_AimLineAttack() decides it has no + chance of hitting. - Added another parameter to P_AimLineAttack(): A target to be aimed at. If this is non-NULL, then all actors between the shooter and the target will be ignored. diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 08bd6af83..980025d96 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2704,6 +2704,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) return; fixed_t saved_pitch = self->pitch; + AActor *linetarget; // [RH] Andy Baker's stealth monsters if (self->flags & MF_STEALTH) @@ -2718,7 +2719,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) self->target->x, self->target->y); - self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, NULL, ANGLE_1*60, false, false, false, self->target); + self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, false, false, false, self->target); + if (linetarget == NULL) + { + // We probably won't hit the target, but aim at it anyway so we don't look stupid. + FVector2 xydiff(self->target->x - self->x, self->target->y - self->y); + double zdiff = (self->target->z + (self->target->height>>1)) - + (self->z + (self->height>>1) - self->floorclip); + self->pitch = int(atan2(zdiff, xydiff.Length()) * ANGLE_180 / -M_PI); + } // Let the aim trail behind the player self->angle = R_PointToAngle2 (self->x, diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 34ef23486..d1c9f4083 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1179,6 +1179,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) ACTION_PARAM_FLOAT(MaxDiff, 6); ACTION_PARAM_CLASS(PuffType, 7); + AActor *linetarget; + fixed_t saved_x = self->x; fixed_t saved_y = self->y; angle_t saved_angle = self->angle; @@ -1204,8 +1206,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) self->target->x, self->target->y); } - self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, NULL, ANGLE_1*60, false, false, false, self->target); - + self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, false, false, false, aim ? self->target : NULL); + if (linetarget == NULL && aim) + { + // We probably won't hit the target, but aim at it anyway so we don't look stupid. + FVector2 xydiff(self->target->x - self->x, self->target->y - self->y); + double zdiff = (self->target->z + (self->target->height>>1)) - + (self->z + (self->height>>1) - self->floorclip); + self->pitch = int(atan2(zdiff, xydiff.Length()) * ANGLE_180 / -M_PI); + } // Let the aim trail behind the player if (aim) { From df317801bfa9c03a974099cd9f206f76da96782a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 28 Oct 2009 23:14:20 +0000 Subject: [PATCH 052/241] - Fixed: Do not exit P_DamageMobj early if damage is 0, so we can still get the side effects from it. PainThreshold also needs to be inclusive, as the docs already state. SVN r1943 (trunk) --- docs/rh-log.txt | 5 +++++ src/p_interaction.cpp | 36 ++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1d85b790d..77d5f674c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +October 28, 2009 +- Fixed: Do not exit P_DamageMobj early if damage is 0, so we can still get + the side effects from it. PainThreshold also needs to be inclusive, as + the docs already state. + October 26, 2009 - Changes to both A_MonsterRail() and A_CustomRailgun(): Save actor's pitch, use a larger aiming range, ignore non-targets in P_AimLineAttack(), and diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 22d8cdc81..3c8f715f5 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -931,7 +931,8 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage } if (inflictor != NULL) { - if (inflictor->flags5 & MF5_PIERCEARMOR) flags |= DMG_NO_ARMOR; + if (inflictor->flags5 & MF5_PIERCEARMOR) + flags |= DMG_NO_ARMOR; } MeansOfDeath = mod; @@ -981,21 +982,22 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage { return; } - } // Handle active damage modifiers (e.g. PowerDamage) if (source != NULL && source->Inventory != NULL) { int olddam = damage; source->Inventory->ModifyDamage(olddam, mod, damage, false); - if (olddam != damage && damage <= 0) return; + if (olddam != damage && damage <= 0) + return; } // Handle passive damage modifiers (e.g. PowerProtection) if (target->Inventory != NULL) { int olddam = damage; target->Inventory->ModifyDamage(olddam, mod, damage, true); - if (olddam != damage && damage <= 0) return; + if (olddam != damage && damage <= 0) + return; } DmgFactors * df = target->GetClass()->ActorInfo->DamageFactors; @@ -1006,11 +1008,13 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage if (pdf != NULL) { damage = FixedMul(damage, *pdf); - if (damage <= 0) return; + if (damage <= 0) + return; } } damage = FixedMul(damage, target->DamageFactor); - if (damage <= 0) return; + if (damage < 0) + return; damage = target->TakeSpecialDamage (inflictor, source, damage, mod); } @@ -1040,7 +1044,6 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage ang = R_PointToAngle2 (origin->x, origin->y, target->x, target->y); - // Calculate this as float to avoid overflows so that the // clamping that had to be done here can be removed. double fltthrust; @@ -1131,8 +1134,9 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage damage = newdam; if (damage <= 0) { - // If MF&_FORCEPAIN is set make the player enter the pain state. - if (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN)) goto dopain; + // If MF6_FORCEPAIN is set, make the player enter the pain state. + if (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN)) + goto dopain; return; } } @@ -1268,7 +1272,6 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) && !G_SkillProperty(SKILLP_NoPain) && !(target->flags & MF_SKULLFLY)) { - pc = target->GetClass()->ActorInfo->PainChances; painchance = target->PainChance; if (pc != NULL) @@ -1280,7 +1283,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage } } - if ((damage > target->PainThreshold && pr_damagemobj() < painchance) || + if ((damage >= target->PainThreshold && pr_damagemobj() < painchance) || (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))) { dopain: @@ -1289,8 +1292,9 @@ dopain: if (pr_lightning() < 96) { justhit = true; - FState * painstate = target->FindState(NAME_Pain, mod); - if (painstate != NULL) target->SetState (painstate); + FState *painstate = target->FindState(NAME_Pain, mod); + if (painstate != NULL) + target->SetState(painstate); } else { // "electrocute" the target @@ -1304,8 +1308,9 @@ dopain: else { justhit = true; - FState * painstate = target->FindState(NAME_Pain, mod); - if (painstate != NULL) target->SetState (painstate); + FState *painstate = target->FindState(NAME_Pain, mod); + if (painstate != NULL) + target->SetState(painstate); if (mod == NAME_PoisonCloud) { if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128) @@ -1353,7 +1358,6 @@ dopain: // killough 11/98: Don't attack a friend, unless hit by that friend. if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target))) target->flags |= MF_JUSTHIT; // fight back! - } bool AActor::OkayToSwitchTarget (AActor *other) From e5d6256c2da09e0fc809564b601649ec0d02db55 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 28 Oct 2009 23:25:27 +0000 Subject: [PATCH 053/241] - Fixed: 0 damage projectiles did not call P_DamageMobj. SVN r1944 (trunk) --- docs/rh-log.txt | 1 + src/p_map.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 77d5f674c..cb5b1cb09 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 28, 2009 +- Fixed: 0 damage projectiles did not call P_DamageMobj. - Fixed: Do not exit P_DamageMobj early if damage is 0, so we can still get the side effects from it. PainThreshold also needs to be inclusive, as the docs already state. diff --git a/src/p_map.cpp b/src/p_map.cpp index de3653a0e..35e512c04 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1092,7 +1092,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // Do damage damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); // [GZ] If MF6_FORCEPAIN is set, we need to call P_DamageMobj even if damage is 0! - if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) + if ((damage >= 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) { P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); if (damage > 0) From 059be338b46121352eb2382f25dc85c13adfceab Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 28 Oct 2009 23:28:09 +0000 Subject: [PATCH 054/241] - Guess we don't need this FORCEPAIN check in PIT_CheckThing() anymore. SVN r1945 (trunk) --- src/p_map.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 35e512c04..510e1f9e5 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1091,8 +1091,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } // Do damage damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); - // [GZ] If MF6_FORCEPAIN is set, we need to call P_DamageMobj even if damage is 0! - if ((damage >= 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) + if (damage >= 0) { P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); if (damage > 0) @@ -1112,7 +1111,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } } - else if (damage < 0) + else { P_GiveBody (thing, -damage); } From d0822663658f9fe4b332689c10a53baf2c549f5d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 29 Oct 2009 05:51:20 +0000 Subject: [PATCH 055/241] - Added Gez's patch for IWAD detection of Blasphemer and Action Doom 2. SVN r1946 (trunk) --- docs/rh-log.txt | 1 + src/d_iwad.cpp | 24 ++++++++++++++++++++++-- src/d_main.h | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index cb5b1cb09..defe86fad 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ October 28, 2009 +- Added Gez's patch for IWAD detection of Blasphemer and Action Doom 2. - Fixed: 0 damage projectiles did not call P_DamageMobj. - Fixed: Do not exit P_DamageMobj early if damage is 0, so we can still get the side effects from it. PainThreshold also needs to be inclusive, as diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index b1270729a..672823d63 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -77,8 +77,10 @@ const IWADInfo IWADInfos[NUM_IWAD_TYPES] = { "Ultimate Freedoom", "Freedoom1",MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom1.txt" }, { "Freedoom \"Demo\"", NULL, MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom1.txt" }, { "FreeDM", "FreeDM", MAKERGB(50,84,67), MAKERGB(198,220,209), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx }, + { "Blasphemer", "Blasphemer",MAKERGB(115,0,0), MAKERGB(0,0,0), GAME_Heretic, "mapinfo/heretic.txt" }, { "Chex(R) Quest", "Chex1", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex.txt" }, { "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt" }, + { "Action Doom 2: Urban Brawl", "UrbanBrawl",MAKERGB(168,168,0), MAKERGB(168,0,0), GAME_Doom, "mapinfo/doom2.txt" }, //{ "ZDoom Engine", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) }, }; @@ -104,8 +106,11 @@ static const char *IWADNames[] = "freedoom1.wad", "freedoomu.wad", "freedm.wad", + "blasphem.wad", + "blasphemer.wad", "chex.wad", "chex3.wad", + "action2.wad", #ifdef unix "DOOM2.WAD", // Also look for all-uppercase names "PLUTONIA.WAD", @@ -124,8 +129,11 @@ static const char *IWADNames[] = "FREEDOOM1.WAD", "FREEDOOMU.WAD", "FREEDM.WAD", + "BLASPHEM.WAD", + "BLASPHEMER.WAD", "CHEX.WAD", "CHEX3.WAD", + "ACTION2.WAD", #endif NULL }; @@ -141,6 +149,7 @@ static EIWADType ScanIWAD (const char *iwad) { static const char checklumps[][8] = { + "AD2LIB", "E1M1", "E4M2", "MAP01", @@ -154,6 +163,7 @@ static EIWADType ScanIWAD (const char *iwad) "MAP33", "INVCURS", { 'F','R','E','E','D','O','O','M' }, + { 'B','L','A','S','P','H','E','M' }, "W94_1", { 'P','O','S','S','H','0','M','0' }, "CYCLA1", @@ -169,6 +179,7 @@ static EIWADType ScanIWAD (const char *iwad) #define NUM_CHECKLUMPS (sizeof(checklumps)/8) enum { + Check_ad2lib, Check_e1m1, Check_e4m1, Check_map01, @@ -182,6 +193,7 @@ static EIWADType ScanIWAD (const char *iwad) Check_map33, Check_invcurs, Check_FreeDoom, + Check_Blasphem, Check_W94_1, Check_POSSH0M0, Check_Cycla1, @@ -237,7 +249,11 @@ static EIWADType ScanIWAD (const char *iwad) } else if (lumpsfound[Check_map01]) { - if (lumpsfound[Check_FreeDoom]) + if (lumpsfound[Check_ad2lib]) + { + return IWAD_ActionDoom2; + } + else if (lumpsfound[Check_FreeDoom]) { // Is there a 100% reliable way to tell FreeDoom and FreeDM // apart based solely on the lump names? @@ -287,7 +303,11 @@ static EIWADType ScanIWAD (const char *iwad) } else { - if (lumpsfound[Check_Extended]) + if (lumpsfound[Check_Blasphem]) + { + return IWAD_Blasphemer; + } + else if (lumpsfound[Check_Extended]) { return IWAD_HereticExtended; } diff --git a/src/d_main.h b/src/d_main.h index dac990bd3..e9af860a0 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -77,8 +77,10 @@ enum EIWADType IWAD_FreeDoomU, IWAD_FreeDoom1, IWAD_FreeDM, + IWAD_Blasphemer, IWAD_ChexQuest, IWAD_ChexQuest3, + IWAD_ActionDoom2, IWAD_Custom, NUM_IWAD_TYPES From aea4e38241d7116a2d56a178a5fc661be9bc69a3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 29 Oct 2009 06:32:50 +0000 Subject: [PATCH 056/241] - GCC compile fix. SVN r1947 (trunk) --- src/r_segs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index d913f56c1..139167c5b 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2187,6 +2187,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, fixed_t zpos; int needrepeat = 0; sector_t *front, *back; + bool calclighting; if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) return; @@ -2430,7 +2431,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, } // Prepare lighting - bool calclighting = false; + calclighting = false; rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep; if (fixedlightlev >= 0) From 0e5f48adb493c7c8566474838626f53418ddcece Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 00:59:34 +0000 Subject: [PATCH 057/241] - Quoth Gez: * when a logical condition was rewritten and inverted, one of the boolean test wasn't inverted along the rest. So the "monster must not be a player" was accidentally changed into "monster must be a player", which is usually going to be false... There's another minor, but related issue. SVN r1948 (trunk) --- src/p_enemy.cpp | 5 ++++- src/p_mobj.cpp | 2 +- wadsrc/static/compatibility.txt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 980025d96..919c11bec 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2545,6 +2545,10 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); info = corpsehit->GetDefault (); + if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) + { + corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses + } if (ib_compatflags & BCOMPATF_VILEGHOSTS) { corpsehit->height <<= 2; @@ -2563,7 +2567,6 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) corpsehit->RenderStyle = STYLE_Translucent; } } - corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses } else { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9b9824264..7ecf49987 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1018,7 +1018,7 @@ bool AActor::Grind(bool items) if (state == NULL // Only use the default crushed state if: && !(flags & MF_NOBLOOD) // 1. the monster bleeeds, && (i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, - && player != NULL) // 3. and the thing isn't a player. + && player == NULL) // 3. and the thing isn't a player. { isgeneric = true; state = FindState(NAME_GenericCrush); diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index dbaadf6fc..b2a168ce7 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -86,6 +86,7 @@ F84AB4557464A383E93F37CD3A82AC48 // MM2 map03 2EEB1E12FA9F9545DE9D99990A4A78E5 // Icarus map24 65A53A09A09525AE42EA210BF879CD37 // Plutonia 2 map32 2499CF9A9351BE9BC4E9C66FC9F291A7 // Requiem map23 +3CA5493FEFF2E27BFD4181E6C4A3C2BF // The Waterfront map01 { corpsegibs vileghosts From 50b0340a565baf40692f175783a692d1445fe41c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 02:18:07 +0000 Subject: [PATCH 058/241] - Fixed: S_EvictAllChannels() must replace the channel's start time with its position when evicting sounds, because restarting the sound system causes the DSP clock to restart at 0, so start times that were recorded before the reset are no longer applicable after the reset. - Fixed: S_StopChannel() always set the channel's actor to NULL, eliminating origin information when resetting the sound system. SVN r1949 (trunk) --- docs/rh-log.txt | 8 ++++++++ src/s_sound.cpp | 15 +++++++++------ src/sound/fmodsound.cpp | 8 ++++---- src/sound/fmodsound.h | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index defe86fad..2162575de 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +October 29, 2009 +- Fixed: S_EvictAllChannels() must replace the channel's start time with its + position when evicting sounds, because restarting the sound system causes + the DSP clock to restart at 0, so start times that were recorded before + the reset are no longer applicable after the reset. +- Fixed: S_StopChannel() always set the channel's actor to NULL, eliminating + origin information when resetting the sound system. + October 28, 2009 - Added Gez's patch for IWAD detection of Blasphemer and Action Doom 2. - Fixed: 0 damage projectiles did not call P_DamageMobj. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 099565925..e294b6efb 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1741,6 +1741,11 @@ void S_EvictAllChannels() chan->ChanFlags |= CHAN_EVICTED; if (chan->SysChannel != NULL) { + if (!(chan->ChanFlags & CHAN_ABSTIME)) + { + chan->StartTime.AsOne = GSnd ? GSnd->GetPosition(chan) : 0; + chan->ChanFlags |= CHAN_ABSTIME; + } S_StopChannel(chan); } // assert(chan->NextChan == next); @@ -2016,13 +2021,11 @@ void S_StopChannel(FSoundChan *chan) if (!(chan->ChanFlags & CHAN_EVICTED)) { chan->ChanFlags |= CHAN_FORGETTABLE; + if (chan->SourceType == SOURCE_Actor) + { + chan->Actor = NULL; + } } - - if (chan->SourceType == SOURCE_Actor) - { - chan->Actor = NULL; - } - GSnd->StopChannel(chan); } else diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 2fc37322d..2a1ad2b9c 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1541,7 +1541,7 @@ FISoundChannel *FMODSoundRenderer::StartSound(SoundHandle sfx, float vol, int pi chan->setFrequency(freq); } chan->setVolume(vol); - if (!HandleChannelDelay(chan, reuse_chan, !!(flags & SNDF_ABSTIME), freq)) + if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) { chan->stop(); return NULL; @@ -1648,7 +1648,7 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * chan->set3DAttributes((FMOD_VECTOR *)&pos[0], (FMOD_VECTOR *)&vel[0]); chan->set3DSpread(snd_3dspread); } - if (!HandleChannelDelay(chan, reuse_chan, !!(flags & SNDF_ABSTIME), freq)) + if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) { chan->stop(); return NULL; @@ -1685,7 +1685,7 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * // //========================================================================== -bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, bool abstime, float freq) const +bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, int flags, float freq) const { if (reuse_chan != NULL) { // Sound is being restarted, so seek it to the position @@ -1695,7 +1695,7 @@ bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel * // If abstime is set, the sound is being restored, and // the channel's start time is actually its seek position. - if (abstime) + if (flags & SNDF_ABSTIME) { unsigned int seekpos = reuse_chan->StartTime.Lo; if (seekpos > 0) diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 2fe497365..5febda3e2 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -69,7 +69,7 @@ private: static FMOD_RESULT F_CALLBACK ChannelCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *data1, void *data2); static float F_CALLBACK RolloffCallback(FMOD_CHANNEL *channel, float distance); - bool HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, bool abstime, float freq) const; + bool HandleChannelDelay(FMOD::Channel *chan, FISoundChannel *reuse_chan, int flags, float freq) const; FISoundChannel *CommonChannelSetup(FMOD::Channel *chan, FISoundChannel *reuse_chan) const; FMOD_MODE SetChanHeadSettings(SoundListener *listener, FMOD::Channel *chan, const FVector3 &pos, bool areasound, FMOD_MODE oldmode) const; From 0f96ec4a32c321c02e5c3798f96bc454b8c935bf Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 02:42:40 +0000 Subject: [PATCH 059/241] - Fixed: An unspecified save_dir will now save to the program directory on Windows. (Other operating systems already use the user's home directory instead.) SVN r1950 (trunk) --- docs/rh-log.txt | 3 +++ src/g_game.cpp | 11 +++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2162575de..b76087dfa 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ October 29, 2009 +- Fixed: An unspecified save_dir will now save to the program directory on + Windows. (Other operating systems already use the user's home directory + instead.) - Fixed: S_EvictAllChannels() must replace the channel's start time with its position when evicting sounds, because restarting the sound system causes the DSP clock to restart at 0, so start times that were recorded before diff --git a/src/g_game.cpp b/src/g_game.cpp index c617f9804..613b147ba 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1851,14 +1851,11 @@ FString G_BuildSaveName (const char *prefix, int slot) { leader = save_dir; } + if (leader.IsEmpty()) + { #ifdef unix - if (leader.IsEmpty()) - { leader = "~/" GAME_DIR; - } #elif defined(__APPLE__) - if (leader.IsEmpty()) - { char cpath[PATH_MAX]; FSRef folder; @@ -1867,8 +1864,10 @@ FString G_BuildSaveName (const char *prefix, int slot) { leader << cpath << "/" GAME_DIR "/Savegames/"; } - } +#else + leader = progdir; #endif + } } size_t len = leader.Len(); if (leader[0] != '\0' && leader[len-1] != '\\' && leader[len-1] != '/') From 321ab2f6867e8a977c130f94cb13721d299f8e36 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 03:29:15 +0000 Subject: [PATCH 060/241] - Make TranslateToStartSpot() set the new sector references for a polyobj's walls so that P_CheckSwitchRange() will work with them. SVN r1951 (trunk) --- docs/rh-log.txt | 4 ++++ src/p_spec.cpp | 6 ++++-- src/p_switch.cpp | 12 ++++++++---- src/po_man.cpp | 15 ++++++++++++--- src/r_defs.h | 2 +- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b76087dfa..39b44e19e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ October 29, 2009 +- Make TranslateToStartSpot() set the new sector references for a polyobj's + walls so that P_CheckSwitchRange() will work with them. +- Fixed: If P_ActivateLine() failed in P_UseTraverse() it would not play + the *usefail sound. - Fixed: An unspecified save_dir will now save to the program directory on Windows. (Other operating systems already use the user's home directory instead.) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 82d91489d..56ecd5179 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -293,7 +293,10 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType) } if (activationType == SPAC_Use) { - if (!P_CheckSwitchRange(mo, line, side)) return false; + if (!P_CheckSwitchRange(mo, line, side)) + { + return false; + } } if ((lineActivation & activationType) == 0) @@ -392,7 +395,6 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType) // void P_PlayerInSpecialSector (player_t *player, sector_t * sector) { - if (sector == NULL) { // Falling, not all the way down yet? diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 4e312a166..25a878884 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -466,7 +466,8 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) { // Activated from an empty side -> always succeed side_t *side = line->sidedef[sideno]; - if (side == NULL) return true; + if (side == NULL) + return true; fixed_t checktop; fixed_t checkbot; @@ -474,7 +475,8 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) FLineOpening open; // 3DMIDTEX forces CHECKSWITCHRANGE because otherwise it might cause problems. - if (!(line->flags & (ML_3DMIDTEX|ML_CHECKSWITCHRANGE))) return true; + if (!(line->flags & (ML_3DMIDTEX|ML_CHECKSWITCHRANGE))) + return true; // calculate the point where the user would touch the wall. divline_t dll, dlu; @@ -502,7 +504,8 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) // Now get the information from the line. P_LineOpening(open, NULL, line, checkx, checky, user->x, user->y); - if (open.range <= 0) goto onesided; + if (open.range <= 0) + goto onesided; if ((TryFindSwitch (side, side_t::top)) != -1) { @@ -516,7 +519,8 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) { // 3DMIDTEX lines will force a mid texture check if no switch is found on this line // to keep compatibility with Eternity's implementation. - if (!P_GetMidTexturePosition(line, sideno, &checktop, &checkbot)) return false; + if (!P_GetMidTexturePosition(line, sideno, &checktop, &checkbot)) + return false; return user->z < checktop || user->z + user->height > checkbot; } else diff --git a/src/po_man.cpp b/src/po_man.cpp index ebafff46f..828ea951a 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1565,21 +1565,30 @@ static void TranslateToStartSpot (int tag, int originX, int originY) (*tempSeg)->v1->x -= deltaX; (*tempSeg)->v1->y -= deltaY; } - avg.x += (*tempSeg)->v1->x>>FRACBITS; - avg.y += (*tempSeg)->v1->y>>FRACBITS; + avg.x += (*tempSeg)->v1->x >> FRACBITS; + avg.y += (*tempSeg)->v1->y >> FRACBITS; // the original Pts are based off the startSpot Pt, and are // unique to each seg, not each linedef tempPt->x = (*tempSeg)->v1->x-po->startSpot[0]; tempPt->y = (*tempSeg)->v1->y-po->startSpot[1]; } + // Put polyobj in its subsector. avg.x /= po->numsegs; avg.y /= po->numsegs; - sub = R_PointInSubsector (avg.x<poly != NULL) { I_Error ("PO_TranslateToStartSpot: Multiple polyobjs in a single subsector.\n"); } sub->poly = po; + // Reassign the sides of the polyobj to its new sector. + sector_t *sec = P_PointInSector (avg.x << FRACBITS, avg.y << FRACBITS); + for (i = 0; i < po->numsegs; ++i) + { + po->segs[i]->linedef->frontsector = sec; + po->segs[i]->linedef->sidedef[0]->sector = sec; + po->segs[i]->frontsector = sec; + } } //========================================================================== diff --git a/src/r_defs.h b/src/r_defs.h index 623e475c4..7d02fb4eb 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -871,7 +871,7 @@ struct line_t DWORD flags; DWORD activation; // activation type int special; - fixed_t Alpha; // <--- translucency (0-255/255=opaque) + fixed_t Alpha; // <--- translucency (0=invisibile, FRACUNIT=opaque) int id; // <--- same as tag or set with Line_SetIdentification int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width) int firstid, nextid; From 4252cd52adac163247a0b67fecb73080fd7a128f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 03:46:51 +0000 Subject: [PATCH 061/241] - Fixed: Sprites and decals that are drawn with addition must fade to black. SVN r1952 (trunk) --- docs/rh-log.txt | 3 +-- src/r_segs.cpp | 17 ++++++++++++----- src/r_things.cpp | 6 ++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 39b44e19e..e10bcb43d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,8 +1,7 @@ October 29, 2009 +- Fixed: Sprites and decals that are drawn with addition must fade to black. - Make TranslateToStartSpot() set the new sector references for a polyobj's walls so that P_CheckSwitchRange() will work with them. -- Fixed: If P_ActivateLine() failed in P_UseTraverse() it would not play - the *usefail sound. - Fixed: An unspecified save_dir will now save to the program directory on Windows. (Other operating systems already use the user's home directory instead.) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 139167c5b..b654c4779 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2432,14 +2432,21 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // Prepare lighting calclighting = false; + FDynamicColormap *usecolormap = basecolormap; + + // Decals that are added to the scene must fade to black. + if (decal->RenderStyle.BlendOp == STYLEOP_Add && usecolormap->Fade != 0) + { + usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); + } rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep; if (fixedlightlev >= 0) - dc_colormap = basecolormap->Maps + fixedlightlev; + dc_colormap = usecolormap->Maps + fixedlightlev; else if (fixedcolormap != NULL) dc_colormap = fixedcolormap; else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) - dc_colormap = basecolormap->Maps; + dc_colormap = usecolormap->Maps; else calclighting = true; @@ -2486,7 +2493,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { if (calclighting) { // calculate lighting - dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } WallSpriteColumn (R_DrawMaskedColumn); @@ -2497,7 +2504,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { if (calclighting) { // calculate lighting - dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } rt_initcols(); for (int zz = 4; zz; --zz) @@ -2512,7 +2519,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { if (calclighting) { // calculate lighting - dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } WallSpriteColumn (R_DrawMaskedColumn); diff --git a/src/r_things.cpp b/src/r_things.cpp index 5f88793e6..2eb5bdafd 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1432,6 +1432,12 @@ void R_ProjectSprite (AActor *thing, int fakeside) FDynamicColormap *mybasecolormap = basecolormap; + // Sprites that are added to the scene must fade to black. + if (vis->RenderStyle.BlendOp == STYLEOP_Add && mybasecolormap->Fade != 0) + { + mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); + } + if (vis->RenderStyle.Flags & STYLEF_FadeToBlack) { if (invertcolormap) From da3daa07213c9522103e6fc29d04e94dad72e630 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Oct 2009 03:53:00 +0000 Subject: [PATCH 062/241] - Fix incorrect fix from previous commit. SVN r1953 (trunk) --- src/r_segs.cpp | 2 +- src/r_things.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b654c4779..a22b28c67 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2435,7 +2435,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, FDynamicColormap *usecolormap = basecolormap; // Decals that are added to the scene must fade to black. - if (decal->RenderStyle.BlendOp == STYLEOP_Add && usecolormap->Fade != 0) + if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) { usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); } diff --git a/src/r_things.cpp b/src/r_things.cpp index 2eb5bdafd..c03c162ba 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1433,7 +1433,7 @@ void R_ProjectSprite (AActor *thing, int fakeside) FDynamicColormap *mybasecolormap = basecolormap; // Sprites that are added to the scene must fade to black. - if (vis->RenderStyle.BlendOp == STYLEOP_Add && mybasecolormap->Fade != 0) + if (vis->RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) { mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); } From a4f4994e182c30d11fc496dacc9489f43879236f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 30 Oct 2009 07:03:26 +0000 Subject: [PATCH 063/241] - re-fixed polyobject CheckSwitchRange so that it doesn't have to alter the polyobject's linedefs. SVN r1954 (trunk) --- src/p_switch.cpp | 22 ++++++++++++++++++---- src/po_man.cpp | 9 +-------- src/r_defs.h | 1 + 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 25a878884..9865b65c1 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -490,11 +490,25 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) dlu.dy = finesine[user->angle >> ANGLETOFINESHIFT]; inter = P_InterceptVector(&dll, &dlu); - checkx = dll.x + FixedMul(dll.dx, inter); - checky = dll.y + FixedMul(dll.dy, inter); - // one sided line - if (line->sidedef[1] == NULL) + // Polyobjects must test the containing sector, not the one they originate from. + if (line->sidedef[0]->Flags & WALLF_POLYOBJ) + { + // Get a check point slightly inside the polyobject so that this still works + // if the polyobject lies directly on a sector boundary + checkx = dll.x + FixedMul(dll.dx, inter + (FRACUNIT/100)); + checky = dll.y + FixedMul(dll.dy, inter + (FRACUNIT/100)); + front = P_PointInSector(checkx, checky); + } + else + { + checkx = dll.x + FixedMul(dll.dx, inter); + checky = dll.y + FixedMul(dll.dy, inter); + } + + + // one sided line or polyobject + if (line->sidedef[1] == NULL || (line->sidedef[0]->Flags & WALLF_POLYOBJ)) { onesided: fixed_t sectorc = front->ceilingplane.ZatPoint(checkx, checky); diff --git a/src/po_man.cpp b/src/po_man.cpp index 828ea951a..37faf119a 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1545,6 +1545,7 @@ static void TranslateToStartSpot (int tag, int originX, int originY) validcount++; for (i = 0; i < po->numsegs; i++, tempSeg++, tempPt++) { + (*tempSeg)->sidedef->Flags |= WALLF_POLYOBJ; if ((*tempSeg)->linedef->validcount != validcount) { (*tempSeg)->linedef->bbox[BOXTOP] -= deltaY; @@ -1581,14 +1582,6 @@ static void TranslateToStartSpot (int tag, int originX, int originY) I_Error ("PO_TranslateToStartSpot: Multiple polyobjs in a single subsector.\n"); } sub->poly = po; - // Reassign the sides of the polyobj to its new sector. - sector_t *sec = P_PointInSector (avg.x << FRACBITS, avg.y << FRACBITS); - for (i = 0; i < po->numsegs; ++i) - { - po->segs[i]->linedef->frontsector = sec; - po->segs[i]->linedef->sidedef[0]->sector = sec; - po->segs[i]->frontsector = sec; - } } //========================================================================== diff --git a/src/r_defs.h b/src/r_defs.h index 7d02fb4eb..a14a819ce 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -725,6 +725,7 @@ enum WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles. WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side. WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side. + WALLF_POLYOBJ = 64, // This wall belongs to a polyobject. }; struct side_t From 4ebfdac887d5f5d8af1c21ba238841b07cc282ff Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 1 Nov 2009 01:27:33 +0000 Subject: [PATCH 064/241] - Changed all coordinates for DrawTexture() to floating point so that the player sprites will retain the same precision they had when they were rendered as part of the 3D view. (needed for propery alignment of flashes on top of weapon sprites) It worked just fine for D3D, but software rendering was another matter. I consequently did battle with imprecisions in the whole masked texture drawing routines that had previously been partially masked by only drawing on whole pixel boundaries. Particularly, the tops of posts are calculated by multiplying by spryscale, and the texture mapping coordinates are calculated by multiplying by dc_iscale (where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point values, there is a significant variance. For best results, the drawing routines should only use one of these values, but that would mean introducing division into the inner loop. If the division removed the necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it? Or would the divide be slower than the fudging? Or would I be better off doing it like Build and using transparent pixel checks instead, not bothering with skipping transparent areas? For now, I chop off the fractional part of the top coordinate for software drawing, since it was the easiest thing to do (even if it wasn't the most correct thing to do). SVN r1955 (trunk) --- docs/rh-log.txt | 21 + src/g_shared/sbarinfo_display.cpp | 6 +- src/r_things.cpp | 6 +- src/textures/textures.h | 4 + src/v_draw.cpp | 323 +++++++------ src/v_video.h | 52 ++- src/vectors.h | 2 +- src/win32/fb_d3d9.cpp | 46 +- src/win32/win32iface.h | 2 +- zdoom.vcproj | 746 +++++++++++++++--------------- 10 files changed, 657 insertions(+), 551 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e10bcb43d..33919afc8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,24 @@ +October 31, 2009 +- Changed all coordinates for DrawTexture() to floating point so that the + player sprites will retain the same precision they had when they were + rendered as part of the 3D view. (needed for propery alignment of flashes + on top of weapon sprites) It worked just fine for D3D, but software + rendering was another matter. I consequently did battle with imprecisions + in the whole masked texture drawing routines that had previously been + partially masked by only drawing on whole pixel boundaries. Particularly, + the tops of posts are calculated by multiplying by spryscale, and the + texture mapping coordinates are calculated by multiplying by dc_iscale + (where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point + values, there is a significant variance. For best results, the drawing + routines should only use one of these values, but that would mean + introducing division into the inner loop. If the division removed the + necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it? + Or would the divide be slower than the fudging? Or would I be better off + doing it like Build and using transparent pixel checks instead, not + bothering with skipping transparent areas? For now, I chop off the + fractional part of the top coordinate for software drawing, since it was + the easiest thing to do (even if it wasn't the most correct thing to do). + October 29, 2009 - Fixed: Sprites and decals that are drawn with addition must fade to black. - Make TranslateToStartSpot() set the new sector references for a polyobj's diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 77c52c60f..0a986fbbb 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -960,7 +960,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a h = fg->GetScaledHeight() << FRACBITS; if (Scaled) { - screen->VirtualToRealCoords(x, y, w, h, 320, 200, true); + screen->VirtualToRealCoordsFixed(x, y, w, h, 320, 200, true); } x >>= FRACBITS; y >>= FRACBITS; @@ -1018,7 +1018,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a ch = (fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2) << FRACBITS; if (Scaled) { - screen->VirtualToRealCoords(cx, cy, cw, ch, 320, 200, true); + screen->VirtualToRealCoordsFixed(cx, cy, cw, ch, 320, 200, true); } cx >>= FRACBITS; cy >>= FRACBITS; @@ -1480,7 +1480,7 @@ void DSBarInfo::DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoo fixed_t fw = texture->GetScaledWidth() << FRACBITS; fixed_t fh = texture->GetScaledHeight() << FRACBITS; if(Scaled) - screen->VirtualToRealCoords(fx, fy, fw, fh, 320, 200, true); + screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true); // Round to nearest w = (fw + (FRACUNIT>>1)) >> FRACBITS; h = (fh + (FRACUNIT>>1)) >> FRACBITS; diff --git a/src/r_things.cpp b/src/r_things.cpp index c03c162ba..ea4accfa3 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1848,9 +1848,9 @@ void R_DrawRemainingPlayerSprites() } screen->DrawTexture(vis->pic, viewwindowx + VisPSpritesX1[i], - viewwindowy + viewheight/2 - MulScale32(vis->texturemid, vis->yscale) - 1, - DTA_DestWidth, FixedMul(vis->pic->GetWidth(), vis->xscale), - DTA_DestHeight, FixedMul(vis->pic->GetHeight(), vis->yscale), + viewwindowy + viewheight/2 - (vis->texturemid / 65536.0) * (vis->yscale / 65536.0) - 1, + DTA_DestWidthF, FIXED2FLOAT(vis->pic->GetWidth() * vis->xscale), + DTA_DestHeightF, FIXED2FLOAT(vis->pic->GetHeight() * vis->yscale), DTA_Translation, TranslationToTable(vis->Translation), DTA_FlipX, flip, DTA_TopOffset, 0, diff --git a/src/textures/textures.h b/src/textures/textures.h index 0f595b5cb..b62da46d8 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -178,9 +178,13 @@ public: int GetScaledWidth () { int foo = (Width << 17) / xScale; return (foo >> 1) + (foo & 1); } int GetScaledHeight () { int foo = (Height << 17) / yScale; return (foo >> 1) + (foo & 1); } + double GetScaledWidthDouble () { return (Width * 65536.f) / xScale; } + double GetScaledHeightDouble () { return (Height * 65536.f) / yScale; } int GetScaledLeftOffset () { int foo = (LeftOffset << 17) / xScale; return (foo >> 1) + (foo & 1); } int GetScaledTopOffset () { int foo = (TopOffset << 17) / yScale; return (foo >> 1) + (foo & 1); } + double GetScaledLeftOffsetDouble() { return (LeftOffset * 65536.f) / xScale; } + double GetScaledTopOffsetDouble() { return (TopOffset * 65536.f) / yScale; } virtual void SetFrontSkyLayer(); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 05cd73c5c..7c05d9042 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -89,14 +89,14 @@ static int PalFromRGB(uint32 rgb) return LastPal; } -void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x, int y, int tags_first, ...) +void STACK_ARGS DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ...) { va_list tags; va_start(tags, tags_first); DrawTextureV(img, x, y, tags_first, tags); } -void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, va_list tags) +void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, double x, double y, uint32 tag, va_list tags) { FTexture::Span unmaskedSpan[2]; const FTexture::Span **spanptr, *spans; @@ -154,8 +154,8 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v BYTE *destorgsave = dc_destorg; dc_destorg = screen->GetBuffer(); - fixed_t x0 = parms.x - Scale (parms.left, parms.destwidth, parms.texwidth); - fixed_t y0 = parms.y - Scale (parms.top, parms.destheight, parms.texheight); + double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth; + double y0 = parms.y - parms.top * parms.destheight / parms.texheight; if (mode != DontDraw) { @@ -174,31 +174,43 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v fixed_t centeryback = centeryfrac; centeryfrac = 0; - sprtopscreen = y0; - spryscale = parms.destheight / img->GetHeight(); + sprtopscreen = FLOAT2FIXED(y0); + // There is not enough precision in the drawing routines to keep the full + // precision for y0. :( + sprtopscreen &= ~(FRACUNIT - 1); + double yscale = parms.destheight / img->GetHeight(); + double iyscale = 1 / yscale; + + spryscale = FLOAT2FIXED(yscale); + +#if 0 // Fix precision errors that are noticeable at some resolutions - if (((y0 + parms.destheight) >> FRACBITS) > ((y0 + spryscale * img->GetHeight()) >> FRACBITS)) + if ((y0 + parms.destheight) > (y0 + yscale * img->GetHeight())) { spryscale++; } +#endif sprflipvert = false; - dc_iscale = 0xffffffffu / (unsigned)spryscale; - dc_texturemid = FixedMul (-y0, dc_iscale); + //dc_iscale = FLOAT2FIXED(iyscale); + //dc_texturemid = FLOAT2FIXED((-y0) * iyscale); + //dc_iscale = 0xffffffffu / (unsigned)spryscale; + dc_iscale = DivScale32(1, spryscale); + dc_texturemid = FixedMul(-sprtopscreen, dc_iscale) + FixedMul(centeryfrac-FRACUNIT, dc_iscale); fixed_t frac = 0; - fixed_t xiscale = DivScale32 (img->GetWidth(), parms.destwidth); - int x2 = (x0 + parms.destwidth) >> FRACBITS; + double xiscale = parms.texwidth / parms.destwidth; + double x2 = x0 + parms.destwidth; if (bottomclipper[0] != parms.dclip) { - clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip); + clearbufshort(bottomclipper, screen->GetWidth(), (short)parms.dclip); } if (parms.uclip != 0) { if (topclipper[0] != parms.uclip) { - clearbufshort (topclipper, screen->GetWidth(), (short)parms.uclip); + clearbufshort(topclipper, screen->GetWidth(), (short)parms.uclip); } mceilingclip = topclipper; } @@ -214,48 +226,53 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v xiscale = -xiscale; } - dc_x = x0 >> FRACBITS; if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { - fixed_t xscale = parms.destwidth / parms.texwidth; - dc_x += (parms.windowleft * xscale) >> FRACBITS; - frac += parms.windowleft << FRACBITS; - x2 -= ((parms.texwidth - parms.windowright) * xscale) >> FRACBITS; + double xscale = parms.destwidth / parms.texwidth; + x0 += parms.windowleft * xscale; + frac += FLOAT2FIXED(parms.windowleft); + x2 -= (parms.texwidth - parms.windowright) * xscale; } - if (dc_x < parms.lclip) + if (x0 < parms.lclip) { - frac += (parms.lclip - dc_x) * xiscale; - dc_x = parms.lclip; + frac += FLOAT2FIXED((parms.lclip - x0) * xiscale); + x0 = parms.lclip; } if (x2 > parms.rclip) { x2 = parms.rclip; } - if (parms.destheight < 32*FRACUNIT) + // Drawing short output ought to fit in the data cache well enough + // if we draw one column at a time, so do that, since it's simpler. + if (parms.destheight < 32 || (parms.dclip - parms.uclip) < 32) { mode = DoDraw0; } + dc_x = int(x0); + int x2_i = int(x2); + fixed_t xiscale_i = FLOAT2FIXED(xiscale); + if (mode == DoDraw0) { // One column at a time stop4 = dc_x; } - else // DoDraw1 + else // DoDraw1` { // Up to four columns at a time - stop4 = x2 & ~3; + stop4 = x2_i & ~3; } - if (dc_x < x2) + if (dc_x < x2_i) { while ((dc_x < stop4) && (dc_x & 3)) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumn (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumn(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } while (dc_x < stop4) @@ -263,20 +280,20 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v rt_initcols(); for (int zz = 4; zz; --zz) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumnHoriz (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumnHoriz(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } - rt_draw4cols (dc_x - 4); + rt_draw4cols(dc_x - 4); } - while (dc_x < x2) + while (dc_x < x2_i) { - pixels = img->GetColumn (frac >> FRACBITS, spanptr); - R_DrawMaskedColumn (pixels, spans); + pixels = img->GetColumn(frac >> FRACBITS, spanptr); + R_DrawMaskedColumn(pixels, spans); dc_x++; - frac += xiscale; + frac += xiscale_i; } } centeryfrac = centeryback; @@ -287,11 +304,11 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v if (ticdup != 0 && menuactive == MENU_Off) { - NetUpdate (); + NetUpdate(); } } -bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const +bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const { INTBOOL boolval; int intval; @@ -313,8 +330,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l virtBottom = false; - parms->texwidth = img->GetScaledWidth(); - parms->texheight = img->GetScaledHeight(); + parms->texwidth = img->GetScaledWidthDouble(); + parms->texheight = img->GetScaledHeightDouble(); parms->windowleft = 0; parms->windowright = parms->texwidth; @@ -322,8 +339,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->uclip = 0; parms->lclip = 0; parms->rclip = this->GetWidth(); - parms->destwidth = parms->windowright << FRACBITS; - parms->destheight = parms->texheight << FRACBITS; + parms->destwidth = parms->windowright; + parms->destheight = parms->texheight; parms->top = img->GetScaledTopOffset(); parms->left = img->GetScaledLeftOffset(); parms->alpha = FRACUNIT; @@ -344,10 +361,12 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l parms->specialcolormap = NULL; parms->colormapstyle = NULL; - parms->x = x << FRACBITS; - parms->y = y << FRACBITS; + parms->x = x; + parms->y = y; - // Parse the tag list for attributes + // Parse the tag list for attributes. (For floating point attributes, + // consider that the C ABI dictates that all floats be promoted to + // doubles when passed as function arguments.) while (tag != TAG_DONE) { va_list *more_p; @@ -357,11 +376,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l { case TAG_IGNORE: default: - data = va_arg (tags, DWORD); + data = va_arg(tags, DWORD); break; case TAG_MORE: - more_p = va_arg (tags, va_list *); + more_p = va_arg(tags, va_list *); va_end (tags); #ifndef NO_VA_COPY va_copy (tags, *more_p); @@ -371,35 +390,43 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_DestWidth: - parms->destwidth = va_arg (tags, int) << FRACBITS; + parms->destwidth = va_arg(tags, int); + break; + + case DTA_DestWidthF: + parms->destwidth = va_arg(tags, double); break; case DTA_DestHeight: - parms->destheight = va_arg (tags, int) << FRACBITS; + parms->destheight = va_arg(tags, int); + break; + + case DTA_DestHeightF: + parms->destheight = va_arg(tags, double); break; case DTA_Clean: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->x = (parms->x - 160*FRACUNIT) * CleanXfac + (Width * (FRACUNIT/2)); - parms->y = (parms->y - 100*FRACUNIT) * CleanYfac + (Height * (FRACUNIT/2)); - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5); + parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5); + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } break; case DTA_CleanNoMove: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } break; case DTA_320x200: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->virtWidth = 320; @@ -408,7 +435,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_Bottom320x200: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->virtWidth = 320; @@ -421,99 +448,123 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l { bool xright = parms->x < 0; bool ybot = parms->y < 0; - intval = va_arg (tags, int); + intval = va_arg(tags, int); if (hud_scale) { parms->x *= CleanXfac; if (intval == HUD_HorizCenter) - parms->x += Width * FRACUNIT / 2; + parms->x += Width * 0.5; else if (xright) - parms->x = Width * FRACUNIT + parms->x; + parms->x = Width + parms->x; parms->y *= CleanYfac; if (ybot) - parms->y = Height * FRACUNIT + parms->y; - parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT; - parms->destheight = parms->texheight * CleanYfac * FRACUNIT; + parms->y = Height + parms->y; + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; } else { if (intval == HUD_HorizCenter) - parms->x += Width * FRACUNIT / 2; + parms->x += Width * 0.5; else if (xright) - parms->x = Width * FRACUNIT + parms->x; + parms->x = Width + parms->x; if (ybot) - parms->y = Height * FRACUNIT + parms->y; + parms->y = Height + parms->y; } } break; case DTA_VirtualWidth: - parms->virtWidth = va_arg (tags, int); + parms->virtWidth = va_arg(tags, int); + break; + + case DTA_VirtualWidthF: + parms->virtWidth = va_arg(tags, double); break; case DTA_VirtualHeight: - parms->virtHeight = va_arg (tags, int); + parms->virtHeight = va_arg(tags, int); + break; + + case DTA_VirtualHeightF: + parms->virtHeight = va_arg(tags, double); break; case DTA_Alpha: - parms->alpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + parms->alpha = MIN(FRACUNIT, va_arg (tags, fixed_t)); break; case DTA_AlphaChannel: - parms->alphaChannel = va_arg (tags, INTBOOL); + parms->alphaChannel = va_arg(tags, INTBOOL); break; case DTA_FillColor: - parms->fillcolor = va_arg (tags, int); + parms->fillcolor = va_arg(tags, uint32); break; case DTA_Translation: - parms->remap = va_arg (tags, FRemapTable *); + parms->remap = va_arg(tags, FRemapTable *); break; case DTA_ColorOverlay: - parms->colorOverlay = va_arg (tags, DWORD); + parms->colorOverlay = va_arg(tags, DWORD); break; case DTA_FlipX: - parms->flipX = va_arg (tags, INTBOOL); + parms->flipX = va_arg(tags, INTBOOL); break; case DTA_TopOffset: - parms->top = va_arg (tags, int); + parms->top = va_arg(tags, int); + break; + + case DTA_TopOffsetF: + parms->top = va_arg(tags, double); break; case DTA_LeftOffset: - parms->left = va_arg (tags, int); + parms->left = va_arg(tags, int); + break; + + case DTA_LeftOffsetF: + parms->left = va_arg(tags, double); break; case DTA_CenterOffset: - if (va_arg (tags, int)) + if (va_arg(tags, int)) { - parms->left = parms->texwidth / 2; - parms->top = parms->texheight / 2; + parms->left = parms->texwidth * 0.5; + parms->top = parms->texheight * 0.5; } break; case DTA_CenterBottomOffset: - if (va_arg (tags, int)) + if (va_arg(tags, int)) { - parms->left = parms->texwidth / 2; + parms->left = parms->texwidth * 0.5; parms->top = parms->texheight; } break; case DTA_WindowLeft: - parms->windowleft = va_arg (tags, int); + parms->windowleft = va_arg(tags, int); + break; + + case DTA_WindowLeftF: + parms->windowleft = va_arg(tags, double); break; case DTA_WindowRight: - parms->windowright = va_arg (tags, int); + parms->windowright = va_arg(tags, int); + break; + + case DTA_WindowRightF: + parms->windowright = va_arg(tags, double); break; case DTA_ClipTop: - parms->uclip = va_arg (tags, int); + parms->uclip = va_arg(tags, int); if (parms->uclip < 0) { parms->uclip = 0; @@ -521,7 +572,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipBottom: - parms->dclip = va_arg (tags, int); + parms->dclip = va_arg(tags, int); if (parms->dclip > this->GetHeight()) { parms->dclip = this->GetHeight(); @@ -529,7 +580,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipLeft: - parms->lclip = va_arg (tags, int); + parms->lclip = va_arg(tags, int); if (parms->lclip < 0) { parms->lclip = 0; @@ -537,7 +588,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ClipRight: - parms->rclip = va_arg (tags, int); + parms->rclip = va_arg(tags, int); if (parms->rclip > this->GetWidth()) { parms->rclip = this->GetWidth(); @@ -545,15 +596,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_ShadowAlpha: - parms->shadowAlpha = MIN (FRACUNIT, va_arg (tags, fixed_t)); + parms->shadowAlpha = MIN(FRACUNIT, va_arg (tags, fixed_t)); break; case DTA_ShadowColor: - parms->shadowColor = va_arg (tags, int); + parms->shadowColor = va_arg(tags, int); break; case DTA_Shadow: - boolval = va_arg (tags, INTBOOL); + boolval = va_arg(tags, INTBOOL); if (boolval) { parms->shadowAlpha = FRACUNIT/2; @@ -566,32 +617,32 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l break; case DTA_Masked: - parms->masked = va_arg (tags, INTBOOL); + parms->masked = va_arg(tags, INTBOOL); break; case DTA_BilinearFilter: - parms->bilinear = va_arg (tags, INTBOOL); + parms->bilinear = va_arg(tags, INTBOOL); break; case DTA_KeepRatio: // I think this is a terribly misleading name, since it actually turns // *off* aspect ratio correction. - parms->keepratio = va_arg (tags, INTBOOL); + parms->keepratio = va_arg(tags, INTBOOL); break; case DTA_RenderStyle: - parms->style.AsDWORD = va_arg (tags, DWORD); + parms->style.AsDWORD = va_arg(tags, DWORD); break; case DTA_SpecialColormap: - parms->specialcolormap = va_arg (tags, FSpecialColormap *); + parms->specialcolormap = va_arg(tags, FSpecialColormap *); break; case DTA_ColormapStyle: - parms->colormapstyle = va_arg (tags, FColormapStyle *); + parms->colormapstyle = va_arg(tags, FColormapStyle *); break; } - tag = va_arg (tags, DWORD); + tag = va_arg(tags, DWORD); } va_end (tags); @@ -645,66 +696,72 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l return true; } -void DCanvas::VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, - int vwidth, int vheight, bool vbottom, bool handleaspect) const +void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, + double vwidth, double vheight, bool vbottom, bool handleaspect) const { int myratio = handleaspect ? CheckRatio (Width, Height) : 0; - int right = x + w; - int bottom = y + h; + double right = x + w; + double bottom = y + h; if (myratio != 0 && myratio != 4) { // The target surface is either 16:9 or 16:10, so expand the // specified virtual size to avoid undesired stretching of the // image. Does not handle non-4:3 virtual sizes. I'll worry about // those if somebody expresses a desire to use them. - x = Scale(x - vwidth*FRACUNIT/2, - Width*960, - vwidth*BaseRatioSizes[myratio][0]) - + Width*FRACUNIT/2; - w = Scale(right - vwidth*FRACUNIT/2, - Width*960, - vwidth*BaseRatioSizes[myratio][0]) - + Width*FRACUNIT/2 - x; + x = (x - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5; + w = (right - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5 - x; } else { - x = Scale (x, Width, vwidth); - w = Scale (right, Width, vwidth) - x; + x = x * Width / vwidth; + w = right * Width / vwidth - x; } if (myratio == 4) { // The target surface is 5:4 - y = Scale(y - vheight*FRACUNIT/2, - Height*600, - vheight*BaseRatioSizes[myratio][1]) - + Height*FRACUNIT/2; - h = Scale(bottom - vheight*FRACUNIT/2, - Height*600, - vheight*BaseRatioSizes[myratio][1]) - + Height*FRACUNIT/2 - y; + y = (y - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5; + h = (bottom - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5 - y; if (vbottom) { - y += (Height - Height * BaseRatioSizes[myratio][3] / 48) << (FRACBITS - 1); + y += (Height - Height * BaseRatioSizes[myratio][3] / 48.0) * 0.5; } } else { - y = Scale (y, Height, vheight); - h = Scale (bottom, Height, vheight) - y; + y = y * Height / vheight; + h = bottom * Height / vheight - y; } } +void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, + int vwidth, int vheight, bool vbottom, bool handleaspect) const +{ + double dx, dy, dw, dh; + + dx = FIXED2FLOAT(x); + dy = FIXED2FLOAT(y); + dw = FIXED2FLOAT(w); + dh = FIXED2FLOAT(h); + VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); + x = FLOAT2FIXED(dx); + y = FLOAT2FIXED(dy); + w = FLOAT2FIXED(dw); + h = FLOAT2FIXED(dh); +} + void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom, bool handleaspect) const { - x <<= FRACBITS; - y <<= FRACBITS; - w <<= FRACBITS; - h <<= FRACBITS; - VirtualToRealCoords(x, y, w, h, vwidth, vheight, vbottom, handleaspect); - x >>= FRACBITS; - y >>= FRACBITS; - w >>= FRACBITS; - h >>= FRACBITS; + double dx, dy, dw, dh; + + dx = x; + dy = y; + dw = w; + dh = h; + VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); + x = int(dx + 0.5); + y = int(dy + 0.5); + w = int(dx + dw + 0.5) - x; + h = int(dy + dh + 0.5) - y; } void DCanvas::FillBorder (FTexture *img) diff --git a/src/v_video.h b/src/v_video.h index 3109901bb..394ba319e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -87,8 +87,8 @@ enum DTA_VirtualHeight, // pretend the canvas is this tall DTA_TopOffset, // override texture's top offset DTA_LeftOffset, // override texture's left offset - DTA_CenterOffset, // override texture's left and top offsets and set them for the texture's middle - DTA_CenterBottomOffset,// override texture's left and top offsets and set them for the texture's bottom middle + DTA_CenterOffset, // bool: override texture's left and top offsets and set them for the texture's middle + DTA_CenterBottomOffset,// bool: override texture's left and top offsets and set them for the texture's bottom middle DTA_WindowLeft, // don't draw anything left of this column (on source, not dest) DTA_WindowRight, // don't draw anything at or to the right of this column (on source, not dest) DTA_ClipTop, // don't draw anything above this row (on dest, not source) @@ -104,6 +104,16 @@ enum DTA_SpecialColormap,// pointer to FSpecialColormapParameters (likely to be forever hardware-only) DTA_ColormapStyle, // pointer to FColormapStyle (hardware-only) + // floating point duplicates of some of the above: + DTA_DestWidthF, + DTA_DestHeightF, + DTA_TopOffsetF, + DTA_LeftOffsetF, + DTA_VirtualWidthF, + DTA_VirtualHeightF, + DTA_WindowLeftF, + DTA_WindowRightF, + // For DrawText calls: DTA_TextLen, // stop after this many characters, even if \0 not hit DTA_CellX, // horizontal size of character cell @@ -188,9 +198,12 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing - void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); + void STACK_ARGS DrawTexture (FTexture *img, double x, double y, int tags, ...); void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays - void VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; + void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; + + // Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. + void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; // 2D Text drawing @@ -199,21 +212,23 @@ public: struct DrawParms { - fixed_t x, y; - int texwidth; - int texheight; - int windowleft; - int windowright; + double x, y; + double texwidth; + double texheight; + double destwidth; + double destheight; + double virtWidth; + double virtHeight; + double windowleft; + double windowright; int dclip; int uclip; int lclip; int rclip; - fixed_t destwidth; - fixed_t destheight; - int top; - int left; + double top; + double left; fixed_t alpha; - int fillcolor; + uint32 fillcolor; FRemapTable *remap; const BYTE *translation; DWORD colorOverlay; @@ -221,8 +236,6 @@ public: INTBOOL flipX; fixed_t shadowAlpha; int shadowColor; - int virtWidth; - int virtHeight; INTBOOL keepratio; INTBOOL masked; INTBOOL bilinear; @@ -239,8 +252,8 @@ protected: int LockCount; bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; - virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); - bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const; + virtual void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags); + bool ParseDrawTextureTags (FTexture *img, double x, double y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const; DCanvas() {} @@ -339,7 +352,7 @@ public: // Tells the device to recreate itself with the new setting from vid_refreshrate. virtual void NewRefreshRate (); - // Set the rect defining the area effected by blending. + // Set the rect defining the area affected by blending. virtual void SetBlendingRect (int x1, int y1, int x2, int y2); // render 3D view @@ -470,6 +483,7 @@ extern "C" void ASM_PatchPitch (void); #endif int CheckRatio (int width, int height); +static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } extern const int BaseRatioSizes[5][4]; diff --git a/src/vectors.h b/src/vectors.h index f3b154aa2..ea11ab611 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1231,6 +1231,6 @@ typedef TMatrix3x3 FMatrix3x3; typedef TAngle FAngle; #define FLOAT2FIXED(f) fixed_t((f) * float(65536)) -#define FIXED2FLOAT(f) (float(f) / float(65536)) +#define FIXED2FLOAT(f) ((f) / float(65536)) #endif diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index a776144ea..7e9197b0e 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2734,7 +2734,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32 color) // //========================================================================== -void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_first, va_list tags) +void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, double x, double y, uint32 tags_first, va_list tags) { if (In2D < 2) { @@ -2759,17 +2759,17 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi CheckQuadBatch(); - float xscale = float(parms.destwidth) / parms.texwidth / 65536.f; - float yscale = float(parms.destheight) / parms.texheight / 65536.f; - float x0 = float(parms.x) / 65536.f - float(parms.left) * xscale; - float y0 = float(parms.y) / 65536.f - float(parms.top) * yscale; - float x1 = x0 + float(parms.destwidth) / 65536.f; - float y1 = y0 + float(parms.destheight) / 65536.f; + double xscale = parms.destwidth / parms.texwidth; + double yscale = parms.destheight / parms.texheight; + double x0 = parms.x - parms.left * xscale; + double y0 = parms.y - parms.top * yscale; + double x1 = x0 + parms.destwidth; + double y1 = y0 + parms.destheight; float u0 = tex->Box->Left; float v0 = tex->Box->Top; float u1 = tex->Box->Right; float v1 = tex->Box->Bottom; - float uscale = 1.f / tex->Box->Owner->Width; + double uscale = 1.f / tex->Box->Owner->Width; bool scissoring = false; if (parms.flipX) @@ -2779,9 +2779,9 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { x0 += parms.windowleft * xscale; - u0 += parms.windowleft * uscale; + u0 = float(u0 + parms.windowleft * uscale); x1 -= (parms.texwidth - parms.windowright) * xscale; - u1 -= (parms.texwidth - parms.windowright) * uscale; + u1 = float(u1 - (parms.texwidth - parms.windowright) * uscale); } #if 0 float vscale = 1.f / tex->Box->Owner->Height / yscale; @@ -2841,6 +2841,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi float yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset; +#if 0 // Coordinates are truncated to integers, because that's effectively // what the software renderer does. The hardware will instead round // to nearest, it seems. @@ -2848,11 +2849,18 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi y0 = floorf(y0) - yoffs; x1 = floorf(x1) - 0.5f; y1 = floorf(y1) - yoffs; +#else + x0 = x0 - 0.5f; + y0 = y0 - yoffs; + x1 = x1 - 0.5f; + y1 = y1 - yoffs; +#endif FBVERTEX *vert = &VertexData[VertexPos]; - vert[0].x = x0; - vert[0].y = y0; + // Fill the vertex buffer. + vert[0].x = float(x0); + vert[0].y = float(y0); vert[0].z = 0; vert[0].rhw = 1; vert[0].color0 = color0; @@ -2860,8 +2868,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[0].tu = u0; vert[0].tv = v0; - vert[1].x = x1; - vert[1].y = y0; + vert[1].x = float(x1); + vert[1].y = float(y0); vert[1].z = 0; vert[1].rhw = 1; vert[1].color0 = color0; @@ -2869,8 +2877,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[1].tu = u1; vert[1].tv = v0; - vert[2].x = x1; - vert[2].y = y1; + vert[2].x = float(x1); + vert[2].y = float(y1); vert[2].z = 0; vert[2].rhw = 1; vert[2].color0 = color0; @@ -2878,8 +2886,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[2].tu = u1; vert[2].tv = v1; - vert[3].x = x0; - vert[3].y = y1; + vert[3].x = float(x0); + vert[3].y = float(y1); vert[3].z = 0; vert[3].rhw = 1; vert[3].color0 = color0; @@ -2887,6 +2895,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi vert[3].tu = u0; vert[3].tv = v1; + // Fill the vertex index buffer. IndexData[IndexPos ] = VertexPos; IndexData[IndexPos + 1] = VertexPos + 1; IndexData[IndexPos + 2] = VertexPos + 2; @@ -2894,6 +2903,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi IndexData[IndexPos + 4] = VertexPos + 2; IndexData[IndexPos + 5] = VertexPos + 3; + // Batch the quad. QuadBatchPos++; VertexPos += 4; IndexPos += 6; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 6c7c066b7..6cce6afe1 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -248,7 +248,7 @@ public: void DrawBlendingRect (); FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping); FNativePalette *CreatePalette (FRemapTable *remap); - void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags); + void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags); void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color); void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin); diff --git a/zdoom.vcproj b/zdoom.vcproj index 2a33a2c6b..681c2ce69 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1868,6 +1860,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2057,6 +2057,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2067,14 +2075,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5343,14 +5351,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5629,7 +5629,7 @@ /> Date: Sun, 1 Nov 2009 01:35:11 +0000 Subject: [PATCH 065/241] - Shift player sprites down half a pixel. Interestingly, this makes vertical scaling much closer between software and hardware. SVN r1956 (trunk) --- src/r_things.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.cpp b/src/r_things.cpp index ea4accfa3..155c84353 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1848,7 +1848,7 @@ void R_DrawRemainingPlayerSprites() } screen->DrawTexture(vis->pic, viewwindowx + VisPSpritesX1[i], - viewwindowy + viewheight/2 - (vis->texturemid / 65536.0) * (vis->yscale / 65536.0) - 1, + viewwindowy + viewheight/2 - (vis->texturemid / 65536.0) * (vis->yscale / 65536.0) - 0.5, DTA_DestWidthF, FIXED2FLOAT(vis->pic->GetWidth() * vis->xscale), DTA_DestHeightF, FIXED2FLOAT(vis->pic->GetHeight() * vis->yscale), DTA_Translation, TranslationToTable(vis->Translation), From adbc9771b7154933fc3f05dedd8aed60f67e00f9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Nov 2009 06:45:47 +0000 Subject: [PATCH 066/241] - yet another GCC compile fix. SVN r1957 (trunk) --- src/r_segs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index a22b28c67..2a291277c 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2188,6 +2188,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, int needrepeat = 0; sector_t *front, *back; bool calclighting; + FDynamicColormap *usecolormap; if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) return; @@ -2432,7 +2433,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // Prepare lighting calclighting = false; - FDynamicColormap *usecolormap = basecolormap; + usecolormap = basecolormap; // Decals that are added to the scene must fade to black. if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) From 358b2421ad0191d88f1a38f9678dbe6ece776074 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 2 Nov 2009 01:02:23 +0000 Subject: [PATCH 067/241] - Fixed: Decals would not use the shading colormap anymore. SVN r1958 (trunk) --- src/r_segs.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 2a291277c..a31ca41dd 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2434,11 +2434,13 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // Prepare lighting calclighting = false; usecolormap = basecolormap; + bool rereadcolormap = true; // Decals that are added to the scene must fade to black. if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) { usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); + rereadcolormap = false; } rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep; @@ -2473,6 +2475,12 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, mode = R_SetPatchStyle (decal->RenderStyle, decal->Alpha, decal->Translation, decal->AlphaColor); + // R_SetPatchStyle can modify basecolormap. + if (rereadcolormap) + { + usecolormap = basecolormap; + } + if (mode == DontDraw) { needrepeat = 0; From a02e8c0b06a837ca2ceb2cc716528021f6dbc890 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 2 Nov 2009 17:02:12 +0000 Subject: [PATCH 068/241] - GCC fix of r_segs.cpp - again... SVN r1959 (trunk) --- src/r_segs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index a31ca41dd..8782f5631 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2188,6 +2188,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, int needrepeat = 0; sector_t *front, *back; bool calclighting; + bool rereadcolormap; FDynamicColormap *usecolormap; if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid()) @@ -2434,7 +2435,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, // Prepare lighting calclighting = false; usecolormap = basecolormap; - bool rereadcolormap = true; + rereadcolormap = true; // Decals that are added to the scene must fade to black. if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) From f1738b0e030df37d905c05e1cc3c33bef900406f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 4 Nov 2009 01:24:00 +0000 Subject: [PATCH 069/241] - Added a command line option -warpwipe to perform the screen wipe if you start with -warp or +map. SVN r1960 (trunk) --- docs/rh-log.txt | 4 ++++ src/d_main.cpp | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 33919afc8..a3492e313 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 3, 2009 +- Added a command line option -warpwipe to perform the screen wipe if you + start with -warp or +map. + October 31, 2009 - Changed all coordinates for DrawTexture() to floating point so that the player sprites will retain the same precision they had when they were diff --git a/src/d_main.cpp b/src/d_main.cpp index 801262790..cad92cce6 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2071,7 +2071,10 @@ void D_DoomMain (void) if (autostart || netgame) { // Do not do any screenwipes when autostarting a game. - NoWipe = 35; + if (!Args->CheckParm("-warpwipe")) + { + NoWipe = TICRATE; + } CheckWarpTransMap (startmap, true); if (demorecording) G_BeginRecording (startmap); From fb74d9b1ecc264f5d1b986c52a4c5c9765b96084 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 4 Nov 2009 02:07:39 +0000 Subject: [PATCH 070/241] - Added virtual status and audibility to the noise debug display. SVN r1961 (trunk) --- docs/rh-log.txt | 1 + src/s_sound.cpp | 29 +++++++++++++++++++++++++++-- src/s_sound.h | 1 + src/sound/fmodsound.cpp | 34 +++++++++++++++++++++++++++++----- src/sound/fmodsound.h | 3 +++ src/sound/i_sound.cpp | 6 ++++++ src/sound/i_sound.h | 4 ++++ src/sound/i_soundinternal.h | 1 - 8 files changed, 71 insertions(+), 8 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a3492e313..fdb2dcbd1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 3, 2009 +- Added virtual status and audibility to the noise debug display. - Added a command line option -warpwipe to perform the screen wipe if you start with -warp or +map. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index e294b6efb..ffacab9e6 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -164,6 +164,7 @@ void S_NoiseDebug (void) screen->DrawText (SmallFont, CR_GOLD, 300, y, "chan", TAG_DONE); screen->DrawText (SmallFont, CR_GOLD, 340, y, "pri", TAG_DONE); screen->DrawText (SmallFont, CR_GOLD, 380, y, "flags", TAG_DONE); + screen->DrawText (SmallFont, CR_GOLD, 460, y, "aud", TAG_DONE); y += 8; if (Channels == NULL) @@ -236,7 +237,7 @@ void S_NoiseDebug (void) screen->DrawText(SmallFont, color, 340, y, temp, TAG_DONE); // Flags - mysnprintf(temp, countof(temp), "%s3%sZ%sU%sM%sN%sA%sL%sE", + mysnprintf(temp, countof(temp), "%s3%sZ%sU%sM%sN%sA%sL%sE%sV", (chan->ChanFlags & CHAN_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, (chan->ChanFlags & CHAN_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, (chan->ChanFlags & CHAN_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, @@ -244,9 +245,14 @@ void S_NoiseDebug (void) (chan->ChanFlags & CHAN_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, (chan->ChanFlags & CHAN_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, (chan->ChanFlags & CHAN_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, - (chan->ChanFlags & CHAN_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK); + (chan->ChanFlags & CHAN_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHAN_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK); screen->DrawText(SmallFont, color, 380, y, temp, TAG_DONE); + // Audibility + mysnprintf(temp, countof(temp), "%.2g", GSnd->GetAudibility(chan)); + screen->DrawText(SmallFont, color, 460, y, temp, TAG_DONE); + y += 8; if (chan->PrevChan == &Channels) { @@ -2003,6 +2009,25 @@ void S_ChannelEnded(FISoundChannel *ichan) } } +//========================================================================== +// +// S_ChannelVirtualChanged (callback for sound interface code) +// +//========================================================================== + +void S_ChannelVirtualChanged(FISoundChannel *ichan, bool is_virtual) +{ + FSoundChan *schan = static_cast(ichan); + if (is_virtual) + { + schan->ChanFlags |= CHAN_VIRTUAL; + } + else + { + schan->ChanFlags &= ~CHAN_VIRTUAL; + } +} + //========================================================================== // // S_StopChannel diff --git a/src/s_sound.h b/src/s_sound.h index ad0f3c61b..638baf5e5 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -262,6 +262,7 @@ void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, floa #define CHAN_FORGETTABLE 4 // internal: Forget channel data when sound stops. #define CHAN_JUSTSTARTED 512 // internal: Sound has not been updated yet. #define CHAN_ABSTIME 1024// internal: Start time is absolute and does not depend on current time. +#define CHAN_VIRTUAL 2048// internal: Channel is currently virtual // sound attenuation values #define ATTN_NONE 0.f // full volume the entire level diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 2a1ad2b9c..724d701fe 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1846,6 +1846,27 @@ unsigned int FMODSoundRenderer::GetPosition(FISoundChannel *chan) return pos; } +//========================================================================== +// +// FMODSoundRenderer :: GetAudibility +// +// Returns the audible volume of the channel, after rollof and any other +// factors are applied. +// +//========================================================================== + +float FMODSoundRenderer::GetAudibility(FISoundChannel *chan) +{ + float aud; + + if (chan == NULL || chan->SysChannel == NULL) + { + return 0; + } + ((FMOD::Channel *)chan->SysChannel)->getAudibility(&aud); + return aud; +} + //========================================================================== // // FMODSoundRenderer :: SetSfxPaused @@ -2284,16 +2305,19 @@ unsigned int FMODSoundRenderer::GetSampleLength(SoundHandle sfx) FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelCallback (FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *data1, void *data2) { - if (type != FMOD_CHANNEL_CALLBACKTYPE_END) - { - return FMOD_OK; - } FMOD::Channel *chan = (FMOD::Channel *)channel; FISoundChannel *schan; if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) { - S_ChannelEnded(schan); + if (type == FMOD_CHANNEL_CALLBACKTYPE_END) + { + S_ChannelEnded(schan); + } + else if (type == FMOD_CHANNEL_CALLBACKTYPE_VIRTUALVOICE) + { + S_ChannelVirtualChanged(schan, data1 != 0); + } } return FMOD_OK; } diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 5febda3e2..78ba8aa86 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -36,6 +36,9 @@ public: // Returns position of sound on this channel, in samples. unsigned int GetPosition(FISoundChannel *chan); + // Gets a channel's audibility (real volume). + float GetAudibility(FISoundChannel *chan); + // Synchronizes following sound startups. void Sync (bool sync); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 3370bd92f..c4b0c63e0 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -175,6 +175,12 @@ public: return 0; } + // Gets a channel's audibility (real volume). + float GetAudibility(FISoundChannel *chan) + { + return 0; + } + // Synchronizes following sound startups. void Sync (bool sync) { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index b402fa3d2..1ff535d93 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -112,6 +112,9 @@ public: // Returns position of sound on this channel, in samples. virtual unsigned int GetPosition(FISoundChannel *chan) = 0; + // Gets a channel's audibility (real volume). + virtual float GetAudibility(FISoundChannel *chan) = 0; + // Synchronizes following sound startups. virtual void Sync (bool sync) = 0; @@ -142,6 +145,7 @@ void I_InitSound (); void I_ShutdownSound (); void S_ChannelEnded(FISoundChannel *schan); +void S_ChannelVirtualChanged(FISoundChannel *schan, bool is_virtual); float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic); FISoundChannel *S_GetChannel(void *syschan); diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index 9f6fe6d87..157c9c87b 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -96,7 +96,6 @@ struct FISoundChannel // callback that can't be passed a sound channel pointer FRolloffInfo Rolloff; float DistanceScale; - }; From 704895f9b9629f3249ca1542ee0143e379117a4d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 4 Nov 2009 02:37:05 +0000 Subject: [PATCH 071/241] - Fixed: S_RestartSound() cleared the evicted flag even if the sound was not restarted because it was too close to too many other identical sounds that were already playing. SVN r1962 (trunk) --- docs/rh-log.txt | 3 +++ src/s_sound.cpp | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fdb2dcbd1..b400d677e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ November 3, 2009 +- Fixed: S_RestartSound() cleared the evicted flag even if the sound + was not restarted because it was too close to too many other identical + sounds that were already playing. - Added virtual status and audibility to the noise debug display. - Added a command line option -warpwipe to perform the screen wipe if you start with -warp or +map. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index ffacab9e6..1287873a5 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -250,7 +250,7 @@ void S_NoiseDebug (void) screen->DrawText(SmallFont, color, 380, y, temp, TAG_DONE); // Audibility - mysnprintf(temp, countof(temp), "%.2g", GSnd->GetAudibility(chan)); + mysnprintf(temp, countof(temp), "%.4f", GSnd->GetAudibility(chan)); screen->DrawText(SmallFont, color, 460, y, temp, TAG_DONE); y += 8; @@ -1125,7 +1125,6 @@ void S_RestartSound(FSoundChan *chan) if (chan->ChanFlags & (CHAN_UI|CHAN_NOPAUSE)) startflags |= SNDF_NOPAUSE; if (chan->ChanFlags & CHAN_ABSTIME) startflags |= SNDF_ABSTIME; - chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME); if (chan->ChanFlags & CHAN_IS3D) { FVector3 pos, vel; @@ -1142,11 +1141,13 @@ void S_RestartSound(FSoundChan *chan) SoundListener listener; S_SetListener(listener, players[consoleplayer].camera); + chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME); ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, chan->Priority, pos, vel, chan->EntChannel, startflags, chan); } else { + chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME); ochan = (FSoundChan*)GSnd->StartSound(sfx->data, chan->Volume, chan->Pitch, startflags, chan); } assert(ochan == NULL || ochan == chan); From d8acbf71fa303dc0d0c7964eb9fa0b6edd08881a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Nov 2009 06:56:25 +0000 Subject: [PATCH 072/241] - fixed: The 'new format only' flag for MAPINFO options was never checked. (ZDoom itself doesn't use it yet so it's only relevant for child ports.) SVN r1964 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_mapinfo.cpp | 4 ++++ src/v_video.h | 2 ++ 3 files changed, 10 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b400d677e..88fa5d630 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 5, 2009 (Changes by Graf Zahl) +- fixed: The 'new format only' flag for MAPINFO options was never checked. + (ZDoom itself doesn't use it yet so it's only relevant for child ports.) + November 3, 2009 - Fixed: S_RestartSound() cleared the evicted flag even if the sound was not restarted because it was too close to too many other identical diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bb3449e0a..eeb222361 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1461,6 +1461,10 @@ void FMapInfoParser::ParseMapDefinition(level_info_t &info) { if (sc.Compare(((FMapOptInfo *)(*probe))->name)) { + if (!((FMapOptInfo *)(*probe))->old && format_type != FMT_New) + { + sc.ScriptError("MAPINFO option '%s' requires the new MAPINFO format", sc.String); + } ((FMapOptInfo *)(*probe))->handler(*this, &info); success = true; break; diff --git a/src/v_video.h b/src/v_video.h index 394ba319e..6e6e6c60d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -403,6 +403,8 @@ public: virtual bool WipeDo(int ticks); virtual void WipeCleanup(); + DWORD GetLastFPS() const { return LastCount; } + #ifdef _WIN32 virtual void PaletteChanged () = 0; virtual int QueryNewPalette () = 0; From de8ec46c0626285f40a42e70d1fdfdabde5ea5e6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 8 Nov 2009 02:51:22 +0000 Subject: [PATCH 073/241] - Fixed: R_GetOneSkyColumn() and R_GetTwoSkyColumns are mulscaling an unsigned integer that can use all 32 bits. They must therefore use the unsigned mul instruction rather than the signed imul instruction. - Fixed several signed/unsigned comparison and possibly uninitialized variable warnings flagged by GCC. SVN r1965 (trunk) --- docs/rh-log.txt | 7 + src/basicinlines.h | 280 ++++++++++++++++--------------- src/d_net.cpp | 6 +- src/g_shared/a_randomspawner.cpp | 23 ++- src/gccinlines.h | 32 ++-- src/mscinlines.h | 7 + src/p_buildmap.cpp | 4 +- src/p_map.cpp | 4 +- src/p_spec.cpp | 4 +- src/r_plane.cpp | 12 +- src/sound/fmod_wrap.h | 2 +- src/thingdef/thingdef_data.cpp | 2 +- src/v_draw.cpp | 2 +- src/v_palette.cpp | 2 +- src/win32/fb_d3d9.cpp | 7 +- 15 files changed, 211 insertions(+), 183 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 88fa5d630..88015541e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +November 7, 2009 +- Fixed: R_GetOneSkyColumn() and R_GetTwoSkyColumns are mulscaling an + unsigned integer that can use all 32 bits. They must therefore use + the unsigned mul instruction rather than the signed imul instruction. +- Fixed several signed/unsigned comparison and possibly uninitialized + variable warnings flagged by GCC. + November 5, 2009 (Changes by Graf Zahl) - fixed: The 'new format only' flag for MAPINFO options was never checked. (ZDoom itself doesn't use it yet so it's only relevant for child ports.) diff --git a/src/basicinlines.h b/src/basicinlines.h index 3ec7ea8de..3969a9507 100644 --- a/src/basicinlines.h +++ b/src/basicinlines.h @@ -12,124 +12,126 @@ #endif #ifndef _MSC_VER -#define __forceinline inline +#define static __forceinline inline #endif -__forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) +static __forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) { return (SDWORD)(((SQWORD)a*b)/c); } -__forceinline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) +static __forceinline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) { return (SDWORD)(((SQWORD)a*b)>>c); } -__forceinline SDWORD MulScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 1); } -__forceinline SDWORD MulScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 2); } -__forceinline SDWORD MulScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 3); } -__forceinline SDWORD MulScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 4); } -__forceinline SDWORD MulScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 5); } -__forceinline SDWORD MulScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 6); } -__forceinline SDWORD MulScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 7); } -__forceinline SDWORD MulScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 8); } -__forceinline SDWORD MulScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 9); } -__forceinline SDWORD MulScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 10); } -__forceinline SDWORD MulScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 11); } -__forceinline SDWORD MulScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 12); } -__forceinline SDWORD MulScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 13); } -__forceinline SDWORD MulScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 14); } -__forceinline SDWORD MulScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 15); } -__forceinline SDWORD MulScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 16); } -__forceinline SDWORD MulScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 17); } -__forceinline SDWORD MulScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 18); } -__forceinline SDWORD MulScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 19); } -__forceinline SDWORD MulScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 20); } -__forceinline SDWORD MulScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 21); } -__forceinline SDWORD MulScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 22); } -__forceinline SDWORD MulScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 23); } -__forceinline SDWORD MulScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 24); } -__forceinline SDWORD MulScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 25); } -__forceinline SDWORD MulScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 26); } -__forceinline SDWORD MulScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 27); } -__forceinline SDWORD MulScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 28); } -__forceinline SDWORD MulScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 29); } -__forceinline SDWORD MulScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 30); } -__forceinline SDWORD MulScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 31); } -__forceinline SDWORD MulScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 32); } +static __forceinline SDWORD MulScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 1); } +static __forceinline SDWORD MulScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 2); } +static __forceinline SDWORD MulScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 3); } +static __forceinline SDWORD MulScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 4); } +static __forceinline SDWORD MulScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 5); } +static __forceinline SDWORD MulScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 6); } +static __forceinline SDWORD MulScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 7); } +static __forceinline SDWORD MulScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 8); } +static __forceinline SDWORD MulScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 9); } +static __forceinline SDWORD MulScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 10); } +static __forceinline SDWORD MulScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 11); } +static __forceinline SDWORD MulScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 12); } +static __forceinline SDWORD MulScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 13); } +static __forceinline SDWORD MulScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 14); } +static __forceinline SDWORD MulScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 15); } +static __forceinline SDWORD MulScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 16); } +static __forceinline SDWORD MulScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 17); } +static __forceinline SDWORD MulScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 18); } +static __forceinline SDWORD MulScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 19); } +static __forceinline SDWORD MulScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 20); } +static __forceinline SDWORD MulScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 21); } +static __forceinline SDWORD MulScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 22); } +static __forceinline SDWORD MulScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 23); } +static __forceinline SDWORD MulScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 24); } +static __forceinline SDWORD MulScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 25); } +static __forceinline SDWORD MulScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 26); } +static __forceinline SDWORD MulScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 27); } +static __forceinline SDWORD MulScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 28); } +static __forceinline SDWORD MulScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 29); } +static __forceinline SDWORD MulScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 30); } +static __forceinline SDWORD MulScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 31); } +static __forceinline SDWORD MulScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a * b) >> 32); } -__forceinline SDWORD DMulScale (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD s) +static __forceinline DWORD UMulScale16 (DWORD a, DWORD b) { return (DWORD)(((QWORD)a * b) >> 16); } + +static __forceinline SDWORD DMulScale (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD s) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> s); } -__forceinline SDWORD DMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 1); } -__forceinline SDWORD DMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 2); } -__forceinline SDWORD DMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 3); } -__forceinline SDWORD DMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 4); } -__forceinline SDWORD DMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 5); } -__forceinline SDWORD DMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 6); } -__forceinline SDWORD DMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 7); } -__forceinline SDWORD DMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 8); } -__forceinline SDWORD DMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 9); } -__forceinline SDWORD DMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 10); } -__forceinline SDWORD DMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 11); } -__forceinline SDWORD DMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 12); } -__forceinline SDWORD DMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 13); } -__forceinline SDWORD DMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 14); } -__forceinline SDWORD DMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 15); } -__forceinline SDWORD DMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 16); } -__forceinline SDWORD DMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 17); } -__forceinline SDWORD DMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 18); } -__forceinline SDWORD DMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 19); } -__forceinline SDWORD DMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 20); } -__forceinline SDWORD DMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 21); } -__forceinline SDWORD DMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 22); } -__forceinline SDWORD DMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 23); } -__forceinline SDWORD DMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 24); } -__forceinline SDWORD DMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 25); } -__forceinline SDWORD DMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 26); } -__forceinline SDWORD DMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 27); } -__forceinline SDWORD DMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 28); } -__forceinline SDWORD DMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 29); } -__forceinline SDWORD DMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 30); } -__forceinline SDWORD DMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 31); } -__forceinline SDWORD DMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 32); } +static __forceinline SDWORD DMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 1); } +static __forceinline SDWORD DMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 2); } +static __forceinline SDWORD DMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 3); } +static __forceinline SDWORD DMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 4); } +static __forceinline SDWORD DMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 5); } +static __forceinline SDWORD DMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 6); } +static __forceinline SDWORD DMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 7); } +static __forceinline SDWORD DMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 8); } +static __forceinline SDWORD DMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 9); } +static __forceinline SDWORD DMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 10); } +static __forceinline SDWORD DMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 11); } +static __forceinline SDWORD DMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 12); } +static __forceinline SDWORD DMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 13); } +static __forceinline SDWORD DMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 14); } +static __forceinline SDWORD DMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 15); } +static __forceinline SDWORD DMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 16); } +static __forceinline SDWORD DMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 17); } +static __forceinline SDWORD DMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 18); } +static __forceinline SDWORD DMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 19); } +static __forceinline SDWORD DMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 20); } +static __forceinline SDWORD DMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 21); } +static __forceinline SDWORD DMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 22); } +static __forceinline SDWORD DMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 23); } +static __forceinline SDWORD DMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 24); } +static __forceinline SDWORD DMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 25); } +static __forceinline SDWORD DMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 26); } +static __forceinline SDWORD DMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 27); } +static __forceinline SDWORD DMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 28); } +static __forceinline SDWORD DMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 29); } +static __forceinline SDWORD DMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 30); } +static __forceinline SDWORD DMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 31); } +static __forceinline SDWORD DMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d) >> 32); } -__forceinline SDWORD TMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 1); } -__forceinline SDWORD TMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 2); } -__forceinline SDWORD TMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 3); } -__forceinline SDWORD TMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 4); } -__forceinline SDWORD TMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 5); } -__forceinline SDWORD TMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 6); } -__forceinline SDWORD TMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 7); } -__forceinline SDWORD TMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 8); } -__forceinline SDWORD TMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 9); } -__forceinline SDWORD TMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 10); } -__forceinline SDWORD TMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 11); } -__forceinline SDWORD TMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 12); } -__forceinline SDWORD TMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 13); } -__forceinline SDWORD TMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 14); } -__forceinline SDWORD TMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 15); } -__forceinline SDWORD TMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 16); } -__forceinline SDWORD TMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 17); } -__forceinline SDWORD TMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 18); } -__forceinline SDWORD TMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 19); } -__forceinline SDWORD TMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 20); } -__forceinline SDWORD TMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 21); } -__forceinline SDWORD TMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 22); } -__forceinline SDWORD TMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 23); } -__forceinline SDWORD TMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 24); } -__forceinline SDWORD TMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 25); } -__forceinline SDWORD TMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 26); } -__forceinline SDWORD TMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 27); } -__forceinline SDWORD TMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 28); } -__forceinline SDWORD TMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 29); } -__forceinline SDWORD TMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 30); } -__forceinline SDWORD TMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 31); } -__forceinline SDWORD TMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 32); } +static __forceinline SDWORD TMulScale1 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 1); } +static __forceinline SDWORD TMulScale2 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 2); } +static __forceinline SDWORD TMulScale3 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 3); } +static __forceinline SDWORD TMulScale4 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 4); } +static __forceinline SDWORD TMulScale5 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 5); } +static __forceinline SDWORD TMulScale6 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 6); } +static __forceinline SDWORD TMulScale7 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 7); } +static __forceinline SDWORD TMulScale8 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 8); } +static __forceinline SDWORD TMulScale9 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 9); } +static __forceinline SDWORD TMulScale10 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 10); } +static __forceinline SDWORD TMulScale11 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 11); } +static __forceinline SDWORD TMulScale12 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 12); } +static __forceinline SDWORD TMulScale13 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 13); } +static __forceinline SDWORD TMulScale14 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 14); } +static __forceinline SDWORD TMulScale15 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 15); } +static __forceinline SDWORD TMulScale16 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 16); } +static __forceinline SDWORD TMulScale17 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 17); } +static __forceinline SDWORD TMulScale18 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 18); } +static __forceinline SDWORD TMulScale19 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 19); } +static __forceinline SDWORD TMulScale20 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 20); } +static __forceinline SDWORD TMulScale21 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 21); } +static __forceinline SDWORD TMulScale22 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 22); } +static __forceinline SDWORD TMulScale23 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 23); } +static __forceinline SDWORD TMulScale24 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 24); } +static __forceinline SDWORD TMulScale25 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 25); } +static __forceinline SDWORD TMulScale26 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 26); } +static __forceinline SDWORD TMulScale27 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 27); } +static __forceinline SDWORD TMulScale28 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 28); } +static __forceinline SDWORD TMulScale29 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 29); } +static __forceinline SDWORD TMulScale30 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 30); } +static __forceinline SDWORD TMulScale31 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 31); } +static __forceinline SDWORD TMulScale32 (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD f) { return (SDWORD)(((SQWORD)a*b + (SQWORD)c*d + (SQWORD)e*f) >> 32); } -__forceinline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) +static __forceinline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) { SQWORD x = ((SQWORD)a * b) >> c; return x > 0x7FFFFFFFll ? 0x7FFFFFFF : @@ -137,45 +139,45 @@ __forceinline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) (SDWORD)x; } -inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) +static inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) { return (SDWORD)(((SQWORD)a << c) / b); } -inline SDWORD DivScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 1) / b); } -inline SDWORD DivScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 2) / b); } -inline SDWORD DivScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 3) / b); } -inline SDWORD DivScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 4) / b); } -inline SDWORD DivScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 5) / b); } -inline SDWORD DivScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 6) / b); } -inline SDWORD DivScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 7) / b); } -inline SDWORD DivScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 8) / b); } -inline SDWORD DivScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 9) / b); } -inline SDWORD DivScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 10) / b); } -inline SDWORD DivScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 11) / b); } -inline SDWORD DivScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 12) / b); } -inline SDWORD DivScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 13) / b); } -inline SDWORD DivScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 14) / b); } -inline SDWORD DivScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 15) / b); } -inline SDWORD DivScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 16) / b); } -inline SDWORD DivScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 17) / b); } -inline SDWORD DivScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 18) / b); } -inline SDWORD DivScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 19) / b); } -inline SDWORD DivScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 20) / b); } -inline SDWORD DivScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 21) / b); } -inline SDWORD DivScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 22) / b); } -inline SDWORD DivScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 23) / b); } -inline SDWORD DivScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 24) / b); } -inline SDWORD DivScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 25) / b); } -inline SDWORD DivScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 26) / b); } -inline SDWORD DivScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 27) / b); } -inline SDWORD DivScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 28) / b); } -inline SDWORD DivScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 29) / b); } -inline SDWORD DivScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 30) / b); } -inline SDWORD DivScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 31) / b); } -inline SDWORD DivScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 32) / b); } +static inline SDWORD DivScale1 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 1) / b); } +static inline SDWORD DivScale2 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 2) / b); } +static inline SDWORD DivScale3 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 3) / b); } +static inline SDWORD DivScale4 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 4) / b); } +static inline SDWORD DivScale5 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 5) / b); } +static inline SDWORD DivScale6 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 6) / b); } +static inline SDWORD DivScale7 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 7) / b); } +static inline SDWORD DivScale8 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 8) / b); } +static inline SDWORD DivScale9 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 9) / b); } +static inline SDWORD DivScale10 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 10) / b); } +static inline SDWORD DivScale11 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 11) / b); } +static inline SDWORD DivScale12 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 12) / b); } +static inline SDWORD DivScale13 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 13) / b); } +static inline SDWORD DivScale14 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 14) / b); } +static inline SDWORD DivScale15 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 15) / b); } +static inline SDWORD DivScale16 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 16) / b); } +static inline SDWORD DivScale17 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 17) / b); } +static inline SDWORD DivScale18 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 18) / b); } +static inline SDWORD DivScale19 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 19) / b); } +static inline SDWORD DivScale20 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 20) / b); } +static inline SDWORD DivScale21 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 21) / b); } +static inline SDWORD DivScale22 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 22) / b); } +static inline SDWORD DivScale23 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 23) / b); } +static inline SDWORD DivScale24 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 24) / b); } +static inline SDWORD DivScale25 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 25) / b); } +static inline SDWORD DivScale26 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 26) / b); } +static inline SDWORD DivScale27 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 27) / b); } +static inline SDWORD DivScale28 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 28) / b); } +static inline SDWORD DivScale29 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 29) / b); } +static inline SDWORD DivScale30 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 30) / b); } +static inline SDWORD DivScale31 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 31) / b); } +static inline SDWORD DivScale32 (SDWORD a, SDWORD b) { return (SDWORD)(((SQWORD)a << 32) / b); } -__forceinline void clearbuf (void *buff, unsigned int count, SDWORD clear) +static __forceinline void clearbuf (void *buff, unsigned int count, SDWORD clear) { SDWORD *b2 = (SDWORD *)buff; for (unsigned int i = 0; i != count; ++i) @@ -184,7 +186,7 @@ __forceinline void clearbuf (void *buff, unsigned int count, SDWORD clear) } } -__forceinline void clearbufshort (void *buff, unsigned int count, WORD clear) +static __forceinline void clearbufshort (void *buff, unsigned int count, WORD clear) { SWORD *b2 = (SWORD *)buff; for (unsigned int i = 0; i != count; ++i) @@ -193,19 +195,19 @@ __forceinline void clearbufshort (void *buff, unsigned int count, WORD clear) } } -__forceinline SDWORD ksgn (SDWORD a) +static __forceinline SDWORD ksgn (SDWORD a) { if (a < 0) return -1; else if (a > 0) return 1; else return 0; } -__forceinline int toint (float v) +static __forceinline int toint (float v) { return int(v); } -__forceinline int quickertoint (float v) +static __forceinline int quickertoint (float v) { return int(v); } diff --git a/src/d_net.cpp b/src/d_net.cpp index f916721b4..cf30c5830 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2100,9 +2100,9 @@ void Net_DoCommand (int type, BYTE **stream, int player) case DEM_SUMMONFOE2: { const PClass *typeinfo; - int angle; - SWORD tid; - BYTE special; + int angle = 0; + SWORD tid = 0; + BYTE special = 0; int args[5]; s = ReadString (stream); diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index a5ffa9251..e62128ec4 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -67,20 +67,29 @@ class ARandomSpawner : public AActor else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn. { // Handle replacement here so as to get the proper speed and flags for missiles - const PClass * cls; PClass * rep; + const PClass *cls; cls = PClass::FindClass(di->Name); - if (cls) rep = cls->ActorInfo->GetReplacement()->Class; - if (rep) cls = rep; - if (cls) + if (cls != NULL) + { + const PClass *rep = cls->ActorInfo->GetReplacement()->Class; + if (rep != NULL) + { + cls = rep; + } + } + if (cls != NULL) { Species = cls->TypeName; - AActor * defmobj = GetDefaultByType(cls); + AActor *defmobj = GetDefaultByType(cls); this->Speed = defmobj->Speed; this->flags |= (defmobj->flags & MF_MISSILE); this->flags2 |= (defmobj->flags2 & MF2_SEEKERMISSILE); this->flags4 |= (defmobj->flags4 & MF4_SPECTRAL); } - else Species = NAME_None; + else + { + Species = NAME_None; + } } } } @@ -152,7 +161,7 @@ class ARandomSpawner : public AActor boss = true; // If a replaced actor has either of those same flags, it's also a boss. AActor * rep = GetDefaultByType(GetClass()->ActorInfo->GetReplacee()->Class); - if (rep && (rep->flags4 & MF4_BOSSDEATH) || (rep->flags2 & MF2_BOSS)) + if (rep && ((rep->flags4 & MF4_BOSSDEATH) || (rep->flags2 & MF2_BOSS))) boss = true; } if (boss) this->tracer = newmobj; diff --git a/src/gccinlines.h b/src/gccinlines.h index ebadcd4cc..3b987895a 100644 --- a/src/gccinlines.h +++ b/src/gccinlines.h @@ -29,7 +29,7 @@ #define alloca __builtin_alloca #endif -inline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) +static inline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; @@ -47,7 +47,7 @@ inline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) return result; } -inline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) +static inline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; @@ -65,7 +65,7 @@ inline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c) } #define MAKECONSTMulScale(s) \ -inline SDWORD MulScale##s (SDWORD a, SDWORD b) { return ((SQWORD)a * b) >> s; } +static inline SDWORD MulScale##s (SDWORD a, SDWORD b) { return ((SQWORD)a * b) >> s; } MAKECONSTMulScale(1) MAKECONSTMulScale(2) @@ -101,8 +101,10 @@ MAKECONSTMulScale(31) MAKECONSTMulScale(32) #undef MAKECONSTMulScale +static inline DWORD UMulScale16(DWORD a, DWORD b) { return ((QWORD)a * b) >> 16; } + #define MAKECONSTDMulScale(s) \ - inline SDWORD DMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d) \ + static inline SDWORD DMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d) \ { \ return (((SQWORD)a * b) + ((SQWORD)c * d)) >> s; \ } @@ -142,7 +144,7 @@ MAKECONSTDMulScale(32) #undef MAKECONSTDMulScale #define MAKECONSTTMulScale(s) \ - inline SDWORD TMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD ee) \ + static inline SDWORD TMulScale##s (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD e, SDWORD ee) \ { \ return (((SQWORD)a * b) + ((SQWORD)c * d) + ((SQWORD)e * ee)) >> s; \ } @@ -181,7 +183,7 @@ MAKECONSTTMulScale(31) MAKECONSTTMulScale(32) #undef MAKECONSTTMulScale -inline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) +static inline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) { union { long long big; @@ -195,7 +197,7 @@ inline SDWORD BoundMulScale (SDWORD a, SDWORD b, SDWORD c) return u.l; } -inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) +static inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) { SDWORD result, dummy; SDWORD lo = a << c; @@ -212,7 +214,7 @@ inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c) return result; } -inline SDWORD DivScale1 (SDWORD a, SDWORD b) +static inline SDWORD DivScale1 (SDWORD a, SDWORD b) { SDWORD result, dummy; @@ -229,7 +231,7 @@ inline SDWORD DivScale1 (SDWORD a, SDWORD b) } #define MAKECONSTDivScale(s) \ - inline SDWORD DivScale##s (SDWORD a, SDWORD b) \ + static inline SDWORD DivScale##s (SDWORD a, SDWORD b) \ { \ SDWORD result, dummy; \ asm volatile \ @@ -275,7 +277,7 @@ MAKECONSTDivScale(30) MAKECONSTDivScale(31) #undef MAKECONSTDivScale -inline SDWORD DivScale32 (SDWORD a, SDWORD b) +static inline SDWORD DivScale32 (SDWORD a, SDWORD b) { SDWORD result, dummy; @@ -290,7 +292,7 @@ inline SDWORD DivScale32 (SDWORD a, SDWORD b) return result; } -inline void clearbuf (void *buff, int count, SDWORD clear) +static inline void clearbuf (void *buff, int count, SDWORD clear) { int dummy1, dummy2; asm volatile @@ -303,7 +305,7 @@ inline void clearbuf (void *buff, int count, SDWORD clear) ); } -inline void clearbufshort (void *buff, unsigned int count, WORD clear) +static inline void clearbufshort (void *buff, unsigned int count, WORD clear) { asm volatile ("shr $1,%%ecx\n\t" @@ -315,7 +317,7 @@ inline void clearbufshort (void *buff, unsigned int count, WORD clear) :"%cc"); } -inline SDWORD ksgn (SDWORD a) +static inline SDWORD ksgn (SDWORD a) { SDWORD result, dummy; @@ -330,7 +332,7 @@ inline SDWORD ksgn (SDWORD a) return result; } -inline int toint (float v) +static inline int toint (float v) { volatile QWORD result; @@ -342,7 +344,7 @@ inline int toint (float v) return result; } -inline int quickertoint (float v) +static inline int quickertoint (float v) { volatile int result; diff --git a/src/mscinlines.h b/src/mscinlines.h index e432e4259..0a5fdb798 100644 --- a/src/mscinlines.h +++ b/src/mscinlines.h @@ -82,6 +82,13 @@ __forceinline SDWORD MulScale32 (SDWORD a, SDWORD b) __asm mov eax,edx } +__forceinline DWORD UMulScale16(DWORD a, DWORD b) +{ + __asm mov eax,a + __asm mul b + __asm shrd eax,edx,16 +} + __forceinline SDWORD DMulScale (SDWORD a, SDWORD b, SDWORD c, SDWORD d, SDWORD s) { __asm mov eax,a diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index a53491370..5799ef563 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -624,11 +624,11 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec) int sidenum = int(intptr_t(lines[linenum].sidedef[1])); if (bsec->floorstat & 64) { // floor is aligned to first wall - R_AlignFlat (linenum, sidenum == (DWORD)bsec->wallptr, 0); + R_AlignFlat (linenum, sidenum == bsec->wallptr, 0); } if (bsec->ceilingstat & 64) { // ceiling is aligned to first wall - R_AlignFlat (linenum, sidenum == (DWORD)bsec->wallptr, 0); + R_AlignFlat (linenum, sidenum == bsec->wallptr, 0); } } for(i = 0; i < numsides; i++) diff --git a/src/p_map.cpp b/src/p_map.cpp index 510e1f9e5..223f62816 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2752,8 +2752,8 @@ extern FRandom pr_bounce; bool P_BounceActor (AActor *mo, AActor * BlockingMobj) { if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors) - || ((mo->flags & MF_MISSILE) && (BlockingMobj->flags2 & MF2_REFLECTIVE) - || ((!BlockingMobj->player) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))) + || ((mo->flags & MF_MISSILE) && (BlockingMobj->flags2 & MF2_REFLECTIVE)) + || ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER))) )) { fixed_t speed; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 56ecd5179..bce0bcb30 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1337,11 +1337,11 @@ static void P_SpawnScrollers(void) if (special != 0) { int max = LineSpecialsInfo[special] != NULL ? LineSpecialsInfo[special]->map_args : countof(l->args); - for (int arg = max; arg < countof(l->args); ++arg) + for (unsigned arg = max; arg < countof(l->args); ++arg) { if (l->args[arg] != 0) { - Printf("Line %d (type %d:%s), arg %d is %d (should be 0)\n", + Printf("Line %d (type %d:%s), arg %u is %d (should be 0)\n", i, special, LineSpecialsInfo[special]->name, arg+1, l->args[arg]); } } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7b263a35c..072518316 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -765,15 +765,15 @@ static int skycolplace; static const BYTE *R_GetOneSkyColumn (FTexture *fronttex, int x) { angle_t column = (viewangle + xtoviewangle[x]) ^ skyflip; - return fronttex->GetColumn((MulScale16(column, frontcyl) + frontpos) >> FRACBITS, NULL); + return fronttex->GetColumn((UMulScale16(column, frontcyl) + frontpos) >> FRACBITS, NULL); } // Get a column of sky when there are two overlapping sky textures static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x) { DWORD ang = (viewangle + xtoviewangle[x]) ^ skyflip; - DWORD angle1 = (DWORD)((MulScale16(ang, frontcyl) + frontpos) >> FRACBITS); - DWORD angle2 = (DWORD)((MulScale16(ang, backcyl) + backpos) >> FRACBITS); + DWORD angle1 = (DWORD)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS); + DWORD angle2 = (DWORD)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS); // Check if this column has already been built. If so, there's // no reason to waste time building it again. @@ -1244,7 +1244,7 @@ ADD_STAT(skyboxes) void R_DrawSkyPlane (visplane_t *pl) { FTextureID sky1tex, sky2tex; - double frontdpos, backdpos; + double frontdpos = 0, backdpos = 0; if ((level.flags & LEVEL_SWAPSKIES) && !(level.flags & LEVEL_DOUBLESKY)) { @@ -1330,10 +1330,10 @@ void R_DrawSkyPlane (visplane_t *pl) } } } - frontpos = int(fmod(frontdpos, double(sky1cyl * 65536.0))); + frontpos = int(fmod(frontdpos, sky1cyl * 65536.0)); if (backskytex != NULL) { - backpos = int(fmod(backdpos, double(sky2cyl * 65536.0))); + backpos = int(fmod(backdpos, sky2cyl * 65536.0)); } bool fakefixed = false; diff --git a/src/sound/fmod_wrap.h b/src/sound/fmod_wrap.h index 3068c41d9..f77eed36c 100644 --- a/src/sound/fmod_wrap.h +++ b/src/sound/fmod_wrap.h @@ -47,7 +47,7 @@ namespace FMOD FMOD global system functions (optional). */ inline FMOD_RESULT Memory_Initialize(void *poolmem, int poollen, FMOD_MEMORY_ALLOCCALLBACK useralloc, FMOD_MEMORY_REALLOCCALLBACK userrealloc, FMOD_MEMORY_FREECALLBACK userfree, FMOD_MEMORY_TYPE memtypeflags = (FMOD_MEMORY_NORMAL | FMOD_MEMORY_XBOX360_PHYSICAL)) { return FMOD_Memory_Initialize(poolmem, poollen, useralloc, userrealloc, userfree, memtypeflags); } - inline FMOD_RESULT Memory_GetStats (int *currentalloced, int *maxalloced) { return FMOD_Memory_GetStats(currentalloced, maxalloced); } + //inline FMOD_RESULT Memory_GetStats(int *currentalloced, int *maxalloced) { return FMOD_Memory_GetStats(currentalloced, maxalloced); } inline FMOD_RESULT Debug_SetLevel(FMOD_DEBUGLEVEL level) { return FMOD_Debug_SetLevel(level); } inline FMOD_RESULT Debug_GetLevel(FMOD_DEBUGLEVEL *level) { return FMOD_Debug_GetLevel(level); } inline FMOD_RESULT File_SetDiskBusy(int busy) { return FMOD_File_SetDiskBusy(busy); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index f4f782464..8af93f0bd 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -410,7 +410,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) const char *GetFlagName(int flagnum, int flagoffset) { - for(int i=0; istyle.BlendOp == 255) { - if (parms->fillcolor != -1) + if (parms->fillcolor != ~0u) { if (parms->alphaChannel) { diff --git a/src/v_palette.cpp b/src/v_palette.cpp index b9279779d..c47f75370 100644 --- a/src/v_palette.cpp +++ b/src/v_palette.cpp @@ -469,7 +469,7 @@ void InitPalette () // build default special maps (e.g. invulnerability) SpecialColormaps.Clear(); - for (int i = 0; i < countof(SpecialColormapParms); ++i) + for (unsigned i = 0; i < countof(SpecialColormapParms); ++i) { AddSpecialColormap(SpecialColormapParms[i].Start[0], SpecialColormapParms[i].Start[1], SpecialColormapParms[i].Start[2], SpecialColormapParms[i].End[0], diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 7e9197b0e..3104b8311 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -417,7 +417,7 @@ void D3DFB::SetInitialState() CurPixelShader = NULL; memset(Constant, 0, sizeof(Constant)); - for (int i = 0; i < countof(Texture); ++i) + for (unsigned i = 0; i < countof(Texture); ++i) { Texture[i] = NULL; D3DDevice->SetSamplerState(i, D3DSAMP_ADDRESSU, (i == 1 && SM14) ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP); @@ -558,7 +558,8 @@ bool D3DFB::LoadShaders() { static const char models[][4] = { "30/", "20/", "14/" }; FString shaderdir, shaderpath; - int model, i, lump; + unsigned model, i; + int lump; // We determine the best available model simply by trying them all in // order of decreasing preference. @@ -3594,7 +3595,7 @@ void D3DFB::SetPixelShader(IDirect3DPixelShader9 *shader) void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture) { - assert(tnum >= 0 && tnum < countof(Texture)); + assert(unsigned(tnum) < countof(Texture)); if (Texture[tnum] != texture) { Texture[tnum] = texture; From 39bd295da8fd3e28045447845668b7d4c49439d3 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 8 Nov 2009 02:58:37 +0000 Subject: [PATCH 074/241] - Fixed: The x64 Release build was configured to use the 32-bit GME, and neither release nor debug builds built the library. SVN r1966 (trunk) --- docs/rh-log.txt | 2 ++ zdoom.sln | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 88015541e..511085c07 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 7, 2009 +- Fixed: The x64 Release build was configured to use the 32-bit GME, and + neither release nor debug builds built the library. - Fixed: R_GetOneSkyColumn() and R_GetTwoSkyColumns are mulscaling an unsigned integer that can use all 32 bits. They must therefore use the unsigned mul instruction rather than the signed imul instruction. diff --git a/zdoom.sln b/zdoom.sln index 0f4d541a6..988e84d68 100644 --- a/zdoom.sln +++ b/zdoom.sln @@ -165,9 +165,11 @@ Global {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.ActiveCfg = Release|Win32 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|Win32.Build.0 = Release|Win32 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|x64.ActiveCfg = Release|x64 + {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Debug|x64.Build.0 = Release|x64 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|Win32.ActiveCfg = Release|Win32 {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|Win32.Build.0 = Release|Win32 - {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|x64.ActiveCfg = Release|Win32 + {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|x64.ActiveCfg = Release|x64 + {9B465A9E-E5C7-4577-B559-3CA2F7AE7D96}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From a0d6a47daf4b29bbed3283ddb0553f41f1349506 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 10 Nov 2009 02:29:18 +0000 Subject: [PATCH 075/241] - Maps inside zips can now satisfy the map checks for IWAD detection. - Fixed: F7ZFile did not delete its Archive when destroyed. SVN r1967 (trunk) --- docs/rh-log.txt | 4 ++++ src/d_iwad.cpp | 44 +++++++++++++++++++++++++++++++---- src/resourcefiles/file_7z.cpp | 9 ++++++- src/win32/i_main.cpp | 2 +- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 511085c07..0e29a173d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 9, 2009 +- Maps inside zips can now satisfy the map checks for IWAD detection. +- Fixed: F7ZFile did not delete its Archive when destroyed. + November 7, 2009 - Fixed: The x64 Release build was configured to use the 32-bit GME, and neither release nor debug builds built the library. diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 672823d63..8a7b0dacf 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -176,7 +176,7 @@ static EIWADType ScanIWAD (const char *iwad) { 'S','P','I','D','A','1','D','1' }, }; -#define NUM_CHECKLUMPS (sizeof(checklumps)/8) +#define NUM_CHECKLUMPS (countof(checklumps)) enum { Check_ad2lib, @@ -202,7 +202,7 @@ static EIWADType ScanIWAD (const char *iwad) Check_Gameinfo, Check_e2m1 }; - int lumpsfound[NUM_CHECKLUMPS]; + bool lumpsfound[NUM_CHECKLUMPS]; size_t i; memset (lumpsfound, 0, sizeof(lumpsfound)); @@ -213,10 +213,44 @@ static EIWADType ScanIWAD (const char *iwad) for(DWORD ii = 0; ii < iwadfile->LumpCount(); ii++) { FResourceLump *lump = iwadfile->GetLump(ii); + size_t j; - for (DWORD j = 0; j < NUM_CHECKLUMPS; j++) - if (strnicmp (lump->Name, checklumps[j], 8) == 0) - lumpsfound[j]++; + for (j = 0; j < NUM_CHECKLUMPS; j++) + { + if (!lumpsfound[j]) + { + if (strnicmp (lump->Name, checklumps[j], 8) == 0) + { + lumpsfound[j] = true; + break; + } + // Check for maps inside zips, too. + else if (lump->FullName != NULL) + { + if (checklumps[j][0] == 'E' && checklumps[j][2] == 'M' && checklumps[j][4] == '\0') + { + if (strnicmp(lump->FullName, "maps/", 5) == 0 && + strnicmp(lump->FullName + 5, checklumps[j], 4) == 0 && + stricmp(lump->FullName + 9, ".wad") == 0) + { + lumpsfound[j] = true; + break; + } + } + else if (checklumps[j][0] == 'M' && checklumps[j][1] == 'A' && checklumps[j][2] == 'P' && + checklumps[j][5] == '\0') + { + if (strnicmp(lump->FullName, "maps/", 5) == 0 && + strnicmp(lump->FullName + 5, checklumps[j], 5) == 0 && + stricmp(lump->FullName + 10, ".wad") == 0) + { + lumpsfound[j] = true; + break; + } + } + } + } + } } delete iwadfile; } diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index 290792140..2943d00aa 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -310,7 +310,14 @@ bool F7ZFile::Open(bool quiet) F7ZFile::~F7ZFile() { - if (Lumps != NULL) delete [] Lumps; + if (Lumps != NULL) + { + delete[] Lumps; + } + if (Archive != NULL) + { + delete Archive; + } } //========================================================================== diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 6bc9e2f5f..af57aaef3 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1290,7 +1290,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - //_crtBreakAlloc = 5501; + //_crtBreakAlloc = 3660; #endif DoMain (hInstance); From f1a672254d8f2edb97dcc4185f9f6033fb2f05cc Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 10 Nov 2009 03:40:54 +0000 Subject: [PATCH 076/241] - Fixed: Do not use scaled texture width when calculating xiscale. SVN r1968 (trunk) --- src/v_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_draw.cpp b/src/v_draw.cpp index e590df524..f53e7cd31 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -199,7 +199,7 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, double x, double y, uint32 dc_iscale = DivScale32(1, spryscale); dc_texturemid = FixedMul(-sprtopscreen, dc_iscale) + FixedMul(centeryfrac-FRACUNIT, dc_iscale); fixed_t frac = 0; - double xiscale = parms.texwidth / parms.destwidth; + double xiscale = img->GetWidth() / parms.destwidth; double x2 = x0 + parms.destwidth; if (bottomclipper[0] != parms.dclip) From 653e2dd1f01dc636042c12a103ed21fcfc20cf7e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 10 Nov 2009 04:24:20 +0000 Subject: [PATCH 077/241] - Whoops! SVN r1969 (trunk) --- src/basicinlines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basicinlines.h b/src/basicinlines.h index 3969a9507..4bc211f99 100644 --- a/src/basicinlines.h +++ b/src/basicinlines.h @@ -12,7 +12,7 @@ #endif #ifndef _MSC_VER -#define static __forceinline inline +#define __forceinline inline #endif static __forceinline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c) From 281b2f563709c5e08c81e8e5ceb9da75e70b7e58 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 12 Nov 2009 01:05:55 +0000 Subject: [PATCH 078/241] - Fixed: MBF sky Y offsets were ignored. X offsets should also be applied to the sky cylinder, not the screen like Hexen scrolling skies. SVN r1970 (trunk) --- docs/rh-log.txt | 4 ++++ src/r_plane.cpp | 16 ++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0e29a173d..39251460b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 11, 2009 +- Fixed: MBF sky Y offsets were ignored. X offsets should also be applied to + the sky cylinder, not the screen like Hexen scrolling skies. + November 9, 2009 - Maps inside zips can now satisfy the map checks for IWAD detection. - Fixed: F7ZFile did not delete its Archive when destroyed. diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 072518316..7ccbec09f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -747,6 +747,8 @@ static angle_t skyflip; static int frontpos, backpos; static fixed_t frontyScale; static fixed_t frontcyl, backcyl; +static fixed_t skymid; +static angle_t skyangle; int frontiScale; extern fixed_t swall[MAXWIDTH]; @@ -764,14 +766,14 @@ static int skycolplace; // Get a column of sky when there is only one sky texture. static const BYTE *R_GetOneSkyColumn (FTexture *fronttex, int x) { - angle_t column = (viewangle + xtoviewangle[x]) ^ skyflip; + angle_t column = (skyangle + xtoviewangle[x]) ^ skyflip; return fronttex->GetColumn((UMulScale16(column, frontcyl) + frontpos) >> FRACBITS, NULL); } // Get a column of sky when there are two overlapping sky textures static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x) { - DWORD ang = (viewangle + xtoviewangle[x]) ^ skyflip; + DWORD ang = (skyangle + xtoviewangle[x]) ^ skyflip; DWORD angle1 = (DWORD)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS); DWORD angle2 = (DWORD)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS); @@ -849,7 +851,7 @@ static void R_DrawSky (visplane_t *pl) rw_offset = 0; frontyScale = rw_pic->yScale; - dc_texturemid = MulScale16 (skytexturemid/*-viewz*/, frontyScale); + dc_texturemid = MulScale16 (skymid, frontyScale); if (1 << frontskytex->HeightBits == frontskytex->GetHeight()) { // The texture tiles nicely @@ -881,7 +883,7 @@ static void R_DrawSkyStriped (visplane_t *pl) // So that I don't have to worry about fractional precision, chop off the // fractional part of centeryfrac. centeryfrac = centery << FRACBITS; - topfrac = (skytexturemid + iscale * (1-centery)) % (frontskytex->GetHeight() << FRACBITS); + topfrac = (skymid + iscale * (1-centery)) % (frontskytex->GetHeight() << FRACBITS); if (topfrac < 0) topfrac += frontskytex->GetHeight() << FRACBITS; yl = 0; yh = (short)MulScale32 ((frontskytex->GetHeight() << FRACBITS) - topfrac, frontyScale); @@ -1255,6 +1257,8 @@ void R_DrawSkyPlane (visplane_t *pl) sky1tex = sky1texture; } sky2tex = sky2texture; + skymid = skytexturemid; + skyangle = viewangle; if (pl->picnum == skyflatnum) { @@ -1311,10 +1315,10 @@ void R_DrawSkyPlane (visplane_t *pl) // to allow sky rotation as well as careful positioning. // However, the offset is scaled very small, so that it // allows a long-period of sky rotation. - frontdpos = (-s->GetTextureXOffset(pos)) >> 6; + skyangle += s->GetTextureXOffset(pos); // Vertical offset allows careful sky positioning. - dc_texturemid = s->GetTextureYOffset(pos) - 28*FRACUNIT; + skymid = s->GetTextureYOffset(pos) - 28*FRACUNIT; // We sometimes flip the picture horizontally. // From 4fed0f805725ccac9570b765fa84e49d28b3c3d7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 12 Nov 2009 01:21:25 +0000 Subject: [PATCH 079/241] - Fixed: nofreeaim in P_SpawnPlayerMissile() was broken. SVN r1971 (trunk) --- docs/rh-log.txt | 1 + src/p_mobj.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 39251460b..5c5a5d8c1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 11, 2009 +- Fixed: nofreeaim in P_SpawnPlayerMissile() was broken. - Fixed: MBF sky Y offsets were ignored. X offsets should also be applied to the sky cylinder, not the screen like Hexen scrolling skies. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7ecf49987..8177b73a1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5204,6 +5204,10 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, if (linetarget == NULL) { an = angle; + if (nofreeaim || !level.IsFreelookAllowed()) + { + pitch = 0; + } } if (pLineTarget) *pLineTarget = linetarget; From 30b21b2eea36c17c82e41285348234cd867c2104 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 12 Nov 2009 02:47:28 +0000 Subject: [PATCH 080/241] - Removed the one embedded DeHackEd lump restriction. SVN r1972 (trunk) --- docs/rh-log.txt | 1 + src/d_dehacked.cpp | 166 ++++++++++++++++++--------------------------- src/d_dehacked.h | 5 +- src/d_main.cpp | 23 ++++--- src/w_wad.cpp | 1 + 5 files changed, 83 insertions(+), 113 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5c5a5d8c1..0cd8d0b35 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 11, 2009 +- Removed the one embedded DeHackEd lump restriction. - Fixed: nofreeaim in P_SpawnPlayerMissile() was broken. - Fixed: MBF sky Y offsets were ignored. X offsets should also be applied to the sky cylinder, not the screen like Hexen scrolling skies. diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index b4901bc8a..29b0e22bb 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -285,6 +285,7 @@ static int PatchPars (int); static int PatchCodePtrs (int); static int PatchMusic (int); static int DoInclude (int); +static bool DoDehPatch(); static const struct { const char *name; @@ -2260,7 +2261,7 @@ static int DoInclude (int dummy) } } - DoDehPatch (path, false); + D_LoadDehFile(path); if (data != path) { @@ -2280,105 +2281,70 @@ static int DoInclude (int dummy) return GetLine(); } -void DoDehPatch (const char *patchfile, bool autoloading, int lump) +int D_LoadDehLumps() { - char file[256]; - int cont; - int filelen = 0; // Be quiet, gcc + int lastlump = 0, lumpnum, count = 0; - PatchFile = NULL; - PatchName = NULL; - - if (lump < 0) + while ((lumpnum = Wads.FindLump("DEHACKED", &lastlump)) >= 0) { - lump = Wads.CheckNumForName ("DEHACKED"); + count += D_LoadDehLump(lumpnum); } + return count; +} - if (lump >= 0 && autoloading) +bool D_LoadDehLump(int lumpnum) +{ + int filelen = Wads.LumpLength(lumpnum); + + PatchName = copystring(Wads.GetLumpFullPath(lumpnum)); + PatchFile = new char[filelen + 1]; + Wads.ReadLump(lumpnum, PatchFile); + PatchFile[filelen] = '\0'; // terminate with a '\0' character + return DoDehPatch(); +} + +bool D_LoadDehFile(const char *patchfile) +{ + FILE *deh; + + deh = fopen(patchfile, "rb"); + if (deh != NULL) { - // Execute the DEHACKED lump as a patch. - strcpy (file, "DEHACKED lump"); - filelen = Wads.LumpLength (lump); - if ( (PatchFile = new char[filelen + 1]) ) - { - Wads.ReadLump (lump, PatchFile); - } - else - { - Printf ("Not enough memory to apply patch\n"); - return; - } - } - else if (patchfile) - { - // Try to use patchfile as a patch. - FILE *deh; + int filelen = Q_filelength(deh); - strcpy (file, patchfile); - FixPathSeperator (file); - DefaultExtension (file, ".deh"); - - if ( !(deh = fopen (file, "rb")) ) - { - strcpy (file, patchfile); - FixPathSeperator (file); - DefaultExtension (file, ".bex"); - deh = fopen (file, "rb"); - } - - if (deh) - { - filelen = Q_filelength (deh); - if ( (PatchFile = new char[filelen + 1]) ) - { - fread (PatchFile, 1, filelen, deh); - fclose (deh); - PatchName = copystring (patchfile); - FixPathSeperator (PatchName); - } - } - - if (!PatchFile) - { - // Couldn't find it on disk, try reading it from a lump - lump = Wads.CheckNumForFullName(patchfile, true); - if (lump == -1) - { - // Compatibility fallback. It's just here because - // some WAD may need it. Should be deleted it it can - // be confirmed that nothing uses this case. - FString filebase(ExtractFileBase (patchfile)); - lump = Wads.CheckNumForName (filebase); - } - if (lump >= 0) - { - filelen = Wads.LumpLength (lump); - if ( (PatchFile = new char[filelen + 1]) ) - { - Wads.ReadLump (lump, PatchFile); - } - else - { - Printf ("Not enough memory to apply patch\n"); - return; - } - } - } - - if (!PatchFile) - { - Printf ("Could not open DeHackEd patch \"%s\"\n", file); - return; - } + PatchName = copystring(patchfile); + PatchFile = new char[filelen + 1]; + fread(PatchFile, 1, filelen, deh); + fclose(deh); + PatchFile[filelen] = '\0'; // terminate with a '\0' character + return DoDehPatch(); } else { - // Nothing to do. - return; + // Couldn't find it in the filesystem; try from a lump instead. + int lumpnum = Wads.CheckNumForFullName(patchfile, true); + if (lumpnum < 0) + { + // Compatibility fallback. It's just here because + // some WAD may need it. Should be deleted if it can + // be confirmed that nothing uses this case. + FString filebase(ExtractFileBase(patchfile)); + lumpnum = Wads.CheckNumForName(filebase); + } + if (lumpnum >= 0) + { + return D_LoadDehLump(lumpnum); + } } + Printf ("Could not open DeHackEd patch \"%s\"\n", patchfile); + return false; +} - // End file with a NULL for our parser - PatchFile[filelen] = 0; +static bool DoDehPatch() +{ + Printf("Adding dehacked patch %s\n", PatchName); + + int cont; dversion = pversion = -1; cont = 0; @@ -2386,10 +2352,10 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump) { if (PatchFile[25] < '3') { - if (PatchName != NULL) delete[] PatchName; + delete[] PatchName; delete[] PatchFile; - Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", file); - return; + Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", PatchFile); + return false; } PatchPt = strchr (PatchFile, '\n'); while ((cont = GetLine()) == 1) @@ -2399,10 +2365,10 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump) } if (!cont || dversion == -1 || pversion == -1) { - if (PatchName != NULL) delete[] PatchName; + delete[] PatchName; delete[] PatchFile; - Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", file); - return; + Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", PatchFile); + return false; } } else @@ -2412,7 +2378,7 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump) pversion = 6; PatchPt = PatchFile; while ((cont = GetLine()) == 1) - ; + {} } if (pversion != 6) @@ -2439,10 +2405,10 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump) if (!LoadDehSupp ()) { Printf ("Could not load DEH support data\n"); - if (PatchName != NULL) delete[] PatchName; - delete[] PatchFile; UnloadDehSupp (); - return; + delete[] PatchName; + delete[] PatchFile; + return false; } do @@ -2459,10 +2425,10 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump) } while (cont); UnloadDehSupp (); - if (PatchName != NULL) delete[] PatchName; + delete[] PatchName; delete[] PatchFile; Printf ("Patch installed\n"); - + return true; } static inline bool CompareLabel (const char *want, const BYTE *have) diff --git a/src/d_dehacked.h b/src/d_dehacked.h index 6967c083d..67473f071 100644 --- a/src/d_dehacked.h +++ b/src/d_dehacked.h @@ -56,8 +56,9 @@ public: bool droppedbymonster; }; - -void DoDehPatch (const char *patchfile, bool autoloading, int lumpnum=-1); +int D_LoadDehLumps(); +bool D_LoadDehLump(int lumpnum); +bool D_LoadDehFile(const char *filename); void FinishDehPatch (); #endif //__D_DEHACK_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index cad92cce6..a06340f68 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1483,9 +1483,9 @@ bool ConsiderPatches (const char *arg, const char *ext) for (i = 0; i < files->NumArgs(); ++i) { if ( (f = BaseFileSearch (files->GetArg (i), ".deh")) ) - DoDehPatch (f, false); + D_LoadDehFile(f); else if ( (f = BaseFileSearch (files->GetArg (i), ".bex")) ) - DoDehPatch (f, false); + D_LoadDehFile(f); } noDef = true; } @@ -1947,13 +1947,12 @@ void D_DoomMain (void) DecalLibrary.Clear (); DecalLibrary.ReadAllDecals (); - // [RH] Try adding .deh and .bex files on the command line. + // [RH] Add any .deh and .bex files on the command line. // If there are none, try adding any in the config file. + // Note that the command line overrides defaults from the config. - if (!ConsiderPatches ("-deh", ".deh") && - !ConsiderPatches ("-bex", ".bex") && - (gameinfo.gametype == GAME_Doom) && - GameConfig->SetSection ("Doom.DefaultDehacked")) + if ((ConsiderPatches("-deh", ".deh") | ConsiderPatches("-bex", ".bex")) == 0 && + gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked")) { const char *key; const char *value; @@ -1963,17 +1962,19 @@ void D_DoomMain (void) if (stricmp (key, "Path") == 0 && FileExists (value)) { Printf ("Applying patch %s\n", value); - DoDehPatch (value, true); + D_LoadDehFile(value); } } } - DoDehPatch (NULL, true); // See if there's a patch in a PWAD - FinishDehPatch (); // Create replacements for dehacked pickups + // Load embedded Dehacked patches + D_LoadDehLumps(); + + // Create replacements for dehacked pickups + FinishDehPatch(); FActorInfo::StaticSetActorNums (); - // [RH] User-configurable startup strings. Because BOOM does. static const char *startupString[5] = { "STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5" diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 4d1d554d9..3594c8b3f 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -832,6 +832,7 @@ int FWadCollection::FindLump (const char *name, int *lastlump, bool anyns) uppercopy (name8, name); + assert(lastlump != NULL && *lastlump >= 0); lump_p = &LumpInfo[*lastlump]; while (lump_p < &LumpInfo[NumLumps]) { From 7b7973c6a7ed4f6c30f16fce633f80fac9769c4e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 12 Nov 2009 03:14:10 +0000 Subject: [PATCH 081/241] - Fixed: The framerate was not capped before starting a game. SVN r1973 (trunk) --- docs/rh-log.txt | 1 + src/d_main.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0cd8d0b35..4444de5bc 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 11, 2009 +- Fixed: The framerate was not capped before starting a game. - Removed the one embedded DeHackEd lump restriction. - Fixed: nofreeaim in P_SpawnPlayerMissile() was broken. - Fixed: MBF sky Y offsets were ignored. X offsets should also be applied to diff --git a/src/d_main.cpp b/src/d_main.cpp index a06340f68..9d1f90048 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -860,6 +860,9 @@ void D_DoomLoop () { int lasttic = 0; + // Clamp the timer to TICRATE until the playloop has been entered. + r_NoInterpolate = true; + for (;;) { try From f09420fce747c9c65d2f7cdd83e718cc87741c7d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 12 Nov 2009 03:45:51 +0000 Subject: [PATCH 082/241] - Modified the event-driven ticks to use the same code for calculating the time as the polled timer so that the timer does not start running until the first time it is used. - Removed the srand() call from D_DoomMain(), because it started the game timer running prematurely, and we never call rand() anywhere. (Not to mention, even if we did use rand(), always seeding it with 0 is rather pointless.) SVN r1974 (trunk) --- docs/rh-log.txt | 7 +++++++ src/d_main.cpp | 2 -- src/win32/i_system.cpp | 47 +++++++----------------------------------- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4444de5bc..631ecc046 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,11 @@ November 11, 2009 +- Modified the event-driven ticks to use the same code for calculating the + time as the polled timer so that the timer does not start running until the + first time it is used. +- Removed the srand() call from D_DoomMain(), because it started the game + timer running prematurely, and we never call rand() anywhere. (Not to + mention, even if we did use rand(), always seeding it with 0 is rather + pointless.) - Fixed: The framerate was not capped before starting a game. - Removed the one embedded DeHackEd lump restriction. - Fixed: nofreeaim in P_SpawnPlayerMissile() was broken. diff --git a/src/d_main.cpp b/src/d_main.cpp index 9d1f90048..d8bae9f8a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1597,8 +1597,6 @@ void D_DoomMain (void) const char *wad; DArgs *execFiles; - srand(I_MSTime()); - // Set the FPU precision to 53 significant bits. This is the default // for Visual C++, but not for GCC, so some slight math variances // might crop up if we leave it alone. diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 8db15225b..caa1e533d 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -145,7 +145,7 @@ int I_GetTimePolled (bool saveMS) } tm = timeGetTime(); - if (!basetime) + if (basetime == 0) basetime = tm; if (saveMS) @@ -186,46 +186,20 @@ void I_FreezeTimePolled (bool frozen) } -static int tics; -static DWORD ted_start, ted_next; - -int I_GetTimeEventDriven (bool saveMS) -{ - if (saveMS) - { - TicStart = ted_start; - TicNext = ted_next; - } - return tics; -} - int I_WaitForTicEvent (int prevtic) { assert(!TicFrozen); + + int tics = I_GetTimePolled(false); while (prevtic >= tics) { WaitForSingleObject(NewTicArrived, 1000/TICRATE); + tics = I_GetTimePolled(false); } return tics; } -void CALLBACK TimerTicked (UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2) -{ - if (!TicFrozen) - { - tics++; - } - ted_start = timeGetTime (); - ted_next = ted_start + MillisecondsPerTic; - SetEvent (NewTicArrived); -} - -void I_FreezeTimeEventDriven(bool frozen) -{ - TicFrozen = frozen; -} - // Returns the fractional amount of a tic passed since the most recent tic fixed_t I_GetTimeFrac (uint32 *ms) { @@ -453,21 +427,14 @@ void I_Init (void) { delay = 1000/TICRATE; } - TimerEventID = timeSetEvent - ( - delay, - 0, - TimerTicked, - 0, - TIME_PERIODIC - ); + TimerEventID = timeSetEvent(delay, 0, (LPTIMECALLBACK)NewTicArrived, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET); MillisecondsPerTic = delay; } if (TimerEventID != 0) { - I_GetTime = I_GetTimeEventDriven; + I_GetTime = I_GetTimePolled; I_WaitForTic = I_WaitForTicEvent; - I_FreezeTime = I_FreezeTimeEventDriven; + I_FreezeTime = I_FreezeTimePolled; } else { // If no timer event, busy-loop with timeGetTime From a0e7cdb73d24704a2c13633843f7e004e6c9fc07 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 13 Nov 2009 03:55:23 +0000 Subject: [PATCH 083/241] - Cleaned up win32/i_system.cpp. - Put back the previous event-driven ticker, except now the timer isn't started until the first time it is needed. SVN r1975 (trunk) --- docs/rh-log.txt | 5 + src/win32/i_system.cpp | 746 ++++++++++++++++++++++++++++++----------- 2 files changed, 552 insertions(+), 199 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 631ecc046..fa255c312 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 12, 2009 +- Cleaned up win32/i_system.cpp. +- Put back the previous event-driven ticker, except now the timer isn't + started until the first time it is needed. + November 11, 2009 - Modified the event-driven ticks to use the same code for calculating the time as the polled timer so that the timer does not start running until the diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index caa1e533d..1cbc957b6 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -1,25 +1,38 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// $Log:$ -// -// DESCRIPTION: -// -//----------------------------------------------------------------------------- +/* +** i_system.cpp +** Timers, pre-console output, IWAD selection, and misc system routines. +** +**--------------------------------------------------------------------------- +** Copyright 1998-2009 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. 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. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ +// HEADER FILES ------------------------------------------------------------ #include #include @@ -39,10 +52,6 @@ #include #include -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - #define USE_WINDOWS_DWORD #include "hardware.h" #include "doomerrors.h" @@ -75,23 +84,51 @@ #include "v_palette.h" #include "stats.h" -EXTERN_CVAR (String, language) +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void CheckCPUID(CPUInfo *cpu); +extern void LayoutMainWindow(HWND hWnd, HWND pane); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void CalculateCPUSpeed(); +static void I_SelectTimer(); + +static int I_GetTimePolled(bool saveMS); +static int I_WaitForTicPolled(int prevtic); +static void I_FreezeTimePolled(bool frozen); +static int I_GetTimeEventDriven(bool saveMS); +static int I_WaitForTicEvent(int prevtic); +static void I_FreezeTimeEventDriven(bool frozen); +static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +EXTERN_CVAR(String, language); +EXTERN_CVAR (Bool, queryiwad); extern HWND Window, ConWindow, GameTitleWindow; extern HANDLE StdOut; extern bool FancyStdOut; extern HINSTANCE g_hInst; +extern FILE *Logfile; + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +CVAR (String, queryiwad_key, "shift", CVAR_GLOBALCONFIG|CVAR_ARCHIVE); double PerfToSec, PerfToMillisec; - UINT TimerPeriod; UINT TimerEventID; UINT MillisecondsPerTic; HANDLE NewTicArrived; uint32 LanguageIDs[4]; -void CalculateCPUSpeed (); const IWADInfo *DoomStartupInfo; @@ -100,42 +137,159 @@ int (*I_WaitForTic) (int); void (*I_FreezeTime) (bool frozen); os_t OSPlatform; +bool gameisdead; -void I_Tactile (int on, int off, int total) +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static ticcmd_t emptycmd; +static bool HasExited; + +static DWORD basetime = 0; +// These are for the polled timer. +static DWORD TicStart; +static DWORD TicNext; +static int TicFrozen; + +// These are for the event-driven timer. +static int tics; +static DWORD ted_start, ted_next; + +static WadStuff *WadList; +static int NumWads; +static int DefaultWad; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// I_Tactile +// +// Doom calls it when you take damage, so presumably it could be converted +// to something compatible with force feedback. +// +//========================================================================== + +void I_Tactile(int on, int off, int total) { // UNUSED. on = off = total = 0; } -ticcmd_t emptycmd; -ticcmd_t *I_BaseTiccmd(void) +//========================================================================== +// +// I_BaseTiccmd +// +// Returns an empty ticcmd. I have no idea why this should be system- +// specific. +// +//========================================================================== + +ticcmd_t *I_BaseTiccmd() { return &emptycmd; } -static DWORD basetime = 0; +// Stubs that select the timer to use and then call into it ---------------- -// [RH] Returns time in milliseconds -unsigned int I_MSTime (void) +//========================================================================== +// +// I_GetTimeSelect +// +//========================================================================== + +static int I_GetTimeSelect(bool saveMS) { - DWORD tm; - - tm = timeGetTime(); - if (!basetime) - basetime = tm; - - return tm - basetime; + I_SelectTimer(); + return I_GetTime(saveMS); } -static DWORD TicStart; -static DWORD TicNext; -static int TicFrozen; +//========================================================================== +// +// I_WaitForTicSelect +// +//========================================================================== +static int I_WaitForTicSelect(int prevtic) +{ + I_SelectTimer(); + return I_WaitForTic(prevtic); +} + +//========================================================================== // -// I_GetTime -// returns time in 1/35th second tics +// I_SelectTimer // -int I_GetTimePolled (bool saveMS) +// Tries to create a timer event for efficent CPU use when the FPS is +// capped. Failing that, it sets things up for a polling timer instead. +// +//========================================================================== + +static void I_SelectTimer() +{ + assert(basetime == 0); + + // Use a timer event if possible. + NewTicArrived = CreateEvent(NULL, FALSE, FALSE, NULL); + if (NewTicArrived) + { + UINT delay; + char *cmdDelay; + + cmdDelay = Args->CheckValue("-timerdelay"); + delay = 0; + if (cmdDelay != 0) + { + delay = atoi(cmdDelay); + } + if (delay == 0) + { + delay = 1000/TICRATE; + } + MillisecondsPerTic = delay; + TimerEventID = timeSetEvent(delay, 0, TimerTicked, 0, TIME_PERIODIC); + } + // Get the current time as the basetime. + basetime = timeGetTime(); + // Set timer functions. + if (TimerEventID != 0) + { + I_GetTime = I_GetTimeEventDriven; + I_WaitForTic = I_WaitForTicEvent; + I_FreezeTime = I_FreezeTimeEventDriven; + } + else + { + I_GetTime = I_GetTimePolled; + I_WaitForTic = I_WaitForTicPolled; + I_FreezeTime = I_FreezeTimePolled; + } +} + +//========================================================================== +// +// I_MSTime +// +// Returns the current time in milliseconds, where 0 is the first call +// to I_GetTime or I_WaitForTic. +// +//========================================================================== + +unsigned int I_MSTime() +{ + assert(basetime != 0); + return timeGetTime() - basetime; +} + +//========================================================================== +// +// I_GetTimePolled +// +// Returns the current time in tics. If saveMS is true, then calls to +// I_GetTimeFrac() will use this tic as 0 and the next tic as 1. +// +//========================================================================== + +static int I_GetTimePolled(bool saveMS) { DWORD tm; @@ -146,8 +300,9 @@ int I_GetTimePolled (bool saveMS) tm = timeGetTime(); if (basetime == 0) + { basetime = tm; - + } if (saveMS) { TicStart = tm; @@ -157,18 +312,35 @@ int I_GetTimePolled (bool saveMS) return ((tm-basetime)*TICRATE)/1000; } -int I_WaitForTicPolled (int prevtic) +//========================================================================== +// +// I_WaitForTicPolled +// +// Busy waits until the current tic is greater than prevtic. Time must not +// be frozen. +// +//========================================================================== + +static int I_WaitForTicPolled(int prevtic) { int time; assert(TicFrozen == 0); while ((time = I_GetTimePolled(false)) <= prevtic) - ; + { } return time; } -void I_FreezeTimePolled (bool frozen) +//========================================================================== +// +// I_FreezeTimePolled +// +// Freeze/unfreeze the timer. +// +//========================================================================== + +static void I_FreezeTimePolled(bool frozen) { if (frozen) { @@ -185,26 +357,92 @@ void I_FreezeTimePolled (bool frozen) } } +//========================================================================== +// +// I_GetTimeEventDriven +// +// Returns the current tick counter. This is incremented asynchronously as +// the timer event fires. +// +//========================================================================== -int I_WaitForTicEvent (int prevtic) +static int I_GetTimeEventDriven(bool saveMS) { - assert(!TicFrozen); - - int tics = I_GetTimePolled(false); - while (prevtic >= tics) + if (saveMS) { - WaitForSingleObject(NewTicArrived, 1000/TICRATE); - tics = I_GetTimePolled(false); + TicStart = ted_start; + TicNext = ted_next; } - return tics; } -// Returns the fractional amount of a tic passed since the most recent tic -fixed_t I_GetTimeFrac (uint32 *ms) +//========================================================================== +// +// I_WaitForTicEvent +// +// Waits on the timer event as long as the current tic is not later than +// prevtic. +// +//========================================================================== + +static int I_WaitForTicEvent(int prevtic) +{ + assert(!TicFrozen); + while (prevtic >= tics) + { + WaitForSingleObject(NewTicArrived, 1000/TICRATE); + } + return tics; +} + +//========================================================================== +// +// I_FreezeTimeEventDriven +// +// Freeze/unfreeze the ticker. +// +//========================================================================== + +static void I_FreezeTimeEventDriven(bool frozen) +{ + TicFrozen = frozen; +} + +//========================================================================== +// +// TimerTicked +// +// Advance the tick count and signal the NewTicArrived event. +// +//========================================================================== + +static void CALLBACK TimerTicked(UINT id, UINT msg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2) +{ + if (!TicFrozen) + { + tics++; + } + ted_start = timeGetTime (); + ted_next = ted_start + MillisecondsPerTic; + SetEvent(NewTicArrived); +} + +//========================================================================== +// +// I_GetTimeFrac +// +// Returns the fractional amount of a tic passed since the most recently +// saved tic. +// +//========================================================================== + +fixed_t I_GetTimeFrac(uint32 *ms) { DWORD now = timeGetTime(); - if (ms) *ms = TicNext; + if (ms != NULL) + { + *ms = TicNext; + } DWORD step = TicNext - TicStart; if (step == 0) { @@ -217,15 +455,30 @@ fixed_t I_GetTimeFrac (uint32 *ms) } } -void I_WaitVBL (int count) +//========================================================================== +// +// I_WaitVBL +// +// I_WaitVBL is never used to actually synchronize to the vertical blank. +// Instead, it's used for delay purposes. Doom used a 70 Hz display mode, +// so that's what we use to determine how long to wait for. +// +//========================================================================== + +void I_WaitVBL(int count) { - // I_WaitVBL is never used to actually synchronize to the - // vertical blank. Instead, it's used for delay purposes. - Sleep (1000 * count / 70); + Sleep(1000 * count / 70); } -// [RH] Detect the OS the game is running under -void I_DetectOS (void) +//========================================================================== +// +// I_DetectOS +// +// Determine which version of Windows the game is running on. +// +//========================================================================== + +void I_DetectOS(void) { OSVERSIONINFO info; const char *osname; @@ -303,19 +556,24 @@ void I_DetectOS (void) } } +//========================================================================== // // SubsetLanguageIDs // -static void SubsetLanguageIDs (LCID id, LCTYPE type, int idx) +// Helper function for SetLanguageIDs. +// +//========================================================================== + +static void SubsetLanguageIDs(LCID id, LCTYPE type, int idx) { char buf[8]; LCID langid; char *idp; - if (!GetLocaleInfo (id, type, buf, 8)) + if (!GetLocaleInfo(id, type, buf, 8)) return; - langid = MAKELCID (strtoul(buf, NULL, 16), SORT_DEFAULT); - if (!GetLocaleInfo (langid, LOCALE_SABBREVLANGNAME, buf, 8)) + langid = MAKELCID(strtoul(buf, NULL, 16), SORT_DEFAULT); + if (!GetLocaleInfo(langid, LOCALE_SABBREVLANGNAME, buf, 8)) return; idp = (char *)(&LanguageIDs[idx]); memset (idp, 0, 4); @@ -325,20 +583,23 @@ static void SubsetLanguageIDs (LCID id, LCTYPE type, int idx) idp[3] = 0; } +//========================================================================== // // SetLanguageIDs // -void SetLanguageIDs () +//========================================================================== + +void SetLanguageIDs() { - size_t langlen = strlen (language); + size_t langlen = strlen(language); if (langlen < 2 || langlen > 3) { - memset (LanguageIDs, 0, sizeof(LanguageIDs)); - SubsetLanguageIDs (LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, 0); - SubsetLanguageIDs (LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE, 1); - SubsetLanguageIDs (LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, 2); - SubsetLanguageIDs (LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTLANGUAGE, 3); + memset(LanguageIDs, 0, sizeof(LanguageIDs)); + SubsetLanguageIDs(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, 0); + SubsetLanguageIDs(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE, 1); + SubsetLanguageIDs(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, 2); + SubsetLanguageIDs(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTLANGUAGE, 3); } else { @@ -354,6 +615,16 @@ void SetLanguageIDs () } } +//========================================================================== +// +// CalculateCPUSpeed +// +// Make a decent guess at how much time elapses between TSC steps. This can +// vary over runtime depending on power management settings, so should not +// be used anywhere that truely accurate timing actually matters. +// +//========================================================================== + void CalculateCPUSpeed() { LARGE_INTEGER freq; @@ -400,81 +671,60 @@ void CalculateCPUSpeed() Printf ("CPU Speed: %.0f MHz\n", 0.001 / PerfToMillisec); } +//========================================================================== // // I_Init // +//========================================================================== -void I_Init (void) +void I_Init() { CheckCPUID(&CPU); CalculateCPUSpeed(); DumpCPUInfo(&CPU); - // Use a timer event if possible - NewTicArrived = CreateEvent (NULL, FALSE, FALSE, NULL); - if (NewTicArrived) - { - UINT delay; - char *cmdDelay; - - cmdDelay = Args->CheckValue ("-timerdelay"); - delay = 0; - if (cmdDelay != 0) - { - delay = atoi (cmdDelay); - } - if (delay == 0) - { - delay = 1000/TICRATE; - } - TimerEventID = timeSetEvent(delay, 0, (LPTIMECALLBACK)NewTicArrived, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET); - MillisecondsPerTic = delay; - } - if (TimerEventID != 0) - { - I_GetTime = I_GetTimePolled; - I_WaitForTic = I_WaitForTicEvent; - I_FreezeTime = I_FreezeTimePolled; - } - else - { // If no timer event, busy-loop with timeGetTime - I_GetTime = I_GetTimePolled; - I_WaitForTic = I_WaitForTicPolled; - I_FreezeTime = I_FreezeTimePolled; - } + I_GetTime = I_GetTimeSelect; + I_WaitForTic = I_WaitForTicSelect; atterm (I_ShutdownSound); I_InitSound (); } +//========================================================================== // // I_Quit // -static int has_exited; +//========================================================================== -void I_Quit (void) +void I_Quit() { - has_exited = 1; /* Prevent infinitely recursive exits -- killough */ - - if (TimerEventID) - timeKillEvent (TimerEventID); - if (NewTicArrived) - CloseHandle (NewTicArrived); - - timeEndPeriod (TimerPeriod); + HasExited = true; /* Prevent infinitely recursive exits -- killough */ + if (TimerEventID != 0) + { + timeKillEvent(TimerEventID); + } + if (NewTicArrived != NULL) + { + CloseHandle(NewTicArrived); + } + timeEndPeriod(TimerPeriod); if (demorecording) + { G_CheckDemoStatus(); + } } +//========================================================================== // -// I_Error +// I_FatalError // -extern FILE *Logfile; -bool gameisdead; +// Throw an error that will end the game. +// +//========================================================================== -void STACK_ARGS I_FatalError (const char *error, ...) +void STACK_ARGS I_FatalError(const char *error, ...) { static BOOL alreadyThrown = false; gameisdead = true; @@ -484,50 +734,72 @@ void STACK_ARGS I_FatalError (const char *error, ...) alreadyThrown = true; char errortext[MAX_ERRORTEXT]; va_list argptr; - va_start (argptr, error); - myvsnprintf (errortext, MAX_ERRORTEXT, error, argptr); - va_end (argptr); + va_start(argptr, error); + myvsnprintf(errortext, MAX_ERRORTEXT, error, argptr); + va_end(argptr); // Record error to log (if logging) if (Logfile) { - fprintf (Logfile, "\n**** DIED WITH FATAL ERROR:\n%s\n", errortext); - fflush (Logfile); + fprintf(Logfile, "\n**** DIED WITH FATAL ERROR:\n%s\n", errortext); + fflush(Logfile); } - throw CFatalError (errortext); + throw CFatalError(errortext); } - if (!has_exited) // If it hasn't exited yet, exit now -- killough + if (!HasExited) // If it hasn't exited yet, exit now -- killough { - has_exited = 1; // Prevent infinitely recursive exits -- killough + HasExited = 1; // Prevent infinitely recursive exits -- killough exit(-1); } } -void STACK_ARGS I_Error (const char *error, ...) +//========================================================================== +// +// I_Error +// +// Throw an error that will send us to the console if we are far enough +// along in the startup process. +// +//========================================================================== + +void STACK_ARGS I_Error(const char *error, ...) { va_list argptr; char errortext[MAX_ERRORTEXT]; - va_start (argptr, error); - myvsnprintf (errortext, MAX_ERRORTEXT, error, argptr); - va_end (argptr); + va_start(argptr, error); + myvsnprintf(errortext, MAX_ERRORTEXT, error, argptr); + va_end(argptr); - throw CRecoverableError (errortext); + throw CRecoverableError(errortext); } -extern void LayoutMainWindow (HWND hWnd, HWND pane); +//========================================================================== +// +// I_SetIWADInfo +// +//========================================================================== -void I_SetIWADInfo (const IWADInfo *info) +void I_SetIWADInfo(const IWADInfo *info) { DoomStartupInfo = info; // Make the startup banner show itself - LayoutMainWindow (Window, NULL); + LayoutMainWindow(Window, NULL); } -void I_PrintStr (const char *cp) +//========================================================================== +// +// I_PrintStr +// +// Send output to the list box shown during startup (and hidden during +// gameplay). +// +//========================================================================== + +void I_PrintStr(const char *cp) { if (ConWindow == NULL && StdOut == NULL) return; @@ -543,16 +815,16 @@ void I_PrintStr (const char *cp) if (edit != NULL) { // Store the current selection and set it to the end so we can append text. - SendMessage (edit, EM_EXGETSEL, 0, (LPARAM)&selection); - endselection.cpMax = endselection.cpMin = GetWindowTextLength (edit); - SendMessage (edit, EM_EXSETSEL, 0, (LPARAM)&endselection); + SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&selection); + endselection.cpMax = endselection.cpMin = GetWindowTextLength(edit); + SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&endselection); // GetWindowTextLength and EM_EXSETSEL can disagree on where the end of // the text is. Find out what EM_EXSETSEL thought it was and use that later. - SendMessage (edit, EM_EXGETSEL, 0, (LPARAM)&endselection); + SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&endselection); // Remember how many lines there were before we added text. - lines_before = SendMessage (edit, EM_GETLINECOUNT, 0, 0); + lines_before = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0); } while (*cp != 0) @@ -563,7 +835,7 @@ void I_PrintStr (const char *cp) buf[bpos] = 0; if (edit != NULL) { - SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf); + SendMessage(edit, EM_REPLACESEL, FALSE, (LPARAM)buf); } if (StdOut != NULL) { @@ -579,13 +851,13 @@ void I_PrintStr (const char *cp) else { const BYTE *color_id = (const BYTE *)cp + 1; - EColorRange range = V_ParseFontColor (color_id, CR_UNTRANSLATED, CR_YELLOW); + EColorRange range = V_ParseFontColor(color_id, CR_UNTRANSLATED, CR_YELLOW); cp = (const char *)color_id; if (range != CR_UNDEFINED) { // Change the color of future text added to the control. - PalEntry color = V_LogColorFromColorRange (range); + PalEntry color = V_LogColorFromColorRange(range); if (StdOut != NULL && FancyStdOut) { // Unfortunately, we are pretty limited here: There are only @@ -594,7 +866,7 @@ void I_PrintStr (const char *cp) float h, s, v, r, g, b; WORD attrib = 0; - RGBtoHSV(color.r / 255.0, color.g / 255.0, color.b / 255.0, &h, &s, &v); + RGBtoHSV(color.r / 255.f, color.g / 255.f, color.b / 255.f, &h, &s, &v); if (s != 0) { // color HSVtoRGB(&r, &g, &b, h, 1, 1); @@ -614,13 +886,13 @@ void I_PrintStr (const char *cp) if (edit != NULL) { // GDI uses BGR colors, but color is RGB, so swap the R and the B. - swap (color.r, color.b); + swap(color.r, color.b); // Change the color. format.cbSize = sizeof(format); format.dwMask = CFM_COLOR; format.dwEffects = 0; format.crTextColor = color; - SendMessage (edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format); + SendMessage(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format); } } } @@ -630,7 +902,7 @@ void I_PrintStr (const char *cp) buf[bpos] = 0; if (edit != NULL) { - SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf); + SendMessage(edit, EM_REPLACESEL, FALSE, (LPARAM)buf); } if (StdOut != NULL) { @@ -646,16 +918,16 @@ void I_PrintStr (const char *cp) if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax) { selection.cpMax = selection.cpMin = GetWindowTextLength (edit); - lines_after = SendMessage (edit, EM_GETLINECOUNT, 0, 0); + lines_after = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0); if (lines_after > lines_before) { - SendMessage (edit, EM_LINESCROLL, 0, lines_after - lines_before); + SendMessage(edit, EM_LINESCROLL, 0, lines_after - lines_before); } } // Restore the previous selection. - SendMessage (edit, EM_EXSETSEL, 0, (LPARAM)&selection); + SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&selection); // Give the edit control a chance to redraw itself. - I_GetEvent (); + I_GetEvent(); } if (StdOut != NULL && FancyStdOut) { // Set text back to gray, in case it was changed. @@ -663,21 +935,24 @@ void I_PrintStr (const char *cp) } } -EXTERN_CVAR (Bool, queryiwad); -CVAR (String, queryiwad_key, "shift", CVAR_GLOBALCONFIG|CVAR_ARCHIVE); -static WadStuff *WadList; -static int NumWads; -static int DefaultWad; +//========================================================================== +// +// SetQueryIWAD +// +// The user had the "Don't ask again" box checked when they closed the +// IWAD selection dialog. +// +//========================================================================== -static void SetQueryIWad (HWND dialog) +static void SetQueryIWad(HWND dialog) { - HWND checkbox = GetDlgItem (dialog, IDC_DONTASKIWAD); - int state = SendMessage (checkbox, BM_GETCHECK, 0, 0); + HWND checkbox = GetDlgItem(dialog, IDC_DONTASKIWAD); + int state = (int)SendMessage(checkbox, BM_GETCHECK, 0, 0); bool query = (state != BST_CHECKED); if (!query && queryiwad) { - MessageBox (dialog, + MessageBox(dialog, "You have chosen not to show this dialog box in the future.\n" "If you wish to see it again, hold down SHIFT while starting " GAMENAME ".", "Don't ask me this again", @@ -687,7 +962,15 @@ static void SetQueryIWad (HWND dialog) queryiwad = query; } -BOOL CALLBACK IWADBoxCallback (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +//========================================================================== +// +// IWADBoxCallback +// +// Dialog proc for the IWAD selector. +// +//========================================================================== + +BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND ctrl; int i; @@ -700,32 +983,32 @@ BOOL CALLBACK IWADBoxCallback (HWND hDlg, UINT message, WPARAM wParam, LPARAM lP TCHAR label[256]; FString newlabel; - GetWindowText (hDlg, label, countof(label)); - newlabel.Format (GAMESIG " " DOTVERSIONSTR_NOREV ": %s", label); - SetWindowText (hDlg, newlabel.GetChars()); + GetWindowText(hDlg, label, countof(label)); + newlabel.Format(GAMESIG " " DOTVERSIONSTR_NOREV ": %s", label); + SetWindowText(hDlg, newlabel.GetChars()); } // Populate the list with all the IWADs found - ctrl = GetDlgItem (hDlg, IDC_IWADLIST); + ctrl = GetDlgItem(hDlg, IDC_IWADLIST); for (i = 0; i < NumWads; i++) { FString work; - const char *filepart = strrchr (WadList[i].Path, '/'); + const char *filepart = strrchr(WadList[i].Path, '/'); if (filepart == NULL) filepart = WadList[i].Path; else filepart++; - work.Format ("%s (%s)", IWADInfos[WadList[i].Type].Name, filepart); - SendMessage (ctrl, LB_ADDSTRING, 0, (LPARAM)work.GetChars()); - SendMessage (ctrl, LB_SETITEMDATA, i, (LPARAM)i); + work.Format("%s (%s)", IWADInfos[WadList[i].Type].Name, filepart); + SendMessage(ctrl, LB_ADDSTRING, 0, (LPARAM)work.GetChars()); + SendMessage(ctrl, LB_SETITEMDATA, i, (LPARAM)i); } - SendMessage (ctrl, LB_SETCURSEL, DefaultWad, 0); - SetFocus (ctrl); + SendMessage(ctrl, LB_SETCURSEL, DefaultWad, 0); + SetFocus(ctrl); // Set the state of the "Don't ask me again" checkbox - ctrl = GetDlgItem (hDlg, IDC_DONTASKIWAD); - SendMessage (ctrl, BM_SETCHECK, queryiwad ? BST_UNCHECKED : BST_CHECKED, 0); + ctrl = GetDlgItem(hDlg, IDC_DONTASKIWAD); + SendMessage(ctrl, BM_SETCHECK, queryiwad ? BST_UNCHECKED : BST_CHECKED, 0); // Make sure the dialog is in front. If SHIFT was pressed to force it visible, // then the other window will normally be on top. - SetForegroundWindow (hDlg); + SetForegroundWindow(hDlg); break; case WM_COMMAND: @@ -736,24 +1019,32 @@ BOOL CALLBACK IWADBoxCallback (HWND hDlg, UINT message, WPARAM wParam, LPARAM lP else if (LOWORD(wParam) == IDOK || (LOWORD(wParam) == IDC_IWADLIST && HIWORD(wParam) == LBN_DBLCLK)) { - SetQueryIWad (hDlg); + SetQueryIWad(hDlg); ctrl = GetDlgItem (hDlg, IDC_IWADLIST); - EndDialog (hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0)); + EndDialog(hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0)); } break; } return FALSE; } -int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) +//========================================================================== +// +// I_PickIWad +// +// Open a dialog to pick the IWAD, if there is more than one found. +// +//========================================================================== + +int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad) { int vkey; - if (stricmp (queryiwad_key, "shift") == 0) + if (stricmp(queryiwad_key, "shift") == 0) { vkey = VK_SHIFT; } - else if (stricmp (queryiwad_key, "control") == 0 || stricmp (queryiwad_key, "ctrl") == 0) + else if (stricmp(queryiwad_key, "control") == 0 || stricmp (queryiwad_key, "ctrl") == 0) { vkey = VK_CONTROL; } @@ -767,13 +1058,21 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) NumWads = numwads; DefaultWad = defaultiwad; - return DialogBox (g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG), + return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG), (HWND)Window, (DLGPROC)IWADBoxCallback); } return defaultiwad; } -bool I_WriteIniFailed () +//========================================================================== +// +// I_WriteIniFailed +// +// Display a message when the config failed to save. +// +//========================================================================== + +bool I_WriteIniFailed() { char *lpMsgBuf; FString errortext; @@ -790,23 +1089,56 @@ bool I_WriteIniFailed () ); errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf); LocalFree (lpMsgBuf); - return MessageBox (Window, errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY; + return MessageBox(Window, errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY; } -void *I_FindFirst (const char *filespec, findstate_t *fileinfo) +//========================================================================== +// +// I_FindFirst +// +// Start a pattern matching sequence. +// +//========================================================================== + +void *I_FindFirst(const char *filespec, findstate_t *fileinfo) { - return FindFirstFileA (filespec, (LPWIN32_FIND_DATAA)fileinfo); -} -int I_FindNext (void *handle, findstate_t *fileinfo) -{ - return !FindNextFileA ((HANDLE)handle, (LPWIN32_FIND_DATAA)fileinfo); + return FindFirstFileA(filespec, (LPWIN32_FIND_DATAA)fileinfo); } -int I_FindClose (void *handle) +//========================================================================== +// +// I_FindNext +// +// Return the next file in a pattern matching sequence. +// +//========================================================================== + +int I_FindNext(void *handle, findstate_t *fileinfo) { - return FindClose ((HANDLE)handle); + return !FindNextFileA((HANDLE)handle, (LPWIN32_FIND_DATAA)fileinfo); } +//========================================================================== +// +// I_FindClose +// +// Finish a pattern matching sequence. +// +//========================================================================== + +int I_FindClose(void *handle) +{ + return FindClose((HANDLE)handle); +} + +//========================================================================== +// +// QueryPathKey +// +// Returns the value of a registry key into the output variable value. +// +//========================================================================== + static bool QueryPathKey(HKEY key, const char *keypath, const char *valname, FString &value) { HKEY steamkey; @@ -833,6 +1165,15 @@ static bool QueryPathKey(HKEY key, const char *keypath, const char *valname, FSt return value.IsNotEmpty(); } +//========================================================================== +// +// I_GetSteamPath +// +// Check the registry for the path to Steam, so that we can search for +// IWADs that were bought with Steam. +// +//========================================================================== + FString I_GetSteamPath() { FString path; @@ -849,7 +1190,14 @@ FString I_GetSteamPath() return path; } -// Return a random seed, preferably one with lots of entropy. +//========================================================================== +// +// I_MakeRNGSeed +// +// Returns a 32-bit random seed, preferably one with lots of entropy. +// +//========================================================================== + unsigned int I_MakeRNGSeed() { unsigned int seed; From 363dfcffbda3881224ff488a7c9ed24db04db5e1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 13 Nov 2009 04:38:03 +0000 Subject: [PATCH 084/241] November 12, 2009 - Improved sky stretching a bit: It now only stretches the sky as tall as it needs to be: 228 pixels, not 256. It no longer stretches horizontally, either. The reason it stretches to 228 and not 200 pixels is because Doom shifted its sky texture down 28 pixels. By stretching to 228 pixels, we can keep the sky tiled at the same height on the horizon. Skies 200 pixels tall (or more) will continue to tile at the center of the screen when looking directly ahead. SVN r1976 (trunk) --- docs/rh-log.txt | 9 +++++++++ src/r_plane.cpp | 8 ++++---- src/r_sky.cpp | 54 ++++++++++++++++++++++--------------------------- src/r_sky.h | 5 +++-- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fa255c312..e3b3ffad9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,13 @@ November 12, 2009 +- Improved sky stretching a bit: It now only stretches the sky as tall as it + needs to be: 228 pixels, not 256. It no longer stretches horizontally, + either. + + The reason it stretches to 228 and not 200 pixels is because Doom shifted + its sky texture down 28 pixels. By stretching to 228 pixels, we can keep + the sky tiled at the same height on the horizon. Skies 200 pixels tall + (or more) will continue to tile at the center of the screen when looking + directly ahead. - Cleaned up win32/i_system.cpp. - Put back the previous event-driven ticker, except now the timer isn't started until the first time it is needed. diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7ccbec09f..7e1a1e7b0 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -823,7 +823,7 @@ static void R_DrawSky (visplane_t *pl) if (pl->minx > pl->maxx) return; - dc_iscale = skyiscale >> skystretch; + dc_iscale = skyiscale; clearbuf (swall+pl->minx, pl->maxx-pl->minx+1, dc_iscale<<2); @@ -864,7 +864,7 @@ static void R_DrawSky (visplane_t *pl) } else { // The texture does not tile nicely - frontyScale = DivScale16 (skyscale << skystretch, frontyScale); + frontyScale = DivScale16 (skyscale, frontyScale); frontiScale = DivScale32 (1, frontyScale); R_DrawSkyStriped (pl); } @@ -1328,9 +1328,9 @@ void R_DrawSkyPlane (visplane_t *pl) skyflip = l->args[2] ? 0u : ~0u; frontcyl = MAX(frontskytex->GetWidth(), frontskytex->xScale >> (16 - 10)); - if (skystretch && frontskytex->GetScaledWidth() < 512) + if (skystretch) { - frontcyl >>= 1; + skymid = Scale(skymid, frontskytex->GetScaledHeight(), SKYSTRETCH_HEIGHT); } } } diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 904e80291..7463be49e 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -43,9 +43,8 @@ FTextureID skyflatnum; FTextureID sky1texture, sky2texture; fixed_t skytexturemid; fixed_t skyscale; -int skystretch; -fixed_t skyheight; fixed_t skyiscale; +bool skystretch; fixed_t sky1cyl, sky2cyl; double sky1pos, sky2pos; @@ -68,7 +67,7 @@ extern fixed_t freelookviewheight; void R_InitSkyMap () { - fixed_t fskyheight; + int skyheight; FTexture *skytex1, *skytex2; skytex1 = TexMan[sky1texture]; @@ -83,27 +82,30 @@ void R_InitSkyMap () sky2texture = sky1texture; } - fskyheight = skytex1->GetHeight() << FRACBITS; - if (skytex1->GetScaledHeight() <= 128) + // Skies between [128,200) are stretched to 200 pixels. Shorter skies do + // not stretch because it is assumed they are meant to tile, and taller + // skies do not stretch because they provide enough information for no + // repetition when looking all the way up. + skyheight = skytex1->GetScaledHeight(); + if (skyheight < 200) { - skytexturemid = r_Yaspect/2*FRACUNIT; skystretch = (r_stretchsky + && skyheight >= 128 && level.IsFreelookAllowed() && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; + // The sky is shifted down from center so that it is entirely visible + // when looking straight ahead. + skytexturemid = -28*FRACUNIT; } else { - skytexturemid = 199 * skytex1->yScale; - skystretch = 0; - // At heights above 600 pixels, the sky is drawn slightly too low. - if (SCREENHEIGHT > 600) - { - skytexturemid += FRACUNIT; - } + // The sky is directly centered so that it is entirely visible when + // looking fully up. + skytexturemid = 0; + skystretch = false; } - skyheight = fskyheight << skystretch; - if (viewwidth && viewheight) + if (viewwidth != 0 && viewheight != 0) { skyiscale = (r_Yaspect*FRACUNIT) / ((freelookviewheight * viewwidth) / viewwidth); skyscale = (((freelookviewheight * viewwidth) / viewwidth) << FRACBITS) / @@ -113,26 +115,18 @@ void R_InitSkyMap () skyscale = Scale (skyscale, 2048, FieldOfView); } + if (skystretch) + { + skyscale = Scale(skyscale, SKYSTRETCH_HEIGHT, skyheight); + skyiscale = Scale(skyiscale, skyheight, SKYSTRETCH_HEIGHT); + skytexturemid = Scale(skytexturemid, skyheight, SKYSTRETCH_HEIGHT); + } + // The standard Doom sky texture is 256 pixels wide, repeated 4 times over 360 degrees, // giving a total sky width of 1024 pixels. So if the sky texture is no wider than 1024, // we map it to a cylinder with circumfrence 1024. For larger ones, we use the width of // the texture as the cylinder's circumfrence. sky1cyl = MAX(skytex1->GetWidth(), skytex1->xScale >> (16 - 10)); sky2cyl = MAX(skytex2->GetWidth(), skytex2->xScale >> (16 - 10)); - - // If we are stretching short skies, we also stretch them horizontally by halving the - // circumfrence of the sky cylinder, unless the texture is 512 or more pixels wide, - // in which case we only stretch it vertically. - if (skystretch) - { - if (skytex1->GetScaledWidth() < 512) - { - sky1cyl >>= 1; - } - if (skytex2->GetScaledWidth() < 512) - { - sky2cyl >>= 1; - } - } } diff --git a/src/r_sky.h b/src/r_sky.h index 468b9738f..3e836ec3e 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -30,10 +30,11 @@ extern fixed_t sky1cyl, sky2cyl; extern FTextureID sky1texture, sky2texture; extern double sky1pos, sky2pos; extern fixed_t skytexturemid; -extern int skystretch; extern fixed_t skyiscale; extern fixed_t skyscale; -extern fixed_t skyheight; +extern bool skystretch; + +#define SKYSTRETCH_HEIGHT 228 // Called whenever the sky changes. void R_InitSkyMap (); From e0734b3c2dd6cdcb262fe0efa04324195671fb44 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 13 Nov 2009 21:28:39 +0000 Subject: [PATCH 085/241] - ported GZDoom's new 'skyoffset' ANIMDEFS option for compatibility purposes. SVN r1977 (trunk) --- src/g_level.cpp | 9 ++++++--- src/r_anim.cpp | 11 +++++++++++ src/r_defs.h | 5 +++++ src/textures/textures.h | 1 + 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index a2bd300ed..6e4cd6f4a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -87,11 +87,13 @@ #ifndef STAT #define STAT_NEW(map) #define STAT_END(newl) -#define STAT_SAVE(arc, hub) +#define STAT_READ(png) +#define STAT_WRITE(f) #else void STAT_NEW(const char *lev); void STAT_END(const char *newl); -void STAT_SAVE(FArchive &arc, bool hubload); +void STAT_READ(PNGHandle *png); +void STAT_WRITE(FILE *f); #endif EXTERN_CVAR (Float, sv_gravity) @@ -1524,7 +1526,6 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) } } screen->EndSerialize(arc); - STAT_SAVE(arc, hubLoad); } //========================================================================== @@ -1645,6 +1646,7 @@ void G_WriteSnapshots (FILE *file) { unsigned int i; + STAT_WRITE(file); for (i = 0; i < wadlevelinfos.Size(); i++) { if (wadlevelinfos[i].snapshot) @@ -1795,6 +1797,7 @@ void G_ReadSnapshots (PNGHandle *png) arc << pnum; } } + STAT_READ(png); png->File->ResetFilePtr(); } diff --git a/src/r_anim.cpp b/src/r_anim.cpp index c4ed59850..2ae96f58e 100644 --- a/src/r_anim.cpp +++ b/src/r_anim.cpp @@ -405,6 +405,17 @@ static void R_InitAnimDefs () { P_ParseAnimatedDoor (sc); } + else if (sc.Compare("skyoffset")) + { + sc.MustGetString (); + FTextureID picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); + sc.MustGetNumber(); + if (picnum.Exists()) + { + FTexture *tex = TexMan[picnum]; + tex->SkyOffset = sc.Number; + } + } else { sc.ScriptError (NULL); diff --git a/src/r_defs.h b/src/r_defs.h index a14a819ce..f19656afa 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -606,6 +606,11 @@ struct sector_t return lightlevel; } + secplane_t &GetSecPlane(int pos) + { + return pos == floor? floorplane:ceilingplane; + } + bool PlaneMoving(int pos); diff --git a/src/textures/textures.h b/src/textures/textures.h index b62da46d8..1bd9282a9 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -121,6 +121,7 @@ public: // doing it per patch. WORD Rotations; + SWORD SkyOffset; enum // UseTypes { From 84fda053ba306e6f7419fc81caca2af819f93938 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 14 Nov 2009 03:08:35 +0000 Subject: [PATCH 086/241] - More sky changes: Textures taller than 200 pixels but shorter than 241 are scaled to the height of a 200 pixel tall sky. Skies taller than 240 use the same scale as a 240 tall sky but are shifted down to make the top of the texture align with the top of the screen when looking fully up. Thus, by using a sky texture with a height of 240 or more pixels, the sky will be drawn with square pixels instead of the vertically elongated ones imposed by Doom's native 320x200 resolution. SVN r1978 (trunk) --- docs/rh-log.txt | 9 +++++++++ src/r_plane.cpp | 8 ++++++++ src/r_sky.cpp | 41 ++++++++++++++++++++++++++++------------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e3b3ffad9..19826e030 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +November 13, 2009 +- More sky changes: Textures taller than 200 pixels but shorter than 241 + are scaled to the height of a 200 pixel tall sky. Skies taller than 240 + use the same scale as a 240 tall sky but are shifted down to make the + top of the texture align with the top of the screen when looking fully up. + Thus, by using a sky texture with a height of 240 or more pixels, the sky + will be drawn with square pixels instead of the vertically elongated ones + imposed by Doom's native 320x200 resolution. + November 12, 2009 - Improved sky stretching a bit: It now only stretches the sky as tall as it needs to be: 228 pixels, not 256. It no longer stretches horizontally, diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7e1a1e7b0..54f68799f 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -866,6 +866,14 @@ static void R_DrawSky (visplane_t *pl) { // The texture does not tile nicely frontyScale = DivScale16 (skyscale, frontyScale); frontiScale = DivScale32 (1, frontyScale); + // Sodding crap. Fixed point sucks when you want precision. + // TODO (if I'm feeling adventurous): Rewrite the renderer to use floating point + // coordinates to keep as much precision as possible until the final + // rasterization stage so fudges like this aren't needed. + if (viewheight <= 600) + { + skymid -= FRACUNIT; + } R_DrawSkyStriped (pl); } } diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 7463be49e..83231fe70 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -82,27 +82,36 @@ void R_InitSkyMap () sky2texture = sky1texture; } - // Skies between [128,200) are stretched to 200 pixels. Shorter skies do - // not stretch because it is assumed they are meant to tile, and taller - // skies do not stretch because they provide enough information for no - // repetition when looking all the way up. + // There are various combinations for sky rendering depending on how tall the sky is: + // h < 128: Unstretched and tiled, centered on horizon + // 128 <= h < 200: Can possibly be stretched. When unstretched, the baseline is + // 28 rows below the horizon so that the top of the texture + // aligns with the top of the screen when looking straight ahead. + // When stretched, it is scaled to 228 pixels with the baseline + // in the same location as an unstretched 128-tall sky, so the top + // of the texture aligns with the top of the screen when looking + // fully up. + // h == 200: Unstretched, baseline is on horizon, and top is at the top of + // the screen when looking fully up. + // 200 < h <= 240: Squashed to consume the same height as a 200-pixel tall sky + // and aligned on the horizon. + // h > 240: Same scale as a 240-tall sky, but the baseline is shifted down + // so that the top of the texture is at the top of the screen + // when looking fully up. skyheight = skytex1->GetScaledHeight(); - if (skyheight < 200) + skystretch = false; + skytexturemid = 0; + if (skyheight >= 128 && skyheight < 200) { skystretch = (r_stretchsky && skyheight >= 128 && level.IsFreelookAllowed() && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; - // The sky is shifted down from center so that it is entirely visible - // when looking straight ahead. skytexturemid = -28*FRACUNIT; } - else + else if (skyheight > 240) { - // The sky is directly centered so that it is entirely visible when - // looking fully up. - skytexturemid = 0; - skystretch = false; + skytexturemid = (240 - skyheight) << FRACBITS; } if (viewwidth != 0 && viewheight != 0) @@ -115,7 +124,13 @@ void R_InitSkyMap () skyscale = Scale (skyscale, 2048, FieldOfView); } - if (skystretch) + if (skyheight > 200) + { + int sheight = MIN(skyheight, 240); + skyscale = Scale(skyscale, 200, sheight); + skyiscale = Scale(skyiscale, sheight, 200); + } + else if (skystretch) { skyscale = Scale(skyscale, SKYSTRETCH_HEIGHT, skyheight); skyiscale = Scale(skyiscale, skyheight, SKYSTRETCH_HEIGHT); From b57ac1aed83cbc0b3d33d3b81cc6d00bb6a100de Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 14 Nov 2009 07:52:14 +0000 Subject: [PATCH 087/241] - added a r_scaletallskies CVAR so that sky positioning can be checked more easily. - fixed: Skies with a height of exactly 200 pixels should not be stretched. SVN r1979 (trunk) --- docs/rh-log.txt | 5 +++++ src/r_sky.cpp | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 19826e030..dc8887621 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 14, 2009 (Changes by Graf Zahl) +- added a r_scaletallskies CVAR so that sky positioning can be checked + more easily. +- fixed: Skies with a height of exactly 200 pixels should not be stretched. + November 13, 2009 - More sky changes: Textures taller than 200 pixels but shorter than 241 are scaled to the height of a 200 pixel tall sky. Skies taller than 240 diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 83231fe70..1c8b520d7 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -64,6 +64,10 @@ extern fixed_t freelookviewheight; // Called whenever the view size changes. // //========================================================================== +CUSTOM_CVAR(Bool, r_scaletallskies, true, CVAR_ARCHIVE) +{ + R_InitSkyMap(); +} void R_InitSkyMap () { @@ -109,10 +113,14 @@ void R_InitSkyMap () && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; skytexturemid = -28*FRACUNIT; } - else if (skyheight > 240) + else if (r_scaletallskies && skyheight > 240) { skytexturemid = (240 - skyheight) << FRACBITS; } + else if (!r_scaletallskies && skyheight > 200) + { + skytexturemid = (200 - skyheight) << FRACBITS; + } if (viewwidth != 0 && viewheight != 0) { @@ -124,13 +132,13 @@ void R_InitSkyMap () skyscale = Scale (skyscale, 2048, FieldOfView); } - if (skyheight > 200) + if (r_scaletallskies && skyheight > 200) { int sheight = MIN(skyheight, 240); skyscale = Scale(skyscale, 200, sheight); skyiscale = Scale(skyiscale, sheight, 200); } - else if (skystretch) + else if (skyheight < 200 && skystretch) { skyscale = Scale(skyscale, SKYSTRETCH_HEIGHT, skyheight); skyiscale = Scale(skyiscale, skyheight, SKYSTRETCH_HEIGHT); From d01c402755819eb02ce7526fa66698982083cbb8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 14 Nov 2009 08:50:23 +0000 Subject: [PATCH 088/241] - Added skillinfo fix by Gez. SVN r1980 (trunk) --- docs/rh-log.txt | 1 + src/info.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index dc8887621..73bf567ce 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 14, 2009 (Changes by Graf Zahl) +- Added skillinfo fix by Gez. - added a r_scaletallskies CVAR so that sky positioning can be checked more easily. - fixed: Skies with a height of exactly 200 pixels should not be stretched. diff --git a/src/info.cpp b/src/info.cpp index 116d4e603..88a0ff7d2 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -220,7 +220,7 @@ FActorInfo *FActorInfo::GetReplacee (bool lookskill) if (lookskill && AllSkills.Size() > (unsigned)gameskill) { - FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); + skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) { Printf("Warning: incorrect actor name in definition of skill %s: \n" From 6310f32843994c986b583baab2b9026827a36b77 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 15 Nov 2009 01:04:58 +0000 Subject: [PATCH 089/241] - Do not squash skies taller than 200 into square pixels. SVN r1981 (trunk) --- docs/rh-log.txt | 3 +++ src/r_sky.cpp | 25 ++++--------------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 73bf567ce..4e778bb49 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +November 14, 2009 +- Do not squash skies taller than 200 into square pixels. + November 14, 2009 (Changes by Graf Zahl) - Added skillinfo fix by Gez. - added a r_scaletallskies CVAR so that sky positioning can be checked diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 1c8b520d7..e10a43f91 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -64,10 +64,6 @@ extern fixed_t freelookviewheight; // Called whenever the view size changes. // //========================================================================== -CUSTOM_CVAR(Bool, r_scaletallskies, true, CVAR_ARCHIVE) -{ - R_InitSkyMap(); -} void R_InitSkyMap () { @@ -97,11 +93,8 @@ void R_InitSkyMap () // fully up. // h == 200: Unstretched, baseline is on horizon, and top is at the top of // the screen when looking fully up. - // 200 < h <= 240: Squashed to consume the same height as a 200-pixel tall sky - // and aligned on the horizon. - // h > 240: Same scale as a 240-tall sky, but the baseline is shifted down - // so that the top of the texture is at the top of the screen - // when looking fully up. + // h > 200: Unstretched, but the baseline is shifted down so that the top + // of the texture is at the top of the screen when looking fully up. skyheight = skytex1->GetScaledHeight(); skystretch = false; skytexturemid = 0; @@ -113,11 +106,7 @@ void R_InitSkyMap () && !(level.flags & LEVEL_FORCENOSKYSTRETCH)) ? 1 : 0; skytexturemid = -28*FRACUNIT; } - else if (r_scaletallskies && skyheight > 240) - { - skytexturemid = (240 - skyheight) << FRACBITS; - } - else if (!r_scaletallskies && skyheight > 200) + else if (skyheight > 200) { skytexturemid = (200 - skyheight) << FRACBITS; } @@ -132,13 +121,7 @@ void R_InitSkyMap () skyscale = Scale (skyscale, 2048, FieldOfView); } - if (r_scaletallskies && skyheight > 200) - { - int sheight = MIN(skyheight, 240); - skyscale = Scale(skyscale, 200, sheight); - skyiscale = Scale(skyiscale, sheight, 200); - } - else if (skyheight < 200 && skystretch) + if (skystretch) { skyscale = Scale(skyscale, SKYSTRETCH_HEIGHT, skyheight); skyiscale = Scale(skyiscale, skyheight, SKYSTRETCH_HEIGHT); From 6161702703b681d6625b5fe05d99628c4d7d2eae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Nov 2009 08:11:14 +0000 Subject: [PATCH 090/241] - fixed: The sky baseline position needs to take texture scaling into account. SVN r1982 (trunk) --- docs/rh-log.txt | 3 +++ src/r_plane.cpp | 2 +- src/r_sky.cpp | 1 + src/textures/texture.cpp | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4e778bb49..11928da78 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +November 15, 2009 (Changes by Graf Zahl) +- fixed: The sky baseline position needs to take texture scaling into account. + November 14, 2009 - Do not squash skies taller than 200 into square pixels. diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 54f68799f..7fb98e4fc 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1313,7 +1313,7 @@ void R_DrawSkyPlane (visplane_t *pl) } frontskytex = TexMan(s->GetTexture(pos)); - if (frontskytex->UseType == FTexture::TEX_Null) + if (frontskytex == NULL || frontskytex->UseType == FTexture::TEX_Null) { // [RH] The blank texture: Use normal sky instead. goto sky1; } diff --git a/src/r_sky.cpp b/src/r_sky.cpp index e10a43f91..544c1ded9 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -110,6 +110,7 @@ void R_InitSkyMap () { skytexturemid = (200 - skyheight) << FRACBITS; } + skytexturemid = FixedMul(skytexturemid, skytex1->yScale); if (viewwidth != 0 && viewheight != 0) { diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 690a59421..88acefb47 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -144,7 +144,7 @@ FTexture::FTexture (const char *name, int lumpnum) WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT), SourceLump(lumpnum), UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false), bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), - Rotations(0xFFFF), Width(0), Height(0), WidthMask(0), Native(NULL) + Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0), WidthMask(0), Native(NULL) { id.SetInvalid(); if (name != NULL) From 3a198a29dceb30e5508c1b9e7e4c9cea90f2e3ad Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Nov 2009 14:33:35 +0000 Subject: [PATCH 091/241] - fixed: fullscreen images with texture scaling used the unscaled size for positioning. To avoid future problems with them I added a new DTA_Fullscreen option for DrawTexture. SVN r1983 (trunk) --- docs/rh-log.txt | 3 +++ src/d_main.cpp | 3 +-- src/f_finale.cpp | 33 +++++++++++++-------------------- src/v_draw.cpp | 10 ++++++++++ src/v_video.h | 1 + src/wi_stuff.cpp | 13 ++++++------- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 11928da78..6ac525820 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ November 15, 2009 (Changes by Graf Zahl) +- fixed: fullscreen images with texture scaling used the unscaled size for + positioning. To avoid future problems with them I added a new DTA_Fullscreen + option for DrawTexture. - fixed: The sky baseline position needs to take texture scaling into account. November 14, 2009 diff --git a/src/d_main.cpp b/src/d_main.cpp index d8bae9f8a..70db2f050 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -953,8 +953,7 @@ void D_PageDrawer (void) if (Page != NULL) { screen->DrawTexture (Page, 0, 0, - DTA_VirtualWidth, Page->GetWidth(), - DTA_VirtualHeight, Page->GetHeight(), + DTA_Fullscreen, true, DTA_Masked, false, DTA_BilinearFilter, true, TAG_DONE); diff --git a/src/f_finale.cpp b/src/f_finale.cpp index 82b8a9e02..e08f249eb 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -809,8 +809,8 @@ void F_DemonScroll () int yval; FTexture *final1 = TexMan(tex1); FTexture *final2 = TexMan(tex2); - int fwidth = final1->GetWidth(); - int fheight = final1->GetHeight(); + int fwidth = final1->GetScaledWidth(); + int fheight = final1->GetScaledHeight(); if (FinaleCount < 70) { @@ -884,10 +884,7 @@ void F_DrawUnderwater(void) // intentional fall-through case 2: pic = TexMan("E2END"); - screen->DrawTexture (pic, 0, 0, - DTA_VirtualWidth, pic->GetWidth(), - DTA_VirtualHeight, pic->GetHeight(), - TAG_DONE); + screen->DrawTexture (pic, 0, 0, DTA_Fullscreen, true, TAG_DONE); screen->FillBorder (NULL); paused = false; menuactive = MENU_Off; @@ -907,10 +904,7 @@ void F_DrawUnderwater(void) screen->UpdatePalette (); pic = TexMan("TITLE"); - screen->DrawTexture (pic, 0, 0, - DTA_VirtualWidth, pic->GetWidth(), - DTA_VirtualHeight, pic->GetHeight(), - TAG_DONE); + screen->DrawTexture (pic, 0, 0, DTA_Fullscreen, true, TAG_DONE); screen->FillBorder (NULL); NoWipe = 0; break; @@ -960,8 +954,8 @@ void F_BunnyScroll (void) V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); tex = TexMan(tex1); - fwidth = tex->GetWidth(); - fheight = tex->GetHeight(); + fwidth = tex->GetScaledWidth(); + fheight = tex->GetScaledHeight(); scrolled = clamp (((signed)FinaleCount-230)*fwidth/640, 0, fwidth); @@ -1315,25 +1309,24 @@ void F_Drawer (void) if (picname != NULL) { FTexture *pic = TexMan[picname]; - screen->DrawTexture (pic, 0, 0, - DTA_VirtualWidth, pic->GetWidth(), - DTA_VirtualHeight, pic->GetHeight(), - TAG_DONE); + screen->DrawTexture (pic, 0, 0, DTA_Fullscreen, true, TAG_DONE); screen->FillBorder (NULL); if (FinaleStage >= 14) { // Chess pic, draw the correct character graphic + double w = pic->GetScaledWidthDouble(); + double h = pic->GetScaledHeightDouble(); if (multiplayer) { screen->DrawTexture (TexMan["CHESSALL"], 20, 0, - DTA_VirtualWidth, pic->GetWidth(), - DTA_VirtualHeight, pic->GetHeight(), TAG_DONE); + DTA_VirtualWidth, w, + DTA_VirtualHeight, h, TAG_DONE); } else if (players[consoleplayer].CurrentPlayerClass > 0) { picname = players[consoleplayer].CurrentPlayerClass == 1 ? "CHESSC" : "CHESSM"; screen->DrawTexture (TexMan[picname], 60, 0, - DTA_VirtualWidth, pic->GetWidth(), - DTA_VirtualHeight, pic->GetHeight(), TAG_DONE); + DTA_VirtualWidth, w, + DTA_VirtualHeight, h, TAG_DONE); } } } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index f53e7cd31..e6ff521cd 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -491,6 +491,16 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag parms->virtHeight = va_arg(tags, double); break; + case DTA_Fullscreen: + boolval = va_arg(tags, INTBOOL); + if (boolval) + { + parms->x = parms->y = 0; + parms->virtWidth = img->GetScaledWidthDouble(); + parms->virtHeight = img->GetScaledHeightDouble(); + } + break; + case DTA_Alpha: parms->alpha = MIN(FRACUNIT, va_arg (tags, fixed_t)); break; diff --git a/src/v_video.h b/src/v_video.h index 6e6e6c60d..69af12ada 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -103,6 +103,7 @@ enum DTA_BilinearFilter, // bool: apply bilinear filtering to the image DTA_SpecialColormap,// pointer to FSpecialColormapParameters (likely to be forever hardware-only) DTA_ColormapStyle, // pointer to FColormapStyle (hardware-only) + DTA_Fullscreen, // Draw image fullscreen (same as DTA_VirtualWidth/Height with graphics size.) // floating point duplicates of some of the above: DTA_DestWidthF, diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index ca7b11e37..a01d15346 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -595,8 +595,8 @@ void WI_updateAnimatedBack() void WI_drawBackground() { unsigned int i; - int animwidth=320; // For a flat fill or clear background scale animations to 320x200 - int animheight=200; + double animwidth=320; // For a flat fill or clear background scale animations to 320x200 + double animheight=200; if (background) { @@ -606,11 +606,10 @@ void WI_drawBackground() // scale all animations below to fit the size of the base pic // The base pic is always scaled to fit the screen so this allows // placing the animations precisely where they belong on the base pic - animwidth = background->GetWidth(); - animheight = background->GetHeight(); + animwidth = background->GetScaledWidth(); + animheight = background->GetScaledHeight(); screen->FillBorder (NULL); - screen->DrawTexture(background, 0, 0, DTA_VirtualWidth, animwidth, - DTA_VirtualHeight, animheight, TAG_DONE); + screen->DrawTexture(background, 0, 0, DTA_Fullscreen, true, TAG_DONE); } else { @@ -666,7 +665,7 @@ void WI_drawBackground() } if (a->ctr >= 0) screen->DrawTexture(a->p[a->ctr], a->loc.x, a->loc.y, - DTA_VirtualWidth, animwidth, DTA_VirtualHeight, animheight, TAG_DONE); + DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, TAG_DONE); } } From 53a717673f39842e85c1f49657322e3c0a4899d7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Nov 2009 07:18:19 +0000 Subject: [PATCH 092/241] - reverted the change that makes 0-damage projectiles call P_DamageMobj. Both Hexen and Heretic depend on such projectiles not doing it as do many mods that create snow/rain effects plus any terrain splash mod. SVN r1984 (trunk) --- docs/rh-log.txt | 5 +++++ src/p_map.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6ac525820..c1c2593d2 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 17, 2009 (Changes by Graf Zahl) +- reverted the change that makes 0-damage projectiles call P_DamageMobj. + Both Hexen and Heretic depend on such projectiles not doing it as do many + mods that create snow/rain effects plus any terrain splash mod. + November 15, 2009 (Changes by Graf Zahl) - fixed: fullscreen images with texture scaling used the unscaled size for positioning. To avoid future problems with them I added a new DTA_Fullscreen diff --git a/src/p_map.cpp b/src/p_map.cpp index 223f62816..4a5f91e50 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1091,7 +1091,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } // Do damage damage = tm.thing->GetMissileDamage ((tm.thing->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1); - if (damage >= 0) + if ((damage > 0) || (tm.thing->flags6 & MF6_FORCEPAIN)) { P_DamageMobj (thing, tm.thing, tm.thing->target, damage, tm.thing->DamageType); if (damage > 0) From 23d0d70ea65a997ee855e80ea000fc2b538a4d32 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Nov 2009 13:50:46 +0000 Subject: [PATCH 093/241] - fixed: R_PointToAngle could overflow with very long vectors passed to it. This caused rendering bugs on some maps. (Interestingly the only other port having a safeguard for this in place was PrBoom.) SVN r1985 (trunk) --- docs/rh-log.txt | 3 ++ src/r_main.cpp | 95 ++++++++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c1c2593d2..453bdf4d9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ November 17, 2009 (Changes by Graf Zahl) +- fixed: R_PointToAngle could overflow with very long vectors passed to + it. This caused rendering bugs on some maps. (Interestingly the only + other port having a safeguard for this in place was PrBoom.) - reverted the change that makes 0-damage projectiles call P_DamageMobj. Both Hexen and Heretic depend on such projectiles not doing it as do many mods that create snow/rain effects plus any terrain splash mod. diff --git a/src/r_main.cpp b/src/r_main.cpp index bcec61c73..e960c7c5c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -264,58 +264,71 @@ angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x, fixed_t y) return 0; } - if (x >= 0) + // We need to be aware of overflows here. If the values get larger than INT_MAX/4 + // this code won't work anymore. + + if (x < INT_MAX/4 && x > -INT_MAX/4 && y < INT_MAX/4 && y > -INT_MAX/4) { - if (y >= 0) + if (x >= 0) { - if (x > y) - { // octant 0 - return SlopeDiv(y, x); + if (y >= 0) + { + if (x > y) + { // octant 0 + return SlopeDiv(y, x); + } + else + { // octant 1 + return ANG90 - 1 - SlopeDiv(x, y); + } } - else - { // octant 1 - return ANG90 - 1 - SlopeDiv(x, y); + else // y < 0 + { + y = -y; + if (x > y) + { // octant 8 + return 0 - SlopeDiv(y, x); + } + else + { // octant 7 + return ANG270 + SlopeDiv(x, y); + } } } - else // y < 0 + else // x < 0 { - y = -y; - if (x > y) - { // octant 8 - return 0 - SlopeDiv(y, x); + x = -x; + if (y >= 0) + { + if (x > y) + { // octant 3 + return ANG180 - 1 - SlopeDiv(y, x); + } + else + { // octant 2 + return ANG90 + SlopeDiv(x, y); + } } - else - { // octant 7 - return ANG270 + SlopeDiv(x, y); + else // y < 0 + { + y = -y; + if (x > y) + { // octant 4 + return ANG180 + SlopeDiv(y, x); + } + else + { // octant 5 + return ANG270 - 1 - SlopeDiv(x, y); + } } } } - else // x < 0 + else { - x = -x; - if (y >= 0) - { - if (x > y) - { // octant 3 - return ANG180 - 1 - SlopeDiv(y, x); - } - else - { // octant 2 - return ANG90 + SlopeDiv(x, y); - } - } - else // y < 0 - { - y = -y; - if (x > y) - { // octant 4 - return ANG180 + SlopeDiv(y, x); - } - else - { // octant 5 - return ANG270 - 1 - SlopeDiv(x, y); - } - } + // we have to use the slower but more precise floating point atan2 function here. + // (use quickertoint to speed this up because the CRT's conversion is rather slow and + // this is used in time critical code.) + return quickertoint((float)(atan2f(float(y-viewy), float(x-viewx)) * (ANGLE_180/M_PI))); } } From 424c6e8963187392ac3c937d08514d15f25c0d00 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Nov 2009 23:09:21 +0000 Subject: [PATCH 094/241] - fixed: P_NowayTraverse was called with a trace distance of 128 instead of the 64 that should have been used. SVN r1986 (trunk) --- docs/rh-log.txt | 2 ++ src/p_map.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 453bdf4d9..48abfcc2c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 17, 2009 (Changes by Graf Zahl) +- fixed: P_NowayTraverse was called with a trace distance of 128 instead of + the 64 that should have been used. - fixed: R_PointToAngle could overflow with very long vectors passed to it. This caused rendering bugs on some maps. (Interestingly the only other port having a safeguard for this in place was PrBoom.) diff --git a/src/p_map.cpp b/src/p_map.cpp index 4a5f91e50..d95d81d4b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4046,12 +4046,16 @@ bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy) void P_UseLines (player_t *player) { angle_t angle; + fixed_t x1, y1; fixed_t x2, y2; bool foundline; foundline = false; angle = player->mo->angle >> ANGLETOFINESHIFT; + x1 = player->mo->x + (USERANGE>>FRACBITS)*finecosine[angle]; + y1 = player->mo->y + (USERANGE>>FRACBITS)*finesine[angle]; + x2 = player->mo->x + (USERANGE>>FRACBITS)*finecosine[angle]*2; y2 = player->mo->y + (USERANGE>>FRACBITS)*finesine[angle]*2; @@ -4067,7 +4071,7 @@ void P_UseLines (player_t *player) int spac = SECSPAC_Use; if (foundline) spac |= SECSPAC_UseWall; if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction (player->mo, spac)) && - P_NoWayTraverse (player->mo, x2, y2)) + P_NoWayTraverse (player->mo, x1, y1)) { S_Sound (player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); } From 51eb6465a2b87645ac39e7431aaa82adfb546bc1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 18 Nov 2009 04:45:20 +0000 Subject: [PATCH 095/241] - Fixed two bugs in FMODSoundRenderer::HandleChannelDelay(): * Looping sounds that have been playing for a very long time, were evicted, and then were restarted need to have their positions clamped to lie within the bounds of the sounds. If we try to set a start position very far beyond the end, it will overflow inside FMOD and not work. * A start time of 0 is not actually valid and means the sound was never assigned a start time. - The latter bug also reveals a problem with starting looped sounds evicted: They need to be assigned a start time so if they should have the opportunity to start later, they will be properly synchronized. SVN r1987 (trunk) --- docs/rh-log.txt | 12 ++++++++++++ src/s_sound.cpp | 1 + src/sound/fmodsound.cpp | 34 +++++++++++++++++++++++++++++++++- src/sound/fmodsound.h | 3 +++ src/sound/i_sound.cpp | 7 ++++++- src/sound/i_sound.h | 3 +++ src/v_video.h | 6 +++--- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 48abfcc2c..79ea15408 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,15 @@ +November 17, 2009 +- Fixed two bugs in FMODSoundRenderer::HandleChannelDelay(): + * Looping sounds that have been playing for a very long time, were evicted, + and then were restarted need to have their positions clamped to lie + within the bounds of the sounds. If we try to set a start position very + far beyond the end, it will overflow inside FMOD and not work. + * A start time of 0 is not actually valid and means the sound was never + assigned a start time. +- The latter bug also reveals a problem with starting looped sounds evicted: + They need to be assigned a start time so if they should have the opportunity + to start later, they will be properly synchronized. + November 17, 2009 (Changes by Graf Zahl) - fixed: P_NowayTraverse was called with a trace distance of 128 instead of the 64 that should have been used. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 1287873a5..4fbef6ae1 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1053,6 +1053,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO if (chan == NULL && (chanflags & CHAN_LOOP)) { chan = (FSoundChan*)S_GetChannel(NULL); + GSnd->MarkStartTime(chan); chanflags |= CHAN_EVICTED; } if (attenuation > 0) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 724d701fe..e278563a6 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1650,6 +1650,10 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * } if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) { + // FMOD seems to get confused if you stop a channel right after + // starting it, so hopefully this function will never fail. + // (Presumably you need an update between them, but I haven't + // tested this hypothesis.) chan->stop(); return NULL; } @@ -1674,6 +1678,19 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * return 0; } +//========================================================================== +// +// FMODSoundRenderer :: MarkStartTime +// +// Marks a channel's start time without actually playing it. +// +//========================================================================== + +void FMODSoundRenderer::MarkStartTime(FISoundChannel *chan) +{ + Sys->getDSPClock(&chan->StartTime.Hi, &chan->StartTime.Lo); +} + //========================================================================== // // FMODSoundRenderer :: HandleChannelDelay @@ -1704,11 +1721,26 @@ bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel * } reuse_chan->StartTime.AsOne = QWORD(nowtime.AsOne - seekpos * OutputRate / freq); } - else + else if (reuse_chan->StartTime.AsOne != 0) { QWORD difftime = nowtime.AsOne - reuse_chan->StartTime.AsOne; if (difftime > 0) { + // Clamp the position of looping sounds to be within the sound. + // If we try to start it several minutes past its normal end, + // FMOD doesn't like that. + if (flags & SNDF_LOOP) + { + FMOD::Sound *sound; + if (FMOD_OK == chan->getCurrentSound(&sound)) + { + unsigned int len; + if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_MS)) + { + difftime %= len; + } + } + } return chan->setPosition((unsigned int)(difftime / OutputRate), FMOD_TIMEUNIT_MS) == FMOD_OK; } } diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 78ba8aa86..3f31481bf 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -33,6 +33,9 @@ public: // Stops a sound channel. void StopChannel (FISoundChannel *chan); + // Marks a channel's start time without actually playing it. + void MarkStartTime (FISoundChannel *chan); + // Returns position of sound on this channel, in samples. unsigned int GetPosition(FISoundChannel *chan); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index c4b0c63e0..0009b48e2 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -159,7 +159,7 @@ public: return NULL; } - // Starts a sound. (No, not really.) + // Starts a sound. FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) { return NULL; @@ -169,6 +169,11 @@ public: return NULL; } + // Marks a channel's start time without actually playing it. + void MarkStartTime (FISoundChannel *chan) + { + } + // Returns position of sound on this channel, in samples. unsigned int GetPosition(FISoundChannel *chan) { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 1ff535d93..31f401093 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -109,6 +109,9 @@ public: // Stops a sound channel. virtual void StopChannel (FISoundChannel *chan) = 0; + // Marks a channel's start time without actually playing it. + virtual void MarkStartTime (FISoundChannel *chan) = 0; + // Returns position of sound on this channel, in samples. virtual unsigned int GetPosition(FISoundChannel *chan) = 0; diff --git a/src/v_video.h b/src/v_video.h index 69af12ada..e722c62db 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -232,7 +232,7 @@ public: uint32 fillcolor; FRemapTable *remap; const BYTE *translation; - DWORD colorOverlay; + uint32 colorOverlay; INTBOOL alphaChannel; INTBOOL flipX; fixed_t shadowAlpha; @@ -404,7 +404,7 @@ public: virtual bool WipeDo(int ticks); virtual void WipeCleanup(); - DWORD GetLastFPS() const { return LastCount; } + uint32 GetLastFPS() const { return LastCount; } #ifdef _WIN32 virtual void PaletteChanged () = 0; @@ -418,7 +418,7 @@ protected: DFrameBuffer () {} private: - DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; + uint32 LastMS, LastSec, FrameCount, LastCount, LastTic; }; From 2b5f765982e22e6cc8b2fc68306ddb8c505409bc Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 19 Nov 2009 01:49:19 +0000 Subject: [PATCH 096/241] - Added padding around packed textures to compensate for apparent NVidia texture coordinate imprecision. SVN r1988 (trunk) --- docs/rh-log.txt | 4 +++ src/win32/fb_d3d9.cpp | 60 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 79ea15408..8bf80f425 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 18, 2009 +- Added padding around packed textures to compensate for apparent NVidia + texture coordinate imprecision. + November 17, 2009 - Fixed two bugs in FMODSoundRenderer::HandleChannelDelay(): * Looping sounds that have been playing for a very long time, were evicted, diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 3104b8311..8e82b5e4f 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -3,7 +3,7 @@ ** Code to let ZDoom use Direct3D 9 as a simple framebuffer ** **--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit +** Copyright 1998-2009 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -96,6 +96,9 @@ struct D3DFB::PackedTexture // Texture coordinates for this image float Left, Top, Right, Bottom; + + // Texture has extra space on the border? + bool Padded; }; struct D3DFB::PackingTexture @@ -1830,9 +1833,12 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D bestpack = new PackingTexture(this, w, h, format); bestpack->OneUse = true; bestbox = bestpack->GetBestFit(w, h, area); + bestbox->Padded = false; } else { // Try to find space in an existing packing texture. + w += 2; // Add padding + h += 2; int bestarea = INT_MAX; int bestareaever = w * h; bestpack = NULL; @@ -1861,6 +1867,7 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D bestpack = new PackingTexture(this, 256, 256, format); bestbox = bestpack->GetBestFit(w, h, bestarea); } + bestbox->Padded = true; } bestpack->AllocateImage(bestbox, w, h); return bestbox; @@ -1990,10 +1997,10 @@ void D3DFB::PackingTexture::AllocateImage(D3DFB::PackedTexture *box, int w, int box->Area.right = box->Area.left + w; box->Area.bottom = box->Area.top + h; - box->Left = float(box->Area.left) / Width; - box->Right = float(box->Area.right) / Width; - box->Top = float(box->Area.top) / Height; - box->Bottom = float(box->Area.bottom) / Height; + box->Left = float(box->Area.left + box->Padded) / Width; + box->Right = float(box->Area.right - box->Padded) / Width; + box->Top = float(box->Area.top + box->Padded) / Height; + box->Bottom = float(box->Area.bottom - box->Padded) / Height; // Remove it from the empty list. *(box->Prev) = box->Next; @@ -2012,7 +2019,6 @@ void D3DFB::PackingTexture::AllocateImage(D3DFB::PackedTexture *box, int w, int box->Prev = &UsedList; // If we didn't use the whole box, split the remainder into the empty list. - if (box->Area.bottom + 7 < start.bottom && box->Area.right + 7 < start.right) { // Split like this: @@ -2236,6 +2242,7 @@ bool D3DTex::CheckWrapping(bool wrapping) // If it needs to wrap, then it can't be packed inside another texture. return Box->Owner->OneUse; } + //========================================================================== // // D3DTex :: Create @@ -2280,6 +2287,7 @@ bool D3DTex::Update() D3DSURFACE_DESC desc; D3DLOCKED_RECT lrect; RECT rect; + BYTE *dest; assert(Box != NULL); assert(Box->Owner != NULL); @@ -2295,7 +2303,45 @@ bool D3DTex::Update() { return false; } - GameTex->FillBuffer((BYTE *)lrect.pBits, lrect.Pitch, GameTex->GetHeight(), ToTexFmt(desc.Format)); + dest = (BYTE *)lrect.pBits; + if (Box->Padded) + { + dest += lrect.Pitch + (desc.Format == D3DFMT_L8 ? 1 : 4); + } + GameTex->FillBuffer(dest, lrect.Pitch, GameTex->GetHeight(), ToTexFmt(desc.Format)); + if (Box->Padded) + { + // Clear top padding row. + dest = (BYTE *)lrect.pBits; + int numbytes = GameTex->GetWidth() + 2; + if (desc.Format != D3DFMT_L8) + { + numbytes <<= 2; + } + memset(dest, 0, numbytes); + dest += lrect.Pitch; + // Clear left and right padding columns. + if (desc.Format == D3DFMT_L8) + { + for (int y = Box->Area.bottom - Box->Area.top - 2; y > 0; --y) + { + dest[0] = 0; + dest[numbytes-1] = 0; + dest += lrect.Pitch; + } + } + else + { + for (int y = Box->Area.bottom - Box->Area.top - 2; y > 0; --y) + { + *(DWORD *)dest = 0; + *(DWORD *)(dest + numbytes - 4) = 0; + dest += lrect.Pitch; + } + } + // Clear bottom padding row. + memset(dest, 0, numbytes); + } Box->Owner->Tex->UnlockRect(0); return true; } From eca9b4981b091e49ee4d4c2c711efce1bdbed2d0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 19 Nov 2009 07:21:10 +0000 Subject: [PATCH 097/241] - fixed the R_PointToAngle fix from r1985. SVN r1989 (trunk) --- src/r_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index e960c7c5c..b528373ee 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -328,7 +328,7 @@ angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x, fixed_t y) // we have to use the slower but more precise floating point atan2 function here. // (use quickertoint to speed this up because the CRT's conversion is rather slow and // this is used in time critical code.) - return quickertoint((float)(atan2f(float(y-viewy), float(x-viewx)) * (ANGLE_180/M_PI))); + return quickertoint((float)(atan2f(float(y), float(x)) * (ANGLE_180/M_PI))); } } From 344dda4a1a824bce3674e285fda3fe2bd31b29e7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 20 Nov 2009 05:34:20 +0000 Subject: [PATCH 098/241] - Replaced toint/quickertoint with the portable routines from xs_Float.h. The former used fistp, which is not portable across platforms, so cannot be used in the play simulation. They were only suitable for the renderer. xs_Float.h also has a very fast float->fixed conversion, so FLOAT2FIXED uses that now. (And I also learned that the FPU's round to nearest is not the rounding I learned in grade school but actually Banker's Rounding. I had no idea.) (Also, also, the only thing that could have made quickertoint faster than toint was that it stored a 32-bit int. I never timed them, and I doubt in practice there was any real difference between the two.) - Changed atan2f to atan2. Using floats is not a win, because the result is returned as a double on the x87 stack, which the caller then needs to cast down to a float using fst/fld. SVN r1990 (trunk) --- docs/rh-log.txt | 12 +++++++ src/basicinlines.h | 10 ------ src/basictypes.h | 4 +++ src/g_skill.cpp | 1 + src/gccinlines.h | 24 ------------- src/m_fixed.h | 6 ++++ src/mscinlines.h | 16 --------- src/r_main.cpp | 6 ++-- src/r_plane.cpp | 2 +- src/r_segs.cpp | 50 ++++++++++++++-------------- src/thingdef/thingdef_expression.cpp | 1 + src/vectors.h | 3 -- zdoom.vcproj | 4 +++ 13 files changed, 56 insertions(+), 83 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 8bf80f425..2b7bbbe9a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,15 @@ +November 19, 2009 +- Replaced toint/quickertoint with the portable routines from xs_Float.h. The + former used fistp, which is not portable across platforms, so cannot be + used in the play simulation. They were only suitable for the renderer. + xs_Float.h also has a very fast float->fixed conversion, so FLOAT2FIXED + uses that now. + (And I also learned that the FPU's round to nearest is not the rounding I + learned in grade school but actually Banker's Rounding. I had no idea.) + (Also, also, the only thing that could have made quickertoint faster than + toint was that it stored a 32-bit int. I never timed them, and I doubt in + practice there was any real difference between the two.) + November 18, 2009 - Added padding around packed textures to compensate for apparent NVidia texture coordinate imprecision. diff --git a/src/basicinlines.h b/src/basicinlines.h index 4bc211f99..fa6ce822b 100644 --- a/src/basicinlines.h +++ b/src/basicinlines.h @@ -201,13 +201,3 @@ static __forceinline SDWORD ksgn (SDWORD a) else if (a > 0) return 1; else return 0; } - -static __forceinline int toint (float v) -{ - return int(v); -} - -static __forceinline int quickertoint (float v) -{ - return int(v); -} diff --git a/src/basictypes.h b/src/basictypes.h index 37d7aec75..3aa4f4635 100644 --- a/src/basictypes.h +++ b/src/basictypes.h @@ -23,6 +23,10 @@ typedef int64_t SQWORD; typedef uint64_t QWORD; #endif +typedef SDWORD int32; +typedef float real32; +typedef double real64; + // windef.h, included by windows.h, has its own incompatible definition // of DWORD as a long. In files that mix Doom and Windows code, you // must define USE_WINDOWS_DWORD before including doomtype.h so that diff --git a/src/g_skill.cpp b/src/g_skill.cpp index 3d2ef9bf2..a91e38264 100644 --- a/src/g_skill.cpp +++ b/src/g_skill.cpp @@ -40,6 +40,7 @@ #include "gi.h" #include "templates.h" #include "v_font.h" +#include "m_fixed.h" TArray AllSkills; int DefaultSkill = -1; diff --git a/src/gccinlines.h b/src/gccinlines.h index 3b987895a..4f1ec7e5e 100644 --- a/src/gccinlines.h +++ b/src/gccinlines.h @@ -331,27 +331,3 @@ static inline SDWORD ksgn (SDWORD a) :"%cc"); return result; } - -static inline int toint (float v) -{ - volatile QWORD result; - - asm volatile - ("fistpq %0" - :"=m" (result) - :"t" (v) - :"%st"); - return result; -} - -static inline int quickertoint (float v) -{ - volatile int result; - - asm volatile - ("fistpl %0" - :"=m" (result) - :"t" (v) - :"%st"); - return result; -} diff --git a/src/m_fixed.h b/src/m_fixed.h index 3d7f577b7..14db59d63 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -20,6 +20,8 @@ #include "basicinlines.h" #endif +#include "xs_Float.h" + #define MAKESAFEDIVSCALE(x) \ inline SDWORD SafeDivScale##x (SDWORD a, SDWORD b) \ { \ @@ -134,4 +136,8 @@ inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval) return num % den; } + +#define FLOAT2FIXED(f) xs_Fix<16>::ToFix(f) +#define FIXED2FLOAT(f) ((f) / float(65536)) + #endif diff --git a/src/mscinlines.h b/src/mscinlines.h index 0a5fdb798..c7f2527f4 100644 --- a/src/mscinlines.h +++ b/src/mscinlines.h @@ -348,20 +348,4 @@ __forceinline SDWORD ksgn (SDWORD a) __asm adc eax,0 } -__forceinline int toint (float v) -{ - SQWORD res; - __asm fld v; - __asm fistp res; - return (int)res; -} - -__forceinline int quickertoint (float v) -{ - SDWORD res; - __asm fld v; - __asm fistp res; - return (int)res; -} - #pragma warning (default: 4035) diff --git a/src/r_main.cpp b/src/r_main.cpp index b528373ee..789388842 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -326,9 +326,7 @@ angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x, fixed_t y) else { // we have to use the slower but more precise floating point atan2 function here. - // (use quickertoint to speed this up because the CRT's conversion is rather slow and - // this is used in time critical code.) - return quickertoint((float)(atan2f(float(y), float(x)) * (ANGLE_180/M_PI))); + return xs_RoundToUInt(atan2(double(y), double(x)) * (ANGLE_180/M_PI)); } } @@ -534,7 +532,7 @@ void R_SetVisibility (float vis) return; } - r_BaseVisibility = toint (vis * 65536.f); + r_BaseVisibility = xs_RoundToInt(vis * 65536.f); // Prevent overflow on walls if (r_BaseVisibility < 0 && r_BaseVisibility < -MaxVisForWall) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7fb98e4fc..c9612c24c 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -336,7 +336,7 @@ void R_MapTiltedPlane (int y, int x1) { uz = (iz + plane_sz[0]*width) * planelightfloat; vz = iz * planelightfloat; - R_CalcTiltedLighting (toint (vz), toint (uz), width); + R_CalcTiltedLighting (xs_RoundToInt(vz), xs_RoundToInt(uz), width); } uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx); diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 8782f5631..06b793af4 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2006,29 +2006,29 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat) x = WallSX1; l = top / bot; - swall[x] = quickertoint (l * WallDepthScale + WallDepthOrg); - lwall[x] = quickertoint (l * xrepeat); + swall[x] = xs_RoundToInt(l * WallDepthScale + WallDepthOrg); + lwall[x] = xs_RoundToInt(l * xrepeat); // As long as l is invalid, step one column at a time so that // we can get as many correct texture columns as possible. while (l > 1.0 && x+1 < WallSX2) { l = (top += WallUoverZstep) / (bot += WallInvZstep); x++; - swall[x] = quickertoint (l * WallDepthScale + WallDepthOrg); - lwall[x] = quickertoint (l * xrepeat); + swall[x] = xs_RoundToInt(l * WallDepthScale + WallDepthOrg); + lwall[x] = xs_RoundToInt(l * xrepeat); } l *= xrepeat; while (x+4 < WallSX2) { top += topinc; bot += botinc; ol = l; l = top / bot; - swall[x+4] = quickertoint (l * WallDepthScale + WallDepthOrg); - lwall[x+4] = quickertoint (l *= xrepeat); + swall[x+4] = xs_RoundToInt(l * WallDepthScale + WallDepthOrg); + lwall[x+4] = xs_RoundToInt(l *= xrepeat); i = (ol+l) * 0.5f; - lwall[x+2] = quickertoint (i); - lwall[x+1] = quickertoint ((ol+i) * 0.5f); - lwall[x+3] = quickertoint ((l+i) * 0.5f); + lwall[x+2] = xs_RoundToInt(i); + lwall[x+1] = xs_RoundToInt((ol+i) * 0.5f); + lwall[x+3] = xs_RoundToInt((l+i) * 0.5f); swall[x+2] = ((swall[x]+swall[x+4])>>1); swall[x+1] = ((swall[x]+swall[x+2])>>1); swall[x+3] = ((swall[x+4]+swall[x+2])>>1); @@ -2038,25 +2038,25 @@ void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat) { top += topinc * 0.5f; bot += botinc * 0.5f; ol = l; l = top / bot; - swall[x+2] = quickertoint (l * WallDepthScale + WallDepthOrg); - lwall[x+2] = quickertoint (l *= xrepeat); + swall[x+2] = xs_RoundToInt(l * WallDepthScale + WallDepthOrg); + lwall[x+2] = xs_RoundToInt(l *= xrepeat); - lwall[x+1] = quickertoint ((l+ol)*0.5f); + lwall[x+1] = xs_RoundToInt((l+ol)*0.5f); swall[x+1] = (swall[x]+swall[x+2])>>1; x += 2; } if (x+1 < WallSX2) { l = (top + WallUoverZstep) / (bot + WallInvZstep); - swall[x+1] = quickertoint (l * WallDepthScale + WallDepthOrg); - lwall[x+1] = quickertoint (l * xrepeat); + swall[x+1] = xs_RoundToInt(l * WallDepthScale + WallDepthOrg); + lwall[x+1] = xs_RoundToInt(l * xrepeat); } /* for (x = WallSX1; x < WallSX2; x++) { frac = top / bot; - lwall[x] = quickertoint (frac * xrepeat); - swall[x] = quickertoint (frac * WallDepthScale + WallDepthOrg); + lwall[x] = xs_RoundToInt(frac * xrepeat); + swall[x] = xs_RoundToInt(frac * WallDepthScale + WallDepthOrg); top += WallUoverZstep; bot += WallInvZstep; } @@ -2108,39 +2108,39 @@ void PrepLWall (fixed_t *lwall, fixed_t walxrepeat) x = WallSX1; l = top / bot; - lwall[x] = quickertoint (l * xrepeat); + lwall[x] = xs_RoundToInt(l * xrepeat); // As long as l is invalid, step one column at a time so that // we can get as many correct texture columns as possible. while (l > 1.0 && x+1 < WallSX2) { l = (top += WallUoverZstep) / (bot += WallInvZstep); - lwall[++x] = quickertoint (l * xrepeat); + lwall[++x] = xs_RoundToInt(l * xrepeat); } l *= xrepeat; while (x+4 < WallSX2) { top += topinc; bot += botinc; ol = l; l = top / bot; - lwall[x+4] = quickertoint (l *= xrepeat); + lwall[x+4] = xs_RoundToInt(l *= xrepeat); i = (ol+l) * 0.5f; - lwall[x+2] = quickertoint (i); - lwall[x+1] = quickertoint ((ol+i) * 0.5f); - lwall[x+3] = quickertoint ((l+i) * 0.5f); + lwall[x+2] = xs_RoundToInt(i); + lwall[x+1] = xs_RoundToInt((ol+i) * 0.5f); + lwall[x+3] = xs_RoundToInt((l+i) * 0.5f); x += 4; } if (x+2 < WallSX2) { top += topinc * 0.5f; bot += botinc * 0.5f; ol = l; l = top / bot; - lwall[x+2] = quickertoint (l *= xrepeat); - lwall[x+1] = quickertoint ((l+ol)*0.5f); + lwall[x+2] = xs_RoundToInt(l *= xrepeat); + lwall[x+1] = xs_RoundToInt((l+ol)*0.5f); x += 2; } if (x+1 < WallSX2) { l = (top + WallUoverZstep) / (bot + WallInvZstep); - lwall[x+1] = quickertoint (l * xrepeat); + lwall[x+1] = xs_RoundToInt(l * xrepeat); } // fix for rounding errors diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index eee2b3608..2511b93a8 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -49,6 +49,7 @@ #include "p_lnspec.h" #include "doomstat.h" #include "thingdef_exp.h" +#include "m_fixed.h" int testglobalvar = 1337; // just for having one global variable to test with DEFINE_GLOBAL_VARIABLE(testglobalvar) diff --git a/src/vectors.h b/src/vectors.h index ea11ab611..013077042 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1230,7 +1230,4 @@ typedef TRotator FRotator; typedef TMatrix3x3 FMatrix3x3; typedef TAngle FAngle; -#define FLOAT2FIXED(f) fixed_t((f) * float(65536)) -#define FIXED2FLOAT(f) ((f) / float(65536)) - #endif diff --git a/zdoom.vcproj b/zdoom.vcproj index 681c2ce69..f31bbbbe2 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1593,6 +1593,10 @@ RelativePath=".\src\x86.h" > + + From 82db01f5ef691fa07c43604b229cd60c81a0fb7b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 20 Nov 2009 06:01:10 +0000 Subject: [PATCH 099/241] - Forgot xs_Float.h with previous commit. SVN r1991 (trunk) --- src/xs_Float.h | 224 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/xs_Float.h diff --git a/src/xs_Float.h b/src/xs_Float.h new file mode 100644 index 000000000..19300b2fc --- /dev/null +++ b/src/xs_Float.h @@ -0,0 +1,224 @@ +// ==================================================================================================================== +// ==================================================================================================================== +// xs_Float.h +// +// Source: "Know Your FPU: Fixing Floating Fast" +// http://www.stereopsis.com/sree/fpu2006.html +// +// xs_CRoundToInt: Round toward nearest, but ties round toward even (just like FISTP) +// xs_ToInt: Round toward zero, just like the C (int) cast +// xs_FloorToInt: Round down +// xs_CeilToInt: Round up +// xs_RoundToInt: Round toward nearest, but ties round up +// ==================================================================================================================== +// ==================================================================================================================== +#ifndef _xs_FLOAT_H_ +#define _xs_FLOAT_H_ + +// ==================================================================================================================== +// Defines +// ==================================================================================================================== +#ifndef _xs_DEFAULT_CONVERSION +#define _xs_DEFAULT_CONVERSION 0 +#endif //_xs_DEFAULT_CONVERSION + + +#if __BIG_ENDIAN__ + #define _xs_iexp_ 0 + #define _xs_iman_ 1 +#else + #define _xs_iexp_ 1 //intel is little endian + #define _xs_iman_ 0 +#endif //BigEndian_ + +#ifdef __GNUC__ +#define finline inline +#else +#define finline __forceinline +#endif + +union _xs_doubleints +{ + real64 val; + uint32 ival[2]; +}; + +#if 0 +#define _xs_doublecopysgn(a,b) ((int32*)&a)[_xs_iexp_]&=~(((int32*)&b)[_xs_iexp_]&0x80000000) +#define _xs_doubleisnegative(a) ((((int32*)&a)[_xs_iexp_])|0x80000000) +#endif + +// ==================================================================================================================== +// Constants +// ==================================================================================================================== +const real64 _xs_doublemagic = real64 (6755399441055744.0); //2^52 * 1.5, uses limited precisicion to floor +const real64 _xs_doublemagicdelta = (1.5e-8); //almost .5f = .5f + 1e^(number of exp bit) +const real64 _xs_doublemagicroundeps = (.5f-_xs_doublemagicdelta); //almost .5f = .5f - 1e^(number of exp bit) + + +// ==================================================================================================================== +// Prototypes +// ==================================================================================================================== +static int32 xs_CRoundToInt (real64 val, real64 dmr = _xs_doublemagic); +static int32 xs_ToInt (real64 val, real64 dme = -_xs_doublemagicroundeps); +static int32 xs_FloorToInt (real64 val, real64 dme = _xs_doublemagicroundeps); +static int32 xs_CeilToInt (real64 val, real64 dme = _xs_doublemagicroundeps); +static int32 xs_RoundToInt (real64 val); + +//int32 versions +finline static int32 xs_CRoundToInt (int32 val) {return val;} +finline static int32 xs_ToInt (int32 val) {return val;} + + + +// ==================================================================================================================== +// Fix Class +// ==================================================================================================================== +template class xs_Fix +{ +public: + typedef int32 Fix; + + // ==================================================================================================================== + // Basic Conversion from Numbers + // ==================================================================================================================== + finline static Fix ToFix (int32 val) {return val<>N;} + + + +protected: + // ==================================================================================================================== + // Helper function - mainly to preserve _xs_DEFAULT_CONVERSION + // ==================================================================================================================== + finline static int32 xs_ConvertToFixed (real64 val) + { + #if _xs_DEFAULT_CONVERSION==0 + return xs_CRoundToInt(val, _xs_doublemagic/(1<= 1400 + // VC++ 2005's standard cast is a little bit faster than this + // magic number code. (Which is pretty amazing!) SSE has the + // fastest C-style float->int conversion, but unfortunately, + // checking for SSE support every time you need to do a + // conversion completely negates its performance advantage. + return int32(val); +#else +#if _xs_DEFAULT_CONVERSION==0 + return (val<0) ? xs_CRoundToInt(val-dme) : + xs_CRoundToInt(val+dme); +#else + return int32(val); +#endif +#endif +} + + +// ==================================================================================================================== +finline static int32 xs_FloorToInt(real64 val, real64 dme) +{ +#if _xs_DEFAULT_CONVERSION==0 + return xs_CRoundToInt (val - dme); +#else + return floor(val); +#endif +} + + +// ==================================================================================================================== +finline static int32 xs_CeilToInt(real64 val, real64 dme) +{ +#if _xs_DEFAULT_CONVERSION==0 + return xs_CRoundToInt (val + dme); +#else + return ceil(val); +#endif +} + + +// ==================================================================================================================== +finline static int32 xs_RoundToInt(real64 val) +{ +#if _xs_DEFAULT_CONVERSION==0 + // Yes, it is important that two fadds be generated, so you cannot override the dmr + // passed to xs_CRoundToInt with _xs_doublemagic + _xs_doublemagicdelta. If you do, + // you'll end up with Banker's Rounding again. + return xs_CRoundToInt (val + _xs_doublemagicdelta); +#else + return floor(val+.5); +#endif +} + + + +// ==================================================================================================================== +// ==================================================================================================================== +// Unsigned variants +// ==================================================================================================================== +// ==================================================================================================================== +finline static uint32 xs_CRoundToUInt(real64 val) +{ + return (uint32)xs_CRoundToInt(val); +} + +finline static uint32 xs_FloorToUInt(real64 val) +{ + return (uint32)xs_FloorToInt(val); +} + +finline static uint32 xs_CeilToUInt(real64 val) +{ + return (uint32)xs_CeilToUInt(val); +} + +finline static uint32 xs_RoundToUInt(real64 val) +{ + return (uint32)xs_RoundToInt(val); +} + + + +// ==================================================================================================================== +// ==================================================================================================================== +#endif // _xs_FLOAT_H_ \ No newline at end of file From 9357ed82edd921af6d1f6fb88ff7fa1849920f16 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 21 Nov 2009 23:11:12 +0000 Subject: [PATCH 100/241] - extended Doom map format linedef translator so that it also handles the flags. SVN r1992 (trunk) --- docs/rh-log.txt | 3 +++ src/p_xlat.cpp | 41 ++++++++++++++++------------------ src/xlat/parse_xlat.cpp | 5 +++-- src/xlat/xlat.h | 8 +++++++ src/xlat/xlat_parser.y | 20 +++++++++++++++++ wadsrc/static/xlat/defines.i | 31 +++++++++++++++++++++++++ wadsrc/static/xlat/doom.txt | 12 ++++++++++ wadsrc/static/xlat/heretic.txt | 11 +++++++++ wadsrc/static/xlat/strife.txt | 13 +++++++++++ 9 files changed, 120 insertions(+), 24 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2b7bbbe9a..9a04d901d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +November 22, 2009 (Changes by Graf Zahl) +- extended Doom map format linedef translator so that it also handles the flags. + November 19, 2009 - Replaced toint/quickertoint with the portable routines from xs_Float.h. The former used fistp, which is not portable across platforms, so cannot be diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index da5695ece..7ec97f3e6 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -68,38 +68,35 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) DWORD flags = LittleShort(mld->flags); INTBOOL passthrough; - if (flags & ML_TRANSLUCENT_STRIFE) + DWORD flags1 = flags; + DWORD newflags = 0; + + for(int i=0;i<16;i++) { - ld->Alpha = FRACUNIT*3/4; - } - if (gameinfo.gametype == GAME_Strife) - { - if (flags & ML_RAILING_STRIFE) + if ((flags & (1<Alpha = FRACUNIT*3/4; + break; + default: + newflags |= LineFlagTranslations[i].newvalue; + break; } } - if (flags & ML_3DMIDTEX_ETERNITY) - { - flags |= ML_3DMIDTEX; - } - passthrough = (flags & ML_PASSUSE_BOOM); } - flags = flags & 0xFFFF01FF; // Ignore flags unknown to DOOM + flags = newflags; // For purposes of maintaining BOOM compatibility, each // line also needs to have its ID set to the same as its tag. diff --git a/src/xlat/parse_xlat.cpp b/src/xlat/parse_xlat.cpp index 75f2d3d27..6221c5497 100644 --- a/src/xlat/parse_xlat.cpp +++ b/src/xlat/parse_xlat.cpp @@ -61,6 +61,7 @@ FBoomTranslator Boomish[MAX_BOOMISH]; int NumBoomish; TAutoGrowArray SectorTranslations; TArray SectorMasks; +FLineFlagTrans LineFlagTranslations[16]; struct SpecialArgs @@ -112,13 +113,13 @@ struct XlatParseContext : public FParseContext static const char *tokens[] = { "arg2", "arg3", "arg4", "arg5", "bitmask", "clear", - "define", "enum", "flags", "include", "lineid", + "define", "enum", "flags", "include", "lineflag", "lineid", "maxlinespecial", "nobitmask", "sector", "tag" }; static const short types[] = { XLAT_ARG2, XLAT_ARG3, XLAT_ARG4, XLAT_ARG5, XLAT_BITMASK, XLAT_CLEAR, - XLAT_DEFINE, XLAT_ENUM, XLAT_FLAGS, XLAT_INCLUDE, XLAT_TAG, + XLAT_DEFINE, XLAT_ENUM, XLAT_FLAGS, XLAT_INCLUDE, XLAT_LINEFLAG, XLAT_TAG, XLAT_MAXLINESPECIAL, XLAT_NOBITMASK, XLAT_SECTOR, XLAT_TAG }; diff --git a/src/xlat/xlat.h b/src/xlat/xlat.h index 3ba4381e6..018a2639e 100644 --- a/src/xlat/xlat.h +++ b/src/xlat/xlat.h @@ -80,10 +80,18 @@ struct FSectorMask int shift; }; +struct FLineFlagTrans +{ + int newvalue; + bool ismask; +}; + + extern TAutoGrowArray SimpleLineTranslations; extern FBoomTranslator Boomish[MAX_BOOMISH]; extern int NumBoomish; extern TAutoGrowArray SectorTranslations; extern TArray SectorMasks; +extern FLineFlagTrans LineFlagTranslations[16]; #endif diff --git a/src/xlat/xlat_parser.y b/src/xlat/xlat_parser.y index 420989338..d6f71b6a3 100644 --- a/src/xlat/xlat_parser.y +++ b/src/xlat/xlat_parser.y @@ -17,6 +17,7 @@ external_declaration ::= enum_statement. external_declaration ::= linetype_declaration. external_declaration ::= boom_declaration. external_declaration ::= sector_declaration. +external_declaration ::= lineflag_declaration. external_declaration ::= sector_bitmask. external_declaration ::= maxlinespecial_def. external_declaration ::= NOP. @@ -512,3 +513,22 @@ sector_bitmask ::= SECTOR BITMASK exp(mask) CLEAR SEMICOLON. sector_op(A) ::= LSHASSIGN. { A = 1; } sector_op(A) ::= RSHASSIGN. { A = -1; } +%type lineflag_op {int} + +lineflag_declaration ::= LINEFLAG exp(from) EQUALS exp(to) SEMICOLON. +{ + if (from >= 0 && from < 16) + { + LineFlagTranslations[from].newvalue = to; + LineFlagTranslations[from].ismask = false; + } +} + +lineflag_declaration ::= LINEFLAG exp(from) AND exp(mask) SEMICOLON. +{ + if (from >= 0 && from < 16) + { + LineFlagTranslations[from].newvalue = mask; + LineFlagTranslations[from].ismask = true; + } +} \ No newline at end of file diff --git a/wadsrc/static/xlat/defines.i b/wadsrc/static/xlat/defines.i index 6673b5ef5..648679894 100644 --- a/wadsrc/static/xlat/defines.i +++ b/wadsrc/static/xlat/defines.i @@ -209,3 +209,34 @@ define FRICTION_MASK (0x0800) define PUSH_MASK (0x1000) +enum +{ + ML_BLOCKING = 0x00000001, + ML_BLOCKMONSTERS = 0x00000002, + ML_TWOSIDED = 0x00000004, + ML_DONTPEGTOP = 0x00000008, + ML_DONTPEGBOTTOM = 0x00000010, + ML_SECRET = 0x00000020, + ML_SOUNDBLOCK = 0x00000040, + ML_DONTDRAW = 0x00000080, + ML_MAPPED = 0x00000100, + + // Extended flags + ML_MONSTERSCANACTIVATE = 0x00002000, + ML_BLOCK_PLAYERS = 0x00004000, + ML_BLOCKEVERYTHING = 0x00008000, + ML_ZONEBOUNDARY = 0x00010000, + ML_RAILING = 0x00020000, + ML_BLOCK_FLOATERS = 0x00040000, + ML_CLIP_MIDTEX = 0x00080000, + ML_WRAP_MIDTEX = 0x00100000, + ML_3DMIDTEX = 0x00200000, + ML_CHECKSWITCHRANGE = 0x00400000, + ML_FIRSTSIDEONLY = 0x00800000, + ML_BLOCKPROJECTILE = 0x01000000, + ML_BLOCKUSE = 0x02000000, + + // + ML_PASSTHROUGH = -1, + ML_TRANSLUCENT = -2 +} \ No newline at end of file diff --git a/wadsrc/static/xlat/doom.txt b/wadsrc/static/xlat/doom.txt index 25b84b2f0..079f5462e 100644 --- a/wadsrc/static/xlat/doom.txt +++ b/wadsrc/static/xlat/doom.txt @@ -28,3 +28,15 @@ sector 22 = LightSequenceStart; sector 23 = LightSequenceSpecial1; sector 24 = LightSequenceSpecial2; +lineflag 0 = ML_BLOCKING; +lineflag 1 = ML_BLOCKMONSTERS; +lineflag 2 = ML_TWOSIDED; +lineflag 3 = ML_DONTPEGTOP; +lineflag 4 = ML_DONTPEGBOTTOM; +lineflag 5 = ML_SECRET; +lineflag 6 = ML_SOUNDBLOCK; +lineflag 7 = ML_DONTDRAW; +lineflag 8 = ML_MAPPED; +lineflag 9 = ML_PASSTHROUGH; +lineflag 10 = ML_3DMIDTEX; +lineflag 11 & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_TWOSIDED|ML_DONTPEGTOP|ML_DONTPEGBOTTOM|ML_SECRET|ML_SOUNDBLOCK|ML_DONTDRAW|ML_MAPPED); diff --git a/wadsrc/static/xlat/heretic.txt b/wadsrc/static/xlat/heretic.txt index b1a4908b0..da4d103a5 100644 --- a/wadsrc/static/xlat/heretic.txt +++ b/wadsrc/static/xlat/heretic.txt @@ -65,3 +65,14 @@ sector 50 = Wind_West_Medium; sector 51 = Wind_West_Strong; +lineflag 0 = ML_BLOCKING; +lineflag 1 = ML_BLOCKMONSTERS; +lineflag 2 = ML_TWOSIDED; +lineflag 3 = ML_DONTPEGTOP; +lineflag 4 = ML_DONTPEGBOTTOM; +lineflag 5 = ML_SECRET; +lineflag 6 = ML_SOUNDBLOCK; +lineflag 7 = ML_DONTDRAW; +lineflag 8 = ML_MAPPED; +lineflag 9 = ML_PASSTHROUGH; +lineflag 10 = ML_3DMIDTEX; diff --git a/wadsrc/static/xlat/strife.txt b/wadsrc/static/xlat/strife.txt index 72ae2686b..0c141c855 100644 --- a/wadsrc/static/xlat/strife.txt +++ b/wadsrc/static/xlat/strife.txt @@ -352,3 +352,16 @@ sector 23 = LightSequenceSpecial1; sector 24 = LightSequenceSpecial2; +lineflag 0 = ML_BLOCKING; +lineflag 1 = ML_BLOCKMONSTERS; +lineflag 2 = ML_TWOSIDED; +lineflag 3 = ML_DONTPEGTOP; +lineflag 4 = ML_DONTPEGBOTTOM; +lineflag 5 = ML_SECRET; +lineflag 6 = ML_SOUNDBLOCK; +lineflag 7 = ML_DONTDRAW; +lineflag 8 = ML_MAPPED; +lineflag 9 = ML_RAILING; +lineflag 10 = ML_BLOCK_FLOATERS; +lineflag 12 = ML_TRANSLUCENT; + From a97f22bfcd614b5f6b74967d840e5c267a6b52a3 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 24 Nov 2009 01:37:54 +0000 Subject: [PATCH 101/241] - Scan backwards for classes in FArchive::ReadClass(). SVN r1993 (trunk) --- src/farchive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/farchive.cpp b/src/farchive.cpp index 9497bc50e..6b9ba2790 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -1395,7 +1395,7 @@ const PClass *FArchive::ReadClass () FName zaname(typeName.val, true); if (zaname != NAME_None) { - for (unsigned int i = 0; i < PClass::m_Types.Size(); i++) + for (unsigned int i = PClass::m_Types.Size(); i-- > 0; ) { if (PClass::m_Types[i]->TypeName == zaname) { From f305b2f70c318224f331a0401852757d5ea47225 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 24 Nov 2009 02:26:01 +0000 Subject: [PATCH 102/241] - Fixed: FWadCollection::AddFile() did not call FixPathSeperator(), so savegames would hold the full file path for wads that had been specified with backslash characters, because GetWadName() would not trim off the path. SVN r1994 (trunk) --- docs/rh-log.txt | 6 ++++++ src/w_wad.cpp | 3 ++- src/w_wad.h | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 9a04d901d..36a23017c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +November 23, 2009 +- Fixed: FWadCollection::AddFile() did not call FixPathSeperator(), so + savegames would hold the full file path for wads that had been specified + with backslash characters, because GetWadName() would not trim off the + path. + November 22, 2009 (Changes by Graf Zahl) - extended Doom map format linedef translator so that it also handles the flags. diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 3594c8b3f..9c5b525ca 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -222,7 +222,7 @@ int FWadCollection::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) +void FWadCollection::AddFile (char *filename, FileReader *wadinfo) { int startlump; bool isdir = false; @@ -252,6 +252,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) return; } } + FixPathSeperator(filename); } Printf (" adding %s", filename); diff --git a/src/w_wad.h b/src/w_wad.h index 293a328f5..7adea8ab7 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -154,7 +154,7 @@ public: enum { IWAD_FILENUM = 1 }; void InitMultipleFiles (wadlist_t **filenames); - void AddFile (const char *filename, FileReader *wadinfo = NULL); + void AddFile (char *filename, FileReader *wadinfo = NULL); int CheckIfWadLoaded (const char *name); const char *GetWadName (int wadnum) const; From 754fe70a79e910dfcbaf4d3213ff97b3c9763b50 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 24 Nov 2009 03:14:21 +0000 Subject: [PATCH 103/241] - Fixed: ArtiPork did not use all its sprite frames. SVN r1995 (trunk) --- docs/rh-log.txt | 1 + wadsrc/static/actors/raven/artiegg.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 36a23017c..acb6110e5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 23, 2009 +- Fixed: ArtiPork did not use all its sprite frames. - Fixed: FWadCollection::AddFile() did not call FixPathSeperator(), so savegames would hold the full file path for wads that had been specified with backslash characters, because GetWadName() would not trim off the diff --git a/wadsrc/static/actors/raven/artiegg.txt b/wadsrc/static/actors/raven/artiegg.txt index 18a2d83f5..6b8de50c9 100644 --- a/wadsrc/static/actors/raven/artiegg.txt +++ b/wadsrc/static/actors/raven/artiegg.txt @@ -94,7 +94,7 @@ ACTOR ArtiPork : CustomInventory 30 States { Spawn: - PORK ABCB 6 + PORK ABCDEFGH 6 Loop Use: TNT1 A 0 A_FireCustomMissile("PorkFX", -15, 0, 0, 0, 1) From 53b1b7efab971d9a18aa10339d7aa2d4607078c4 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 24 Nov 2009 04:29:36 +0000 Subject: [PATCH 104/241] - Added Windows 7 (aka Windows NT 6.1) and Server 2008 identification to I_DetectOS(). SVN r1996 (trunk) --- docs/rh-log.txt | 2 ++ src/win32/i_system.cpp | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index acb6110e5..2db27819f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 23, 2009 +- Added Windows 7 (aka Windows NT 6.1) and Server 2008 identification to + I_DetectOS(). - Fixed: ArtiPork did not use all its sprite frames. - Fixed: FWadCollection::AddFile() did not call FixPathSeperator(), so savegames would hold the full file path for wads that had been specified diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 1cbc957b6..d39cfc804 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -480,11 +480,16 @@ void I_WaitVBL(int count) void I_DetectOS(void) { - OSVERSIONINFO info; + OSVERSIONINFOEX info; const char *osname; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx (&info); + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!GetVersionEx((OSVERSIONINFO *)&info)) + { + // Retry with the older OSVERSIONINFO structure. + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx((OSVERSIONINFO *)&info); + } switch (info.dwPlatformId) { @@ -522,9 +527,30 @@ void I_DetectOS(void) osname = "Server 2003"; } } - else if (info.dwMajorVersion == 6 && info.dwMinorVersion == 0) + else if (info.dwMajorVersion == 6) { - osname = "Vista"; + if (info.dwMinorVersion == 0) + { + if (info.wProductType == VER_NT_WORKSTATION) + { + osname = "Vista"; + } + else + { + osname = "Server 2008"; + } + } + else if (info.dwMinorVersion == 1) + { + if (info.wProductType == VER_NT_WORKSTATION) + { + osname = "7"; + } + else + { + osname = "Server 2008 R2"; + } + } } break; @@ -543,7 +569,7 @@ void I_DetectOS(void) } else { - Printf ("OS: Windows %s %lu.%lu (Build %lu)\n %s\n", + Printf ("OS: Windows %s (NT %lu.%lu) Build %lu\n %s\n", osname, info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber, info.szCSDVersion); From f94c9ce81de9c53b182a7ab6e9428173863af7c0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Nov 2009 06:55:38 +0000 Subject: [PATCH 105/241] - Fixed: Not all places checking for player start spots above 4 did it correctly. The editor number for player start spot 5 is now stored in the game info so that there's only one place where this check needs to be done. - Fixed: WIF_NOAUTOAIM only worked for projectiles unlike Skulltag's original implementation. SVN r1997 (trunk) --- docs/rh-log.txt | 6 ++++++ src/g_game.cpp | 14 ++++---------- src/gi.cpp | 1 + src/gi.h | 1 + src/p_map.cpp | 19 ++++++++++++++----- src/p_mobj.cpp | 15 ++++----------- wadsrc/static/mapinfo/chex.txt | 1 + wadsrc/static/mapinfo/doomcommon.txt | 1 + wadsrc/static/mapinfo/heretic.txt | 1 + wadsrc/static/mapinfo/hexen.txt | 1 + wadsrc/static/mapinfo/strife.txt | 1 + 11 files changed, 35 insertions(+), 26 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2db27819f..418d6fceb 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +November 24, 2009 (Changes by Graf Zahl) +- Fixed: Not all places checking for player start spots did it correctly. + The editor number for player start spot 5 is now stored in the game info + so that there's only one place where this check needs to be done. +- Fixed: WIF_NOAUTOAIM only worked for projectiles. + November 23, 2009 - Added Windows 7 (aka Windows NT 6.1) and Server 2008 identification to I_DetectOS(). diff --git a/src/g_game.cpp b/src/g_game.cpp index 613b147ba..2f3a62c07 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1475,10 +1475,8 @@ void G_DeathMatchSpawnPlayer (int playernum) { if (playernum < 4) spot->type = playernum+1; - else if (gameinfo.gametype != GAME_Hexen) - spot->type = playernum+4001-4; // [RH] > 4 players - else - spot->type = playernum+9100-4; + else + spot->type = playernum + gameinfo.player5start - 4; } AActor *mo = P_SpawnPlayer (spot); @@ -1569,17 +1567,13 @@ void G_DoReborn (int playernum, bool freshbot) // fake as other player // [RH] These numbers should be common across all games. Or better yet, not // used at all outside P_SpawnMapThing(). - if (playernum < 4 || gameinfo.gametype == GAME_Strife) + if (playernum < 4) { playerstarts[i].type = playernum + 1; } - else if (gameinfo.gametype == GAME_Hexen) - { - playerstarts[i].type = playernum + 9100 - 4; - } else { - playerstarts[i].type = playernum + 4001 - 4; + playerstarts[i].type = playernum + gameinfo.player5start - 4; } AActor *mo = P_SpawnPlayer (&playerstarts[i]); if (mo != NULL) P_PlayerStartStomp(mo); diff --git a/src/gi.cpp b/src/gi.cpp index ae473ef66..e0813479a 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -281,6 +281,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle") GAMEINFOKEY_CSTRING(Endoom, "endoom", 8) + GAMEINFOKEY_INT(player5start, "player5start") else { // ignore unkown keys. diff --git a/src/gi.h b/src/gi.h index c5dfadfc4..b46be119c 100644 --- a/src/gi.h +++ b/src/gi.h @@ -103,6 +103,7 @@ struct gameinfo_t int definventorymaxamount; int defaultrespawntime; int defaultdropstyle; + int player5start; const char *GetFinalePage(unsigned int num) const; }; diff --git a/src/p_map.cpp b/src/p_map.cpp index d95d81d4b..00db77bee 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3157,11 +3157,20 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p } else { - // 35 degrees is approximately what Doom used. You cannot have a - // vrange of 0 degrees, because then toppitch and bottompitch will - // be equal, and PTR_AimTraverse will never find anything to shoot at - // if it crosses a line. - vrange = clamp (t1->player->userinfo.GetAimDist(), ANGLE_1/2, ANGLE_1*35); + // [BB] Disable autoaim on weapons with WIF_NOAUTOAIM. + AWeapon *weapon = t1->player->ReadyWeapon; + if ( weapon && (weapon->WeaponFlags & WIF_NOAUTOAIM) ) + { + vrange = ANGLE_1/2; + } + else + { + // 35 degrees is approximately what Doom used. You cannot have a + // vrange of 0 degrees, because then toppitch and bottompitch will + // be equal, and PTR_AimTraverse will never find anything to shoot at + // if it crosses a line. + vrange = clamp (t1->player->userinfo.aimdist, ANGLE_1/2, ANGLE_1*35); + } } } aim.toppitch = t1->pitch - vrange; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8177b73a1..15045a15e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3838,17 +3838,13 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer) // [RH] Things 4001-? are also multiplayer starts. Just like 1-4. // To make things simpler, figure out which player is being // spawned here. - if (mthing->type <= 4 || gameinfo.gametype == GAME_Strife) // don't forget Strife's starts 5-8 here! + if (mthing->type <= 4) { playernum = mthing->type - 1; } - else if (gameinfo.gametype != GAME_Hexen) - { - playernum = mthing->type - 4001 + 4; - } else { - playernum = mthing->type - 9100 + 4; + playernum = mthing->type - gameinfo.player5start + 4; } // not playing? @@ -4140,12 +4136,9 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) } else { - const int base = (gameinfo.gametype == GAME_Strife) ? 5 : - (gameinfo.gametype == GAME_Hexen) ? 9100 : 4001; - - if (mthing->type >= base && mthing->type < base + MAXPLAYERS - 4) + if (mthing->type >= gameinfo.player5start && mthing->type < gameinfo.player5start + MAXPLAYERS - 4) { - pnum = mthing->type - base + 4; + pnum = mthing->type - gameinfo.player5start + 4; } } diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index 3401551eb..2f2f494fb 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -40,6 +40,7 @@ gameinfo defaultrespawntime = 12 defaultdropstyle = 1 endoom = "ENDOOM" + player5start = 4001 } skill baby diff --git a/wadsrc/static/mapinfo/doomcommon.txt b/wadsrc/static/mapinfo/doomcommon.txt index 0a5abbcda..4aeee99ad 100644 --- a/wadsrc/static/mapinfo/doomcommon.txt +++ b/wadsrc/static/mapinfo/doomcommon.txt @@ -39,6 +39,7 @@ gameinfo defaultrespawntime = 12 defaultdropstyle = 1 endoom = "ENDOOM" + player5start = 4001 } skill baby diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index 6136baca2..955574891 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -40,6 +40,7 @@ gameinfo defaultrespawntime = 12 defaultdropstyle = 1 endoom = "ENDTEXT" + player5start = 4001 } skill baby diff --git a/wadsrc/static/mapinfo/hexen.txt b/wadsrc/static/mapinfo/hexen.txt index b4ab056fb..cdababe39 100644 --- a/wadsrc/static/mapinfo/hexen.txt +++ b/wadsrc/static/mapinfo/hexen.txt @@ -38,6 +38,7 @@ gameinfo definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 + player5start = 9100 } skill baby diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt index 28b87f357..7495c860b 100644 --- a/wadsrc/static/mapinfo/strife.txt +++ b/wadsrc/static/mapinfo/strife.txt @@ -41,6 +41,7 @@ gameinfo defaultrespawntime = 16 defaultdropstyle = 2 endoom = "ENDSTRF" + player5start = 5 } skill baby From 32d9946f3040ed1e39dece441deb7871823542d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Nov 2009 07:02:30 +0000 Subject: [PATCH 106/241] - Fixed: Doom line type 44 (lower ceiling to 8 above floor) must halt movement if blocked which essentially means it acts like a Hexen-style crusher. SVN r1998 (trunk) --- docs/rh-log.txt | 3 +++ wadsrc/static/xlat/base.txt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 418d6fceb..0f7f71920 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ November 24, 2009 (Changes by Graf Zahl) +- Fixed: Doom line type 44 (lower ceiling to 8 above floor) must halt + movement if blocked which essentially means it acts like a Hexen-style + crusher. - Fixed: Not all places checking for player start spots did it correctly. The editor number for player start spot 5 is now stored in the game info so that there's only one place where this check needs to be done. diff --git a/wadsrc/static/xlat/base.txt b/wadsrc/static/xlat/base.txt index ca13bc244..c6645c521 100644 --- a/wadsrc/static/xlat/base.txt +++ b/wadsrc/static/xlat/base.txt @@ -43,7 +43,7 @@ include "xlat/defines.i" 41 = USE, Ceiling_LowerToFloor (tag, C_SLOW) 42 = USE|REP, Door_Close (tag, D_SLOW) 43 = USE|REP, Ceiling_LowerToFloor (tag, C_SLOW) - 44 = WALK, Ceiling_LowerAndCrush (tag, C_SLOW, 0) + 44 = WALK, Ceiling_LowerAndCrush (tag, C_SLOW, 0, 2) 45 = USE|REP, Floor_LowerToHighest (tag, F_SLOW, 128) 46 = SHOOT|REP|MONST, Door_Open (tag, D_SLOW) 47 = SHOOT, Plat_RaiseAndStayTx0 (tag, P_SLOW/2) From a3c28e2a2fe914cbfe66e5ffa2489a6bf3f5db13 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Nov 2009 07:08:20 +0000 Subject: [PATCH 107/241] - last revision's fix should be set to all 4 linedef types triggering the same action. SVN r1999 (trunk) --- wadsrc/static/xlat/base.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/xlat/base.txt b/wadsrc/static/xlat/base.txt index c6645c521..a7aa69f1c 100644 --- a/wadsrc/static/xlat/base.txt +++ b/wadsrc/static/xlat/base.txt @@ -71,7 +71,7 @@ include "xlat/defines.i" 69 = USE|REP, Floor_RaiseToNearest (tag, F_SLOW) 70 = USE|REP, Floor_LowerToHighest (tag, F_FAST, 136) 71 = USE, Floor_LowerToHighest (tag, F_FAST, 136) - 72 = WALK|REP, Ceiling_LowerAndCrush (tag, C_SLOW, 0) + 72 = WALK|REP, Ceiling_LowerAndCrush (tag, C_SLOW, 0, 2) 73 = WALK|REP, Ceiling_CrushAndRaiseA (tag, C_SLOW, C_SLOW, 10) 74 = WALK|REP, Ceiling_CrushStop (tag) 75 = WALK|REP, Door_Close (tag, D_SLOW) @@ -169,7 +169,7 @@ include "xlat/defines.i" 164 = USE, Ceiling_CrushAndRaiseA (tag, C_NORMAL, C_NORMAL, 10) 165 = USE, Ceiling_CrushAndRaiseSilentA (tag, C_SLOW, C_SLOW, 10) 166 = USE, FloorAndCeiling_LowerRaise (tag, F_SLOW, C_SLOW) -167 = USE, Ceiling_LowerAndCrush (tag, C_SLOW, 0) +167 = USE, Ceiling_LowerAndCrush (tag, C_SLOW, 0, 2) 168 = USE, Ceiling_CrushStop (tag) 169 = USE, Light_MaxNeighbor (tag) 170 = USE, Light_ChangeToValue (tag, 35) @@ -189,7 +189,7 @@ include "xlat/defines.i" 184 = USE|REP, Ceiling_CrushAndRaiseA (tag, C_SLOW, C_SLOW, 10) 185 = USE|REP, Ceiling_CrushAndRaiseSilentA (tag, C_SLOW, C_SLOW, 10) 186 = USE|REP, FloorAndCeiling_LowerRaise (tag, F_SLOW, C_SLOW) -187 = USE|REP, Ceiling_LowerAndCrush (tag, C_SLOW, 0) +187 = USE|REP, Ceiling_LowerAndCrush (tag, C_SLOW, 0, 2) 188 = USE|REP, Ceiling_CrushStop (tag) 189 = USE, Floor_TransferTrigger (tag) 190 = USE|REP, Floor_TransferTrigger (tag) From 233e662a92a46bb76f310553e858761c26a565bd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Nov 2009 07:38:11 +0000 Subject: [PATCH 108/241] - Fixed: EV_DoDonut, EV_DoElevator and EV_StartWaggle did not to any 0-tag checks. SVN r2000 (trunk) --- docs/rh-log.txt | 2 ++ src/p_floor.cpp | 45 +++++++++++++++++++++++++++++++++++++++++---- src/p_lnspec.cpp | 6 +++--- src/p_spec.h | 8 ++++---- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0f7f71920..06c4b04db 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 24, 2009 (Changes by Graf Zahl) +- Fixed: EV_DoDonut, EV_DoElevator and EV_StartWaggle did not to any 0-tag + checks. - Fixed: Doom line type 44 (lower ceiling to 8 above floor) must halt movement if blocked which essentially means it acts like a Hexen-style crusher. diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 4e2afe109..0b9a634e8 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -770,7 +770,7 @@ manual_stair: // //========================================================================== -bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed) +bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed) { sector_t* s1; sector_t* s2; @@ -781,13 +781,24 @@ bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed) DFloor* floor; vertex_t* spot; fixed_t height; + bool manual = false; secnum = -1; rtn = false; + + if (tag == 0) + { + if (!line || !(s1 = line->backsector)) + return rtn; + manual = true; + goto manual_donut; + } + while ((secnum = P_FindSectorFromTag(tag,secnum)) >= 0) { s1 = §ors[secnum]; // s1 is pillar's sector - + +manual_donut: // ALREADY MOVING? IF SO, KEEP GOING... if (s1->PlaneMoving(sector_t::floor)) continue; @@ -834,6 +845,7 @@ bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed) floor->StartFloorSound (); break; } + if (manual) break; } return rtn; } @@ -989,17 +1001,28 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype, fixed_t floorheight, ceilingheight; fixed_t newheight; vertex_t* spot; + bool manual = false; if (!line && (elevtype == DElevator::elevateCurrent)) return false; secnum = -1; rtn = false; + + if (tag == 0) + { + if (!line || !(sec = line->backsector)) + return rtn; + manual = true; + goto manual_elevator; + } + + // act on all sectors with the same tag as the triggering linedef while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) { sec = §ors[secnum]; - +manual_elevator: // If either floor or ceiling is already activated, skip it if (sec->PlaneMoving(sector_t::floor) || sec->ceilingdata) //jff 2/22/98 continue; @@ -1060,6 +1083,7 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype, elevator->m_CeilingDestDist = sec->ceilingplane.PointToDist (sec->soundorg[0], sec->soundorg[1], ceilingheight - height); break; } + if (manual) break; } return rtn; } @@ -1307,19 +1331,31 @@ void DCeilingWaggle::Tick () // //========================================================================== -bool EV_StartWaggle (int tag, int height, int speed, int offset, +bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset, int timer, bool ceiling) { int sectorIndex; sector_t *sector; DWaggleBase *waggle; bool retCode; + bool manual = false; retCode = false; sectorIndex = -1; + + if (tag == 0) + { + if (!line || !(sector = line->backsector)) + return retCode; + manual = true; + goto manual_waggle; + } + + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) { sector = §ors[sectorIndex]; +manual_waggle: if ((!ceiling && sector->PlaneMoving(sector_t::floor)) || (ceiling && sector->PlaneMoving(sector_t::ceiling))) { // Already busy with another thinker @@ -1344,6 +1380,7 @@ bool EV_StartWaggle (int tag, int height, int speed, int offset, /(TICRATE+((3*TICRATE)*height)/255); waggle->m_Ticker = timer ? timer*TICRATE : -1; waggle->m_State = WGLSTATE_EXPAND; + if (manual) break; } return retCode; } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index e5d2c78fc..7417ebbef 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -341,13 +341,13 @@ FUNC(LS_Floor_LowerToLowestTxTy) FUNC(LS_Floor_Waggle) // Floor_Waggle (tag, amplitude, frequency, delay, time) { - return EV_StartWaggle (arg0, arg1, arg2, arg3, arg4, false); + return EV_StartWaggle (arg0, ln, arg1, arg2, arg3, arg4, false); } FUNC(LS_Ceiling_Waggle) // Ceiling_Waggle (tag, amplitude, frequency, delay, time) { - return EV_StartWaggle (arg0, arg1, arg2, arg3, arg4, true); + return EV_StartWaggle (arg0, ln, arg1, arg2, arg3, arg4, true); } FUNC(LS_Floor_TransferTrigger) @@ -365,7 +365,7 @@ FUNC(LS_Floor_TransferNumeric) FUNC(LS_Floor_Donut) // Floor_Donut (pillartag, pillarspeed, slimespeed) { - return EV_DoDonut (arg0, SPEED(arg1), SPEED(arg2)); + return EV_DoDonut (arg0, ln, SPEED(arg1), SPEED(arg2)); } FUNC(LS_Generic_Floor) diff --git a/src/p_spec.h b/src/p_spec.h index b47f9aa9d..ca0d9492c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -825,7 +825,7 @@ protected: friend bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag, fixed_t speed, fixed_t height, int crush, int change, bool hexencrush); friend bool EV_FloorCrushStop (int tag); - friend bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed); + friend bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed); private: DFloor (); }; @@ -836,7 +836,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag, fixed_t speed, fixed_t height, int crush, int change, bool hexencrush); bool EV_FloorCrushStop (int tag); -bool EV_DoDonut (int tag, fixed_t pillarspeed, fixed_t slimespeed); +bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed); inline FArchive &operator<< (FArchive &arc, DFloor::EFloor &type) { @@ -915,7 +915,7 @@ protected: int m_State; TObjPtr m_Interpolation; - friend bool EV_StartWaggle (int tag, int height, int speed, + friend bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset, int timer, bool ceiling); void DoWaggle (bool ceiling); @@ -923,7 +923,7 @@ protected: DWaggleBase (); }; -bool EV_StartWaggle (int tag, int height, int speed, +bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset, int timer, bool ceiling); class DFloorWaggle : public DWaggleBase From 5d7670acc414f732e0eb071f1d744983a1302224 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Nov 2009 22:28:38 +0000 Subject: [PATCH 109/241] - Added MF4_ALLOWPARTICLES checks to blood spawning code. SVN r2001 (trunk) --- docs/rh-log.txt | 1 + src/p_mobj.cpp | 37 +++++++++++++++++++++------ wadsrc/static/actors/shared/blood.txt | 3 +++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 06c4b04db..10d1c0a05 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 24, 2009 (Changes by Graf Zahl) +- Added MF4_ALLOWPARTICLES checks to blood spawning code. - Fixed: EV_DoDonut, EV_DoElevator and EV_StartWaggle did not to any 0-tag checks. - Fixed: Doom line type 44 (lower ceiling to 8 above floor) must halt diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 15045a15e..5705fb77b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4442,8 +4442,13 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc AActor *th; PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood)); + + int bloodtype = cl_bloodtype; + + if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) + bloodtype = 0; - if (bloodcls!=NULL && cl_bloodtype <= 1) + if (bloodcls!=NULL && bloodtype <= 1) { z += pr_spawnblood.Random2 () << 10; th = Spawn (bloodcls, x, y, z, ALLOW_REPLACE); @@ -4485,7 +4490,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc } } - if (cl_bloodtype >= 1) + if (bloodtype >= 1) P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor); } @@ -4500,7 +4505,12 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter)); - if (bloodcls!=NULL && cl_bloodtype <= 1) + int bloodtype = cl_bloodtype; + + if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) + bloodtype = 0; + + if (bloodcls!=NULL && bloodtype <= 1) { AActor *mo; @@ -4516,7 +4526,7 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } } - if (cl_bloodtype >= 1) + if (bloodtype >= 1) { P_DrawSplash2 (40, x, y, z, R_PointToAngle2 (x, y, originator->x, originator->y), 2, bloodcolor); } @@ -4533,7 +4543,12 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood)); - if (bloodcls!=NULL && cl_bloodtype <= 1) + int bloodtype = cl_bloodtype; + + if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) + bloodtype = 0; + + if (bloodcls!=NULL && bloodtype <= 1) { AActor *mo; @@ -4549,7 +4564,7 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } } - if (cl_bloodtype >= 1) + if (bloodtype >= 1) { P_DrawSplash2 (100, x, y, z, R_PointToAngle2 (0, 0, originator->x - x, originator->y - y), 2, bloodcolor); } @@ -4570,7 +4585,13 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) x = mo->x + (pr_ripperblood.Random2 () << 12); y = mo->y + (pr_ripperblood.Random2 () << 12); z = mo->z + (pr_ripperblood.Random2 () << 12); - if (bloodcls!=NULL && cl_bloodtype <= 1) + + int bloodtype = cl_bloodtype; + + if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) + bloodtype = 0; + + if (bloodcls!=NULL && bloodtype <= 1) { AActor *th; th = Spawn (bloodcls, x, y, z, ALLOW_REPLACE); @@ -4586,7 +4607,7 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } } - if (cl_bloodtype >= 1) + if (bloodtype >= 1) { P_DrawSplash2 (28, x, y, z, 0, 0, bloodcolor); } diff --git a/wadsrc/static/actors/shared/blood.txt b/wadsrc/static/actors/shared/blood.txt index 5a7ae201d..1a294c6af 100644 --- a/wadsrc/static/actors/shared/blood.txt +++ b/wadsrc/static/actors/shared/blood.txt @@ -7,6 +7,7 @@ ACTOR Blood Mass 5 +NOBLOCKMAP +NOTELEPORT + +ALLOWPARTICLES States { Spawn: @@ -30,6 +31,7 @@ ACTOR BloodSplatter +DROPOFF +NOTELEPORT +CANNOTPUSH + +ALLOWPARTICLES Mass 5 States { @@ -53,6 +55,7 @@ ACTOR AxeBlood +DROPOFF +NOTELEPORT +CANNOTPUSH + +ALLOWPARTICLES Mass 5 States { From 787f00abf9b9ef6ed4b283f210dc5a4160a7739c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 26 Nov 2009 03:16:54 +0000 Subject: [PATCH 110/241] - Make the palette indexes used by FRemapTable subject to the global remap table, just as the images they translate are. SVN r2002 (trunk) --- docs/rh-log.txt | 4 ++++ src/r_translate.cpp | 33 +++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 10d1c0a05..a5f7b6e57 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 25, 2009 +- Make the palette indexes used by FRemapTable subject to the global remap + table, just as the images they translate are. + November 24, 2009 (Changes by Graf Zahl) - Added MF4_ALLOWPARTICLES checks to blood spawning code. - Fixed: EV_DoDonut, EV_DoElevator and EV_StartWaggle did not to any 0-tag diff --git a/src/r_translate.cpp b/src/r_translate.cpp index bd1e7bfd4..8e74f4443 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -315,18 +315,21 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) } else if (start == end) { + start = GPalette.Remap[start]; + pal1 = GPalette.Remap[pal1]; Remap[start] = pal1; Palette[start] = GPalette.BaseColors[pal1]; - Palette[start].a = start==0? 0:255; + Palette[start].a = start == 0 ? 0 : 255; return; } palcol = pal1 << FRACBITS; palstep = ((pal2 << FRACBITS) - palcol) / (end - start); for (int i = start; i <= end; palcol += palstep, ++i) { - Remap[i] = palcol >> FRACBITS; - Palette[i] = GPalette.BaseColors[palcol >> FRACBITS]; - Palette[i].a = i==0? 0:255; + int j = GPalette.Remap[i], k = GPalette.Remap[palcol >> FRACBITS]; + Remap[j] = k; + Palette[j] = GPalette.BaseColors[k]; + Palette[j].a = j == 0 ? 0 : 255; } } @@ -368,10 +371,10 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in } if (start == end) { - Remap[start] = ColorMatcher.Pick - (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + start = GPalette.Remap[start]; + Remap[start] = ColorMatcher.Pick(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); Palette[start] = PalEntry(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); - Palette[start].a = start==0? 0:255; + Palette[start].a = start == 0 ? 0 : 255; } else { @@ -380,9 +383,9 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in bs /= (end - start); for (int i = start; i <= end; ++i) { - Remap[i] = ColorMatcher.Pick - (r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); - Palette[i] = PalEntry(start==0? 0:255, r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + int j = GPalette.Remap[i]; + Remap[j] = ColorMatcher.Pick(r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); + Palette[j] = PalEntry(j == 0 ? 0 : 255, r >> FRACBITS, g >> FRACBITS, b >> FRACBITS); r += rs; g += gs; b += bs; @@ -412,7 +415,7 @@ void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b g1 *= 255; b1 *= 255; - for(int c=start; c < end; c++) + for(int c = start; c < end; c++) { double intensity = (GPalette.BaseColors[c].r * 77 + GPalette.BaseColors[c].g * 143 + @@ -422,9 +425,11 @@ void FRemapTable::AddDesaturation(int start, int end, float r1,float g1, float b MIN(255, int(g1 + intensity*g2)), MIN(255, int(b1 + intensity*b2))); - Remap[c] = ColorMatcher.Pick(pe); - Palette[c] = pe; - Palette[c].a = c==0? 0:255; + int cc = GPalette.Remap[c]; + + Remap[cc] = ColorMatcher.Pick(pe); + Palette[cc] = pe; + Palette[cc].a = cc == 0 ? 0:255; } } From 53a6ffee15ca70ed4c71e8ccc8a99ef5b9f531a4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Nov 2009 13:23:02 +0000 Subject: [PATCH 111/241] - fixed: The charge attack of Heretic's imp is not precisely the same as A_SkullAttack with a different speed so A_ImpMsAttack has been reinstated. SVN r2003 (trunk) --- docs/rh-log.txt | 5 +++++ src/g_doom/a_lostsoul.cpp | 3 --- src/g_doom/a_painelemental.cpp | 3 --- src/g_heretic/a_hereticimp.cpp | 18 ++++++++++++++++++ src/p_enemy.h | 3 +++ wadsrc/static/actors/heretic/hereticimp.txt | 3 ++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a5f7b6e57..ec1efb083 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 27, 2009 (Changes by Graf Zahl) +- fixed: The charge attack of Heretic's imp is not precisely the same + as A_SkullAttack with a different speed so A_ImpMsAttack has been + reinstated. + November 25, 2009 - Make the palette indexes used by FRemapTable subject to the global remap table, just as the images they translate are. diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index c648afaba..b6c2ee067 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -19,7 +19,6 @@ // SkullAttack // Fly at the player like a missile. // -#define SKULLSPEED (20*FRACUNIT) void A_SkullAttack(AActor *self, fixed_t speed) { @@ -55,8 +54,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack) A_SkullAttack(self, n); } - - DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack) { int damage; diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index bf0d0501b..c52137919 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -22,9 +22,6 @@ static const PClass *GetSpawnType(DECLARE_PARAMINFO) } -#define SKULLSPEED (20*FRACUNIT) -void A_SkullAttack(AActor *self, fixed_t speed); - // // A_PainShootSkull // Spawn a lost soul and launch it at the target diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp index b2c92426e..221fe49fb 100644 --- a/src/g_heretic/a_hereticimp.cpp +++ b/src/g_heretic/a_hereticimp.cpp @@ -9,8 +9,26 @@ #include "thingdef/thingdef.h" */ +static FRandom pr_impmsatk ("ImpMsAttack"); static FRandom pr_imp ("ImpExplode"); + +//---------------------------------------------------------------------------- +// +// PROC A_ImpMsAttack +// +//---------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, A_ImpMsAttack) +{ + if (!self->target || pr_impmsatk() > 64) + { + self->SetState (self->SeeState); + return; + } + A_SkullAttack(self, 12 * FRACUNIT); +} + //---------------------------------------------------------------------------- // // PROC A_ImpExplode diff --git a/src/p_enemy.h b/src/p_enemy.h index ae259806a..a7386ccf5 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -76,4 +76,7 @@ bool CheckBossDeath (AActor *); int P_Massacre (); bool P_CheckMissileRange (AActor *actor); +#define SKULLSPEED (20*FRACUNIT) +void A_SkullAttack(AActor *self, fixed_t speed); + #endif //__P_ENEMY_H__ diff --git a/wadsrc/static/actors/heretic/hereticimp.txt b/wadsrc/static/actors/heretic/hereticimp.txt index 1d663b662..25f64a2ea 100644 --- a/wadsrc/static/actors/heretic/hereticimp.txt +++ b/wadsrc/static/actors/heretic/hereticimp.txt @@ -25,6 +25,7 @@ ACTOR HereticImp 66 Obituary "$OB_HERETICIMP" HitObituary "$OB_HERETICIMPHIT" + action native A_ImpMsAttack(); action native A_ImpDeath(); action native A_ImpXDeath1(); action native A_ImpExplode(); @@ -44,7 +45,7 @@ ACTOR HereticImp 66 Goto See Missile: IMPX A 10 A_FaceTarget - IMPX B 6 A_SkullAttack(12) + IMPX B 6 A_ImpMsAttack IMPX CBAB 6 Goto Missile+2 Pain: From f3b19fcca21ac0f7b4b447297b609fbe12ba904c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Nov 2009 21:45:17 +0000 Subject: [PATCH 112/241] - fixed an uninitialized variable in p_xlat.cpp . SVN r2004 (trunk) --- docs/rh-log.txt | 2 ++ src/p_xlat.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ec1efb083..21805e309 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 27, 2009 (Changes by Graf Zahl) +- fixed an uninitialized variable in p_xlat.cpp (Thanks, MSVC for not + warning about such an obvious problem! :( ) - fixed: The charge attack of Heretic's imp is not precisely the same as A_SkullAttack with a different speed so A_ImpMsAttack has been reinstated. diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index 7ec97f3e6..9e87d13ba 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -66,7 +66,7 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) unsigned short special = (unsigned short) LittleShort(mld->special); short tag = LittleShort(mld->tag); DWORD flags = LittleShort(mld->flags); - INTBOOL passthrough; + INTBOOL passthrough = 0; DWORD flags1 = flags; DWORD newflags = 0; From d14faa5f98a80ba5b5490dd81afecdc4330d59cb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 28 Nov 2009 07:46:30 +0000 Subject: [PATCH 113/241] - fixed: Morph weapons weren't destroyed because the code checked for them in the unmorphed player class. - fixed: With padding the largest texture to fit into a page is 254x254. SVN r2005 (trunk) --- docs/rh-log.txt | 5 +++++ src/g_shared/a_morph.cpp | 4 ++-- src/win32/fb_d3d9.cpp | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 21805e309..64a480429 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 28, 2009 (Changes by Graf Zahl) +- fixed: Morph weapons weren't destroyed because the code checked for + them in the unmorphed player class. +- fixed: With padding the largest texture to fit into a page is 254x254. + November 27, 2009 (Changes by Graf Zahl) - fixed an uninitialized variable in p_xlat.cpp (Thanks, MSVC for not warning about such an obvious problem! :( ) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 917ae5a92..4a730eb2f 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -177,7 +177,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, { AWeapon *beastweap; APlayerPawn *mo; - AActor *pmo; + APlayerPawn *pmo; angle_t angle; pmo = player->mo; @@ -330,7 +330,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, } if (correctweapon) { // Better "lose morphed weapon" semantics - const PClass *morphweapon = PClass::FindClass (mo->MorphWeapon); + const PClass *morphweapon = PClass::FindClass (pmo->MorphWeapon); if (morphweapon != NULL && morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon))) { AWeapon *OriginalMorphWeapon = static_cast(mo->FindInventory (morphweapon)); diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 8e82b5e4f..ac6cda921 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1828,7 +1828,8 @@ D3DFB::PackedTexture *D3DFB::AllocPackedTexture(int w, int h, bool wrapping, D3D PackedTexture *bestbox; int area; - if (w > 256 || h > 256 || wrapping) + // check for 254 to account for padding + if (w > 254 || h > 254 || wrapping) { // Create a new packing texture. bestpack = new PackingTexture(this, w, h, format); bestpack->OneUse = true; From 4edd51eb098f11d244500d4b95ac4f73657c518a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 29 Nov 2009 01:56:22 +0000 Subject: [PATCH 114/241] - Use the spawned class's scale as default for ScriptedMarine instead of DoomPlayer. SVN r2006 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_doom/a_scriptedmarine.cpp | 18 ++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 64a480429..952c2f0ea 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +November 28, 2009 +- Use the spawned class's scale as default for ScriptedMarine instead of + DoomPlayer. + November 28, 2009 (Changes by Graf Zahl) - fixed: Morph weapons weren't destroyed because the code checked for them in the unmorphed player class. diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 9f6f54051..763fd26b9 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -97,14 +97,6 @@ void AScriptedMarine::BeginPlay () } } } - - // Copy the standard player's scaling - AActor * playerdef = GetDefaultByName("DoomPlayer"); - if (playerdef != NULL) - { - scaleX = playerdef->scaleX; - scaleY = playerdef->scaleY; - } } void AScriptedMarine::Tick () @@ -607,14 +599,12 @@ void AScriptedMarine::SetSprite (const PClass *source) if (source == NULL || source->ActorInfo == NULL) { // A valid actor class wasn't passed, so use the standard sprite SpriteOverride = sprite = GetClass()->ActorInfo->OwnedStates[0].sprite; - // Copy the standard player's scaling - AActor * playerdef = GetDefaultByName("DoomPlayer"); - if (playerdef == NULL) playerdef = GetDefaultByType(RUNTIME_CLASS(AScriptedMarine)); - scaleX = playerdef->scaleX; - scaleY = playerdef->scaleY; + // Copy the standard scaling + scaleX = GetDefault()->scaleX; + scaleY = GetDefault()->scaleY; } else - { // Use the same sprite the passed class spawns with + { // Use the same sprite and scaling the passed class spawns with SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite; scaleX = GetDefaultByType(source)->scaleX; scaleY = GetDefaultByType(source)->scaleY; From cdb26a9b288595d69e7dc6337377c18e1c0a9ca4 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 29 Nov 2009 02:33:52 +0000 Subject: [PATCH 115/241] - Fixed: Windowed mode always needs to draw to the temporary surface, even when not gamma correcting, so that D3DFB::GetCurrentScreen() can read from it. SVN r2007 (trunk) --- docs/rh-log.txt | 3 +++ src/win32/fb_d3d9.cpp | 2 +- src/win32/fb_d3d9_wipe.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 952c2f0ea..8b82c18ec 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ November 28, 2009 +- Fixed: Windowed mode always needs to draw to the temporary surface, even + when not gamma correcting, so that D3DFB::GetCurrentScreen() can read from + it. - Use the spawned class's scale as default for ScriptedMarine instead of DoomPlayer. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index ac6cda921..f5978e750 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1141,7 +1141,7 @@ void D3DFB::Draw3DPart(bool copy3d) D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, vid_hwaalines); assert(OldRenderTarget == NULL); if (TempRenderTexture != NULL && - ((Windowed && GammaShader && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling)) + ((Windowed && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling)) { IDirect3DSurface9 *targetsurf; if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &targetsurf))) diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp index 699407b85..9c446a5b2 100644 --- a/src/win32/fb_d3d9_wipe.cpp +++ b/src/win32/fb_d3d9_wipe.cpp @@ -164,7 +164,7 @@ bool D3DFB::WipeStartScreen(int type) // Create another texture to copy the final wipe screen to so // we can still gamma correct the wipe. Since this is just for // gamma correction, it's okay to fail (though not desirable.) - if (PixelDoubling || (Shaders[SHADER_GammaCorrection] != NULL && Windowed)) + if (PixelDoubling || Windowed) { if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &tsurf))) { From a5c8b33f10130368c70f526f49dadf33628e9dc7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 29 Nov 2009 02:42:20 +0000 Subject: [PATCH 116/241] - Initialize TempRenderTexture and the back buffer to black upon creation. SVN r2008 (trunk) --- docs/rh-log.txt | 1 + src/win32/fb_d3d9.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 8b82c18ec..cb1dae7db 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ November 28, 2009 +- Initialize TempRenderTexture and the back buffer to black upon creation. - Fixed: Windowed mode always needs to draw to the temporary surface, even when not gamma correcting, so that D3DFB::GetCurrentScreen() can read from it. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index f5978e750..f696951e1 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -464,6 +464,9 @@ void D3DFB::SetInitialState() AlphaTestEnabled = FALSE; CurBorderColor = 0; + + // Clear to black, just in case it wasn't done already. + D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 0, 0); } //========================================================================== @@ -753,6 +756,20 @@ void D3DFB::KillNativeTexs() } } +//========================================================================== +// +// D3DFB :: CreateFBTexture +// +// Creates the "Framebuffer" texture. With the advent of hardware-assisted +// 2D, this is something of a misnomer now. The FBTexture is only used for +// uploading the software 3D image to video memory so that it can be drawn +// to the real frame buffer. +// +// It also creates the TempRenderTexture, since this seemed like a +// convenient place to do so. +// +//========================================================================== + bool D3DFB::CreateFBTexture () { if (FAILED(D3DDevice->CreateTexture (Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) @@ -781,9 +798,25 @@ bool D3DFB::CreateFBTexture () { TempRenderTexture = NULL; } + else + { + // Initialize the TempRenderTexture to black. + IDirect3DSurface9 *surf; + if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &surf))) + { + D3DDevice->ColorFill(surf, NULL, D3DCOLOR_XRGB(0,0,0)); + surf->Release(); + } + } return true; } +//========================================================================== +// +// D3DFB :: CreatePaletteTexture +// +//========================================================================== + bool D3DFB::CreatePaletteTexture () { if (FAILED(D3DDevice->CreateTexture (256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &PaletteTexture, NULL))) @@ -793,6 +826,12 @@ bool D3DFB::CreatePaletteTexture () return true; } +//========================================================================== +// +// D3DFB :: CreateGammaTexture +// +//========================================================================== + bool D3DFB::CreateGammaTexture () { // If this fails, you just won't get gamma correction in a window @@ -806,6 +845,12 @@ bool D3DFB::CreateGammaTexture () return false; } +//========================================================================== +// +// D3DFB :: CreateVertexes +// +//========================================================================== + bool D3DFB::CreateVertexes () { VertexPos = -1; @@ -825,6 +870,12 @@ bool D3DFB::CreateVertexes () return true; } +//========================================================================== +// +// D3DFB :: CalcFullscreenCoords +// +//========================================================================== + void D3DFB::CalcFullscreenCoords (FBVERTEX verts[4], bool viewarea_only, bool can_double, D3DCOLOR color0, D3DCOLOR color1) const { float offset = OldRenderTarget != NULL ? 0 : LBOffset; @@ -898,35 +949,77 @@ void D3DFB::CalcFullscreenCoords (FBVERTEX verts[4], bool viewarea_only, bool ca verts[3].tv = tmyb; } +//========================================================================== +// +// D3DFB :: GetPageCount +// +//========================================================================== + int D3DFB::GetPageCount () { return 1; } +//========================================================================== +// +// D3DFB :: PaletteChanged +// +//========================================================================== + void D3DFB::PaletteChanged () { } +//========================================================================== +// +// D3DFB :: QueryNewPalette +// +//========================================================================== + int D3DFB::QueryNewPalette () { return 0; } +//========================================================================== +// +// D3DFB :: IsValid +// +//========================================================================== + bool D3DFB::IsValid () { return D3DDevice != NULL; } +//========================================================================== +// +// D3DFB :: GetHR +// +//========================================================================== + HRESULT D3DFB::GetHR () { return 0; } +//========================================================================== +// +// D3DFB :: IsFullscreen +// +//========================================================================== + bool D3DFB::IsFullscreen () { return !Windowed; } +//========================================================================== +// +// D3DFB :: Lock +// +//========================================================================== + bool D3DFB::Lock () { return Lock(true); @@ -944,6 +1037,12 @@ bool D3DFB::Lock (bool buffered) return false; } +//========================================================================== +// +// D3DFB :: Unlock +// +//========================================================================== + void D3DFB::Unlock () { LOG1 ("Unlock <%d>\n", LockCount); @@ -963,10 +1062,17 @@ void D3DFB::Unlock () } } +//========================================================================== +// +// D3DFB :: Update +// // When In2D == 0: Copy buffer to screen and present // When In2D == 1: Copy buffer to screen but do not present // When In2D == 2: Set up for 2D drawing but do not draw anything // When In2D == 3: Present and set In2D to 0 +// +//========================================================================== + void D3DFB::Update () { if (In2D == 3) @@ -1061,6 +1167,12 @@ void D3DFB::Update () UpdatePending = false; } +//========================================================================== +// +// D3DFB :: Flip +// +//========================================================================== + void D3DFB::Flip() { assert(InScene); @@ -1085,6 +1197,12 @@ void D3DFB::Flip() InScene = false; } +//========================================================================== +// +// D3DFB :: PaintToWindow +// +//========================================================================== + bool D3DFB::PaintToWindow () { HRESULT hr; @@ -1106,6 +1224,14 @@ bool D3DFB::PaintToWindow () return true; } +//========================================================================== +// +// D3DFB :: Draw3DPart +// +// The software 3D part, to be exact. +// +//========================================================================== + void D3DFB::Draw3DPart(bool copy3d) { if (copy3d) From 26f14f439be932769b487f51ecf421f66317ae91 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 29 Nov 2009 02:57:09 +0000 Subject: [PATCH 117/241] - Fixed: The FPS meter cannot use I_MSTime(), because if the game is started with +vid_fps 1, it can need the time before the timer is ready to start. SVN r2009 (trunk) --- docs/rh-log.txt | 2 ++ src/sdl/i_system.cpp | 6 ++++++ src/sdl/i_system.h | 1 + src/v_video.cpp | 4 ++-- src/win32/i_system.cpp | 16 ++++++++++++++++ src/win32/i_system.h | 1 + 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index cb1dae7db..53b5891ef 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ November 28, 2009 +- Fixed: The FPS meter cannot use I_MSTime(), because if the game is started + with +vid_fps 1, it can need the time before the timer is ready to start. - Initialize TempRenderTexture and the back buffer to black upon creation. - Fixed: Windowed mode always needs to draw to the temporary surface, even when not gamma correcting, so that D3DFB::GetCurrentScreen() can read from diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 8d0a8b947..931b8a37d 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -124,6 +124,12 @@ unsigned int I_MSTime (void) return time - BaseTime; } +// Exactly the same thing, but based does no modification to the time. +unsigned int I_FPSTime() +{ + return SDL_GetTicks(); +} + // // I_GetTime // returns time in 1/35th second tics diff --git a/src/sdl/i_system.h b/src/sdl/i_system.h index 768240074..778af53f5 100644 --- a/src/sdl/i_system.h +++ b/src/sdl/i_system.h @@ -126,6 +126,7 @@ bool I_WriteIniFailed (); // [RH] Returns millisecond-accurate time unsigned int I_MSTime (void); +unsigned int I_FPSTime(); // Directory searching routines diff --git a/src/v_video.cpp b/src/v_video.cpp index ca8eb7fdc..d8187eb9d 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -838,7 +838,7 @@ void DFrameBuffer::DrawRateStuff () // Draws frame time and cumulative fps if (vid_fps) { - DWORD ms = I_MSTime (); + DWORD ms = I_FPSTime(); DWORD howlong = ms - LastMS; if (howlong >= 0) { @@ -876,7 +876,7 @@ void DFrameBuffer::DrawRateStuff () // Buffer can be NULL if we're doing hardware accelerated 2D if (buffer != NULL) { - buffer += (GetHeight()-1)*GetPitch(); + buffer += (GetHeight()-1) * GetPitch(); for (i = 0; i < tics*2; i += 2) buffer[i] = 0xff; for ( ; i < 20*2; i += 2) buffer[i] = 0x00; diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index d39cfc804..6320c33f5 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -280,6 +280,22 @@ unsigned int I_MSTime() return timeGetTime() - basetime; } +//========================================================================== +// +// I_FPSTime +// +// Returns the current system time in milliseconds. This is used by the FPS +// meter of DFrameBuffer::DrawRateStuff(). Since the screen can display +// before the play simulation is ready to begin, this needs to be +// separate from I_MSTime(). +// +//========================================================================== + +unsigned int I_FPSTime() +{ + return timeGetTime(); +} + //========================================================================== // // I_GetTimePolled diff --git a/src/win32/i_system.h b/src/win32/i_system.h index f268358d7..66b2bac7d 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -132,6 +132,7 @@ bool I_WriteIniFailed (); // [RH] Returns millisecond-accurate time unsigned int I_MSTime (void); +unsigned int I_FPSTime(); // [RH] Title banner to display during startup extern const IWADInfo *DoomStartupInfo; From 17553cfbf619895d81628d1e4fb568904ec47618 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 29 Nov 2009 11:24:01 +0000 Subject: [PATCH 118/241] - fixed: Line_SetBlocking and Line_SetTextureScale were not in the list of action specials used by DECORATE or MAPINFO. - fixed: Teleport_NoStop was not in the line special function table. SVN r2010 (trunk) --- docs/rh-log.txt | 5 +++++ src/actionspecials.h | 2 ++ src/p_lnspec.cpp | 10 +++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 53b5891ef..2dd7aafa3 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +November 29, 2009 (Changes by Graf Zahl) +- fixed: Line_SetBlocking and Line_SetTextureScale were not in the list + of action specials used by DECORATE or MAPINFO. +- fixed: Teleport_NoStop was not in the line special function table. + November 28, 2009 - Fixed: The FPS meter cannot use I_MSTime(), because if the game is started with +vid_fps 1, it can need the time before the timer is ready to start. diff --git a/src/actionspecials.h b/src/actionspecials.h index aefdcc951..98c899f5b 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -53,6 +53,8 @@ DEFINE_SPECIAL(Sector_SetLink, 51, 4, 4, 4) DEFINE_SPECIAL(Scroll_Wall, 52, 5, 5, 5) DEFINE_SPECIAL(Line_SetTextureOffset, 53, 5, 5, 5) DEFINE_SPECIAL(Sector_ChangeFlags, 54, 3, 3, 3) +DEFINE_SPECIAL(Line_SetBlocking, 55, 3, 3, 3) +DEFINE_SPECIAL(Line_SetTextureScale, 56, 5, 5, 5) DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3, 3) DEFINE_SPECIAL(Plat_Stop, 61, 1, 1, 1) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 7417ebbef..7a51075b4 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3120,14 +3120,14 @@ lnSpecFunc LineSpecials[256] = LS_NOP, // 151 Team_UseFP LS_NOP, // 152 Team_Score LS_NOP, // 153 Team_Init - LS_NOP, // 154 Var_Lock + LS_Teleport_NoStop, LS_NOP, // 155 Team_RemoveItem LS_NOP, // 156 Team_GiveItem // [BC] End LS_NOP, // 157 - LS_NOP, // 158 - LS_NOP, // 159 - LS_NOP, // 160 - LS_NOP, // 161 + LS_NOP, // 158 (FS_Execute in GZDoom) + LS_NOP, // 159 (Sector_SetPlaneReflection in GZDoom) + LS_NOP, // 160 (Sector_Set3DFloor in GZDoom and Vavoom) + LS_NOP, // 161 (Sector_SetContents in GZDoom and Vavoom) LS_NOP, // 162 LS_NOP, // 163 LS_NOP, // 164 From f722b10294fd126affbd95a6550a24a8102100b9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 1 Dec 2009 01:15:49 +0000 Subject: [PATCH 119/241] - Increase STEEPSLOPE by 1, because the new FIXED2FLOAT rounds toward nearest, and this makes 45 degree slopes unclimbable again. SVN r2011 (trunk) --- src/p_local.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 31096fb8c..84a50bb5d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -31,7 +31,7 @@ #include -#define STEEPSLOPE 46341 // [RH] Minimum floorplane.c value for walking +#define STEEPSLOPE 46342 // [RH] Minimum floorplane.c value for walking #define BONUSADD 6 From 80034135ef7e326e6dcc941e3896f62cd3e23651 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 1 Dec 2009 03:15:00 +0000 Subject: [PATCH 120/241] - The initial wipe screen is now kept in video memory. I had previously assumed that since the wipes only run at 35 FPS, the time spent DMA'ing it from system to video memory would be acceptable. Apparently I was wrong. In particular, updating the same surface several times probably has to synchronize between each one, making melt particularly slower than it needs to be. SVN r2012 (trunk) --- docs/rh-log.txt | 8 ++ src/win32/fb_d3d9.cpp | 75 ++++++++++-------- src/win32/fb_d3d9_wipe.cpp | 158 +++++++++++++++++++++++-------------- src/win32/win32iface.h | 31 +++++++- 4 files changed, 181 insertions(+), 91 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2dd7aafa3..d150ed707 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +November 30, 2009 +- The initial wipe screen is now kept in video memory. I had previously + assumed that since the wipes only run at 35 FPS, the time spent DMA'ing + it from system to video memory would be acceptable. Apparently I was wrong. + In particular, updating the same surface several times probably has to + synchronize between each one, making melt particularly slower than it + needs to be. + November 29, 2009 (Changes by Graf Zahl) - fixed: Line_SetBlocking and Line_SetTextureScale were not in the list of action specials used by DECORATE or MAPINFO. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index f696951e1..abcd952cb 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -162,30 +162,6 @@ public: int RoundedPaletteSize; }; -// Flags for a buffered quad -enum -{ - BQF_GamePalette = 1, - BQF_CustomPalette = 7, - BQF_Paletted = 7, - BQF_Bilinear = 8, - BQF_WrapUV = 16, - BQF_InvertSource = 32, - BQF_DisableAlphaTest= 64, - BQF_Desaturated = 128, -}; - -// Shaders for a buffered quad -enum -{ - BQS_PalTex, - BQS_Plain, - BQS_RedToAlpha, - BQS_ColorOnly, - BQS_SpecialColormap, - BQS_InGameColormap, -}; - // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -1709,12 +1685,14 @@ void D3DFB::ReleaseScreenshotBuffer() // //========================================================================== -IDirect3DTexture9 *D3DFB::GetCurrentScreen() +IDirect3DTexture9 *D3DFB::GetCurrentScreen(D3DPOOL pool) { IDirect3DTexture9 *tex; IDirect3DSurface9 *tsurf, *surf; D3DSURFACE_DESC desc; + assert(pool == D3DPOOL_SYSTEMMEM || pool == D3DPOOL_DEFAULT); + if (Windowed || PixelDoubling) { // The texture we read into must have the same pixel format as @@ -1752,8 +1730,8 @@ IDirect3DTexture9 *D3DFB::GetCurrentScreen() desc.Format = D3DFMT_A8R8G8B8; } - if (FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height, 1, 0, - desc.Format, D3DPOOL_SYSTEMMEM, &tex, NULL))) + // Read the image data into system memory. + if (FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height, 1, 0, desc.Format, D3DPOOL_SYSTEMMEM, &tex, NULL))) { return NULL; } @@ -1790,6 +1768,39 @@ IDirect3DTexture9 *D3DFB::GetCurrentScreen() return NULL; } } + + // If the caller wants the screen in video memory, create a new texture, and copy back to that. + if (pool == D3DPOOL_DEFAULT) + { + IDirect3DTexture9 *vtex; + IDirect3DSurface9 *vsurf; + + if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, 0, desc.Format, D3DPOOL_DEFAULT, &vtex, NULL))) + { + surf->Release(); + tex->Release(); + return NULL; + } + if (FAILED(vtex->GetSurfaceLevel(0, &vsurf))) + { + vtex->Release(); + surf->Release(); + tex->Release(); + return NULL; + } + if (FAILED(D3DDevice->UpdateSurface(surf, NULL, vsurf, NULL))) + { + vsurf->Release(); + vtex->Release(); + surf->Release(); + tex->Release(); + return NULL; + } + surf->Release(); + tex->Release(); + surf = vsurf; + tex = vtex; + } surf->Release(); return tex; } @@ -1861,7 +1872,7 @@ void D3DFB::DrawPackedTextures(int packnum) quad->ShaderNum = BQS_Plain; } quad->Palette = NULL; - quad->Texture = pack; + quad->Texture = pack->Tex; float x0 = float(x) - 0.5f; float y0 = float(y) - 0.5f; @@ -3007,7 +3018,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, double x, double y, uint32 t return; } - QuadExtra[QuadBatchPos].Texture = tex->Box->Owner; + QuadExtra[QuadBatchPos].Texture = tex->Box->Owner->Tex; if (parms.bilinear) { QuadExtra[QuadBatchPos].Flags |= BQF_Bilinear; @@ -3148,7 +3159,7 @@ void D3DFB::FlatFill(int left, int top, int right, int bottom, FTexture *src, bo quad->ShaderNum = BQS_Plain; } quad->Palette = NULL; - quad->Texture = tex->Box->Owner; + quad->Texture = tex->Box->Owner->Tex; vert[0].x = x0; vert[0].y = y0; @@ -3380,11 +3391,13 @@ void D3DFB::EndQuadBatch() { SetPaletteTexture(quad->Palette->Tex, quad->Palette->RoundedPaletteSize, quad->Palette->BorderColor); } +#if 0 // Set paletted bilinear filtering (IF IT WORKED RIGHT!) if ((quad->Flags & (BQF_Paletted | BQF_Bilinear)) == (BQF_Paletted | BQF_Bilinear)) { SetPalTexBilinearConstants(quad->Texture); } +#endif // Set the alpha blending SetAlphaBlend(D3DBLENDOP(quad->BlendOp), D3DBLEND(quad->SrcBlend), D3DBLEND(quad->DestBlend)); @@ -3442,7 +3455,7 @@ void D3DFB::EndQuadBatch() // Set the texture if (quad->Texture != NULL) { - SetTexture(0, quad->Texture->Tex); + SetTexture(0, quad->Texture); } // Draw the quad diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp index 9c446a5b2..8783a2588 100644 --- a/src/win32/fb_d3d9_wipe.cpp +++ b/src/win32/fb_d3d9_wipe.cpp @@ -159,7 +159,7 @@ bool D3DFB::WipeStartScreen(int type) return false; } - InitialWipeScreen = GetCurrentScreen(); + InitialWipeScreen = GetCurrentScreen(D3DPOOL_DEFAULT); // Create another texture to copy the final wipe screen to so // we can still gamma correct the wipe. Since this is just for @@ -338,6 +338,27 @@ D3DFB::Wiper::~Wiper() { } +//========================================================================== +// +// D3DFB :: Wiper :: DrawScreen +// +// Draw either the initial or target screen completely to the screen. +// +//========================================================================== + +void D3DFB::Wiper::DrawScreen(D3DFB *fb, IDirect3DTexture9 *tex, + D3DBLENDOP blendop, D3DCOLOR color0, D3DCOLOR color1) +{ + FBVERTEX verts[4]; + + fb->CalcFullscreenCoords(verts, false, false, color0, color1); + fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); + fb->SetTexture(0, tex); + fb->SetAlphaBlend(blendop, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); + fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]); + fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); +} + // WIPE: CROSSFADE --------------------------------------------------------- //========================================================================== @@ -363,29 +384,12 @@ bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb) { Clock += ticks; - // Put the initial screen back to the buffer, presumably with DMA. - IDirect3DSurface9 *source = NULL, *target = NULL; - - if (SUCCEEDED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) && - SUCCEEDED(fb->D3DDevice->GetRenderTarget(0, &target))) - { - fb->D3DDevice->UpdateSurface(source, NULL, target, NULL); - target->Release(); - } - if (source != NULL) - { - source->Release(); - } + // Put the initial screen back to the buffer. + DrawScreen(fb, fb->InitialWipeScreen); // Draw the new screen on top of it. - FBVERTEX verts[4]; - - fb->CalcFullscreenCoords(verts, false, false, D3DCOLOR_COLORVALUE(0,0,0,Clock / 32.f), D3DCOLOR_RGBA(255,255,255,0)); - fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); - fb->SetTexture(0, fb->FinalWipeScreen); - fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); - fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]); - fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); + DrawScreen(fb, fb->FinalWipeScreen, D3DBLENDOP_ADD, + D3DCOLOR_COLORVALUE(0,0,0,Clock / 32.f), D3DCOLOR_RGBA(255,255,255,0)); return Clock >= 32; } @@ -422,28 +426,8 @@ D3DFB::Wiper_Melt::Wiper_Melt() bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb) { - IDirect3DSurface9 *source = NULL, *target; - - if (FAILED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) || - FAILED(fb->D3DDevice->GetRenderTarget(0, &target))) - { - // A fat lot of good we can do if we can't get these two surfaces. - if (source != NULL) - { - source->Release(); - } - return true; - } - // Draw the new screen on the bottom. - FBVERTEX verts[4]; - - fb->CalcFullscreenCoords(verts, false, false, 0, 0xFFFFFFFF); - fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); - fb->SetTexture(0, fb->FinalWipeScreen); - fb->SetAlphaBlend(D3DBLENDOP(0)); - fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]); - fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); + DrawScreen(fb, fb->FinalWipeScreen); int i, dy; int fbwidth = fb->Width; @@ -481,13 +465,82 @@ bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb) dpt.y += fb->LBOffsetI; if (rect.bottom > rect.top) { - fb->D3DDevice->UpdateSurface(source, &rect, target, &dpt); + fb->CheckQuadBatch(); + + BufferedQuad *quad = &fb->QuadExtra[fb->QuadBatchPos]; + FBVERTEX *vert = &fb->VertexData[fb->VertexPos]; + WORD *index = &fb->IndexData[fb->IndexPos]; + + quad->Group1 = 0; + quad->Flags = BQF_DisableAlphaTest; + quad->ShaderNum = BQS_Plain; + quad->Palette = NULL; + quad->Texture = fb->InitialWipeScreen; + + // Fill the vertex buffer. + float u0 = rect.left / float(fb->FBWidth); + float v0 = 0; + float u1 = rect.right / float(fb->FBWidth); + float v1 = (rect.bottom - rect.top) / float(fb->FBHeight); + + float x0 = float(rect.left) - 0.5f; + float x1 = float(rect.right) - 0.5f; + float y0 = float(dpt.y) - 0.5f; + float y1 = float(fbheight) - 0.5f; + + vert[0].x = x0; + vert[0].y = y0; + vert[0].z = 0; + vert[0].rhw = 1; + vert[0].color0 = 0; + vert[0].color1 = 0xFFFFFFF; + vert[0].tu = u0; + vert[0].tv = v0; + + vert[1].x = x1; + vert[1].y = y0; + vert[1].z = 0; + vert[1].rhw = 1; + vert[1].color0 = 0; + vert[1].color1 = 0xFFFFFFF; + vert[1].tu = u1; + vert[1].tv = v0; + + vert[2].x = x1; + vert[2].y = y1; + vert[2].z = 0; + vert[2].rhw = 1; + vert[2].color0 = 0; + vert[2].color1 = 0xFFFFFFF; + vert[2].tu = u1; + vert[2].tv = v1; + + vert[3].x = x0; + vert[3].y = y1; + vert[3].z = 0; + vert[3].rhw = 1; + vert[3].color0 = 0; + vert[3].color1 = 0xFFFFFFF; + vert[3].tu = u0; + vert[3].tv = v1; + + // Fill the vertex index buffer. + index[0] = fb->VertexPos; + index[1] = fb->VertexPos + 1; + index[2] = fb->VertexPos + 2; + index[3] = fb->VertexPos; + index[4] = fb->VertexPos + 2; + index[5] = fb->VertexPos + 3; + + // Batch the quad. + fb->QuadBatchPos++; + fb->VertexPos += 4; + fb->IndexPos += 6; } } } } - target->Release(); - source->Release(); + fb->EndQuadBatch(); return done; } @@ -561,18 +614,7 @@ bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb) } // Put the initial screen back to the buffer. - IDirect3DSurface9 *source = NULL, *target; - - if (SUCCEEDED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) && - SUCCEEDED(fb->D3DDevice->GetRenderTarget(0, &target))) - { - fb->D3DDevice->UpdateSurface(source, NULL, target, NULL); - target->Release(); - } - if (source != NULL) - { - source->Release(); - } + DrawScreen(fb, fb->InitialWipeScreen); // Burn the new screen on top of it. float top = fb->LBOffset - 0.5f; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 6cce6afe1..1684f9d82 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -289,7 +289,7 @@ private: DWORD Group1; }; D3DPal *Palette; - PackingTexture *Texture; + IDirect3DTexture9 *Texture; }; enum @@ -344,7 +344,7 @@ private: void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); void CalcFullscreenCoords (FBVERTEX verts[4], bool viewarea_only, bool can_double, D3DCOLOR color0, D3DCOLOR color1) const; bool Reset(); - IDirect3DTexture9 *GetCurrentScreen(); + IDirect3DTexture9 *GetCurrentScreen(D3DPOOL pool=D3DPOOL_SYSTEMMEM); void ReleaseDefaultPoolItems(); void KillNativePals(); void KillNativeTexs(); @@ -444,6 +444,9 @@ private: public: virtual ~Wiper(); virtual bool Run(int ticks, D3DFB *fb) = 0; + + void DrawScreen(D3DFB *fb, IDirect3DTexture9 *tex, + D3DBLENDOP blendop=D3DBLENDOP(0), D3DCOLOR color0=0, D3DCOLOR color1=0xFFFFFFF); }; class Wiper_Melt; friend class Wiper_Melt; @@ -453,6 +456,30 @@ private: Wiper *ScreenWipe; }; +// Flags for a buffered quad +enum +{ + BQF_GamePalette = 1, + BQF_CustomPalette = 7, + BQF_Paletted = 7, + BQF_Bilinear = 8, + BQF_WrapUV = 16, + BQF_InvertSource = 32, + BQF_DisableAlphaTest= 64, + BQF_Desaturated = 128, +}; + +// Shaders for a buffered quad +enum +{ + BQS_PalTex, + BQS_Plain, + BQS_RedToAlpha, + BQS_ColorOnly, + BQS_SpecialColormap, + BQS_InGameColormap, +}; + #if 0 #define STARTLOG do { if (!dbg) dbg = fopen ("k:/vid.log", "w"); } while(0) #define STOPLOG do { if (dbg) { fclose (dbg); dbg=NULL; } } while(0) From d924575b1e1391bf3f023fa0fa96fa22b5b920bf Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 2 Dec 2009 05:02:40 +0000 Subject: [PATCH 121/241] - Fixed: After the previous screenwipe changes, the melt type no longer worked properly in letterboxed modes. - Added another surface to receive a copy of the top back buffer immediately before it is presented. This effectively produces a copy of the front buffer without the performance penalty of GetFrontBufferData, so fullscreen wipe preparation and screenshots are faster now. At lower resolutions, always copying the backbuffer does incur a slight FPS hit, but it's practically free at higher resolutions. SVN r2013 (trunk) --- docs/rh-log.txt | 8 ++ src/win32/fb_d3d9.cpp | 162 ++++++++++++++++--------------------- src/win32/fb_d3d9_wipe.cpp | 9 +-- src/win32/win32iface.h | 2 + 4 files changed, 82 insertions(+), 99 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index d150ed707..dc72ef882 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +December 1, 2009 +- Added another surface to receive a copy of the top back buffer immediately + before it is presented. This effectively produces a copy of the front + buffer without the performance penalty of GetFrontBufferData, so fullscreen + wipe preparation and screenshots are faster now. At lower resolutions, + always copying the backbuffer does incur a slight FPS hit, but it's + practically free at higher resolutions. + November 30, 2009 - The initial wipe screen is now kept in video memory. I had previously assumed that since the wipes only run at 35 FPS, the time spent DMA'ing diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index abcd952cb..9c34db2bd 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -253,6 +253,7 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) FinalWipeScreen = NULL; PaletteTexture = NULL; GammaTexture = NULL; + FrontCopySurface = NULL; for (int i = 0; i < NUM_SHADERS; ++i) { Shaders[i] = NULL; @@ -637,6 +638,7 @@ void D3DFB::ReleaseDefaultPoolItems() SAFE_RELEASE( IndexBuffer ); SAFE_RELEASE( BlockSurface[0] ); SAFE_RELEASE( BlockSurface[1] ); + SAFE_RELEASE( FrontCopySurface ); } //========================================================================== @@ -748,14 +750,14 @@ void D3DFB::KillNativeTexs() bool D3DFB::CreateFBTexture () { - if (FAILED(D3DDevice->CreateTexture (Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) + if (FAILED(D3DDevice->CreateTexture(Width, Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) { int pow2width, pow2height, i; for (i = 1; i < Width; i <<= 1) {} pow2width = i; for (i = 1; i < Height; i <<= 1) {} pow2height = i; - if (FAILED(D3DDevice->CreateTexture (pow2width, pow2height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) + if (FAILED(D3DDevice->CreateTexture(pow2width, pow2height, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &FBTexture, NULL))) { return false; } @@ -770,7 +772,7 @@ bool D3DFB::CreateFBTexture () FBWidth = Width; FBHeight = Height; } - if (FAILED(D3DDevice->CreateTexture (FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &TempRenderTexture, NULL))) + if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &TempRenderTexture, NULL))) { TempRenderTexture = NULL; } @@ -784,6 +786,10 @@ bool D3DFB::CreateFBTexture () surf->Release(); } } + if (FAILED(D3DDevice->CreateRenderTarget(Width, Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &FrontCopySurface, NULL))) + { + return false; + } return true; } @@ -1156,6 +1162,8 @@ void D3DFB::Flip() DoWindowedGamma(); D3DDevice->EndScene(); + CopyNextFrontBuffer(); + // Attempt to counter input lag. if (d3d_antilag && BlockSurface[0] != NULL) { @@ -1173,6 +1181,42 @@ void D3DFB::Flip() InScene = false; } +//========================================================================== +// +// D3DFB :: CopyNextFrontBuffer +// +// Duplicates the contents of the back buffer that will become the front +// buffer upon Present into FrontCopySurface so that we can get the +// contents of the display without wasting time in GetFrontBufferData(). +// +//========================================================================== + +void D3DFB::CopyNextFrontBuffer() +{ + IDirect3DSurface9 *backbuff; + + if (Windowed || PixelDoubling) + { + // Windowed mode or pixel doubling: TempRenderTexture has what we want + if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &backbuff))) + { + D3DDevice->StretchRect(backbuff, NULL, FrontCopySurface, NULL, D3DTEXF_NONE); + backbuff->Release(); + } + } + else + { + // Fullscreen, not pixel doubled: The back buffer has what we want, + // but it might be letter boxed. + if (SUCCEEDED(D3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuff))) + { + RECT srcrect = { 0, LBOffsetI, Width, LBOffsetI + Height }; + D3DDevice->StretchRect(backbuff, &srcrect, FrontCopySurface, NULL, D3DTEXF_NONE); + backbuff->Release(); + } + } +} + //========================================================================== // // D3DFB :: PaintToWindow @@ -1688,50 +1732,25 @@ void D3DFB::ReleaseScreenshotBuffer() IDirect3DTexture9 *D3DFB::GetCurrentScreen(D3DPOOL pool) { IDirect3DTexture9 *tex; - IDirect3DSurface9 *tsurf, *surf; + IDirect3DSurface9 *surf; D3DSURFACE_DESC desc; + HRESULT hr; assert(pool == D3DPOOL_SYSTEMMEM || pool == D3DPOOL_DEFAULT); - if (Windowed || PixelDoubling) + if (FAILED(FrontCopySurface->GetDesc(&desc))) { - // The texture we read into must have the same pixel format as - // the TempRenderTexture. - if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &tsurf))) - { - if (FAILED(tsurf->GetDesc(&desc))) - { - tsurf->Release(); - return NULL; - } - tsurf->Release(); - } - else - { - return NULL; - } + return NULL; + } + if (pool == D3DPOOL_SYSTEMMEM) + { + hr = D3DDevice->CreateTexture(desc.Width, desc.Height, 1, 0, desc.Format, D3DPOOL_SYSTEMMEM, &tex, NULL); } else { - if (SUCCEEDED(D3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &tsurf))) - { - if (FAILED(tsurf->GetDesc(&desc))) - { - tsurf->Release(); - return NULL; - } - tsurf->Release(); - } - else - { - return NULL; - } - // GetFrontBufferData works only with this format - desc.Format = D3DFMT_A8R8G8B8; + hr = D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, desc.Format, D3DPOOL_DEFAULT, &tex, NULL); } - - // Read the image data into system memory. - if (FAILED(D3DDevice->CreateTexture(desc.Width, desc.Height, 1, 0, desc.Format, D3DPOOL_SYSTEMMEM, &tex, NULL))) + if (FAILED(hr)) { return NULL; } @@ -1740,68 +1759,23 @@ IDirect3DTexture9 *D3DFB::GetCurrentScreen(D3DPOOL pool) tex->Release(); return NULL; } - - if (!Windowed && !PixelDoubling) + if (pool == D3DPOOL_SYSTEMMEM) { - if (FAILED(D3DDevice->GetFrontBufferData(0, surf))) - { - surf->Release(); - tex->Release(); - return NULL; - } + // Video -> System memory : use GetRenderTargetData + hr = D3DDevice->GetRenderTargetData(FrontCopySurface, surf); } else { - if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &tsurf))) - { - if (FAILED(D3DDevice->GetRenderTargetData(tsurf, surf))) - { - tsurf->Release(); - tex->Release(); - return NULL; - } - tsurf->Release(); - } - else - { - tex->Release(); - return NULL; - } - } - - // If the caller wants the screen in video memory, create a new texture, and copy back to that. - if (pool == D3DPOOL_DEFAULT) - { - IDirect3DTexture9 *vtex; - IDirect3DSurface9 *vsurf; - - if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, 0, desc.Format, D3DPOOL_DEFAULT, &vtex, NULL))) - { - surf->Release(); - tex->Release(); - return NULL; - } - if (FAILED(vtex->GetSurfaceLevel(0, &vsurf))) - { - vtex->Release(); - surf->Release(); - tex->Release(); - return NULL; - } - if (FAILED(D3DDevice->UpdateSurface(surf, NULL, vsurf, NULL))) - { - vsurf->Release(); - vtex->Release(); - surf->Release(); - tex->Release(); - return NULL; - } - surf->Release(); - tex->Release(); - surf = vsurf; - tex = vtex; + // Video -> Video memory : use StretchRect + RECT destrect = { 0, 0, Width, Height }; + hr = D3DDevice->StretchRect(FrontCopySurface, NULL, surf, &destrect, D3DTEXF_POINT); } surf->Release(); + if (FAILED(hr)) + { + tex->Release(); + return NULL; + } return tex; } diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp index 8783a2588..798a95080 100644 --- a/src/win32/fb_d3d9_wipe.cpp +++ b/src/win32/fb_d3d9_wipe.cpp @@ -459,10 +459,9 @@ bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb) dpt.x = i * fbwidth / WIDTH; dpt.y = MAX(0, y[i] * fbheight / HEIGHT); rect.left = dpt.x; - rect.top = fb->LBOffsetI; + rect.top = 0; rect.right = (i + 1) * fbwidth / WIDTH; - rect.bottom = fbheight - dpt.y + fb->LBOffsetI; - dpt.y += fb->LBOffsetI; + rect.bottom = fbheight - dpt.y; if (rect.bottom > rect.top) { fb->CheckQuadBatch(); @@ -485,8 +484,8 @@ bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb) float x0 = float(rect.left) - 0.5f; float x1 = float(rect.right) - 0.5f; - float y0 = float(dpt.y) - 0.5f; - float y1 = float(fbheight) - 0.5f; + float y0 = float(dpt.y + fb->LBOffsetI) - 0.5f; + float y1 = float(fbheight + fb->LBOffsetI) - 0.5f; vert[0].x = x0; vert[0].y = y0; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 1684f9d82..e311049b7 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -363,6 +363,7 @@ private: void BeginLineBatch(); void EndLineBatch(); void EndBatch(); + void CopyNextFrontBuffer(); D3DCAPS9 DeviceCaps; @@ -419,6 +420,7 @@ private: IDirect3DTexture9 *GammaTexture; IDirect3DTexture9 *ScreenshotTexture; IDirect3DSurface9 *ScreenshotSurface; + IDirect3DSurface9 *FrontCopySurface; IDirect3DVertexBuffer9 *VertexBuffer; FBVERTEX *VertexData; From 88b4ab52ad9e58bd6ee8bcb10ab3f88613ea7817 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 2 Dec 2009 05:49:45 +0000 Subject: [PATCH 122/241] - For windowed and pixel doubled modes, use a chain of two TempRenderTextures and swap between them each frame. The one that's not the TempRenderTexture is used as the FrontCopySurface without the need for a copy operation. This removes the performance penalty the previous commit introduced for these modes. SVN r2014 (trunk) --- src/win32/fb_d3d9.cpp | 61 ++++++++++++++++++++++++++------------ src/win32/fb_d3d9_wipe.cpp | 16 +++++----- src/win32/win32iface.h | 4 ++- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 9c34db2bd..561891e29 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -247,6 +247,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) IndexBuffer = NULL; FBTexture = NULL; TempRenderTexture = NULL; + RenderTexture[0] = NULL; + RenderTexture[1] = NULL; InitialWipeScreen = NULL; ScreenshotTexture = NULL; ScreenshotSurface = NULL; @@ -277,6 +279,8 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) Packs = NULL; PixelDoubling = 0; SkipAt = -1; + CurrRenderTexture = 0; + RenderTextureToggle = 0; Gamma = 1.0; FlashColor0 = 0; @@ -624,15 +628,9 @@ void D3DFB::ReleaseResources () void D3DFB::ReleaseDefaultPoolItems() { SAFE_RELEASE( FBTexture ); - if (FinalWipeScreen != NULL) - { - if (FinalWipeScreen != TempRenderTexture) - { - FinalWipeScreen->Release(); - } - FinalWipeScreen = NULL; - } - SAFE_RELEASE( TempRenderTexture ); + SAFE_RELEASE( FinalWipeScreen ); + SAFE_RELEASE( RenderTexture[0] ); + SAFE_RELEASE( RenderTexture[1] ); SAFE_RELEASE( InitialWipeScreen ); SAFE_RELEASE( VertexBuffer ); SAFE_RELEASE( IndexBuffer ); @@ -772,24 +770,42 @@ bool D3DFB::CreateFBTexture () FBWidth = Width; FBHeight = Height; } - if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &TempRenderTexture, NULL))) + RenderTextureToggle = 0; + RenderTexture[0] = NULL; + RenderTexture[1] = NULL; + if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &RenderTexture[0], NULL))) { - TempRenderTexture = NULL; + return false; + } + if (Windowed || PixelDoubling) + { + // Windowed or pixel doubling: Create another render texture so we can flip between them. + RenderTextureToggle = 1; + if (FAILED(D3DDevice->CreateTexture(FBWidth, FBHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &RenderTexture[1], NULL))) + { + return false; + } } else { - // Initialize the TempRenderTexture to black. + // Fullscreen and not pixel doubling: Create a render target to have the back buffer copied to. + if (FAILED(D3DDevice->CreateRenderTarget(Width, Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &FrontCopySurface, NULL))) + { + return false; + } + } + // Initialize the TempRenderTextures to black. + for (int i = 0; i <= RenderTextureToggle; ++i) + { IDirect3DSurface9 *surf; - if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &surf))) + if (SUCCEEDED(RenderTexture[i]->GetSurfaceLevel(0, &surf))) { D3DDevice->ColorFill(surf, NULL, D3DCOLOR_XRGB(0,0,0)); surf->Release(); } } - if (FAILED(D3DDevice->CreateRenderTarget(Width, Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &FrontCopySurface, NULL))) - { - return false; - } + TempRenderTexture = RenderTexture[0]; + CurrRenderTexture = 0; return true; } @@ -1179,6 +1195,13 @@ void D3DFB::Flip() } D3DDevice->Present(NULL, NULL, NULL, NULL); InScene = false; + + if (RenderTextureToggle) + { + // Flip the TempRenderTexture to the other one now. + CurrRenderTexture ^= RenderTextureToggle; + TempRenderTexture = RenderTexture[CurrRenderTexture]; + } } //========================================================================== @@ -1198,10 +1221,10 @@ void D3DFB::CopyNextFrontBuffer() if (Windowed || PixelDoubling) { // Windowed mode or pixel doubling: TempRenderTexture has what we want + SAFE_RELEASE( FrontCopySurface ); if (SUCCEEDED(TempRenderTexture->GetSurfaceLevel(0, &backbuff))) { - D3DDevice->StretchRect(backbuff, NULL, FrontCopySurface, NULL, D3DTEXF_NONE); - backbuff->Release(); + FrontCopySurface = backbuff; } } else diff --git a/src/win32/fb_d3d9_wipe.cpp b/src/win32/fb_d3d9_wipe.cpp index 798a95080..9a3b34412 100644 --- a/src/win32/fb_d3d9_wipe.cpp +++ b/src/win32/fb_d3d9_wipe.cpp @@ -173,14 +173,14 @@ bool D3DFB::WipeStartScreen(int type) 1, D3DUSAGE_RENDERTARGET, desc.Format, D3DPOOL_DEFAULT, &FinalWipeScreen, NULL))) { - FinalWipeScreen = TempRenderTexture; + (FinalWipeScreen = TempRenderTexture)->AddRef(); } tsurf->Release(); } } else { - FinalWipeScreen = TempRenderTexture; + (FinalWipeScreen = TempRenderTexture)->AddRef(); } // Make even fullscreen model render to the TempRenderTexture, so @@ -229,7 +229,11 @@ void D3DFB::WipeEndScreen() // If these are different, reverse their roles so we don't need to // waste time copying from TempRenderTexture to FinalWipeScreen. - swap(FinalWipeScreen, TempRenderTexture); + if (FinalWipeScreen != TempRenderTexture) + { + swap(RenderTexture[CurrRenderTexture], FinalWipeScreen); + TempRenderTexture = RenderTexture[CurrRenderTexture]; + } // At this point, InitialWipeScreen holds the screen we are wiping from. // FinalWipeScreen holds the screen we are wiping to, which may be the @@ -315,11 +319,7 @@ void D3DFB::WipeCleanup() ScreenWipe = NULL; } SAFE_RELEASE( InitialWipeScreen ); - if (FinalWipeScreen != NULL && FinalWipeScreen != TempRenderTexture) - { - FinalWipeScreen->Release(); - } - FinalWipeScreen = NULL; + SAFE_RELEASE( FinalWipeScreen ); GatheringWipeScreen = false; if (!Accel2D) { diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index e311049b7..9bdfd1072 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -395,6 +395,8 @@ private: int PixelDoubling; int SkipAt; int LBOffsetI; + int RenderTextureToggle; + int CurrRenderTexture; float LBOffset; float Gamma; bool UpdatePending; @@ -415,7 +417,7 @@ private: IDirect3DDevice9 *D3DDevice; IDirect3DTexture9 *FBTexture; - IDirect3DTexture9 *TempRenderTexture; + IDirect3DTexture9 *TempRenderTexture, *RenderTexture[2]; IDirect3DTexture9 *PaletteTexture; IDirect3DTexture9 *GammaTexture; IDirect3DTexture9 *ScreenshotTexture; From ee4b9ed09b360e895a5942531a6ef1e09c41a6f5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Dec 2009 22:10:25 +0000 Subject: [PATCH 123/241] - added some code that prevents overlapping monsters from getting stuck in each other. PIT_CheckThing will return true under the following contitions now: * It was called from P_Move * The actor that is blocking the move already overlaps with the monster that is being moved. * the move will take the 2 actors further apart. SVN r2018 (trunk) --- docs/rh-log.txt | 9 +++++++++ src/p_enemy.cpp | 4 +++- src/p_local.h | 2 ++ src/p_map.cpp | 23 +++++++++++++++++++++-- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index dc72ef882..39d052324 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +December 6, 2009 (Changes by Graf Zahl) +- added some code that prevents overlapping monsters from getting stuck in + each other. PIT_CheckThing will return true under the following contitions + now: + * It was called from P_Move + * The actor that is blocking the move already overlaps with the monster + that is being moved. + * the move will take the 2 actors further apart. + December 1, 2009 - Added another surface to receive a copy of the top back buffer immediately before it is presented. This effectively produces a copy of the front diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 919c11bec..4b80d5b68 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -507,6 +507,8 @@ bool P_Move (AActor *actor) } FCheckPosition tm; + tm.FromPMove = true; + try_ok = true; for(int i=1; i < steps; i++) { @@ -518,7 +520,7 @@ bool P_Move (AActor *actor) if (try_ok) try_ok = P_TryMove (actor, tryx, tryy, dropoff, false, tm); // [GrafZahl] Interpolating monster movement as it is done here just looks bad - // so make it switchable! + // so make it switchable if (nomonsterinterpolation) { actor->PrevX = actor->x; diff --git a/src/p_local.h b/src/p_local.h index 84a50bb5d..415ac46ca 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -346,6 +346,7 @@ struct FCheckPosition sector_t *ceilingsector; bool touchmidtex; bool floatok; + bool FromPMove; line_t *ceilingline; AActor *stepthing; // [RH] These are used by PIT_CheckThing and P_XYMovement to apply @@ -359,6 +360,7 @@ struct FCheckPosition DoRipping = rip; LastRipped = NULL; PushTime = 0; + FromPMove = false; } }; diff --git a/src/p_map.cpp b/src/p_map.cpp index 00db77bee..e401e84fb 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -831,13 +831,32 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } } + + // Both things overlap in x or y direction + bool unblocking = false; + + if (tm.FromPMove) + { + fixed_t newdist = P_AproxDistance(thing->x - tm.x, thing->y - tm.y); + fixed_t olddist = P_AproxDistance(thing->x - tm.thing->x, thing->y - tm.thing->y); + + // Both actors already overlap. To prevent them from remaining stuck allow the move if it + // takes them further apart. + if (newdist > olddist) + { + // ... but not if they did not overlap in z-direction before but would after the move. + unblocking = !((tm.thing->x >= thing->x + thing->height && tm.x < thing->x + thing->height) || + (tm.thing->x + tm.thing->height <= thing->x && tm.x + tm.thing->height > thing->x)); + } + } + // [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so // you can use a scrolling floor to move scenery items underneath a bridge. if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) { // check if a mobj passed over/under another object if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP) { // Some things prefer not to overlap each other, if possible - return false; + return unblocking; } if ((tm.thing->z >= topz) || (tm.thing->z + tm.thing->height <= thing->z)) { @@ -1145,7 +1164,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // despite another solid thing being in the way. // killough 4/11/98: Treat no-clipping things as not blocking - return !solid; + return !solid || unblocking; // return !(thing->flags & MF_SOLID); // old code -- killough } From 20e265f8fb427b8eea8f689733229b03ff359c3c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 11 Dec 2009 06:20:35 +0000 Subject: [PATCH 124/241] - Fixed: You should still be able to pick up ammo that has a max amount set at 0. - Added a few NULL screen checks. SVN r2019 (trunk) --- docs/rh-log.txt | 5 +++++ src/c_console.cpp | 2 +- src/d_main.cpp | 2 +- src/g_shared/a_pickups.cpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 39d052324..869f0c6d0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +December 11, 2009 +- Fixed: You should still be able to pick up ammo that has a max amount set + at 0. +- Added a few NULL screen checks. + December 6, 2009 (Changes by Graf Zahl) - added some code that prevents overlapping monsters from getting stuck in each other. PIT_CheckThing will return true under the following contitions diff --git a/src/c_console.cpp b/src/c_console.cpp index ef06baa6a..324fad660 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1843,7 +1843,7 @@ static const char logbar[] = "\n<------------------------------->\n"; void C_MidPrint (FFont *font, const char *msg) { - if (StatusBar == NULL) + if (StatusBar == NULL || screen == NULL) return; if (msg != NULL) diff --git a/src/d_main.cpp b/src/d_main.cpp index 70db2f050..0aa0b1baf 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -560,7 +560,7 @@ void D_Display () bool wipe; bool hw2d; - if (nodrawers) + if (nodrawers || screen == NULL) return; // for comparative timing / profiling cycle_t cycles; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index eb0037793..201d83e5f 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1190,7 +1190,7 @@ bool AInventory::TryPickup (AActor *&toucher) ItemFlags &= ~IF_PICKUPGOOD; GoAwayAndDie (); } - else if (MaxAmount == 0) + else if (MaxAmount == 0 && !IsKindOf(RUNTIME_CLASS(AAmmo))) { // Special case: If an item's MaxAmount is 0, you can still pick it // up if it is autoactivate-able. From 9522d81cd7ff4b3a8fdabe85eed7a1d23b341f07 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Dec 2009 07:42:06 +0000 Subject: [PATCH 125/241] - Added Blzut's zipdir compatibility patch for Solaris. SVN r2020 (trunk) --- tools/zipdir/zipdir.c | 100 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/tools/zipdir/zipdir.c b/tools/zipdir/zipdir.c index 584cf98ae..0daf927f9 100644 --- a/tools/zipdir/zipdir.c +++ b/tools/zipdir/zipdir.c @@ -36,8 +36,10 @@ #define stat _stat #else #include +#if !defined(__sun) #include #endif +#endif #include #include #include @@ -131,7 +133,10 @@ typedef unsigned int DWORD; typedef unsigned short WORD; typedef unsigned char BYTE; -#pragma pack(push,1) +// [BL] Solaris (well GCC on Solaris) doesn't seem to support pack(push/pop, 1) so we'll need to use use it +// on the whole file. +#pragma pack(1) +//#pragma pack(push,1) typedef struct { DWORD Magic; // 0 @@ -179,7 +184,7 @@ typedef struct DWORD DirectoryOffset; WORD ZipCommentLength; } EndOfCentralDirectory; -#pragma pack(pop) +//#pragma pack(pop) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -484,6 +489,97 @@ dir_tree_t *add_dirs(char **argv) return trees; } +#elif defined(__sun) + +//========================================================================== +// +// add_dirs +// Solaris version +// +// Given NULL-terminated array of directory paths, create trees for them. +// +//========================================================================== + +void add_dir(dir_tree_t *tree, char* dirpath) +{ + DIR *directory = opendir(dirpath); + if(directory == NULL) + return; + + struct dirent *file; + while((file = readdir(directory)) != NULL) + { + if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it. + continue; + + int isDirectory = 0; + int time = 0; + + char* fullFileName = malloc(strlen(dirpath) + strlen(file->d_name) + 1); + strcpy(fullFileName, dirpath); + strcat(fullFileName, file->d_name); + + struct stat *fileStat; + fileStat = malloc(sizeof(struct stat)); + stat(fullFileName, fileStat); + isDirectory = S_ISDIR(fileStat->st_mode); + time = fileStat->st_mtime; + free(stat); + + free(fullFileName); + + if(isDirectory) + { + char* newdir; + newdir = malloc(strlen(dirpath) + strlen(file->d_name) + 2); + strcpy(newdir, dirpath); + strcat(newdir, file->d_name); + strcat(newdir, "/"); + add_dir(tree, newdir); + free(newdir); + continue; + } + + file_entry_t *entry; + entry = alloc_file_entry(dirpath, file->d_name, time); + if (entry == NULL) + { + //no_mem = 1; + break; + } + entry->next = tree->files; + tree->files = entry; + } + + closedir(directory); +} + +dir_tree_t *add_dirs(char **argv) +{ + dir_tree_t *tree, *trees = NULL; + + int i = 0; + while(argv[i] != NULL) + { + tree = alloc_dir_tree(argv[i]); + tree->next = trees; + trees = tree; + + if(tree != NULL) + { + char* dirpath = malloc(sizeof(argv[i]) + 2); + strcpy(dirpath, argv[i]); + if(dirpath[strlen(dirpath)] != '/') + strcat(dirpath, "/"); + add_dir(tree, dirpath); + free(dirpath); + } + + i++; + } + return trees; +} + #else //========================================================================== From c7ae1b585d50278cbc4e3755623feeb4f24765c6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Dec 2009 07:45:46 +0000 Subject: [PATCH 126/241] - Added SnailMan's updated language.ita file. SVN r2021 (trunk) --- docs/rh-log.txt | 3 + wadsrc/static/language.ita | 151 +++++++++++++++++++++++++++++++++---- 2 files changed, 139 insertions(+), 15 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 869f0c6d0..9d40bf8e4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +December 11, 2009 (Changes by Graf Zahl) +- Added SnailMan's updated language.ita file. + December 11, 2009 - Fixed: You should still be able to pick up ammo that has a max amount set at 0. diff --git a/wadsrc/static/language.ita b/wadsrc/static/language.ita index b284a2e41..a46237991 100644 --- a/wadsrc/static/language.ita +++ b/wadsrc/static/language.ita @@ -31,6 +31,25 @@ QUITMSG12 = "senti amico, esci adesso\ne perdi il tuo body count!"; QUITMSG13 = "esci pure. quanto tornerai\nti aspettero' con un bastone."; QUITMSG14 = "sei fortunato che non ti picchi\nper aver pensato di andartene."; +// Quit Strife messages +QUITMSG15 = "dove stai andando?!\ne la ribellione?"; +QUITMSG16 = "macellus interruptus...\nche presa in giro!"; +QUITMSG17 = "ma tu sei la speranza\n-- la mia unica possibilita'!!"; +QUITMSG18 = "nessuno gira le spalle a Blackbird."; +QUITMSG19 = "pensavo tu fossi diverso..."; +QUITMSG20 = "ma bravo! uccidi e scappi!"; +QUITMSG21 = "puoi uscire...\nma non puoi nasconderti..."; +QUITMSG22 = "eehi, che problema c'e'?\nla mamma ha detto che e' ora di cena?"; + +// Quit Chex messages +QUITMSG23 = "Non uscire ora, ci sono ancora\nflemoidi a piede libero!"; +QUITMSG24 = "Non arrenderti -- i flemoidi\nci sopraffaranno!"; +QUITMSG25 = "Non andartene ora.\nCi serve il tuo aiuto!"; +QUITMSG26 = "Spero tu stia solo facendo un\nbreak per prendere un Chex(R) party mix."; +QUITMSG27 = "non uscire ora!\nCi serve il tuo aiuto!"; +QUITMSG28 = "Non abbandonare la\nFederazione Intergalattica dei Cereali!"; +QUITMSG29 = "Il vero guerriero Chex(R)\nnon si arrenderebbe cosi' in fretta!"; + LOADNET = "non puoi caricare una partita durante un netgame!\n\npremi un tasto."; QLOADNET = "non puoi fare un quickload durante un netgame!\n\npremi un tasto."; QSAVESPOT = "non hai ancora scelto uno slot per il quicksave!\n\npremi un tasto."; @@ -91,6 +110,7 @@ PD_REDK = "Ti serve una chiave rossa per aprire questa porta"; PD_YELLOWK = "Ti serve una chiave gialla per aprire questa porta"; GGSAVED = "gioco salvato"; HUSTR_MSGU = "[Messaggio non inviato]"; +PICKUP_PISTOL_DROPPED = "Raccolta una pistola."; // Level names HUSTR_E1M1 = "E1M1: Hangar"; @@ -254,6 +274,8 @@ STSTR_BEHOLD = "inVuln, BerSerk, Invisib, Tuta anti-Rad, MAppa, o Amplif-Luce"; STSTR_BEHOLDX = "Power-up concesso/tolto"; STSTR_CHOPPERS = "Ora vai e segali tutti!"; STSTR_CLEV = "Cambio di livello...\n"; +TXT_BUDDHAON = "Modalita' Buddha attivata"; +TXT_BUDDHAOFF = "Modalita' Buddha disattivata"; E1TEXT = "Una volta che hai eliminato i cattivi e\n" @@ -559,13 +581,15 @@ PD_BLUESO = "ti serve una chiave-teschio blu per attivare questo oggetto "; PD_REDSO = "ti serve una chiave-teschio rossa per attivare questo oggetto "; PD_YELLOWSO = "ti serve una chiave-teschio gialla per attivare questo oggetto "; +PD_ALLKEYS = "Ti servono tutte le chiavi"; + // Gameflow messages TXT_FRAGLIMIT = "Fraglimit raggiunto."; TXT_TIMELIMIT = "Timelimit raggiunto."; // Spree messages -SPREEKILLSELF = "%o stava bene finche' %g non si e' ucciso!"; +SPREEKILLSELF = "%o stava andando bene finche' non si e' ucciso da solo!"; SPREEOVER = "La sequela di frag di %o e' stata terminata da %k"; SPREE5 = "%k e' preda di un momento omicida!"; SPREE10 = "%k sta facendo un massacro!"; @@ -578,6 +602,10 @@ MULTI2 = "Frag doppio!"; MULTI3 = "Frag multiplo!"; MULTI4 = "Frag ultra!"; MULTI5 = "Frag DA PAURA!"; +//MULTI2 = "Double kill!"; +//MULTI3 = "Multi kill!"; +//MULTI4 = "Ultra kill!"; +//MULTI5 = "Monster kill!"; // Obituary strings // First the self-kills, then the other-kills @@ -588,24 +616,24 @@ OB_EXIT = "%o ha provato a uscire."; OB_WATER = "%o non sapeva nuotare."; OB_SLIME = "%o e' mutato."; OB_LAVA = "%o si e' sciolto."; -OB_BARREL = "%o e' esploso."; +OB_BARREL = "%o ha fatto bum."; OB_SPLASH = "%o si e' trovato nel posto sbagliato."; OB_R_SPLASH = "%o avrebbe dovuto allontanarsi."; OB_ROCKET = "%o avrebbe dovuto allontanarsi."; OB_KILLEDSELF = "%o ha ucciso se stesso."; -OB_STEALTHBABY = "%o pensava che %g avesse visto un arachnotron."; -OB_STEALTHVILE = "%o pensava che %g avesse visto un Arch-Vile."; -OB_STEALTHBARON = "%o pensava che %g avesse visto un Barone Infernale."; -OB_STEALTHCACO = "%o pensava che %g avesse visto un cacodemone."; -OB_STEALTHCHAINGUY = "%o pensava che %g avesse visto uno zombie commando."; -OB_STEALTHDEMON = "%o pensava che %g avesse visto un demone."; -OB_STEALTHKNIGHT = "%o pensava che %g avesse visto un Cavaliere Infernale."; -OB_STEALTHIMP = "%o pensava che %g avesse visto un imp."; -OB_STEALTHFATSO = "%o pensava che %g avesse visto un mancubo."; -OB_STEALTHUNDEAD = "%o pensava che %g avesse visto un revenant."; -OB_STEALTHSHOTGUY = "%o pensava che %g avesse visto un sergente."; -OB_STEALTHZOMBIE = "%o pensava che %g avesse visto uno zombie."; +OB_STEALTHBABY = "a %o sembrava di aver visto un arachnotron."; +OB_STEALTHVILE = "a %o sembrava di aver visto un Arch-Vile."; +OB_STEALTHBARON = "a %o sembrava di aver visto un Barone Infernale."; +OB_STEALTHCACO = "a %o sembrava di aver visto un cacodemone."; +OB_STEALTHCHAINGUY = "a %o sembrava di aver visto uno zombie commando."; +OB_STEALTHDEMON = "a %o sembrava di aver visto un demone."; +OB_STEALTHKNIGHT = "a %o sembrava di aver visto un Cavaliere Infernale."; +OB_STEALTHIMP = "a %o sembrava di aver visto un imp."; +OB_STEALTHFATSO = "a %o sembrava di aver visto un mancubo."; +OB_STEALTHUNDEAD = "a %o sembrava di aver visto un revenant."; +OB_STEALTHSHOTGUY = "a %o sembrava di aver visto un sergente."; +OB_STEALTHZOMBIE = "a %o sembrava di aver visto uno zombie."; OB_UNDEADHIT = "%o e' stato massacrato da un revenant."; OB_IMPHIT = "%o e' stato squarciato da un imp."; OB_CACOHIT = "%o si e' avvicinato troppo a un cacodemone."; @@ -629,6 +657,7 @@ OB_BABY = "%o ha permesso che un arachnotron l'uccidesse."; OB_CYBORG = "%o e' stato spiaccicato da un Cyberdemonio."; OB_WOLFSS = "%o ha incontrato un Nazista."; +OB_DOG = "%o e' stato sbranato da un cane."; OB_CHICKEN = "%o e' stato beccato a morte."; OB_BEAST = "%o e' stato carbonizzato da una bestia."; OB_CLINK = "%o e' stato squarciato da un lapillo."; @@ -667,7 +696,7 @@ OB_MONTELEFRAG = "%o si e' fatto telefraggare."; OB_DEFAULT = "%o e' morto."; OB_FRIENDLY1 = "%k falcia via un compagno."; -OB_FRIENDLY2 = "%k controlla gli occhiali di %p."; +OB_FRIENDLY2 = "%k si controlla gli occhiali."; OB_FRIENDLY3 = "%k regala un frag all'altro team."; OB_FRIENDLY4 = "%k perde un altro amico."; @@ -1016,3 +1045,95 @@ BBA_SCROTUM = "%o ha subito la separazione dello scroto"; BBA_POPULATION = "%o si e' offerto per il controllo della popolazione"; BBA_SUICIDE = "%o si e' suicidato"; BBA_DARWIN = "%o ha ricevuto il Darwin Award"; + +// Chex Quest Strings +CHUSTR_E1M1 = "E1M1: Zona di Atterraggio"; +CHUSTR_E1M2 = "E1M2: Struttura di Immagazzinamento"; +CHUSTR_E1M3 = "E1M3: Laboratorio Sperimentale"; +CHUSTR_E1M4 = "E1M4: Arboreto"; +CHUSTR_E1M5 = "E1M5: Caverne di Bazoik"; + +CE1TEXT = + "Missione compiuta.\n" + "\n" + "Sei preparato per la prossima missione?\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "Premi il tasto 'esc' per continuare..."; + +CE2TEXT = "Ce l'hai fatta!"; +CE3TEXT = "Meraviglioso!"; +CE4TEXT = "Fantastico"; + +CLOADNET = "non puoi caricare una quest durante una net quest!\n\npress a key."; +CQSPROMPT = "sovrascrivere il salvataggio\n\n'%s'?\n\npremi y oppure n."; +CQLOADNET = "non puoi fare un quickload durante una netquest!\n\npremi un tasto."; +CQLPROMPT = "vuoi fare un quickload della quest\n\n'%s'?\n\npremi y oppure n."; +CNEWGAME = "non puoi iniziare una nuova quest\ndurante una quest in rete.\n\npremi un tasto."; + +CNIGHTMARE = "Attento, sara' dura.\nVuoi continuare?\n\npremi y oppure n."; + +CSWSTRING = "questa e' Chex(R) Quest. cerca\n\nfuturi livelli su www.chexquest.com.\n\npremi un tasto."; + +CNETEND = "non puoi terminare una netquest!\n\npremi un tasto"; +CENDGAME = "sei sicuro di voler terminare la quest?\n\npremi y oppure n."; + +GOTCHEXARMOR = "Raccolta un'Armatura Chex(R)."; +GOTSUPERCHEXARMOR = "Raccolta la Super Armatura Chex(R)!"; +GOTWATER = "Raccolto un bicchiere d'acqua."; +GOTREPELLENT = "Raccolto del repellente allo slime."; +GOTBREAKFAST = "Colazione da supercarica!"; +GOTCBLUEKEY = "Raccolta una chiave blu."; +GOTCYELLOWKEY = "Raccolta una chiave gialla."; +GOTCREDKEY = "Raccolta una chiave rossa."; +GOTFRUIT = "Raccolto un vassoio di frutta."; +GOTVEGETABLESNEED = "La verdura ti fa DAVVERO bene!"; +GOTVEGETABLES = "Raccolto un vassoio di verdura."; +GOTSLIMESUIT = "Raccolto un vestito a prova di slime"; +GOTCHEXMAP = "Trovata una mappa computerizzata"; + +GOTZORCHRECHARGE = "Raccolta una ricarica di mini zorch."; +GOTMINIZORCHPACK = "Raccolta una scatola di mini zorch."; +GOTPROPULSORRECHARGE = "Raccolta una ricarica di zorch a propulsione."; +GOTPROPULSORPACK = "Raccolta una scatola di zorch a propulsione."; +GOTPHASINGZORCHERRECHARGE = "Raccolta una ricarica per zorcher a phasing"; +GOTPHASINGZORCHERPACK = "Raccolta una scatola per zorcher a phasing."; +GOTLARGEZORCHERRECHARGE = "Raccolta una ricarica per zorcher grande."; +GOTLARGEZORCHERPACK = "Raccolta una scatola per zorcher grande."; +GOTZORCHPACK = "Raccolto uno ZorchZaino!"; + +GOTLAZDEVICE = "Hai trovato il dispositivo LAZ! Cavolo!"; +GOTRAPIDZORCHER = "Hai trovato il zorcher rapido!"; +GOTSUPERBOOTSPORK = "Hai trovato il super bootspork!"; +GOTZORCHPROPULSOR = "Hai trovato il propulsore zorch!"; +GOTPHASINGZORCHER = "Hai trovato il zorcher a phasing!"; +GOTLARGEZORCHER = "Hai trovato il zorcher grande!"; +GOTSUPERLARGEZORCHER = "Hai trovato il mega zorcher!"; +GOTMINIZORCHER = "Raccolto un mini zorcher."; + +STSTR_CDQDON = "Modalita' invincibile attivata"; +STSTR_CDQDOFF = "Modalita' invincibile disattivata"; +STSTR_CFAADDED = "Zorch aggiunto"; +STSTR_CKFAADDED = "Super Zorch aggiunto"; +STSTR_CCHOPPERS = "... Mangia Chex(R)!"; + +OB_COMMONUS = "%o e' stato coperto di slime da un flemoid."; +OB_BIPEDICUS = "%o e' stato coperto di slime da un bipedicus."; +OB_BIPEDICUS2 = "%o e' stato coperto di slime da un bipedicus corazzato."; +OB_CYCLOPTIS = "%o e' stato coperto di slime da un cycloptis."; +OB_FLEMBRANE = "%o e' stato sconfitto dalla Flembrana."; + +OB_MPSPOON = "%o e' stato imboccato da %k."; +OB_MPBOOTSPORK = "%o e' stato mischiato ben bene dal bootspork di %k."; +OB_MPZORCH = "%o e' stato zorchato da %k."; +OB_MPMEGAZORCH = "%o e' stato colpito dal mega-zorcher di %k."; +OB_MPRAPIDZORCH = "%o e' stato rapid-zorchato da %k."; +OB_MPPROPULSOR = "%o e' stato zorchato dal propulsore di %k."; +OB_MPP_SPLASH = "%o e' stato colpito dal propulsore di %k."; +OB_MPPHASEZORCH = "%o e' stato phase-zorchato da %k."; +OB_MPLAZ_BOOM = "%o e' stato preda del dispositivo LAZ di %k."; +OB_MPLAZ_SPLASH = "%o e' stato lazzato da %k."; From 2fb2c798879727156b0568514b64f3a7d3518f2b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Dec 2009 09:21:08 +0000 Subject: [PATCH 127/241] - fixed: Auto-COMPAT_SHORTTEX for IWADs must be set per IWAD, not in general for Doom. - added autodetection of Harmony's IWAD. SVN r2022 (trunk) --- docs/rh-log.txt | 3 +++ src/compatibility.cpp | 2 +- src/d_iwad.cpp | 25 +++++++++++++++++++------ src/d_main.h | 1 + src/gi.h | 1 + 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 9d40bf8e4..57df4f98c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ December 11, 2009 (Changes by Graf Zahl) +- fixed: Auto-COMPAT_SHORTTEX for IWADs must be set per IWAD, not in general + for Doom. +- added autodetection of Harmony's IWAD. - Added SnailMan's updated language.ita file. December 11, 2009 diff --git a/src/compatibility.cpp b/src/compatibility.cpp index a6bb4a38a..059a8a4b7 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -196,7 +196,7 @@ void CheckCompatibility(MapData *map) FCompatValues *flags; // When playing Doom IWAD levels force COMPAT_SHORTTEX. - if (Wads.GetLumpFile(map->lumpnum) == 1 && gameinfo.gametype == GAME_Doom && !(level.flags & LEVEL_HEXENFORMAT)) + if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATSHORTTEX) && !(level.flags & LEVEL_HEXENFORMAT)) { ii_compatflags = COMPATF_SHORTTEX; ib_compatflags = 0; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 8a7b0dacf..dae65379d 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -58,18 +58,18 @@ EIWADType gameiwad; const IWADInfo IWADInfos[NUM_IWAD_TYPES] = { // banner text, autoname, fg color, bg color - { "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/tnt.txt", GI_MAPxx }, - { "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/plutonia.txt", GI_MAPxx }, + { "Final Doom: TNT - Evilution", "TNT", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/tnt.txt", GI_MAPxx | GI_COMPATSHORTTEX }, + { "Final Doom: Plutonia Experiment", "Plutonia", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/plutonia.txt", GI_MAPxx | GI_COMPATSHORTTEX }, { "Hexen: Beyond Heretic", NULL, MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx }, { "Hexen: Deathkings of the Dark Citadel", "HexenDK", MAKERGB(240,240,240), MAKERGB(139,68,9), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx }, { "Hexen: Demo Version", "HexenDemo",MAKERGB(240,240,240), MAKERGB(107,44,24), GAME_Hexen, "mapinfo/hexen.txt", GI_MAPxx | GI_SHAREWARE }, - { "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx }, + { "DOOM 2: Hell on Earth", "Doom2", MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx | GI_COMPATSHORTTEX }, { "Heretic Shareware", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0), GAME_Heretic, "mapinfo/hereticsw.txt",GI_SHAREWARE }, { "Heretic: Shadow of the Serpent Riders", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0), GAME_Heretic, "mapinfo/heretic.txt", GI_MENUHACK_EXTENDED }, { "Heretic", NULL, MAKERGB(252,252,0), MAKERGB(168,0,0), GAME_Heretic, "mapinfo/heretic.txt" }, - { "DOOM Shareware", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom1.txt", GI_SHAREWARE }, - { "The Ultimate DOOM", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168), GAME_Doom, "mapinfo/ultdoom.txt" }, - { "DOOM Registered", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom1.txt" }, + { "DOOM Shareware", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom1.txt", GI_SHAREWARE | GI_COMPATSHORTTEX }, + { "The Ultimate DOOM", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168), GAME_Doom, "mapinfo/ultdoom.txt", GI_COMPATSHORTTEX }, + { "DOOM Registered", "Doom1", MAKERGB(84,84,84), MAKERGB(168,168,168), GAME_Doom, "mapinfo/doom1.txt", GI_COMPATSHORTTEX }, { "Strife: Quest for the Sigil", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101), GAME_Strife, "mapinfo/strife.txt", GI_MAPxx }, { "Strife: Teaser (Old Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101), GAME_Strife, "mapinfo/strife.txt", GI_MAPxx | GI_SHAREWARE }, { "Strife: Teaser (New Version)", NULL, MAKERGB(224,173,153), MAKERGB(0,107,101), GAME_Strife, "mapinfo/strife.txt", GI_MAPxx | GI_SHAREWARE | GI_TEASER2 }, @@ -81,6 +81,7 @@ const IWADInfo IWADInfos[NUM_IWAD_TYPES] = { "Chex(R) Quest", "Chex1", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex.txt" }, { "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt" }, { "Action Doom 2: Urban Brawl", "UrbanBrawl",MAKERGB(168,168,0), MAKERGB(168,0,0), GAME_Doom, "mapinfo/doom2.txt" }, + { "Harmony", "Harmony", MAKERGB(110,180,230), MAKERGB(69,79,126), GAME_Doom, "mapinfo/doom2.txt" }, //{ "ZDoom Engine", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) }, }; @@ -111,6 +112,7 @@ static const char *IWADNames[] = "chex.wad", "chex3.wad", "action2.wad", + "harm1.wad", #ifdef unix "DOOM2.WAD", // Also look for all-uppercase names "PLUTONIA.WAD", @@ -134,6 +136,7 @@ static const char *IWADNames[] = "CHEX.WAD", "CHEX3.WAD", "ACTION2.WAD", + "HARM1.WAD", #endif NULL }; @@ -169,6 +172,9 @@ static EIWADType ScanIWAD (const char *iwad) "CYCLA1", "FLMBA1", "MAPINFO", + "0HAWK01", + "0CARA3", + "0NOSE1", { 'G','A','M','E','I','N','F','O' }, "E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", "E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9", @@ -199,6 +205,9 @@ static EIWADType ScanIWAD (const char *iwad) Check_Cycla1, Check_Flmba1, Check_Mapinfo, + Check_Hawk, + Check_Car, + Check_Nose, Check_Gameinfo, Check_e2m1 }; @@ -287,6 +296,10 @@ static EIWADType ScanIWAD (const char *iwad) { return IWAD_ActionDoom2; } + else if (lumpsfound[Check_Hawk] && lumpsfound[Check_Car] && lumpsfound[Check_Nose]) + { + return IWAD_Harmony; + } else if (lumpsfound[Check_FreeDoom]) { // Is there a 100% reliable way to tell FreeDoom and FreeDM diff --git a/src/d_main.h b/src/d_main.h index e9af860a0..744e76bcc 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -81,6 +81,7 @@ enum EIWADType IWAD_ChexQuest, IWAD_ChexQuest3, IWAD_ActionDoom2, + IWAD_Harmony, IWAD_Custom, NUM_IWAD_TYPES diff --git a/src/gi.h b/src/gi.h index b46be119c..0ada094c2 100644 --- a/src/gi.h +++ b/src/gi.h @@ -42,6 +42,7 @@ #define GI_SHAREWARE 0x00000002 #define GI_MENUHACK_EXTENDED 0x00000004 // (Heretic) #define GI_TEASER2 0x00000008 // Alternate version of the Strife Teaser +#define GI_COMPATSHORTTEX 0x00000010 // always force COMPAT_SHORTTEX for IWAD maps. #include "gametype.h" From b3d2a1f074ffc72bdbb9a27044f7d906caeb268c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 13 Dec 2009 04:59:19 +0000 Subject: [PATCH 128/241] - Added a damage type parameter to A_KillChildren, A_KillMaster, and A_KillSiblings. SVN r2023 (trunk) --- docs/rh-log.txt | 4 ++++ src/thingdef/thingdef_codeptr.cpp | 25 +++++++++++++++++-------- wadsrc/static/actors/actor.txt | 6 +++--- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 57df4f98c..cd78d4d9d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 12, 2009 +- Added a damage type parameter to A_KillChildren, A_KillMaster, and + A_KillSiblings. + December 11, 2009 (Changes by Graf Zahl) - fixed: Auto-COMPAT_SHORTTEX for IWADs must be set per IWAD, not in general for Doom. diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d1c9f4083..441304ea1 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1951,11 +1951,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf) // A_KillMaster // //=========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_KillMaster) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) { + ACTION_PARAM_START(1); + ACTION_PARAM_NAME(damagetype, 0); + if (self->master != NULL) { - P_DamageMobj(self->master, self, self, self->master->health, NAME_None, DMG_NO_ARMOR); + P_DamageMobj(self->master, self, self, self->master->health, damagetype, DMG_NO_ARMOR); } } @@ -1964,16 +1967,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_KillMaster) // A_KillChildren // //=========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_KillChildren) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { + ACTION_PARAM_START(1); + ACTION_PARAM_NAME(damagetype, 0); + TThinkerIterator it; - AActor * mo; + AActor *mo; while ( (mo = it.Next()) ) { if (mo->master == self) { - P_DamageMobj(mo, self, self, mo->health, NAME_None, DMG_NO_ARMOR); + P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR); } } } @@ -1983,16 +1989,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_KillChildren) // A_KillSiblings // //=========================================================================== -DEFINE_ACTION_FUNCTION(AActor, A_KillSiblings) +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { + ACTION_PARAM_START(1); + ACTION_PARAM_NAME(damagetype, 0); + TThinkerIterator it; - AActor * mo; + AActor *mo; while ( (mo = it.Next()) ) { if (mo->master == self->master && mo != self) { - P_DamageMobj(mo, self, self, mo->health, NAME_None, DMG_NO_ARMOR); + P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR); } } } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 51513e10c..117a29ac8 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -209,9 +209,9 @@ ACTOR Actor native //: Thinker action native A_RemoveMaster(); action native A_RemoveChildren(bool removeall = false); action native A_RemoveSiblings(bool removeall = false); - action native A_KillMaster(); - action native A_KillChildren(); - action native A_KillSiblings(); + action native A_KillMaster(name damagetype = "none"); + action native A_KillChildren(name damagetype = "none"); + action native A_KillSiblings(name damagetype = "none"); action native A_RaiseMaster(); action native A_RaiseChildren(); action native A_RaiseSiblings(); From 28c23edb2f07adf05fda2c267b8ebda3c7b29285 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 13 Dec 2009 05:04:12 +0000 Subject: [PATCH 129/241] - Added a DMG_NO_FACTOR flag for P_DamageMobj(). A_KillChildren, A_KillMaster, and A_KillSiblings now use it. SVN r2024 (trunk) --- docs/rh-log.txt | 2 ++ src/p_interaction.cpp | 25 ++++++++++++++----------- src/p_local.h | 1 + src/thingdef/thingdef_codeptr.cpp | 6 +++--- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index cd78d4d9d..19dc7f7d1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ December 12, 2009 +- Added a DMG_NO_FACTOR flag for P_DamageMobj(). A_KillChildren, A_KillMaster, + and A_KillSiblings now use it. - Added a damage type parameter to A_KillChildren, A_KillMaster, and A_KillSiblings. diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 3c8f715f5..003e0077e 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1000,21 +1000,24 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage return; } - DmgFactors * df = target->GetClass()->ActorInfo->DamageFactors; - if (df != NULL) + if (!(flags & DMG_NO_FACTOR)) { - fixed_t * pdf = df->CheckKey(mod); - if (pdf== NULL && mod != NAME_None) pdf = df->CheckKey(NAME_None); - if (pdf != NULL) + DmgFactors *df = target->GetClass()->ActorInfo->DamageFactors; + if (df != NULL) { - damage = FixedMul(damage, *pdf); - if (damage <= 0) - return; + fixed_t *pdf = df->CheckKey(mod); + if (pdf== NULL && mod != NAME_None) pdf = df->CheckKey(NAME_None); + if (pdf != NULL) + { + damage = FixedMul(damage, *pdf); + if (damage <= 0) + return; + } } + damage = FixedMul(damage, target->DamageFactor); + if (damage < 0) + return; } - damage = FixedMul(damage, target->DamageFactor); - if (damage < 0) - return; damage = target->TakeSpecialDamage (inflictor, source, damage, mod); } diff --git a/src/p_local.h b/src/p_local.h index 415ac46ca..27654aafa 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -468,6 +468,7 @@ enum EDmgFlags DMG_INFLICTOR_IS_PUFF = 2, DMG_THRUSTLESS = 4, DMG_FORCED = 8, + DMG_NO_FACTOR = 16, }; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 441304ea1..cf8a2f5e4 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1958,7 +1958,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster) if (self->master != NULL) { - P_DamageMobj(self->master, self, self, self->master->health, damagetype, DMG_NO_ARMOR); + P_DamageMobj(self->master, self, self, self->master->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR); } } @@ -1979,7 +1979,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren) { if (mo->master == self) { - P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR); + P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR); } } } @@ -2001,7 +2001,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings) { if (mo->master == self->master && mo != self) { - P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR); + P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR); } } } From ba106c28c4f8ea7c888085a84123bda6467977be Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Dec 2009 22:22:25 +0000 Subject: [PATCH 130/241] - fixed: old-style DECORATE definitions with non-alphanumeric characters in the name produced an error. SVN r2025 (trunk) --- docs/rh-log.txt | 4 ++++ src/textures/warptexture.cpp | 2 +- src/thingdef/thingdef_parse.cpp | 3 --- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 19dc7f7d1..7a3c73ad1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 13, 2009 (Changes by Graf Zahl) +- fixed: old-style DECORATE definitions with non-alphanumeric characters in + the name produced an error. + December 12, 2009 - Added a DMG_NO_FACTOR flag for P_DamageMobj(). A_KillChildren, A_KillMaster, and A_KillSiblings now use it. diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index f87688ea1..360d1d38a 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -229,7 +229,7 @@ void FWarp2Texture::MakeTexture (DWORD time) FTexture *FWarpTexture::GetRedirect(bool wantwarped) { - if (!wantwarped) return SourcePic; + if (!wantwarped) return SourcePic->GetRedirect(false); else return this; } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index cc9b3284c..4aea677aa 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -1229,9 +1229,6 @@ void ParseDecorate (FScanner &sc) break; } default: - // without the option of game filters following, anything but an opening brace - // here means a syntax error. - sc.MustGetStringName("{"); sc.RestorePos(pos); ParseOldDecoration(sc, DEF_Decoration); break; From fdec06ff9b49a05ff6ceb1da927e298ccb8a9433 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Dec 2009 16:09:48 +0000 Subject: [PATCH 131/241] - fixed:P_DamageMobj just set an ice corpse's velocity to 0 to make it shatter. But that's insufficient because it doesn't factor in any subsequent velocity change that happens between the damaging and the next call to A_FreezeDeathChunks. - fixed: The TimeFreezer did not freeze other players' controls in a multiplayer game. - fixed: DECORATE's 'gravity' property incorrectly messed around with the NOGRAVITY flag. - fixed: Hitscan attacks didn't check the puff's replacement for damage types. SVN r2026 (trunk) --- docs/rh-log.txt | 10 ++++++++++ src/actor.h | 1 + src/c_console.cpp | 21 ++++++++++++++------- src/g_doom/a_doomweaps.cpp | 2 +- src/g_doom/a_scriptedmarine.cpp | 2 +- src/g_shared/a_action.cpp | 5 +++-- src/g_strife/a_strifeweapons.cpp | 2 +- src/g_strife/a_templar.cpp | 2 +- src/p_interaction.cpp | 1 + src/p_map.cpp | 13 ++++++++++--- src/p_mobj.cpp | 3 +++ src/p_user.cpp | 14 ++++++++++++-- src/thingdef/thingdef_codeptr.cpp | 8 ++++---- src/thingdef/thingdef_properties.cpp | 1 - 14 files changed, 62 insertions(+), 23 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 7a3c73ad1..5909da9aa 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,13 @@ +December 16, 2009 (Changes by Graf Zahl) +- fixed:P_DamageMobj just set an ice corpse's velocity to 0 to make it shatter. + But that's insufficient because it doesn't factor in any subsequent velocity + change that happens between the damaging and the next call to A_FreezeDeathChunks. +- fixed: The TimeFreezer did not freeze other players' controls in a + multiplayer game. +- fixed: DECORATE's 'gravity' property incorrectly messed around with the + NOGRAVITY flag. +- fixed: Hitscan attacks didn't check the puff's replacement for damage types. + December 13, 2009 (Changes by Graf Zahl) - fixed: old-style DECORATE definitions with non-alphanumeric characters in the name produced an error. diff --git a/src/actor.h b/src/actor.h index 8dbfdf194..b6dab786a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -317,6 +317,7 @@ enum MF6_FALLING = 0x00004000, // From MBF: Object is falling (for pseudotorque simulation) MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions + MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering // --- mobj.renderflags --- diff --git a/src/c_console.cpp b/src/c_console.cpp index 324fad660..aafc76f36 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -81,6 +81,7 @@ static bool C_TabCompleteList (); static bool TabbedLast; // True if last key pressed was tab static bool TabbedList; // True if tab list was shown CVAR (Bool, con_notablist, false, CVAR_ARCHIVE) +CVAR (Bool, con_ticker, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static FTextureID conback; static DWORD conshade; @@ -1104,17 +1105,23 @@ static void C_DrawNotifyText () void C_InitTicker (const char *label, unsigned int max, bool showpercent) { - TickerPercent = showpercent; - TickerMax = max; - TickerLabel = label; - TickerAt = 0; - maybedrawnow (true, false); + if (con_ticker) + { + TickerPercent = showpercent; + TickerMax = max; + TickerLabel = label; + TickerAt = 0; + maybedrawnow (true, false); + } } void C_SetTicker (unsigned int at, bool forceUpdate) { - TickerAt = at > TickerMax ? TickerMax : at; - maybedrawnow (true, TickerVisible ? forceUpdate : false); + if (con_ticker) + { + TickerAt = at > TickerMax ? TickerMax : at; + maybedrawnow (true, TickerVisible ? forceUpdate : false); + } } void C_DrawConsole (bool hw2d) diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 3cf59f16e..cfa5cdbae 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -133,7 +133,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) P_LineAttack (self, angle, MELEERANGE+1, P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage, - GetDefaultByType(pufftype)->DamageType, pufftype); + NAME_None, pufftype); if (!linetarget) { diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 763fd26b9..701a0930f 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -442,7 +442,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_FireShotgun2) P_LineAttack (self, angle, MISSILERANGE, pitch + (pr_m_fireshotgun2.Random2() * 332063), damage, - NAME_None, PClass::FindClass(NAME_BulletPuff)); + NAME_None, NAME_BulletPuff); } self->special1 = level.maptime; } diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 767d282b8..5dcdd0c28 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -233,18 +233,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks) int numChunks; AActor *mo; - if (self->velx || self->vely || self->velz) + if ((self->velx || self->vely || self->velz) && !(self->flags6 & MF6_SHATTERING)) { self->tics = 3*TICRATE; return; } + self->velx = self->vely = self->velz = 0; S_Sound (self, CHAN_BODY, "misc/icebreak", 1, ATTN_NORM); // [RH] In Hexen, this creates a random number of shards (range [24,56]) // with no relation to the size of the self shattering. I think it should // base the number of shards on the size of the dead thing, so bigger // things break up into more shards than smaller things. - // An self with radius 20 and height 64 creates ~40 chunks. + // An actor with radius 20 and height 64 creates ~40 chunks. numChunks = MAX (4, (self->radius>>FRACBITS)*(self->height>>FRACBITS)/32); i = (pr_freeze.Random2()) % (numChunks/4); for (i = MAX (24, numChunks + i); i >= 0; i--) diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 6c53fa247..97526bf67 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -429,7 +429,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler1) // it should use a different puff. ZDoom's default range is longer // than this, so let's not handicap it by being too faithful to the // original. - P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Disintegrate, NAME_MaulerPuff); + P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_None, NAME_MaulerPuff); } } diff --git a/src/g_strife/a_templar.cpp b/src/g_strife/a_templar.cpp index afdac2e15..a6a733a00 100644 --- a/src/g_strife/a_templar.cpp +++ b/src/g_strife/a_templar.cpp @@ -30,6 +30,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_TemplarAttack) damage = (pr_templar() & 4) * 2; angle = self->angle + (pr_templar.Random2() << 19); pitchdiff = pr_templar.Random2() * 332063; - P_LineAttack (self, angle, MISSILERANGE+64*FRACUNIT, pitch+pitchdiff, damage, NAME_Disintegrate, NAME_MaulerPuff); + P_LineAttack (self, angle, MISSILERANGE+64*FRACUNIT, pitch+pitchdiff, damage, NAME_None, NAME_MaulerPuff); } } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 003e0077e..3b1521f8c 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -906,6 +906,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage else if (target->flags & MF_ICECORPSE) // frozen { target->tics = 1; + target->flags6 |= MF6_SHATTERING; target->velx = target->vely = target->velz = 0; } return; diff --git a/src/p_map.cpp b/src/p_map.cpp index e401e84fb..dc056972f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3325,9 +3325,16 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, t1->player->ReadyWeapon != NULL && (t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)); - // Need to check defaults of replacement here + // We need to check the defaults of the replacement here AActor *puffDefaults = GetDefaultByType(pufftype->ActorInfo->GetReplacement()->Class); + // if the puff uses a non-standard damage type this will override default and melee damage type. + // All other explicitly passed damage types (currenty only MDK) will be preserved. + if ((damageType == NAME_None || damageType == NAME_Melee) && puffDefaults->DamageType != NAME_None) + { + damageType = puffDefaults->DamageType; + } + int tflags; if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) tflags = TRACE_NoSky; else tflags = TRACE_NoSky|TRACE_Impact; @@ -3417,14 +3424,14 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, hitz = shootz + FixedMul (vz, trace.Distance); // Spawn bullet puffs or blood spots, depending on target type. - AActor *puffDefaults = GetDefaultByType (pufftype); if ((puffDefaults->flags3 & MF3_PUFFONACTORS) || (trace.Actor->flags & MF_NOBLOOD) || (trace.Actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT))) { + // We must pass the unreplaced puff type here puff = P_SpawnPuff (t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING); } - if (!(GetDefaultByType(pufftype)->flags3&MF3_BLOODLESSIMPACT)) + if (!(puffDefaults->flags3&MF3_BLOODLESSIMPACT)) { if (!bloodsplatter && !axeBlood && !(trace.Actor->flags & MF_NOBLOOD) && diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5705fb77b..b275539b6 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3486,6 +3486,9 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t actor->picnum.SetInvalid(); actor->health = actor->SpawnHealth(); + // Actors with zero gravity need the NOGRAVITY flag set. + if (actor->gravity == 0) actor->flags |= MF_NOGRAVITY; + FRandom &rng = bglobal.m_Thinking ? pr_botspawnmobj : pr_spawnmobj; if (actor->isFast() && actor->flags3 & MF3_ISMONSTER) diff --git a/src/p_user.cpp b/src/p_user.cpp index 374442a18..82914b1f6 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -614,6 +614,12 @@ bool APlayerPawn::UseInventory (AInventory *item) { // You can't use items if you're totally frozen return false; } + if (( level.flags2 & LEVEL2_FROZEN ) && ( player == NULL || !( player->cheats & CF_TIMEFREEZE ))) + { + // Time frozen + return false; + } + if (!Super::UseInventory (item)) { // Heretic and Hexen advance the inventory cursor if the use failed. @@ -2053,8 +2059,12 @@ void P_PlayerThink (player_t *player) player->mo->flags &= ~MF_JUSTATTACKED; } + bool totallyfrozen = (player->cheats & CF_TOTALLYFROZEN || gamestate == GS_TITLELEVEL || + (( level.flags2 & LEVEL2_FROZEN ) && ( player == NULL || !( player->cheats & CF_TIMEFREEZE ))) + ); + // [RH] Being totally frozen zeros out most input parameters. - if (player->cheats & CF_TOTALLYFROZEN || gamestate == GS_TITLELEVEL) + if (totallyfrozen) { if (gamestate == GS_TITLELEVEL) { @@ -2086,7 +2096,7 @@ void P_PlayerThink (player_t *player) } if (player->morphTics == 0 && player->health > 0 && level.IsCrouchingAllowed()) { - if (!(player->cheats & CF_TOTALLYFROZEN)) + if (!totallyfrozen) { int crouchdir = player->crouching; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index cf8a2f5e4..1c00e7ae5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -834,7 +834,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomBulletAttack) int angle = bangle + pr_cabullet.Random2() * (Spread_XY / 255); int slope = bslope + pr_cabullet.Random2() * (Spread_Z / 255); int damage = ((pr_cabullet()%3)+1) * DamagePerBullet; - P_LineAttack(self, angle, Range, slope, damage, GetDefaultByType(pufftype)->DamageType, pufftype); + P_LineAttack(self, angle, Range, slope, damage, NAME_None, pufftype); } } } @@ -986,7 +986,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) if ((NumberOfBullets==1 && !player->refire) || NumberOfBullets==0) { int damage = ((pr_cwbullet()%3)+1)*DamagePerBullet; - P_LineAttack(self, bangle, Range, bslope, damage, GetDefaultByType(PuffType)->DamageType, PuffType); + P_LineAttack(self, bangle, Range, bslope, damage, NAME_None, PuffType); } else { @@ -996,7 +996,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireBullets) int angle = bangle + pr_cwbullet.Random2() * (Spread_XY / 255); int slope = bslope + pr_cwbullet.Random2() * (Spread_Z / 255); int damage = ((pr_cwbullet()%3)+1) * DamagePerBullet; - P_LineAttack(self, angle, Range, slope, damage, GetDefaultByType(PuffType)->DamageType, PuffType); + P_LineAttack(self, angle, Range, slope, damage, NAME_None, PuffType); } } } @@ -1104,7 +1104,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) if (!PuffType) PuffType = PClass::FindClass(NAME_BulletPuff); - P_LineAttack (self, angle, Range, pitch, Damage, GetDefaultByType(PuffType)->DamageType, PuffType, true); + P_LineAttack (self, angle, Range, pitch, Damage, NAME_None, PuffType, true); // turn to face target if (linetarget) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 6226bd0df..6d9419f97 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1026,7 +1026,6 @@ DEFINE_PROPERTY(gravity, F, Actor) if (i < 0) I_Error ("Gravity must not be negative."); defaults->gravity = i; - if (i == 0) defaults->flags |= MF_NOGRAVITY; } //========================================================================== From 1c5103c9b1aa82f9964f5dd29e8ca27133409a76 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Dec 2009 22:42:15 +0000 Subject: [PATCH 132/241] - Fixed: Morphed players tried endlessly to switch to a weapon they picked up. SVN r2027 (trunk) --- docs/rh-log.txt | 3 ++- src/p_pspr.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5909da9aa..c3c5da73d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,5 +1,6 @@ December 16, 2009 (Changes by Graf Zahl) -- fixed:P_DamageMobj just set an ice corpse's velocity to 0 to make it shatter. +- Fixed: Morphed players tried endlessly to switch to a weapon they picked up. +- fixed: P_DamageMobj just set an ice corpse's velocity to 0 to make it shatter. But that's insufficient because it doesn't factor in any subsequent velocity change that happens between the damaging and the next call to A_FreezeDeathChunks. - fixed: The TimeFreezer did not freeze other players' controls in a diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 0b464aab2..e8751c1f0 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -505,6 +505,11 @@ void P_CheckWeaponSwitch (player_t *player) P_SetPsprite (player, ps_weapon, weapon->GetDownState()); return; } + else if (player->morphTics != 0) + { + // morphed classes cannot change weapons so don't even try again. + player->PendingWeapon = WP_NOCHANGE; + } } //--------------------------------------------------------------------------- From f6428e1cbb2934027f3fab5f3279ac2806f68671 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 18 Dec 2009 03:05:38 +0000 Subject: [PATCH 133/241] - Replaced sprite sorting with a stable sort. Performance at the start of nuts.wad seems the same. SVN r2028 (trunk) --- docs/rh-log.txt | 4 ++++ src/r_things.cpp | 13 +++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c3c5da73d..6b6bac33a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 17, 2009 +- Replaced sprite sorting with a stable sort. Performance at the start of + nuts.wad seems the same. + December 16, 2009 (Changes by Graf Zahl) - Fixed: Morphed players tried endlessly to switch to a weapon they picked up. - fixed: P_DamageMobj just set an ice corpse's velocity to 0 to make it shatter. diff --git a/src/r_things.cpp b/src/r_things.cpp index 155c84353..869d73a6a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "templates.h" #include "doomdef.h" @@ -1883,13 +1884,9 @@ void R_DrawRemainingPlayerSprites() // gain compared to the old function. // // Sort vissprites by depth, far to near -static int STACK_ARGS sv_compare (const void *arg1, const void *arg2) +static bool sv_compare(vissprite_t *a, vissprite_t *b) { - int diff = (*(vissprite_t **)arg2)->idepth - (*(vissprite_t **)arg1)->idepth; - // If two sprites are the same distance, then the higher one gets precedence - if (diff == 0) - return (*(vissprite_t **)arg2)->gzt - (*(vissprite_t **)arg1)->gzt; - return diff; + return a->idepth > b->idepth; } #if 0 @@ -2023,7 +2020,7 @@ void R_SplitVisSprites () } #endif -void R_SortVisSprites (int (STACK_ARGS *compare)(const void *, const void *), size_t first) +void R_SortVisSprites (bool (*compare)(vissprite_t *, vissprite_t *), size_t first) { int i; vissprite_t **spr; @@ -2046,7 +2043,7 @@ void R_SortVisSprites (int (STACK_ARGS *compare)(const void *, const void *), si spritesorter[i] = *spr; } - qsort (spritesorter, vsprcount, sizeof (vissprite_t *), compare); + std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare); } From 0e3c1dc33e609f4ab194375cde77dafefa5d30b1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 18 Dec 2009 04:58:20 +0000 Subject: [PATCH 134/241] - Add a swap overload to make GCC happy. SVN r2029 (trunk) --- src/r_things.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index 869d73a6a..a3a466b4e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2020,6 +2020,15 @@ void R_SplitVisSprites () } #endif +#ifdef __GNUC__ +static void swap(vissprite_t *&a, vissprite_t *&b) +{ + vissprite_t *t = a; + a = b; + b = t; +} +#endif + void R_SortVisSprites (bool (*compare)(vissprite_t *, vissprite_t *), size_t first) { int i; From 0a4d860ec7409f38763ef180cb1b4da87a2d49d4 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 18 Dec 2009 05:38:14 +0000 Subject: [PATCH 135/241] - Fixed: Using Transfer_Heights with the SECF_UNDERWATER and SECF_FAKEFLOORONLY flags applied the water effect to the ceiling and not just the floor. SVN r2030 (trunk) --- docs/rh-log.txt | 3 +++ src/p_mobj.cpp | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6b6bac33a..5bf1fe581 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ December 17, 2009 +- Fixed: Using Transfer_Heights with the SECF_UNDERWATER and + SECF_FAKEFLOORONLY flags applied the water effect to the ceiling and not + just the floor. - Replaced sprite sorting with a stable sort. Performance at the start of nuts.wad seems the same. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b275539b6..0d3ab7ac2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3358,7 +3358,7 @@ void AActor::Tick () bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash) { BYTE lastwaterlevel = waterlevel; - fixed_t fh=FIXED_MIN; + fixed_t fh = FIXED_MIN; bool reset=false; waterlevel = 0; @@ -3393,18 +3393,21 @@ bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash) } } } - else if (z + height > hsec->ceilingplane.ZatPoint (x, y)) + else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (z + height > hsec->ceilingplane.ZatPoint (x, y))) { waterlevel = 3; } else { - waterlevel=0; + waterlevel = 0; } } // even non-swimmable deep water must be checked here to do the splashes correctly // But the water level must be reset when this function returns - if (!(hsec->MoreFlags&SECF_UNDERWATERMASK)) reset=true; + if (!(hsec->MoreFlags&SECF_UNDERWATERMASK)) + { + reset = true; + } } #ifdef _3DFLOORS else @@ -3449,8 +3452,11 @@ bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash) { P_HitWater(this, Sector, FIXED_MIN, FIXED_MIN, fh, true); } - boomwaterlevel=waterlevel; - if (reset) waterlevel=lastwaterlevel; + boomwaterlevel = waterlevel; + if (reset) + { + waterlevel = lastwaterlevel; + } return false; // we did the splash ourselves } From 51e158d7dcdfad86cf75bdb3b7e316a6a9f36f32 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Dec 2009 08:19:34 +0000 Subject: [PATCH 136/241] - added all known maps requiring inverted sprite sorting to compatibility.txt. - added compatibility option to invert sprite sorting. Apparently Doom.exe originally sorted them differently than most source port and on some maps which depends on this it doesn't look right (e.g. Strain MAP13) SVN r2031 (trunk) --- docs/rh-log.txt | 6 ++++++ src/compatibility.cpp | 1 + src/d_main.cpp | 5 +++-- src/doomdef.h | 1 + src/g_mapinfo.cpp | 1 + src/m_options.cpp | 1 + src/r_things.cpp | 17 +++++++++++++++-- wadsrc/static/compatibility.txt | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5bf1fe581..f778dc3e4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +December 18, 2009 (Changes by Graf Zahl) +- added all known maps requiring inverted sprite sorting to compatibility.txt. +- added compatibility option to invert sprite sorting. Apparently Doom.exe + originally sorted them differently than most source port and on some maps + which depends on this it doesn't look right (e.g. Strain MAP13) + December 17, 2009 - Fixed: Using Transfer_Heights with the SECF_UNDERWATER and SECF_FAKEFLOORONLY flags applied the water effect to the ceiling and not diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 059a8a4b7..f4fbaa529 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -105,6 +105,7 @@ static FCompatOption Options[] = { "mbfmonstermove", COMPATF_MBFMONSTERMOVE, 0 }, { "corpsegibs", COMPATF_CORPSEGIBS, 0 }, { "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 }, + { "spritesort", COMPATF_SPRITESORT, 0 }, { NULL, 0, 0 } }; diff --git a/src/d_main.cpp b/src/d_main.cpp index 0aa0b1baf..656875941 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -492,12 +492,12 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) break; case 1: // Doom2.exe compatible with a few relaxed settings - v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT| + v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT| COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF; break; case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set) - v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT| + v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT| COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN| COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS; break; @@ -546,6 +546,7 @@ CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM); CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE); CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS); CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS); +CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT); //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index 868479faa..485f15a5e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -324,6 +324,7 @@ enum COMPATF_MBFMONSTERMOVE = 1 << 24, // Monsters are affected by friction and pushers/pullers. COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs. COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines. + COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance }; // Emulate old bugs for select maps. These are not exposed by a cvar diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index eeb222361..800fa8957 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1359,6 +1359,7 @@ MapFlagHandlers[] = { "compat_mbfmonstermove", MITYPE_COMPATFLAG, COMPATF_MBFMONSTERMOVE}, { "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS}, { "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS}, + { "compat_spritesort", MITYPE_COMPATFLAG, COMPATF_SPRITESORT}, { "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, diff --git a/src/m_options.cpp b/src/m_options.cpp index ac297a2f2..313d0d602 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -1112,6 +1112,7 @@ static menuitem_t CompatibilityItems[] = { { bitflag, "Monster movement is affected by effects", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MBFMONSTERMOVE} }, { bitflag, "Crushed monsters can be resurrected", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CORPSEGIBS} }, { bitflag, "Friendly monsters aren't blocked", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOBLOCKFRIENDS} }, + { bitflag, "Invert sprite sorting", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SPRITESORT} }, { discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} }, }; diff --git a/src/r_things.cpp b/src/r_things.cpp index a3a466b4e..a2f18de5f 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2047,9 +2047,22 @@ void R_SortVisSprites (bool (*compare)(vissprite_t *, vissprite_t *), size_t fir spritesortersize = MaxVisSprites; } - for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++) + if (!(i_compatflags & COMPATF_SPRITESORT)) { - spritesorter[i] = *spr; + for (i = 0, spr = firstvissprite; i < vsprcount; i++, spr++) + { + spritesorter[i] = *spr; + } + } + else + { + // If the compatibility option is on sprites of equal distance need to + // be sorted in inverse order. This is most easily achieved by + // filling the sort array backwards before the sort. + for (i = 0, spr = firstvissprite + vsprcount-1; i < vsprcount; i++, spr--) + { + spritesorter[i] = *spr; + } } std::stable_sort(&spritesorter[0], &spritesorter[vsprcount], compare); diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index b2a168ce7..a4fd90659 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -91,3 +91,35 @@ F84AB4557464A383E93F37CD3A82AC48 // MM2 map03 corpsegibs vileghosts } + +// invert the sorting order of overlapping sprites at the same spot +551D6B416EB3324790BC0F0F74B49600 // Strain map13 +2F49C29691F8565F0B99B27FCF2627E6 // Astrostein 1 MAP01 +55A741F9C2955C2B06F2387E45ED6C62 // MAP02 +4E7286B735671A942C54FAC6CB52A8C3 // MAP03 +825772094FF3569FC3722145F82F820A // MAP04 +CB6CF6BE0EA4A6AB9830FBB7F9192B80 // MAP05 +AB24CCF84C2FE1A543FE033589BD1FBC // MAP06 +6BE0908B4DAFF53AA0A7493C04A608A4 // MAP07 +305275E5E07755E17AAB064981279295 // MAP08 +A8FBF3600088E79D02283C40D12B7F26 // MAP09 +A8FBF3600088E79D02283C40D12B7F26 // MAP09 +F0C95C76237DF617560577767EC21E1C // MAP10 +2A2AF2CDAB7E7A66D28AFC3AA6243DCC // Astrostein 2 map01 +0667DA831EB293D3387579565C11F0DD // map02 +76DA72420EBE0A53D861373D7123DE33 // map03 +5A4F8186580FFE41BCD80960B7F19CA8 // map04 +E3A1EE2A0A2FB27496074057E3FA82F0 // map05 +1CA60DE4062F41DC1A39396228913882 // map06 +DABC3033A734DEF402A8FEF6C2FEDCC2 // map07 +2E8211EA051EA8C3241859D1854386D6 // map08 +EAD27C506AFC856BE07DDDDED20D7ED0 // map09 +7DA47B044E2D5D17EAE2960BBFAEDE1A // Astrostein 3 map10 +46E0F4529E8E396DEDC8DB83443078A7 // map13 +2742D556921FBE753C16175F0C980091 // map14 +AB1A6C1D3898D4259C0645306939374C // map15 +0599F0D0CC1F41F52B7E8214D0348EEA // map17 +CA267398C9B3A8F79349D3394F8B2106 // map20 +{ + spritesort +} From d8a2387c39eb0b6af3ee1bd36a143fb5a0576f15 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 19 Dec 2009 04:54:04 +0000 Subject: [PATCH 137/241] - A_FreezeDeath() now removes fuzz effects. - In mus2midi.cpp, added range checking to MUS_SYSEVENT and MUS_CTRLCHANGE, and masking for note-off keys, note-on velocities, and program changes. SVN r2032 (trunk) --- docs/rh-log.txt | 5 +++++ src/g_shared/a_action.cpp | 8 ++++++- src/mus2midi.cpp | 45 ++++++++++++++++++++++++++++----------- src/mus2midi.h | 1 + 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f778dc3e4..ed7666230 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +December 18, 2009 +- A_FreezeDeath() now removes fuzz effects. +- In mus2midi.cpp, added range checking to MUS_SYSEVENT and MUS_CTRLCHANGE, + and masking for note-off keys, note-on velocities, and program changes. + December 18, 2009 (Changes by Graf Zahl) - added all known maps requiring inverted sprite sorting to compatibility.txt. - added compatibility option to invert sprite sorting. Apparently Doom.exe diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 5dcdd0c28..571b7bf1f 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -163,6 +163,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) self->flags2 |= MF2_PUSHABLE|MF2_TELESTOMP|MF2_PASSMOBJ|MF2_SLIDE; self->flags3 |= MF3_CRASHED; self->height = self->GetDefault()->height; + // Remove fuzz effects from frozen actors. + if (self->RenderStyle.BlendOp >= STYLEOP_Fuzz && self->RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub) + { + self->RenderStyle = STYLE_Normal; + } + S_Sound (self, CHAN_BODY, "misc/freeze", 1, ATTN_NORM); // [RH] Andy Baker's stealth monsters @@ -178,7 +184,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeath) self->player->poisoncount = 0; self->player->bonuscount = 0; } - else if (self->flags3&MF3_ISMONSTER && self->special) + else if (self->flags3 & MF3_ISMONSTER && self->special) { // Initiate monster death actions LineSpecials [self->special] (NULL, self, false, self->args[0], self->args[1], self->args[2], self->args[3], self->args[4]); diff --git a/src/mus2midi.cpp b/src/mus2midi.cpp index 9dafcaabf..beef4ffa4 100644 --- a/src/mus2midi.cpp +++ b/src/mus2midi.cpp @@ -121,7 +121,8 @@ bool ProduceMIDI (const BYTE *musBuf, TArray &outFile) BYTE chanUsed[16]; BYTE lastVel[16]; long trackLen; - + bool no_op; + // Do some validation of the MUS file if (MUSMagic != musHead->Magic) return false; @@ -178,12 +179,13 @@ bool ProduceMIDI (const BYTE *musBuf, TArray &outFile) midStatus = channel; midArgs = 0; // Most events have two args (0 means 2, 1 means 1) - + no_op = false; + switch (event & 0x70) { case MUS_NOTEOFF: midStatus |= MIDI_NOTEOFF; - mid1 = t; + mid1 = t & 127; mid2 = 64; break; @@ -192,7 +194,7 @@ bool ProduceMIDI (const BYTE *musBuf, TArray &outFile) mid1 = t & 127; if (t & 128) { - lastVel[channel] = musBuf[mus_p++];; + lastVel[channel] = musBuf[mus_p++] & 127; } mid2 = lastVel[channel]; break; @@ -204,9 +206,16 @@ bool ProduceMIDI (const BYTE *musBuf, TArray &outFile) break; case MUS_SYSEVENT: - midStatus |= MIDI_CTRLCHANGE; - mid1 = CtrlTranslate[t]; - mid2 = t == 12 ? LittleShort(musHead->NumChans) : 0; + if (t < 10 || t > 14) + { + no_op = true; + } + else + { + midStatus |= MIDI_CTRLCHANGE; + mid1 = CtrlTranslate[t]; + mid2 = t == 12 /* Mono */ ? LittleShort(musHead->NumChans) : 0; + } break; case MUS_CTRLCHANGE: @@ -214,27 +223,39 @@ bool ProduceMIDI (const BYTE *musBuf, TArray &outFile) { // program change midArgs = 1; midStatus |= MIDI_PRGMCHANGE; - mid1 = musBuf[mus_p++]; + mid1 = musBuf[mus_p++] & 127; mid2 = 0; // Assign mid2 just to make GCC happy } - else + else if (t > 0 && t < 10) { midStatus |= MIDI_CTRLCHANGE; mid1 = CtrlTranslate[t]; mid2 = musBuf[mus_p++]; } + else + { + no_op = true; + } break; case MUS_SCOREEND: - midStatus = 0xff; - mid1 = 0x2f; - mid2 = 0x00; + midStatus = MIDI_META; + mid1 = MIDI_META_EOT; + mid2 = 0; break; default: return false; } + if (no_op) + { + // A system-specific event with no data is a no-op. + midStatus = MIDI_META; + mid1 = MIDI_META_SSPEC; + mid2 = 0; + } + WriteVarLen (outFile, deltaTime); if (midStatus != status) diff --git a/src/mus2midi.h b/src/mus2midi.h index 79b410078..6780bdf47 100644 --- a/src/mus2midi.h +++ b/src/mus2midi.h @@ -46,6 +46,7 @@ #define MIDI_META ((BYTE)0xFF) // Meta event begin #define MIDI_META_TEMPO ((BYTE)0x51) #define MIDI_META_EOT ((BYTE)0x2F) // End-of-track +#define MIDI_META_SSPEC ((BYTE)0x7F) // System-specific event #define MIDI_NOTEOFF ((BYTE)0x80) // + note + velocity #define MIDI_NOTEON ((BYTE)0x90) // + note + velocity From bdd1203aca48a35bf43cf3be578ed5f31f7e9205 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Dec 2009 07:44:04 +0000 Subject: [PATCH 138/241] - Fixed: It was not possible to set the ammo type of a weapon explicitly to 'none'. SVN r2033 (trunk) --- docs/rh-log.txt | 4 ++++ src/thingdef/thingdef_properties.cpp | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ed7666230..0897f3eb9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 19, 2009 (Changes by Graf Zahl) +- Fixed: It was not possible to set the ammo type of a weapon explicitly to + 'none'. + December 18, 2009 - A_FreezeDeath() now removes fuzz effects. - In mus2midi.cpp, added range checking to MUS_SYSEVENT and MUS_CTRLCHANGE, diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 6d9419f97..ea8407cc0 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1421,7 +1421,8 @@ DEFINE_CLASS_PROPERTY(ammogive2, I, Weapon) DEFINE_CLASS_PROPERTY(ammotype, S, Weapon) { PROP_STRING_PARM(str, 0); - defaults->AmmoType1 = FindClassTentative(str, "Ammo"); + if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; + else defaults->AmmoType1 = FindClassTentative(str, "Ammo"); } //========================================================================== @@ -1430,7 +1431,8 @@ DEFINE_CLASS_PROPERTY(ammotype, S, Weapon) DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon) { PROP_STRING_PARM(str, 0); - defaults->AmmoType1 = FindClassTentative(str, "Ammo"); + if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; + else defaults->AmmoType1 = FindClassTentative(str, "Ammo"); } //========================================================================== @@ -1439,7 +1441,8 @@ DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon) DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon) { PROP_STRING_PARM(str, 0); - defaults->AmmoType2 = FindClassTentative(str, "Ammo"); + if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; + else defaults->AmmoType2 = FindClassTentative(str, "Ammo"); } //========================================================================== From 00447b8f444757f4b55eed57cf462c7493b11228 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 20 Dec 2009 05:11:30 +0000 Subject: [PATCH 139/241] - Extended MF3_SKYEXPLODE to apply to horizon walls as well. SVN r2034 (trunk) --- docs/rh-log.txt | 3 +++ src/p_mobj.cpp | 34 ++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0897f3eb9..11bdf92bf 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +December 19, 2009 +- Extended MF3_SKYEXPLODE to apply to horizon walls as well. + December 19, 2009 (Changes by Graf Zahl) - Fixed: It was not possible to set the ammo type of a weapon explicitly to 'none'. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 0d3ab7ac2..868941d01 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1190,7 +1190,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) return; } - if (line != NULL && line->special == Line_Horizon) + if (line != NULL && line->special == Line_Horizon && !(mo->flags3 & MF3_SKYEXPLODE)) { // [RH] Don't explode missiles on horizon lines. mo->Destroy (); @@ -1901,22 +1901,24 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly) } explode: // explode a missile - if (tm.ceilingline && - tm.ceilingline->backsector && - tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum && - mo->z >= tm.ceilingline->backsector->ceilingplane.ZatPoint (mo->x, mo->y) && //killough - !(mo->flags3 & MF3_SKYEXPLODE)) + if (!(mo->flags3 & MF3_SKYEXPLODE)) { - // Hack to prevent missiles exploding against the sky. - // Does not handle sky floors. - mo->Destroy (); - return oldfloorz; - } - // [RH] Don't explode on horizon lines. - if (mo->BlockingLine != NULL && mo->BlockingLine->special == Line_Horizon) - { - mo->Destroy (); - return oldfloorz; + if (tm.ceilingline && + tm.ceilingline->backsector && + tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum && + mo->z >= tm.ceilingline->backsector->ceilingplane.ZatPoint (mo->x, mo->y)) + { + // Hack to prevent missiles exploding against the sky. + // Does not handle sky floors. + mo->Destroy (); + return oldfloorz; + } + // [RH] Don't explode on horizon lines. + if (mo->BlockingLine != NULL && mo->BlockingLine->special == Line_Horizon) + { + mo->Destroy (); + return oldfloorz; + } } P_ExplodeMissile (mo, mo->BlockingLine, BlockingMobj); return oldfloorz; From cc3b7967a1c5bc3a1b1cacda7204844d2baa8757 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Dec 2009 19:14:10 +0000 Subject: [PATCH 140/241] - Fixed: The Dehacked parser could read past the end of the file if the last element was improperly defined. SVN r2035 (trunk) --- docs/rh-log.txt | 4 ++++ src/d_dehacked.cpp | 23 +++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 11bdf92bf..4f241608b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 20, 2009 (Changes by Graf Zahl) +- Fixed: The Dehacked parser could read past the end of the file if the last + element was improperly defined. + December 19, 2009 - Extended MF3_SKYEXPLODE to apply to horizon walls as well. diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 29b0e22bb..a8a154512 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -252,6 +252,7 @@ DehSpriteMappings[] = #define CHECKKEY(a,b) if (!stricmp (Line1, (a))) (b) = atoi(Line2); static char *PatchFile, *PatchPt, *PatchName; +static int PatchSize; static char *Line1, *Line2; static int dversion, pversion; static bool including, includenotext; @@ -427,7 +428,7 @@ static bool ReadChars (char **stuff, int size) size++; PatchPt++; - } while (--size); + } while (--size && *PatchPt != 0); *str = 0; return true; @@ -524,7 +525,7 @@ static char *igets (void) { char *line; - if (*PatchPt == '\0') + if (*PatchPt == '\0' || PatchPt >= PatchFile + PatchSize ) return NULL; line = PatchPt; @@ -2205,7 +2206,7 @@ static int DoInclude (int dummy) { char *data; int savedversion, savepversion; - char *savepatchfile, *savepatchpt, *savepatchname; + char *savepatchfile, *savepatchpt, *savepatchname, savepatchsize; if (including) { @@ -2239,6 +2240,7 @@ static int DoInclude (int dummy) savepatchname = PatchName; savepatchfile = PatchFile; savepatchpt = PatchPt; + savepatchsize = PatchSize; savedversion = dversion; savepversion = pversion; including = true; @@ -2272,6 +2274,7 @@ static int DoInclude (int dummy) PatchName = savepatchname; PatchFile = savepatchfile; PatchPt = savepatchpt; + PatchSize = savepatchsize; dversion = savedversion; pversion = savepversion; } @@ -2294,12 +2297,12 @@ int D_LoadDehLumps() bool D_LoadDehLump(int lumpnum) { - int filelen = Wads.LumpLength(lumpnum); + PatchSize = Wads.LumpLength(lumpnum); PatchName = copystring(Wads.GetLumpFullPath(lumpnum)); - PatchFile = new char[filelen + 1]; + PatchFile = new char[PatchSize + 1]; Wads.ReadLump(lumpnum, PatchFile); - PatchFile[filelen] = '\0'; // terminate with a '\0' character + PatchFile[PatchSize] = '\0'; // terminate with a '\0' character return DoDehPatch(); } @@ -2310,13 +2313,13 @@ bool D_LoadDehFile(const char *patchfile) deh = fopen(patchfile, "rb"); if (deh != NULL) { - int filelen = Q_filelength(deh); + PatchSize = Q_filelength(deh); PatchName = copystring(patchfile); - PatchFile = new char[filelen + 1]; - fread(PatchFile, 1, filelen, deh); + PatchFile = new char[PatchSize + 1]; + fread(PatchFile, 1, PatchSize, deh); fclose(deh); - PatchFile[filelen] = '\0'; // terminate with a '\0' character + PatchFile[PatchSize] = '\0'; // terminate with a '\0' character return DoDehPatch(); } else From b0b80f6996134904a44ac170631ce2b20c166e3d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Dec 2009 11:41:24 +0000 Subject: [PATCH 141/241] - made the initial weave index for A_BishopMissileWeave and A_CStaffMissileSlither a configurable actor property. - added a menu item for snd_channels. SVN r2036 (trunk) --- docs/rh-log.txt | 5 +++++ src/actor.h | 1 + src/g_hexen/a_bishop.cpp | 11 ++++++----- src/g_hexen/a_clericstaff.cpp | 11 +++++++---- src/m_options.cpp | 2 ++ src/p_mobj.cpp | 8 ++++++++ src/thingdef/thingdef_properties.cpp | 9 +++++++++ wadsrc/static/actors/actor.txt | 1 + 8 files changed, 39 insertions(+), 9 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4f241608b..08d1f117b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +December 23, 2009 (Changes by Graf Zahl) +- made the initial weave index for A_BishopMissileWeave and A_CStaffMissileSlither + a configurable actor property. +- added a menu item for snd_channels. + December 20, 2009 (Changes by Graf Zahl) - Fixed: The Dehacked parser could read past the end of the file if the last element was improperly defined. diff --git a/src/actor.h b/src/actor.h index b6dab786a..a7f06281a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -764,6 +764,7 @@ public: DWORD flags6; // Shit! Where did all the flags go? int special1; // Special info int special2; // Special info + int weaveindex; // Separated from special2 because it's used by globally accessible functions. int health; BYTE movedir; // 0-7 SBYTE visdir; diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp index 1e4109748..df998a8ab 100644 --- a/src/g_hexen/a_bishop.cpp +++ b/src/g_hexen/a_bishop.cpp @@ -60,7 +60,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2) if (mo != NULL) { mo->tracer = self->target; - mo->special2 = 16; // High word == x/y, Low word == z } self->special1--; } @@ -77,10 +76,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) int weaveXY, weaveZ; int angle; - if (self->special2 == 0) self->special2 = 16; + // for compatibility this needs to set the value itself if it was never done by the projectile itself + if (self->weaveindex == -1) self->weaveindex = 16; - weaveXY = self->special2 >> 16; - weaveZ = self->special2 & 0xFFFF; + // since these values are now user configurable we have to do a proper range check to avoid array overflows. + weaveXY = (self->weaveindex >> 16) & 63; + weaveZ = (self->weaveindex & 63); angle = (self->angle + ANG90) >> ANGLETOFINESHIFT; newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); @@ -91,7 +92,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) self->z -= FloatBobOffsets[weaveZ]; weaveZ = (weaveZ + 2) & 63; self->z += FloatBobOffsets[weaveZ]; - self->special2 = weaveZ + (weaveXY<<16); + self->weaveindex = weaveZ + (weaveXY<<16); } //============================================================================ diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index 38018071c..b2a50487c 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -135,12 +135,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle-(ANG45/15)); if (mo) { - mo->special2 = 32; + mo->weaveindex = 32; } mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle+(ANG45/15)); if (mo) { - mo->special2 = 0; + mo->weaveindex = 0; } S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM); } @@ -157,7 +157,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) int weaveXY; int angle; - weaveXY = self->special2; + if (self->weaveindex == -1) self->weaveindex = 0; + + // since these values are now user configurable we have to do a proper range check to avoid array overflows. + weaveXY = self->weaveindex & 63; angle = (self->angle+ANG90)>>ANGLETOFINESHIFT; newX = self->x-FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); newY = self->y-FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); @@ -165,7 +168,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); P_TryMove (self, newX, newY, true); - self->special2 = weaveXY; + self->weaveindex = weaveXY; } //============================================================================ diff --git a/src/m_options.cpp b/src/m_options.cpp index 313d0d602..e8ffa85c3 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -94,6 +94,7 @@ EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Int, compatmode) EXTERN_CVAR (Bool, vid_vsync) EXTERN_CVAR(Bool, displaynametags) +EXTERN_CVAR (Int, snd_channels) // // defaulted values @@ -1252,6 +1253,7 @@ static menuitem_t SoundItems[] = { discrete, "Underwater reverb", {&snd_waterreverb}, {2.0}, {0.0}, {0.0}, {OnOff} }, { slider, "Underwater cutoff", {&snd_waterlp}, {0.0}, {2000.0},{50.0}, {NULL} }, { discrete, "Randomize pitches", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} }, + { slider, "Sound channels", {&snd_channels}, {8.0}, {256.0}, {8.0}, {NULL} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { more, "Restart sound", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 868941d01..c0f8af6e8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -312,6 +312,14 @@ void AActor::Serialize (FArchive &arc) { arc << DamageFactor; } + if (SaveVersion >= 2036) + { + arc << weaveindex; + } + else + { + weaveindex = special2; + } // Skip past uservar array in old savegames if (SaveVersion < 1933) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index ea8407cc0..e8b170880 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -902,6 +902,15 @@ DEFINE_PROPERTY(bouncecount, I, Actor) defaults->bouncecount = id; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(weaveindex, I, Actor) +{ + PROP_INT_PARM(id, 0); + defaults->weaveindex = id; +} + //========================================================================== // //========================================================================== diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 117a29ac8..71c0790db 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -19,6 +19,7 @@ ACTOR Actor native //: Thinker Gravity 1 DamageFactor 1.0 PushFactor 0.25 + WeaveIndex -1 // Variables for the expression evaluator // NOTE: fixed_t and angle_t are only used here to ensure proper conversion From 611834ea2a54c99a3a02e5d144f75d6766a5facc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 24 Dec 2009 23:31:06 +0000 Subject: [PATCH 142/241] - fixed: The UDMF blockfloaters flag was misnamed. Changed to match the spec. SVN r2037 (trunk) --- docs/rh-log.txt | 3 +++ src/namedef.h | 2 +- src/p_udmf.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 08d1f117b..bbfd763b1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +December 24, 2009 (Changes by Graf Zahl) +- fixed: The UDMF blockfloaters flag was misnamed. Changed to match the spec. + December 23, 2009 (Changes by Graf Zahl) - made the initial weave index for A_BishopMissileWeave and A_CStaffMissileSlither a configurable actor property. diff --git a/src/namedef.h b/src/namedef.h index a00ca93f5..ebddcc213 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -370,7 +370,7 @@ xx(Blockplayers) xx(Blockeverything) xx(Zoneboundary) xx(Jumpover) -xx(Blockfloating) +xx(Blockfloaters) xx(Clipmidtex) xx(Wrapmidtex) xx(Midtex3d) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 79b64a1de..5dfa06dd7 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -691,7 +691,7 @@ struct UDMFParser Flag(ld->flags, ML_RAILING, key); continue; - case NAME_Blockfloating: + case NAME_Blockfloaters: CHECK_N(St | Zd | Zdt | Va) Flag(ld->flags, ML_BLOCK_FLOATERS, key); continue; From d2a43398169852fc7cd61686bc4d427fe83bee71 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 00:19:28 +0000 Subject: [PATCH 143/241] - Split weaveindex into two separate byte-sized properties and moved them into unused space inside AActor. SVN r2038 (trunk) --- src/actor.h | 3 ++- src/g_hexen/a_bishop.cpp | 10 ++++------ src/g_hexen/a_clericstaff.cpp | 10 ++++------ src/p_mobj.cpp | 27 ++++++++++++++++++++++++--- src/thingdef/thingdef_properties.cpp | 13 +++++++++++-- wadsrc/static/actors/actor.txt | 3 ++- 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/actor.h b/src/actor.h index a7f06281a..5a8acbfc8 100644 --- a/src/actor.h +++ b/src/actor.h @@ -764,7 +764,6 @@ public: DWORD flags6; // Shit! Where did all the flags go? int special1; // Special info int special2; // Special info - int weaveindex; // Separated from special2 because it's used by globally accessible functions. int health; BYTE movedir; // 0-7 SBYTE visdir; @@ -782,6 +781,8 @@ public: TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) fixed_t SpawnPoint[3]; // For nightmare respawn WORD SpawnAngle; + BYTE WeaveIndexXY; // Separated from special2 because it's used by globally accessible functions. + BYTE WeaveIndexZ; int skillrespawncount; int TIDtoHate; // TID of things to hate (0 if none) FNameNoInit Species; // For monster families diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp index df998a8ab..d4de94f60 100644 --- a/src/g_hexen/a_bishop.cpp +++ b/src/g_hexen/a_bishop.cpp @@ -76,12 +76,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) int weaveXY, weaveZ; int angle; - // for compatibility this needs to set the value itself if it was never done by the projectile itself - if (self->weaveindex == -1) self->weaveindex = 16; - // since these values are now user configurable we have to do a proper range check to avoid array overflows. - weaveXY = (self->weaveindex >> 16) & 63; - weaveZ = (self->weaveindex & 63); + weaveXY = self->WeaveIndexXY & 63; + weaveZ = self->WeaveIndexZ & 63; angle = (self->angle + ANG90) >> ANGLETOFINESHIFT; newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); @@ -92,7 +89,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) self->z -= FloatBobOffsets[weaveZ]; weaveZ = (weaveZ + 2) & 63; self->z += FloatBobOffsets[weaveZ]; - self->weaveindex = weaveZ + (weaveXY<<16); + self->WeaveIndexXY = weaveXY; + self->WeaveIndexZ = weaveZ; } //============================================================================ diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index b2a50487c..a29d3afd6 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -135,12 +135,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle-(ANG45/15)); if (mo) { - mo->weaveindex = 32; + mo->WeaveIndexXY = 32; } mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle+(ANG45/15)); if (mo) { - mo->weaveindex = 0; + mo->WeaveIndexXY = 0; } S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM); } @@ -157,10 +157,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) int weaveXY; int angle; - if (self->weaveindex == -1) self->weaveindex = 0; - // since these values are now user configurable we have to do a proper range check to avoid array overflows. - weaveXY = self->weaveindex & 63; + weaveXY = self->WeaveIndexXY & 63; angle = (self->angle+ANG90)>>ANGLETOFINESHIFT; newX = self->x-FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); newY = self->y-FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); @@ -168,7 +166,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); P_TryMove (self, newX, newY, true); - self->weaveindex = weaveXY; + self->WeaveIndexXY = weaveXY; } //============================================================================ diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c0f8af6e8..496bd7587 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -312,13 +312,34 @@ void AActor::Serialize (FArchive &arc) { arc << DamageFactor; } - if (SaveVersion >= 2036) + if (SaveVersion > 2036) { - arc << weaveindex; + arc << WeaveIndexXY << WeaveIndexZ; } else { - weaveindex = special2; + int index; + + if (SaveVersion < 2036) + { + index = special2; + } + else + { + arc << index; + } + // A_BishopMissileWeave and A_CStaffMissileSlither stored the weaveXY + // value in different parts of the index. + if (this->IsKindOf(PClass::FindClass("BishopFX"))) + { + WeaveIndexXY = index >> 16; + WeaveIndexZ = index; + } + else + { + WeaveIndexXY = index; + WeaveIndexZ = 0; + } } // Skip past uservar array in old savegames diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index e8b170880..cd2537db0 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -905,10 +905,19 @@ DEFINE_PROPERTY(bouncecount, I, Actor) //========================================================================== // //========================================================================== -DEFINE_PROPERTY(weaveindex, I, Actor) +DEFINE_PROPERTY(weaveindexXY, I, Actor) { PROP_INT_PARM(id, 0); - defaults->weaveindex = id; + defaults->WeaveIndexXY = id; +} + +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(weaveindexZ, I, Actor) +{ + PROP_INT_PARM(id, 0); + defaults->WeaveIndexZ = id; } //========================================================================== diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 71c0790db..8517b12fd 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -19,7 +19,8 @@ ACTOR Actor native //: Thinker Gravity 1 DamageFactor 1.0 PushFactor 0.25 - WeaveIndex -1 + WeaveIndexXY 0 + WeaveIndexZ 16 // Variables for the expression evaluator // NOTE: fixed_t and angle_t are only used here to ensure proper conversion From 5aa673baad443b067629607e5b3c98f92a77d928 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 00:24:54 +0000 Subject: [PATCH 144/241] - Changed AFastProjectile::Effect() so that it sets the spawned trail to face same direction as the projectile. SVN r2039 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_shared/a_fastprojectile.cpp | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bbfd763b1..1a1b346aa 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 24, 2009 +- Changed AFastProjectile::Effect() so that it sets the spawned trail to face + same direction as the projectile. + December 24, 2009 (Changes by Graf Zahl) - fixed: The UDMF blockfloaters flag was misnamed. Changed to match the spec. diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index fe97e6a53..5829fc167 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -125,7 +125,14 @@ void AFastProjectile::Effect() } const PClass *trail = PClass::FindClass(name); - Spawn (trail, x, y, hitz, ALLOW_REPLACE); + if (trail != NULL) + { + AActor *act = Spawn (trail, x, y, hitz, ALLOW_REPLACE); + if (act != NULL) + { + act->angle = this->angle; + } + } } } } From 735294884eb315bb02c3aed81f73af996b0e0289 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 00:34:34 +0000 Subject: [PATCH 145/241] - Fixed: savepatchsize was declared incorrectly in d_dehacked.cpp:DoInclude(). SVN r2040 (trunk) --- docs/rh-log.txt | 1 + src/d_dehacked.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1a1b346aa..758459ef0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ December 24, 2009 +- Fixed: savepatchsize was declared incorrectly in d_dehacked.cpp:DoInclude(). - Changed AFastProjectile::Effect() so that it sets the spawned trail to face same direction as the projectile. diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index a8a154512..c90eabe90 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2205,8 +2205,8 @@ static int PatchStrings (int dummy) static int DoInclude (int dummy) { char *data; - int savedversion, savepversion; - char *savepatchfile, *savepatchpt, *savepatchname, savepatchsize; + int savedversion, savepversion, savepatchsize; + char *savepatchfile, *savepatchpt, *savepatchname; if (including) { From 6beaf818e37a6fcb09f8e1f5167f236e0016516c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 00:41:15 +0000 Subject: [PATCH 146/241] - Fixed: Calling S_ChangeMusic() with the same song but a different looping flag now restarts the song so that the new looping setting can be applied. (This was easier than modifying every music handler to support modifying loop changes on the fly, which seems like overkill.) SVN r2041 (trunk) --- docs/rh-log.txt | 4 ++++ src/s_sound.cpp | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 758459ef0..bd6e9ca3e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ December 24, 2009 +- Fixed: Calling S_ChangeMusic() with the same song but a different looping + flag now restarts the song so that the new looping setting can be applied. + (This was easier than modifying every music handler to support modifying + loop changes on the fly, which seems like overkill.) - Fixed: savepatchsize was declared incorrectly in d_dehacked.cpp:DoInclude(). - Changed AFastProjectile::Effect() so that it sets the spawned trail to face same direction as the projectile. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 4fbef6ae1..d63bd60e0 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2306,7 +2306,9 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } } - if (!mus_playing.name.IsEmpty() && stricmp (mus_playing.name, musicname) == 0) + if (!mus_playing.name.IsEmpty() && + stricmp (mus_playing.name, musicname) == 0 && + mus_playing.handle->m_Looping == looping) { if (order != mus_playing.baseorder) { From f667e68c94bbd62d56c9b242ee00cace51133b47 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 01:02:19 +0000 Subject: [PATCH 147/241] - Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag. It now also sets the X scale, so switching skins while morphed does not produce weird stretching upon unmorphing. SVN r2042 (trunk) --- docs/rh-log.txt | 3 +++ src/p_user.cpp | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bd6e9ca3e..901dd172f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ December 24, 2009 +- Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag. It now also sets + the X scale, so switching skins while morphed does not produce weird + stretching upon unmorphing. - Fixed: Calling S_ChangeMusic() with the same song but a different looping flag now restarts the song so that the new looping setting can be applied. (This was easier than modifying every music handler to support modifying diff --git a/src/p_user.cpp b/src/p_user.cpp index 82914b1f6..6f951ad24 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1399,10 +1399,12 @@ void P_CheckPlayerSprites() { int crouchspriteno; fixed_t defscaleY = mo->GetDefault()->scaleY; + fixed_t defscaleX = mo->GetDefault()->scaleX; - if (player->userinfo.skin != 0) + if (player->userinfo.skin != 0 && !(player->mo->flags4 & MF4_NOSKIN)) { defscaleY = skins[player->userinfo.skin].ScaleY; + defscaleX = skins[player->userinfo.skin].ScaleX; } // Set the crouch sprite @@ -1413,8 +1415,9 @@ void P_CheckPlayerSprites() { crouchspriteno = mo->crouchsprite; } - else if (mo->sprite == skins[player->userinfo.skin].sprite || - mo->sprite == skins[player->userinfo.skin].crouchsprite) + else if (!(player->mo->flags4 & MF4_NOSKIN) && + (mo->sprite == skins[player->userinfo.skin].sprite || + mo->sprite == skins[player->userinfo.skin].crouchsprite)) { crouchspriteno = skins[player->userinfo.skin].crouchsprite; } @@ -1446,6 +1449,7 @@ void P_CheckPlayerSprites() } mo->scaleY = defscaleY; } + mo->scaleX = defscaleX; } } } From 9eb5fdd276ee5e7c9bcf6f8b479f9ab94d1877e6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 02:19:50 +0000 Subject: [PATCH 148/241] - Added a channel parameter to the sector overload of SN_StopSequence() so it can be properly paired with calls to SN_StartSequence(). SVN r2043 (trunk) --- docs/rh-log.txt | 2 ++ src/p_ceiling.cpp | 6 +++--- src/p_doors.cpp | 4 ++-- src/p_floor.cpp | 6 +++--- src/p_pillar.cpp | 2 +- src/p_plats.cpp | 4 ++-- src/s_sndseq.cpp | 20 +++++++++++++++++--- src/s_sndseq.h | 2 +- 8 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 901dd172f..2cd36f7fb 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ December 24, 2009 +- Added a channel parameter to the sector overload of SN_StopSequence() so + it can be properly paired with calls to SN_StartSequence(). - Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag. It now also sets the X scale, so switching skins while morphed does not produce weird stretching upon unmorphing. diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index 12f957b47..4dd072a06 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -112,7 +112,7 @@ void DCeiling::Tick () m_Sector->SetTexture(sector_t::ceiling, m_Texture); // fall through default: - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_CEILING); Destroy (); break; } @@ -145,7 +145,7 @@ void DCeiling::Tick () m_Sector->SetTexture(sector_t::ceiling, m_Texture); // fall through default: - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_CEILING); Destroy (); break; } @@ -500,7 +500,7 @@ bool EV_CeilingCrushStop (int tag) { if (scan->m_Tag == tag && scan->m_Direction != 0) { - SN_StopSequence (scan->m_Sector); + SN_StopSequence (scan->m_Sector, CHAN_CEILING); scan->m_OldDirection = scan->m_Direction; scan->m_Direction = 0; // in-stasis; rtn = true; diff --git a/src/p_doors.cpp b/src/p_doors.cpp index c77ded90d..78fb9e576 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -133,7 +133,7 @@ void DDoor::Tick () if (res == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_CEILING); switch (m_Type) { case doorRaise: @@ -179,7 +179,7 @@ void DDoor::Tick () if (res == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_CEILING); switch (m_Type) { case doorRaise: diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 0b9a634e8..984a0f064 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -126,7 +126,7 @@ void DFloor::Tick () if (res == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_FLOOR); if (m_Type == buildStair) m_Type = waitStair; @@ -530,7 +530,7 @@ bool EV_FloorCrushStop (int tag) if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DFloor)) && barrier_cast(sec->floordata)->m_Type == DFloor::floorRaiseAndCrush) { - SN_StopSequence (sec); + SN_StopSequence (sec, CHAN_FLOOR); sec->floordata->Destroy (); sec->floordata = NULL; } @@ -959,7 +959,7 @@ void DElevator::Tick () if (res == pastdest) // if destination height acheived { // make floor stop sound - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_FLOOR); m_Sector->floordata = NULL; //jff 2/22/98 m_Sector->ceilingdata = NULL; //jff 2/22/98 diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index f20dc1ef4..1d2d5ba81 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -98,7 +98,7 @@ void DPillar::Tick () if (r == pastdest && s == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_FLOOR); Destroy (); } else diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 962447e49..87d9e6737 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -82,7 +82,7 @@ void DPlat::Tick () } else if (res == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_FLOOR); if (m_Type != platToggle) { m_Count = m_Wait; @@ -121,7 +121,7 @@ void DPlat::Tick () if (res == pastdest) { - SN_StopSequence (m_Sector); + SN_StopSequence (m_Sector, CHAN_FLOOR); // if not an instant toggle, start waiting if (m_Type != platToggle) //jff 3/14/98 toggle up down { // is silent, instant, no waiting diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index ecfed1246..93474ae19 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -849,7 +849,7 @@ DSeqNode *SN_StartSequence (sector_t *sector, int chan, int sequence, seqtype_t { if (!nostop) { - SN_StopSequence (sector); + SN_StopSequence (sector, chan); } if (TwiddleSeqNum (sequence, type)) { @@ -963,9 +963,23 @@ void SN_StopSequence (AActor *actor) SN_DoStop (actor); } -void SN_StopSequence (sector_t *sector) +void SN_StopSequence (sector_t *sector, int chan) { - SN_DoStop (sector); + DSeqNode *node; + + for (node = DSeqNode::FirstSequence(); node; ) + { + DSeqNode *next = node->NextSequence(); + if (node->Source() == sector) + { + assert(node->IsKindOf(RUNTIME_CLASS(DSeqSectorNode))); + if ((static_cast(node)->Channel & 7) == chan) + { + node->StopAndDestroy (); + } + } + node = next; + } } void SN_StopSequence (FPolyObj *poly) diff --git a/src/s_sndseq.h b/src/s_sndseq.h index e54010075..434dccb6f 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -86,7 +86,7 @@ DSeqNode *SN_StartSequence (sector_t *sec, int chan, FName seqname, int modenum) DSeqNode *SN_StartSequence (FPolyObj *poly, int sequence, seqtype_t type, int modenum, bool nostop=false); DSeqNode *SN_StartSequence (FPolyObj *poly, const char *name, int modenum); void SN_StopSequence (AActor *mobj); -void SN_StopSequence (sector_t *sector); +void SN_StopSequence (sector_t *sector, int chan); void SN_StopSequence (FPolyObj *poly); void SN_UpdateActiveSequences (void); ptrdiff_t SN_GetSequenceOffset (int sequence, SDWORD *sequencePtr); From b3986a0235ce99cb0faf029953e750427df24639 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 25 Dec 2009 05:55:51 +0000 Subject: [PATCH 149/241] - The options menu no longer scales up so quickly, so it can fit wider text onscreen. In addition, it now uses the whole height available to it. Also, at lower resolutions, items on the compatibility options menu now cut off the beginning of the option label rather than the option setting, making this menu useable where previously it was not. SVN r2044 (trunk) --- docs/rh-log.txt | 5 ++ src/m_menu.cpp | 34 +++++++-- src/m_menu.h | 3 - src/m_options.cpp | 179 ++++++++++++++++++++++++++-------------------- src/v_draw.cpp | 12 ++++ src/v_text.cpp | 12 +++- src/v_video.cpp | 5 ++ src/v_video.h | 2 + 8 files changed, 166 insertions(+), 86 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2cd36f7fb..5c0f7b3c7 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,9 @@ December 24, 2009 +- The options menu no longer scales up so quickly, so it can fit wider text + onscreen. In addition, it now uses the whole height available to it. Also, + at lower resolutions, items on the compatibility options menu now cut off + the beginning of the option label rather than the option setting, making + this menu useable where previously it was not. - Added a channel parameter to the sector overload of SN_StopSequence() so it can be properly paired with calls to SN_StartSequence(). - Fixed: P_CheckPlayerSprites() ignored the MF4_NOSKIN flag. It now also sets diff --git a/src/m_menu.cpp b/src/m_menu.cpp index d16a964dd..3535cf484 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -2120,6 +2120,26 @@ static void M_PlayerSetupTicker (void) } } + +static void M_DrawPlayerSlider (int x, int y, int cur) +{ + const int range = 255; + + x = (x - 160) * CleanXfac + screen->GetWidth() / 2; + y = (y - 100) * CleanYfac + screen->GetHeight() / 2; + + screen->DrawText (ConFont, CR_WHITE, x, y, + "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, + "\x13", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); +} + static void M_PlayerSetupDrawer () { int x, xo, yo; @@ -2251,9 +2271,9 @@ static void M_PlayerSetupDrawer () x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x; color = players[consoleplayer].userinfo.color; - M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, 0.0f, 255.0f, float(RPART(color)), -1); - M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, 0.0f, 255.0f, float(GPART(color)), -1); - M_DrawSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, 0.0f, 255.0f, float(BPART(color)), -1); + M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, RPART(color)); + M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, GPART(color)); + M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, BPART(color)); // [GRB] Draw class setting int pclass = players[consoleplayer].userinfo.PlayerClass; @@ -3443,7 +3463,13 @@ void M_Drawer () screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE); if (skullAnimCounter < 6) { - M_DrawConText(CR_RED, 150, y + (fontheight + 1) * messageSelection, "\xd"); + screen->DrawText(ConFont, CR_RED, + (150 - 160) * CleanXfac + screen->GetWidth() / 2, + (y + (fontheight + 1) * messageSelection - 100) * CleanYfac + screen->GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); } } } diff --git a/src/m_menu.h b/src/m_menu.h index ce7ba99e2..997cf0e7d 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -84,9 +84,6 @@ void M_DeactivateMenuInput (); void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); -// Draw a slider. Set fracdigits negative to not display the current value numerically. -void M_DrawSlider (int x, int y, double min, double max, double cur, int fracdigits=1); - // // MENU TYPEDEFS // diff --git a/src/m_options.cpp b/src/m_options.cpp index e8ffa85c3..219170e36 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -1494,11 +1494,9 @@ void M_DrawConText (int color, int x, int y, const char *str) { int len = (int)strlen(str); - x = (x - 160) * CleanXfac + screen->GetWidth() / 2; - y = (y - 100) * CleanYfac + screen->GetHeight() / 2; screen->DrawText (ConFont, color, x, y, str, - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, + DTA_CellX, 8 * CleanXfac_1, + DTA_CellY, 8 * CleanYfac_1, TAG_DONE); } @@ -1558,7 +1556,8 @@ bool M_StartOptionsMenu (void) return true; } -void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits) +// Draw a slider. Set fracdigits negative to not display the current value numerically. +static void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigits) { double range; @@ -1572,7 +1571,7 @@ void M_DrawSlider (int x, int y, double min, double max, double cur,int fracdigi { char textbuf[16]; mysnprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur); - screen->DrawText(SmallFont, CR_DARKGRAY, x + 12*8 + 4, y, textbuf, DTA_Clean, true, TAG_DONE); + screen->DrawText(SmallFont, CR_DARKGRAY, x + (12*8 + 4) * CleanXfac_1, y, textbuf, DTA_CleanNoMove_1, true, TAG_DONE); } } @@ -1643,6 +1642,7 @@ void M_OptDrawer () DWORD overlay; int labelofs; int indent; + int cursorspace; if (!CurrentMenu->DontDim) { @@ -1663,9 +1663,9 @@ void M_OptDrawer () if (BigFont && CurrentMenu->texttitle) { screen->DrawText (BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, - 160-BigFont->StringWidth (CurrentMenu->texttitle)/2, 10, - CurrentMenu->texttitle, DTA_Clean, true, TAG_DONE); - y = 15 + BigFont->GetHeight (); + (screen->GetWidth() - BigFont->StringWidth(CurrentMenu->texttitle) * CleanXfac_1) / 2, 10*CleanYfac_1, + CurrentMenu->texttitle, DTA_CleanNoMove_1, true, TAG_DONE); + y = 15 + BigFont->GetHeight(); } else { @@ -1674,7 +1674,7 @@ void M_OptDrawer () } if (gameinfo.gametype & GAME_Raven) { - labelofs = 2; + labelofs = 2 * CleanXfac_1; y -= 2; fontheight = 9; } @@ -1683,9 +1683,13 @@ void M_OptDrawer () labelofs = 0; fontheight = 8; } - ytop = y + CurrentMenu->scrolltop * 8; + cursorspace = 14 * CleanXfac_1; + y *= CleanYfac_1; + fontheight *= CleanYfac_1; + ytop = y + CurrentMenu->scrolltop * 8 * CleanYfac_1; + int lastrow = screen->GetHeight() - SmallFont->GetHeight() * CleanYfac_1; - for (i = 0; i < CurrentMenu->numitems && y <= 200 - SmallFont->GetHeight(); i++, y += fontheight) + for (i = 0; i < CurrentMenu->numitems && y <= lastrow; i++, y += fontheight) { if (i == CurrentMenu->scrolltop) { @@ -1696,15 +1700,30 @@ void M_OptDrawer () overlay = 0; if (item->type == discrete && item->c.discretecenter == 1) { - indent = 160; + indent = screen->GetWidth() / 2; } else if (item->type == joymore) { - indent = 4; + indent = 4 * CleanXfac_1; } else { indent = CurrentMenu->indent; + if (indent > 280) + { // kludge for the compatibility options with their extremely long labels + if (indent + 40 <= CleanWidth_1) + { + indent = (screen->GetWidth() - ((indent + 40) * CleanXfac_1)) / 2 + indent * CleanXfac_1; + } + else + { + indent = screen->GetWidth() - 40 * CleanXfac_1; + } + } + else + { + indent = (indent - 160) * CleanXfac_1 + screen->GetWidth() / 2; + } } if (item->type != screenres) @@ -1727,7 +1746,7 @@ void M_OptDrawer () label = somestring; } } - width = SmallFont->StringWidth(label); + width = SmallFont->StringWidth(label) * CleanXfac_1; switch (item->type) { case more: @@ -1737,34 +1756,34 @@ void M_OptDrawer () break; case joymore: - x = 20; + x = 20 * CleanXfac_1; color = MoreColor; break; case numberedmore: case rsafemore: case rightmore: - x = indent + 14; + x = indent + cursorspace; color = item->type != rightmore ? CR_GREEN : MoreColor; break; case redtext: - x = 160 - width / 2; + x = screen->GetWidth() / 2 - width / 2; color = LabelColor; break; case whitetext: - x = 160 - width / 2; + x = screen->GetWidth() / 2 - width / 2; color = CR_GOLD;//ValueColor; break; case listelement: - x = indent + 14; + x = indent + cursorspace; color = LabelColor; break; case colorpicker: - x = indent + 14; + x = indent + cursorspace; color = MoreColor; break; @@ -1781,7 +1800,7 @@ void M_OptDrawer () ? CR_YELLOW : LabelColor; break; } - screen->DrawText (SmallFont, color, x, y, label, DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); + screen->DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE); switch (item->type) { @@ -1791,8 +1810,8 @@ void M_OptDrawer () char tbuf[16]; mysnprintf (tbuf, countof(tbuf), "%d.", item->b.position); - x = indent - SmallFont->StringWidth (tbuf); - screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE); + x = indent - SmallFont->StringWidth (tbuf) * CleanXfac_1; + screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_CleanNoMove_1, true, TAG_DONE); } break; @@ -1808,14 +1827,14 @@ void M_OptDrawer () if (v == vals) { - screen->DrawText (SmallFont, ValueColor, indent + 14, y, "Unknown", - DTA_Clean, true, TAG_DONE); + screen->DrawText (SmallFont, ValueColor, indent + cursorspace, y, "Unknown", + DTA_CleanNoMove_1, true, TAG_DONE); } else { screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor, - indent + 14, y, item->e.values[v].name, - DTA_Clean, true, TAG_DONE); + indent + cursorspace, y, item->e.values[v].name, + DTA_CleanNoMove_1, true, TAG_DONE); } } @@ -1865,15 +1884,15 @@ void M_OptDrawer () if (v == vals) { - screen->DrawText (SmallFont, ValueColor, indent + 14, y, "Unknown", - DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); + screen->DrawText (SmallFont, ValueColor, indent + cursorspace, y, "Unknown", + DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE); } else { screen->DrawText (SmallFont, item->type == cdiscrete ? v : ValueColor, - indent + 14, y, + indent + cursorspace, y, item->type != discretes ? item->e.values[v].name : item->e.valuestrings[v].name.GetChars(), - DTA_Clean, true, DTA_ColorOverlay, overlay, TAG_DONE); + DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_DONE); } } @@ -1885,18 +1904,18 @@ void M_OptDrawer () value = item->a.cvar->GetGenericRep (CVAR_String); v = M_FindCurVal(value.String, item->e.enumvalues, (int)item->b.numvalues); - screen->DrawText(SmallFont, ValueColor, indent + 14, y, v, DTA_Clean, true, TAG_DONE); + screen->DrawText(SmallFont, ValueColor, indent + cursorspace, y, v, DTA_CleanNoMove_1, true, TAG_DONE); } break; case nochoice: - screen->DrawText (SmallFont, CR_GOLD, indent + 14, y, - (item->e.values[(int)item->b.min]).name, DTA_Clean, true, TAG_DONE); + screen->DrawText (SmallFont, CR_GOLD, indent + cursorspace, y, + (item->e.values[(int)item->b.min]).name, DTA_CleanNoMove_1, true, TAG_DONE); break; case joy_sens: value.Float = SELECTED_JOYSTICK->GetSensitivity(); - M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float, 1); + M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, value.Float, 1); break; case joy_slider: @@ -1909,29 +1928,29 @@ void M_OptDrawer () assert(item->e.joyslidernum == 1); value.Float = SELECTED_JOYSTICK->GetAxisDeadZone(item->a.joyselection); } - M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 3); + M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 3); break; case joy_inverter: assert(item->e.joyslidernum == 0); value.Float = SELECTED_JOYSTICK->GetAxisScale(item->a.joyselection); - screen->DrawText(SmallFont, ValueColor, indent + 14, y, + screen->DrawText(SmallFont, ValueColor, indent + cursorspace, y, (value.Float < 0) ? "Yes" : "No", - DTA_Clean, true, TAG_DONE); + DTA_CleanNoMove_1, true, TAG_DONE); break; case slider: value = item->a.cvar->GetGenericRep (CVAR_Float); - M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, value.Float, 1); + M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, value.Float, 1); break; case absslider: value = item->a.cvar->GetGenericRep (CVAR_Float); - M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 1); + M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, fabs(value.Float), 1); break; case intslider: - M_DrawSlider (indent + 14, y + labelofs, item->b.min, item->c.max, item->a.fval, 0); + M_DrawSlider (indent + cursorspace, y + labelofs, item->b.min, item->c.max, item->a.fval, 0); break; case control: @@ -1941,12 +1960,12 @@ void M_OptDrawer () C_NameKeys (description, item->b.key1, item->c.key2); if (description[0]) { - M_DrawConText(CR_WHITE, indent + 14, y-1+labelofs, description); + M_DrawConText(CR_WHITE, indent + cursorspace, y-1+labelofs, description); } else { - screen->DrawText(SmallFont, CR_BLACK, indent + 14, y + labelofs, "---", - DTA_Clean, true, TAG_DONE); + screen->DrawText(SmallFont, CR_BLACK, indent + cursorspace, y + labelofs, "---", + DTA_CleanNoMove_1, true, TAG_DONE); } } break; @@ -1954,9 +1973,9 @@ void M_OptDrawer () case colorpicker: { int box_x, box_y; - box_x = (indent - 35 - 160) * CleanXfac + screen->GetWidth()/2; - box_y = (y - ((gameinfo.gametype & GAME_Raven) ? 99 : 100)) * CleanYfac + screen->GetHeight()/2; - screen->Clear (box_x, box_y, box_x + 32*CleanXfac, box_y + (fontheight-1)*CleanYfac, + box_x = indent - 35 * CleanXfac_1; + box_y = (gameinfo.gametype & GAME_Raven) ? y - CleanYfac_1 : y; + screen->Clear (box_x, box_y, box_x + 32*CleanXfac_1, box_y + fontheight-CleanYfac_1, item->a.colorcvar->GetIndex(), 0); } break; @@ -1965,12 +1984,12 @@ void M_OptDrawer () { int box_x, box_y; int x1, p; - const int w = fontheight*CleanXfac; - const int h = fontheight*CleanYfac; + const int w = fontheight; + const int h = fontheight; - box_y = (y - 98) * CleanYfac + screen->GetHeight()/2; + box_y = y - 2 * CleanYfac_1; p = 0; - box_x = (indent - 32 - 160) * CleanXfac + screen->GetWidth()/2; + box_x = indent - 32 * CleanXfac_1; for (x1 = 0, p = int(item->b.min * 16); x1 < 16; ++p, ++x1) { screen->Clear (box_x, box_y, box_x + w, box_y + h, p, 0); @@ -2025,7 +2044,7 @@ void M_OptDrawer () } screen->DrawText (SmallFont, ValueColor, - indent + 14, y, str, DTA_Clean, true, TAG_DONE); + indent + cursorspace, y, str, DTA_CleanNoMove_1, true, TAG_DONE); } break; @@ -2037,12 +2056,13 @@ void M_OptDrawer () i == CurrentItem && (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) { - M_DrawConText(CR_RED, indent + 3, y-1+labelofs, "\xd"); + M_DrawConText(CR_RED, indent + 3 * CleanXfac_1, y-CleanYfac_1+labelofs, "\xd"); } } else { char *str = NULL; + int colwidth = screen->GetWidth() / 3; for (x = 0; x < 3; x++) { @@ -2059,13 +2079,13 @@ void M_OptDrawer () else color = CR_BRICK; //LabelColor; - screen->DrawText (SmallFont, color, 104 * x + 20, y, str, DTA_Clean, true, TAG_DONE); + screen->DrawText (SmallFont, color, colwidth * x + 20 * CleanXfac_1, y, str, DTA_CleanNoMove_1, true, TAG_DONE); } } if (i == CurrentItem && ((item->a.selmode != -1 && (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) || testingmode)) { - M_DrawConText(CR_RED, item->a.selmode * 104 + 8, y-1 + labelofs, "\xd"); + M_DrawConText(CR_RED, item->a.selmode * colwidth + 8 * CleanXfac_1, y - CleanYfac_1 + labelofs, "\xd"); } } } @@ -2076,11 +2096,11 @@ void M_OptDrawer () if (CanScrollUp) { - M_DrawConText(CR_ORANGE, 3, ytop + labelofs, "\x1a"); + M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop + labelofs, "\x1a"); } if (CanScrollDown) { - M_DrawConText(CR_ORANGE, 3, y - 8 + labelofs, "\x1b"); + M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1 + labelofs, "\x1b"); } if (flagsvar) @@ -2103,8 +2123,8 @@ void M_OptDrawer () } } screen->DrawText (SmallFont, ValueColor, - 160 - (SmallFont->StringWidth (flagsblah) >> 1), 0, flagsblah, - DTA_Clean, true, TAG_DONE); + (screen->GetWidth() - SmallFont->StringWidth (flagsblah) * CleanXfac_1) / 2, 0, flagsblah, + DTA_CleanNoMove_1, true, TAG_DONE); } } @@ -2257,31 +2277,33 @@ void M_OptButtonHandler(EMenuKey key, bool repeat) } if (CurrentItem < 0) { - int maxitems, rowheight; + int ytop, maxitems, rowheight; // Figure out how many lines of text fit on the menu if (CurrentMenu->y != 0) { - maxitems = CurrentMenu->y; + ytop = CurrentMenu->y; } else if (BigFont && CurrentMenu->texttitle) { - maxitems = 15 + BigFont->GetHeight (); + ytop = 15 + BigFont->GetHeight (); } else { - maxitems = 15; + ytop = 15; } if (!(gameinfo.gametype & GAME_DoomChex)) { - maxitems -= 2; + ytop -= 2; rowheight = 9; } else { rowheight = 8; } - maxitems = (200 - SmallFont->GetHeight () - maxitems) / rowheight + 1; + ytop *= CleanYfac_1; + rowheight *= CleanYfac_1; + maxitems = (screen->GetHeight() - SmallFont->GetHeight() - ytop) / rowheight + 1; CurrentMenu->scrollpos = MAX (0,CurrentMenu->numitems - maxitems + CurrentMenu->scrolltop); CurrentItem = CurrentMenu->numitems - 1; @@ -2989,16 +3011,16 @@ static void ColorPickerDrawer () DWORD oldColor = DWORD(*ColorPickerItems[0].a.colorcvar) | 0xFF000000; int x = screen->GetWidth()*2/3; - int y = (15 + BigFont->GetHeight() + SmallFont->GetHeight()*5 - 90) * CleanYfac + screen->GetHeight()/2; + int y = (15 + BigFont->GetHeight() + SmallFont->GetHeight()*5 - 10) * CleanYfac_1; - screen->Clear (x, y, x + 48*CleanXfac, y + 48*CleanYfac, -1, oldColor); - screen->Clear (x + 48*CleanXfac, y, x + 48*2*CleanXfac, y + 48*CleanYfac, -1, newColor); + screen->Clear (x, y, x + 48*CleanXfac_1, y + 48*CleanYfac_1, -1, oldColor); + screen->Clear (x + 48*CleanXfac_1, y, x + 48*2*CleanXfac_1, y + 48*CleanYfac_1, -1, newColor); - y += 49*CleanYfac; - screen->DrawText (SmallFont, CR_GRAY, x+(24-SmallFont->StringWidth("Old")/2)*CleanXfac, y, - "Old", DTA_CleanNoMove, true, TAG_DONE); - screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac, y, - "New", DTA_CleanNoMove, true, TAG_DONE); + y += 49*CleanYfac_1; + screen->DrawText (SmallFont, CR_GRAY, x+(24-SmallFont->StringWidth("Old")/2)*CleanXfac_1, y, + "Old", DTA_CleanNoMove_1, true, TAG_DONE); + screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac_1, y, + "New", DTA_CleanNoMove_1, true, TAG_DONE); } static void SetColorPickerSliders () @@ -3099,11 +3121,12 @@ static void DrawJoystickConfigMenuHeader() { FString joyname = SELECTED_JOYSTICK->GetName(); screen->DrawText(BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, - 160-BigFont->StringWidth(CurrentMenu->texttitle)/2, 5, - CurrentMenu->texttitle, DTA_Clean, true, TAG_DONE); + (screen->GetWidth() - BigFont->StringWidth(CurrentMenu->texttitle) * CleanXfac_1) / 2, + 5 * CleanYfac_1, + CurrentMenu->texttitle, DTA_CleanNoMove_1, true, TAG_DONE); screen->DrawText(SmallFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, - 160-SmallFont->StringWidth(joyname)/2, 8 + BigFont->GetHeight(), - joyname, DTA_Clean, true, TAG_DONE); + (screen->GetWidth() - SmallFont->StringWidth(joyname) * CleanXfac_1) / 2, (8 + BigFont->GetHeight()) * CleanYfac_1, + joyname, DTA_CleanNoMove_1, true, TAG_DONE); } static void UpdateJoystickConfigMenu(IJoystickConfig *joy) diff --git a/src/v_draw.cpp b/src/v_draw.cpp index e6ff521cd..e46a99d12 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -59,6 +59,9 @@ int CleanXfac, CleanYfac; // [RH] Effective screen sizes that the above scale values give you int CleanWidth, CleanHeight; +// Above minus 1 (or 1, if they are already 1) +int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; + CVAR (Bool, hud_scale, false, CVAR_ARCHIVE); // For routines that take RGB colors, cache the previous lookup in case there @@ -425,6 +428,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag } break; + case DTA_CleanNoMove_1: + boolval = va_arg(tags, INTBOOL); + if (boolval) + { + parms->destwidth = parms->texwidth * CleanXfac_1; + parms->destheight = parms->texheight * CleanYfac_1; + } + break; + case DTA_320x200: boolval = va_arg(tags, INTBOOL); if (boolval) diff --git a/src/v_text.cpp b/src/v_text.cpp index 2c758d5fa..be386e992 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -156,13 +156,23 @@ void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, c ptrval = va_arg (tags, void*); break; + case DTA_CleanNoMove_1: + boolval = va_arg (tags, INTBOOL); + if (boolval) + { + scalex = CleanXfac_1; + scaley = CleanYfac_1; + maxwidth = Width - (Width % scalex); + } + break; + case DTA_CleanNoMove: boolval = va_arg (tags, INTBOOL); if (boolval) { scalex = CleanXfac; scaley = CleanYfac; - maxwidth = Width - (Width % CleanYfac); + maxwidth = Width - (Width % scalex); } break; diff --git a/src/v_video.cpp b/src/v_video.cpp index d8187eb9d..fa1f090d0 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1398,6 +1398,11 @@ bool V_DoModeSetup (int width, int height, int bits) assert(CleanWidth >= 320); assert(CleanHeight >= 200); + CleanXfac_1 = MAX(CleanXfac - 1, 1); + CleanYfac_1 = MAX(CleanYfac - 1, 1); + CleanWidth_1 = width / CleanXfac_1; + CleanHeight_1 = height / CleanYfac_1; + DisplayWidth = width; DisplayHeight = height; DisplayBits = bits; diff --git a/src/v_video.h b/src/v_video.h index e722c62db..6beaeea7b 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -42,6 +42,7 @@ #include "c_cvars.h" extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac; +extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1; extern int DisplayWidth, DisplayHeight, DisplayBits; bool V_DoModeSetup (int width, int height, int bits); @@ -79,6 +80,7 @@ enum DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen DTA_Bottom320x200, // bool: same as DTA_320x200 but centers virtual screen on bottom for 1280x1024 targets DTA_CleanNoMove, // bool: like DTA_Clean but does not reposition output position + DTA_CleanNoMove_1, // bool: like DTA_CleanNoMove, but uses Clean[XY]fac_1 instead DTA_FlipX, // bool: flip image horizontally //FIXME: Does not work with DTA_Window(Left|Right) DTA_ShadowColor, // color of shadow DTA_ShadowAlpha, // alpha of shadow From 85c683e0c7f8a0fd77ff590a32113611683947ac Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 11:09:56 +0000 Subject: [PATCH 150/241] - Reintroduced Doom.exe's player_t::usedown variable so that respawning a player does not immediately activate switches. oldbuttons was not usable for this. This also required that CopyPlayer preserves this info. - Fixed: When restarting the music there was a NULL pointer check missing so it crashed when the game was started wi - Fixed: If the Use key is used to respawn the player it must be cleared so that it doesn't trigger any subsequent actions after respawning. - Fixed: Resurrecting a monster did not restore flags5 and flags6. - Fixed: Projectiles which killed a non-monster were unable to determine what precisely they hit because MF_CORPSE is only valid for monsters. A new flag, MF6_KILLED that gets set for all objects that die, was added for this case. - Added a generic A_Weave function that exposes all possible options of A_BishopMissileWeave and A_CStaffMissileSlither. These 2 functions are no longer needed from DECORATE and therefore deprecated. SVN r2045 (trunk) --- docs/rh-log.txt | 17 ++++++++++ src/actor.h | 1 + src/c_console.cpp | 21 ++++-------- src/d_player.h | 1 + src/g_game.cpp | 2 +- src/g_hexen/a_bishop.cpp | 20 +----------- src/g_hexen/a_clericstaff.cpp | 15 +-------- src/g_hexen/a_hexenspecialdecs.cpp | 1 + src/p_enemy.h | 1 + src/p_interaction.cpp | 2 ++ src/p_mobj.cpp | 4 +-- src/p_saveg.cpp | 5 +++ src/p_things.cpp | 2 ++ src/p_user.cpp | 8 ++++- src/s_sound.cpp | 1 + src/thingdef/thingdef_codeptr.cpp | 52 ++++++++++++++++++++++++++++++ 16 files changed, 102 insertions(+), 51 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5c0f7b3c7..ac1362295 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,20 @@ +December 25, 2009 (Changes by Graf Zahl) +- Reintroduced Doom.exe's player_t::usedown variable so that respawning a + player does not immediately activate switches. oldbuttons was not usable + for this. This also required that CopyPlayer preserves this info. +- Fixed: When restarting the music there was a NULL pointer check missing + so it crashed when the game was started wi +- Fixed: If the Use key is used to respawn the player it must be cleared + so that it doesn't trigger any subsequent actions after respawning. +- Fixed: Resurrecting a monster did not restore flags5 and flags6. +- Fixed: Projectiles which killed a non-monster were unable to determine + what precisely they hit because MF_CORPSE is only valid for monsters. + A new flag, MF6_KILLED that gets set for all objects that die, was added + for this case. +- Added a generic A_Weave function that exposes all possible options of + A_BishopMissileWeave and A_CStaffMissileSlither. These 2 functions are + no longer needed from DECORATE and therefore deprecated. + December 24, 2009 - The options menu no longer scales up so quickly, so it can fit wider text onscreen. In addition, it now uses the whole height available to it. Also, diff --git a/src/actor.h b/src/actor.h index 5a8acbfc8..be6046f0e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -318,6 +318,7 @@ enum MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect MF6_NOTRIGGER = 0x00010000, // actor cannot trigger any line actions MF6_SHATTERING = 0x00020000, // marks an ice corpse for forced shattering + MF6_KILLED = 0x00040000, // Something that was killed (but not necessarily a corpse) // --- mobj.renderflags --- diff --git a/src/c_console.cpp b/src/c_console.cpp index aafc76f36..324fad660 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -81,7 +81,6 @@ static bool C_TabCompleteList (); static bool TabbedLast; // True if last key pressed was tab static bool TabbedList; // True if tab list was shown CVAR (Bool, con_notablist, false, CVAR_ARCHIVE) -CVAR (Bool, con_ticker, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static FTextureID conback; static DWORD conshade; @@ -1105,23 +1104,17 @@ static void C_DrawNotifyText () void C_InitTicker (const char *label, unsigned int max, bool showpercent) { - if (con_ticker) - { - TickerPercent = showpercent; - TickerMax = max; - TickerLabel = label; - TickerAt = 0; - maybedrawnow (true, false); - } + TickerPercent = showpercent; + TickerMax = max; + TickerLabel = label; + TickerAt = 0; + maybedrawnow (true, false); } void C_SetTicker (unsigned int at, bool forceUpdate) { - if (con_ticker) - { - TickerAt = at > TickerMax ? TickerMax : at; - maybedrawnow (true, TickerVisible ? forceUpdate : false); - } + TickerAt = at > TickerMax ? TickerMax : at; + maybedrawnow (true, TickerVisible ? forceUpdate : false); } void C_DrawConsole (bool hw2d) diff --git a/src/d_player.h b/src/d_player.h index b23d0616d..3c9ad954c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -276,6 +276,7 @@ public: bool centering; BYTE turnticks; bool attackdown; + bool usedown; DWORD oldbuttons; int health; // only used between levels, mo->health // is used during levels diff --git a/src/g_game.cpp b/src/g_game.cpp index 2f3a62c07..dc576c2fc 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1316,7 +1316,7 @@ void G_PlayerReborn (int player) p->skill = b_skill; //Added by MC: - p->oldbuttons = ~0, p->attackdown = true; // don't do anything immediately + p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; p->playerstate = PST_LIVE; diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp index d4de94f60..68b5ce9d6 100644 --- a/src/g_hexen/a_bishop.cpp +++ b/src/g_hexen/a_bishop.cpp @@ -72,25 +72,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2) DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) { - fixed_t newX, newY; - int weaveXY, weaveZ; - int angle; - - // since these values are now user configurable we have to do a proper range check to avoid array overflows. - weaveXY = self->WeaveIndexXY & 63; - weaveZ = self->WeaveIndexZ & 63; - angle = (self->angle + ANG90) >> ANGLETOFINESHIFT; - newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); - newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); - weaveXY = (weaveXY + 2) & 63; - newX += FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); - newY += FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); - P_TryMove (self, newX, newY, true); - self->z -= FloatBobOffsets[weaveZ]; - weaveZ = (weaveZ + 2) & 63; - self->z += FloatBobOffsets[weaveZ]; - self->WeaveIndexXY = weaveXY; - self->WeaveIndexZ = weaveZ; + A_Weave(self, 2, 2, 2*FRACUNIT, FRACUNIT); } //============================================================================ diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index a29d3afd6..829e45127 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -153,20 +153,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack) DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither) { - fixed_t newX, newY; - int weaveXY; - int angle; - - // since these values are now user configurable we have to do a proper range check to avoid array overflows. - weaveXY = self->WeaveIndexXY & 63; - angle = (self->angle+ANG90)>>ANGLETOFINESHIFT; - newX = self->x-FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); - newY = self->y-FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); - weaveXY = (weaveXY+3)&63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); - P_TryMove (self, newX, newY, true); - self->WeaveIndexXY = weaveXY; + A_Weave(self, 3, 0, FRACUNIT, 0); } //============================================================================ diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index a3fee8557..60302c680 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -348,6 +348,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BellReset2) { self->flags |= MF_SHOOTABLE; self->flags &= ~MF_CORPSE; + self->flags6 &= ~MF6_KILLED; self->health = 5; } diff --git a/src/p_enemy.h b/src/p_enemy.h index a7386ccf5..ce5703e73 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -54,6 +54,7 @@ void P_NewChaseDir (AActor *actor); AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance); void P_TossItem (AActor *item); bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params); +void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdist); DECLARE_ACTION(A_Look) DECLARE_ACTION(A_Wander) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 3b1521f8c..075d978bc 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -396,6 +396,8 @@ void AActor::Die (AActor *source, AActor *inflictor) // be revived by an Arch-Vile. Batman Doom needs this. flags |= MF_CORPSE; } + flags6 |= MF6_KILLED; + // [RH] Allow the death height to be overridden using metadata. fixed_t metaheight = 0; if (DamageType == NAME_Fire) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 496bd7587..067ee62b4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1206,7 +1206,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) FState *nextstate=NULL; - if (target != NULL && target->flags & (MF_SHOOTABLE|MF_CORPSE)) + if (target != NULL && ((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_KILLED)) ) { if (target->flags & MF_NOBLOOD) nextstate = mo->FindState(NAME_Crash); if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme); @@ -5472,7 +5472,7 @@ int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FN void AActor::Crash() { - if ((flags & MF_CORPSE) && + if ((flags6 & MF6_KILLED) && !(flags3 & MF3_CRASHED) && !(flags & MF_ICECORPSE)) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index d9ee189e5..5e9a18f9c 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -244,6 +244,8 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) // needs to come from the save for bots. userinfo_t uibackup = dst->userinfo; int chasecam = dst->cheats & CF_CHASECAM; // Remember the chasecam setting + bool attackdown = dst->attackdown; + bool usedown = dst->usedown; *dst = *src; dst->cheats |= chasecam; @@ -270,6 +272,9 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) { dst->mo->player = dst; } + // These 2 variables may not be overwritten. + dst->attackdown = attackdown; + dst->usedown = usedown; } static void SpawnExtraPlayers () diff --git a/src/p_things.cpp b/src/p_things.cpp index 0b166cdc3..109b2d698 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -466,6 +466,8 @@ bool P_Thing_Raise(AActor *thing) thing->flags2 = info->flags2; thing->flags3 = info->flags3; thing->flags4 = info->flags4; + thing->flags5 = info->flags5; + thing->flags6 = info->flags6; thing->health = info->health; thing->target = NULL; thing->lastenemy = NULL; diff --git a/src/p_user.cpp b/src/p_user.cpp index 6f951ad24..9146b2bb6 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -222,6 +222,7 @@ player_t::player_t() centering(0), turnticks(0), attackdown(0), + usedown(0), oldbuttons(0), health(0), inventorytics(0), @@ -2287,10 +2288,15 @@ void P_PlayerThink (player_t *player) } } // check for use - if ((cmd->ucmd.buttons & BT_USE) && !(player->oldbuttons & BT_USE)) + if ((cmd->ucmd.buttons & BT_USE) && !player->usedown) { + player->usedown = true; P_UseLines (player); } + else + { + player->usedown = false; + } // Morph counter if (player->morphTics) { diff --git a/src/s_sound.cpp b/src/s_sound.cpp index d63bd60e0..8e5284f46 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2307,6 +2307,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } if (!mus_playing.name.IsEmpty() && + mus_playing.handle != NULL && stricmp (mus_playing.name, musicname) == 0 && mus_playing.handle->m_Looping == looping) { diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 1c00e7ae5..2c3d3fe63 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3019,6 +3019,58 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound); } +//=========================================================================== +// +// A_Weave +// +//=========================================================================== + +void A_Weave(AActor *self, int xyspeed, int zspeed, fixed_t xydist, fixed_t zdist) +{ + fixed_t newX, newY; + int weaveXY, weaveZ; + int angle; + fixed_t dist; + + weaveXY = self->WeaveIndexXY & 63; + weaveZ = self->WeaveIndexZ & 63; + angle = (self->angle + ANG90) >> ANGLETOFINESHIFT; + + if (xydist != 0 && xyspeed != 0) + { + dist = FixedMul(FloatBobOffsets[weaveXY], xydist); + newX = self->x - FixedMul (finecosine[angle], dist); + newY = self->y - FixedMul (finesine[angle], dist); + weaveXY = (weaveXY + xyspeed) & 63; + dist = FixedMul(FloatBobOffsets[weaveXY], xydist); + newX += FixedMul (finecosine[angle], dist); + newY += FixedMul (finesine[angle], dist); + P_TryMove (self, newX, newY, true); + self->WeaveIndexXY = weaveXY; + } + + if (zdist != 0 && zspeed != 0) + { + self->z -= FixedMul(FloatBobOffsets[weaveZ], zdist); + weaveZ = (weaveZ + zspeed) & 63; + self->z += FixedMul(FloatBobOffsets[weaveZ], zdist); + self->WeaveIndexZ = weaveZ; + } +} + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Weave) +{ + ACTION_PARAM_START(4); + ACTION_PARAM_INT(xspeed, 0); + ACTION_PARAM_INT(yspeed, 1); + ACTION_PARAM_FIXED(xdist, 2); + ACTION_PARAM_FIXED(ydist, 3); + A_Weave(self, xspeed, yspeed, xdist, ydist); +} + + + + //=========================================================================== // // A_LineEffect From 23caac1c9bb2b9d79ee311f4bb8990bfed521089 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 11:59:37 +0000 Subject: [PATCH 151/241] - Fixed: Decals could spread to walls which had a decal-less texture or were flagged not to have decals. - Fixed: DBaseDecal/DImpactDecal::CloneSelf never checked the return value from their StickToWall call and left unplaced decals behind if that happened. SVN r2046 (trunk) --- docs/rh-log.txt | 4 +++ src/g_shared/a_decals.cpp | 54 +++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ac1362295..733aef90d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,8 @@ December 25, 2009 (Changes by Graf Zahl) +- Fixed: Decals could spread to walls which had a decal-less texture or + were flagged not to have decals. +- Fixed: DBaseDecal/DImpactDecal::CloneSelf never checked the return value + from their StickToWall call and left unplaced decals behind if that happened. - Reintroduced Doom.exe's player_t::usedown variable so that respawning a player does not immediately activate switches. oldbuttons was not usable for this. This also required that CopyPlayer preserves this info. diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 51a30e081..d992bec9e 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -298,6 +298,13 @@ FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y, F3DFloor else return FNullTextureID(); CalcFracPos (wall, x, y); + FTexture *texture = TexMan[tex]; + + if (texture == NULL || texture->bNoDecals) + { + return FNullTextureID(); + } + return tex; } @@ -546,11 +553,18 @@ DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_ DBaseDecal *decal = new DBaseDecal(iz); if (decal != NULL) { - decal->StickToWall (wall, ix, iy, ffloor); - tpl->ApplyToDecal (decal, wall); - decal->AlphaColor = AlphaColor; - decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | - (this->RenderFlags & ~RF_DECALMASK); + if (decal->StickToWall (wall, ix, iy, ffloor).isValid()) + { + tpl->ApplyToDecal (decal, wall); + decal->AlphaColor = AlphaColor; + decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | + (this->RenderFlags & ~RF_DECALMASK); + } + else + { + decal->Destroy(); + return NULL; + } } return decal; } @@ -652,16 +666,12 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x, } DImpactDecal::CheckMax(); decal = new DImpactDecal (z); - - FTextureID stickypic = decal->StickToWall (wall, x, y, ffloor); - FTexture *tex = TexMan[stickypic]; - - if (tex != NULL && tex->bNoDecals) + if (decal == NULL) { return NULL; } - if (decal == NULL) + if (!decal->StickToWall (wall, x, y, ffloor).isValid()) { return NULL; } @@ -685,15 +695,27 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x, DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall, F3DFloor * ffloor) const { + if (wall->Flags & WALLF_NOAUTODECALS) + { + return NULL; + } + DImpactDecal::CheckMax(); DImpactDecal *decal = new DImpactDecal(iz); if (decal != NULL) { - decal->StickToWall (wall, ix, iy, ffloor); - tpl->ApplyToDecal (decal, wall); - decal->AlphaColor = AlphaColor; - decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | - (this->RenderFlags & ~RF_DECALMASK); + if (decal->StickToWall (wall, ix, iy, ffloor).isValid()) + { + tpl->ApplyToDecal (decal, wall); + decal->AlphaColor = AlphaColor; + decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) | + (this->RenderFlags & ~RF_DECALMASK); + } + else + { + decal->Destroy(); + return NULL; + } } return decal; } From 9747aaa9672ebcd9f6838bfbd1c6799d35e55f78 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 12:03:51 +0000 Subject: [PATCH 152/241] - forgot to save actor.txt with the A_Weave declaration. SVN r2047 (trunk) --- wadsrc/static/actors/actor.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 8517b12fd..90a592c3a 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -222,6 +222,7 @@ ACTOR Actor native //: Thinker action native A_PlayerSkinCheck(state label); action native A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); action native A_ThrowGrenade(class itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); + action native A_Weave(int xspeed, int yspeed, float xdist, float ydist); action native A_Recoil(float xyvel); action native A_JumpIfInTargetInventory(class itemtype, int amount, state label); From 350b5943f61f909af4b762a12768790ce013fd35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 13:43:08 +0000 Subject: [PATCH 153/241] - added PRINT_LOG option to all of the node builder's debug messages because outputting them to the console takes forever and makes them useless as a debug tool. SVN r2048 (trunk) --- src/nodebuild.cpp | 34 ++++++++++++++++++---------------- src/nodebuild_gl.cpp | 4 ++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index cd68c49e3..a988ba6e8 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -115,7 +115,7 @@ int FNodeBuilder::CreateNode (DWORD set, fixed_t bbox[4]) SplitSegs (set, node, splitseg, set1, set2); D(PrintSet (1, set1)); - D(Printf ("(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); + D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); D(PrintSet (2, set2)); node.intchildren[0] = CreateNode (set1, node.bbox[0]); node.intchildren[1] = CreateNode (set2, node.bbox[1]); @@ -138,7 +138,7 @@ int FNodeBuilder::CreateSubsector (DWORD set, fixed_t bbox[4]) bbox[BOXTOP] = bbox[BOXRIGHT] = INT_MIN; bbox[BOXBOTTOM] = bbox[BOXLEFT] = INT_MAX; - D(Printf ("Subsector from set %d\n", set)); + D(Printf (PRINT_LOG, "Subsector from set %d\n", set)); assert (set != DWORD_MAX); @@ -163,7 +163,7 @@ int FNodeBuilder::CreateSubsector (DWORD set, fixed_t bbox[4]) C_SetTicker (MulScale16 (SegsStuffed, (SDWORD)Segs.Size())); } - D(Printf ("bbox (%d,%d)-(%d,%d)\n", bbox[BOXLEFT]>>16, bbox[BOXBOTTOM]>>16, bbox[BOXRIGHT]>>16, bbox[BOXTOP]>>16)); + D(Printf (PRINT_LOG, "bbox (%d,%d)-(%d,%d)\n", bbox[BOXLEFT]>>16, bbox[BOXBOTTOM]>>16, bbox[BOXRIGHT]>>16, bbox[BOXTOP]>>16)); return ssnum; } @@ -293,7 +293,7 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int do { - D(Printf (" - seg %d(%d,%d)-(%d,%d) line %d front %d back %d\n", seg, + D(Printf (PRINT_LOG, " - seg %d(%d,%d)-(%d,%d) line %d front %d back %d\n", seg, Vertices[Segs[seg].v1].x>>16, Vertices[Segs[seg].v1].y>>16, Vertices[Segs[seg].v2].x>>16, Vertices[Segs[seg].v2].y>>16, Segs[seg].linedef, Segs[seg].frontsector, Segs[seg].backsector)); @@ -330,7 +330,7 @@ bool FNodeBuilder::CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int return false; } - D(Printf("Need to synthesize a splitter for set %d on seg %d\n", set, seg)); + D(Printf(PRINT_LOG, "Need to synthesize a splitter for set %d on seg %d\n", set, seg)); splitseg = DWORD_MAX; // This is a very simple and cheap "fix" for subsectors with segs @@ -364,7 +364,7 @@ bool FNodeBuilder::CheckSubsectorOverlappingSegs (DWORD set, node_t &node, DWORD { // Do not put minisegs into a new subsector. swap (seg1, seg2); } - D(Printf("Need to synthesize a splitter for set %d on seg %d (ov)\n", set, seg2)); + D(Printf(PRINT_LOG, "Need to synthesize a splitter for set %d on seg %d (ov)\n", set, seg2)); splitseg = DWORD_MAX; return ShoveSegBehind (set, node, seg2, seg1); @@ -424,6 +424,8 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int memset (&PlaneChecked[0], 0, PlaneChecked.Size()); + D(Printf (PRINT_LOG, "Processing set %d\n", set)); + while (seg != DWORD_MAX) { FPrivSeg *pseg = &Segs[seg]; @@ -445,7 +447,7 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int int value = Heuristic (node, set, nosplit); - D(Printf ("Seg %5d (%5d,%5d)-(%5d,%5d) scores %d\n", seg, node.x>>16, node.y>>16, + D(Printf (PRINT_LOG, "Seg %5d, ld %d (%5d,%5d)-(%5d,%5d) scores %d\n", seg, Segs[seg].linedef, node.x>>16, node.y>>16, (node.x+node.dx)>>16, (node.y+node.dy)>>16, value)); if (value > bestvalue) @@ -469,11 +471,11 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int if (bestseg == DWORD_MAX) { // No lines split any others into two sets, so this is a convex region. - D(Printf ("set %d, step %d, nosplit %d has no good splitter (%d)\n", set, step, nosplit, nosplitters)); + D(Printf (PRINT_LOG, "set %d, step %d, nosplit %d has no good splitter (%d)\n", set, step, nosplit, nosplitters)); return nosplitters ? -1 : 0; } - D(Printf ("split seg %u in set %d, score %d, step %d, nosplit %d\n", bestseg, set, bestvalue, step, nosplit)); + D(Printf (PRINT_LOG, "split seg %u in set %d, score %d, step %d, nosplit %d\n", bestseg, set, bestvalue, step, nosplit)); splitseg = bestseg; SetNodeFromSeg (node, &Segs[bestseg]); @@ -581,7 +583,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) { if (honorNoSplit) { - D(Printf ("Splits seg %d\n", i)); + D(Printf (PRINT_LOG, "Splits seg %d\n", i)); return -1; } else @@ -627,7 +629,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) // determine which sector it lies inside. if (realSegs[0] == 0 || realSegs[1] == 0) { - D(Printf ("Leaves a side with only mini segs\n")); + D(Printf (PRINT_LOG, "Leaves a side with only mini segs\n")); return -1; } @@ -636,7 +638,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) // is not neccesarily bad, just undesirable. if (honorNoSplit && (specialSegs[0] == realSegs[0] || specialSegs[1] == realSegs[1])) { - D(Printf ("Leaves a side with only special segs\n")); + D(Printf (PRINT_LOG, "Leaves a side with only special segs\n")); return -1; } @@ -908,7 +910,7 @@ DWORD FNodeBuilder::SplitSeg (DWORD segnum, int splitvert, int v1InFront) Segs.Push (newseg); - D(Printf ("Split seg %d to get seg %d\n", segnum, newnum)); + D(Printf (PRINT_LOG, "Split seg %d to get seg %d\n", segnum, newnum)); return newnum; } @@ -988,14 +990,14 @@ double FNodeBuilder::InterceptVector (const node_t &splitter, const FPrivSeg &se void FNodeBuilder::PrintSet (int l, DWORD set) { - Printf ("set %d:\n", l); + Printf (PRINT_LOG, "set %d:\n", l); for (; set != DWORD_MAX; set = Segs[set].next) { - Printf ("\t%u(%td):%d(%d,%d)-%d(%d,%d) ", set, Segs[set].frontsector-sectors, + Printf (PRINT_LOG, "\t%u(%td):%d(%d,%d)-%d(%d,%d) ", set, Segs[set].frontsector-sectors, Segs[set].v1, Vertices[Segs[set].v1].x>>16, Vertices[Segs[set].v1].y>>16, Segs[set].v2, Vertices[Segs[set].v2].x>>16, Vertices[Segs[set].v2].y>>16); } - Printf ("*\n"); + Printf (PRINT_LOG, "*\n"); } diff --git a/src/nodebuild_gl.cpp b/src/nodebuild_gl.cpp index e3453cd33..d990d17c3 100644 --- a/src/nodebuild_gl.cpp +++ b/src/nodebuild_gl.cpp @@ -117,7 +117,7 @@ void FNodeBuilder::FixSplitSharers (const node_t &node) while (event != NULL && next != NULL && event->Info.Vertex != v2) { - D(Printf("Forced split of seg %d(%d->%d) at %d(%d,%d)\n", seg, + D(Printf(PRINT_LOG, "Forced split of seg %d(%d->%d) at %d(%d,%d)\n", seg, Segs[seg].v1, Segs[seg].v2, event->Info.Vertex, Vertices[event->Info.Vertex].x>>16, @@ -209,7 +209,7 @@ void FNodeBuilder::AddMinisegs (const node_t &node, DWORD splitseg, DWORD &fset, ); } - D(Printf ("**Minisegs** %d/%d added %d(%d,%d)->%d(%d,%d)\n", fnseg, bnseg, + D(Printf (PRINT_LOG, "**Minisegs** %d/%d added %d(%d,%d)->%d(%d,%d)\n", fnseg, bnseg, prev->Info.Vertex, Vertices[prev->Info.Vertex].x>>16, Vertices[prev->Info.Vertex].y>>16, event->Info.Vertex, From abd9c62983ef983b7f744c5329e6ac472566ff35 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 16:22:57 +0000 Subject: [PATCH 154/241] - fixed usedown code from this morning. SVN r2049 (trunk) --- src/p_user.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index 9146b2bb6..2792f22fa 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2288,10 +2288,13 @@ void P_PlayerThink (player_t *player) } } // check for use - if ((cmd->ucmd.buttons & BT_USE) && !player->usedown) + if (cmd->ucmd.buttons & BT_USE) { - player->usedown = true; - P_UseLines (player); + if (!player->usedown) + { + player->usedown = true; + P_UseLines (player); + } } else { From 07dba2b4fe974bfc87607106ce7bebdd3c975cdc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Dec 2009 22:57:42 +0000 Subject: [PATCH 155/241] - The crash state must still be activatable by actors that have MF_CORPSE but not MF6_KILLED. SVN r2050 (trunk) --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 067ee62b4..53d6c6227 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1206,7 +1206,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) FState *nextstate=NULL; - if (target != NULL && ((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_KILLED)) ) + if (target != NULL && ((target->flags & (MF_SHOOTABLE|MF_CORPSE)) || (target->flags6 & MF6_KILLED)) ) { if (target->flags & MF_NOBLOOD) nextstate = mo->FindState(NAME_Crash); if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme); From 69270937dd5737edd79040f9c23533aa9f860dd2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Dec 2009 07:29:29 +0000 Subject: [PATCH 156/241] - crash fix for real this time. SVN r2051 (trunk) --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 53d6c6227..29480a7ee 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5472,7 +5472,7 @@ int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FN void AActor::Crash() { - if ((flags6 & MF6_KILLED) && + if (((flags & MF_CORPSE) || (flags6 & MF6_KILLED)) && !(flags3 & MF3_CRASHED) && !(flags & MF_ICECORPSE)) { From 3f059898fde0fe53b77e85e247f086fa0f66f525 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 27 Dec 2009 15:50:35 +0000 Subject: [PATCH 157/241] - added a linedef based method to define portals. Portals defined this way still have the same limitations as those defines with the portal things. SVN r2052 (trunk) --- docs/rh-log.txt | 4 +++ src/actionspecials.h | 1 + src/g_shared/a_sharedglobal.h | 10 +++++- src/g_shared/a_skies.cpp | 11 ++----- src/p_spec.cpp | 57 +++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 733aef90d..0c96f07a5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 27, 2009 (Changes by Graf Zahl) +- added a linedef based method to define portals. Portals defined this way + still have the same limitations as those defines with the portal things. + December 25, 2009 (Changes by Graf Zahl) - Fixed: Decals could spread to walls which had a decal-less texture or were flagged not to have decals. diff --git a/src/actionspecials.h b/src/actionspecials.h index 98c899f5b..417c823b1 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -55,6 +55,7 @@ DEFINE_SPECIAL(Line_SetTextureOffset, 53, 5, 5, 5) DEFINE_SPECIAL(Sector_ChangeFlags, 54, 3, 3, 3) DEFINE_SPECIAL(Line_SetBlocking, 55, 3, 3, 3) DEFINE_SPECIAL(Line_SetTextureScale, 56, 5, 5, 5) +DEFINE_SPECIAL(Sector_SetPortal, 57, -1, -1, 5) DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3, 3) DEFINE_SPECIAL(Plat_Stop, 61, 1, 1, 1) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 798f314e3..c152bf44d 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -89,16 +89,24 @@ public: class ASkyViewpoint : public AActor { DECLARE_CLASS (ASkyViewpoint, AActor) + HAS_OBJECT_POINTERS public: void Serialize (FArchive &arc); void BeginPlay (); void Destroy (); bool bInSkybox; bool bAlways; - ASkyViewpoint *Mate; + TObjPtr Mate; fixed_t PlaneAlpha; }; +class AStackPoint : public ASkyViewpoint +{ + DECLARE_CLASS (AStackPoint, ASkyViewpoint) +public: + void BeginPlay (); +}; + class DFlashFader : public DThinker { DECLARE_CLASS (DFlashFader, DThinker) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 77704dd50..cfe024b48 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -38,7 +38,9 @@ // arg0 = Visibility*4 for this skybox -IMPLEMENT_CLASS (ASkyViewpoint) +IMPLEMENT_POINTY_CLASS (ASkyViewpoint) + DECLARE_POINTER(Mate) +END_POINTERS // If this actor has no TID, make it the default sky box void ASkyViewpoint::BeginPlay () @@ -144,13 +146,6 @@ void ASkyPicker::PostBeginPlay () // arg0 = opacity of plane; 0 = invisible, 255 = fully opaque -class AStackPoint : public ASkyViewpoint -{ - DECLARE_CLASS (AStackPoint, ASkyViewpoint) -public: - void BeginPlay (); -}; - IMPLEMENT_CLASS (AStackPoint) void AStackPoint::BeginPlay () diff --git a/src/p_spec.cpp b/src/p_spec.cpp index bce0bcb30..1571ef31b 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -59,6 +59,7 @@ #include "statnums.h" #include "g_level.h" #include "v_font.h" +#include "a_sharedglobal.h" // State. #include "r_state.h" @@ -827,6 +828,50 @@ void DWallLightTransfer::DoTransfer (BYTE lightlevel, int target, BYTE flags) } } +void P_SpawnPortal(line_t *line, int sectortag, INTBOOL ceiling, int alpha) +{ + for (int i=0;iv1->x + line->v2->x) >> 1; + fixed_t y1 = (line->v1->y + line->v2->y) >> 1; + fixed_t x2 = (lines[i].v1->x + lines[i].v2->x) >> 1; + fixed_t y2 = (lines[i].v1->y + lines[i].v2->y) >> 1; + + AStackPoint *anchor = Spawn(x1, y1, 0, NO_REPLACE); + AStackPoint *reference = Spawn(x2, y2, 0, NO_REPLACE); + + reference->Mate = anchor; + anchor->Mate = reference; + + // This is so that the renderer can distinguish these portals from + // the ones spawned with the '*StackLookOnly' things. + reference->flags |= MF_JUSTATTACKED; + anchor->flags |= MF_JUSTATTACKED; + + for (int s=-1; (s = P_FindSectorFromTag(sectortag,s)) >= 0;) + { + if (ceiling) + { + if (sectors[s].CeilingSkyBox == NULL) sectors[s].CeilingSkyBox = reference; + } + else + { + if (sectors[s].FloorSkyBox == NULL) sectors[s].FloorSkyBox = reference; + } + } + return; + } + } +} + // // P_SpawnSpecials @@ -1049,6 +1094,18 @@ void P_SpawnSpecials (void) } break; + case Sector_SetPortal: + // arg 0 = sector tag + // arg 1 = type (must be 0, other values reserved for later use) + // arg 2 = 0:floor, 1:ceiling + // arg 3 = 0: anchor, 1: reference line + // arg 4 = for the anchor only: alpha + if (lines[i].args[1] == 0 && lines[i].args[3] == 0) + { + P_SpawnPortal(&lines[i], lines[i].args[0], lines[i].args[2], lines[i].args[4]); + } + break; + // [RH] ZDoom Static_Init settings case Static_Init: switch (lines[i].args[1]) From 4a8518e4f190e4b77c76057505400788c35a5473 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Dec 2009 00:01:07 +0000 Subject: [PATCH 158/241] - added a 'copy portal' option so that linedef-based portals can be transferred to sectors that already have a tag. SVN r2053 (trunk) --- src/p_setup.cpp | 12 ++++++------ src/p_spec.cpp | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f844b01ea..ab467a77e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1601,9 +1601,6 @@ void P_SpawnThings (int position) { int numthings = MapThingsConverted.Size(); - // [RH] Spawn slope creating things first. - P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[numthings]); - for (int i=0; i < numthings; i++) { SpawnMapThing (i, &MapThingsConverted[i], position); @@ -3623,11 +3620,14 @@ void P_SetupLevel (char *lumpname, int position) deathmatchstarts.Clear (); - // Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials - P_Spawn3DFloors(); - if (!buildmap) { + // [RH] Spawn slope creating things first. + P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()]); + + // Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials + P_Spawn3DFloors(); + times[14].Clock(); P_SpawnThings(position); diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 1571ef31b..525a601fa 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -828,6 +828,19 @@ void DWallLightTransfer::DoTransfer (BYTE lightlevel, int target, BYTE flags) } } + +inline void SetPortal(sector_t *sector, INTBOOL ceiling, AStackPoint *portal) +{ + if (ceiling) + { + if (sector->CeilingSkyBox == NULL) sector->CeilingSkyBox = portal; + } + else + { + if (sector->FloorSkyBox == NULL) sector->FloorSkyBox = portal; + } +} + void P_SpawnPortal(line_t *line, int sectortag, INTBOOL ceiling, int alpha) { for (int i=0;i= 0;) { - if (ceiling) + SetPortal(§ors[s], ceiling, reference); + } + + for (int j=0;j= 0;) + { + SetPortal(§ors[s], ceiling, reference); + } + } } } + return; } } From b6557a82ffa36001238f6c72b6b310163cf91e4c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Dec 2009 00:07:04 +0000 Subject: [PATCH 159/241] - added Hirogen2's Backpack fix for sv_unlimited_pickup. SVN r2054 (trunk) --- docs/rh-log.txt | 1 + src/g_shared/a_pickups.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0c96f07a5..089076e0a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ December 27, 2009 (Changes by Graf Zahl) +- added Hirogen2's Backpack fix for sv_unlimited_pickup. - added a linedef based method to define portals. Portals defined this way still have the same limitations as those defines with the portal things. diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 201d83e5f..194618933 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1638,7 +1638,7 @@ bool ABackpackItem::HandlePickup (AInventory *item) { if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo)) { - if (probe->Amount < probe->MaxAmount) + if (probe->Amount < probe->MaxAmount || sv_unlimited_pickup) { int amount = static_cast(probe->GetDefault())->BackpackAmount; // extra ammo in baby mode and nightmare mode @@ -1647,7 +1647,7 @@ bool ABackpackItem::HandlePickup (AInventory *item) amount = FixedMul(amount, G_SkillProperty(SKILLP_AmmoFactor)); } probe->Amount += amount; - if (probe->Amount > probe->MaxAmount) + if (probe->Amount > probe->MaxAmount && !sv_unlimited_pickup) { probe->Amount = probe->MaxAmount; } From 3d40dbb659a41553f2357d99d714a995c2d73cf9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Dec 2009 17:13:30 +0000 Subject: [PATCH 160/241] - merged all portals with the same displacement together. While this provides a mild performance increase it's not what I hoped it would do... - Moved portal initialization for the portal things to P_SpawnSpecials instead of having the things self-initialize in PostBeginPlay. This was done to ensure that the portals are fully set up when the game begins. Otherwise there is no decent way to let the renderer post-process this information during setup. - Changed: For 800x600 the default scaling handling of the options menu makes it become too small so for any resolution with a width between 800 and 959 it has been reverted to the regular clean scaling factor. SVN r2055 (trunk) --- docs/rh-log.txt | 12 ++++ src/g_shared/a_skies.cpp | 44 -------------- src/namedef.h | 3 + src/p_spec.cpp | 87 +++++++++++++++++++++++++++ src/v_video.cpp | 19 ++++-- wadsrc/static/actors/shared/skies.txt | 4 +- 6 files changed, 119 insertions(+), 50 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 089076e0a..436836e97 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,15 @@ +December 28, 2009 (Changes by Graf Zahl) +- merged all portals with the same displacement together. While this provides + a mild performance increase it's not what I hoped it would do... +- Moved portal initialization for the portal things to P_SpawnSpecials + instead of having the things self-initialize in PostBeginPlay. This was + done to ensure that the portals are fully set up when the game begins. + Otherwise there is no decent way to let the renderer post-process this + information during setup. +- Changed: For 800x600 the default scaling handling of the options menu + makes it become too small so for any resolution with a width between + 800 and 959 it has been reverted to the regular clean scaling factor. + December 27, 2009 (Changes by Graf Zahl) - added Hirogen2's Backpack fix for sv_unlimited_pickup. - added a linedef based method to define portals. Portals defined this way diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index cfe024b48..8ca0937c2 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -156,50 +156,6 @@ void AStackPoint::BeginPlay () bAlways = true; } -//--------------------------------------------------------------------------- -// Upper stacks go in the top sector. Lower stacks go in the bottom sector. - -class AUpperStackLookOnly : public AStackPoint -{ - DECLARE_CLASS (AUpperStackLookOnly, AStackPoint) -public: - void PostBeginPlay (); -}; - -class ALowerStackLookOnly : public AStackPoint -{ - DECLARE_CLASS (ALowerStackLookOnly, AStackPoint) -public: - void PostBeginPlay (); -}; - -IMPLEMENT_CLASS (AUpperStackLookOnly) -IMPLEMENT_CLASS (ALowerStackLookOnly) - -void AUpperStackLookOnly::PostBeginPlay () -{ - Super::PostBeginPlay (); - TActorIterator it (tid); - Sector->FloorSkyBox = it.Next(); - if (Sector->FloorSkyBox != NULL) - { - Sector->FloorSkyBox->Mate = this; - Sector->FloorSkyBox->PlaneAlpha = Scale (args[0], OPAQUE, 255); - } -} - -void ALowerStackLookOnly::PostBeginPlay () -{ - Super::PostBeginPlay (); - TActorIterator it (tid); - Sector->CeilingSkyBox = it.Next(); - if (Sector->CeilingSkyBox != NULL) - { - Sector->CeilingSkyBox->Mate = this; - Sector->CeilingSkyBox->PlaneAlpha = Scale (args[0], OPAQUE, 255); - } -} - //--------------------------------------------------------------------------- class ASectorSilencer : public AActor diff --git a/src/namedef.h b/src/namedef.h index ebddcc213..0eb9ce108 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -64,6 +64,9 @@ xx(Wind) xx(PointPusher) xx(PointPuller) +xx(UpperStackLookOnly) +xx(LowerStackLookOnly) + xx(BulletPuff) xx(StrifePuff) xx(MaulerPuff) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 525a601fa..487fff482 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -69,6 +69,8 @@ #include "r_interpolate.h" static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); +void P_SetupPortals(); + // [GrafZahl] Make this message changable by the user! ;) CVAR(String, secretmessage, "A Secret is revealed!", CVAR_ARCHIVE) @@ -828,6 +830,89 @@ void DWallLightTransfer::DoTransfer (BYTE lightlevel, int target, BYTE flags) } } +//----------------------------------------------------------------------------- +// +// Portals +// +//----------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Upper stacks go in the top sector. Lower stacks go in the bottom sector. + +static void SetupFloorPortal (AStackPoint *point) +{ + NActorIterator it (NAME_LowerStackLookOnly, point->tid); + sector_t *Sector = point->Sector; + Sector->FloorSkyBox = static_cast(it.Next()); + if (Sector->FloorSkyBox != NULL) + { + Sector->FloorSkyBox->Mate = point; + Sector->FloorSkyBox->PlaneAlpha = Scale (point->args[0], OPAQUE, 255); + } +} + +static void SetupCeilingPortal (AStackPoint *point) +{ + NActorIterator it (NAME_UpperStackLookOnly, point->tid); + sector_t *Sector = point->Sector; + Sector->CeilingSkyBox = static_cast(it.Next()); + if (Sector->CeilingSkyBox != NULL) + { + Sector->CeilingSkyBox->Mate = point; + Sector->CeilingSkyBox->PlaneAlpha = Scale (point->args[0], OPAQUE, 255); + } +} + +void P_SetupPortals() +{ + TThinkerIterator it; + AStackPoint *pt; + TArray points; + + while ((pt = it.Next())) + { + FName nm = pt->GetClass()->TypeName; + if (nm == NAME_UpperStackLookOnly) + { + SetupFloorPortal(pt); + } + else if (nm == NAME_LowerStackLookOnly) + { + SetupCeilingPortal(pt); + } + pt->special1 = 0; + points.Push(pt); + } + + for(unsigned i=0;ispecial1 == 0 && points[i]->Mate != NULL) + { + for(unsigned j=1;jspecial1 == 0 && points[j]->Mate != NULL && points[i]->GetClass() == points[j]->GetClass()) + { + fixed_t deltax1 = points[i]->Mate->x - points[i]->x; + fixed_t deltay1 = points[i]->Mate->y - points[i]->y; + fixed_t deltax2 = points[j]->Mate->x - points[j]->x; + fixed_t deltay2 = points[j]->Mate->y - points[j]->y; + if (deltax1 == deltax2 && deltay1 == deltay2) + { + if (points[j]->Sector->FloorSkyBox == points[j]) + points[j]->Sector->FloorSkyBox == points[i]; + + if (points[j]->Sector->CeilingSkyBox == points[j]) + points[j]->Sector->CeilingSkyBox == points[i]; + + points[j]->special1 = 1; + break; + } + + } + } + } + } +} inline void SetPortal(sector_t *sector, INTBOOL ceiling, AStackPoint *portal) { @@ -914,6 +999,8 @@ void P_SpawnSpecials (void) sector_t *sector; int i; + P_SetupPortals(); + // Init special SECTORs. sector = sectors; for (i = 0; i < numsectors; i++, sector++) diff --git a/src/v_video.cpp b/src/v_video.cpp index fa1f090d0..e9be86208 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1398,10 +1398,21 @@ bool V_DoModeSetup (int width, int height, int bits) assert(CleanWidth >= 320); assert(CleanHeight >= 200); - CleanXfac_1 = MAX(CleanXfac - 1, 1); - CleanYfac_1 = MAX(CleanYfac - 1, 1); - CleanWidth_1 = width / CleanXfac_1; - CleanHeight_1 = height / CleanYfac_1; + if (width < 800 || width >= 960) + { + CleanXfac_1 = MAX(CleanXfac - 1, 1); + CleanYfac_1 = MAX(CleanYfac - 1, 1); + CleanWidth_1 = width / CleanXfac_1; + CleanHeight_1 = height / CleanYfac_1; + } + else // if the width is between 800 and 960 the ratio between the screensize and CleanXFac-1 becomes too large. + { + CleanXfac_1 = CleanXfac; + CleanYfac_1 = CleanYfac; + CleanWidth_1 = CleanWidth; + CleanHeight_1 = CleanHeight; + } + DisplayWidth = width; DisplayHeight = height; diff --git a/wadsrc/static/actors/shared/skies.txt b/wadsrc/static/actors/shared/skies.txt index a4dce7db4..d652f5505 100644 --- a/wadsrc/static/actors/shared/skies.txt +++ b/wadsrc/static/actors/shared/skies.txt @@ -19,11 +19,11 @@ ACTOR StackPoint : SkyViewpoint native { } -ACTOR UpperStackLookOnly : StackPoint 9077 native +ACTOR UpperStackLookOnly : StackPoint 9077 { } -ACTOR LowerStackLookOnly : StackPoint 9078 native +ACTOR LowerStackLookOnly : StackPoint 9078 { } From 9b5c2c81f1295e7c0991abca5229ae5b19f0fa36 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Dec 2009 22:41:14 +0000 Subject: [PATCH 161/241] - Added full sound definitions for Heretic's ChickenPlayer and Hexen's PigPlayer (submitted by NeuralStunner.) - Added unmorph fix by Gez. SVN r2056 (trunk) --- docs/rh-log.txt | 3 +++ src/g_shared/a_morph.cpp | 2 +- src/g_shared/a_morph.h | 3 +++ src/p_user.cpp | 2 +- wadsrc/static/sndinfo.txt | 12 ++++++++++++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 436836e97..8c676eb35 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ December 28, 2009 (Changes by Graf Zahl) +- Added full sound definitions for Heretic's ChickenPlayer and Hexen's + PigPlayer (submitted by NeuralStunner.) +- Added unmorph fix by Gez. - merged all portals with the same displacement together. While this provides a mild performance increase it's not what I hoped it would do... - Moved portal initialization for the portal things to P_SpawnSpecials diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 4a730eb2f..a807ad70b 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -192,7 +192,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, return false; } - bool DeliberateUnmorphIsOkay = !!(player->MorphStyle & unmorphflag); + bool DeliberateUnmorphIsOkay = !!(MORPH_STANDARDUNDOING & unmorphflag); if ((pmo->flags2 & MF2_INVULNERABLE) // If the player is invulnerable && ((player != activator) // and either did not decide to unmorph, diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h index 1ddbf863d..e86332b3d 100644 --- a/src/g_shared/a_morph.h +++ b/src/g_shared/a_morph.h @@ -23,6 +23,9 @@ enum MORPH_UNDOBYDEATH = 0x00000200, // Actor unmorphs when killed and (unless MORPH_UNDOBYDEATHSAVES) stays dead MORPH_UNDOBYDEATHFORCED = 0x00000400, // Actor (if unmorphed when killed) forces unmorph (not very useful with UNDOBYDEATHSAVES) MORPH_UNDOBYDEATHSAVES = 0x00000800, // Actor (if unmorphed when killed) regains their health and doesn't die + MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires + + MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT, }; struct PClass; diff --git a/src/p_user.cpp b/src/p_user.cpp index 2792f22fa..ff3c8c01e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2309,7 +2309,7 @@ void P_PlayerThink (player_t *player) } if (!--player->morphTics) { // Attempt to undo the chicken/pig - P_UndoPlayerMorph (player, player); + P_UndoPlayerMorph (player, player, MORPH_UNDOBYTIMEOUT); } } // Cycle psprites diff --git a/wadsrc/static/sndinfo.txt b/wadsrc/static/sndinfo.txt index c8840310e..c69ef903e 100644 --- a/wadsrc/static/sndinfo.txt +++ b/wadsrc/static/sndinfo.txt @@ -545,6 +545,10 @@ $playersound player male *jump plrjmp $playersound player male *burndeath hedat1 $playeralias chicken male *usefail chicken/peck +$PlayerAlias Chicken Male *Grunt chicken/pain +$PlayerAlias Chicken Male *Land chicken/pain +$PlayerAlias Chicken Male *Jump chicken/active +$PlayerAlias Chicken Male *EvilLaugh chicken/active chicken/sight chicpai chicken/pain chicpai @@ -887,6 +891,14 @@ $playeralias mage male *puzzfail PuzzleFailMage $playersound mage male *jump mgjump $playeralias pig male *usefail PigActive1 +$PlayerAlias Pig Male *UseFail PigActive1 +$playeralias Pig Male *PuzzFail PigActive2 +$PlayerAlias Pig Male *Grunt PigActive1 +$PlayerAlias Pig Male *Land PigActive2 +$PlayerAlias Pig Male *Jump PigActive1 +$PlayerAlias Pig Male *Poison PigActive2 +$PlayerAlias Pig Male *Falling PigPain +$PlayerAlias Pig Male *Splat PigDeath $alias world/drip Ambient10 $alias world/watersplash WaterSplash From 64789b9111aabca4f3c568badba339676411c893 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 29 Dec 2009 04:50:56 +0000 Subject: [PATCH 162/241] - Fixed: Shooting up and down with AArtiPoisonBag3::Use() was completely broken. I don't know what I thinking when I plugged in 2*finesine[pitch] for Hexen's lookdir, because that's totally wrong. Not only is the magnitude far too low, but it also aims in the opposite direction you are looking. The new code only attempts to be close to Hexen's original while looking straight ahead and extrapolates that to other angles using proper 3D math. SVN r2057 (trunk) --- docs/rh-log.txt | 9 +++++++++ src/g_hexen/a_flechette.cpp | 35 ++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 8c676eb35..ab9dbf4dd 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +December 28, 2009 +- Fixed: Shooting up and down with AArtiPoisonBag3::Use() was completely + broken. I don't know what I thinking when I plugged in 2*finesine[pitch] + for Hexen's lookdir, because that's totally wrong. Not only is the + magnitude far too low, but it also aims in the opposite direction you + are looking. The new code only attempts to be close to Hexen's original + while looking straight ahead and extrapolates that to other angles using + proper 3D math. + December 28, 2009 (Changes by Graf Zahl) - Added full sound definitions for Heretic's ChickenPlayer and Hexen's PigPlayer (submitted by NeuralStunner.) diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index 884e356fd..ea72cb208 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -104,21 +104,38 @@ bool AArtiPoisonBag3::Use (bool pickup) { AActor *mo; - mo = Spawn ("ThrowingBomb", Owner->x, Owner->y, + mo = Spawn("ThrowingBomb", Owner->x, Owner->y, Owner->z-Owner->floorclip+35*FRACUNIT + (Owner->player? Owner->player->crouchoffset : 0), ALLOW_REPLACE); if (mo) { - angle_t pitch = (angle_t)Owner->pitch >> ANGLETOFINESHIFT; + mo->angle = Owner->angle + (((pr_poisonbag()&7) - 4) << 24); + + /* Original flight code from Hexen + * mo->momz = 4*FRACUNIT+((player->lookdir)<<(FRACBITS-4)); + * mo->z += player->lookdir<<(FRACBITS-4); + * P_ThrustMobj(mo, mo->angle, mo->info->speed); + * mo->momx += player->mo->momx>>1; + * mo->momy += player->mo->momy>>1; + */ + + // When looking straight ahead, it uses a z velocity of 4 while the xy velocity + // is as set by the projectile. To accomodate this with a proper trajectory, we + // aim the projectile ~20 degrees higher than we're looking at and increase the + // speed we fire at accordingly. + angle_t orgpitch = angle_t(-Owner->pitch) >> ANGLETOFINESHIFT; + angle_t modpitch = angle_t(0xDC00000 - Owner->pitch) >> ANGLETOFINESHIFT; + angle_t angle = mo->angle >> ANGLETOFINESHIFT; + fixed_t speed = fixed_t(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536))); + fixed_t xyscale = FixedMul(speed, finecosine[modpitch]); + + mo->velz = FixedMul(speed, finesine[modpitch]); + mo->velx = FixedMul(xyscale, finecosine[angle]) + (Owner->velx >> 1); + mo->vely = FixedMul(xyscale, finesine[angle]) + (Owner->vely >> 1); + mo->z += FixedMul(mo->Speed, finesine[orgpitch]); - mo->angle = Owner->angle+(((pr_poisonbag()&7)-4)<<24); - mo->velz = 4*FRACUNIT + 2*finesine[pitch]; - mo->z += 2*finesine[pitch]; - P_ThrustMobj (mo, mo->angle, mo->Speed); - mo->velx += Owner->velx >> 1; - mo->vely += Owner->vely >> 1; mo->target = Owner; mo->tics -= pr_poisonbag()&3; - P_CheckMissileSpawn (mo); + P_CheckMissileSpawn(mo); return true; } return false; From 66c2e4b5409567fe860762c9dc766f203b11b096 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Dec 2009 22:53:45 +0000 Subject: [PATCH 163/241] - Added ACS stubs for GZDoom's new SetGlobalFogParameter action special. SVN r2058 (trunk) --- src/actionspecials.h | 1 + src/g_hexen/a_flechette.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/actionspecials.h b/src/actionspecials.h index 417c823b1..552b65e49 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -139,6 +139,7 @@ DEFINE_SPECIAL(Teleport_NoStop, 154, 2, 3, 3) // Although ZDoom doesn't support them it's better to have them defined so that // WADs using them somewhere can at least be started without aborting due // to an error message. +DEFINE_SPECIAL(SetGlobalFogParameter, 157, 2, 2, 2) DEFINE_SPECIAL(FS_Execute, 158, 1, 4, 4) DEFINE_SPECIAL(Sector_SetPlaneReflection, 159, 3, 3, 3) DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5) diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index ea72cb208..dd951d451 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -125,7 +125,7 @@ bool AArtiPoisonBag3::Use (bool pickup) angle_t orgpitch = angle_t(-Owner->pitch) >> ANGLETOFINESHIFT; angle_t modpitch = angle_t(0xDC00000 - Owner->pitch) >> ANGLETOFINESHIFT; angle_t angle = mo->angle >> ANGLETOFINESHIFT; - fixed_t speed = fixed_t(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536))); + fixed_t speed = FLOAT2FIXED(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536))); fixed_t xyscale = FixedMul(speed, finecosine[modpitch]); mo->velz = FixedMul(speed, finesine[modpitch]); From 26c33afafb7d644d44247c20f37966ba3f3fc389 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Dec 2009 12:20:47 +0000 Subject: [PATCH 164/241] - fixed: Movement performed by actor movers was not interpolated because it happened outside the moved actor's Tick function. This got particularly obvious with moving skybox viewpoints (See Daedalus's MAP21 intro for a good example.) SVN r2059 (trunk) --- docs/rh-log.txt | 6 +++++ src/actor.h | 6 +++++ src/g_shared/a_fastprojectile.cpp | 1 + src/g_shared/a_movingcamera.cpp | 1 + src/p_enemy.cpp | 10 +++---- src/p_map.cpp | 6 ++--- src/p_mobj.cpp | 43 ++++++++++++++++++++++--------- src/p_things.cpp | 6 ++--- src/r_plane.cpp | 10 ++++--- 9 files changed, 62 insertions(+), 27 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ab9dbf4dd..a7a16b7ba 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,9 @@ +December 30, 2009 (Changes by Graf Zahl) +- fixed: Movement performed by actor movers was not interpolated because + it happened outside the moved actor's Tick function. This got particularly + obvious with moving skybox viewpoints (See Daedalus's MAP21 intro for a good + example.) + December 28, 2009 - Fixed: Shooting up and down with AArtiPoisonBag3::Use() was completely broken. I don't know what I thinking when I plugged in 2*finesine[pitch] diff --git a/src/actor.h b/src/actor.h index be6046f0e..90f80be1e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -570,6 +570,7 @@ public: // BeginPlay: Called just after the actor is created virtual void BeginPlay (); + virtual void PostBeginPlay (); // LevelSpawned: Called after BeginPlay if this actor was spawned by the world virtual void LevelSpawned (); // Translates SpawnFlags into in-game flags. @@ -579,6 +580,7 @@ public: virtual void Deactivate (AActor *activator); virtual void Tick (); + void DoTick (); // Smallest yaw interval for a mapthing to be spawned with virtual angle_t AngleIncrements (); @@ -868,6 +870,10 @@ public: // [RH] Used to interpolate the view to get >35 FPS fixed_t PrevX, PrevY, PrevZ; + angle_t PrevAngle; + + fixed_t LastX, LastY, LastZ; + angle_t LastAngle; // ThingIDs static void ClearTIDHashes (); diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 5829fc167..64b1451bb 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -26,6 +26,7 @@ void AFastProjectile::Tick () PrevX = x; PrevY = y; PrevZ = z; + PrevAngle = angle; if (!(flags5 & MF5_NOTIMEFREEZE)) { diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 0e704c95a..55316dbf1 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -585,6 +585,7 @@ void AActorMover::Activate (AActor *activator) tracer->PrevX = tracer->x; tracer->PrevY = tracer->y; tracer->PrevZ = tracer->z; + tracer->PrevAngle = tracer->angle; } void AActorMover::Deactivate (AActor *activator) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 4b80d5b68..0b5c29137 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -523,9 +523,9 @@ bool P_Move (AActor *actor) // so make it switchable if (nomonsterinterpolation) { - actor->PrevX = actor->x; - actor->PrevY = actor->y; - actor->PrevZ = actor->z; + actor->LastX = actor->PrevX = actor->x; + actor->LastY = actor->PrevY = actor->y; + actor->LastZ = actor->PrevZ = actor->z; } if (try_ok && friction > ORIG_FRICTION) @@ -2435,8 +2435,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi { if (nomonsterinterpolation) { - actor->PrevX = oldX; - actor->PrevY = oldY; + actor->LastX = actor->PrevX = oldX; + actor->LastY = actor->PrevY = oldY; } } P_NewChaseDir (actor); diff --git a/src/p_map.cpp b/src/p_map.cpp index dc056972f..0750050e9 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -392,9 +392,9 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr R_ResetViewInterpolation (); } - thing->PrevX = x; - thing->PrevY = y; - thing->PrevZ = z; + thing->LastX = thing->PrevX = x; + thing->LastY = thing->PrevY = y; + thing->LastZ = thing->PrevZ = z; return true; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 29480a7ee..82d8120b7 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -434,9 +434,10 @@ void AActor::Serialize (FArchive &arc) Speed = GetDefault()->Speed; } } - PrevX = x; - PrevY = y; - PrevZ = z; + LastX = PrevX = x; + LastY = PrevY = y; + LastZ = PrevZ = z; + LastAngle = PrevAngle = angle; UpdateWaterLevel(z, false); } } @@ -2805,7 +2806,7 @@ void AActor::SetShade (int r, int g, int b) // // P_MobjThinker // -void AActor::Tick () +void AActor::DoTick () { // [RH] Data for Heretic/Hexen scrolling sectors static const BYTE HexenScrollDirs[8] = { 64, 0, 192, 128, 96, 32, 224, 160 }; @@ -2835,10 +2836,6 @@ void AActor::Tick () return; } - PrevX = x; - PrevY = y; - PrevZ = z; - if (flags5 & MF5_NOINTERACTION) { // only do the minimally necessary things here to save time: @@ -3378,6 +3375,23 @@ void AActor::Tick () } } +void AActor::Tick() +{ + // This is necessary to properly interpolate movement outside this function + // like from an ActorMover + PrevX = LastX; + PrevY = LastY; + PrevZ = LastZ; + PrevAngle = LastAngle; + + DoTick(); + + LastX = x; + LastY = y; + LastZ = z; + LastAngle = angle; +} + //========================================================================== // // AActor::UpdateWaterLevel @@ -3517,9 +3531,9 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t actor = static_cast(const_cast(type)->CreateNew ()); - actor->x = actor->PrevX = ix; - actor->y = actor->PrevY = iy; - actor->z = actor->PrevZ = iz; + actor->x = actor->LastX = actor->PrevX = ix; + actor->y = actor->LastY = actor->PrevY = iy; + actor->z = actor->LastZ = actor->PrevZ = iz; actor->picnum.SetInvalid(); actor->health = actor->SpawnHealth(); @@ -3735,6 +3749,11 @@ void AActor::BeginPlay () } } +void AActor::PostBeginPlay () +{ + PrevAngle = angle; +} + bool AActor::isFast() { if (flags5&MF5_ALWAYSFAST) return true; @@ -4399,7 +4418,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) mobj->tid = mthing->thingid; mobj->AddToHash (); - mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360); + mobj->LastAngle = mobj->PrevAngle = mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360); mobj->BeginPlay (); if (!(mobj->ObjectFlags & OF_EuthanizeMe)) { diff --git a/src/p_things.cpp b/src/p_things.cpp index 109b2d698..46c46be99 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -142,9 +142,9 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog) Spawn (x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE); Spawn (oldx, oldy, oldz + TELEFOGHEIGHT, ALLOW_REPLACE); } - source->PrevX=x; - source->PrevY=y; - source->PrevZ=z; + source->LastX = source->PrevX = x; + source->LastY = source->PrevY = y; + source->LastZ = source->PrevZ = z; return true; } else diff --git a/src/r_plane.cpp b/src/r_plane.cpp index c9612c24c..aae870fbe 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1105,10 +1105,12 @@ void R_DrawSkyBoxes () // Don't let gun flashes brighten the sky box extralight = 0; R_SetVisibility (sky->args[0] * 0.25f); - viewx = sky->x; - viewy = sky->y; - viewz = sky->z; - viewangle = savedangle + sky->angle; + + viewx = sky->PrevX + FixedMul(r_TicFrac, sky->x - sky->PrevX); + viewy = sky->PrevY + FixedMul(r_TicFrac, sky->y - sky->PrevY); + viewz = sky->PrevZ + FixedMul(r_TicFrac, sky->z - sky->PrevZ); + viewangle = savedangle + sky->PrevAngle + FixedMul(r_TicFrac, sky->angle - sky->PrevAngle); + R_CopyStackedViewParameters(); } else From fa452ffd41719eceb391e56b0ce0635d769e5a2f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Dec 2009 18:53:14 +0000 Subject: [PATCH 165/241] - My ActorMover fix from earlier today was causing problems with moving sectors because it exposed a design flaw in the thinker system: Having every single actor default to the highest available statnum means that nothing can be placed in a slot where it is guaranteed to be run after all actors have ticked. But this is required for any thinker that moves an actor (i.e. AActorMover and DSectorEffect.) With DSectorEffect it just went unnoticed because they were added at the end of the list so almost nothing they moved was behind them in a thinker list. However, when an actor was spawned on a moving floor it did not move smoothly. The default statnum is now 100 so that there's sufficient slots above where such thinkers can be placed. SVN r2060 (trunk) --- docs/rh-log.txt | 9 +++++++ src/actor.h | 4 ---- src/dsectoreffect.cpp | 2 ++ src/dthinker.h | 3 ++- src/g_shared/a_movingcamera.cpp | 1 + src/p_enemy.cpp | 10 ++++---- src/p_map.cpp | 6 ++--- src/p_mobj.cpp | 42 +++++++++++++-------------------- src/p_spec.cpp | 10 ++++---- src/p_things.cpp | 6 ++--- src/statnums.h | 8 +++++++ 11 files changed, 53 insertions(+), 48 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a7a16b7ba..fae4f4cc5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -3,6 +3,15 @@ December 30, 2009 (Changes by Graf Zahl) it happened outside the moved actor's Tick function. This got particularly obvious with moving skybox viewpoints (See Daedalus's MAP21 intro for a good example.) + Fixing this exposed a design flaw in the thinker system: + Having every single actor default to the highest available statnum means that + nothing can be placed in a slot where it is guaranteed to be run after all actors + have ticked. But this is required for any thinker that moves an actor + (i.e. AActorMover and DSectorEffect.) With DSectorEffect it just went unnoticed + because they were added at the end of the list so almost nothing they moved was + behind them in a thinker list. However, when an actor was spawned on a moving + floor it did not move smoothly. The default statnum is now 100 so that there's + sufficient slots above where such thinkers can be placed. December 28, 2009 - Fixed: Shooting up and down with AArtiPoisonBag3::Use() was completely diff --git a/src/actor.h b/src/actor.h index 90f80be1e..5fd0619b9 100644 --- a/src/actor.h +++ b/src/actor.h @@ -580,7 +580,6 @@ public: virtual void Deactivate (AActor *activator); virtual void Tick (); - void DoTick (); // Smallest yaw interval for a mapthing to be spawned with virtual angle_t AngleIncrements (); @@ -872,9 +871,6 @@ public: fixed_t PrevX, PrevY, PrevZ; angle_t PrevAngle; - fixed_t LastX, LastY, LastZ; - angle_t LastAngle; - // ThingIDs static void ClearTIDHashes (); void AddToHash (); diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 48e58d0a9..2f4af7359 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -27,12 +27,14 @@ #include "p_local.h" #include "p_3dmidtex.h" #include "r_interpolate.h" +#include "statnums.h" IMPLEMENT_CLASS (DSectorEffect) DSectorEffect::DSectorEffect () { m_Sector = NULL; + ChangeStatNum(STAT_SECTOREFFECT); } void DSectorEffect::Destroy() diff --git a/src/dthinker.h b/src/dthinker.h index e50141475..32857d86b 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -36,6 +36,7 @@ #include #include "dobject.h" +#include "statnums.h" class AActor; class player_t; @@ -62,7 +63,7 @@ class DThinker : public DObject { DECLARE_CLASS (DThinker, DObject) public: - DThinker (int statnum = MAX_STATNUM) throw(); + DThinker (int statnum = STAT_DEFAULT) throw(); void Destroy (); virtual ~DThinker (); virtual void Tick (); diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 55316dbf1..58bde3cff 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -213,6 +213,7 @@ void APathFollower::BeginPlay () Super::BeginPlay (); PrevNode = CurrNode = NULL; bActive = false; + ChangeStatNum(STAT_ACTORMOVER); } void APathFollower::PostBeginPlay () diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 0b5c29137..4b80d5b68 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -523,9 +523,9 @@ bool P_Move (AActor *actor) // so make it switchable if (nomonsterinterpolation) { - actor->LastX = actor->PrevX = actor->x; - actor->LastY = actor->PrevY = actor->y; - actor->LastZ = actor->PrevZ = actor->z; + actor->PrevX = actor->x; + actor->PrevY = actor->y; + actor->PrevZ = actor->z; } if (try_ok && friction > ORIG_FRICTION) @@ -2435,8 +2435,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi { if (nomonsterinterpolation) { - actor->LastX = actor->PrevX = oldX; - actor->LastY = actor->PrevY = oldY; + actor->PrevX = oldX; + actor->PrevY = oldY; } } P_NewChaseDir (actor); diff --git a/src/p_map.cpp b/src/p_map.cpp index 0750050e9..dc056972f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -392,9 +392,9 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr R_ResetViewInterpolation (); } - thing->LastX = thing->PrevX = x; - thing->LastY = thing->PrevY = y; - thing->LastZ = thing->PrevZ = z; + thing->PrevX = x; + thing->PrevY = y; + thing->PrevZ = z; return true; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 82d8120b7..57ba84030 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -434,10 +434,10 @@ void AActor::Serialize (FArchive &arc) Speed = GetDefault()->Speed; } } - LastX = PrevX = x; - LastY = PrevY = y; - LastZ = PrevZ = z; - LastAngle = PrevAngle = angle; + PrevX = x; + PrevY = y; + PrevZ = z; + PrevAngle = angle; UpdateWaterLevel(z, false); } } @@ -2806,7 +2806,7 @@ void AActor::SetShade (int r, int g, int b) // // P_MobjThinker // -void AActor::DoTick () +void AActor::Tick () { // [RH] Data for Heretic/Hexen scrolling sectors static const BYTE HexenScrollDirs[8] = { 64, 0, 192, 128, 96, 32, 224, 160 }; @@ -2836,6 +2836,13 @@ void AActor::DoTick () return; } + // This is necessary to properly interpolate movement outside this function + // like from an ActorMover + PrevX = x; + PrevY = y; + PrevZ = z; + PrevAngle = angle; + if (flags5 & MF5_NOINTERACTION) { // only do the minimally necessary things here to save time: @@ -3375,23 +3382,6 @@ void AActor::DoTick () } } -void AActor::Tick() -{ - // This is necessary to properly interpolate movement outside this function - // like from an ActorMover - PrevX = LastX; - PrevY = LastY; - PrevZ = LastZ; - PrevAngle = LastAngle; - - DoTick(); - - LastX = x; - LastY = y; - LastZ = z; - LastAngle = angle; -} - //========================================================================== // // AActor::UpdateWaterLevel @@ -3531,9 +3521,9 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t actor = static_cast(const_cast(type)->CreateNew ()); - actor->x = actor->LastX = actor->PrevX = ix; - actor->y = actor->LastY = actor->PrevY = iy; - actor->z = actor->LastZ = actor->PrevZ = iz; + actor->x = actor->PrevX = ix; + actor->y = actor->PrevY = iy; + actor->z = actor->PrevZ = iz; actor->picnum.SetInvalid(); actor->health = actor->SpawnHealth(); @@ -4418,7 +4408,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) mobj->tid = mthing->thingid; mobj->AddToHash (); - mobj->LastAngle = mobj->PrevAngle = mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360); + mobj->PrevAngle = mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360); mobj->BeginPlay (); if (!(mobj->ObjectFlags & OF_EuthanizeMe)) { diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 487fff482..c78e4ebe3 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -898,16 +898,14 @@ void P_SetupPortals() fixed_t deltay2 = points[j]->Mate->y - points[j]->y; if (deltax1 == deltax2 && deltay1 == deltay2) { - if (points[j]->Sector->FloorSkyBox == points[j]) - points[j]->Sector->FloorSkyBox == points[i]; + if (points[j]->Sector->FloorSkyBox == points[j]->Mate) + points[j]->Sector->FloorSkyBox = points[i]->Mate; - if (points[j]->Sector->CeilingSkyBox == points[j]) - points[j]->Sector->CeilingSkyBox == points[i]; + if (points[j]->Sector->CeilingSkyBox == points[j]->Mate) + points[j]->Sector->CeilingSkyBox = points[i]->Mate; points[j]->special1 = 1; - break; } - } } } diff --git a/src/p_things.cpp b/src/p_things.cpp index 46c46be99..cd1540f4f 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -142,9 +142,9 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog) Spawn (x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE); Spawn (oldx, oldy, oldz + TELEFOGHEIGHT, ALLOW_REPLACE); } - source->LastX = source->PrevX = x; - source->LastY = source->PrevY = y; - source->LastZ = source->PrevZ = z; + source->PrevX = x; + source->PrevY = y; + source->PrevZ = z; return true; } else diff --git a/src/statnums.h b/src/statnums.h index fd6831dc8..201b586da 100644 --- a/src/statnums.h +++ b/src/statnums.h @@ -1,3 +1,5 @@ +#ifndef __STATNUMS_H +#define __STATNUMS_H /* ** statnums.h ** @@ -56,4 +58,10 @@ enum STAT_LIGHTTRANSFER, // A sector light transfer. These must be ticked after the light effects!!! STAT_EARTHQUAKE, // Earthquake actors STAT_MAPMARKER, // Map marker actors + + STAT_DEFAULT = 100, + STAT_SECTOREFFECT, + STAT_ACTORMOVER, }; + +#endif \ No newline at end of file From 403ab51781a379aefea98f33c9e1f33a938f3e48 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Dec 2009 19:17:10 +0000 Subject: [PATCH 166/241] - needed one more change... SVN r2061 (trunk) --- src/dsectoreffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 2f4af7359..6c717b998 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -32,9 +32,9 @@ IMPLEMENT_CLASS (DSectorEffect) DSectorEffect::DSectorEffect () +: DThinker(STAT_SECTOREFFECT) { m_Sector = NULL; - ChangeStatNum(STAT_SECTOREFFECT); } void DSectorEffect::Destroy() From bcbf4c3c841bf830e9404a0422518ab114afaa9d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 31 Dec 2009 06:13:47 +0000 Subject: [PATCH 167/241] - Fixed: A_ThrowGrenade used the same code as the old fighter flechette, so it was just as broken at aiming up and down. SVN r2062 (trunk) --- docs/rh-log.txt | 4 ++++ src/thingdef/thingdef_codeptr.cpp | 36 ++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fae4f4cc5..6c9a92f2b 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 30, 2009 +- Fixed: A_ThrowGrenade used the same code as the old fighter flechette, so + it was just as broken at aiming up and down. + December 30, 2009 (Changes by Graf Zahl) - fixed: Movement performed by actor movers was not interpolated because it happened outside the moved actor's Tick function. This got particularly diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 2c3d3fe63..2c8eb2684 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1592,8 +1592,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) if (ACTION_CALL_FROM_WEAPON()) { - // Used from a weapon so use some ammo - AWeapon * weapon=self->player->ReadyWeapon; + // Used from a weapon, so use some ammo + AWeapon *weapon = self->player->ReadyWeapon; if (!weapon) return; if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) return; @@ -1607,17 +1607,33 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade) ALLOW_REPLACE); if (bo) { - int pitch = self->pitch; - P_PlaySpawnSound(bo, self); - if (xyvel) + if (xyvel != 0) bo->Speed = xyvel; bo->angle = self->angle + (((pr_grenade()&7) - 4) << 24); - bo->velz = zvel + 2*finesine[pitch>>ANGLETOFINESHIFT]; - bo->z += 2 * finesine[pitch>>ANGLETOFINESHIFT]; - P_ThrustMobj(bo, bo->angle, bo->Speed); - bo->velx += self->velx >> 1; - bo->vely += self->vely >> 1; + + angle_t pitch = angle_t(-self->pitch) >> ANGLETOFINESHIFT; + angle_t angle = bo->angle >> ANGLETOFINESHIFT; + + // There are two vectors we are concerned about here: xy and z. We rotate + // them separately according to the shooter's pitch and then sum them to + // get the final velocity vector to shoot with. + + fixed_t xy_xyscale = FixedMul(bo->Speed, finecosine[pitch]); + fixed_t xy_velz = FixedMul(bo->Speed, finesine[pitch]); + fixed_t xy_velx = FixedMul(xy_xyscale, finecosine[angle]); + fixed_t xy_vely = FixedMul(xy_xyscale, finesine[angle]); + + pitch = angle_t(self->pitch) >> ANGLETOFINESHIFT; + fixed_t z_xyscale = FixedMul(zvel, finesine[pitch]); + fixed_t z_velz = FixedMul(zvel, finecosine[pitch]); + fixed_t z_velx = FixedMul(z_xyscale, finecosine[angle]); + fixed_t z_vely = FixedMul(z_xyscale, finesine[angle]); + + bo->velx = xy_velx + z_velx + (self->velx >> 1); + bo->vely = xy_vely + z_vely + (self->vely >> 1); + bo->velz = xy_velz + z_velz; + bo->target= self; P_CheckMissileSpawn (bo); } From 3288d56caccd3dbf8f2aebed4ac3d889da1df382 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 31 Dec 2009 09:02:38 +0000 Subject: [PATCH 168/241] - fixed: FastProjectile was missing all sky checks when the projectile's move was blocked. SVN r2063 (trunk) --- docs/rh-log.txt | 4 ++++ src/g_shared/a_fastprojectile.cpp | 38 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6c9a92f2b..7a1263930 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,7 @@ +December 31, 2009 (Changes by Graf Zahl) +- fixed: FastProjectile was missing all sky checks when the projectile's move + was blocked. + December 30, 2009 - Fixed: A_ThrowGrenade used the same code as the old fighter flechette, so it was just as broken at aiming up and down. diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index 64b1451bb..3bd2903ee 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -2,6 +2,8 @@ #include "a_sharedglobal.h" #include "p_local.h" #include "g_level.h" +#include "r_sky.h" +#include "p_lnspec.h" IMPLEMENT_CLASS(AFastProjectile) @@ -72,6 +74,26 @@ void AFastProjectile::Tick () if (!P_TryMove (this, x + xfrac,y + yfrac, true, false, tm)) { // Blocked move + if (!(flags3 & MF3_SKYEXPLODE)) + { + if (tm.ceilingline && + tm.ceilingline->backsector && + tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum && + z >= tm.ceilingline->backsector->ceilingplane.ZatPoint (x, y)) + { + // Hack to prevent missiles exploding against the sky. + // Does not handle sky floors. + Destroy (); + return; + } + // [RH] Don't explode on horizon lines. + if (BlockingLine != NULL && BlockingLine->special == Line_Horizon) + { + Destroy (); + return; + } + } + P_ExplodeMissile (this, BlockingLine, BlockingMobj); return; } @@ -79,6 +101,15 @@ void AFastProjectile::Tick () z += zfrac; if (z <= floorz) { // Hit the floor + + if (floorpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE)) + { + // [RH] Just remove the missile without exploding it + // if this is a sky floor. + Destroy (); + return; + } + z = floorz; P_HitFloor (this); P_ExplodeMissile (this, NULL, NULL); @@ -86,6 +117,13 @@ void AFastProjectile::Tick () } if (z + height > ceilingz) { // Hit the ceiling + + if (ceilingpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE)) + { + Destroy (); + return; + } + z = ceilingz - height; P_ExplodeMissile (this, NULL, NULL); return; From b21eb894ae60b5e8c43a083ed96553c2981acd09 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 31 Dec 2009 20:50:30 +0000 Subject: [PATCH 169/241] - reverted accidental commit SVN r2064 (trunk) --- src/g_hexen/a_flechette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index dd951d451..ea72cb208 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -125,7 +125,7 @@ bool AArtiPoisonBag3::Use (bool pickup) angle_t orgpitch = angle_t(-Owner->pitch) >> ANGLETOFINESHIFT; angle_t modpitch = angle_t(0xDC00000 - Owner->pitch) >> ANGLETOFINESHIFT; angle_t angle = mo->angle >> ANGLETOFINESHIFT; - fixed_t speed = FLOAT2FIXED(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536))); + fixed_t speed = fixed_t(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536))); fixed_t xyscale = FixedMul(speed, finecosine[modpitch]); mo->velz = FixedMul(speed, finesine[modpitch]); From 038d99aea4b6259449f123352f7c4c629b1df518 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 1 Jan 2010 01:57:48 +0000 Subject: [PATCH 170/241] - Version bump to 2.4.0. SVN r2065 (trunk) --- src/version.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/version.h b/src/version.h index 8896eb713..80a8fd861 100644 --- a/src/version.h +++ b/src/version.h @@ -40,21 +40,21 @@ /** Lots of different version numbers **/ -#define DOTVERSIONSTR_NOREV "2.3.1" +#define DOTVERSIONSTR_NOREV "2.4.0" // The version string the user actually sees. #define DOTVERSIONSTR DOTVERSIONSTR_NOREV " (r" SVN_REVISION_STRING ")" // The version as seen in the Windows resource -#define RC_FILEVERSION 2,3,1,SVN_REVISION_NUMBER -#define RC_PRODUCTVERSION 2,3,1,0 +#define RC_FILEVERSION 2,4,0,SVN_REVISION_NUMBER +#define RC_PRODUCTVERSION 2,4,0,0 #define RC_FILEVERSION2 DOTVERSIONSTR -#define RC_PRODUCTVERSION2 "2.3" +#define RC_PRODUCTVERSION2 "2.4" // Version identifier for network games. // Bump it every time you do a release unless you're certain you // didn't change anything that will affect sync. -#define NETGAMEVERSION 223 +#define NETGAMEVERSION 224 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to From 515862636a771bd882668743e35db0df3ae58d94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 07:11:39 +0000 Subject: [PATCH 171/241] - Fixed: Heretic's Weredragon (Beast) should not have a melee state. SVN r2068 (trunk) --- docs/rh-log.txt | 3 +++ wadsrc/static/actors/heretic/beast.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 7a1263930..57fdbebba 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +January 1, 2010 (Changes by Graf Zahl) +- Fixed: Heretic's Weredragon (Beast) should not have a melee state. + December 31, 2009 (Changes by Graf Zahl) - fixed: FastProjectile was missing all sky checks when the projectile's move was blocked. diff --git a/wadsrc/static/actors/heretic/beast.txt b/wadsrc/static/actors/heretic/beast.txt index c89e6a02c..7f54c3442 100644 --- a/wadsrc/static/actors/heretic/beast.txt +++ b/wadsrc/static/actors/heretic/beast.txt @@ -28,7 +28,6 @@ ACTOR Beast 70 See: BEAS ABCDEF 3 A_Chase Loop - Melee: Missile: BEAS H 10 A_FaceTarget BEAS I 10 A_CustomComboAttack("BeastBall", 32, random[BeastAttack](1,8)*3, "beast/attack") From 3f4f0a8ae4ab5a91c18b63df1049e2ec6849e495 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 09:11:55 +0000 Subject: [PATCH 172/241] SBARINFO update: - Reorganized the SBarInfo code. - Added interpolate() flag to drawnumber, drawbar, and drawgem. The old way of interpolating the health and armor is depreciated. - Added: armortype to drawswitchableimage loosely based on Gez's submission. - As an extension to the previous you can now use comparison operators on inventory items and armortype in drawswitchableimage. SVN r2069 (trunk) --- docs/rh-log.txt | 8 + src/CMakeLists.txt | 3 +- src/g_shared/sbar.h | 48 +- src/g_shared/sbar_mugshot.cpp | 18 +- src/g_shared/sbarinfo.cpp | 1303 ++++++++++++++ src/g_shared/sbarinfo.h | 339 +--- src/g_shared/sbarinfo_commands.cpp | 2574 ++++++++++++++++++++++++++++ src/g_shared/sbarinfo_display.cpp | 1765 ------------------- src/g_shared/sbarinfo_parser.cpp | 1622 ------------------ src/p_acs.cpp | 1 - zdoom.vcproj | 772 +++++---- 11 files changed, 4333 insertions(+), 4120 deletions(-) create mode 100644 src/g_shared/sbarinfo.cpp create mode 100644 src/g_shared/sbarinfo_commands.cpp delete mode 100644 src/g_shared/sbarinfo_display.cpp delete mode 100644 src/g_shared/sbarinfo_parser.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 57fdbebba..36d6d9a2e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +January 1, 2010 (SBARINFO update) +- Reorganized the SBarInfo code. +- Added interpolate() flag to drawnumber, drawbar, and drawgem. The old + way of interpolating the health and armor is depreciated. +- Added: armortype to drawswitchableimage loosely based on Gez's submission. +- As an extension to the previous you can now use comparison operators on + inventory items and armortype in drawswitchableimage. + January 1, 2010 (Changes by Graf Zahl) - Fixed: Heretic's Weredragon (Beast) should not have a melee state. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee106ffb0..3184bc6b7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -696,8 +696,7 @@ add_executable( zdoom WIN32 g_shared/a_weaponpiece.cpp g_shared/a_weapons.cpp g_shared/hudmessages.cpp - g_shared/sbarinfo_display.cpp - g_shared/sbarinfo_parser.cpp + g_shared/sbarinfo.cpp g_shared/sbar_mugshot.cpp g_shared/shared_hud.cpp g_shared/shared_sbar.cpp diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index 162947bf4..d3e72c79e 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -32,6 +32,9 @@ ** */ +#ifndef __SBAR_H__ +#define __SBAR_H__ + #include "dobject.h" #include "v_collection.h" #include "v_text.h" @@ -195,22 +198,37 @@ private: }; class player_t; -struct FMugShot +class FMugShot { - FMugShot(); - void Tick(player_t *player); - bool SetState(const char *state_name, bool wait_till_done=false, bool reset=false); - int UpdateState(player_t *player, int stateflags=0); - FTexture *GetFace(player_t *player, const char *default_face, int accuracy, int stateflags=0); + public: + enum StateFlags + { + STANDARD = 0x0, - FMugShotState *CurrentState; - int RampageTimer; - int LastDamageAngle; - int FaceHealth; - bool bEvilGrin; - bool bDamageFaceActive; - bool bNormal; - bool bOuchActive; + XDEATHFACE = 0x1, + ANIMATEDGODMODE = 0x2, + DISABLEGRIN = 0x4, + DISABLEOUCH = 0x8, + DISABLEPAIN = 0x10, + DISABLERAMPAGE = 0x20, + }; + + FMugShot(); + void Grin(bool grin=true) { bEvilGrin = grin; } + void Tick(player_t *player); + bool SetState(const char *state_name, bool wait_till_done=false, bool reset=false); + int UpdateState(player_t *player, StateFlags stateflags=STANDARD); + FTexture *GetFace(player_t *player, const char *default_face, int accuracy, StateFlags stateflags=STANDARD); + + private: + FMugShotState *CurrentState; + int RampageTimer; + int LastDamageAngle; + int FaceHealth; + bool bEvilGrin; + bool bDamageFaceActive; + bool bNormal; + bool bOuchActive; }; extern TArray MugShotStates; @@ -369,3 +387,5 @@ DBaseStatusBar *CreateCustomStatusBar(int script=0); void ST_LoadCrosshair(bool alwaysload=false); extern FTexture *CrosshairImage; + +#endif /* __SBAR_H__ */ diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp index c62e7c4d6..a41476576 100644 --- a/src/g_shared/sbar_mugshot.cpp +++ b/src/g_shared/sbar_mugshot.cpp @@ -324,7 +324,7 @@ bool FMugShot::SetState(const char *state_name, bool wait_till_done, bool reset) // //=========================================================================== -int FMugShot::UpdateState(player_t *player, int stateflags) +int FMugShot::UpdateState(player_t *player, StateFlags stateflags) { int i; angle_t badguyangle; @@ -333,7 +333,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) if (player->health > 0) { - if (bEvilGrin && !(stateflags & DRAWMUGSHOT_DISABLEGRIN)) + if (bEvilGrin && !(stateflags & DISABLEGRIN)) { if (player->bonuscount) { @@ -348,7 +348,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) if (player->damagecount && // Now go in if pain is disabled but we think ouch will be shown (and ouch is not disabled!) - (!(stateflags & DRAWMUGSHOT_DISABLEPAIN) || (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DRAWMUGSHOT_DISABLEOUCH)))) + (!(stateflags & DISABLEPAIN) || (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH)))) { int damage_angle = 1; if (player->attacker && player->attacker != player->mo) @@ -380,7 +380,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) } } bool use_ouch = false; - if (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DRAWMUGSHOT_DISABLEOUCH)) + if (((FaceHealth != -1 && FaceHealth - player->health > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH)) { use_ouch = true; full_state_name = "ouch."; @@ -407,7 +407,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) else { bool use_ouch = false; - if (((FaceHealth != -1 && player->health - FaceHealth > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DRAWMUGSHOT_DISABLEOUCH)) + if (((FaceHealth != -1 && player->health - FaceHealth > ST_MUCHPAIN) || bOuchActive) && !(stateflags & DISABLEOUCH)) { use_ouch = true; full_state_name = "ouch."; @@ -425,7 +425,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) } } - if (RampageTimer == ST_RAMPAGEDELAY && !(stateflags & DRAWMUGSHOT_DISABLERAMPAGE)) + if (RampageTimer == ST_RAMPAGEDELAY && !(stateflags & DISABLERAMPAGE)) { SetState("rampage", !bNormal); //If we have nothing better to show, use the rampage face. return 0; @@ -436,7 +436,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) bool good; if ((player->cheats & CF_GODMODE) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE)) { - good = SetState((stateflags & DRAWMUGSHOT_ANIMATEDGODMODE) ? "godanimated" : "god"); + good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god"); } else { @@ -450,7 +450,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) } else { - if (!(stateflags & DRAWMUGSHOT_XDEATHFACE) || !(player->cheats & CF_EXTREMELYDEAD)) + if (!(stateflags & XDEATHFACE) || !(player->cheats & CF_EXTREMELYDEAD)) { full_state_name = "death."; } @@ -473,7 +473,7 @@ int FMugShot::UpdateState(player_t *player, int stateflags) // //=========================================================================== -FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accuracy, int stateflags) +FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accuracy, StateFlags stateflags) { int angle = UpdateState(player, stateflags); int level = 0; diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp new file mode 100644 index 000000000..9a2fe38a4 --- /dev/null +++ b/src/g_shared/sbarinfo.cpp @@ -0,0 +1,1303 @@ +/* +** sbarinfo_display.cpp +** +** Contains all functions required for the display of custom statusbars. +** +**--------------------------------------------------------------------------- +** Copyright 2008 Braden Obrzut +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. 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. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ + +#include "doomtype.h" +#include "doomstat.h" +#include "v_font.h" +#include "v_video.h" +#include "sbar.h" +#include "r_defs.h" +#include "w_wad.h" +#include "m_random.h" +#include "d_player.h" +#include "st_stuff.h" +#include "r_local.h" +#include "m_swap.h" +#include "a_keys.h" +#include "templates.h" +#include "i_system.h" +#include "sbarinfo.h" +#include "gi.h" +#include "r_translate.h" +#include "r_main.h" +#include "a_weaponpiece.h" +#include "a_strifeglobal.h" +#include "g_level.h" +#include "v_palette.h" +#include "p_acs.h" + +#define ADJUST_RELCENTER(x, y, outX, outY) \ + if(x.RelCenter()) \ + outX = *x + SCREENWIDTH/(hud_scale ? CleanXfac*2 : 2); \ + else \ + outX = *x; \ + if(y.RelCenter()) \ + outY = *y + SCREENHEIGHT/(hud_scale ? CleanYfac*2 : 2); \ + else \ + outY = *y; + +#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6) +enum +{ + imgARTIBOX, + imgSELECTBOX, + imgCURSOR, + imgINVLFGEM1, + imgINVLFGEM2, + imgINVRTGEM1, + imgINVRTGEM2, +}; + +EXTERN_CVAR(Int, fraglimit) +EXTERN_CVAR(Int, screenblocks) +EXTERN_CVAR(Bool, vid_fps) +EXTERN_CVAR(Bool, hud_scale) + +class DSBarInfo; + +//////////////////////////////////////////////////////////////////////////////// + +/** + * This class is used to help prevent errors that may occur from adding or + * subtracting from coordinates. + * + * In order to provide the maximum flexibility, coordinates are packed into + * an int with one bit reserved for relCenter. + */ +class SBarInfoCoordinate +{ + public: + SBarInfoCoordinate &Add(int add) + { + value += add; + return *this; + } + int Coordinate() const { return value; } + bool RelCenter() const { return relCenter; } + void Set(int coord, bool center) { value = coord; relCenter = center; } + void SetCoord(int coord) { value = coord; } + void SetRelCenter(bool center) { relCenter = center; } + + int operator* () const { return Coordinate(); } + SBarInfoCoordinate operator+ (int add) const { return SBarInfoCoordinate(*this).Add(add); } + SBarInfoCoordinate operator+ (const SBarInfoCoordinate &other) const { return SBarInfoCoordinate(*this).Add(other.Coordinate()); } + SBarInfoCoordinate operator- (int sub) const { return SBarInfoCoordinate(*this).Add(-sub); } + SBarInfoCoordinate operator- (const SBarInfoCoordinate &other) const { return SBarInfoCoordinate(*this).Add(-other.Coordinate()); } + void operator+= (int add) { Add(add); } + void operator-= (int sub) { Add(-sub); } + + protected: + unsigned relCenter:1; + int value:31; +}; + +class SBarInfoMainBlock; + +//////////////////////////////////////////////////////////////////////////////// +/* There are three major classes here. The SBarInfoCommand is our root class. + * SBarInfoCommandFlowControl would be the base class for command which + * implements a sub-block. And SBarInfoMainBlock which is the root for a + * single hud (so all commands are held inside a MainBlock at some point). + * + * A MainBlock can be passed NULL for the first argument of the Draw function. + */ + +class SBarInfoCommand +{ + public: + enum Offset + { + TOP = 0x1, + VMIDDLE = 0x2, + BOTTOM = 0x4, + + LEFT = 0x10, + RIGHT = 0x20, + HMIDDLE = 0x40, + + CENTER = VMIDDLE|HMIDDLE, + CENTER_BOTTOM = BOTTOM|HMIDDLE + }; + + SBarInfoCommand(SBarInfo *script) : script(script) {} + virtual ~SBarInfoCommand() {} + + virtual void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)=0; + virtual void Parse(FScanner &sc, bool fullScreenOffsets)=0; + virtual void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) {} + + protected: + void GetCoordinates(FScanner &sc, bool fullScreenOffsets, SBarInfoCoordinate &x, SBarInfoCoordinate &y) + { + bool negative = false; + bool relCenter = false; + SBarInfoCoordinate *coords[2] = {&x, &y}; + for(int i = 0;i < 2;i++) + { + negative = false; + relCenter = false; + if(i > 0) + sc.MustGetToken(','); + + // [-]INT center + negative = sc.CheckToken('-'); + sc.MustGetToken(TK_IntConst); + coords[i]->Set(negative ? -sc.Number : sc.Number, false); + if(sc.CheckToken('+')) + { + sc.MustGetToken(TK_Identifier); + if(!sc.Compare("center")) + sc.ScriptError("Expected 'center' but got '%s' instead.", sc.String); + relCenter = true; + } + if(fullScreenOffsets) + { + coords[i]->SetRelCenter(relCenter); + } + } + + if(!fullScreenOffsets) + y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - script->height)); + } + EColorRange GetTranslation(FScanner &sc) + { + sc.MustGetToken(TK_Identifier); + EColorRange returnVal = CR_UNTRANSLATED; + FString namedTranslation; //we must send in "[translation]" + const BYTE *trans_ptr; + namedTranslation.Format("[%s]", sc.String); + trans_ptr = (const BYTE *)(&namedTranslation[0]); + if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED) + { + sc.ScriptError("Missing definition for color %s.", sc.String); + } + return returnVal; + } + + SBarInfo *script; +}; + +class SBarInfoCommandFlowControl : public SBarInfoCommand +{ + public: + SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script) {} + ~SBarInfoCommandFlowControl() + { + for(unsigned int i = 0;i < commands.Size();i++) + delete commands[i]; + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + for(unsigned int i = 0;i < commands.Size();i++) + commands[i]->Draw(block, statusBar); + } + int NumCommands() const { return commands.Size(); } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken('{'); + SBarInfoCommand *cmd = NULL; + while((cmd = NextCommand(sc)) != NULL) + { + cmd->Parse(sc, fullScreenOffsets); + commands.Push(cmd); + } + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + for(unsigned int i = 0;i < commands.Size();i++) + commands[i]->Tick(block, statusBar, hudChanged); + } + + private: + SBarInfoCommand *NextCommand(FScanner &sc); + + TArray commands; +}; + +class SBarInfoMainBlock : public SBarInfoCommandFlowControl +{ + public: + SBarInfoMainBlock(SBarInfo *script) : SBarInfoCommandFlowControl(script), + alpha(FRACUNIT), forceScaled(false), fullScreenOffsets(false) + { + } + + int Alpha() const { return alpha; } + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, int xOffset, int yOffset, int alpha) + { + this->xOffset = xOffset; + this->yOffset = yOffset; + this->alpha = alpha; + SBarInfoCommandFlowControl::Draw(this, statusBar); + } + bool ForceScaled() const { return forceScaled; } + bool FullScreenOffsets() const { return fullScreenOffsets; } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + this->fullScreenOffsets = fullScreenOffsets; + if(sc.CheckToken(',')) + { + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("forcescaled")) + forceScaled = true; + else if(sc.Compare("fullscreenoffsets")) + this->fullScreenOffsets = true; + else + sc.ScriptError("Unkown flag '%s'.", sc.String); + if(!sc.CheckToken('|') && !sc.CheckToken(',')) + { + SBarInfoCommandFlowControl::Parse(sc, this->fullScreenOffsets); + return; + } + } + sc.MustGetToken(TK_FloatConst); + alpha = fixed_t(FRACUNIT * sc.Float); + } + SBarInfoCommandFlowControl::Parse(sc, this->fullScreenOffsets); + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { SBarInfoCommandFlowControl::Tick(this, statusBar, hudChanged); } + int XOffset() const { return xOffset; } + int YOffset() const { return yOffset; } + + private: + int alpha; + bool forceScaled; + bool fullScreenOffsets; + int xOffset; + int yOffset; +}; + +//////////////////////////////////////////////////////////////////////////////// + +SBarInfo *SBarInfoScript[2] = {NULL,NULL}; + +enum //Key words +{ + SBARINFO_BASE, + SBARINFO_HEIGHT, + SBARINFO_INTERPOLATEHEALTH, + SBARINFO_INTERPOLATEARMOR, + SBARINFO_COMPLETEBORDER, + SBARINFO_MONOSPACEFONTS, + SBARINFO_LOWERHEALTHCAP, + SBARINFO_STATUSBAR, + SBARINFO_MUGSHOT, + SBARINFO_CREATEPOPUP, +}; + +enum //Bar types +{ + STBAR_NONE, + STBAR_FULLSCREEN, + STBAR_NORMAL, + STBAR_AUTOMAP, + STBAR_INVENTORY, + STBAR_INVENTORYFULLSCREEN, + STBAR_POPUPLOG, + STBAR_POPUPKEYS, + STBAR_POPUPSTATUS, +}; + +static const char *SBarInfoTopLevel[] = +{ + "base", + "height", + "interpolatehealth", + "interpolatearmor", + "completeborder", + "monospacefonts", + "lowerhealthcap", + "statusbar", + "mugshot", + "createpopup", + NULL +}; + +static const char *StatusBars[] = +{ + "none", + "fullscreen", + "normal", + "automap", + "inventory", + "inventoryfullscreen", + "popuplog", + "popupkeys", + "popupstatus", + NULL +}; + +static void FreeSBarInfoScript() +{ + for(int i = 0;i < 2;i++) + { + if (SBarInfoScript[i] != NULL) + { + delete SBarInfoScript[i]; + SBarInfoScript[i] = NULL; + } + } +} + +void SBarInfo::Load() +{ + if(gameinfo.statusbar.IsNotEmpty()) + { + int lump = Wads.CheckNumForFullName(gameinfo.statusbar, true); + if(lump != -1) + { + Printf ("ParseSBarInfo: Loading default status bar definition.\n"); + if(SBarInfoScript[SCRIPT_DEFAULT] == NULL) + SBarInfoScript[SCRIPT_DEFAULT] = new SBarInfo(lump); + else + SBarInfoScript[SCRIPT_DEFAULT]->ParseSBarInfo(lump); + } + } + + if(Wads.CheckNumForName("SBARINFO") != -1) + { + Printf ("ParseSBarInfo: Loading custom status bar definition.\n"); + int lastlump, lump; + lastlump = 0; + while((lump = Wads.FindLump("SBARINFO", &lastlump)) != -1) + { + if(SBarInfoScript[SCRIPT_CUSTOM] == NULL) + SBarInfoScript[SCRIPT_CUSTOM] = new SBarInfo(lump); + else //We now have to load multiple SBarInfo Lumps so the 2nd time we need to use this method instead. + SBarInfoScript[SCRIPT_CUSTOM]->ParseSBarInfo(lump); + } + } + atterm(FreeSBarInfoScript); +} + +//SBarInfo Script Reader +void SBarInfo::ParseSBarInfo(int lump) +{ + gameType = gameinfo.gametype; + bool baseSet = false; + FScanner sc(lump); + sc.SetCMode(true); + while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include)) + { + if(sc.TokenType == TK_Include) + { + sc.MustGetToken(TK_StringConst); + int lump = Wads.CheckNumForFullName(sc.String, true); + if (lump == -1) + sc.ScriptError("Lump '%s' not found", sc.String); + ParseSBarInfo(lump); + continue; + } + switch(sc.MustMatchString(SBarInfoTopLevel)) + { + case SBARINFO_BASE: + baseSet = true; + if(!sc.CheckToken(TK_None)) + sc.MustGetToken(TK_Identifier); + if(sc.Compare("Doom")) + { + int lump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true); + if(lump == -1) + sc.ScriptError("Standard Doom Status Bar not found."); + ParseSBarInfo(lump); + } + else if(sc.Compare("Heretic")) + gameType = GAME_Heretic; + else if(sc.Compare("Hexen")) + gameType = GAME_Hexen; + else if(sc.Compare("Strife")) + gameType = GAME_Strife; + else if(sc.Compare("None")) + gameType = GAME_Any; + else + sc.ScriptError("Bad game name: %s", sc.String); + sc.MustGetToken(';'); + break; + case SBARINFO_HEIGHT: + sc.MustGetToken(TK_IntConst); + this->height = sc.Number; + sc.MustGetToken(';'); + break; + case SBARINFO_INTERPOLATEHEALTH: //mimics heretics interpolated health values. + if(sc.CheckToken(TK_True)) + { + interpolateHealth = true; + } + else + { + sc.MustGetToken(TK_False); + interpolateHealth = false; + } + if(sc.CheckToken(',')) //speed param + { + sc.MustGetToken(TK_IntConst); + this->interpolationSpeed = sc.Number; + } + sc.MustGetToken(';'); + break; + case SBARINFO_INTERPOLATEARMOR: //Since interpolatehealth is such a popular command + if(sc.CheckToken(TK_True)) + { + interpolateArmor = true; + } + else + { + sc.MustGetToken(TK_False); + interpolateArmor = false; + } + if(sc.CheckToken(',')) //speed + { + sc.MustGetToken(TK_IntConst); + this->armorInterpolationSpeed = sc.Number; + } + sc.MustGetToken(';'); + break; + case SBARINFO_COMPLETEBORDER: //draws the border instead of an HOM + if(sc.CheckToken(TK_True)) + { + completeBorder = true; + } + else + { + sc.MustGetToken(TK_False); + completeBorder = false; + } + sc.MustGetToken(';'); + break; + case SBARINFO_MONOSPACEFONTS: + if(sc.CheckToken(TK_True)) + { + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); + spacingCharacter = sc.String[0]; + } + else + { + sc.MustGetToken(TK_False); + spacingCharacter = '\0'; + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); //Don't tell anyone we're just ignoring this ;) + } + sc.MustGetToken(';'); + break; + case SBARINFO_LOWERHEALTHCAP: + if(sc.CheckToken(TK_False)) + { + lowerHealthCap = false; + } + else + { + sc.MustGetToken(TK_True); + lowerHealthCap = true; + } + sc.MustGetToken(';'); + break; + case SBARINFO_STATUSBAR: + { + if(!baseSet) //If the user didn't explicitly define a base, do so now. + gameType = GAME_Any; + int barNum = 0; + if(!sc.CheckToken(TK_None)) + { + sc.MustGetToken(TK_Identifier); + barNum = sc.MustMatchString(StatusBars); + } + this->huds[barNum] = new SBarInfoMainBlock(this); + if(barNum == STBAR_AUTOMAP) + { + automapbar = true; + } + this->huds[barNum]->Parse(sc, false); + break; + } + case SBARINFO_MUGSHOT: + { + sc.MustGetToken(TK_StringConst); + FMugShotState state(sc.String); + if(sc.CheckToken(',')) //first loop must be a comma + { + do + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("health")) + state.bUsesLevels = true; + else if(sc.Compare("health2")) + state.bUsesLevels = state.bHealth2 = true; + else if(sc.Compare("healthspecial")) + state.bUsesLevels = state.bHealthSpecial = true; + else if(sc.Compare("directional")) + state.bDirectional = true; + else + sc.ScriptError("Unknown MugShot state flag '%s'.", sc.String); + } + while(sc.CheckToken(',') || sc.CheckToken('|')); + } + ParseMugShotBlock(sc, state); + int index; + if((index = FindMugShotStateIndex(state.State)) != -1) //We already had this state, remove the old one. + { + MugShotStates.Delete(index); + } + MugShotStates.Push(state); + break; + } + case SBARINFO_CREATEPOPUP: + { + int pop = 0; + sc.MustGetToken(TK_Identifier); + if(sc.Compare("log")) + pop = 0; + else if(sc.Compare("keys")) + pop = 1; + else if(sc.Compare("status")) + pop = 2; + else + sc.ScriptError("Unkown popup: '%s'", sc.String); + Popup &popup = popups[pop]; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.width = sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.height = sc.Number; + sc.MustGetToken(','); + if(!sc.CheckToken(TK_None)) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("slideinbottom")) + { + popup.transition = Popup::TRANSITION_SLIDEINBOTTOM; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + popup.speed = sc.Number; + } + else if(sc.Compare("fade")) + { + popup.transition = Popup::TRANSITION_FADE; + sc.MustGetToken(','); + sc.MustGetToken(TK_FloatConst); + popup.speed = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float))); + sc.MustGetToken(','); + sc.MustGetToken(TK_FloatConst); + popup.speed2 = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float))); + } + else + sc.ScriptError("Unkown transition type: '%s'", sc.String); + } + popup.init(); + sc.MustGetToken(';'); + break; + } + } + } +} + +void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state) +{ + sc.MustGetToken('{'); + while(!sc.CheckToken('}')) + { + FMugShotFrame frame; + bool multiframe = false; + if(sc.CheckToken('{')) + multiframe = true; + do + { + sc.MustGetToken(TK_Identifier); + if(strlen(sc.String) > 5) + sc.ScriptError("MugShot frames cannot exceed 5 characters."); + frame.Graphic.Push(sc.String); + } + while(multiframe && sc.CheckToken(',')); + if(multiframe) + sc.MustGetToken('}'); + bool negative = sc.CheckToken('-'); + sc.MustGetToken(TK_IntConst); + frame.Delay = (negative ? -1 : 1)*sc.Number; + sc.MustGetToken(';'); + state.Frames.Push(frame); + } +} + +int SBarInfo::newImage(const char *patchname) +{ + if(patchname[0] == '\0' || stricmp(patchname, "nullimage") == 0) + { + return -1; + } + for(unsigned int i = 0;i < this->Images.Size();i++) //did we already load it? + { + if(stricmp(this->Images[i], patchname) == 0) + { + return i; + } + } + return this->Images.Push(patchname); +} + +SBarInfo::SBarInfo() //make results more predicable +{ + Init(); +} + +SBarInfo::SBarInfo(int lumpnum) +{ + Init(); + ParseSBarInfo(lumpnum); +} + +void SBarInfo::Init() +{ + automapbar = false; + interpolateHealth = false; + interpolateArmor = false; + completeBorder = false; + lowerHealthCap = true; + interpolationSpeed = 8; + armorInterpolationSpeed = 8; + height = 0; + spacingCharacter = '\0'; + + for(unsigned int i = 0;i < NUMHUDS;i++) + huds[i] = new SBarInfoMainBlock(this); +} + +SBarInfo::~SBarInfo() +{ + for (size_t i = 0; i < NUMHUDS; ++i) + { + delete huds[i]; +// huds[i].commands.Clear(); + } +} + +//Popup +Popup::Popup() +{ + transition = TRANSITION_NONE; + height = 320; + width = 200; + speed = 0; + x = 320; + y = 200; + alpha = FRACUNIT; + opened = false; + moving = false; +} + +void Popup::init() +{ + x = width; + y = height; + if(transition == TRANSITION_SLIDEINBOTTOM) + { + x = 0; + } + else if(transition == TRANSITION_FADE) + { + alpha = 0; + x = 0; + y = 0; + } +} + +void Popup::tick() +{ + if(transition == TRANSITION_SLIDEINBOTTOM) + { + if(moving) + { + if(opened) + y -= clamp(height + (y - height), 1, speed); + else + y += clamp(height - y, 1, speed); + } + if(y != 0 && y != height) + moving = true; + else + moving = false; + } + else if(transition == TRANSITION_FADE) + { + if(moving) + { + if(opened) + alpha = clamp(alpha + speed, 0, FRACUNIT); + else + alpha = clamp(alpha - speed2, 0, FRACUNIT); + } + if(alpha == 0 || alpha == FRACUNIT) + moving = false; + else + moving = true; + } + else + { + if(opened) + { + y = 0; + x = 0; + } + else + { + y = height; + x = width; + } + moving = false; + } +} + +bool Popup::isDoneMoving() +{ + return !moving; +} + +int Popup::getXOffset() +{ + return x; +} + +int Popup::getYOffset() +{ + return y; +} + +int Popup::getAlpha(int maxAlpha) +{ + double a = (double) alpha / (double) FRACUNIT; + double b = (double) maxAlpha / (double) FRACUNIT; + return fixed_t((a * b) * FRACUNIT); +} + +void Popup::open() +{ + opened = true; + moving = true; +} + +void Popup::close() +{ + opened = false; + moving = true; +} + +//////////////////////////////////////////////////////////////////////////////// + +class DSBarInfo : public DBaseStatusBar +{ + DECLARE_CLASS(DSBarInfo, DBaseStatusBar) +public: + DSBarInfo (SBarInfo *script=NULL) : DBaseStatusBar(script->height), + ammo1(NULL), ammo2(NULL), ammocount1(0), ammocount2(0), armor(NULL), + pendingPopup(POP_None), currentPopup(POP_None), lastHud(0), + lastInventoryBar(NULL), lastPopup(NULL) + { + this->script = script; + + static const char *InventoryBarLumps[] = + { + "ARTIBOX", "SELECTBO", "INVCURS", "INVGEML1", + "INVGEML2", "INVGEMR1", "INVGEMR2", + "USEARTIA", "USEARTIB", "USEARTIC", "USEARTID", + }; + TArray patchnames; + patchnames.Resize(script->Images.Size()+10); + unsigned int i = 0; + for(i = 0;i < script->Images.Size();i++) + { + patchnames[i] = script->Images[i]; + } + for(i = 0;i < 10;i++) + { + patchnames[i+script->Images.Size()] = InventoryBarLumps[i]; + } + for (i = 0;i < numskins;i++) + { + AddFaceToImageCollection (&skins[i], &Images); + } + invBarOffset = script->Images.Size(); + Images.Init(&patchnames[0], patchnames.Size()); + } + + ~DSBarInfo () + { + Images.Uninit(); + } + + void Draw (EHudState state) + { + DBaseStatusBar::Draw(state); + int hud = STBAR_NORMAL; + if(state == HUD_StatusBar) + { + if(script->completeBorder) //Fill the statusbar with the border before we draw. + { + FTexture *b = TexMan[gameinfo.border->b]; + R_DrawBorder(viewwindowx, viewwindowy + viewheight + b->GetHeight(), viewwindowx + viewwidth, SCREENHEIGHT); + if(screenblocks == 10) + screen->FlatFill(viewwindowx, viewwindowy + viewheight, viewwindowx + viewwidth, viewwindowy + viewheight + b->GetHeight(), b, true); + } + if(script->automapbar && automapactive) + { + hud = STBAR_AUTOMAP; + } + else + { + hud = STBAR_NORMAL; + } + } + else if(state == HUD_Fullscreen) + { + hud = STBAR_FULLSCREEN; + } + else + { + hud = STBAR_NONE; + } + bool oldhud_scale = hud_scale; + if(script->huds[hud]->ForceScaled()) //scale the statusbar + { + SetScaled(true, true); + setsizeneeded = true; + if(script->huds[hud]->FullScreenOffsets()) + hud_scale = true; + } + + //prepare ammo counts + GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2); + armor = CPlayer->mo->FindInventory(); + if(hud != lastHud) + script->huds[hud]->Tick(NULL, this, true); + script->huds[hud]->Draw(NULL, this, 0, 0, FRACUNIT); + lastHud = hud; + if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR) && (state == HUD_StatusBar || state == HUD_Fullscreen)) + { + SBarInfoMainBlock *inventoryBar = state == HUD_StatusBar ? script->huds[STBAR_INVENTORY] : script->huds[STBAR_INVENTORYFULLSCREEN]; + if(inventoryBar != lastInventoryBar) + inventoryBar->Tick(NULL, this, true); + + // No overlay? Lets cancel it. + if(inventoryBar->NumCommands() == 0) + CPlayer->inventorytics = 0; + else + inventoryBar->Draw(NULL, this, 0, 0, FRACUNIT); + } + if(currentPopup != POP_None) + { + int popbar = 0; + if(currentPopup == POP_Log) + popbar = STBAR_POPUPLOG; + else if(currentPopup == POP_Keys) + popbar = STBAR_POPUPKEYS; + else if(currentPopup == POP_Status) + popbar = STBAR_POPUPSTATUS; + if(script->huds[popbar] != lastPopup) + { + lastPopup = script->huds[popbar]; + lastPopup->Tick(NULL, this, true); + } + + script->huds[popbar]->Draw(NULL, this, script->popups[currentPopup-1].getXOffset(), script->popups[currentPopup-1].getYOffset(), script->popups[currentPopup-1].getAlpha()); + } + else + lastPopup = NULL; + if(script->huds[hud]->ForceScaled() && script->huds[hud]->FullScreenOffsets()) + hud_scale = oldhud_scale; + } + + void NewGame () + { + if (CPlayer != NULL) + { + AttachToPlayer (CPlayer); + } + } + + void SetMugShotState (const char *state_name, bool wait_till_done, bool reset) + { + script->MugShot.SetState(state_name, wait_till_done, reset); + } + + void Tick () + { + DBaseStatusBar::Tick(); + + script->MugShot.Tick(CPlayer); + if(currentPopup != POP_None) + { + script->popups[currentPopup-1].tick(); + if(script->popups[currentPopup-1].opened == false && script->popups[currentPopup-1].isDoneMoving()) + { + currentPopup = pendingPopup; + if(currentPopup != POP_None) + script->popups[currentPopup-1].open(); + } + + lastPopup->Tick(NULL, this, false); + } + + script->huds[lastHud]->Tick(NULL, this, false); + if(lastInventoryBar != NULL && CPlayer->inventorytics > 0) + lastInventoryBar->Tick(NULL, this, false); + } + + void ReceivedWeapon(AWeapon *weapon) + { + script->MugShot.Grin(); + } + + // void DSBarInfo::FlashItem(const PClass *itemtype) - Is defined with CommandDrawSelectedInventory + void FlashItem(const PClass *itemtype); + + void ShowPop(int popnum) + { + DBaseStatusBar::ShowPop(popnum); + if(popnum != currentPopup) + { + pendingPopup = popnum; + } + else + pendingPopup = POP_None; + if(currentPopup != POP_None) + script->popups[currentPopup-1].close(); + else + { + currentPopup = pendingPopup; + pendingPopup = POP_None; + if(currentPopup != POP_None) + script->popups[currentPopup-1].open(); + } + } + + //draws an image with the specified flags + void DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool translate=false, bool dim=false, int offsetflags=0, bool alphaMap=false, int forceWidth=-1, int forceHeight=-1, fixed_t cx=0, fixed_t cy=0, fixed_t cr=0, fixed_t cb=0, bool clearDontDraw=false) const + { + if (texture == NULL) + return; + + if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER) + { + x -= (texture->GetScaledWidth()/2)-texture->LeftOffset; + y -= (texture->GetScaledHeight()/2)-texture->TopOffset; + } + + x += xOffset; + y += yOffset; + int w, h; + if(!fullScreenOffsets) + { + fixed_t tmp = 0; + // I'll handle the conversion from fixed to int myself for more control + fixed_t fx = (x + ST_X).Coordinate() << FRACBITS; + fixed_t fy = (y + ST_Y).Coordinate() << FRACBITS; + fixed_t fw = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth) << FRACBITS; + fixed_t fh = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight) << FRACBITS; + fixed_t fcx = cx == 0 ? 0 : fx + cx - (texture->GetScaledLeftOffset() << FRACBITS); + fixed_t fcy = cy == 0 ? 0 : fy + cy - (texture->GetScaledTopOffset() << FRACBITS); + fixed_t fcr = fx + fw - cr; + fixed_t fcb = fy + fh - cb; + if(Scaled) + { + if(cx != 0 || cy != 0) + screen->VirtualToRealCoordsFixed(fcx, fcy, tmp, tmp, 320, 200, true); + if(cr != 0 || cb != 0 || clearDontDraw) + screen->VirtualToRealCoordsFixed(fcr, fcb, tmp, tmp, 320, 200, true); + screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true); + } + // Round to nearest + w = (fw + (FRACUNIT>>1)) >> FRACBITS; + h = (fh + (FRACUNIT>>1)) >> FRACBITS; + cr = cr != 0 ? fcr >> FRACBITS : INT_MAX; + cb = cb != 0 ? fcb >> FRACBITS : INT_MAX; + if(clearDontDraw) + screen->Clear(MAX(fx, fcx)>>FRACBITS, MAX(fy, fcy)>>FRACBITS, fcr>>FRACBITS, fcb>>FRACBITS, GPalette.BlackIndex, 0); + else + { + if(alphaMap) + { + screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS), + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_ClipLeft, fcx>>FRACBITS, + DTA_ClipTop, fcy>>FRACBITS, + DTA_ClipRight, cr, + DTA_ClipBottom, cb, + DTA_Translation, translate ? GetTranslation() : 0, + DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, + DTA_Alpha, alpha, + DTA_AlphaChannel, alphaMap, + DTA_FillColor, 0, + TAG_DONE); + } + else + { + screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS), + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_ClipLeft, fcx>>FRACBITS, + DTA_ClipTop, fcy>>FRACBITS, + DTA_ClipRight, cr, + DTA_ClipBottom, cb, + DTA_Translation, translate ? GetTranslation() : 0, + DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, + DTA_Alpha, alpha, + TAG_DONE); + } + } + } + else + { + int rx, ry, rcx=0, rcy=0, rcr=INT_MAX, rcb=INT_MAX; + ADJUST_RELCENTER(x,y,rx,ry) + + w = (forceWidth <= -1 ? texture->GetScaledWidth() : forceWidth); + h = (forceHeight <= -1 ? texture->GetScaledHeight() : forceHeight); + if(vid_fps && rx < 0 && ry >= 0) + ry += 10; + + // Check for clipping + if(cx != 0 || cy != 0 || cr != 0 || cb != 0) + { + rcx = cx == 0 ? 0 : rx+(cx>>FRACBITS); + rcy = cy == 0 ? 0 : ry+(cy>>FRACBITS); + rcr = cr == 0 ? INT_MAX : rx+w-(cr>>FRACBITS); + rcb = cb == 0 ? INT_MAX : ry+h-(cb>>FRACBITS); + // Fix the clipping for fullscreenoffsets. + if(ry < 0) + { + if(rcy != 0) + rcy = hud_scale ? SCREENHEIGHT + (rcy*CleanYfac) : SCREENHEIGHT + rcy; + if(rcb != INT_MAX) + rcb = hud_scale ? SCREENHEIGHT + (rcb*CleanYfac) : SCREENHEIGHT + rcb; + } + else if(hud_scale) + { + rcy *= CleanYfac; + if(rcb != INT_MAX) + rcb *= CleanYfac; + } + if(rx < 0) + { + if(rcx != 0) + rcx = hud_scale ? SCREENWIDTH + (rcx*CleanXfac) : SCREENWIDTH + rcx; + if(rcr != INT_MAX) + rcr = hud_scale ? SCREENWIDTH + (rcr*CleanXfac) : SCREENWIDTH + rcr; + } + else if(hud_scale) + { + rcx *= CleanXfac; + if(rcr != INT_MAX) + rcr *= CleanXfac; + } + } + + if(clearDontDraw) + { + screen->Clear(rcx, rcy, MIN(rcr, w*(hud_scale ? CleanXfac : 1)), MIN(rcb, h*(hud_scale ? CleanYfac : 1)), GPalette.BlackIndex, 0); + } + else + { + if(alphaMap) + { + screen->DrawTexture(texture, rx, ry, + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_ClipLeft, rcx, + DTA_ClipTop, rcy, + DTA_ClipRight, rcr, + DTA_ClipBottom, rcb, + DTA_Translation, translate ? GetTranslation() : 0, + DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, + DTA_HUDRules, HUD_Normal, + DTA_Alpha, alpha, + DTA_AlphaChannel, alphaMap, + DTA_FillColor, 0, + TAG_DONE); + } + else + { + screen->DrawTexture(texture, rx, ry, + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_ClipLeft, rcx, + DTA_ClipTop, rcy, + DTA_ClipRight, rcr, + DTA_ClipBottom, rcb, + DTA_Translation, translate ? GetTranslation() : 0, + DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, + DTA_HUDRules, HUD_Normal, + DTA_Alpha, alpha, + TAG_DONE); + } + } + } + } + + void DrawString(FFont *font, const char* str, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool drawshadow=false) const + { + x += spacing; + int ax = *x; + int ay = *y; + if(fullScreenOffsets) + { + ADJUST_RELCENTER(x,y,ax,ay) + } + while(*str != '\0') + { + if(*str == ' ') + { + ax += font->GetSpaceWidth(); + str++; + continue; + } + int width; + if(script->spacingCharacter == '\0') //No monospace? + width = font->GetCharWidth((int) *str); + else + width = font->GetCharWidth((int) script->spacingCharacter); + FTexture* character = font->GetChar((int) *str, &width); + if(character == NULL) //missing character. + { + str++; + continue; + } + if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset + ax += (character->LeftOffset+1); //ignore x offsets since we adapt to character size + + int rx, ry, rw, rh; + rx = ax + xOffset; + ry = ay + yOffset; + rw = character->GetScaledWidth(); + rh = character->GetScaledHeight(); + if(!fullScreenOffsets) + { + rx += ST_X; + ry += ST_Y; + if(Scaled) + screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); + } + else + { + if(vid_fps && ax < 0 && ay >= 0) + ry += 10; + } + if(drawshadow) + { + int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT); + if(!fullScreenOffsets) + { + screen->DrawTexture(character, rx+2, ry+2, + DTA_DestWidth, rw, + DTA_DestHeight, rh, + DTA_Alpha, salpha, + DTA_FillColor, 0, + TAG_DONE); + } + else + { + screen->DrawTexture(character, rx+2, ry+2, + DTA_DestWidth, rw, + DTA_DestHeight, rh, + DTA_Alpha, salpha, + DTA_HUDRules, HUD_Normal, + DTA_FillColor, 0, + TAG_DONE); + } + } + if(!fullScreenOffsets) + { + screen->DrawTexture(character, rx, ry, + DTA_DestWidth, rw, + DTA_DestHeight, rh, + DTA_Translation, font->GetColorTranslation(translation), + DTA_Alpha, alpha, + TAG_DONE); + } + else + { + screen->DrawTexture(character, rx, ry, + DTA_DestWidth, rw, + DTA_DestHeight, rh, + DTA_Translation, font->GetColorTranslation(translation), + DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, + TAG_DONE); + } + if(script->spacingCharacter == '\0') + ax += width + spacing - (character->LeftOffset+1); + else //width gets changed at the call to GetChar() + ax += font->GetCharWidth((int) script->spacingCharacter) + spacing; + str++; + } + } + + FRemapTable* GetTranslation() const + { + if(gameinfo.gametype & GAME_Raven) + return translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)]; + return translationtables[TRANSLATION_Players][int(CPlayer - players)]; + } + + AAmmo *ammo1, *ammo2; + int ammocount1, ammocount2; + ABasicArmor *armor; + FImageCollection Images; + unsigned int invBarOffset; + +private: + SBarInfo *script; + int pendingPopup; + int currentPopup; + int lastHud; + SBarInfoMainBlock *lastInventoryBar; + SBarInfoMainBlock *lastPopup; +}; + +IMPLEMENT_CLASS(DSBarInfo); + +DBaseStatusBar *CreateCustomStatusBar (int script) +{ + if(SBarInfoScript[script] == NULL) + I_FatalError("Tried to create a status bar with no script!"); + return new DSBarInfo(SBarInfoScript[script]); +} + +#include "sbarinfo_commands.cpp" diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index ef36c50c5..b10eb440b 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -37,57 +37,24 @@ #define __SBarInfo_SBAR_H__ #include "tarray.h" -#include "v_collection.h" #define NUMHUDS 9 #define NUMPOPUPS 3 -class FBarTexture; class FScanner; -/** - * This class is used to help prevent errors that may occur from adding or - * subtracting from coordinates. - * - * In order to provide the maximum flexibility, coordinates are packed into - * an int with one bit reserved for relCenter. - */ -class SBarInfoCoordinate -{ - public: - SBarInfoCoordinate &Add(int add); - int Coordinate() const { return value; } - bool RelCenter() const { return relCenter; } - void Set(int coord, bool center) { value = coord; relCenter = center; } - void SetCoord(int coord) { value = coord; } - void SetRelCenter(bool center) { relCenter = center; } - - int operator* () const { return Coordinate(); } - SBarInfoCoordinate operator+ (int add) const { return SBarInfoCoordinate(*this).Add(add); } - SBarInfoCoordinate operator+ (const SBarInfoCoordinate &other) const { return SBarInfoCoordinate(*this).Add(other.Coordinate()); } - SBarInfoCoordinate operator- (int sub) const { return SBarInfoCoordinate(*this).Add(-sub); } - SBarInfoCoordinate operator- (const SBarInfoCoordinate &other) const { return SBarInfoCoordinate(*this).Add(-other.Coordinate()); } - void operator+= (int add) { Add(add); } - void operator-= (int sub) { Add(-sub); } - - protected: - unsigned relCenter:1; - int value:31; -}; - -struct SBarInfoCommand; //we need to be able to use this before it is defined. -struct MugShotState; +class SBarInfoMainBlock; //Popups! -enum PopupTransition -{ - TRANSITION_NONE, - TRANSITION_SLIDEINBOTTOM, - TRANSITION_FADE, -}; - struct Popup { + enum PopupTransition + { + TRANSITION_NONE, + TRANSITION_SLIDEINBOTTOM, + TRANSITION_FADE, + }; + PopupTransition transition; bool opened; bool moving; @@ -110,54 +77,10 @@ struct Popup int getAlpha(int maxAlpha=FRACUNIT); }; -//SBarInfo -struct SBarInfoBlock -{ - TArray commands; - bool forceScaled; - bool fullScreenOffsets; - int alpha; - - SBarInfoBlock(); -}; - -struct SBarInfoCommand -{ - SBarInfoCommand(); - ~SBarInfoCommand(); - void setString(FScanner &sc, const char* source, int strnum, int maxlength=-1, bool exact=false); - - int type; - int special; - union - { - int special2; - SBarInfoCoordinate sbcoord2; - }; - union - { - int special3; - SBarInfoCoordinate sbcoord3; - }; - int special4; - int flags; - SBarInfoCoordinate x; - SBarInfoCoordinate y; - int value; - int image_index; - FTextureID sprite_index; - FString string[2]; - FFont *font; - EColorRange translation; - EColorRange translation2; - EColorRange translation3; - SBarInfoBlock subBlock; //for type SBarInfo_CMD_GAMEMODE -}; - struct SBarInfo { TArray Images; - SBarInfoBlock huds[NUMHUDS]; + SBarInfoMainBlock *huds[NUMHUDS]; Popup popups[NUMPOPUPS]; bool automapbar; bool interpolateHealth; @@ -169,16 +92,13 @@ struct SBarInfo int armorInterpolationSpeed; int height; int gameType; + FMugShot MugShot; int GetGameType() { return gameType; } void ParseSBarInfo(int lump); - void ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block); void ParseMugShotBlock(FScanner &sc, FMugShotState &state); - void getCoordinates(FScanner &sc, bool fullScreenOffsets, SBarInfoCoordinate &x, SBarInfoCoordinate &y); //retrieves the next two arguments as x and y. - int getSignedInteger(FScanner &sc); //returns a signed integer. int newImage(const char* patchname); void Init(); - EColorRange GetTranslation(FScanner &sc, const char* translation); SBarInfo(); SBarInfo(int lumpnum); ~SBarInfo(); @@ -190,243 +110,4 @@ struct SBarInfo #define SCRIPT_DEFAULT 1 extern SBarInfo *SBarInfoScript[2]; -// Enums used between the parser and the display -enum //gametype flags -{ - GAMETYPE_SINGLEPLAYER = 1, - GAMETYPE_COOPERATIVE = 2, - GAMETYPE_DEATHMATCH = 4, - GAMETYPE_TEAMGAME = 8, -}; - -enum //drawimage flags -{ - DRAWIMAGE_PLAYERICON = 0x1, - DRAWIMAGE_AMMO1 = 0x2, - DRAWIMAGE_AMMO2 = 0x4, - DRAWIMAGE_INVENTORYICON = 0x8, - DRAWIMAGE_TRANSLATABLE = 0x10, - DRAWIMAGE_WEAPONSLOT = 0x20, - DRAWIMAGE_SWITCHABLE_AND = 0x40, - DRAWIMAGE_INVULNERABILITY = 0x80, - DRAWIMAGE_OFFSET_CENTER = 0x100, - DRAWIMAGE_OFFSET_CENTERBOTTOM = 0x200, - DRAWIMAGE_ARMOR = 0x800, - DRAWIMAGE_WEAPONICON = 0x1000, - DRAWIMAGE_SIGIL = 0x2000, - DRAWIMAGE_KEYSLOT = 0x4000, - DRAWIMAGE_HEXENARMOR = 0x8000, - - DRAWIMAGE_OFFSET = DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM, -}; - -enum //drawnumber flags -{ - DRAWNUMBER_HEALTH = 0x1, - DRAWNUMBER_ARMOR = 0x2, - DRAWNUMBER_AMMO1 = 0x4, - DRAWNUMBER_AMMO2 = 0x8, - DRAWNUMBER_AMMO = 0x10, - DRAWNUMBER_AMMOCAPACITY = 0x20, - DRAWNUMBER_FRAGS = 0x40, - DRAWNUMBER_INVENTORY = 0x80, - DRAWNUMBER_KILLS = 0x100, - DRAWNUMBER_MONSTERS = 0x200, - DRAWNUMBER_ITEMS = 0x400, - DRAWNUMBER_TOTALITEMS = 0x800, - DRAWNUMBER_SECRETS = 0x1000, - DRAWNUMBER_TOTALSECRETS = 0x2000, - DRAWNUMBER_ARMORCLASS = 0x4000, - DRAWNUMBER_GLOBALVAR = 0x8000, - DRAWNUMBER_GLOBALARRAY = 0x10000, - DRAWNUMBER_FILLZEROS = 0x20000, - DRAWNUMBER_WHENNOTZERO = 0x40000, - DRAWNUMBER_POWERUPTIME = 0x80000, - DRAWNUMBER_DRAWSHADOW = 0x100000, - DRAWNUMBER_AIRTIME = 0x200000, -}; - -enum //drawbar flags (will go into special2) -{ - DRAWBAR_HORIZONTAL = 1, - DRAWBAR_REVERSE = 2, - DRAWBAR_COMPAREDEFAULTS = 4, -}; - -enum //drawselectedinventory flags -{ - DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY = 0x1, - DRAWSELECTEDINVENTORY_ARTIFLASH = 0x2, - DRAWSELECTEDINVENTORY_ALWAYSSHOWCOUNTER = 0x4, - DRAWSELECTEDINVENTORY_CENTER = 0x8, - DRAWSELECTEDINVENTORY_CENTERBOTTOM = 0x10, - DRAWSELECTEDINVENTORY_DRAWSHADOW = 0x20, -}; - -enum //drawinventorybar flags -{ - DRAWINVENTORYBAR_ALWAYSSHOW = 0x1, - DRAWINVENTORYBAR_NOARTIBOX = 0x2, - DRAWINVENTORYBAR_NOARROWS = 0x4, - DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER = 0x8, - DRAWINVENTORYBAR_TRANSLUCENT = 0x10, - DRAWINVENTORYBAR_VERTICAL = 0x20, -}; - -enum //drawgem flags -{ - DRAWGEM_WIGGLE = 1, - DRAWGEM_TRANSLATABLE = 2, - DRAWGEM_ARMOR = 4, - DRAWGEM_REVERSE = 8, -}; - -enum //drawshader flags -{ - DRAWSHADER_VERTICAL = 1, - DRAWSHADER_REVERSE = 2, -}; - -enum //drawmugshot flags -{ - DRAWMUGSHOT_XDEATHFACE = 0x1, - DRAWMUGSHOT_ANIMATEDGODMODE = 0x2, - DRAWMUGSHOT_DISABLEGRIN = 0x4, - DRAWMUGSHOT_DISABLEOUCH = 0x8, - DRAWMUGSHOT_DISABLEPAIN = 0x10, - DRAWMUGSHOT_DISABLERAMPAGE = 0x20, -}; - -enum //drawkeybar flags -{ - DRAWKEYBAR_VERTICAL = 0x1, - DRAWKEYBAR_REVERSEROWS = 0x2, -}; - -enum //event flags -{ - SBARINFOEVENT_NOT = 1, - SBARINFOEVENT_OR = 2, - SBARINFOEVENT_AND = 4, -}; - -enum //aspect ratios -{ - ASPECTRATIO_4_3 = 0, - ASPECTRATIO_16_9 = 1, - ASPECTRATIO_16_10 = 2, - ASPECTRATIO_5_4 = 4, -}; - -enum //Key words -{ - SBARINFO_BASE, - SBARINFO_HEIGHT, - SBARINFO_INTERPOLATEHEALTH, - SBARINFO_INTERPOLATEARMOR, - SBARINFO_COMPLETEBORDER, - SBARINFO_MONOSPACEFONTS, - SBARINFO_LOWERHEALTHCAP, - SBARINFO_STATUSBAR, - SBARINFO_MUGSHOT, - SBARINFO_CREATEPOPUP, -}; - -enum //Bar types -{ - STBAR_NONE, - STBAR_FULLSCREEN, - STBAR_NORMAL, - STBAR_AUTOMAP, - STBAR_INVENTORY, - STBAR_INVENTORYFULLSCREEN, - STBAR_POPUPLOG, - STBAR_POPUPKEYS, - STBAR_POPUPSTATUS, -}; - -enum //Bar key words -{ - SBARINFO_DRAWIMAGE, - SBARINFO_DRAWNUMBER, - SBARINFO_DRAWSWITCHABLEIMAGE, - SBARINFO_DRAWMUGSHOT, - SBARINFO_DRAWSELECTEDINVENTORY, - SBARINFO_DRAWINVENTORYBAR, - SBARINFO_DRAWBAR, - SBARINFO_DRAWGEM, - SBARINFO_DRAWSHADER, - SBARINFO_DRAWSTRING, - SBARINFO_DRAWKEYBAR, - SBARINFO_GAMEMODE, - SBARINFO_PLAYERCLASS, - SBARINFO_ASPECTRATIO, - SBARINFO_ISSELECTED, - SBARINFO_USESAMMO, - SBARINFO_USESSECONDARYAMMO, - SBARINFO_HASWEAPONPIECE, - SBARINFO_INVENTORYBARNOTVISIBLE, - SBARINFO_WEAPONAMMO, - SBARINFO_ININVENTORY, -}; - -//All this so I can change the mugshot state in ACS... -class FBarShader : public FTexture -{ -public: - FBarShader(bool vertical, bool reverse); - const BYTE *GetColumn(unsigned int column, const Span **spans_out); - const BYTE *GetPixels(); - void Unload(); -private: - BYTE Pixels[512]; - Span DummySpan[2]; -}; - -class DSBarInfo : public DBaseStatusBar -{ - DECLARE_CLASS(DSBarInfo, DBaseStatusBar) -public: - DSBarInfo(SBarInfo *script=NULL); - ~DSBarInfo(); - void Draw(EHudState state); - void NewGame(); - void AttachToPlayer(player_t *player); - void Tick(); - void ReceivedWeapon (AWeapon *weapon); - void FlashItem(const PClass *itemtype); - void ShowPop(int popnum); - void SetMugShotState(const char* stateName, bool waitTillDone=false, bool reset=false); -private: - void doCommands(SBarInfoBlock &block, int xOffset=0, int yOffset=0, int alpha=FRACUNIT); - void DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool translate=false, bool dim=false, int offsetflags=0); - void DrawString(const char* str, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool drawshadow=false); - void DrawNumber(int num, int len, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool fillzeros=false, bool drawshadow=false); - void DrawFace(const char *defaultFace, int accuracy, int stateflags, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets); - int updateState(bool xdth, bool animatedgodmode); - void DrawInventoryBar(int type, int num, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool alwaysshow, - SBarInfoCoordinate counterx, SBarInfoCoordinate countery, EColorRange translation, bool drawArtiboxes, bool noArrows, bool alwaysshowcounter, int bgalpha, bool vertical); - void DrawGem(FTexture* chain, FTexture* gem, int value, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, int padleft, int padright, int chainsize, - bool wiggle, bool translate); - FRemapTable* getTranslation(); - - SBarInfo *script; - FImageCollection Images; - FPlayerSkin *oldSkin; - FFont *drawingFont; - int oldHealth; - int oldArmor; - int mugshotHealth; - int chainWiggle; - int artiflash; - int pendingPopup; - int currentPopup; - unsigned int invBarOffset; - FBarShader shader_horz_normal; - FBarShader shader_horz_reverse; - FBarShader shader_vert_normal; - FBarShader shader_vert_reverse; - FMugShot MugShot; -}; - #endif //__SBarInfo_SBAR_H__ diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp new file mode 100644 index 000000000..bd1bd1478 --- /dev/null +++ b/src/g_shared/sbarinfo_commands.cpp @@ -0,0 +1,2574 @@ +/* +** sbarinfo_commands.cpp +** +** This is an extension to the sbarinfo.cpp file. This contains all of the +** commands. +**--------------------------------------------------------------------------- +** Copyright 2008 Braden Obrzut +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. 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. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +**--------------------------------------------------------------------------- +** +*/ + +// [BL] Do note that this file is included by sbarinfo.cpp. This is done so +// that all the code can be more or less in one spot. +// +// At the bottom of this file is a function that belongs to +// SBarInfoCommandFlowControl which creates the instances of the following +// classes. +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawImage : public SBarInfoCommand +{ + public: + CommandDrawImage(SBarInfo *script) : SBarInfoCommand(script), + translatable(false), type(NORMAL_IMAGE), image(-1), offset(static_cast (TOP|LEFT)), + texture(NULL), alpha(FRACUNIT) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(texture == NULL) + return; + + statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), alpha, block->FullScreenOffsets(), + translatable, false, offset); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + bool getImage = true; + if(sc.CheckToken(TK_Identifier)) + { + getImage = false; + if(sc.Compare("playericon")) + type = PLAYERICON; + else if(sc.Compare("ammoicon1")) + type = AMMO1; + else if(sc.Compare("ammoicon2")) + type = AMMO2; + else if(sc.Compare("armoricon")) + type = ARMOR; + else if(sc.Compare("weaponicon")) + type = WEAPONICON; + else if(sc.Compare("sigil")) + type = SIGIL; + else if(sc.Compare("hexenarmor")) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("armor")) + type = HEXENARMOR_ARMOR; + else if(sc.Compare("shield")) + type = HEXENARMOR_SHIELD; + else if(sc.Compare("helm")) + type = HEXENARMOR_HELM; + else if(sc.Compare("amulet")) + type = HEXENARMOR_AMULET; + else + sc.ScriptError("Unkown armor type: '%s'", sc.String); + sc.MustGetToken(','); + getImage = true; + } + else if(sc.Compare("translatable")) + { + translatable = true; + getImage = true; + } + else + { + type = INVENTORYICON; + const PClass* item = PClass::FindClass(sc.String); + if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory + { + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + sprite = ((AInventory *)GetDefaultByType(item))->Icon; + image = -1; + } + } + if(getImage) + { + sc.MustGetToken(TK_StringConst); + image = script->newImage(sc.String); + sprite.SetInvalid(); + } + sc.MustGetToken(','); + GetCoordinates(sc, fullScreenOffsets, imgx, imgy); + if(sc.CheckToken(',')) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("center")) + offset = CENTER; + else if(sc.Compare("centerbottom")) + offset = static_cast (HMIDDLE|BOTTOM); + else + sc.ScriptError("'%s' is not a valid alignment.", sc.String); + } + sc.MustGetToken(';'); + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + texture = NULL; + alpha = block->Alpha(); + if(type == PLAYERICON) + texture = TexMan[statusBar->CPlayer->mo->ScoreIcon]; + else if(type == AMMO1) + { + if(statusBar->ammo1 != NULL) + texture = TexMan[statusBar->ammo1->Icon]; + } + else if(type == AMMO2) + { + if(statusBar->ammo2 != NULL) + texture = TexMan[statusBar->ammo2->Icon]; + } + else if(type == ARMOR) + { + if(statusBar->armor != NULL && statusBar->armor->Amount != 0) + texture = TexMan(statusBar->armor->Icon); + } + else if(type == WEAPONICON) + { + AWeapon *weapon = statusBar->CPlayer->ReadyWeapon; + if(weapon != NULL && weapon->Icon.isValid()) + { + texture = TexMan[weapon->Icon]; + } + } + else if(type == SIGIL) + { + AInventory *item = statusBar->CPlayer->mo->FindInventory(); + if (item != NULL) + texture = TexMan[item->Icon]; + } + else if(type == HEXENARMOR_ARMOR || type == HEXENARMOR_SHIELD || type == HEXENARMOR_AMULET || type == HEXENARMOR_ARMOR) + { + int armorType = type - HEXENARMOR_ARMOR; + + AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory(); + if (harmor != NULL) + { + if (harmor->Slots[armorType] > 0 && harmor->SlotsIncrement[armorType] > 0) + { + //combine the alpha values + alpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) MIN (OPAQUE, Scale(harmor->Slots[armorType], OPAQUE, harmor->SlotsIncrement[armorType])) / (double) OPAQUE) * FRACUNIT); + texture = statusBar->Images[image]; + } + else + return; + } + } + else if(type == INVENTORYICON) + texture = TexMan[sprite]; + else if(type == SELECTEDINVENTORYICON && statusBar->CPlayer->mo->InvSel != NULL) + texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon); + else if(image >= 0) + texture = statusBar->Images[image]; + } + protected: + enum ImageType + { + PLAYERICON, + AMMO1, + AMMO2, + ARMOR, + WEAPONICON, + SIGIL, + HEXENARMOR_ARMOR, + HEXENARMOR_SHIELD, + HEXENARMOR_HELM, + HEXENARMOR_AMULET, + INVENTORYICON, + WEAPONSLOT, + SELECTEDINVENTORYICON, + + NORMAL_IMAGE + }; + + bool translatable; + ImageType type; + int image; + FTextureID sprite; + // I'm using imgx/imgy here so that I can inherit drawimage with drawnumber for some commands. + SBarInfoCoordinate imgx; + SBarInfoCoordinate imgy; + Offset offset; + + FTexture *texture; + int alpha; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawSwitchableImage : public CommandDrawImage +{ + private: + enum Operator + { + EQUAL, + LESS, + GREATER, + LESSOREQUAL, + GREATEROREQUAL, + NOTEQUAL + }; + + static void GetOperation(FScanner &sc, Operator &op, int &value) + { + if(sc.CheckToken(TK_Eq)) + op = EQUAL; + else if(sc.CheckToken('<')) + op = LESS; + else if(sc.CheckToken('>')) + op = GREATER; + else if(sc.CheckToken(TK_Leq)) + op = LESSOREQUAL; + else if(sc.CheckToken(TK_Geq)) + op = GREATEROREQUAL; + else if(sc.CheckToken(TK_Neq)) + op = NOTEQUAL; + else + { // Default + op = GREATER; + value = 0; + return; + } + sc.MustGetToken(TK_IntConst); + value = sc.Number; + } + static bool EvaluateOperation(const Operator &op, const int &value, const int &compare) + { + switch(op) + { + case EQUAL: + return compare == value; + case LESS: + return compare < value; + case GREATER: + default: + return compare > value; + case LESSOREQUAL: + return compare <= value; + case GREATEROREQUAL: + return compare >= value; + case NOTEQUAL: + return compare != value; + } + } + + public: + CommandDrawSwitchableImage(SBarInfo *script) : CommandDrawImage(script), + condition(INVENTORY), conditionAnd(false) + { + conditionalImage[0] = conditionalImage[1] = conditionalImage[2] = -1; + conditionalValue[0] = conditionalValue[1] = 0; + armorType[0] = armorType[1] = 0; + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("weaponslot")) + { + condition = WEAPONSLOT; + sc.MustGetToken(TK_IntConst); + conditionalValue[0] = sc.Number; + } + else if(sc.Compare("invulnerable")) + { + condition = INVULNERABILITY; + } + else if(sc.Compare("keyslot")) + { + condition = KEYSLOT; + sc.MustGetToken(TK_IntConst); + conditionalValue[0] = sc.Number; + } + else if(sc.Compare("armortype")) + { + condition = ARMORTYPE; + sc.MustGetToken(TK_Identifier); + armorType[0] = FName(sc.String).GetIndex(); + GetOperation(sc, conditionalOperator[0], conditionalValue[0]); + } + else + { + inventoryItem[0] = sc.String; + const PClass* item = PClass::FindClass(sc.String); + if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory + { + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + GetOperation(sc, conditionalOperator[0], conditionalValue[0]); + } + if(sc.CheckToken(TK_AndAnd) && condition != INVULNERABILITY) + { + conditionAnd = true; + if(condition == KEYSLOT || condition == WEAPONSLOT) + { + sc.MustGetToken(TK_IntConst); + conditionalValue[1] = sc.Number; + } + else if(condition == ARMORTYPE) + { + sc.MustGetToken(TK_Identifier); + armorType[1] = FName(sc.String).GetIndex(); + GetOperation(sc, conditionalOperator[1], conditionalValue[1]); + } + else + { + sc.MustGetToken(TK_Identifier); + inventoryItem[1] = sc.String; + const PClass* item = PClass::FindClass(sc.String); + if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory + { + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + GetOperation(sc, conditionalOperator[1], conditionalValue[1]); + } + } + // [BL] I have word that MSVC++ wants this static_cast ;) Shut up MSVC! + for(unsigned int i = 0;i < static_cast (conditionAnd ? 3 : 1);i++) + { + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); + conditionalImage[i] = script->newImage(sc.String); + } + sc.MustGetToken(','); + CommandDrawImage::Parse(sc, fullScreenOffsets); + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + // DrawSwitchable image allows 2 or 4 images to be supplied. + // drawAlt toggles these: + // 1 = first image + // 2 = second image + // 3 = thrid image + // 0 = last image + int drawAlt = 0; + if(condition == WEAPONSLOT) //weaponslots + { + drawAlt = 1; //draw off state until we know we have something. + for (int i = 0; i < statusBar->CPlayer->weapons.Slots[conditionalValue[0]].Size(); i++) + { + const PClass *weap = statusBar->CPlayer->weapons.Slots[conditionalValue[0]].GetWeapon(i); + if(weap == NULL) + { + continue; + } + else if(statusBar->CPlayer->mo->FindInventory(weap) != NULL) + { + drawAlt = 0; + break; + } + } + } + else if(condition == INVULNERABILITY) + { + if(statusBar->CPlayer->cheats&CF_GODMODE) + { + drawAlt = 1; + } + } + else if(condition == KEYSLOT) + { + bool found1 = false; + bool found2 = false; + drawAlt = 1; + + for(AInventory *item = statusBar->CPlayer->mo->Inventory;item != NULL;item = item->Inventory) + { + if(item->IsKindOf(RUNTIME_CLASS(AKey))) + { + int keynum = static_cast(item)->KeyNumber; + + if(keynum == conditionalValue[0]) + found1 = true; + if(conditionAnd && keynum == conditionalValue[1]) // two keys + found2 = true; + } + } + + if(conditionAnd) + { + if(found1 && found2) + drawAlt = 0; + else if(found1) + drawAlt = 2; + else if(found2) + drawAlt = 3; + } + else + { + if(found1) + drawAlt = 0; + } + } + else if(condition == ARMORTYPE) + { + ABasicArmor *armor = (ABasicArmor *) statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor); + if(armor != NULL) + { + bool matches1 = armor->ArmorType.GetIndex() == armorType[0] && EvaluateOperation(conditionalOperator[0], conditionalValue[0], armor->Amount); + bool matches2 = armor->ArmorType.GetIndex() == armorType[1] && EvaluateOperation(conditionalOperator[1], conditionalValue[1], armor->Amount); + + drawAlt = 1; + if(conditionAnd) + { + if(matches1 && matches2) + drawAlt = 0; + else if(matches2) + drawAlt = 3; + else if(matches1) + drawAlt = 2; + } + else if(matches1) + drawAlt = 0; + } + } + else //check the inventory items and draw selected sprite + { + AInventory* item = statusBar->CPlayer->mo->FindInventory(PClass::FindClass(inventoryItem[0])); + if(item == NULL || !EvaluateOperation(conditionalOperator[0], conditionalValue[0], item->Amount)) + drawAlt = 1; + if(conditionAnd) + { + item = statusBar->CPlayer->mo->FindInventory(PClass::FindClass(inventoryItem[1])); + bool secondCondition = item != NULL && EvaluateOperation(conditionalOperator[1], conditionalValue[1], item->Amount); + if((item != NULL && secondCondition) && drawAlt == 0) //both + { + drawAlt = 0; + } + else if((item != NULL && secondCondition) && drawAlt == 1) //2nd + { + drawAlt = 3; + } + else if((item == NULL || !secondCondition) && drawAlt == 0) //1st + { + drawAlt = 2; + } + } + } + if(drawAlt != 0) //draw 'off' image + { + texture = statusBar->Images[conditionalImage[drawAlt-1]]; + return; + } + CommandDrawImage::Tick(block, statusBar, hudChanged); + } + + private: + enum Condition + { + WEAPONSLOT, + INVULNERABILITY, + KEYSLOT, + ARMORTYPE, + + INVENTORY + }; + + Condition condition; + bool conditionAnd; + int conditionalImage[3]; + int conditionalValue[2]; + Operator conditionalOperator[2]; + FString inventoryItem[2]; + int armorType[2]; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawString : public SBarInfoCommand +{ + public: + CommandDrawString(SBarInfo *script) : SBarInfoCommand(script), + shadow(false), spacing(0), font(NULL), translation(CR_UNTRANSLATED) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + statusBar->DrawString(font, str.GetChars(), x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + font = V_GetFont(sc.String); + if(font == NULL) + sc.ScriptError("Unknown font '%s'.", sc.String); + sc.MustGetToken(','); + translation = GetTranslation(sc); + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); + str = sc.String; + sc.MustGetToken(','); + GetCoordinates(sc, fullScreenOffsets, x, y); + if(sc.CheckToken(',')) //spacing + { + sc.MustGetToken(TK_IntConst); + spacing = sc.Number; + } + sc.MustGetToken(';'); + + if(script->spacingCharacter == '\0') + x -= static_cast (font->StringWidth(str)+(spacing * str.Len())); + else //monospaced, so just multiplay the character size + x -= static_cast ((font->GetCharWidth((int) script->spacingCharacter) + spacing) * str.Len()); + } + protected: + bool shadow; + int spacing; + FFont *font; + EColorRange translation; + SBarInfoCoordinate x; + SBarInfoCoordinate y; + FString str; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawNumber : public CommandDrawString +{ + public: + CommandDrawNumber(SBarInfo *script) : CommandDrawString(script), + fillZeros(false), whenNotZero(false), interpolationSpeed(0), drawValue(0), + length(3), lowValue(-1), lowTranslation(CR_UNTRANSLATED), highValue(-1), + highTranslation(CR_UNTRANSLATED), value(CONSTANT), valueArgument(0), + inventoryItem(NULL) + { + } + + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_IntConst); + length = sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + font = V_GetFont(sc.String); + if(font == NULL) + sc.ScriptError("Unknown font '%s'.", sc.String); + sc.MustGetToken(','); + normalTranslation = GetTranslation(sc); + sc.MustGetToken(','); + if(sc.CheckToken(TK_IntConst)) + { + value = CONSTANT; + valueArgument = sc.Number; + sc.MustGetToken(','); + } + else + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("health")) + value = HEALTH; + else if(sc.Compare("armor")) + value = ARMOR; + else if(sc.Compare("ammo1")) + value = AMMO1; + else if(sc.Compare("ammo2")) + value = AMMO2; + else if(sc.Compare("ammo")) //request the next string to be an ammo type + { + value = AMMO; + sc.MustGetToken(TK_Identifier); + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo + { + sc.ScriptError("'%s' is not a type of ammo.", sc.String); + } + } + else if(sc.Compare("ammocapacity")) + { + value = AMMOCAPACITY; + sc.MustGetToken(TK_Identifier); + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo + { + sc.ScriptError("'%s' is not a type of ammo.", sc.String); + } + } + else if(sc.Compare("frags")) + value = FRAGS; + else if(sc.Compare("kills")) + value = KILLS; + else if(sc.Compare("monsters")) + value = MONSTERS; + else if(sc.Compare("items")) + value = ITEMS; + else if(sc.Compare("totalitems")) + value = TOTALITEMS; + else if(sc.Compare("secrets")) + value = SECRETS; + else if(sc.Compare("totalsecrets")) + value = TOTALSECRETS; + else if(sc.Compare("armorclass")) + value = ARMORCLASS; + else if(sc.Compare("airtime")) + value = AIRTIME; + else if(sc.Compare("globalvar")) + { + value = GLOBALVAR; + sc.MustGetToken(TK_IntConst); + if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS) + sc.ScriptError("Global variable number out of range: %d", sc.Number); + valueArgument = sc.Number; + } + else if(sc.Compare("globalarray")) //acts like variable[playernumber()] + { + value = GLOBALARRAY; + sc.MustGetToken(TK_IntConst); + if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS) + sc.ScriptError("Global variable number out of range: %d", sc.Number); + valueArgument = sc.Number; + } + else if(sc.Compare("poweruptime")) + { + value = POWERUPTIME; + sc.MustGetToken(TK_Identifier); + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(inventoryItem)) + { + sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String); + } + } + else + { + value = INVENTORY; + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(inventoryItem)) //must be a kind of ammo + { + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + } + sc.MustGetToken(','); + } + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("fillzeros")) + fillZeros = true; + else if(sc.Compare("whennotzero")) + whenNotZero = true; + else if(sc.Compare("drawshadow")) + shadow = true; + else if(sc.Compare("interpolate")) + { + sc.MustGetToken('('); + sc.MustGetToken(TK_IntConst); + interpolationSpeed = sc.Number; + sc.MustGetToken(')'); + } + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + GetCoordinates(sc, fullScreenOffsets, startX, y); + if(sc.CheckToken(',')) + { + bool needsComma = false; + if(sc.CheckToken(TK_IntConst)) //font spacing + { + spacing = sc.Number; + needsComma = true; + } + if(!needsComma || sc.CheckToken(',')) //2nd coloring for "low-on" value + { + lowTranslation = GetTranslation(sc); + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + lowValue = sc.Number; + if(sc.CheckToken(',')) //3rd coloring for "high-on" value + { + highTranslation = GetTranslation(sc); + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + highValue = sc.Number; + } + } + } + sc.MustGetToken(';'); + + if(value == HEALTH) + interpolationSpeed = script->interpolateHealth ? script->interpolationSpeed : interpolationSpeed; + else if(value == ARMOR) + interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + int num = valueArgument; + switch(value) + { + case HEALTH: + num = statusBar->CPlayer->mo->health; + if(script->lowerHealthCap && num < 0) //health shouldn't display negatives + num = 0; + if(script->interpolateHealth) + interpolationSpeed = script->interpolationSpeed; + break; + case ARMOR: + num = statusBar->armor != NULL ? statusBar->armor->Amount : 0; + if(script->interpolateArmor) + interpolationSpeed = script->armorInterpolationSpeed; + break; + case AMMO1: + if(statusBar->ammo1 == NULL) //no ammo, do not draw + { + str = ""; + return; + } + num = statusBar->ammocount1; + break; + case AMMO2: + if(statusBar->ammo2 == NULL) //no ammo, do not draw + { + str = ""; + return; + } + num = statusBar->ammocount2; + break; + case AMMO: + { + AInventory* item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + num = item->Amount; + else + num = 0; + break; + } + case AMMOCAPACITY: + { + AInventory* item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + num = item->MaxAmount; + else + num = ((AInventory *)GetDefaultByType(inventoryItem))->MaxAmount; + break; + } + case FRAGS: + num = statusBar->CPlayer->fragcount; + break; + case KILLS: + num = level.killed_monsters; + break; + case MONSTERS: + num = level.total_monsters; + break; + case ITEMS: + num = level.found_items; + break; + case TOTALITEMS: + num = level.total_items; + break; + case SECRETS: + num = level.found_secrets; + break; + case TOTALSECRETS: + num = level.total_secrets; + break; + case ARMORCLASS: + { + AHexenArmor *harmor = statusBar->CPlayer->mo->FindInventory(); + if(harmor != NULL) + { + num = harmor->Slots[0] + harmor->Slots[1] + + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]; + } + //Hexen counts basic armor also so we should too. + if(statusBar->armor != NULL) + { + num += statusBar->armor->SavePercent; + } + num /= (5*FRACUNIT); + break; + } + case GLOBALVAR: + num = ACS_GlobalVars[valueArgument]; + break; + case GLOBALARRAY: + num = ACS_GlobalArrays[valueArgument][consoleplayer]; + break; + case POWERUPTIME: + { + //Get the PowerupType and check to see if the player has any in inventory. + const PClass* powerupType = ((APowerupGiver*) GetDefaultByType(inventoryItem))->PowerupType; + APowerup* powerup = (APowerup*) statusBar->CPlayer->mo->FindInventory(powerupType); + if(powerup != NULL) + num = powerup->EffectTics / TICRATE + 1; + break; + } + case INVENTORY: + { + AInventory* item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + num = item->Amount; + else + num = 0; + break; + } + case AIRTIME: + { + if(statusBar->CPlayer->mo->waterlevel < 3) + num = level.airsupply/TICRATE; + else + num = clamp((statusBar->CPlayer->air_finished - level.time + (TICRATE-1))/TICRATE, 0, INT_MAX); + break; + } + case SELECTEDINVENTORY: + if(statusBar->CPlayer->mo->InvSel != NULL) + num = statusBar->CPlayer->mo->InvSel->Amount; + break; + default: break; + } + if(interpolationSpeed != 0 && (!hudChanged || level.time == 1)) + { + if(num < drawValue) + drawValue -= clamp((drawValue - num) >> 2, 1, interpolationSpeed); + else if(drawValue < num) + drawValue += clamp((num - drawValue) >> 2, 1, interpolationSpeed); + } + else + drawValue = num; + if(whenNotZero && drawValue == 0) + { + str = ""; + return; + } + + translation = normalTranslation; + if(lowValue != -1 && drawValue <= lowValue) //low + translation = lowTranslation; + else if(highValue != -1 && drawValue >= highValue) //high + translation = highTranslation; + + x = startX; + + // 10^9 is a largest we can hold in a 32-bit int. So if we go any larger we have to toss out the positions limit. + int maxval = length <= 9 ? (int) ceil(pow(10., length))-1 : INT_MAX; + if(!fillZeros || length == 1) + drawValue = clamp(drawValue, -maxval, maxval); + else //The community wanted negatives to take the last digit, but we can only do this if there is room + drawValue = clamp(drawValue, length <= 9 ? (int) -(ceil(pow(10., length-1))-1) : INT_MIN, maxval); + str.Format("%d", drawValue); + if(fillZeros) + { + if(drawValue < 0) //We don't want the negative just yet + str.Format("%d", -drawValue); + while(str.Len() < (unsigned int) length) + { + if(drawValue < 0 && str.Len() == (unsigned int) (length-1)) + str.Insert(0, "-"); + else + str.Insert(0, "0"); + } + } + if(script->spacingCharacter == '\0') + x -= static_cast (font->StringWidth(str)+(spacing * str.Len())); + else //monospaced, so just multiplay the character size + x -= static_cast ((font->GetCharWidth((int) script->spacingCharacter) + spacing) * str.Len()); + } + protected: + enum ValueType + { + HEALTH, + ARMOR, + AMMO1, + AMMO2, + AMMO, + AMMOCAPACITY, + FRAGS, + INVENTORY, + KILLS, + MONSTERS, + ITEMS, + TOTALITEMS, + SECRETS, + TOTALSECRETS, + ARMORCLASS, + GLOBALVAR, + GLOBALARRAY, + POWERUPTIME, + AIRTIME, + SELECTEDINVENTORY, + + CONSTANT + }; + + bool fillZeros; + bool whenNotZero; + + int interpolationSpeed; + int drawValue; + + int length; + int lowValue; + EColorRange lowTranslation; + int highValue; + EColorRange highTranslation; + EColorRange normalTranslation; + ValueType value; + int valueArgument; + const PClass *inventoryItem; + + SBarInfoCoordinate startX; + + friend class CommandDrawInventoryBar; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawMugShot : public SBarInfoCommand +{ + public: + CommandDrawMugShot(SBarInfo *script) : SBarInfoCommand(script), + accuracy(5), stateFlags(FMugShot::STANDARD) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + FTexture *face = script->MugShot.GetFace(statusBar->CPlayer, defaultFace, accuracy, stateFlags); + if (face != NULL) + statusBar->DrawGraphic(face, x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + if(sc.CheckToken(TK_StringConst)) + { + defaultFace = sc.String; + if(defaultFace.Len() > 3) + sc.ScriptError("Default can not be longer than 3 characters."); + sc.MustGetToken(','); + } + sc.MustGetToken(TK_IntConst); //accuracy + if(sc.Number < 1 || sc.Number > 9) + sc.ScriptError("Expected a number between 1 and 9, got %d instead.", sc.Number); + accuracy = sc.Number; + sc.MustGetToken(','); + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("xdeathface")) + stateFlags = static_cast (stateFlags|FMugShot::XDEATHFACE); + else if(sc.Compare("animatedgodmode")) + stateFlags = static_cast (stateFlags|FMugShot::ANIMATEDGODMODE); + else if(sc.Compare("disablegrin")) + stateFlags = static_cast (stateFlags|FMugShot::DISABLEGRIN); + else if(sc.Compare("disableouch")) + stateFlags = static_cast (stateFlags|FMugShot::DISABLEOUCH); + else if(sc.Compare("disablepain")) + stateFlags = static_cast (stateFlags|FMugShot::DISABLEPAIN); + else if(sc.Compare("disablerampage")) + stateFlags = static_cast (stateFlags|FMugShot::DISABLERAMPAGE); + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + + GetCoordinates(sc, fullScreenOffsets, x, y); + sc.MustGetToken(';'); + } + + protected: + FString defaultFace; //Deprecated + + int accuracy; + FMugShot::StateFlags stateFlags; + SBarInfoCoordinate x; + SBarInfoCoordinate y; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawSelectedInventory : public SBarInfoCommandFlowControl, private CommandDrawImage, private CommandDrawNumber +{ + public: + CommandDrawSelectedInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), + CommandDrawImage(script), CommandDrawNumber(script), alternateOnEmpty(false), + artiflash(false), alwaysShowCounter(false) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(statusBar->CPlayer->mo->InvSel != NULL && !(level.flags & LEVEL_NOINVENTORYBAR)) + { + if(artiflash && artiflashTick) + { + statusBar->DrawGraphic(statusBar->Images[ARTIFLASH_OFFSET+(4-artiflashTick)], imgx, imgy, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), + translatable, false, offset); + } + else + CommandDrawImage::Draw(block, statusBar); + if(alwaysShowCounter || statusBar->CPlayer->mo->InvSel->Amount != 1) + CommandDrawNumber::Draw(block, statusBar); + } + else if(alternateOnEmpty) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + type = SELECTEDINVENTORYICON; + value = SELECTEDINVENTORY; + while(true) //go until we get a font (non-flag) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("alternateonempty")) + alternateOnEmpty = true; + else if(sc.Compare("artiflash")) + artiflash = true; + else if(sc.Compare("alwaysshowcounter")) + alwaysShowCounter = true; + else if(sc.Compare("center")) + offset = CENTER; + else if(sc.Compare("centerbottom")) + offset = static_cast (HMIDDLE|BOTTOM); + else if(sc.Compare("drawshadow")) + shadow = true; + else + { + font = V_GetFont(sc.String); + if(font == NULL) + sc.ScriptError("Unknown font '%s'.", sc.String); + sc.MustGetToken(','); + break; + } + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + CommandDrawImage::GetCoordinates(sc, fullScreenOffsets, imgx, imgy); + startX = imgx + 30; + y = imgy + 24; + translation = CR_GOLD; + if(sc.CheckToken(',')) //more font information + { + CommandDrawNumber::GetCoordinates(sc, fullScreenOffsets, startX, y); + if(sc.CheckToken(',')) + { + translation = CommandDrawNumber::GetTranslation(sc); + if(sc.CheckToken(',')) + { + sc.MustGetToken(TK_IntConst); + spacing = sc.Number; + } + } + } + if(alternateOnEmpty) + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + else + sc.MustGetToken(';'); + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + if(artiflashTick > 0) + artiflashTick--; + + CommandDrawImage::Tick(block, statusBar, hudChanged); + CommandDrawNumber::Tick(block, statusBar, hudChanged); + } + + static void Flash() { artiflashTick = 4; } + protected: + bool alternateOnEmpty; + bool artiflash; + bool alwaysShowCounter; + + static int artiflashTick; +}; +int CommandDrawSelectedInventory::artiflashTick = 4; + +void DSBarInfo::FlashItem(const PClass *itemtype) +{ + CommandDrawSelectedInventory::Flash(); +} + +//////////////////////////////////////////////////////////////////////////////// + +class CommandGameMode : public SBarInfoCommandFlowControl +{ + public: + CommandGameMode(SBarInfo *script) : SBarInfoCommandFlowControl(script), + modes(static_cast (0)) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if((!multiplayer && (modes & SINGLEPLAYER)) || + (deathmatch && (modes & DEATHMATCH)) || + (multiplayer && !deathmatch && (modes & COOPERATIVE)) || + (teamplay && (modes & TEAMGAME))) + { + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + do + { + sc.MustGetToken(TK_Identifier); + modes |= static_cast (1<CPlayer->ReadyWeapon != NULL && (statusBar->CPlayer->ReadyWeapon->AmmoType1 != NULL || statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL)) ^ negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + if(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("not")) + negate = true; + else + sc.ScriptError("Expected 'not', but got '%s' instead.", sc.String); + } + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + bool negate; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandUsesSecondaryAmmo : public CommandUsesAmmo +{ + public: + CommandUsesSecondaryAmmo(SBarInfo *script) : CommandUsesAmmo(script) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if((statusBar->CPlayer->ReadyWeapon != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType1 != statusBar->CPlayer->ReadyWeapon->AmmoType2) ^ negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandInventoryBarNotVisible : public SBarInfoCommandFlowControl +{ + public: + CommandInventoryBarNotVisible(SBarInfo *script) : SBarInfoCommandFlowControl(script) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(statusBar->CPlayer->inventorytics <= 0 || (level.flags & LEVEL_NOINVENTORYBAR)) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandAspectRatio : public SBarInfoCommandFlowControl +{ + public: + CommandAspectRatio(SBarInfo *script) : SBarInfoCommandFlowControl(script), + ratio(ASPECTRATIO_4_3) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(CheckRatio(screen->GetWidth(), screen->GetHeight()) == ratio) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_StringConst); + if(sc.Compare("4:3")) + ratio = ASPECTRATIO_4_3; + else if(sc.Compare("16:9")) + ratio = ASPECTRATIO_16_9; + else if(sc.Compare("16:10")) + ratio = ASPECTRATIO_16_10; + else if(sc.Compare("5:4")) + ratio = ASPECTRATIO_5_4; + else + sc.ScriptError("Unkown aspect ratio: %s", sc.String); + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + enum Ratio + { + ASPECTRATIO_4_3 = 0, + ASPECTRATIO_16_9 = 1, + ASPECTRATIO_16_10 = 2, + ASPECTRATIO_5_4 = 4 + }; + + Ratio ratio; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawShader : public SBarInfoCommand +{ + public: + CommandDrawShader(SBarInfo *script) : SBarInfoCommand(script), + vertical(false), reverse(false), width(1), height(1) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + statusBar->DrawGraphic(&shaders[(vertical<<1) + reverse], x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, true, width, height); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_IntConst); + width = sc.Number; + if(sc.Number < 1) + sc.ScriptError("Width must be greater than 1."); + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + height = sc.Number; + if(sc.Number < 1) + sc.ScriptError("Height must be greater than 1."); + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + if(sc.Compare("vertical")) + vertical = true; + else if(!sc.Compare("horizontal")) + sc.ScriptError("Unknown direction '%s'.", sc.String); + sc.MustGetToken(','); + if(sc.CheckToken(TK_Identifier)) + { + if(!sc.Compare("reverse")) + { + sc.ScriptError("Exspected 'reverse', got '%s' instead.", sc.String); + } + reverse = true; + sc.MustGetToken(','); + } + GetCoordinates(sc, fullScreenOffsets, x, y); + sc.MustGetToken(';'); + } + protected: + bool vertical; + bool reverse; + unsigned int width; + unsigned int height; + SBarInfoCoordinate x; + SBarInfoCoordinate y; + private: + class FBarShader : public FTexture + { + public: + FBarShader(bool vertical, bool reverse) + { + int i; + + Width = vertical ? 2 : 256; + Height = vertical ? 256 : 2; + CalcBitSize(); + + // Fill the column/row with shading values. + // Vertical shaders have have minimum alpha at the top + // and maximum alpha at the bottom, unless flipped by + // setting reverse to true. Horizontal shaders are just + // the opposite. + if (vertical) + { + if (!reverse) + { + for (i = 0; i < 256; ++i) + { + Pixels[i] = i; + Pixels[256+i] = i; + } + } + else + { + for (i = 0; i < 256; ++i) + { + Pixels[i] = 255 - i; + Pixels[256+i] = 255 -i; + } + } + } + else + { + if (!reverse) + { + for (i = 0; i < 256; ++i) + { + Pixels[i*2] = 255 - i; + Pixels[i*2+1] = 255 - i; + } + } + else + { + for (i = 0; i < 256; ++i) + { + Pixels[i*2] = i; + Pixels[i*2+1] = i; + } + } + } + DummySpan[0].TopOffset = 0; + DummySpan[0].Length = vertical ? 256 : 2; + DummySpan[1].TopOffset = 0; + DummySpan[1].Length = 0; + } + const BYTE *GetColumn(unsigned int column, const Span **spans_out) + { + if (spans_out != NULL) + { + *spans_out = DummySpan; + } + return Pixels + ((column & WidthMask) << HeightBits); + } + const BYTE *GetPixels() { return Pixels; } + void Unload() {} + private: + BYTE Pixels[512]; + Span DummySpan[2]; + }; + + static FBarShader shaders[4]; +}; + +CommandDrawShader::FBarShader CommandDrawShader::shaders[4] = +{ + FBarShader(false, false), FBarShader(false, true), + FBarShader(true, false), FBarShader(true, true) +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawInventoryBar : public SBarInfoCommand +{ + public: + CommandDrawInventoryBar(SBarInfo *script) : SBarInfoCommand(script), + style(GAME_Doom), size(7), alwaysShow(false), noArtibox(false), + noArrows(false), alwaysShowCounter(false), translucent(false), + vertical(false), counters(NULL), font(NULL), translation(CR_GOLD), + fontSpacing(0) + { + } + ~CommandDrawInventoryBar() + { + if(counters != NULL) + { + for(unsigned int i = 0;i < size;i++) + delete counters[i]; + delete[] counters; + } + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + int spacing = 0; + if(!vertical) + spacing = (style != GAME_Strife) ? statusBar->Images[statusBar->invBarOffset + imgARTIBOX]->GetScaledWidth() + 1 : statusBar->Images[statusBar->invBarOffset + imgCURSOR]->GetScaledWidth() - 1; + else + spacing = (style != GAME_Strife) ? statusBar->Images[statusBar->invBarOffset + imgARTIBOX]->GetScaledHeight() + 1 : statusBar->Images[statusBar->invBarOffset + imgCURSOR]->GetScaledHeight() - 1; + + int bgalpha = block->Alpha(); + if(translucent) + bgalpha = fixed_t((((double) block->Alpha() / (double) FRACUNIT) * ((double) HX_SHADOW / (double) FRACUNIT)) * FRACUNIT); + + AInventory *item; + unsigned int i = 0; + // If the player has no artifacts, don't draw the bar + statusBar->CPlayer->mo->InvFirst = statusBar->ValidateInvFirst(size); + if(statusBar->CPlayer->mo->InvFirst != NULL || alwaysShow) + { + for(item = statusBar->CPlayer->mo->InvFirst, i = 0; item != NULL && i < size; item = item->NextInv(), ++i) + { + SBarInfoCoordinate rx = x + (!vertical ? i*spacing : 0); + SBarInfoCoordinate ry = y + (vertical ? i*spacing : 0); + if(!noArtibox) + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgARTIBOX], rx, ry, block->XOffset(), block->YOffset(), bgalpha, block->FullScreenOffsets()); + + if(style != GAME_Strife) //Strife draws the cursor before the icons + statusBar->DrawGraphic(TexMan(item->Icon), rx, ry, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, item->Amount <= 0); + if(item == statusBar->CPlayer->mo->InvSel) + { + if(style == GAME_Heretic) + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgSELECTBOX], rx, ry+29, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + else if(style == GAME_Hexen) + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgSELECTBOX], rx, ry-1, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + else if(style == GAME_Strife) + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgCURSOR], rx-6, ry-2, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + else + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgSELECTBOX], rx, ry, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + } + if(style == GAME_Strife) + statusBar->DrawGraphic(TexMan(item->Icon), rx, ry, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, item->Amount <= 0); + if(counters != NULL && (alwaysShowCounter || item->Amount != 1)) + { + counters[i]->valueArgument = item->Amount; + counters[i]->Draw(block, statusBar); + } + } + for (; i < size && !noArtibox; ++i) + statusBar->DrawGraphic(statusBar->Images[statusBar->invBarOffset + imgARTIBOX], x + (!vertical ? (i*spacing) : 0), y + (vertical ? (i*spacing) : 0), block->XOffset(), block->YOffset(), bgalpha, block->FullScreenOffsets()); + + // Is there something to the left? + if (!noArrows && statusBar->CPlayer->mo->FirstInv() != statusBar->CPlayer->mo->InvFirst) + { + int offset = style != GAME_Strife ? -12 : 14; + statusBar->DrawGraphic(statusBar->Images[!(gametic & 4) ? + statusBar->invBarOffset + imgINVLFGEM1 : statusBar->invBarOffset + imgINVLFGEM2], x + (!vertical ? offset : 0), y + (vertical ? offset : 0), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + } + // Is there something to the right? + if (!noArrows && item != NULL) + { + int offset = style != GAME_Strife ? size*31+2 : size*35-4; + statusBar->DrawGraphic(statusBar->Images[!(gametic & 4) ? + statusBar->invBarOffset + imgINVRTGEM1 : statusBar->invBarOffset + imgINVRTGEM2], x + (!vertical ? offset : 0), y + (vertical ? offset : 0), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + } + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("Doom")) + style = GAME_Doom; + else if(sc.Compare("Heretic")) + style = GAME_Heretic; + else if(sc.Compare("Hexen")) + style = GAME_Hexen; + else if(sc.Compare("Strife")) + style = GAME_Strife; + else + sc.ScriptError("Unknown style '%s'.", sc.String); + + sc.MustGetToken(','); + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("alwaysshow")) + alwaysShow = true; + else if(sc.Compare("noartibox")) + noArtibox = true; + else if(sc.Compare("noarrows")) + noArrows = true; + else if(sc.Compare("alwaysshowcounter")) + alwaysShowCounter = true; + else if(sc.Compare("translucent")) + translucent = true; + else if(sc.Compare("vertical")) + vertical = true; + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + sc.MustGetToken(TK_IntConst); + size = sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + font = V_GetFont(sc.String); + if(font == NULL) + sc.ScriptError("Unknown font '%s'.", sc.String); + + sc.MustGetToken(','); + GetCoordinates(sc, fullScreenOffsets, x, y); + counterX = x + 26; + counterY = y + 22; + if(sc.CheckToken(',')) //more font information + { + GetCoordinates(sc, fullScreenOffsets, counterX, counterY); + if(sc.CheckToken(',')) + { + translation = GetTranslation(sc); + if(sc.CheckToken(',')) + { + sc.MustGetToken(TK_IntConst); + fontSpacing = sc.Number; + } + } + } + sc.MustGetToken(';'); + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + // Make the counters if need be. + if(counters == NULL) + { + int spacing = 0; + if(!vertical) + spacing = (style != GAME_Strife) ? statusBar->Images[statusBar->invBarOffset + imgARTIBOX]->GetScaledWidth() + 1 : statusBar->Images[statusBar->invBarOffset + imgCURSOR]->GetScaledWidth() - 1; + else + spacing = (style != GAME_Strife) ? statusBar->Images[statusBar->invBarOffset + imgARTIBOX]->GetScaledHeight() + 1 : statusBar->Images[statusBar->invBarOffset + imgCURSOR]->GetScaledHeight() - 1; + counters = new CommandDrawNumber*[size]; + + for(unsigned int i = 0;i < size;i++) + { + counters[i] = new CommandDrawNumber(script); + + counters[i]->startX = counterX + (!vertical ? spacing*i : 0); + counters[i]->y = counterY + (vertical ? spacing*i : 0); + counters[i]->normalTranslation = translation; + counters[i]->font = font; + counters[i]->spacing = fontSpacing; + counters[i]->whenNotZero = !alwaysShowCounter; + counters[i]->drawValue = counters[i]->value = CommandDrawNumber::CONSTANT; + counters[i]->length = 3; + } + } + + for(unsigned int i = 0;i < size;i++) + counters[i]->Tick(block, statusBar, hudChanged); + } + protected: + int style; + unsigned int size; + bool alwaysShow; + bool noArtibox; + bool noArrows; + bool alwaysShowCounter; + bool translucent; + bool vertical; + SBarInfoCoordinate x; + SBarInfoCoordinate y; + CommandDrawNumber* *counters; + private: + // This information will be transferred to counters as soon as possible. + FFont *font; + SBarInfoCoordinate counterX; + SBarInfoCoordinate counterY; + EColorRange translation; + int fontSpacing; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawKeyBar : public SBarInfoCommand +{ + public: + CommandDrawKeyBar(SBarInfo *script) : SBarInfoCommand(script), + number(3), vertical(false), reverseRows(false), iconSize(-1), + rowIconSize(-1), keyOffset(0), rowSize(0) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + AInventory *item = statusBar->CPlayer->mo->Inventory; + if(item == NULL) + return; + int slotOffset = 0; + int rowOffset = 0; + int rowWidth = 0; + for(unsigned int i = 0;i < number+keyOffset;i++) + { + while(!item->Icon.isValid() || !item->IsKindOf(RUNTIME_CLASS(AKey))) + { + item = item->Inventory; + if(item == NULL) + return; + } + if(i >= keyOffset) //Should we start drawing? + { + if(!vertical) + { + statusBar->DrawGraphic(TexMan[item->Icon], x+slotOffset, y+rowOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + rowWidth = rowIconSize == -1 ? TexMan[item->Icon]->GetScaledHeight()+2 : rowIconSize; + } + else + { + statusBar->DrawGraphic(TexMan[item->Icon], x+rowOffset, y+slotOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + rowWidth = rowIconSize == -1 ? TexMan[item->Icon]->GetScaledWidth()+2 : rowIconSize; + } + + // If cmd.special is -1 then the slot size is auto detected + if(iconSize == -1) + { + if(!vertical) + slotOffset += TexMan[item->Icon]->GetScaledWidth() + 2; + else + slotOffset += TexMan[item->Icon]->GetScaledHeight() + 2; + } + else + slotOffset += iconSize; + + if(rowSize > 0 && (i % rowSize == rowSize-1)) + { + if(reverseRows) + rowOffset -= rowWidth; + else + rowOffset += rowWidth; + rowWidth = 0; + slotOffset = 0; + } + } + + item = item->Inventory; + if(item == NULL) + return; + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_IntConst); + number = sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + if(sc.Compare("vertical")) + vertical = true; + else if(!sc.Compare("horizontal")) + sc.ScriptError("Unknown direction '%s'.", sc.String); + sc.MustGetToken(','); + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("reverserows")) + reverseRows = true; + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + if(sc.CheckToken(TK_Auto)) + iconSize = -1; + else + { + sc.MustGetToken(TK_IntConst); + iconSize = sc.Number; + } + sc.MustGetToken(','); + GetCoordinates(sc, fullScreenOffsets, x, y); + if(sc.CheckToken(',')) + { + //key offset + sc.MustGetToken(TK_IntConst); + keyOffset = sc.Number; + if(sc.CheckToken(',')) + { + //max per row/column + sc.MustGetToken(TK_IntConst); + rowSize = sc.Number; + sc.MustGetToken(','); + //row/column spacing (opposite of previous) + if(sc.CheckToken(TK_Auto)) + rowIconSize = -1; + else + { + sc.MustGetToken(TK_IntConst); + rowIconSize = sc.Number; + } + } + } + sc.MustGetToken(';'); + } + protected: + unsigned int number; + bool vertical; + bool reverseRows; + int iconSize; + int rowIconSize; + unsigned int keyOffset; + unsigned int rowSize; + SBarInfoCoordinate x; + SBarInfoCoordinate y; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawBar : public SBarInfoCommand +{ + public: + CommandDrawBar(SBarInfo *script) : SBarInfoCommand(script), + border(0), horizontal(false), reverse(false), foreground(-1), background(-1), + type(HEALTH), inventoryItem(NULL), interpolationSpeed(0), drawValue(0) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(foreground == -1 || statusBar->Images[foreground] == NULL) + return; //don't draw anything. + assert(statusBar->Images[foreground] != NULL); + + FTexture *fg = statusBar->Images[foreground]; + FTexture *bg = (background != -1) ? statusBar->Images[background] : NULL; + + if(border != 0) + { + //Draw the whole foreground + statusBar->DrawGraphic(fg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + } + else + { + // Draw background + if (bg != NULL && bg->GetScaledWidth() == fg->GetScaledWidth() && bg->GetScaledHeight() == fg->GetScaledHeight()) + statusBar->DrawGraphic(bg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + else + statusBar->DrawGraphic(fg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, false, -1, -1, 0, 0, 0, 0, true); + } + + // {cx, cy, cr, cb} + fixed_t clip[4] = {0, 0, 0, 0}; + + fixed_t sizeOfImage = (horizontal ? fg->GetScaledWidth()-border*2 : fg->GetScaledHeight()-border*2)<GetScaledWidth() == fg->GetScaledWidth() && bg->GetScaledHeight() == fg->GetScaledHeight()) + statusBar->DrawGraphic(bg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, false, -1, -1, clip[0], clip[1], clip[2], clip[3]); + else + statusBar->DrawGraphic(fg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, false, -1, -1, clip[0], clip[1], clip[2], clip[3], true); + } + else + statusBar->DrawGraphic(fg, this->x, this->y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), false, false, 0, false, -1, -1, clip[0], clip[1], clip[2], clip[3]); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_StringConst); + foreground = script->newImage(sc.String); + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); + background = script->newImage(sc.String); + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + if(sc.Compare("health")) + { + type = HEALTH; + if(sc.CheckToken(TK_Identifier)) //comparing reference + { + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(inventoryItem)) //must be a kind of inventory + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + } + else if(sc.Compare("armor")) + { + type = ARMOR; + if(sc.CheckToken(TK_Identifier)) + { + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(inventoryItem)) //must be a kind of inventory + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + } + else if(sc.Compare("ammo1")) + type = AMMO1; + else if(sc.Compare("ammo2")) + type = AMMO2; + else if(sc.Compare("ammo")) //request the next string to be an ammo type + { + sc.MustGetToken(TK_Identifier); + type = AMMO; + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(inventoryItem)) //must be a kind of ammo + { + sc.ScriptError("'%s' is not a type of ammo.", sc.String); + } + } + else if(sc.Compare("frags")) + type = FRAGS; + else if(sc.Compare("kills")) + type = KILLS; + else if(sc.Compare("items")) + type = ITEMS; + else if(sc.Compare("secrets")) + type = SECRETS; + else if(sc.Compare("airtime")) + type = AIRTIME; + else if(sc.Compare("poweruptime")) + { + type = POWERUPTIME; + sc.MustGetToken(TK_Identifier); + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(inventoryItem)) + { + sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String); + } + } + else + { + type = INVENTORY; + inventoryItem = PClass::FindClass(sc.String); + if(inventoryItem == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(inventoryItem)) + { + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + } + } + sc.MustGetToken(','); + sc.MustGetToken(TK_Identifier); + if(sc.Compare("horizontal")) + horizontal = true; + else if(!sc.Compare("vertical")) + sc.ScriptError("Unknown direction '%s'.", sc.String); + sc.MustGetToken(','); + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("reverse")) + reverse = true; + else if(sc.Compare("interpolate")) + { + sc.MustGetToken('('); + sc.MustGetToken(TK_IntConst); + interpolationSpeed = sc.Number; + sc.MustGetToken(')'); + } + else + sc.ScriptError("Unkown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + GetCoordinates(sc, fullScreenOffsets, x, y); + if(sc.CheckToken(',')) //border + { + sc.MustGetToken(TK_IntConst); + border = sc.Number; + } + sc.MustGetToken(';'); + + if(type == HEALTH) + interpolationSpeed = script->interpolateHealth ? script->interpolationSpeed : interpolationSpeed; + else if(type == ARMOR) + interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + fixed_t value = 0; + int max = 0; + switch(type) + { + case HEALTH: + value = statusBar->CPlayer->mo->health; + if(value < 0) //health shouldn't display negatives + value = 0; + + if(inventoryItem != NULL) + { + AInventory *item = statusBar->CPlayer->mo->FindInventory(inventoryItem); //max comparer + if(item != NULL) + max = item->Amount; + else + max = 0; + } + else //default to the class's health + max = statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->stamina; + break; + case ARMOR: + value = statusBar->armor != NULL ? statusBar->armor->Amount : 0; + if(inventoryItem != NULL) + { + AInventory *item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + max = item->Amount; + else + max = 0; + } + else + max = 100; + break; + case AMMO1: + value = statusBar->ammocount1; + if(statusBar->ammo1 == NULL) //no ammo, draw as empty + { + value = 0; + max = 1; + } + else + max = statusBar->ammo1->MaxAmount; + break; + case AMMO2: + value = statusBar->ammocount2; + if(statusBar->ammo2 == NULL) //no ammo, draw as empty + { + value = 0; + max = 1; + } + else + max = statusBar->ammo2->MaxAmount; + break; + case AMMO: + { + AInventory *item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + { + value = item->Amount; + max = item->MaxAmount; + } + else + value = 0; + break; + } + case FRAGS: + value = statusBar->CPlayer->fragcount; + max = fraglimit; + break; + case KILLS: + value = level.killed_monsters; + max = level.total_monsters; + break; + case ITEMS: + value = level.found_items; + max = level.total_items; + break; + case SECRETS: + value = level.found_secrets; + max = level.total_secrets; + break; + case INVENTORY: + { + AInventory *item = statusBar->CPlayer->mo->FindInventory(inventoryItem); + if(item != NULL) + { + value = item->Amount; + max = item->MaxAmount; + } + else + value = 0; + break; + } + case AIRTIME: + value = clamp(statusBar->CPlayer->air_finished - level.time, 0, INT_MAX); + max = level.airsupply; + break; + case POWERUPTIME: + { + //Get the PowerupType and check to see if the player has any in inventory. + APowerupGiver *powerupGiver = (APowerupGiver*) GetDefaultByType(inventoryItem); + const PClass *powerupType = powerupGiver->PowerupType; + APowerup *powerup = (APowerup*) statusBar->CPlayer->mo->FindInventory(powerupType); + if(powerup != NULL && powerupType != NULL && powerupGiver != NULL) + { + value = powerup->EffectTics + 1; + if(powerupGiver->EffectTics == 0) //if 0 we need to get the default from the powerup + max = ((APowerup*) GetDefaultByType(powerupType))->EffectTics + 1; + else + max = powerupGiver->EffectTics + 1; + } + break; + } + default: return; + } + + if(border != 0) + value = max - value; //invert since the new drawing method requires drawing the bg on the fg. + if(max != 0 && value > 0) + { + value = (value << FRACBITS) / max; + if(value > FRACUNIT) + value = FRACUNIT; + } + else if(border != 0 && max == 0 && value <= 0) + value = FRACUNIT; + else + value = 0; + if(interpolationSpeed != 0 && (!hudChanged || level.time == 1)) + { + if(value < drawValue) + drawValue -= clamp((drawValue - value) >> 2, 1, FixedDiv(interpolationSpeed<((value - drawValue) >> 2, 1, FixedDiv(interpolationSpeed<CPlayer->ReadyWeapon != NULL) + { + const PClass *readyWeapon = statusBar->CPlayer->ReadyWeapon->GetClass(); + if(((weapon[1] != NULL) && + ((negate && (weapon[0] != readyWeapon && weapon[1] != readyWeapon)) || + (!negate && (weapon[0] == readyWeapon || weapon[1] == readyWeapon)))) || + ((weapon[1] == NULL) && + ((!negate && weapon[0] == readyWeapon) || (negate && weapon[0] != readyWeapon)))) + { + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + //Using StringConst instead of Identifieres is deperecated! + if(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("not")) + { + negate = true; + if(!sc.CheckToken(TK_StringConst)) + sc.MustGetToken(TK_Identifier); + } + } + else + sc.MustGetToken(TK_StringConst); + for(int i = 0;i < 2;i++) + { + weapon[i] = PClass::FindClass(sc.String); + if(weapon[i] == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(weapon[i])) + sc.ScriptError("'%s' is not a type of weapon.", sc.String); + + if(sc.CheckToken(',')) + { + if(!sc.CheckToken(TK_StringConst)) + sc.MustGetToken(TK_Identifier); + } + else + break; + } + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + bool negate; + const PClass *weapon[2]; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandPlayerClass : public SBarInfoCommandFlowControl +{ + public: + CommandPlayerClass(SBarInfo *script) : SBarInfoCommandFlowControl(script) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(statusBar->CPlayer->cls == NULL) + return; //No class so we can not continue + + int spawnClass = statusBar->CPlayer->cls->ClassIndex; + for(unsigned int i = 0;i < classes.Size();i++) + { + if(classes[i] == spawnClass) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + do + { + bool foundClass = false; + for(unsigned int c = 0;c < PlayerClasses.Size();c++) + { + if(stricmp(sc.String, PlayerClasses[c].Type->Meta.GetMetaString(APMETA_DisplayName)) == 0) + { + foundClass = true; + classes.Push(PlayerClasses[c].Type->ClassIndex); + break; + } + } + if(!foundClass) + sc.ScriptError("Unkown PlayerClass '%s'.", sc.String); + if(!sc.CheckToken(',')) + break; + } + while(sc.CheckToken(TK_Identifier)); + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + TArray classes; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandHasWeaponPiece : public SBarInfoCommandFlowControl +{ + public: + CommandHasWeaponPiece(SBarInfo *script) : SBarInfoCommandFlowControl(script), + weapon(NULL), piece(1) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + for(AInventory *inv = statusBar->CPlayer->mo->Inventory;inv != NULL;inv=inv->Inventory) + { + if(inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder))) + { + AWeaponHolder *hold = static_cast(inv); + if(hold->PieceWeapon == weapon) + { + if(hold->PieceMask & (1 << (piece-1))) + SBarInfoCommandFlowControl::Draw(block, statusBar); + break; + } + } + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + weapon = PClass::FindClass(sc.String); + if(weapon == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(weapon)) //must be a weapon + sc.ScriptError("%s is not a kind of weapon.", sc.String); + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + if(sc.Number < 1) + sc.ScriptError("Weapon piece number can not be less than 1."); + piece = sc.Number; + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + const PClass *weapon; + unsigned int piece; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandDrawGem : public SBarInfoCommand +{ + public: + CommandDrawGem(SBarInfo *script) : SBarInfoCommand(script), + wiggle(false), translatable(false), armor(false), reverse(false), + chain(-1), gem(-1), leftPadding(0), rightPadding(0), chainSize(1), + interpolationSpeed(0), drawValue(0), goalValue(0), chainWiggle(0) + { + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + FTexture *chainImg = statusBar->Images[chain]; + FTexture *gemImg = statusBar->Images[gem]; + if(chainImg == NULL) + return; + + SBarInfoCoordinate drawY = y; + if(wiggle && drawValue != goalValue) // Should only wiggle when the value doesn't equal what is being drawn. + drawY += chainWiggle; + int chainWidth = chainImg->GetWidth(); + int offset = (int) (((double) (chainWidth-leftPadding-rightPadding)/100)*drawValue); + statusBar->DrawGraphic(chainImg, x+(offset%chainSize), drawY, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets()); + if(gemImg != NULL) + statusBar->DrawGraphic(gemImg, x+leftPadding+offset, drawY, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translatable); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("wiggle")) + wiggle = true; + else if(sc.Compare("translatable")) + translatable = true; + else if(sc.Compare("armor")) + armor = true; + else if(sc.Compare("interpolate")) + { + sc.MustGetToken('('); + sc.MustGetToken(TK_IntConst); + interpolationSpeed = sc.Number; + sc.MustGetToken(')'); + } + else if(sc.Compare("reverse")) + reverse = true; + else + sc.ScriptError("Unknown drawgem flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + sc.MustGetToken(TK_StringConst); //chain + chain = script->newImage(sc.String); + sc.MustGetToken(','); + sc.MustGetToken(TK_StringConst); //gem + gem = script->newImage(sc.String); + sc.MustGetToken(','); + bool negative = sc.CheckToken('-'); + sc.MustGetToken(TK_IntConst); + leftPadding = (negative ? -1 : 1) * sc.Number; + sc.MustGetToken(','); + negative = sc.CheckToken('-'); + sc.MustGetToken(TK_IntConst); + rightPadding = (negative ? -1 : 1) * sc.Number; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + if(sc.Number < 0) + sc.ScriptError("Chain size must be a positive number."); + chainSize = sc.Number; + sc.MustGetToken(','); + GetCoordinates(sc, fullScreenOffsets, x, y); + sc.MustGetToken(';'); + + if(!armor) + interpolationSpeed = script->interpolateHealth ? script->interpolationSpeed : interpolationSpeed; + else + interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; + } + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + goalValue = armor ? statusBar->armor->Amount : statusBar->CPlayer->mo->health; + int max = armor ? 100 : statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->stamina; + if(max != 0 && goalValue > 0) + { + goalValue = (goalValue*100)/max; + if(goalValue > 100) + goalValue = 100; + } + else + goalValue = 0; + + goalValue = reverse ? 100 - goalValue : goalValue; + + if(interpolationSpeed != 0 && (!hudChanged || level.time == 1)) // At the start force an animation + { + if(goalValue < drawValue) + drawValue -= clamp((drawValue - goalValue) >> 2, 1, interpolationSpeed); + else if(drawValue < goalValue) + drawValue += clamp((goalValue - drawValue) >> 2, 1, interpolationSpeed); + } + else + drawValue = goalValue; + + if(wiggle && level.time & 1) + chainWiggle = pr_chainwiggle() & 1; + } + protected: + bool wiggle; + bool translatable; + bool armor; + bool reverse; + int chain; + int gem; + int leftPadding; + int rightPadding; + unsigned int chainSize; + SBarInfoCoordinate x; + SBarInfoCoordinate y; + + int interpolationSpeed; + int drawValue; + int goalValue; + private: + int chainWiggle; + static FRandom pr_chainwiggle; +}; +FRandom CommandDrawGem::pr_chainwiggle; //use the same method of chain wiggling as heretic. + +//////////////////////////////////////////////////////////////////////////////// + +class CommandWeaponAmmo : public SBarInfoCommandFlowControl +{ + public: + CommandWeaponAmmo(SBarInfo *script) : SBarInfoCommandFlowControl(script), + conditionAnd(false), negate(false) + { + ammo[0] = NULL; + ammo[1] = NULL; + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + if(statusBar->CPlayer->ReadyWeapon != NULL) + { + const PClass *AmmoType1 = statusBar->CPlayer->ReadyWeapon->AmmoType1; + const PClass *AmmoType2 = statusBar->CPlayer->ReadyWeapon->AmmoType2; + bool usesammo1 = (AmmoType1 != NULL); + bool usesammo2 = (AmmoType2 != NULL); + if(!negate && !usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. + { + SBarInfoCommandFlowControl::Draw(block, statusBar); + return; + } + //Or means only 1 ammo type needs to match and means both need to match. + if(ammo[1] != NULL) + { + bool match1 = ((usesammo1 && (AmmoType1 == ammo[0] || AmmoType1 == ammo[1])) || !usesammo1); + bool match2 = ((usesammo2 && (AmmoType2 == ammo[0] || AmmoType2 == ammo[1])) || !usesammo2); + if((!conditionAnd && (match1 || match2)) || (conditionAnd && (match1 && match2))) + { + if(!negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + else if(negate) + { + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + } + else //Every thing here could probably be one long if statement but then it would be more confusing. + { + if((usesammo1 && (AmmoType1 == ammo[0])) || (usesammo2 && (AmmoType2 == ammo[0]))) + { + if(!negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + else if(negate) + { + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + } + } + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("not")) + { + negate = true; + sc.MustGetToken(TK_Identifier); + } + for(int i = 0;i < 2;i++) + { + ammo[i] = PClass::FindClass(sc.String); + if(ammo[i] == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo[i])) //must be a kind of ammo + sc.ScriptError("'%s' is not a type of ammo.", sc.String); + + if(sc.CheckToken(TK_OrOr)) + { + conditionAnd = false; + sc.MustGetToken(TK_Identifier); + } + else if(sc.CheckToken(TK_AndAnd)) + { + conditionAnd = true; + sc.MustGetToken(TK_Identifier); + } + else + break; + } + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + bool conditionAnd; + bool negate; + const PClass *ammo[2]; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class CommandInInventory : public SBarInfoCommandFlowControl +{ + public: + CommandInInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), + conditionAnd(false), negate(false) + { + item[0] = item[1] = NULL; + amount[0] = amount[1] = 0; + } + + void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) + { + AInventory *invItem[2] = { statusBar->CPlayer->mo->FindInventory(item[0]), statusBar->CPlayer->mo->FindInventory(item[1]) }; + if (invItem[0] != NULL && amount[0] > 0 && invItem[0]->Amount < amount[0]) invItem[0] = NULL; + if (invItem[1] != NULL && amount[1] > 0 && invItem[1]->Amount < amount[1]) invItem[1] = NULL; + if(invItem[1] != NULL && conditionAnd) + { + if((invItem[0] != NULL && invItem[1] != NULL) && !negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + else if((invItem[0] == NULL || invItem[1] == NULL) && negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + else if(invItem[1] != NULL && !conditionAnd) + { + if((invItem[0] != NULL || invItem[1] != NULL) && !negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + else if((invItem[0] == NULL && invItem[1] == NULL) && negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + else if((invItem[0] != NULL) && !negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + else if((invItem[0] == NULL) && negate) + SBarInfoCommandFlowControl::Draw(block, statusBar); + } + void Parse(FScanner &sc, bool fullScreenOffsets) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("not")) + { + negate = true; + sc.MustGetToken(TK_Identifier); + } + for(int i = 0;i < 2;i++) + { + item[i] = PClass::FindClass(sc.String); + if(item[i] == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(item[i])) + sc.ScriptError("'%s' is not a type of inventory item.", sc.String); + + if (sc.CheckToken(',')) + { + sc.MustGetNumber(); + amount[i] = sc.Number; + } + + if(sc.CheckToken(TK_OrOr)) + { + conditionAnd = false; + sc.MustGetToken(TK_Identifier); + } + else if(sc.CheckToken(TK_AndAnd)) + { + conditionAnd = true; + sc.MustGetToken(TK_Identifier); + } + else + break; + } + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + } + protected: + bool conditionAnd; + bool negate; + const PClass *item[2]; + int amount[2]; +}; + +//////////////////////////////////////////////////////////////////////////////// + +static const char *SBarInfoCommandNames[] = +{ + "drawimage", "drawnumber", "drawswitchableimage", + "drawmugshot", "drawselectedinventory", + "drawinventorybar", "drawbar", "drawgem", + "drawshader", "drawstring", "drawkeybar", + "gamemode", "playerclass", "aspectratio", + "isselected", "usesammo", "usessecondaryammo", + "hasweaponpiece", "inventorybarnotvisible", + "weaponammo", "ininventory", + NULL +}; + +enum SBarInfoCommands +{ + SBARINFO_DRAWIMAGE, SBARINFO_DRAWNUMBER, SBARINFO_DRAWSWITCHABLEIMAGE, + SBARINFO_DRAWMUGSHOT, SBARINFO_DRAWSELECTEDINVENTORY, + SBARINFO_DRAWINVENTORYBAR, SBARINFO_DRAWBAR, SBARINFO_DRAWGEM, + SBARINFO_DRAWSHADER, SBARINFO_DRAWSTRING, SBARINFO_DRAWKEYBAR, + SBARINFO_GAMEMODE, SBARINFO_PLAYERCLASS, SBARINFO_ASPECTRATIO, + SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO, + SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE, + SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, +}; + +SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc) +{ + if(sc.CheckToken(TK_Identifier)) + { + switch(sc.MatchString(SBarInfoCommandNames)) + { + default: break; + case SBARINFO_DRAWIMAGE: return new CommandDrawImage(script); + case SBARINFO_DRAWSWITCHABLEIMAGE: return new CommandDrawSwitchableImage(script); + case SBARINFO_DRAWSTRING: return new CommandDrawString(script); + case SBARINFO_DRAWNUMBER: return new CommandDrawNumber(script); + case SBARINFO_DRAWMUGSHOT: return new CommandDrawMugShot(script); + case SBARINFO_DRAWSELECTEDINVENTORY: return reinterpret_cast (new CommandDrawSelectedInventory(script)); + case SBARINFO_DRAWSHADER: return new CommandDrawShader(script); + case SBARINFO_DRAWINVENTORYBAR: return new CommandDrawInventoryBar(script); + case SBARINFO_DRAWKEYBAR: return new CommandDrawKeyBar(script); + case SBARINFO_DRAWBAR: return new CommandDrawBar(script); + case SBARINFO_DRAWGEM: return new CommandDrawGem(script); + case SBARINFO_GAMEMODE: return new CommandGameMode(script); + case SBARINFO_USESAMMO: return new CommandUsesAmmo(script); + case SBARINFO_USESSECONDARYAMMO: return new CommandUsesSecondaryAmmo(script); + case SBARINFO_INVENTORYBARNOTVISIBLE: return new CommandInventoryBarNotVisible(script); + case SBARINFO_ASPECTRATIO: return new CommandAspectRatio(script); + case SBARINFO_ISSELECTED: return new CommandIsSelected(script); + case SBARINFO_PLAYERCLASS: return new CommandPlayerClass(script); + case SBARINFO_HASWEAPONPIECE: return new CommandHasWeaponPiece(script); + case SBARINFO_WEAPONAMMO: return new CommandWeaponAmmo(script); + case SBARINFO_ININVENTORY: return new CommandInInventory(script); + } + + sc.ScriptError("Unknown command '%s'.\n", sc.String); + return NULL; + } + + sc.MustGetToken('}'); + return NULL; +} diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp deleted file mode 100644 index 0a986fbbb..000000000 --- a/src/g_shared/sbarinfo_display.cpp +++ /dev/null @@ -1,1765 +0,0 @@ -/* -** sbarinfo_display.cpp -** -** Contains all functions required for the display of custom statusbars. -** -**--------------------------------------------------------------------------- -** Copyright 2008 Braden Obrzut -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. 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. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -*/ - -#include "doomtype.h" -#include "doomstat.h" -#include "v_font.h" -#include "v_video.h" -#include "sbar.h" -#include "r_defs.h" -#include "w_wad.h" -#include "m_random.h" -#include "d_player.h" -#include "st_stuff.h" -#include "r_local.h" -#include "m_swap.h" -#include "a_keys.h" -#include "templates.h" -#include "i_system.h" -#include "sbarinfo.h" -#include "gi.h" -#include "r_translate.h" -#include "r_main.h" -#include "a_weaponpiece.h" -#include "a_strifeglobal.h" -#include "g_level.h" -#include "v_palette.h" -#include "p_acs.h" - -static FRandom pr_chainwiggle; //use the same method of chain wiggling as heretic. - -#define ST_RAMPAGETIME (TICRATE*2) -#define ARTIFLASH_OFFSET (invBarOffset+6) - -EXTERN_CVAR(Int, fraglimit) -EXTERN_CVAR(Int, screenblocks) -EXTERN_CVAR(Bool, vid_fps) -EXTERN_CVAR(Bool, hud_scale) - -enum -{ - imgARTIBOX, - imgSELECTBOX, - imgCURSOR, - imgINVLFGEM1, - imgINVLFGEM2, - imgINVRTGEM1, - imgINVRTGEM2, -}; - -#define ADJUST_RELCENTER(x, y, outX, outY) \ - if(x.RelCenter()) \ - outX = *x + SCREENWIDTH/(hud_scale ? CleanXfac*2 : 2); \ - else \ - outX = *x; \ - if(y.RelCenter()) \ - outY = *y + SCREENHEIGHT/(hud_scale ? CleanYfac*2 : 2); \ - else \ - outY = *y; - -//////////////////////////////////////////////////////////////////////////////// - -SBarInfoCoordinate &SBarInfoCoordinate::Add(int add) -{ - value += add; - return *this; -} - -//////////////////////////////////////////////////////////////////////////////// - -//Used for shading -FBarShader::FBarShader(bool vertical, bool reverse) //make an alpha map -{ - int i; - - Width = vertical ? 2 : 256; - Height = vertical ? 256 : 2; - CalcBitSize(); - - // Fill the column/row with shading values. - // Vertical shaders have have minimum alpha at the top - // and maximum alpha at the bottom, unless flipped by - // setting reverse to true. Horizontal shaders are just - // the opposite. - if (vertical) - { - if (!reverse) - { - for (i = 0; i < 256; ++i) - { - Pixels[i] = i; - Pixels[256+i] = i; - } - } - else - { - for (i = 0; i < 256; ++i) - { - Pixels[i] = 255 - i; - Pixels[256+i] = 255 -i; - } - } - } - else - { - if (!reverse) - { - for (i = 0; i < 256; ++i) - { - Pixels[i*2] = 255 - i; - Pixels[i*2+1] = 255 - i; - } - } - else - { - for (i = 0; i < 256; ++i) - { - Pixels[i*2] = i; - Pixels[i*2+1] = i; - } - } - } - DummySpan[0].TopOffset = 0; - DummySpan[0].Length = vertical ? 256 : 2; - DummySpan[1].TopOffset = 0; - DummySpan[1].Length = 0; -} - -const BYTE *FBarShader::GetColumn(unsigned int column, const Span **spans_out) -{ - if (spans_out != NULL) - { - *spans_out = DummySpan; - } - return Pixels + ((column & WidthMask) << HeightBits); -} - -const BYTE *FBarShader::GetPixels() -{ - return Pixels; -} - -void FBarShader::Unload() -{ -} - -//SBarInfo Display -DSBarInfo::DSBarInfo (SBarInfo *script) : DBaseStatusBar(script->height), - shader_horz_normal(false, false), - shader_horz_reverse(false, true), - shader_vert_normal(true, false), - shader_vert_reverse(true, true) -{ - this->script = script; - - static const char *InventoryBarLumps[] = - { - "ARTIBOX", "SELECTBO", "INVCURS", "INVGEML1", - "INVGEML2", "INVGEMR1", "INVGEMR2", - "USEARTIA", "USEARTIB", "USEARTIC", "USEARTID", - }; - TArray patchnames; - patchnames.Resize(script->Images.Size()+10); - unsigned int i = 0; - for(i = 0;i < script->Images.Size();i++) - { - patchnames[i] = script->Images[i]; - } - for(i = 0;i < 10;i++) - { - patchnames[i+script->Images.Size()] = InventoryBarLumps[i]; - } - for (i = 0;i < numskins;i++) - { - AddFaceToImageCollection (&skins[i], &Images); - } - invBarOffset = script->Images.Size(); - Images.Init(&patchnames[0], patchnames.Size()); - drawingFont = V_GetFont("ConFont"); - oldHealth = 0; - oldArmor = 0; - chainWiggle = 0; - artiflash = 4; - currentPopup = POP_None; - pendingPopup = POP_None; -} - -DSBarInfo::~DSBarInfo () -{ - Images.Uninit(); -} - -void DSBarInfo::Draw (EHudState state) -{ - DBaseStatusBar::Draw(state); - int hud = STBAR_NORMAL; - if(state == HUD_StatusBar) - { - if(script->completeBorder) //Fill the statusbar with the border before we draw. - { - FTexture *b = TexMan[gameinfo.border->b]; - R_DrawBorder(viewwindowx, viewwindowy + viewheight + b->GetHeight(), viewwindowx + viewwidth, SCREENHEIGHT); - if(screenblocks == 10) - screen->FlatFill(viewwindowx, viewwindowy + viewheight, viewwindowx + viewwidth, viewwindowy + viewheight + b->GetHeight(), b, true); - } - if(script->automapbar && automapactive) - { - hud = STBAR_AUTOMAP; - } - else - { - hud = STBAR_NORMAL; - } - } - else if(state == HUD_Fullscreen) - { - hud = STBAR_FULLSCREEN; - } - else - { - hud = STBAR_NONE; - } - bool oldhud_scale = hud_scale; - if(script->huds[hud].forceScaled) //scale the statusbar - { - SetScaled(true, true); - setsizeneeded = true; - if(script->huds[hud].fullScreenOffsets) - hud_scale = true; - } - doCommands(script->huds[hud], 0, 0, script->huds[hud].alpha); - if(CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR)) - { - if(state == HUD_StatusBar) - { - // No overlay? Lets cancel it. - if(script->huds[STBAR_INVENTORY].commands.Size() == 0) - CPlayer->inventorytics = 0; - else - doCommands(script->huds[STBAR_INVENTORY], 0, 0, script->huds[STBAR_INVENTORY].alpha); - } - else if(state == HUD_Fullscreen) - { - if(script->huds[STBAR_INVENTORYFULLSCREEN].commands.Size() == 0) - CPlayer->inventorytics = 0; - else - doCommands(script->huds[STBAR_INVENTORYFULLSCREEN], 0, 0, script->huds[STBAR_INVENTORYFULLSCREEN].alpha); - } - } - if(currentPopup != POP_None) - { - int popbar = 0; - if(currentPopup == POP_Log) - popbar = STBAR_POPUPLOG; - else if(currentPopup == POP_Keys) - popbar = STBAR_POPUPKEYS; - else if(currentPopup == POP_Status) - popbar = STBAR_POPUPSTATUS; - doCommands(script->huds[popbar], script->popups[currentPopup-1].getXOffset(), script->popups[currentPopup-1].getYOffset(), - script->popups[currentPopup-1].getAlpha(script->huds[popbar].alpha)); - } - if(script->huds[hud].forceScaled && script->huds[hud].fullScreenOffsets) - hud_scale = oldhud_scale; -} - -void DSBarInfo::NewGame () -{ - if (CPlayer != NULL) - { - AttachToPlayer (CPlayer); - } -} - -void DSBarInfo::AttachToPlayer (player_t *player) -{ - DBaseStatusBar::AttachToPlayer(player); -// MugShot.CurrentState = NULL; -} - -void DSBarInfo::SetMugShotState (const char *state_name, bool wait_till_done, bool reset) -{ - MugShot.SetState(state_name, wait_till_done, reset); -} - -void DSBarInfo::Tick () -{ - DBaseStatusBar::Tick(); - if(level.time & 1) - chainWiggle = pr_chainwiggle() & 1; - if(!script->interpolateHealth) - { - oldHealth = CPlayer->health; - } - else - { - int health = script->lowerHealthCap ? CPlayer->health : CPlayer->mo->health; - if(oldHealth > health) - { - oldHealth -= clamp((oldHealth - health), 1, script->interpolationSpeed); - } - else if(oldHealth < CPlayer->health) - { - oldHealth += clamp((health - oldHealth), 1, script->interpolationSpeed); - } - } - AInventory *armor = CPlayer->mo != NULL? CPlayer->mo->FindInventory() : NULL; - if(armor == NULL) - { - oldArmor = 0; - } - else - { - if(!script->interpolateArmor) - { - oldArmor = armor->Amount; - } - else - { - if(oldArmor > armor->Amount) - { - oldArmor -= clamp((oldArmor - armor->Amount) >> 2, 1, script->armorInterpolationSpeed); - } - else if(oldArmor < armor->Amount) - { - oldArmor += clamp((armor->Amount - oldArmor) >> 2, 1, script->armorInterpolationSpeed); - } - } - } - if(artiflash) - { - artiflash--; - } - - MugShot.Tick(CPlayer); - if(currentPopup != POP_None) - { - script->popups[currentPopup-1].tick(); - if(script->popups[currentPopup-1].opened == false && script->popups[currentPopup-1].isDoneMoving()) - { - currentPopup = pendingPopup; - if(currentPopup != POP_None) - script->popups[currentPopup-1].open(); - } - } -} - -void DSBarInfo::ReceivedWeapon(AWeapon *weapon) -{ - MugShot.bEvilGrin = true; -} - -void DSBarInfo::FlashItem(const PClass *itemtype) -{ - artiflash = 4; -} - -void DSBarInfo::ShowPop(int popnum) -{ - DBaseStatusBar::ShowPop(popnum); - if(popnum != currentPopup) - { - pendingPopup = popnum; - } - else - pendingPopup = POP_None; - if(currentPopup != POP_None) - script->popups[currentPopup-1].close(); - else - { - currentPopup = pendingPopup; - pendingPopup = POP_None; - if(currentPopup != POP_None) - script->popups[currentPopup-1].open(); - } -} - -void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int alpha) -{ - //prepare ammo counts - AAmmo *ammo1, *ammo2; - int ammocount1, ammocount2; - GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2); - ABasicArmor *armor = CPlayer->mo->FindInventory(); - int health = CPlayer->mo->health; - int armorAmount = armor != NULL ? armor->Amount : 0; - if(script->interpolateHealth) - { - health = oldHealth; - } - if(script->interpolateArmor) - { - armorAmount = oldArmor; - } - for(unsigned int i = 0;i < block.commands.Size();i++) - { - SBarInfoCommand& cmd = block.commands[i]; - switch(cmd.type) //read and execute all the commands - { - case SBARINFO_DRAWSWITCHABLEIMAGE: //draw the alt image if we don't have the item else this is like a normal drawimage - { - // DrawSwitchable image allows 2 or 4 images to be supplied. - // drawAlt toggles these: - // 1 = first image - // 2 = second image - // 3 = thrid image - // 0 = last image - int drawAlt = 0; - if((cmd.flags & DRAWIMAGE_WEAPONSLOT)) //weaponslots - { - drawAlt = 1; //draw off state until we know we have something. - for (int i = 0; i < CPlayer->weapons.Slots[cmd.value].Size(); i++) - { - const PClass *weap = CPlayer->weapons.Slots[cmd.value].GetWeapon(i); - if(weap == NULL) - { - continue; - } - else if(CPlayer->mo->FindInventory(weap) != NULL) - { - drawAlt = 0; - break; - } - } - } - else if((cmd.flags & DRAWIMAGE_INVULNERABILITY)) - { - if(CPlayer->cheats&CF_GODMODE) - { - drawAlt = 1; - } - } - else if(cmd.flags & DRAWIMAGE_KEYSLOT) - { - bool found1 = false; - bool found2 = false; - drawAlt = 1; - - for(AInventory *item = CPlayer->mo->Inventory;item != NULL;item = item->Inventory) - { - if(item->IsKindOf(RUNTIME_CLASS(AKey))) - { - int keynum = static_cast(item)->KeyNumber; - - if(keynum == cmd.value) - found1 = true; - if(cmd.flags & DRAWIMAGE_SWITCHABLE_AND && keynum == cmd.special4) // two keys - found2 = true; - } - } - - if(cmd.flags & DRAWIMAGE_SWITCHABLE_AND) - { - if(found1 && found2) - drawAlt = 0; - else if(found1) - drawAlt = 2; - else if(found2) - drawAlt = 3; - } - else - { - if(found1) - drawAlt = 0; - } - } - else //check the inventory items and draw selected sprite - { - AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); - if(item == NULL || item->Amount == 0) - drawAlt = 1; - if((cmd.flags & DRAWIMAGE_SWITCHABLE_AND)) - { - item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[1])); - if((item != NULL && item->Amount != 0) && drawAlt == 0) //both - { - drawAlt = 0; - } - else if((item != NULL && item->Amount != 0) && drawAlt == 1) //2nd - { - drawAlt = 3; - } - else if((item == NULL || item->Amount == 0) && drawAlt == 0) //1st - { - drawAlt = 2; - } - } - } - if(drawAlt != 0) //draw 'off' image - { - if(cmd.special != -1 && drawAlt == 1) - DrawGraphic(Images[cmd.special], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET)); - else if(cmd.special2 != -1 && drawAlt == 2) - DrawGraphic(Images[cmd.special2], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET)); - else if(cmd.special3 != -1 && drawAlt == 3) - DrawGraphic(Images[cmd.special3], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, (cmd.flags & DRAWIMAGE_OFFSET)); - break; - } - } - case SBARINFO_DRAWIMAGE: - { - FTexture *texture = NULL; - if((cmd.flags & DRAWIMAGE_PLAYERICON)) - texture = TexMan[CPlayer->mo->ScoreIcon]; - else if((cmd.flags & DRAWIMAGE_AMMO1)) - { - if(ammo1 != NULL) - texture = TexMan[ammo1->Icon]; - } - else if((cmd.flags & DRAWIMAGE_AMMO2)) - { - if(ammo2 != NULL) - texture = TexMan[ammo2->Icon]; - } - else if((cmd.flags & DRAWIMAGE_ARMOR)) - { - if(armor != NULL && armor->Amount != 0) - texture = TexMan(armor->Icon); - } - else if((cmd.flags & DRAWIMAGE_WEAPONICON)) - { - AWeapon *weapon = CPlayer->ReadyWeapon; - if(weapon != NULL && weapon->Icon.isValid()) - { - texture = TexMan[weapon->Icon]; - } - } - else if(cmd.flags & DRAWIMAGE_SIGIL) - { - AInventory *item = CPlayer->mo->FindInventory(); - if (item != NULL) - texture = TexMan[item->Icon]; - } - else if(cmd.flags & DRAWIMAGE_HEXENARMOR) - { - AHexenArmor *harmor = CPlayer->mo->FindInventory(); - if (harmor != NULL) - { - if (harmor->Slots[cmd.value] > 0 && harmor->SlotsIncrement[cmd.value] > 0) - { - //combine the alpha values - alpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) MIN (OPAQUE, Scale(harmor->Slots[cmd.value], OPAQUE, harmor->SlotsIncrement[cmd.value])) / (double) OPAQUE) * FRACUNIT); - texture = Images[cmd.image_index]; - } - else - break; - } - } - else if((cmd.flags & DRAWIMAGE_INVENTORYICON)) - texture = TexMan[cmd.sprite_index]; - else if(cmd.image_index >= 0) - texture = Images[cmd.image_index]; - - // if we reach here with DRAWIMAGE_HEXENARMOR set we know we want it to be dim. - DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, (cmd.flags & (DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM))); - break; - } - case SBARINFO_DRAWNUMBER: - { - int value = cmd.value; - if(drawingFont != cmd.font) - { - drawingFont = cmd.font; - } - if(cmd.flags & DRAWNUMBER_HEALTH) - { - value = health; - if(script->lowerHealthCap && value < 0) //health shouldn't display negatives - { - value = 0; - } - } - else if(cmd.flags & DRAWNUMBER_ARMOR) - { - value = armorAmount; - } - else if(cmd.flags & DRAWNUMBER_AMMO1) - { - value = ammocount1; - if(ammo1 == NULL) //no ammo, do not draw - { - continue; - } - } - else if(cmd.flags & DRAWNUMBER_AMMO2) - { - value = ammocount2; - if(ammo2 == NULL) //no ammo, do not draw - { - continue; - } - } - else if(cmd.flags & DRAWNUMBER_AMMO) - { - const PClass* ammo = PClass::FindClass(cmd.string[0]); - AInventory* item = CPlayer->mo->FindInventory(ammo); - if(item != NULL) - { - value = item->Amount; - } - else - { - value = 0; - } - } - else if(cmd.flags & DRAWNUMBER_AMMOCAPACITY) - { - const PClass* ammo = PClass::FindClass(cmd.string[0]); - AInventory* item = CPlayer->mo->FindInventory(ammo); - if(item != NULL) - { - value = item->MaxAmount; - } - else - { - value = ((AInventory *)GetDefaultByType(ammo))->MaxAmount; - } - } - else if(cmd.flags & DRAWNUMBER_FRAGS) - value = CPlayer->fragcount; - else if(cmd.flags & DRAWNUMBER_KILLS) - value = level.killed_monsters; - else if(cmd.flags & DRAWNUMBER_MONSTERS) - value = level.total_monsters; - else if(cmd.flags & DRAWNUMBER_ITEMS) - value = level.found_items; - else if(cmd.flags & DRAWNUMBER_TOTALITEMS) - value = level.total_items; - else if(cmd.flags & DRAWNUMBER_SECRETS) - value = level.found_secrets; - else if(cmd.flags & DRAWNUMBER_TOTALSECRETS) - value = level.total_secrets; - else if(cmd.flags & DRAWNUMBER_ARMORCLASS) - { - AHexenArmor *harmor = CPlayer->mo->FindInventory(); - if(harmor != NULL) - { - value = harmor->Slots[0] + harmor->Slots[1] + - harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]; - } - //Hexen counts basic armor also so we should too. - if(armor != NULL) - { - value += armor->SavePercent; - } - value /= (5*FRACUNIT); - } - else if(cmd.flags & DRAWNUMBER_GLOBALVAR) - value = ACS_GlobalVars[cmd.value]; - else if(cmd.flags & DRAWNUMBER_GLOBALARRAY) - value = ACS_GlobalArrays[cmd.value][consoleplayer]; - else if(cmd.flags & DRAWNUMBER_POWERUPTIME) - { - //Get the PowerupType and check to see if the player has any in inventory. - const PClass* powerupType = ((APowerupGiver*) GetDefaultByType(PClass::FindClass(cmd.string[0])))->PowerupType; - APowerup* powerup = (APowerup*) CPlayer->mo->FindInventory(powerupType); - if(powerup != NULL) - { - value = powerup->EffectTics / TICRATE + 1; - } - } - else if(cmd.flags & DRAWNUMBER_INVENTORY) - { - AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); - if(item != NULL) - { - value = item->Amount; - } - else - { - value = 0; - } - } - else if(cmd.flags & DRAWNUMBER_AIRTIME) - { - if(CPlayer->mo->waterlevel < 3) - value = level.airsupply/TICRATE; - else - value = clamp((CPlayer->air_finished - level.time + (TICRATE-1))/TICRATE, 0, INT_MAX); - } - bool fillzeros = !!(cmd.flags & DRAWNUMBER_FILLZEROS); - bool drawshadow = !!(cmd.flags & DRAWNUMBER_DRAWSHADOW); - EColorRange translation = cmd.translation; - if(cmd.special3 != -1 && value <= cmd.special3) //low - translation = cmd.translation2; - else if(cmd.special4 != -1 && value >= cmd.special4) //high - translation = cmd.translation3; - if((cmd.flags & DRAWNUMBER_WHENNOTZERO) && value == 0) - break; - DrawNumber(value, cmd.special, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, translation, cmd.special2, fillzeros, drawshadow); - break; - } - case SBARINFO_DRAWMUGSHOT: - { - bool xdth = false; - bool animatedgodmode = false; - if(cmd.flags & DRAWMUGSHOT_XDEATHFACE) - xdth = true; - if(cmd.flags & DRAWMUGSHOT_ANIMATEDGODMODE) - animatedgodmode = true; - int stateflags = cmd.flags & (DRAWMUGSHOT_XDEATHFACE | DRAWMUGSHOT_ANIMATEDGODMODE | DRAWMUGSHOT_DISABLEGRIN | DRAWMUGSHOT_DISABLEOUCH | DRAWMUGSHOT_DISABLEPAIN | DRAWMUGSHOT_DISABLERAMPAGE); - DrawFace(cmd.string[0], cmd.special, stateflags, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets); - break; - } - case SBARINFO_DRAWSELECTEDINVENTORY: - if(CPlayer->mo->InvSel != NULL && !(level.flags & LEVEL_NOINVENTORYBAR)) - { - int offsetflags = (cmd.flags & DRAWSELECTEDINVENTORY_CENTER) ? DRAWIMAGE_OFFSET_CENTER : 0; - offsetflags |= (cmd.flags & DRAWSELECTEDINVENTORY_CENTERBOTTOM) ? DRAWIMAGE_OFFSET_CENTERBOTTOM : 0; - if((cmd.flags & DRAWSELECTEDINVENTORY_ARTIFLASH) && artiflash) - { - DrawGraphic(Images[ARTIFLASH_OFFSET+(4-artiflash)], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, false, CPlayer->mo->InvSel->Amount <= 0, offsetflags); - } - else - { - DrawGraphic(TexMan(CPlayer->mo->InvSel->Icon), cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, false, CPlayer->mo->InvSel->Amount <= 0, offsetflags); - } - if((cmd.flags & DRAWSELECTEDINVENTORY_ALWAYSSHOWCOUNTER) || CPlayer->mo->InvSel->Amount != 1) - { - if(drawingFont != cmd.font) - { - drawingFont = cmd.font; - } - DrawNumber(CPlayer->mo->InvSel->Amount, 3, cmd.sbcoord2, cmd.sbcoord3, xOffset, yOffset, alpha, block.fullScreenOffsets, cmd.translation, cmd.special4, false, !!(cmd.flags & DRAWSELECTEDINVENTORY_DRAWSHADOW)); - } - } - else if((cmd.flags & DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY)) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - case SBARINFO_DRAWINVENTORYBAR: - { - bool alwaysshow = false; - bool artibox = true; - bool noarrows = false; - bool alwaysshowcounter = false; - bool vertical = false; - int bgalpha = alpha; - if((cmd.flags & DRAWINVENTORYBAR_ALWAYSSHOW)) - alwaysshow = true; - if((cmd.flags & DRAWINVENTORYBAR_NOARTIBOX)) - artibox = false; - if((cmd.flags & DRAWINVENTORYBAR_NOARROWS)) - noarrows = true; - if((cmd.flags & DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER)) - alwaysshowcounter = true; - if(cmd.flags & DRAWINVENTORYBAR_TRANSLUCENT) - bgalpha = fixed_t((((double) alpha / (double) FRACUNIT) * ((double) HX_SHADOW / (double) FRACUNIT)) * FRACUNIT); - if((cmd.flags & DRAWINVENTORYBAR_VERTICAL)) - vertical = true; - if(drawingFont != cmd.font) - { - drawingFont = cmd.font; - } - DrawInventoryBar(cmd.special, cmd.value, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, alwaysshow, cmd.sbcoord2, cmd.sbcoord3, cmd.translation, artibox, noarrows, alwaysshowcounter, bgalpha, vertical); - break; - } - case SBARINFO_DRAWBAR: - { - if(cmd.image_index == -1 || Images[cmd.image_index] == NULL) - break; //don't draw anything. - bool horizontal = !!((cmd.special2 & DRAWBAR_HORIZONTAL)); - bool reverse = !!((cmd.special2 & DRAWBAR_REVERSE)); - fixed_t value = 0; - int max = 0; - if(cmd.flags == DRAWNUMBER_HEALTH) - { - value = health; - if(value < 0) //health shouldn't display negatives - { - value = 0; - } - if(!(cmd.special2 & DRAWBAR_COMPAREDEFAULTS)) - { - AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); //max comparer - if(item != NULL) - { - max = item->Amount; - } - else - { - max = 0; - } - } - else //default to the class's health - { - max = CPlayer->mo->GetMaxHealth() + CPlayer->stamina; - } - } - else if(cmd.flags == DRAWNUMBER_ARMOR) - { - value = armorAmount; - if(!((cmd.special2 & DRAWBAR_COMPAREDEFAULTS) == DRAWBAR_COMPAREDEFAULTS)) - { - AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); //max comparer - if(item != NULL) - { - max = item->Amount; - } - else - { - max = 0; - } - } - else //default to 100 - { - max = 100; - } - } - else if(cmd.flags == DRAWNUMBER_AMMO1) - { - value = ammocount1; - if(ammo1 == NULL) //no ammo, draw as empty - { - value = 0; - max = 1; - } - else - max = ammo1->MaxAmount; - } - else if(cmd.flags == DRAWNUMBER_AMMO2) - { - value = ammocount2; - if(ammo2 == NULL) //no ammo, draw as empty - { - value = 0; - max = 1; - } - else - max = ammo2->MaxAmount; - } - else if(cmd.flags == DRAWNUMBER_AMMO) - { - const PClass* ammo = PClass::FindClass(cmd.string[0]); - AInventory* item = CPlayer->mo->FindInventory(ammo); - if(item != NULL) - { - value = item->Amount; - max = item->MaxAmount; - } - else - { - value = 0; - } - } - else if(cmd.flags == DRAWNUMBER_FRAGS) - { - value = CPlayer->fragcount; - max = fraglimit; - } - else if(cmd.flags == DRAWNUMBER_KILLS) - { - value = level.killed_monsters; - max = level.total_monsters; - } - else if(cmd.flags == DRAWNUMBER_ITEMS) - { - value = level.found_items; - max = level.total_items; - } - else if(cmd.flags == DRAWNUMBER_SECRETS) - { - value = level.found_secrets; - max = level.total_secrets; - } - else if(cmd.flags == DRAWNUMBER_INVENTORY) - { - AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); - if(item != NULL) - { - value = item->Amount; - max = item->MaxAmount; - } - else - { - value = 0; - } - } - else if(cmd.flags & DRAWNUMBER_POWERUPTIME) - { - //Get the PowerupType and check to see if the player has any in inventory. - APowerupGiver* powerupGiver = (APowerupGiver*) GetDefaultByType(PClass::FindClass(cmd.string[0])); - const PClass* powerupType = powerupGiver->PowerupType; - APowerup* powerup = (APowerup*) CPlayer->mo->FindInventory(powerupType); - if(powerup != NULL && powerupType != NULL && powerupGiver != NULL) - { - value = powerup->EffectTics + 1; - if(powerupGiver->EffectTics == 0) //if 0 we need to get the default from the powerup - max = ((APowerup*) GetDefaultByType(powerupType))->EffectTics + 1; - else - max = powerupGiver->EffectTics + 1; - } - } - else if(cmd.flags & DRAWNUMBER_AIRTIME) - { - value = clamp(CPlayer->air_finished - level.time, 0, INT_MAX); - max = level.airsupply; - } - if(cmd.special3 != 0) - value = max - value; //invert since the new drawing method requires drawing the bg on the fg. - if(max != 0 && value > 0) - { - value = (value << FRACBITS) / max; - if(value > FRACUNIT) - value = FRACUNIT; - } - else if(cmd.special3 != 0 && max == 0 && value <= 0) - { - value = FRACUNIT; - } - else - { - value = 0; - } - assert(Images[cmd.image_index] != NULL); - - FTexture *fg = Images[cmd.image_index]; - FTexture *bg = (cmd.special != -1) ? Images[cmd.special] : NULL; - int x, y, w, h; - int cx, cy, cw, ch, cr, cb; - - // These still need to be caclulated for the clear call. - if(!block.fullScreenOffsets) - { - // Calc real screen coordinates for bar - x = *(cmd.x + ST_X + xOffset) << FRACBITS; - y = *(cmd.y + ST_Y + yOffset) << FRACBITS; - w = fg->GetScaledWidth() << FRACBITS; - h = fg->GetScaledHeight() << FRACBITS; - if (Scaled) - { - screen->VirtualToRealCoordsFixed(x, y, w, h, 320, 200, true); - } - x >>= FRACBITS; - y >>= FRACBITS; - w = (w + FRACUNIT/2) >> FRACBITS; - h = (h + FRACUNIT/2) >> FRACBITS; - } - else - { - ADJUST_RELCENTER(cmd.x,cmd.y,x,y) - - x += xOffset; - y += yOffset; - w = fg->GetScaledWidth(); - h = fg->GetScaledHeight(); - - if(vid_fps && x < 0 && y >= 0) - y += 10; - } - - if(cmd.special3 != 0) - { - //Draw the whole foreground - DrawGraphic(fg, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets); - } - else - { - // Draw background - if (bg != NULL && bg->GetScaledWidth() == fg->GetScaledWidth() && bg->GetScaledHeight() == fg->GetScaledHeight()) - { - DrawGraphic(bg, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets); - } - else - { - int clx = x; - int cly = y; - int clw = x + w; - int clh = y + h; - if(block.fullScreenOffsets) - { - clx = x < 0 ? SCREENWIDTH + x : x; - cly = y < 0 ? SCREENHEIGHT + y : y; - clw = clx+w > SCREENWIDTH ? SCREENWIDTH-clx : clx+w; - clh = cly+h > SCREENHEIGHT ? SCREENHEIGHT-cly : cly+h; - } - screen->Clear(clx, cly, clw, clh, GPalette.BlackIndex, 0); - } - } - - if(!block.fullScreenOffsets) - { - // Calc clipping rect for background - cx = *(cmd.x + ST_X + cmd.special3 + xOffset) << FRACBITS; - cy = *(cmd.y + ST_Y + cmd.special3 + yOffset) << FRACBITS; - cw = (fg->GetScaledWidth() - fg->GetScaledLeftOffset() - cmd.special3 * 2) << FRACBITS; - ch = (fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2) << FRACBITS; - if (Scaled) - { - screen->VirtualToRealCoordsFixed(cx, cy, cw, ch, 320, 200, true); - } - cx >>= FRACBITS; - cy >>= FRACBITS; - cw = (cw + FRACUNIT/2) >> FRACBITS; - ch = (ch + FRACUNIT/2) >> FRACBITS; - } - else - { - ADJUST_RELCENTER(cmd.x,cmd.y,cx,cy) - - cx += cmd.special3 + xOffset; - cy += cmd.special3 + yOffset; - cw = fg->GetScaledWidth() - fg->GetScaledLeftOffset() - cmd.special3 * 2; - ch = fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2; - if(vid_fps && x < 0 && y >= 0) - y += 10; - } - - if (horizontal) - { - if ((cmd.special3 != 0 && reverse) || (cmd.special3 == 0 && !reverse)) - { // left to right - cr = cx + FixedMul(cw, value); - } - else - { // right to left - cr = cx + cw; - cx += FixedMul(cw, FRACUNIT - value); - } - cb = cy + ch; - } - else - { - if ((cmd.special3 != 0 && reverse) || (cmd.special3 == 0 && !reverse)) - { // bottom to top - cb = cy + ch; - cy += FixedMul(ch, FRACUNIT - value); - } - else - { // top to bottom - cb = cy + FixedMul(ch, value); - } - cr = cx + cw; - } - // Fix the clipping for fullscreenoffsets. - if(block.fullScreenOffsets && y < 0) - { - cy = hud_scale ? SCREENHEIGHT + (cy*CleanYfac) : SCREENHEIGHT + cy; - cb = hud_scale ? SCREENHEIGHT + (cb*CleanYfac) : SCREENHEIGHT + cb; - } - else if(block.fullScreenOffsets && hud_scale) - { - cy *= CleanYfac; - cb *= CleanYfac; - } - if(block.fullScreenOffsets && x < 0) - { - cx = hud_scale ? SCREENWIDTH + (cx*CleanXfac) : SCREENWIDTH + cx; - cr = hud_scale ? SCREENWIDTH + (cr*CleanXfac) : SCREENWIDTH + cr; - } - else if(block.fullScreenOffsets && hud_scale) - { - cx *= CleanXfac; - cr *= CleanXfac; - } - - // Draw background - if(cmd.special3 != 0) - { - if (bg != NULL && bg->GetScaledWidth() == fg->GetScaledWidth() && bg->GetScaledHeight() == fg->GetScaledHeight()) - { - if(!block.fullScreenOffsets) - { - screen->DrawTexture(bg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_ClipLeft, cx, - DTA_ClipTop, cy, - DTA_ClipRight, cr, - DTA_ClipBottom, cb, - DTA_Alpha, alpha, - TAG_DONE); - } - else - { - screen->DrawTexture(bg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_ClipLeft, cx, - DTA_ClipTop, cy, - DTA_ClipRight, cr, - DTA_ClipBottom, cb, - DTA_Alpha, alpha, - DTA_HUDRules, HUD_Normal, - TAG_DONE); - } - } - else - { - screen->Clear(cx, cy, cr, cb, GPalette.BlackIndex, 0); - } - } - else - { - if(!block.fullScreenOffsets) - { - screen->DrawTexture(fg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_ClipLeft, cx, - DTA_ClipTop, cy, - DTA_ClipRight, cr, - DTA_ClipBottom, cb, - DTA_Alpha, alpha, - TAG_DONE); - } - else - { - screen->DrawTexture(fg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_ClipLeft, cx, - DTA_ClipTop, cy, - DTA_ClipRight, cr, - DTA_ClipBottom, cb, - DTA_Alpha, alpha, - DTA_HUDRules, HUD_Normal, - TAG_DONE); - } - } - break; - } - case SBARINFO_DRAWGEM: - { - int value = (cmd.flags & DRAWGEM_ARMOR) ? armorAmount : health; - int max = (cmd.flags & DRAWGEM_ARMOR) ? 100 : CPlayer->mo->GetMaxHealth() + CPlayer->stamina; - bool wiggle = false; - bool translate = !!(cmd.flags & DRAWGEM_TRANSLATABLE); - if(max != 0 || value < 0) - { - value = (value*100)/max; - if(value > 100) - value = 100; - } - else - { - value = 0; - } - value = (cmd.flags & DRAWGEM_REVERSE) ? 100 - value : value; - if(health != CPlayer->health) - { - wiggle = !!(cmd.flags & DRAWGEM_WIGGLE); - } - DrawGem(Images[cmd.special], Images[cmd.image_index], value, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, cmd.special2, cmd.special3, cmd.special4+1, wiggle, translate); - break; - } - case SBARINFO_DRAWSHADER: - { - FBarShader *const shaders[4] = - { - &shader_horz_normal, &shader_horz_reverse, - &shader_vert_normal, &shader_vert_reverse - }; - bool vertical = !!(cmd.flags & DRAWSHADER_VERTICAL); - bool reverse = !!(cmd.flags & DRAWSHADER_REVERSE); - SBarInfoCoordinate x = cmd.x + xOffset; - SBarInfoCoordinate y = cmd.y + yOffset; - int w = cmd.special; - int h = cmd.special2; - if(!block.fullScreenOffsets) - { - x += ST_X; - y += ST_Y; - if(Scaled) - { - int tmpX = *x; - int tmpY = *y; - screen->VirtualToRealCoordsInt(tmpX, tmpY, w, h, 320, 200, true); - x.SetCoord(tmpX); - y.SetCoord(tmpY); - } - } - else - { - if(vid_fps && *x < 0 && *y >= 0) - y += 10; - } - if(!block.fullScreenOffsets) - { - screen->DrawTexture (shaders[(vertical << 1) + reverse], *x, *y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_Alpha, alpha, - DTA_AlphaChannel, true, - DTA_FillColor, 0, - TAG_DONE); - } - else - { - int rx, ry; - ADJUST_RELCENTER(x,y,rx,ry) - - screen->DrawTexture (shaders[(vertical << 1) + reverse], rx, ry, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_Alpha, alpha, - DTA_AlphaChannel, true, - DTA_FillColor, 0, - DTA_HUDRules, HUD_Normal, - TAG_DONE); - } - break; - } - case SBARINFO_DRAWSTRING: - if(drawingFont != cmd.font) - { - drawingFont = cmd.font; - } - DrawString(cmd.string[0], cmd.x - drawingFont->StringWidth(cmd.string[0]), cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, cmd.translation, cmd.special); - break; - case SBARINFO_DRAWKEYBAR: - { - bool vertical = !!(cmd.flags & DRAWKEYBAR_VERTICAL); - AInventory *item = CPlayer->mo->Inventory; - if(item == NULL) - break; - int slotOffset = 0; - int rowOffset = 0; - int rowWidth = 0; - for(int i = 0;i < cmd.value+cmd.special2;i++) - { - while(!item->Icon.isValid() || !item->IsKindOf(RUNTIME_CLASS(AKey))) - { - item = item->Inventory; - if(item == NULL) - goto FinishDrawKeyBar; - } - if(i >= cmd.special2) //Should we start drawing? - { - if(!vertical) - { - DrawGraphic(TexMan[item->Icon], cmd.x+slotOffset, cmd.y+rowOffset, xOffset, yOffset, alpha, block.fullScreenOffsets); - rowWidth = cmd.special4 == -1 ? TexMan[item->Icon]->GetScaledHeight()+2 : cmd.special4; - } - else - { - DrawGraphic(TexMan[item->Icon], cmd.x+rowOffset, cmd.y+slotOffset, xOffset, yOffset, alpha, block.fullScreenOffsets); - rowWidth = cmd.special4 == -1 ? TexMan[item->Icon]->GetScaledWidth()+2 : cmd.special4; - } - - // If cmd.special is -1 then the slot size is auto detected - if(cmd.special == -1) - { - if(!vertical) - slotOffset += TexMan[item->Icon]->GetScaledWidth() + 2; - else - slotOffset += TexMan[item->Icon]->GetScaledHeight() + 2; - } - else - slotOffset += cmd.special; - - if(cmd.special3 > 0 && (i % cmd.special3 == cmd.special3-1)) - { - if(cmd.flags & DRAWKEYBAR_REVERSEROWS) - rowOffset -= rowWidth; - else - rowOffset += rowWidth; - rowWidth = 0; - slotOffset = 0; - } - } - - item = item->Inventory; - if(item == NULL) - break; - } - FinishDrawKeyBar: - break; - } - case SBARINFO_GAMEMODE: - if(((cmd.flags & GAMETYPE_SINGLEPLAYER) && !multiplayer) || - ((cmd.flags & GAMETYPE_DEATHMATCH) && deathmatch) || - ((cmd.flags & GAMETYPE_COOPERATIVE) && multiplayer && !deathmatch) || - ((cmd.flags & GAMETYPE_TEAMGAME) && teamplay)) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - case SBARINFO_PLAYERCLASS: - { - if(CPlayer->cls == NULL) break; //No class so we can not continue - int spawnClass = CPlayer->cls->ClassIndex; - if(cmd.special == spawnClass || cmd.special2 == spawnClass || cmd.special3 == spawnClass) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - } - case SBARINFO_ASPECTRATIO: - if(CheckRatio(screen->GetWidth(), screen->GetHeight()) == cmd.value) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - case SBARINFO_ISSELECTED: - if(CPlayer->ReadyWeapon != NULL) - { - const PClass *weapon1 = PClass::FindClass(cmd.string[0]); - const PClass *weapon2 = PClass::FindClass(cmd.string[1]); - if(weapon2 != NULL) - { - if((cmd.flags & SBARINFOEVENT_NOT) && (weapon1 != CPlayer->ReadyWeapon->GetClass() && weapon2 != CPlayer->ReadyWeapon->GetClass())) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - else if(!(cmd.flags & SBARINFOEVENT_NOT) && (weapon1 == CPlayer->ReadyWeapon->GetClass() || weapon2 == CPlayer->ReadyWeapon->GetClass())) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - else - { - if(!(cmd.flags & SBARINFOEVENT_NOT) && weapon1 == CPlayer->ReadyWeapon->GetClass()) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - else if((cmd.flags & SBARINFOEVENT_NOT) && weapon1 != CPlayer->ReadyWeapon->GetClass()) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - } - break; - case SBARINFO_USESAMMO: - if ((CPlayer->ReadyWeapon != NULL && (CPlayer->ReadyWeapon->AmmoType1 != NULL || CPlayer->ReadyWeapon->AmmoType2 != NULL)) ^ - !!(cmd.flags & SBARINFOEVENT_NOT)) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - case SBARINFO_USESSECONDARYAMMO: - if((CPlayer->ReadyWeapon != NULL && CPlayer->ReadyWeapon->AmmoType2 != NULL && CPlayer->ReadyWeapon->AmmoType2 != CPlayer->ReadyWeapon->AmmoType1 && !(cmd.flags & SBARINFOEVENT_NOT)) || - ((CPlayer->ReadyWeapon == NULL || CPlayer->ReadyWeapon->AmmoType2 == NULL || CPlayer->ReadyWeapon->AmmoType2 == CPlayer->ReadyWeapon->AmmoType1) && cmd.flags & SBARINFOEVENT_NOT)) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - break; - case SBARINFO_HASWEAPONPIECE: - { - AInventory *inv; - AWeaponHolder *hold; - const PClass *weapon = PClass::FindClass(cmd.string[0]); - for(inv = CPlayer->mo->Inventory;inv != NULL;inv=inv->Inventory) - { - if(inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder))) - { - hold = static_cast(inv); - if(hold->PieceWeapon == weapon) - { - if(hold->PieceMask & (1 << (cmd.value-1))) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - break; - } - } - } - break; - } - case SBARINFO_INVENTORYBARNOTVISIBLE: - if(CPlayer->inventorytics <= 0 || (level.flags & LEVEL_NOINVENTORYBAR)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - break; - case SBARINFO_WEAPONAMMO: - if(CPlayer->ReadyWeapon != NULL) - { - const PClass *AmmoType1 = CPlayer->ReadyWeapon->AmmoType1; - const PClass *AmmoType2 = CPlayer->ReadyWeapon->AmmoType2; - const PClass *IfAmmo1 = PClass::FindClass(cmd.string[0]); - const PClass *IfAmmo2 = (cmd.flags & SBARINFOEVENT_OR) || (cmd.flags & SBARINFOEVENT_AND) ? - PClass::FindClass(cmd.string[1]) : NULL; - bool usesammo1 = (AmmoType1 != NULL); - bool usesammo2 = (AmmoType2 != NULL); - if(!(cmd.flags & SBARINFOEVENT_NOT) && !usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - break; - } - //Or means only 1 ammo type needs to match and means both need to match. - if((cmd.flags & SBARINFOEVENT_OR) || (cmd.flags & SBARINFOEVENT_AND)) - { - bool match1 = ((usesammo1 && (AmmoType1 == IfAmmo1 || AmmoType1 == IfAmmo2)) || !usesammo1); - bool match2 = ((usesammo2 && (AmmoType2 == IfAmmo1 || AmmoType2 == IfAmmo2)) || !usesammo2); - if(((cmd.flags & SBARINFOEVENT_OR) && (match1 || match2)) || ((cmd.flags & SBARINFOEVENT_AND) && (match1 && match2))) - { - if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - else if(cmd.flags & SBARINFOEVENT_NOT) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - } - else //Every thing here could probably be one long if statement but then it would be more confusing. - { - if((usesammo1 && (AmmoType1 == IfAmmo1)) || (usesammo2 && (AmmoType2 == IfAmmo1))) - { - if(!(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - else if(cmd.flags & SBARINFOEVENT_NOT) - { - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - } - } - break; - case SBARINFO_ININVENTORY: - { - AInventory *item1 = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); - AInventory *item2 = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[1])); - if (item1 != NULL && cmd.special2 > 0 && item1->Amount < cmd.special2) item1 = NULL; - if (item2 != NULL && cmd.special3 > 0 && item2->Amount < cmd.special3) item2 = NULL; - if(cmd.flags & SBARINFOEVENT_AND) - { - if((item1 != NULL && item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - else if((item1 == NULL || item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - else if(cmd.flags & SBARINFOEVENT_OR) - { - if((item1 != NULL || item2 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - else if((item1 == NULL && item2 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - } - else if((item1 != NULL) && !(cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - else if((item1 == NULL) && (cmd.flags & SBARINFOEVENT_NOT)) - doCommands(cmd.subBlock, xOffset, yOffset, alpha); - break; - } - } - } -} - -//draws an image with the specified flags -void DSBarInfo::DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, - bool translate, bool dim, int offsetflags) //flags -{ - if (texture == NULL) - return; - - if(offsetflags & DRAWIMAGE_OFFSET_CENTER) - { - x -= (texture->GetScaledWidth()/2)-texture->LeftOffset; - y -= (texture->GetScaledHeight()/2)-texture->TopOffset; - } - - x += xOffset; - y += yOffset; - int w, h; - if(!fullScreenOffsets) - { - // I'll handle the conversion from fixed to int myself for more control - fixed_t fx = (x + ST_X).Coordinate() << FRACBITS; - fixed_t fy = (y + ST_Y).Coordinate() << FRACBITS; - fixed_t fw = texture->GetScaledWidth() << FRACBITS; - fixed_t fh = texture->GetScaledHeight() << FRACBITS; - if(Scaled) - screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true); - // Round to nearest - w = (fw + (FRACUNIT>>1)) >> FRACBITS; - h = (fh + (FRACUNIT>>1)) >> FRACBITS; - screen->DrawTexture(texture, (fx >> FRACBITS), (fy >> FRACBITS), - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_Translation, translate ? getTranslation() : 0, - DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, - DTA_CenterBottomOffset, (offsetflags & DRAWIMAGE_OFFSET_CENTERBOTTOM), - DTA_Alpha, alpha, - TAG_DONE); - } - else - { - int rx, ry; - ADJUST_RELCENTER(x,y,rx,ry) - - w = texture->GetScaledWidth(); - h = texture->GetScaledHeight(); - if(vid_fps && rx < 0 && ry >= 0) - ry += 10; - screen->DrawTexture(texture, rx, ry, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_Translation, translate ? getTranslation() : 0, - DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, - DTA_CenterBottomOffset, (offsetflags & DRAWIMAGE_OFFSET_CENTERBOTTOM), - DTA_HUDRules, HUD_Normal, - DTA_Alpha, alpha, - TAG_DONE); - } -} - -void DSBarInfo::DrawString(const char* str, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing, bool drawshadow) -{ - x += spacing; - int ax = *x; - int ay = *y; - if(fullScreenOffsets) - { - ADJUST_RELCENTER(x,y,ax,ay) - } - while(*str != '\0') - { - if(*str == ' ') - { - ax += drawingFont->GetSpaceWidth(); - str++; - continue; - } - int width; - if(script->spacingCharacter == '\0') //No monospace? - width = drawingFont->GetCharWidth((int) *str); - else - width = drawingFont->GetCharWidth((int) script->spacingCharacter); - FTexture* character = drawingFont->GetChar((int) *str, &width); - if(character == NULL) //missing character. - { - str++; - continue; - } - if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset - ax += (character->LeftOffset+1); //ignore x offsets since we adapt to character size - - int rx, ry, rw, rh; - rx = ax + xOffset; - ry = ay + yOffset; - rw = character->GetScaledWidth(); - rh = character->GetScaledHeight(); - if(!fullScreenOffsets) - { - rx += ST_X; - ry += ST_Y; - if(Scaled) - screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); - } - else - { - if(vid_fps && ax < 0 && ay >= 0) - ry += 10; - } - if(drawshadow) - { - int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT); - if(!fullScreenOffsets) - { - screen->DrawTexture(character, rx+2, ry+2, - DTA_DestWidth, rw, - DTA_DestHeight, rh, - DTA_Alpha, salpha, - DTA_FillColor, 0, - TAG_DONE); - } - else - { - screen->DrawTexture(character, rx+2, ry+2, - DTA_DestWidth, rw, - DTA_DestHeight, rh, - DTA_Alpha, salpha, - DTA_HUDRules, HUD_Normal, - DTA_FillColor, 0, - TAG_DONE); - } - } - if(!fullScreenOffsets) - { - screen->DrawTexture(character, rx, ry, - DTA_DestWidth, rw, - DTA_DestHeight, rh, - DTA_Translation, drawingFont->GetColorTranslation(translation), - DTA_Alpha, alpha, - TAG_DONE); - } - else - { - screen->DrawTexture(character, rx, ry, - DTA_DestWidth, rw, - DTA_DestHeight, rh, - DTA_Translation, drawingFont->GetColorTranslation(translation), - DTA_Alpha, alpha, - DTA_HUDRules, HUD_Normal, - TAG_DONE); - } - if(script->spacingCharacter == '\0') - ax += width + spacing - (character->LeftOffset+1); - else //width gets changed at the call to GetChar() - ax += drawingFont->GetCharWidth((int) script->spacingCharacter) + spacing; - str++; - } -} - -//draws the specified number up to len digits -void DSBarInfo::DrawNumber(int num, int len, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing, bool fillzeros, bool drawshadow) -{ - FString value; - // 10^9 is a largest we can hold in a 32-bit int. So if we go any larger we have to toss out the positions limit. - int maxval = len <= 9 ? (int) ceil(pow(10., len))-1 : INT_MAX; - if(!fillzeros || len == 1) - num = clamp(num, -maxval, maxval); - else //The community wanted negatives to take the last digit, but we can only do this if there is room - num = clamp(num, len <= 9 ? (int) -(ceil(pow(10., len-1))-1) : INT_MIN, maxval); - value.Format("%d", num); - if(fillzeros) - { - if(num < 0) //We don't want the negative just yet - value.Format("%d", -num); - while(fillzeros && value.Len() < (unsigned int) len) - { - if(num < 0 && value.Len() == (unsigned int) (len-1)) - value.Insert(0, "-"); - else - value.Insert(0, "0"); - } - } - if(script->spacingCharacter == '\0') - x -= int(drawingFont->StringWidth(value)+(spacing * value.Len())); - else //monospaced, so just multiplay the character size - x -= int((drawingFont->GetCharWidth((int) script->spacingCharacter) + spacing) * value.Len()); - DrawString(value, x, y, xOffset, yOffset, alpha, fullScreenOffsets, translation, spacing, drawshadow); -} - -//draws the mug shot -void DSBarInfo::DrawFace(const char *defaultFace, int accuracy, int stateflags, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets) -{ - FTexture *face = MugShot.GetFace(CPlayer, defaultFace, accuracy, stateflags); - if (face != NULL) - { - DrawGraphic(face, x, y, xOffset, yOffset, alpha, fullScreenOffsets); - } -} - -void DSBarInfo::DrawInventoryBar(int type, int num, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool alwaysshow, - SBarInfoCoordinate counterx, SBarInfoCoordinate countery, EColorRange translation, bool drawArtiboxes, bool noArrows, bool alwaysshowcounter, int bgalpha, bool vertical) -{ //yes, there is some Copy & Paste here too - AInventory *item; - int i; - int spacing = 0; - if(!vertical) - spacing = (type != GAME_Strife) ? Images[invBarOffset + imgARTIBOX]->GetScaledWidth() + 1 : Images[invBarOffset + imgCURSOR]->GetScaledWidth() - 1; - else - spacing = (type != GAME_Strife) ? Images[invBarOffset + imgARTIBOX]->GetScaledHeight() + 1 : Images[invBarOffset + imgCURSOR]->GetScaledHeight() - 1; - - // If the player has no artifacts, don't draw the bar - CPlayer->mo->InvFirst = ValidateInvFirst(num); - if(CPlayer->mo->InvFirst != NULL || alwaysshow) - { - for(item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < num; item = item->NextInv(), ++i) - { - SBarInfoCoordinate rx = x + (!vertical ? i*spacing : 0); - SBarInfoCoordinate ry = y + (vertical ? i*spacing : 0); - if(drawArtiboxes) - { - DrawGraphic(Images[invBarOffset + imgARTIBOX], rx, ry, xOffset, yOffset, bgalpha, fullScreenOffsets); - } - if(type != GAME_Strife) //Strife draws the cursor before the icons - DrawGraphic(TexMan(item->Icon), rx, ry, xOffset, yOffset, alpha, fullScreenOffsets, false, item->Amount <= 0); - if(item == CPlayer->mo->InvSel) - { - if(type == GAME_Heretic) - { - DrawGraphic(Images[invBarOffset + imgSELECTBOX], rx, ry+29, xOffset, yOffset, alpha, fullScreenOffsets); - } - else if(type == GAME_Hexen) - { - DrawGraphic(Images[invBarOffset + imgSELECTBOX], rx, ry-1, xOffset, yOffset, alpha, fullScreenOffsets); - } - else if(type == GAME_Strife) - { - DrawGraphic(Images[invBarOffset + imgCURSOR], rx-6, ry-2, xOffset, yOffset, alpha, fullScreenOffsets); - } - else - { - DrawGraphic(Images[invBarOffset + imgSELECTBOX], rx, ry, xOffset, yOffset, alpha, fullScreenOffsets); - } - } - if(type == GAME_Strife) - DrawGraphic(TexMan(item->Icon), rx, ry, xOffset, yOffset, alpha, fullScreenOffsets, false, item->Amount <= 0); - if(alwaysshowcounter || item->Amount != 1) - { - DrawNumber(item->Amount, 3, counterx+(!vertical ? i*spacing : 0), countery+(vertical ? i*spacing : 0), xOffset, yOffset, alpha, fullScreenOffsets, translation); - } - } - for (; i < num && drawArtiboxes; ++i) - { - DrawGraphic(Images[invBarOffset + imgARTIBOX], x + (!vertical ? (i*spacing) : 0), y + (vertical ? (i*spacing) : 0), xOffset, yOffset, bgalpha, fullScreenOffsets); - } - // Is there something to the left? - if (!noArrows && CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst) - { - int offset = type != GAME_Strife ? -12 : 14; - DrawGraphic(Images[!(gametic & 4) ? - invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x + (!vertical ? offset : 0), y + (vertical ? offset : 0), xOffset, yOffset, alpha, fullScreenOffsets); - } - // Is there something to the right? - if (!noArrows && item != NULL) - { - int offset = type != GAME_Strife ? num*31+2 : num*35-4; - DrawGraphic(Images[!(gametic & 4) ? - invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x + (!vertical ? offset : 0), y + (vertical ? offset : 0), xOffset, yOffset, alpha, fullScreenOffsets); - } - } -} - -//draws heretic/hexen style life gems -void DSBarInfo::DrawGem(FTexture* chain, FTexture* gem, int value, SBarInfoCoordinate x, SBarInfoCoordinate y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, int padleft, int padright, int chainsize, - bool wiggle, bool translate) -{ - if(chain == NULL) - return; - if(value > 100) - value = 100; - else if(value < 0) - value = 0; - if(wiggle) - y += chainWiggle; - int chainWidth = chain->GetWidth(); - int offset = (int) (((double) (chainWidth-padleft-padright)/100)*value); - DrawGraphic(chain, x+(offset%chainsize), y, xOffset, yOffset, alpha, fullScreenOffsets); - if(gem != NULL) - DrawGraphic(gem, x+padleft+offset, y, xOffset, yOffset, alpha, fullScreenOffsets, translate); -} - -FRemapTable* DSBarInfo::getTranslation() -{ - if(gameinfo.gametype & GAME_Raven) - return translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)]; - return translationtables[TRANSLATION_Players][int(CPlayer - players)]; -} - -IMPLEMENT_CLASS(DSBarInfo); - -DBaseStatusBar *CreateCustomStatusBar (int script) -{ - if(SBarInfoScript[script] == NULL) - I_FatalError("Tried to create a status bar with no script!"); - return new DSBarInfo(SBarInfoScript[script]); -} - -DBaseStatusBar *CreateDoomStatusBar () -{ - return new DSBarInfo(SBarInfoScript[1]); -} diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp deleted file mode 100644 index b6130826b..000000000 --- a/src/g_shared/sbarinfo_parser.cpp +++ /dev/null @@ -1,1622 +0,0 @@ -/* -** sbarinfo_parser.cpp -** -** Reads custom status bar definitions. -** -**--------------------------------------------------------------------------- -** Copyright 2008 Braden Obrzut -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. 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. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -**--------------------------------------------------------------------------- -** -*/ - -#include "doomtype.h" -#include "doomstat.h" -#include "sc_man.h" -#include "v_font.h" -#include "w_wad.h" -#include "d_player.h" -#include "sbar.h" -#include "sbarinfo.h" -#include "templates.h" -#include "m_random.h" -#include "gi.h" -#include "i_system.h" -#include "g_level.h" -#include "p_acs.h" - -SBarInfo *SBarInfoScript[2] = {NULL,NULL}; - -static const char *SBarInfoTopLevel[] = -{ - "base", - "height", - "interpolatehealth", - "interpolatearmor", - "completeborder", - "monospacefonts", - "lowerhealthcap", - "statusbar", - "mugshot", - "createpopup", - NULL -}; - -static const char *StatusBars[] = -{ - "none", - "fullscreen", - "normal", - "automap", - "inventory", - "inventoryfullscreen", - "popuplog", - "popupkeys", - "popupstatus", - NULL -}; - -static const char *SBarInfoRoutineLevel[] = -{ - "drawimage", - "drawnumber", - "drawswitchableimage", - "drawmugshot", - "drawselectedinventory", - "drawinventorybar", - "drawbar", - "drawgem", - "drawshader", - "drawstring", - "drawkeybar", - "gamemode", - "playerclass", - "aspectratio", - "isselected", - "usesammo", - "usessecondaryammo", - "hasweaponpiece", - "inventorybarnotvisible", - "weaponammo", //event - "ininventory", - NULL -}; - -static void FreeSBarInfoScript() -{ - for(int i = 0;i < 2;i++) - { - if (SBarInfoScript[i] != NULL) - { - delete SBarInfoScript[i]; - SBarInfoScript[i] = NULL; - } - } -} - -void SBarInfo::Load() -{ - if(gameinfo.statusbar.IsNotEmpty()) - { - int lump = Wads.CheckNumForFullName(gameinfo.statusbar, true); - if(lump != -1) - { - Printf ("ParseSBarInfo: Loading default status bar definition.\n"); - if(SBarInfoScript[SCRIPT_DEFAULT] == NULL) - SBarInfoScript[SCRIPT_DEFAULT] = new SBarInfo(lump); - else - SBarInfoScript[SCRIPT_DEFAULT]->ParseSBarInfo(lump); - } - } - - if(Wads.CheckNumForName("SBARINFO") != -1) - { - Printf ("ParseSBarInfo: Loading custom status bar definition.\n"); - int lastlump, lump; - lastlump = 0; - while((lump = Wads.FindLump("SBARINFO", &lastlump)) != -1) - { - if(SBarInfoScript[SCRIPT_CUSTOM] == NULL) - SBarInfoScript[SCRIPT_CUSTOM] = new SBarInfo(lump); - else //We now have to load multiple SBarInfo Lumps so the 2nd time we need to use this method instead. - SBarInfoScript[SCRIPT_CUSTOM]->ParseSBarInfo(lump); - } - } - atterm(FreeSBarInfoScript); -} - -//SBarInfo Script Reader -void SBarInfo::ParseSBarInfo(int lump) -{ - gameType = gameinfo.gametype; - bool baseSet = false; - FScanner sc(lump); - sc.SetCMode(true); - while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include)) - { - if(sc.TokenType == TK_Include) - { - sc.MustGetToken(TK_StringConst); - int lump = Wads.CheckNumForFullName(sc.String, true); - if (lump == -1) - sc.ScriptError("Lump '%s' not found", sc.String); - ParseSBarInfo(lump); - continue; - } - switch(sc.MustMatchString(SBarInfoTopLevel)) - { - case SBARINFO_BASE: - baseSet = true; - if(!sc.CheckToken(TK_None)) - sc.MustGetToken(TK_Identifier); - if(sc.Compare("Doom")) - { - int lump = Wads.CheckNumForFullName("sbarinfo/doom.txt", true); - if(lump == -1) - sc.ScriptError("Standard Doom Status Bar not found."); - ParseSBarInfo(lump); - } - else if(sc.Compare("Heretic")) - gameType = GAME_Heretic; - else if(sc.Compare("Hexen")) - gameType = GAME_Hexen; - else if(sc.Compare("Strife")) - gameType = GAME_Strife; - else if(sc.Compare("None")) - gameType = GAME_Any; - else - sc.ScriptError("Bad game name: %s", sc.String); - sc.MustGetToken(';'); - break; - case SBARINFO_HEIGHT: - sc.MustGetToken(TK_IntConst); - this->height = sc.Number; - sc.MustGetToken(';'); - break; - case SBARINFO_INTERPOLATEHEALTH: //mimics heretics interpolated health values. - if(sc.CheckToken(TK_True)) - { - interpolateHealth = true; - } - else - { - sc.MustGetToken(TK_False); - interpolateHealth = false; - } - if(sc.CheckToken(',')) //speed param - { - sc.MustGetToken(TK_IntConst); - this->interpolationSpeed = sc.Number; - } - sc.MustGetToken(';'); - break; - case SBARINFO_INTERPOLATEARMOR: //Since interpolatehealth is such a popular command - if(sc.CheckToken(TK_True)) - { - interpolateArmor = true; - } - else - { - sc.MustGetToken(TK_False); - interpolateArmor = false; - } - if(sc.CheckToken(',')) //speed - { - sc.MustGetToken(TK_IntConst); - this->armorInterpolationSpeed = sc.Number; - } - sc.MustGetToken(';'); - break; - case SBARINFO_COMPLETEBORDER: //draws the border instead of an HOM - if(sc.CheckToken(TK_True)) - { - completeBorder = true; - } - else - { - sc.MustGetToken(TK_False); - completeBorder = false; - } - sc.MustGetToken(';'); - break; - case SBARINFO_MONOSPACEFONTS: - if(sc.CheckToken(TK_True)) - { - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - spacingCharacter = sc.String[0]; - } - else - { - sc.MustGetToken(TK_False); - spacingCharacter = '\0'; - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); //Don't tell anyone we're just ignoring this ;) - } - sc.MustGetToken(';'); - break; - case SBARINFO_LOWERHEALTHCAP: - if(sc.CheckToken(TK_False)) - { - lowerHealthCap = false; - } - else - { - sc.MustGetToken(TK_True); - lowerHealthCap = true; - } - sc.MustGetToken(';'); - break; - case SBARINFO_STATUSBAR: - { - if(!baseSet) //If the user didn't explicitly define a base, do so now. - gameType = GAME_Any; - int barNum = 0; - if(!sc.CheckToken(TK_None)) - { - sc.MustGetToken(TK_Identifier); - barNum = sc.MustMatchString(StatusBars); - } - this->huds[barNum] = SBarInfoBlock(); - if(sc.CheckToken(',')) - { - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("forcescaled")) - { - this->huds[barNum].forceScaled = true; - } - else if(sc.Compare("fullscreenoffsets")) - { - this->huds[barNum].fullScreenOffsets = true; - } - else - { - sc.ScriptError("Unkown flag '%s'.", sc.String); - } - if(!sc.CheckToken('|') && !sc.CheckToken(',')) - goto FinishStatusBar; //No more args so we must skip over anything else and go to the end. - } - sc.MustGetToken(TK_FloatConst); - this->huds[barNum].alpha = fixed_t(FRACUNIT * sc.Float); - } - FinishStatusBar: - sc.MustGetToken('{'); - if(barNum == STBAR_AUTOMAP) - { - automapbar = true; - } - ParseSBarInfoBlock(sc, this->huds[barNum]); - break; - } - case SBARINFO_MUGSHOT: - { - sc.MustGetToken(TK_StringConst); - FMugShotState state(sc.String); - if(sc.CheckToken(',')) //first loop must be a comma - { - do - { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("health")) - state.bUsesLevels = true; - else if(sc.Compare("health2")) - state.bUsesLevels = state.bHealth2 = true; - else if(sc.Compare("healthspecial")) - state.bUsesLevels = state.bHealthSpecial = true; - else if(sc.Compare("directional")) - state.bDirectional = true; - else - sc.ScriptError("Unknown MugShot state flag '%s'.", sc.String); - } - while(sc.CheckToken(',') || sc.CheckToken('|')); - } - ParseMugShotBlock(sc, state); - int index; - if((index = FindMugShotStateIndex(state.State)) != -1) //We already had this state, remove the old one. - { - MugShotStates.Delete(index); - } - MugShotStates.Push(state); - break; - } - case SBARINFO_CREATEPOPUP: - { - int pop = 0; - sc.MustGetToken(TK_Identifier); - if(sc.Compare("log")) - pop = 0; - else if(sc.Compare("keys")) - pop = 1; - else if(sc.Compare("status")) - pop = 2; - else - sc.ScriptError("Unkown popup: '%s'", sc.String); - Popup &popup = popups[pop]; - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - popup.width = sc.Number; - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - popup.height = sc.Number; - sc.MustGetToken(','); - if(!sc.CheckToken(TK_None)) - { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("slideinbottom")) - { - popup.transition = TRANSITION_SLIDEINBOTTOM; - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - popup.speed = sc.Number; - } - else if(sc.Compare("fade")) - { - popup.transition = TRANSITION_FADE; - sc.MustGetToken(','); - sc.MustGetToken(TK_FloatConst); - popup.speed = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float))); - sc.MustGetToken(','); - sc.MustGetToken(TK_FloatConst); - popup.speed2 = fixed_t(FRACUNIT * (1.0 / (35.0 * sc.Float))); - } - else - sc.ScriptError("Unkown transition type: '%s'", sc.String); - } - popup.init(); - sc.MustGetToken(';'); - break; - } - } - } -} - -void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) -{ - while(sc.CheckToken(TK_Identifier)) - { - SBarInfoCommand cmd; - - switch(cmd.type = sc.MustMatchString(SBarInfoRoutineLevel)) - { - case SBARINFO_DRAWSWITCHABLEIMAGE: - sc.MustGetToken(TK_Identifier); - if(sc.Compare("weaponslot")) - { - cmd.flags = DRAWIMAGE_WEAPONSLOT; - sc.MustGetToken(TK_IntConst); - cmd.value = sc.Number; - } - else if(sc.Compare("invulnerable")) - { - cmd.flags = DRAWIMAGE_INVULNERABILITY; - } - else if(sc.Compare("keyslot")) - { - cmd.flags = DRAWIMAGE_KEYSLOT; - sc.MustGetToken(TK_IntConst); - cmd.value = sc.Number; - } - else - { - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - if(sc.CheckToken(TK_AndAnd)) - { - cmd.flags |= DRAWIMAGE_SWITCHABLE_AND; - if(cmd.flags & DRAWIMAGE_KEYSLOT) - { - sc.MustGetToken(TK_IntConst); - cmd.special4 = sc.Number; - } - else - { - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 1); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.special = newImage(sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.special2 = newImage(sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.special3 = newImage(sc.String); - sc.MustGetToken(','); - } - else - { - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.special = newImage(sc.String); - sc.MustGetToken(','); - } - case SBARINFO_DRAWIMAGE: - { - bool getImage = true; - if(sc.CheckToken(TK_Identifier)) - { - getImage = false; - if(sc.Compare("playericon")) - cmd.flags |= DRAWIMAGE_PLAYERICON; - else if(sc.Compare("ammoicon1")) - cmd.flags |= DRAWIMAGE_AMMO1; - else if(sc.Compare("ammoicon2")) - cmd.flags |= DRAWIMAGE_AMMO2; - else if(sc.Compare("armoricon")) - cmd.flags |= DRAWIMAGE_ARMOR; - else if(sc.Compare("weaponicon")) - cmd.flags |= DRAWIMAGE_WEAPONICON; - else if(sc.Compare("sigil")) - cmd.flags |= DRAWIMAGE_SIGIL; - else if(sc.Compare("hexenarmor")) - { - cmd.flags = DRAWIMAGE_HEXENARMOR; - sc.MustGetToken(TK_Identifier); - if(sc.Compare("armor")) - cmd.value = 0; - else if(sc.Compare("shield")) - cmd.value = 1; - else if(sc.Compare("helm")) - cmd.value = 2; - else if(sc.Compare("amulet")) - cmd.value = 3; - else - sc.ScriptError("Unkown armor type: '%s'", sc.String); - sc.MustGetToken(','); - getImage = true; - } - else if(sc.Compare("translatable")) - { - cmd.flags |= DRAWIMAGE_TRANSLATABLE; - getImage = true; - } - else - { - //sc.CheckToken(TK_Identifier); - cmd.flags |= DRAWIMAGE_INVENTORYICON; - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of Inventory - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - cmd.sprite_index = ((AInventory *)GetDefaultByType(item))->Icon; - cmd.image_index = -1; - } - } - if(getImage) - { - sc.MustGetToken(TK_StringConst); - cmd.image_index = newImage(sc.String); - cmd.sprite_index.SetInvalid(); - } - sc.MustGetToken(','); - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - if(sc.CheckToken(',')) - { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("center")) - cmd.flags |= DRAWIMAGE_OFFSET_CENTER; - else if(sc.Compare("centerbottom")) - cmd.flags |= DRAWIMAGE_OFFSET_CENTERBOTTOM; - else - sc.ScriptError("'%s' is not a valid alignment.", sc.String); - } - sc.MustGetToken(';'); - break; - } - case SBARINFO_DRAWNUMBER: - cmd.special4 = cmd.special3 = -1; - sc.MustGetToken(TK_IntConst); - cmd.special = sc.Number; - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - cmd.font = V_GetFont(sc.String); - if(cmd.font == NULL) - sc.ScriptError("Unknown font '%s'.", sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - cmd.translation = this->GetTranslation(sc, sc.String); - sc.MustGetToken(','); - if(sc.CheckToken(TK_IntConst)) - { - cmd.value = sc.Number; - sc.MustGetToken(','); - } - else - { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("health")) - cmd.flags = DRAWNUMBER_HEALTH; - else if(sc.Compare("armor")) - cmd.flags = DRAWNUMBER_ARMOR; - else if(sc.Compare("ammo1")) - cmd.flags = DRAWNUMBER_AMMO1; - else if(sc.Compare("ammo2")) - cmd.flags = DRAWNUMBER_AMMO2; - else if(sc.Compare("ammo")) //request the next string to be an ammo type - { - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 0); - cmd.flags = DRAWNUMBER_AMMO; - const PClass* ammo = PClass::FindClass(sc.String); - if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo - { - sc.ScriptError("'%s' is not a type of ammo.", sc.String); - } - } - else if(sc.Compare("ammocapacity")) - { - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 0); - cmd.flags = DRAWNUMBER_AMMOCAPACITY; - const PClass* ammo = PClass::FindClass(sc.String); - if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo - { - sc.ScriptError("'%s' is not a type of ammo.", sc.String); - } - } - else if(sc.Compare("frags")) - cmd.flags = DRAWNUMBER_FRAGS; - else if(sc.Compare("kills")) - cmd.flags |= DRAWNUMBER_KILLS; - else if(sc.Compare("monsters")) - cmd.flags |= DRAWNUMBER_MONSTERS; - else if(sc.Compare("items")) - cmd.flags |= DRAWNUMBER_ITEMS; - else if(sc.Compare("totalitems")) - cmd.flags |= DRAWNUMBER_TOTALITEMS; - else if(sc.Compare("secrets")) - cmd.flags |= DRAWNUMBER_SECRETS; - else if(sc.Compare("totalsecrets")) - cmd.flags |= DRAWNUMBER_TOTALSECRETS; - else if(sc.Compare("armorclass")) - cmd.flags |= DRAWNUMBER_ARMORCLASS; - else if(sc.Compare("airtime")) - cmd.flags |= DRAWNUMBER_AIRTIME; - else if(sc.Compare("globalvar")) - { - cmd.flags |= DRAWNUMBER_GLOBALVAR; - sc.MustGetToken(TK_IntConst); - if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS) - sc.ScriptError("Global variable number out of range: %d", sc.Number); - cmd.value = sc.Number; - } - else if(sc.Compare("globalarray")) //acts like variable[playernumber()] - { - cmd.flags |= DRAWNUMBER_GLOBALARRAY; - sc.MustGetToken(TK_IntConst); - if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS) - sc.ScriptError("Global variable number out of range: %d", sc.Number); - cmd.value = sc.Number; - } - else if(sc.Compare("poweruptime")) - { - cmd.flags |= DRAWNUMBER_POWERUPTIME; - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(item)) - { - sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String); - } - } - else - { - cmd.flags = DRAWNUMBER_INVENTORY; - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of ammo - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - sc.MustGetToken(','); - } - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("fillzeros")) - cmd.flags |= DRAWNUMBER_FILLZEROS; - else if(sc.Compare("whennotzero")) - cmd.flags |= DRAWNUMBER_WHENNOTZERO; - else if(sc.Compare("drawshadow")) - cmd.flags |= DRAWNUMBER_DRAWSHADOW; - else - sc.ScriptError("Unknown flag '%s'.", sc.String); - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - if(sc.CheckToken(',')) - { - bool needsComma = false; - if(sc.CheckToken(TK_IntConst)) //font spacing - { - cmd.special2 = sc.Number; - needsComma = true; - } - if(!needsComma || sc.CheckToken(',')) //2nd coloring for "low-on" value - { - sc.MustGetToken(TK_Identifier); - cmd.translation2 = this->GetTranslation(sc, sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - cmd.special3 = sc.Number; - if(sc.CheckToken(',')) //3rd coloring for "high-on" value - { - sc.MustGetToken(TK_Identifier); - cmd.translation3 = this->GetTranslation(sc, sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - cmd.special4 = sc.Number; - } - } - } - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWMUGSHOT: - if(sc.CheckToken(TK_StringConst)) - { - cmd.setString(sc, sc.String, 0, 3, true); - sc.MustGetToken(','); - } - sc.MustGetToken(TK_IntConst); //accuracy - if(sc.Number < 1 || sc.Number > 9) - sc.ScriptError("Expected a number between 1 and 9, got %d instead.", sc.Number); - cmd.special = sc.Number; - sc.MustGetToken(','); - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("xdeathface")) - cmd.flags |= DRAWMUGSHOT_XDEATHFACE; - else if(sc.Compare("animatedgodmode")) - cmd.flags |= DRAWMUGSHOT_ANIMATEDGODMODE; - else if(sc.Compare("disablegrin")) - cmd.flags |= DRAWMUGSHOT_DISABLEGRIN; - else if(sc.Compare("disableouch")) - cmd.flags |= DRAWMUGSHOT_DISABLEOUCH; - else if(sc.Compare("disablepain")) - cmd.flags |= DRAWMUGSHOT_DISABLEPAIN; - else if(sc.Compare("disablerampage")) - cmd.flags |= DRAWMUGSHOT_DISABLERAMPAGE; - else - sc.ScriptError("Unknown flag '%s'.", sc.String); - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWSELECTEDINVENTORY: - { - bool alternateonempty = false; - while(true) //go until we get a font (non-flag) - { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("alternateonempty")) - { - alternateonempty = true; - cmd.flags |= DRAWSELECTEDINVENTORY_ALTERNATEONEMPTY; - } - else if(sc.Compare("artiflash")) - { - cmd.flags |= DRAWSELECTEDINVENTORY_ARTIFLASH; - } - else if(sc.Compare("alwaysshowcounter")) - { - cmd.flags |= DRAWSELECTEDINVENTORY_ALWAYSSHOWCOUNTER; - } - else if(sc.Compare("center")) - { - cmd.flags |= DRAWSELECTEDINVENTORY_CENTER; - } - else if(sc.Compare("centerbottom")) - { - cmd.flags |= DRAWSELECTEDINVENTORY_CENTERBOTTOM; - } - else if(sc.Compare("drawshadow")) - { - cmd.flags |= DRAWSELECTEDINVENTORY_DRAWSHADOW; - } - else - { - cmd.font = V_GetFont(sc.String); - if(cmd.font == NULL) - sc.ScriptError("Unknown font '%s'.", sc.String); - sc.MustGetToken(','); - break; - } - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - cmd.sbcoord2 = cmd.x + 30; - cmd.sbcoord3 = cmd.y + 24; - cmd.translation = CR_GOLD; - if(sc.CheckToken(',')) //more font information - { - this->getCoordinates(sc, block.fullScreenOffsets, cmd.sbcoord2, cmd.sbcoord3); - if(sc.CheckToken(',')) - { - sc.MustGetToken(TK_Identifier); - cmd.translation = this->GetTranslation(sc, sc.String); - if(sc.CheckToken(',')) - { - sc.MustGetToken(TK_IntConst); - cmd.special4 = sc.Number; - } - } - } - if(alternateonempty) - { - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - } - else - { - sc.MustGetToken(';'); - } - break; - } - case SBARINFO_DRAWINVENTORYBAR: - sc.MustGetToken(TK_Identifier); - if(sc.Compare("Doom")) - cmd.special = GAME_Doom; - else if(sc.Compare("Heretic")) - cmd.special = GAME_Heretic; - else if(sc.Compare("Hexen")) - cmd.special = GAME_Hexen; - else if(sc.Compare("Strife")) - cmd.special = GAME_Strife; - else - sc.ScriptError("Unknown style '%s'.", sc.String); - - sc.MustGetToken(','); - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("alwaysshow")) - { - cmd.flags |= DRAWINVENTORYBAR_ALWAYSSHOW; - } - else if(sc.Compare("noartibox")) - { - cmd.flags |= DRAWINVENTORYBAR_NOARTIBOX; - } - else if(sc.Compare("noarrows")) - { - cmd.flags |= DRAWINVENTORYBAR_NOARROWS; - } - else if(sc.Compare("alwaysshowcounter")) - { - cmd.flags |= DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER; - } - else if(sc.Compare("translucent")) - { - cmd.flags |= DRAWINVENTORYBAR_TRANSLUCENT; - } - else if(sc.Compare("vertical")) - { - cmd.flags |= DRAWINVENTORYBAR_VERTICAL; - } - else - { - sc.ScriptError("Unknown flag '%s'.", sc.String); - } - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - sc.MustGetToken(TK_IntConst); - cmd.value = sc.Number; - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - cmd.font = V_GetFont(sc.String); - if(cmd.font == NULL) - sc.ScriptError("Unknown font '%s'.", sc.String); - - sc.MustGetToken(','); - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - cmd.sbcoord2 = cmd.x + 26; - cmd.sbcoord3 = cmd.y + 22; - cmd.translation = CR_GOLD; - if(sc.CheckToken(',')) //more font information - { - this->getCoordinates(sc, block.fullScreenOffsets, cmd.sbcoord2, cmd.sbcoord3); - if(sc.CheckToken(',')) - { - sc.MustGetToken(TK_Identifier); - cmd.translation = this->GetTranslation(sc, sc.String); - if(sc.CheckToken(',')) - { - sc.MustGetToken(TK_IntConst); - cmd.special4 = sc.Number; - } - } - } - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWBAR: - sc.MustGetToken(TK_StringConst); - cmd.image_index = newImage(sc.String); - cmd.sprite_index.SetInvalid(); - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.special = newImage(sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); //yeah, this is the same as drawnumber, there might be a better way to copy it... - if(sc.Compare("health")) - { - cmd.flags = DRAWNUMBER_HEALTH; - if(sc.CheckToken(TK_Identifier)) //comparing reference - { - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of inventory - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - else - cmd.special2 = DRAWBAR_COMPAREDEFAULTS; - } - else if(sc.Compare("armor")) - { - cmd.flags = DRAWNUMBER_ARMOR; - if(sc.CheckToken(TK_Identifier)) - { - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("Inventory")->IsAncestorOf(item)) //must be a kind of inventory - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - else - cmd.special2 = DRAWBAR_COMPAREDEFAULTS; - } - else if(sc.Compare("ammo1")) - cmd.flags = DRAWNUMBER_AMMO1; - else if(sc.Compare("ammo2")) - cmd.flags = DRAWNUMBER_AMMO2; - else if(sc.Compare("ammo")) //request the next string to be an ammo type - { - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 0); - cmd.flags = DRAWNUMBER_AMMO; - const PClass* ammo = PClass::FindClass(sc.String); - if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo - { - sc.ScriptError("'%s' is not a type of ammo.", sc.String); - } - } - else if(sc.Compare("frags")) - cmd.flags = DRAWNUMBER_FRAGS; - else if(sc.Compare("kills")) - cmd.flags = DRAWNUMBER_KILLS; - else if(sc.Compare("items")) - cmd.flags = DRAWNUMBER_ITEMS; - else if(sc.Compare("secrets")) - cmd.flags = DRAWNUMBER_SECRETS; - else if(sc.Compare("airtime")) - cmd.flags = DRAWNUMBER_AIRTIME; - else if(sc.Compare("poweruptime")) - { - cmd.flags |= DRAWNUMBER_POWERUPTIME; - sc.MustGetToken(TK_Identifier); - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !PClass::FindClass("PowerupGiver")->IsAncestorOf(item)) - { - sc.ScriptError("'%s' is not a type of PowerupGiver.", sc.String); - } - } - else - { - cmd.flags = DRAWNUMBER_INVENTORY; - cmd.setString(sc, sc.String, 0); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(item)) - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - } - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - if(sc.Compare("horizontal")) - cmd.special2 += DRAWBAR_HORIZONTAL; - else if(!sc.Compare("vertical")) - sc.ScriptError("Unknown direction '%s'.", sc.String); - sc.MustGetToken(','); - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("reverse")) - cmd.special2 += DRAWBAR_REVERSE; - else - sc.ScriptError("Unkown flag '%s'.", sc.String); - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - if(sc.CheckToken(',')) //border - { - sc.MustGetToken(TK_IntConst); - cmd.special3 = sc.Number; - } - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWGEM: - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("wiggle")) - cmd.flags |= DRAWGEM_WIGGLE; - else if(sc.Compare("translatable")) - cmd.flags |= DRAWGEM_TRANSLATABLE; - else if(sc.Compare("armor")) - cmd.flags |= DRAWGEM_ARMOR; - else if(sc.Compare("reverse")) - cmd.flags |= DRAWGEM_REVERSE; - else - sc.ScriptError("Unknown drawgem flag '%s'.", sc.String); - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - sc.MustGetToken(TK_StringConst); //chain - cmd.special = newImage(sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); //gem - cmd.image_index = newImage(sc.String); - cmd.sprite_index.SetInvalid(); - sc.MustGetToken(','); - cmd.special2 = this->getSignedInteger(sc); - sc.MustGetToken(','); - cmd.special3 = this->getSignedInteger(sc); - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - if(sc.Number < 0) - sc.ScriptError("Chain size must be a positive number."); - cmd.special4 = sc.Number; - sc.MustGetToken(','); - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWSHADER: - sc.MustGetToken(TK_IntConst); - cmd.special = sc.Number; - if(sc.Number < 1) - sc.ScriptError("Width must be greater than 1."); - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - cmd.special2 = sc.Number; - if(sc.Number < 1) - sc.ScriptError("Height must be greater than 1."); - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - if(sc.Compare("vertical")) - cmd.flags |= DRAWSHADER_VERTICAL; - else if(!sc.Compare("horizontal")) - sc.ScriptError("Unknown direction '%s'.", sc.String); - sc.MustGetToken(','); - if(sc.CheckToken(TK_Identifier)) - { - if(!sc.Compare("reverse")) - { - sc.ScriptError("Exspected 'reverse', got '%s' instead.", sc.String); - } - cmd.flags |= DRAWSHADER_REVERSE; - sc.MustGetToken(','); - } - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWSTRING: - sc.MustGetToken(TK_Identifier); - cmd.font = V_GetFont(sc.String); - if(cmd.font == NULL) - sc.ScriptError("Unknown font '%s'.", sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - cmd.translation = this->GetTranslation(sc, sc.String); - sc.MustGetToken(','); - sc.MustGetToken(TK_StringConst); - cmd.setString(sc, sc.String, 0, -1, false); - sc.MustGetToken(','); - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - if(sc.CheckToken(',')) //spacing - { - sc.MustGetToken(TK_IntConst); - cmd.special = sc.Number; - } - sc.MustGetToken(';'); - break; - case SBARINFO_DRAWKEYBAR: - sc.MustGetToken(TK_IntConst); - cmd.value = sc.Number; - sc.MustGetToken(','); - sc.MustGetToken(TK_Identifier); - if(sc.Compare("vertical")) - cmd.flags |= DRAWKEYBAR_VERTICAL; - else if(!sc.Compare("horizontal")) - sc.ScriptError("Unknown direction '%s'.", sc.String); - sc.MustGetToken(','); - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("reverserows")) - cmd.flags |= DRAWKEYBAR_REVERSEROWS; - else - sc.ScriptError("Unknown flag '%s'.", sc.String); - if(!sc.CheckToken('|')) - sc.MustGetToken(','); - } - if(sc.CheckToken(TK_Auto)) - cmd.special = -1; - else - { - sc.MustGetToken(TK_IntConst); - cmd.special = sc.Number; - } - sc.MustGetToken(','); - this->getCoordinates(sc, block.fullScreenOffsets, cmd.x, cmd.y); - if(sc.CheckToken(',')) - { - //key offset - sc.MustGetToken(TK_IntConst); - cmd.special2 = sc.Number; - if(sc.CheckToken(',')) - { - //max per row/column - sc.MustGetToken(TK_IntConst); - cmd.special3 = sc.Number; - sc.MustGetToken(','); - //row/column spacing (opposite of previous) - if(sc.CheckToken(TK_Auto)) - cmd.special4 = -1; - else - { - sc.MustGetToken(TK_IntConst); - cmd.special4 = sc.Number; - } - } - } - sc.MustGetToken(';'); - break; - case SBARINFO_GAMEMODE: - while(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("singleplayer")) - cmd.flags |= GAMETYPE_SINGLEPLAYER; - else if(sc.Compare("cooperative")) - cmd.flags |= GAMETYPE_COOPERATIVE; - else if(sc.Compare("deathmatch")) - cmd.flags |= GAMETYPE_DEATHMATCH; - else if(sc.Compare("teamgame")) - cmd.flags |= GAMETYPE_TEAMGAME; - //else I'm removing this error to allow cross port compatiblity. If it doesn't know what a gamemode is lets just ignore it. - // sc.ScriptError("Unknown gamemode: %s", sc.String); - if(sc.CheckToken('{')) - break; - sc.MustGetToken(','); - } - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_PLAYERCLASS: - cmd.special = cmd.special2 = cmd.special3 = -1; - for(int i = 0;i < 3 && sc.CheckToken(TK_Identifier);i++) //up to 3 classes - { - bool foundClass = false; - for(unsigned int c = 0;c < PlayerClasses.Size();c++) - { - if(stricmp(sc.String, PlayerClasses[c].Type->Meta.GetMetaString(APMETA_DisplayName)) == 0) - { - foundClass = true; - if(i == 0) - cmd.special = PlayerClasses[c].Type->ClassIndex; - else if(i == 1) - cmd.special2 = PlayerClasses[c].Type->ClassIndex; - else //should be 2 - cmd.special3 = PlayerClasses[c].Type->ClassIndex; - break; - } - } - if(!foundClass) - sc.ScriptError("Unkown PlayerClass '%s'.", sc.String); - if(sc.CheckToken('{') || i == 2) - goto FinishPlayerClass; - sc.MustGetToken(','); - } - FinishPlayerClass: - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_ASPECTRATIO: - sc.MustGetToken(TK_StringConst); - if(sc.Compare("4:3")) - cmd.value = ASPECTRATIO_4_3; - else if(sc.Compare("16:9")) - cmd.value = ASPECTRATIO_16_9; - else if(sc.Compare("16:10")) - cmd.value = ASPECTRATIO_16_10; - else if(sc.Compare("5:4")) - cmd.value = ASPECTRATIO_5_4; - else - sc.ScriptError("Unkown aspect ratio: %s", sc.String); - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_ISSELECTED: - //Using StringConst instead of Identifieres is deperecated! - if(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("not")) - { - cmd.flags |= SBARINFOEVENT_NOT; - if(!sc.CheckToken(TK_StringConst)) - sc.MustGetToken(TK_Identifier); - } - } - else - sc.MustGetToken(TK_StringConst); - for(int i = 0;i < 2;i++) - { - cmd.setString(sc, sc.String, i); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(item)) - { - sc.ScriptError("'%s' is not a type of weapon.", sc.String); - } - if(sc.CheckToken(',')) - { - if(!sc.CheckToken(TK_StringConst)) - sc.MustGetToken(TK_Identifier); - } - else - break; - } - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_USESSECONDARYAMMO: - case SBARINFO_USESAMMO: - if(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("not")) - cmd.flags |= SBARINFOEVENT_NOT; - else - sc.ScriptError("Expected 'not' got '%s' instead.", sc.String); - } - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_HASWEAPONPIECE: - { - sc.MustGetToken(TK_Identifier); - const PClass* weapon = PClass::FindClass(sc.String); - if(weapon == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(weapon)) //must be a weapon - sc.ScriptError("%s is not a kind of weapon.", sc.String); - cmd.setString(sc, sc.String, 0); - sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - if(sc.Number < 1) - sc.ScriptError("Weapon piece number can not be less than 1."); - cmd.value = sc.Number; - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - } - case SBARINFO_INVENTORYBARNOTVISIBLE: - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_WEAPONAMMO: - sc.MustGetToken(TK_Identifier); - if(sc.Compare("not")) - { - cmd.flags |= SBARINFOEVENT_NOT; - sc.MustGetToken(TK_Identifier); - } - for(int i = 0;i < 2;i++) - { - cmd.setString(sc, sc.String, i); - const PClass* ammo = PClass::FindClass(sc.String); - if(ammo == NULL || !RUNTIME_CLASS(AAmmo)->IsAncestorOf(ammo)) //must be a kind of ammo - { - sc.ScriptError("'%s' is not a type of ammo.", sc.String); - } - if(sc.CheckToken(TK_OrOr)) - { - cmd.flags |= SBARINFOEVENT_OR; - sc.MustGetToken(TK_Identifier); - } - else if(sc.CheckToken(TK_AndAnd)) - { - cmd.flags |= SBARINFOEVENT_AND; - sc.MustGetToken(TK_Identifier); - } - else - break; - } - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - case SBARINFO_ININVENTORY: - cmd.special2 = cmd.special3 = 0; - sc.MustGetToken(TK_Identifier); - if(sc.Compare("not")) - { - cmd.flags |= SBARINFOEVENT_NOT; - sc.MustGetToken(TK_Identifier); - } - for(int i = 0;i < 2;i++) - { - cmd.setString(sc, sc.String, i); - const PClass* item = PClass::FindClass(sc.String); - if(item == NULL || !RUNTIME_CLASS(AInventory)->IsAncestorOf(item)) - { - sc.ScriptError("'%s' is not a type of inventory item.", sc.String); - } - if (sc.CheckToken(',')) - { - sc.MustGetNumber(); - if (i == 0) cmd.special2 = sc.Number; - else cmd.special3 = sc.Number; - } - - if(sc.CheckToken(TK_OrOr)) - { - cmd.flags |= SBARINFOEVENT_OR; - sc.MustGetToken(TK_Identifier); - } - else if(sc.CheckToken(TK_AndAnd)) - { - cmd.flags |= SBARINFOEVENT_AND; - sc.MustGetToken(TK_Identifier); - } - else - break; - } - sc.MustGetToken('{'); - cmd.subBlock.fullScreenOffsets = block.fullScreenOffsets; - this->ParseSBarInfoBlock(sc, cmd.subBlock); - break; - } - block.commands.Push(cmd); - } - sc.MustGetToken('}'); -} - -void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state) -{ - sc.MustGetToken('{'); - while(!sc.CheckToken('}')) - { - FMugShotFrame frame; - bool multiframe = false; - if(sc.CheckToken('{')) - multiframe = true; - do - { - sc.MustGetToken(TK_Identifier); - if(strlen(sc.String) > 5) - sc.ScriptError("MugShot frames cannot exceed 5 characters."); - frame.Graphic.Push(sc.String); - } - while(multiframe && sc.CheckToken(',')); - if(multiframe) - sc.MustGetToken('}'); - frame.Delay = getSignedInteger(sc); - sc.MustGetToken(';'); - state.Frames.Push(frame); - } -} - -void SBarInfo::getCoordinates(FScanner &sc, bool fullScreenOffsets, SBarInfoCoordinate &x, SBarInfoCoordinate &y) -{ - bool negative = false; - bool relCenter = false; - SBarInfoCoordinate *coords[2] = {&x, &y}; - for(int i = 0;i < 2;i++) - { - negative = false; - relCenter = false; - if(i > 0) - sc.MustGetToken(','); - - // [-]INT center - negative = sc.CheckToken('-'); - sc.MustGetToken(TK_IntConst); - coords[i]->Set(negative ? -sc.Number : sc.Number, false); - if(sc.CheckToken('+')) - { - sc.MustGetToken(TK_Identifier); - if(!sc.Compare("center")) - sc.ScriptError("Expected 'center' but got '%s' instead.", sc.String); - relCenter = true; - } - if(fullScreenOffsets) - { - coords[i]->SetRelCenter(relCenter); - } - } - - if(!fullScreenOffsets) - y.SetCoord((negative ? -sc.Number : sc.Number) - (200 - this->height)); -} - -int SBarInfo::getSignedInteger(FScanner &sc) -{ - if(sc.CheckToken('-')) - { - sc.MustGetToken(TK_IntConst); - return -sc.Number; - } - else - { - sc.MustGetToken(TK_IntConst); - return sc.Number; - } -} - -int SBarInfo::newImage(const char *patchname) -{ - if(patchname[0] == '\0' || stricmp(patchname, "nullimage") == 0) - { - return -1; - } - for(unsigned int i = 0;i < this->Images.Size();i++) //did we already load it? - { - if(stricmp(this->Images[i], patchname) == 0) - { - return i; - } - } - return this->Images.Push(patchname); -} - -//converts a string into a tranlation. -EColorRange SBarInfo::GetTranslation(FScanner &sc, const char* translation) -{ - EColorRange returnVal = CR_UNTRANSLATED; - FString namedTranslation; //we must send in "[translation]" - const BYTE *trans_ptr; - namedTranslation.Format("[%s]", translation); - trans_ptr = (const BYTE *)(&namedTranslation[0]); - if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED) - { - sc.ScriptError("Missing definition for color %s.", translation); - } - return returnVal; -} - -SBarInfo::SBarInfo() //make results more predicable -{ - Init(); -} - -SBarInfo::SBarInfo(int lumpnum) -{ - Init(); - ParseSBarInfo(lumpnum); -} - -void SBarInfo::Init() -{ - automapbar = false; - interpolateHealth = false; - interpolateArmor = false; - completeBorder = false; - lowerHealthCap = true; - interpolationSpeed = 8; - armorInterpolationSpeed = 8; - height = 0; - spacingCharacter = '\0'; -} - -SBarInfo::~SBarInfo() -{ - for (size_t i = 0; i < NUMHUDS; ++i) - { - huds[i].commands.Clear(); - } -} - -void SBarInfoCommand::setString(FScanner &sc, const char* source, int strnum, int maxlength, bool exact) -{ - if(!exact) - { - if(maxlength != -1 && strlen(source) > (unsigned int) maxlength) - { - sc.ScriptError("%s is greater than %d characters.", source, maxlength); - return; - } - } - else - { - if(maxlength != -1 && strlen(source) != (unsigned int) maxlength) - { - sc.ScriptError("%s must be %d characters.", source, maxlength); - return; - } - } - string[strnum] = source; -} - -SBarInfoCommand::SBarInfoCommand() //sets the default values for more predicable behavior -{ - type = 0; - special = 0; - special2 = 0; - special3 = 0; - special4 = 0; - flags = 0; - x.Set(0, 0); - y.Set(0, 0); - value = 0; - image_index = 0; - sprite_index.SetInvalid(); - translation = CR_UNTRANSLATED; - translation2 = CR_UNTRANSLATED; - translation3 = CR_UNTRANSLATED; - font = V_GetFont("CONFONT"); -} - -SBarInfoCommand::~SBarInfoCommand() -{ -} - -SBarInfoBlock::SBarInfoBlock() -{ - forceScaled = false; - fullScreenOffsets = false; - alpha = FRACUNIT; -} - -//Popup -Popup::Popup() -{ - transition = TRANSITION_NONE; - height = 320; - width = 200; - speed = 0; - x = 320; - y = 200; - alpha = FRACUNIT; - opened = false; - moving = false; -} - -void Popup::init() -{ - x = width; - y = height; - if(transition == TRANSITION_SLIDEINBOTTOM) - { - x = 0; - } - else if(transition == TRANSITION_FADE) - { - alpha = 0; - x = 0; - y = 0; - } -} - -void Popup::tick() -{ - if(transition == TRANSITION_SLIDEINBOTTOM) - { - if(moving) - { - if(opened) - y -= clamp(height + (y - height), 1, speed); - else - y += clamp(height - y, 1, speed); - } - if(y != 0 && y != height) - moving = true; - else - moving = false; - } - else if(transition == TRANSITION_FADE) - { - if(moving) - { - if(opened) - alpha = clamp(alpha + speed, 0, FRACUNIT); - else - alpha = clamp(alpha - speed2, 0, FRACUNIT); - } - if(alpha == 0 || alpha == FRACUNIT) - moving = false; - else - moving = true; - } - else - { - if(opened) - { - y = 0; - x = 0; - } - else - { - y = height; - x = width; - } - moving = false; - } -} - -bool Popup::isDoneMoving() -{ - return !moving; -} - -int Popup::getXOffset() -{ - return x; -} - -int Popup::getYOffset() -{ - return y; -} - -int Popup::getAlpha(int maxAlpha) -{ - double a = (double) alpha / (double) FRACUNIT; - double b = (double) maxAlpha / (double) FRACUNIT; - return fixed_t((a * b) * FRACUNIT); -} - -void Popup::open() -{ - opened = true; - moving = true; -} - -void Popup::close() -{ - opened = false; - moving = true; -} diff --git a/src/p_acs.cpp b/src/p_acs.cpp index c6f4791c4..6ffabeec3 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -67,7 +67,6 @@ #include "c_bind.h" #include "info.h" #include "r_translate.h" -#include "sbarinfo.h" #include "cmdlib.h" #include "m_png.h" #include "p_setup.h" diff --git a/zdoom.vcproj b/zdoom.vcproj index f31bbbbe2..97a2f1378 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -1864,14 +1872,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -2061,14 +2061,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -2079,6 +2071,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + + + - - + + + + + + - - - + + + - - - @@ -5355,6 +5363,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -5633,7 +5649,7 @@ /> Date: Fri, 1 Jan 2010 09:21:04 +0000 Subject: [PATCH 173/241] - Added Blzut3's Solaris patch. SVN r2070 (trunk) --- docs/rh-log.txt | 1 + src/CMakeLists.txt | 5 ++ src/i_net.cpp | 7 ++ src/m_alloc.cpp | 95 ++++++++++++++++++++++++++++ src/p_switch.cpp | 4 +- src/resourcefiles/file_directory.cpp | 43 +++++++++++++ src/sdl/crashcatcher.c | 6 ++ src/sound/fmodsound.cpp | 2 + src/sound/music_dumb.cpp | 4 +- src/w_zip.h | 4 +- 10 files changed, 165 insertions(+), 6 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 36d6d9a2e..4af0837cd 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -7,6 +7,7 @@ January 1, 2010 (SBARINFO update) inventory items and armortype in drawswitchableimage. January 1, 2010 (Changes by Graf Zahl) +- Added Blzut3's Solaris patch. - Fixed: Heretic's Weredragon (Beast) should not have a melee state. December 31, 2009 (Changes by Graf Zahl) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3184bc6b7..a2a556629 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -774,6 +774,11 @@ add_executable( zdoom WIN32 set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) +if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") + # [BL] Solaris requires these to be explicitly linked. + set( ZDOOM_LIBS ${ZDOOM_LIBS} nsl socket) +endif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") + target_link_libraries( zdoom ${ZDOOM_LIBS} gme gdtoa dumb lzma ) include_directories( . g_doom diff --git a/src/i_net.cpp b/src/i_net.cpp index 739da291e..3ff86f7ec 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -46,6 +46,9 @@ # include # include # include +# ifdef __sun +# include +# endif #endif #include "doomtype.h" @@ -422,7 +425,11 @@ void StartNetwork (bool autoPort) // create communication socket mysocket = UDPsocket (); BindToLocalPort (mysocket, autoPort ? 0 : DOOMPORT); +#ifndef __sun ioctlsocket (mysocket, FIONBIO, &trueval); +#else + fcntl(mysocket, F_SETFL, trueval | O_NONBLOCK); +#endif } void SendAbort (void) diff --git a/src/m_alloc.cpp b/src/m_alloc.cpp index 569b5c94d..e81a5ce31 100644 --- a/src/m_alloc.cpp +++ b/src/m_alloc.cpp @@ -52,11 +52,14 @@ #endif #if defined(__APPLE__) #define _msize(p) malloc_size(p) +#elif defined(__sun) +#define _msize(p) (*((size_t*)(p)-1)) #elif !defined(_WIN32) #define _msize(p) malloc_usable_size(p) // from glibc/FreeBSD #endif #ifndef _DEBUG +#if !defined(__sun) void *M_Malloc(size_t size) { void *block = malloc(size); @@ -83,10 +86,50 @@ void *M_Realloc(void *memblock, size_t size) return block; } #else +void *M_Malloc(size_t size) +{ + void *block = malloc(size+sizeof(size_t)); + + if (block == NULL) + I_FatalError("Could not malloc %zu bytes", size); + + size_t *sizeStore = (size_t *) block; + *sizeStore = size; + block = sizeStore+1; + + GC::AllocBytes += _msize(block); + return block; +} + +void *M_Realloc(void *memblock, size_t size) +{ + if(memblock == NULL) + return M_Malloc(size); + + if (memblock != NULL) + { + GC::AllocBytes -= _msize(memblock); + } + void *block = realloc(((size_t*) memblock)-1, size+sizeof(size_t)); + if (block == NULL) + { + I_FatalError("Could not realloc %zu bytes", size); + } + + size_t *sizeStore = (size_t *) block; + *sizeStore = size; + block = sizeStore+1; + + GC::AllocBytes += _msize(block); + return block; +} +#endif +#else #ifdef _MSC_VER #include #endif +#if !defined(__sun) void *M_Malloc_Dbg(size_t size, const char *file, int lineno) { void *block = _malloc_dbg(size, _NORMAL_BLOCK, file, lineno); @@ -112,8 +155,49 @@ void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) GC::AllocBytes += _msize(block); return block; } +#else +void *M_Malloc_Dbg(size_t size, const char *file, int lineno) +{ + void *block = _malloc_dbg(size+sizeof(size_t), _NORMAL_BLOCK, file, lineno); + + if (block == NULL) + I_FatalError("Could not malloc %zu bytes", size); + + size_t *sizeStore = (size_t *) block; + *sizeStore = size; + block = sizeStore+1; + + GC::AllocBytes += _msize(block); + return block; +} + +void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) +{ + if(memblock == NULL) + return M_Malloc_Dbg(size, file, lineno); + + if (memblock != NULL) + { + GC::AllocBytes -= _msize(memblock); + } + void *block = _realloc_dbg(((size_t*) memblock)-1, size+sizeof(size_t), _NORMAL_BLOCK, file, lineno); + + if (block == NULL) + { + I_FatalError("Could not realloc %zu bytes", size); + } + + size_t *sizeStore = (size_t *) block; + *sizeStore = size; + block = sizeStore+1; + + GC::AllocBytes += _msize(block); + return block; +} +#endif #endif +#if !defined(__sun) void M_Free (void *block) { if (block != NULL) @@ -122,3 +206,14 @@ void M_Free (void *block) free(block); } } +#else +void M_Free (void *block) +{ + if(block != NULL) + { + GC::AllocBytes -= _msize(block); + free(((size_t*) block)-1); + } +} +#endif + diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 9865b65c1..f3b642b05 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -274,11 +274,11 @@ void P_ProcessSwitchDef (FScanner &sc) { if (def2 != NULL) { - free (def2); + M_Free (def2); } if (def1 != NULL) { - free (def1); + M_Free (def1); } return; } diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index cb250ed1e..89fb2be9c 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -41,8 +41,10 @@ #define stat _stat #else #include +#ifndef __sun #include #endif +#endif #include #include #include @@ -197,6 +199,46 @@ int FDirectory::AddDirectory(const char *dirpath) return count; } +#elif defined(__sun) + +int FDirectory::AddDirectory(const char *dirpath) +{ + int count = 0; + TArray scanDirectories; + scanDirectories.Push(dirpath); + for(unsigned int i = 0;i < scanDirectories.Size();i++) + { + DIR* directory = opendir(scanDirectories[i].GetChars()); + if (directory == NULL) + { + Printf("Could not ready directory: %s\n", strerror(errno)); + return NULL; + } + + struct dirent *file; + while((file = readdir(directory)) != NULL) + { + if(file->d_name[0] == '.') //File is hidden or ./.. directory so ignore it. + continue; + + FString fullFileName = scanDirectories[i] + file->d_name; + + struct stat fileStat; + stat(fullFileName.GetChars(), &fileStat); + + if(S_ISDIR(fileStat.st_mode)) + { + scanDirectories.Push(scanDirectories[i] + file->d_name + "/"); + continue; + } + AddEntry(scanDirectories[i] + file->d_name, fileStat.st_size); + count++; + } + closedir(directory); + } + return count; +} + #else //========================================================================== @@ -294,6 +336,7 @@ FileReader *FDirectoryLump::NewReader() { FString fullpath = Owner->Filename; fullpath += FullName; + printf("%s\n", fullpath.GetChars()); return new FileReader(fullpath); } catch (CRecoverableError &) diff --git a/src/sdl/crashcatcher.c b/src/sdl/crashcatcher.c index 3a4c5a0ce..7dc928407 100644 --- a/src/sdl/crashcatcher.c +++ b/src/sdl/crashcatcher.c @@ -8,6 +8,12 @@ #include #include +// Solaris doesn't have SA_ONESHOT +// According to the Linux header this is the same. +#ifndef SA_ONESHOT +#define SA_ONESHOT SA_RESETHAND +#endif + static const char *cc_logfile = NULL; static char respfile[256]; diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index e278563a6..f8f01f2a9 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -46,6 +46,8 @@ extern HWND Window; #endif #ifdef __APPLE__ #include +#elif __sun +#include #else #include #endif diff --git a/src/sound/music_dumb.cpp b/src/sound/music_dumb.cpp index 3b6f29c5c..101368934 100644 --- a/src/sound/music_dumb.cpp +++ b/src/sound/music_dumb.cpp @@ -73,7 +73,7 @@ protected: static bool read(SoundStream *stream, void *buff, int len, void *userdata); }; -#pragma pack(push, 1) +#pragma pack(1) typedef struct tagITFILEHEADER { @@ -108,7 +108,7 @@ typedef struct MODMIDICFG char szMidiZXXExt[128*32]; // changed from CHAR } MODMIDICFG, *LPMODMIDICFG; -#pragma pack(pop) +#pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- diff --git a/src/w_zip.h b/src/w_zip.h index 299e75589..40a8a4b1d 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -1,7 +1,7 @@ #ifndef __W_ZIP #define __W_ZIP -#pragma pack(push, 1) +#pragma pack(1) // FZipCentralInfo struct FZipEndOfCentralDirectory { @@ -56,7 +56,7 @@ struct FZipLocalFileHeader }; -#pragma pack(pop) +#pragma pack() #define ZIP_LOCALFILE MAKE_ID('P','K',3,4) #define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) From bf7ed6258befe2504a81c5506cc480fa50472717 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 11:00:58 +0000 Subject: [PATCH 174/241] - fixed: The node builder did not check if all segs could be split properly. Also removed some fudging that tried to work around this case but produced a broken BSP tree on other maps. SVN r2071 (trunk) --- docs/rh-log.txt | 11 ++++++---- src/nodebuild.cpp | 38 +++++++++++++++++++++++++++++++++-- src/p_setup.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++- src/r_bsp.cpp | 1 + 4 files changed, 94 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4af0837cd..e93b2a877 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +January 1, 2010 (Changes by Graf Zahl) +- fixed: The node builder did not check if all segs could be split properly. + Also removed some fudging that tried to work around this case but produced + a broken BSP tree on other maps. +- Added Blzut3's Solaris patch. +- Fixed: Heretic's Weredragon (Beast) should not have a melee state. + January 1, 2010 (SBARINFO update) - Reorganized the SBarInfo code. - Added interpolate() flag to drawnumber, drawbar, and drawgem. The old @@ -6,10 +13,6 @@ January 1, 2010 (SBARINFO update) - As an extension to the previous you can now use comparison operators on inventory items and armortype in drawswitchableimage. -January 1, 2010 (Changes by Graf Zahl) -- Added Blzut3's Solaris patch. -- Fixed: Heretic's Weredragon (Beast) should not have a melee state. - December 31, 2009 (Changes by Graf Zahl) - fixed: FastProjectile was missing all sky checks when the projectile's move was blocked. diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index a988ba6e8..3c87fb6e5 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -114,6 +114,17 @@ int FNodeBuilder::CreateNode (DWORD set, fixed_t bbox[4]) DWORD set1, set2; SplitSegs (set, node, splitseg, set1, set2); + + // Check if the set could be split. It may happen that all segs end up on the same side + // in which case we need to create a subsector from such a set. + if (set1 == DWORD_MAX) + { + return 0x80000000 | CreateSubsector (set2, bbox); + } + else if (set2 == DWORD_MAX) + { + return 0x80000000 | CreateSubsector (set1, bbox); + } D(PrintSet (1, set1)); D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); D(PrintSet (2, set2)); @@ -490,7 +501,9 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) { - int score = 0; + int score = 1000000; // a high base so that segs that come too close to a splitter + // still can be weighed extremely negatively but preventing + // them from creating a negative score. int segsInSet = 0; int counts[2] = { 0, 0 }; int realSegs[2] = { 0, 0 }; @@ -767,6 +780,27 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y)); vertnum = VertexMap->SelectVertexClose (newvert); + if (vertnum == seg->v1 || vertnum == seg->v2) + { + // Check if the resulting split vertex matches one of the line's ends. + // In this case this seg must not be split + if ((vertnum == seg->v1 && sidev2 == -1) || (vertnum == seg->v2 && sidev1 == -1)) + { + side = 0; + sidev1 = 0; + seg->next = outset0; + outset0 = set; + } + else + { + side = 1; + sidev2 = 0; + seg->next = outset1; + outset1 = set; + } + break; + } + seg2 = SplitSeg (set, vertnum, sidev1); Segs[seg2].next = outset0; @@ -841,7 +875,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou set = next; } FixSplitSharers (node); - if (GLNodes) + if (GLNodes && outset0 != DWORD_MAX && outset1 != DWORD_MAX) { AddMinisegs (node, splitseg, outset0, outset1); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ab467a77e..6b714cf44 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -2712,6 +2712,7 @@ static void P_GroupLines (bool buildmap) FBoundingBox bbox; bool flaggedNoFronts = false; unsigned int ii, jj; + TArray nosector; for (i = 0; i < (int)countof(times); ++i) { @@ -2722,7 +2723,13 @@ static void P_GroupLines (bool buildmap) times[0].Clock(); for (i = 0; i < numsubsectors; i++) { - subsectors[i].sector = segs[subsectors[i].firstline].sidedef->sector; + side_t *side = segs[subsectors[i].firstline].sidedef; + if (side != NULL) subsectors[i].sector = side->sector; + else + { + subsectors[i].sector = NULL; + nosector.Push(i); + } subsectors[i].validcount = validcount; double accumx = 0.0, accumy = 0.0; @@ -2737,6 +2744,48 @@ static void P_GroupLines (bool buildmap) subsectors[i].CenterX = fixed_t(accumx * 0.5 / subsectors[i].numlines); subsectors[i].CenterY = fixed_t(accumy * 0.5 / subsectors[i].numlines); } + for(unsigned i=0;inumlines; j++) + { + seg_t *seg = &segs[sub->firstline + j]; + if (seg->frontsector != NULL) + { + sub->sector = seg->frontsector; + break; + } + if (seg->PartnerSeg != NULL && seg->PartnerSeg->backsector != NULL) + { + sub->sector = seg->PartnerSeg->backsector; + break; + } + } + // we still haven't found a matching sector. Check the back sides of this subsector's segs next + if (sub->sector == NULL) + { + for(unsigned j=0;jnumlines; j++) + { + seg_t *seg = &segs[sub->firstline + j]; + if (seg->backsector != NULL) + { + sub->sector = seg->backsector; + break; + } + if (seg->PartnerSeg != NULL && seg->PartnerSeg->frontsector != NULL) + { + sub->sector = seg->PartnerSeg->frontsector; + break; + } + } + } + if (sub->sector == NULL) + { + sub->sector = §ors[0]; // prevent crashes. This hopefully does not matter because + // any subsector going through here is malformed. + Printf("Unable to assign a sector to subsector %d\n", subsectors[i].firstline); + } + } times[0].Unclock(); // count number of lines in each sector diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index a1f6f6098..a0aa40e8d 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -1026,6 +1026,7 @@ void R_Subsector (subsector_t *sub) #endif frontsector = sub->sector; + if (sub->sector == NULL) return; frontsector->MoreFlags |= SECF_DRAWN; count = sub->numlines; line = &segs[sub->firstline]; From 370eff9014b01ab22e032b7514831e40d4e0c9ba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 12:40:47 +0000 Subject: [PATCH 175/241] - replaced wadlist_t with an array of FStrings and added a list parameter to everything that eventually calls D_AddFile. Also create the list of files loaded on the command line separately to allow further checks on them. SVN r2072 (trunk) --- docs/rh-log.txt | 3 + src/c_dispatch.cpp | 3 +- src/d_iwad.cpp | 14 ++--- src/d_main.cpp | 133 +++++++++++++++++++++++++-------------------- src/d_main.h | 2 +- src/w_wad.cpp | 12 ++-- src/w_wad.h | 12 +--- 7 files changed, 93 insertions(+), 86 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e93b2a877..5326ee3aa 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ January 1, 2010 (Changes by Graf Zahl) +- replaced wadlist_t with an array of FStrings and added a list parameter to + everything that eventually calls D_AddFile. Also create the list of files + loaded on the command line separately to allow further checks on them. - fixed: The node builder did not check if all segs could be split properly. Also removed some fudging that tried to work around this case but produced a broken BSP tree on other maps. diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 6540fc4c9..5ebe450b6 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -1376,6 +1376,7 @@ void FConsoleAlias::SafeDelete () static BYTE PullinBad = 2; static const char *PullinFile; +extern TArray allwads; int C_ExecFile (const char *file, bool usePullin) { @@ -1492,7 +1493,7 @@ CCMD (pullin) FixPathSeperator (path); } } - D_AddFile (path); + D_AddFile (allwads, path); if (path != argv[i]) { delete[] path; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index dae65379d..421a35e4a 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -484,7 +484,7 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads) // //========================================================================== -static EIWADType IdentifyVersion (const char *zdoom_wad) +static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_wad) { WadStuff wads[countof(IWADNames)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; @@ -630,14 +630,14 @@ static EIWADType IdentifyVersion (const char *zdoom_wad) exit (0); // zdoom.pk3 must always be the first file loaded and the IWAD second. - D_AddFile (zdoom_wad); + D_AddFile (wadfiles, zdoom_wad); if (wads[pickwad].Type == IWAD_HexenDK) { // load hexen.wad before loading hexdd.wad - D_AddFile (wads[foundwads[IWAD_Hexen]-1].Path); + D_AddFile (wadfiles, wads[foundwads[IWAD_Hexen]-1].Path); } - D_AddFile (wads[pickwad].Path); + D_AddFile (wadfiles, wads[pickwad].Path); if (wads[pickwad].Type == IWAD_Strife) { // Try to load voices.wad along with strife1.wad @@ -653,16 +653,16 @@ static EIWADType IdentifyVersion (const char *zdoom_wad) path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); } path += "voices.wad"; - D_AddFile (path); + D_AddFile (wadfiles, path); } return wads[pickwad].Type; } -const IWADInfo *D_FindIWAD(const char *basewad) +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad) { - EIWADType iwadType = IdentifyVersion(basewad); + EIWADType iwadType = IdentifyVersion(wadfiles, basewad); gameiwad = iwadType; const IWADInfo *iwad_info = &IWADInfos[iwadType]; I_SetIWADInfo(iwad_info); diff --git a/src/d_main.cpp b/src/d_main.cpp index 656875941..d59eee1e5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -118,7 +118,7 @@ extern void R_ExecuteSetViewSize (); extern void G_NewInit (); extern void SetupPlayerClasses (); extern bool CheckCheatmode (); -extern const IWADInfo *D_FindIWAD(const char *basewad); +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -182,7 +182,7 @@ CVAR (Int, wipetype, 1, CVAR_ARCHIVE); CVAR (Int, snd_drawoutput, 0, 0); bool DrawFSHUD; // [RH] Draw fullscreen HUD? -wadlist_t *wadfiles; // [RH] remove limit on # of loaded wads +TArray allwads; bool devparm; // started game with -devparm const char *D_DrawIcon; // [RH] Patch name of icon to draw on next refresh int NoWipe; // [RH] Allow wipe? (Needs to be set each time) @@ -204,7 +204,6 @@ cycle_t FrameCycles; // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static wadlist_t **wadtail = &wadfiles; static int demosequence; static int pagetic; @@ -1242,7 +1241,7 @@ CCMD (endgame) // //========================================================================== -void D_AddFile (const char *file, bool check) +void D_AddFile (TArray &wadfiles, const char *file, bool check) { if (file == NULL) { @@ -1259,12 +1258,10 @@ void D_AddFile (const char *file, bool check) } file = f; } - wadlist_t *wad = (wadlist_t *)M_Malloc (sizeof(*wad) + strlen(file)); - *wadtail = wad; - wad->next = NULL; - strcpy (wad->name, file); - wadtail = &wad->next; + FString f = file; + FixPathSeperator(f); + wadfiles.Push(f); } //========================================================================== @@ -1273,13 +1270,13 @@ void D_AddFile (const char *file, bool check) // //========================================================================== -void D_AddWildFile (const char *value) +void D_AddWildFile (TArray &wadfiles, const char *value) { const char *wadfile = BaseFileSearch (value, ".wad"); if (wadfile != NULL) { - D_AddFile (wadfile); + D_AddFile (wadfiles, wadfile); } else { // Try pattern matching @@ -1309,12 +1306,12 @@ void D_AddWildFile (const char *value) { if (sep == NULL) { - D_AddFile (I_FindName (&findstate)); + D_AddFile (wadfiles, I_FindName (&findstate)); } else { strcpy (sep+1, I_FindName (&findstate)); - D_AddFile (path); + D_AddFile (wadfiles, path); } } } while (I_FindNext (handle, &findstate) == 0); @@ -1331,7 +1328,7 @@ void D_AddWildFile (const char *value) // //========================================================================== -void D_AddConfigWads (const char *section) +void D_AddConfigWads (TArray &wadfiles, const char *section) { if (GameConfig->SetSection (section)) { @@ -1345,7 +1342,7 @@ void D_AddConfigWads (const char *section) { // D_AddWildFile resets GameConfig's position, so remember it GameConfig->GetPosition (pos); - D_AddWildFile (value); + D_AddWildFile (wadfiles, value); // Reset GameConfig's position to get next wad GameConfig->SetPosition (pos); } @@ -1361,7 +1358,7 @@ void D_AddConfigWads (const char *section) // //========================================================================== -static void D_AddDirectory (const char *dir) +static void D_AddDirectory (TArray &wadfiles, const char *dir) { char curdir[PATH_MAX]; @@ -1391,7 +1388,7 @@ static void D_AddDirectory (const char *dir) if (!(I_FindAttr (&findstate) & FA_DIREC)) { strcpy (skindir + stuffstart, I_FindName (&findstate)); - D_AddFile (skindir); + D_AddFile (wadfiles, skindir); } } while (I_FindNext (handle, &findstate) == 0); I_FindClose (handle); @@ -1584,6 +1581,53 @@ void D_MultiExec (DArgs *list, bool usePullin) } } +static void GetCmdLineFiles(TArray &wadfiles) +{ + DArgs *files = Args->GatherFiles ("-file", ".wad", true); + DArgs *files1 = Args->GatherFiles (NULL, ".zip", false); + DArgs *files2 = Args->GatherFiles (NULL, ".pk3", false); + DArgs *files3 = Args->GatherFiles (NULL, ".txt", false); + if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0 || files3->NumArgs() > 0) + { + // Check for -file in shareware + if (gameinfo.flags & GI_SHAREWARE) + { + I_FatalError ("You cannot -file with the shareware version. Register!"); + } + + // the files gathered are wadfile/lump names + for (int i = 0; i < files->NumArgs(); i++) + { + D_AddWildFile (wadfiles, files->GetArg (i)); + } + for (int i = 0; i < files1->NumArgs(); i++) + { + D_AddWildFile (wadfiles, files1->GetArg (i)); + } + for (int i = 0; i < files2->NumArgs(); i++) + { + D_AddWildFile (wadfiles, files2->GetArg (i)); + } + for (int i = 0; i < files3->NumArgs(); i++) + { + D_AddWildFile (wadfiles, files3->GetArg (i)); + } + } + files->Destroy(); + files1->Destroy(); + files2->Destroy(); + files3->Destroy(); +} + +static void CopyFiles(TArray &to, TArray &from) +{ + unsigned int ndx = to.Reserve(from.Size()); + for(unsigned i=0;i pwads; // Set the FPU precision to 53 significant bits. This is the default // for Visual C++, but not for GCC, so some slight math variances @@ -1640,7 +1685,7 @@ void D_DoomMain (void) // Load zdoom.pk3 alone so that we can get access to the internal gameinfos before // the IWAD is known. - const IWADInfo *iwad_info = D_FindIWAD(wad); + const IWADInfo *iwad_info = D_FindIWAD(allwads, wad); gameinfo.gametype = iwad_info->gametype; gameinfo.flags = iwad_info->flags; @@ -1657,7 +1702,7 @@ void D_DoomMain (void) // it for something else, so this gets to stay here. wad = BaseFileSearch ("zvox.wad", NULL); if (wad) - D_AddFile (wad); + D_AddFile (allwads, wad); // [RH] Add any .wad files in the skins directory #ifdef unix @@ -1666,27 +1711,27 @@ void D_DoomMain (void) file = progdir; #endif file += "skins"; - D_AddDirectory (file); + D_AddDirectory (allwads, file); #ifdef unix file = NicePath("~/" GAME_DIR "/skins"); - D_AddDirectory (file); + D_AddDirectory (allwads, file); #endif // Add common (global) wads - D_AddConfigWads ("Global.Autoload"); + D_AddConfigWads (allwads, "Global.Autoload"); // Add game-specific wads file = GameNames[gameinfo.gametype]; file += ".Autoload"; - D_AddConfigWads (file); + D_AddConfigWads (allwads, file); // Add IWAD-specific wads if (iwad_info->Autoname != NULL) { file = iwad_info->Autoname; file += ".Autoload"; - D_AddConfigWads(file); + D_AddConfigWads(allwads, file); } } @@ -1703,43 +1748,13 @@ void D_DoomMain (void) C_ExecCmdLineParams (); // [RH] do all +set commands on the command line - DArgs *files = Args->GatherFiles ("-file", ".wad", true); - DArgs *files1 = Args->GatherFiles (NULL, ".zip", false); - DArgs *files2 = Args->GatherFiles (NULL, ".pk3", false); - DArgs *files3 = Args->GatherFiles (NULL, ".txt", false); - if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0 || files3->NumArgs() > 0) - { - // Check for -file in shareware - if (gameinfo.flags & GI_SHAREWARE) - { - I_FatalError ("You cannot -file with the shareware version. Register!"); - } + GetCmdLineFiles(pwads); - // the files gathered are wadfile/lump names - for (int i = 0; i < files->NumArgs(); i++) - { - D_AddWildFile (files->GetArg (i)); - } - for (int i = 0; i < files1->NumArgs(); i++) - { - D_AddWildFile (files1->GetArg (i)); - } - for (int i = 0; i < files2->NumArgs(); i++) - { - D_AddWildFile (files2->GetArg (i)); - } - for (int i = 0; i < files3->NumArgs(); i++) - { - D_AddWildFile (files3->GetArg (i)); - } - } - files->Destroy(); - files1->Destroy(); - files2->Destroy(); - files3->Destroy(); + CopyFiles(allwads, pwads); Printf ("W_Init: Init WADfiles.\n"); - Wads.InitMultipleFiles (&wadfiles); + Wads.InitMultipleFiles (allwads); + allwads.Clear(); // [RH] Initialize localizable strings. GStrings.LoadStrings (false); @@ -2043,7 +2058,7 @@ void D_DoomMain (void) V_Init2(); - files = Args->GatherFiles ("-playdemo", ".lmp", false); + DArgs *files = Args->GatherFiles ("-playdemo", ".lmp", false); if (files->NumArgs() > 0) { singledemo = true; // quit after one demo diff --git a/src/d_main.h b/src/d_main.h index 744e76bcc..3e22acb71 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -49,7 +49,7 @@ void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void); -void D_AddFile (const char *file, bool check = true); +void D_AddFile (TArray &wadfiles, const char *file, bool check = true); // [RH] Set this to something to draw an icon during the next screen refresh. diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 9c5b525ca..bb8deb384 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -160,7 +160,7 @@ void FWadCollection::DeleteAll () // //========================================================================== -void FWadCollection::InitMultipleFiles (wadlist_t **filenames) +void FWadCollection::InitMultipleFiles (TArray &filenames) { int numfiles; @@ -168,13 +168,10 @@ void FWadCollection::InitMultipleFiles (wadlist_t **filenames) DeleteAll(); numfiles = 0; - while (*filenames) + for(unsigned i=0;inext; int baselump = NumLumps; - AddFile ((*filenames)->name); - M_Free (*filenames); - *filenames = next; + AddFile (filenames[i]); } NumLumps = LumpInfo.Size(); @@ -222,7 +219,7 @@ int FWadCollection::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FWadCollection::AddFile (char *filename, FileReader *wadinfo) +void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) { int startlump; bool isdir = false; @@ -252,7 +249,6 @@ void FWadCollection::AddFile (char *filename, FileReader *wadinfo) return; } } - FixPathSeperator(filename); } Printf (" adding %s", filename); diff --git a/src/w_wad.h b/src/w_wad.h index 7adea8ab7..2edd71587 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -49,14 +49,6 @@ struct wadlump_t #define PWAD_ID MAKE_ID('P','W','A','D') -// [RH] Remove limit on number of WAD files -struct wadlist_t -{ - wadlist_t *next; - char name[1]; // +size of string -}; -extern wadlist_t *wadfiles; - // [RH] Namespaces from BOOM. typedef enum { ns_global = 0, @@ -153,8 +145,8 @@ public: // The wadnum for the IWAD enum { IWAD_FILENUM = 1 }; - void InitMultipleFiles (wadlist_t **filenames); - void AddFile (char *filename, FileReader *wadinfo = NULL); + void InitMultipleFiles (TArray &filenames); + void AddFile (const char *filename, FileReader *wadinfo = NULL); int CheckIfWadLoaded (const char *name); const char *GetWadName (int wadnum) const; From 90ea0c3f6fba1693c0269e75fa623c1b6f63484e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 15:31:00 +0000 Subject: [PATCH 176/241] - added initial support for a GAMEINFO lump in PWADs. When the game is started all files loaded with '-file' are scanned for this lump. This lump is read before any WAD initialization takes place, in particular the IWAD is not yet loaded at this time. This allows PWADs the option to specify an IWAD they want to run with and optionally autoload external resource WADs. - Fixed a few places where FixPathSeperator was called with a locked FString buffer. It's better to use the FString version of this function instead. SVN r2073 (trunk) --- docs/rh-log.txt | 7 ++ src/d_iwad.cpp | 19 +++-- src/d_main.cpp | 131 +++++++++++++++++++++++++++-- src/d_main.h | 2 +- src/resourcefiles/resourcefile.cpp | 4 +- src/resourcefiles/resourcefile.h | 2 +- 6 files changed, 145 insertions(+), 20 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5326ee3aa..bf9dcdb6e 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,11 @@ January 1, 2010 (Changes by Graf Zahl) +- added initial support for a GAMEINFO lump in PWADs. When the game is started + all files loaded with '-file' are scanned for this lump. This lump is read + before any WAD initialization takes place, in particular the IWAD is not yet + loaded at this time. This allows PWADs the option to specify an IWAD they + want to run with and optionally autoload external resource WADs. +- Fixed a few places where FixPathSeperator was called with a locked FString buffer. + It's better to use the FString version of this function instead. - replaced wadlist_t with an array of FStrings and added a list parameter to everything that eventually calls D_AddFile. Also create the list of files loaded on the command line separately to allow further checks on them. diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 421a35e4a..075f5f700 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -446,8 +446,7 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads) FString iwad; iwad.Format ("%s%s%s", doomwaddir, slash, IWADNames[i]); - FixPathSeperator (iwad.LockBuffer()); - iwad.UnlockBuffer(); + FixPathSeperator (iwad); if (FileExists (iwad)) { wads[i].Type = ScanIWAD (iwad); @@ -484,7 +483,7 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads) // //========================================================================== -static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_wad) +static EIWADType IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad) { WadStuff wads[countof(IWADNames)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; @@ -495,10 +494,15 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w bool iwadparmfound = false; FString custwad; + if (iwadparm == NULL && iwad != NULL && *iwad != 0) + { + iwadparm = iwad; + } + if (iwadparm) { custwad = iwadparm; - FixPathSeperator (custwad.LockBuffer()); + FixPathSeperator (custwad); if (CheckIWAD (custwad, wads)) { // -iwad parameter was a directory iwadparm = NULL; @@ -524,8 +528,7 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); - FixPathSeperator(nice.LockBuffer()); - nice.UnlockBuffer(); + FixPathSeperator(nice); CheckIWAD(nice, wads); } } @@ -660,9 +663,9 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w } -const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad) +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad) { - EIWADType iwadType = IdentifyVersion(wadfiles, basewad); + EIWADType iwadType = IdentifyVersion(wadfiles, iwad, basewad); gameiwad = iwadType; const IWADInfo *iwad_info = &IWADInfos[iwadType]; I_SetIWADInfo(iwad_info); diff --git a/src/d_main.cpp b/src/d_main.cpp index d59eee1e5..732cd6acd 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "doomerrors.h" @@ -102,6 +103,8 @@ #include "m_cheat.h" #include "compatibility.h" #include "m_joy.h" +#include "sc_man.h" +#include "resourcefiles/resourcefile.h" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -118,7 +121,7 @@ extern void R_ExecuteSetViewSize (); extern void G_NewInit (); extern void SetupPlayerClasses (); extern bool CheckCheatmode (); -const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad); +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -1241,11 +1244,11 @@ CCMD (endgame) // //========================================================================== -void D_AddFile (TArray &wadfiles, const char *file, bool check) +bool D_AddFile (TArray &wadfiles, const char *file, bool check, int position) { if (file == NULL) { - return; + return false; } if (check && !DirEntryExists (file)) @@ -1254,14 +1257,16 @@ void D_AddFile (TArray &wadfiles, const char *file, bool check) if (f == NULL) { Printf ("Can't find '%s'\n", file); - return; + return false; } file = f; } FString f = file; FixPathSeperator(f); - wadfiles.Push(f); + if (position == -1) wadfiles.Push(f); + else wadfiles.Insert(position, f); + return true; } //========================================================================== @@ -1628,6 +1633,114 @@ static void CopyFiles(TArray &to, TArray &from) } } +static FString ParseGameInfo(TArray &pwads, const char *fn, const char *data, int size) +{ + FScanner sc; + FString iwad; + int pos = 0; + + const char *lastSlash = strrchr (fn, '/'); + + sc.OpenMem("GAMEINFO", data, size); + while(sc.GetToken()) + { + sc.TokenMustBe(TK_Identifier); + FString nextKey = sc.String; + sc.MustGetToken('='); + if (!nextKey.CompareNoCase("IWAD")) + { + sc.MustGetString(); + iwad = sc.String; + } + else if (!nextKey.CompareNoCase("LOAD")) + { + do + { + sc.MustGetToken(TK_StringConst); + + // Try looking for the wad in the same directory as the .wad + // before looking for it in the current directory. + + if (lastSlash != NULL) + { + FString checkpath(fn, (lastSlash - fn) + 1); + checkpath += sc.String; + + if (!FileExists (checkpath)) + { + pos += D_AddFile(pwads, sc.String, true, pos); + } + else + { + pos += D_AddFile(pwads, checkpath, true, pos); + } + } + } + while (sc.CheckToken(',')); + } + } + return iwad; +} + +static FString CheckGameInfo(TArray & pwads) +{ + DWORD t = I_FPSTime(); + // scan the list of WADs backwards to find the last one that contains a GAMEINFO lump + for(int i=pwads.Size()-1; i>=0; i--) + { + bool isdir = false; + FileReader *wadinfo; + FResourceFile *resfile; + const char *filename = pwads[i]; + + // Does this exist? If so, is it a directory? + struct stat info; + if (stat(pwads[i], &info) != 0) + { + Printf(TEXTCOLOR_RED "Could not stat %s\n", filename); + continue; + } + isdir = (info.st_mode & S_IFDIR) != 0; + + if (!isdir) + { + try + { + wadinfo = new FileReader(filename); + } + catch (CRecoverableError &) + { + // Didn't find file + continue; + } + resfile = FResourceFile::OpenResourceFile(filename, wadinfo, true); + } + else + resfile = FResourceFile::OpenDirectory(filename, true); + + if (resfile != NULL) + { + DWORD cnt = resfile->LumpCount(); + for(int i=cnt-1; i>=0; i--) + { + FResourceLump *lmp = resfile->GetLump(i); + + if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "GAMEINFO")) + { + // Found one! + FString iwad = ParseGameInfo(pwads, resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize); + delete resfile; + return iwad; + } + } + delete resfile; + } + } + t = I_FPSTime() - t; + Printf("Gameinfo scan took %d ms\n", t); + return ""; +} + //========================================================================== // // D_DoomMain @@ -1681,11 +1794,15 @@ void D_DoomMain (void) { I_FatalError ("Cannot find " BASEWAD); } + FString basewad = wad; // Load zdoom.pk3 alone so that we can get access to the internal gameinfos before // the IWAD is known. - const IWADInfo *iwad_info = D_FindIWAD(allwads, wad); + GetCmdLineFiles(pwads); + FString iwad = CheckGameInfo(pwads); + + const IWADInfo *iwad_info = D_FindIWAD(allwads, iwad, basewad); gameinfo.gametype = iwad_info->gametype; gameinfo.flags = iwad_info->flags; @@ -1748,8 +1865,6 @@ void D_DoomMain (void) C_ExecCmdLineParams (); // [RH] do all +set commands on the command line - GetCmdLineFiles(pwads); - CopyFiles(allwads, pwads); Printf ("W_Init: Init WADfiles.\n"); diff --git a/src/d_main.h b/src/d_main.h index 3e22acb71..517653bec 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -49,7 +49,7 @@ void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void); -void D_AddFile (TArray &wadfiles, const char *file, bool check = true); +bool D_AddFile (TArray &wadfiles, const char *file, bool check = true, int position = -1); // [RH] Set this to something to draw an icon during the next screen refresh. diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 9831ec70c..c5bde5712 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -283,9 +283,9 @@ FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader return NULL; } -FResourceFile *FResourceFile::OpenDirectory(const char *filename) +FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) { - return CheckDir(filename, NULL, false); + return CheckDir(filename, NULL, quiet); } //========================================================================== diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index 39c9594f8..ac8499944 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -67,7 +67,7 @@ private: public: static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false); - static FResourceFile *OpenDirectory(const char *filename); + static FResourceFile *OpenDirectory(const char *filename, bool quiet = false); virtual ~FResourceFile(); FileReader *GetReader() const { return Reader; } DWORD LumpCount() const { return NumLumps; } From 54283ee2311ec25c55c7a8fa6e2ebc7503b1dfee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 18:02:30 +0000 Subject: [PATCH 177/241] - unquoted strings should still work for GAMEINFO... SVN r2074 (trunk) --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 732cd6acd..3de2bab7c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1656,7 +1656,7 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char { do { - sc.MustGetToken(TK_StringConst); + sc.MustGetString(); // Try looking for the wad in the same directory as the .wad // before looking for it in the current directory. From 87f3c9c5b75c8b78d96e462e0028e960883a62e4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 11:38:27 +0000 Subject: [PATCH 178/241] - fixed: The floor waggle code used FloatBobOffsets as sine table but this only has 64 entries and is not precise enough. It now uses finesine instead. - fixed: When compositing a multipatch texture any patch that is a multpatch texture itself and contains rotations may not be composited directly into the destination buffer. This must be done with an intermediate buffer. - Fixed: Drawing a slider in the options menu did not scale the x-coordinate. - Fixed: If the alt HUD had to draw negative numbers the minus sign was misplaced due to incorrect texture coordinate calculations. - changed option menu scaling for widescreen modes so that it doesn't scale down so quickly. - made some error messages in DECORATE that don't affect the parsing non-fatal so that the parser can continue to find more problems. SVN r2076 (trunk) --- docs/rh-log.txt | 14 ++++++ src/g_shared/shared_hud.cpp | 9 +++- src/m_options.cpp | 2 +- src/p_floor.cpp | 12 ++++- src/textures/multipatchtexture.cpp | 9 +++- src/textures/texture.cpp | 2 +- src/textures/textures.h | 1 + src/thingdef/thingdef_parse.cpp | 52 +++++++++++++-------- src/v_font.cpp | 6 +-- src/v_video.cpp | 74 ++++++++++++++++-------------- 10 files changed, 117 insertions(+), 64 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bf9dcdb6e..b727cb295 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,17 @@ +January 2, 2010 (Changes by Graf Zahl) +- fixed: The floor waggle code used FloatBobOffsets as sine table but this + only has 64 entries and is not precise enough. It now uses finesine instead. +- fixed: When compositing a multipatch texture any patch that is a multpatch + texture itself and contains rotations may not be composited directly into + the destination buffer. This must be done with an intermediate buffer. +- Fixed: Drawing a slider in the options menu did not scale the x-coordinate. +- Fixed: If the alt HUD had to draw negative numbers the minus sign was misplaced + due to incorrect texture coordinate calculations. +- changed option menu scaling for widescreen modes so that it doesn't scale down + so quickly. +- made some error messages in DECORATE that don't affect the parsing non-fatal + so that the parser can continue to find more problems. + January 1, 2010 (Changes by Graf Zahl) - added initial support for a GAMEINFO lump in PWADs. When the game is started all files loaded with '-file' are scanned for this lump. This lump is read diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index a1905aff9..b2efa1d13 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -158,15 +158,20 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans static void DrawHudText(FFont *font, int color, char * text, int x, int y, int trans=0xc000) { - int zerowidth = font->GetCharWidth('0'); + int zerowidth; + FTexture *tex_zero = font->GetChar('0', &zerowidth); x+=zerowidth/2; for(int i=0;text[i];i++) { + int width; + FTexture *texc = font->GetChar(text[i], &width); + int offset = texc->TopOffset - tex_zero->TopOffset + tex_zero->GetHeight(); screen->DrawChar(font, color, x, y, text[i], DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans, - DTA_CenterBottomOffset, 1, TAG_DONE); + DTA_LeftOffset, width/2, DTA_TopOffset, offset, + /*DTA_CenterBottomOffset, 1,*/ TAG_DONE); x+=zerowidth; } } diff --git a/src/m_options.cpp b/src/m_options.cpp index 219170e36..83b2a038d 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -1565,7 +1565,7 @@ static void M_DrawSlider (int x, int y, double min, double max, double cur,int f cur = clamp(cur, min, max) - min; M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); - M_DrawConText(CR_ORANGE, x + 5 + (int)((cur * 78) / range), y, "\x13"); + M_DrawConText(CR_ORANGE, x + int((5 + ((cur * 78) / range)) * CleanXfac_1), y, "\x13"); if (fracdigits >= 0) { diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 984a0f064..fd06ff0c1 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -1268,9 +1268,17 @@ void DWaggleBase::DoWaggle (bool ceiling) break; } m_Accumulator += m_AccDelta; + + +#if 1 + fixed_t mag = finesine[(m_Accumulator>>9)&8191]*8; +#else + // Hexen used a 64 entry(!) sine table here which is not nearly precise enough for smooth movement + fixed_t mag = FloatBobOffsets[(m_Accumulator>>FRACBITS)&63]; +#endif + dist = plane->d; - plane->d = m_OriginalDist + plane->PointToDist (0, 0, - FixedMul (FloatBobOffsets[(m_Accumulator>>FRACBITS)&63], m_Scale)); + plane->d = m_OriginalDist + plane->PointToDist (0, 0, FixedMul (mag, m_Scale)); m_Sector->ChangePlaneTexZ(pos, plane->HeightDiff (dist)); dist = plane->HeightDiff (dist); diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 34956dff7..faaa5db6c 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -218,6 +218,7 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl int i; mtexture.d = (const maptexture_t *)texdef; + bMultiPatch = true; if (strife) { @@ -561,7 +562,10 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota { int ret = -1; - if (!Parts[i].Texture->bComplex || inf == NULL) + // rotated multipatch parts cannot be composited directly + bool rotatedmulti = Parts[i].Rotate != 0 && Parts[i].Texture->bMultiPatch; + + if ((!Parts[i].Texture->bComplex || inf == NULL) && !rotatedmulti) { memset (&info, 0, sizeof (info)); info.alpha = Parts[i].Alpha; @@ -612,7 +616,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota { Parts[i].Texture->CopyTrueColorPixels(&bmp1, 0, 0); bmp->CopyPixelDataRGB(x+Parts[i].OriginX, y+Parts[i].OriginY, bmp1.GetPixels(), - bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch()*4, Parts[i].Rotate, CF_BGRA, inf); + bmp1.GetWidth(), bmp1.GetHeight(), 4, bmp1.GetPitch(), Parts[i].Rotate, CF_BGRA, inf); } } @@ -1179,6 +1183,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) { TArray parts; + bMultiPatch = true; sc.SetCMode(true); sc.MustGetString(); uppercopy(Name, sc.String); diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 88acefb47..97f393cb2 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -143,7 +143,7 @@ FTexture::FTexture (const char *name, int lumpnum) : LeftOffset(0), TopOffset(0), WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT), SourceLump(lumpnum), UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false), - bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), + bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0), WidthMask(0), Native(NULL) { id.SetInvalid(); diff --git a/src/textures/textures.h b/src/textures/textures.h index 1bd9282a9..0146b7355 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -119,6 +119,7 @@ public: BYTE bComplex:1; // Will be used to mark extended MultipatchTextures that have to be // fully composited before subjected to any kinf of postprocessing instead of // doing it per patch. + BYTE bMultiPatch:1; // This is a multipatch texture (we really could use real type info for textures...) WORD Rotations; SWORD SkyOffset; diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 4aea677aa..85930b09c 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -149,7 +149,8 @@ FxExpression *ParseParameter(FScanner &sc, PClass *cls, char type, bool constant x = ParseExpression (sc, cls); if (constant && !x->isConstant()) { - sc.ScriptError("Default parameter must be constant."); + sc.ScriptMessage("Default parameter must be constant."); + FScriptPosition::ErrorCounter++; } break; @@ -196,13 +197,15 @@ static void ParseConstant (FScanner &sc, PSymbolTable * symt, PClass *cls) if (symt->AddSymbol (sym) == NULL) { delete sym; - sc.ScriptError ("'%s' is already defined in '%s'.", + sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls? cls->TypeName.GetChars() : "Global"); + FScriptPosition::ErrorCounter++; } } else { - sc.ScriptError("Numeric type required for constant"); + sc.ScriptMessage("Numeric type required for constant"); + FScriptPosition::ErrorCounter++; } } @@ -235,8 +238,9 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls) if (symt->AddSymbol (sym) == NULL) { delete sym; - sc.ScriptError ("'%s' is already defined in '%s'.", + sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls? cls->TypeName.GetChars() : "Global"); + FScriptPosition::ErrorCounter++; } // This allows a comma after the last value but doesn't enforce it. if (sc.CheckToken('}')) break; @@ -260,7 +264,8 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) { - sc.ScriptError ("variables can only be imported by internal class and actor definitions!"); + sc.ScriptMessage ("variables can only be imported by internal class and actor definitions!"); + FScriptPosition::ErrorCounter++; } // Read the type and make sure it's int or float. @@ -324,8 +329,9 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable * symt, PClass *cls) if (symt->AddSymbol (sym) == NULL) { delete sym; - sc.ScriptError ("'%s' is already defined in '%s'.", + sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls? cls->TypeName.GetChars() : "Global"); + FScriptPosition::ErrorCounter++; } } @@ -349,21 +355,20 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) // Read the type and make sure it's int. sc.MustGetAnyToken(); - if (sc.TokenType == TK_Int) + if (sc.TokenType != TK_Int) { - valuetype = VAL_Int; - } - else - { - sc.ScriptError("User variables must be of type int"); + sc.ScriptMessage("User variables must be of type int"); + FScriptPosition::ErrorCounter++; } + valuetype = VAL_Int; sc.MustGetToken(TK_Identifier); // For now, restrict user variables to those that begin with "user_" to guarantee // no clashes with internal member variable names. if (sc.StringLen < 6 || strnicmp("user_", sc.String, 5) != 0) { - sc.ScriptError("User variable names must begin with \"user_\""); + sc.ScriptMessage("User variable names must begin with \"user_\""); + FScriptPosition::ErrorCounter++; } FName symname = sc.String; @@ -375,7 +380,9 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) sc.MustGetToken(']'); if (maxelems <= 0) { - sc.ScriptError("Array size must be positive"); + sc.ScriptMessage("Array size must be positive"); + FScriptPosition::ErrorCounter++; + maxelems = 1; } valuetype.MakeArray(maxelems); } @@ -388,8 +395,9 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls) if (symt->AddSymbol(sym) == NULL) { delete sym; - sc.ScriptError ("'%s' is already defined in '%s'.", + sc.ScriptMessage ("'%s' is already defined in '%s'.", symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global"); + FScriptPosition::ErrorCounter++; } } @@ -445,12 +453,13 @@ void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char * { if (part2 == NULL) { - sc.ScriptError("\"%s\" is an unknown flag\n", part1); + sc.ScriptMessage("\"%s\" is an unknown flag\n", part1); } else { - sc.ScriptError("\"%s.%s\" is an unknown flag\n", part1, part2); + sc.ScriptMessage("\"%s.%s\" is an unknown flag\n", part1, part2); } + FScriptPosition::ErrorCounter++; } } @@ -583,13 +592,18 @@ static FState *CheckState(FScanner &sc, PClass *type) if (v!=0 && state==NULL) { - sc.ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars()); + sc.ScriptMessage("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars()); + FScriptPosition::ErrorCounter++; return NULL; } state+=v; return state; } - else sc.ScriptError("Invalid state assignment"); + else + { + sc.ScriptMessage("Invalid state assignment"); + FScriptPosition::ErrorCounter++; + } } return NULL; } diff --git a/src/v_font.cpp b/src/v_font.cpp index e36bd1cac..ead32a8c5 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -736,19 +736,19 @@ FTexture *FFont::GetChar (int code, int *const width) const code > LastChar || Chars[code - FirstChar].Pic == NULL) { - *width = SpaceWidth; + if (width != NULL) *width = SpaceWidth; return NULL; } } else { - *width = SpaceWidth; + if (width != NULL) *width = SpaceWidth; return NULL; } } code -= FirstChar; - *width = Chars[code].Pic->GetScaledWidth(); + if (width != NULL) *width = Chars[code].Pic->GetScaledWidth(); return Chars[code].Pic; } diff --git a/src/v_video.cpp b/src/v_video.cpp index e9be86208..f6e0eb546 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1336,6 +1336,10 @@ CCMD(clean) bool V_DoModeSetup (int width, int height, int bits) { DFrameBuffer *buff = I_SetMode (width, height, screen); + int ratio; + int cwidth; + int cheight; + int cx1, cy1, cx2, cy2; if (buff == NULL) { @@ -1350,39 +1354,32 @@ bool V_DoModeSetup (int width, int height, int bits) // if D3DFB is being used for the display. FFont::StaticPreloadFonts(); + ratio = CheckRatio (width, height); + if (ratio & 4) { - int ratio; - int cwidth; - int cheight; - int cx1, cy1, cx2, cy2; - - ratio = CheckRatio (width, height); - if (ratio & 4) - { - cwidth = width; - cheight = height * BaseRatioSizes[ratio][3] / 48; - } - else - { - cwidth = width * BaseRatioSizes[ratio][3] / 48; - cheight = height; - } - // Use whichever pair of cwidth/cheight or width/height that produces less difference - // between CleanXfac and CleanYfac. - cx1 = MAX(cwidth / 320, 1); - cy1 = MAX(cheight / 200, 1); - cx2 = MAX(width / 320, 1); - cy2 = MAX(height / 200, 1); - if (abs(cx1 - cy1) <= abs(cx2 - cy2)) - { // e.g. 640x360 looks better with this. - CleanXfac = cx1; - CleanYfac = cy1; - } - else - { // e.g. 720x480 looks better with this. - CleanXfac = cx2; - CleanYfac = cy2; - } + cwidth = width; + cheight = height * BaseRatioSizes[ratio][3] / 48; + } + else + { + cwidth = width * BaseRatioSizes[ratio][3] / 48; + cheight = height; + } + // Use whichever pair of cwidth/cheight or width/height that produces less difference + // between CleanXfac and CleanYfac. + cx1 = MAX(cwidth / 320, 1); + cy1 = MAX(cheight / 200, 1); + cx2 = MAX(width / 320, 1); + cy2 = MAX(height / 200, 1); + if (abs(cx1 - cy1) <= abs(cx2 - cy2)) + { // e.g. 640x360 looks better with this. + CleanXfac = cx1; + CleanYfac = cy1; + } + else + { // e.g. 720x480 looks better with this. + CleanXfac = cx2; + CleanYfac = cy2; } if (CleanXfac > 1 && CleanYfac > 1 && CleanXfac != CleanYfac) @@ -1400,8 +1397,17 @@ bool V_DoModeSetup (int width, int height, int bits) if (width < 800 || width >= 960) { - CleanXfac_1 = MAX(CleanXfac - 1, 1); - CleanYfac_1 = MAX(CleanYfac - 1, 1); + if (cx1 < cx2) + { + // Special case in which we don't need to scale down. + CleanXfac_1 = + CleanYfac_1 = cx1; + } + else + { + CleanXfac_1 = MAX(CleanXfac - 1, 1); + CleanYfac_1 = MAX(CleanYfac - 1, 1); + } CleanWidth_1 = width / CleanXfac_1; CleanHeight_1 = height / CleanYfac_1; } From efb420228c7b16cf3c8857d7d27d1b2964ac1d4e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 12:03:36 +0000 Subject: [PATCH 179/241] - fixed: SBARINFO's DrawGem command accepted a size value of 0 and divided by it. Reinstated the old '+1' this command had in the old code. SVN r2077 (trunk) --- docs/rh-log.txt | 2 ++ src/g_shared/sbarinfo_commands.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b727cb295..919ecdfc5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ January 2, 2010 (Changes by Graf Zahl) +- fixed: SBARINFO's DrawGem command accepted a size value of 0 and divided + by it. Reinstated the old '+1' this command had in the old code. - fixed: The floor waggle code used FloatBobOffsets as sine table but this only has 64 entries and is not precise enough. It now uses finesine instead. - fixed: When compositing a multipatch texture any patch that is a multpatch diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index bd1bd1478..df6bd1b4a 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -2281,7 +2281,7 @@ class CommandDrawGem : public SBarInfoCommand sc.MustGetToken(TK_IntConst); if(sc.Number < 0) sc.ScriptError("Chain size must be a positive number."); - chainSize = sc.Number; + chainSize = sc.Number+1; sc.MustGetToken(','); GetCoordinates(sc, fullScreenOffsets, x, y); sc.MustGetToken(';'); From 840fc6bfa303bb917f3010191950d46c20315584 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 12:15:47 +0000 Subject: [PATCH 180/241] - fixed: Only ActorMovers should go into STAT_ACTORMOVER, not all PathFollowers. SVN r2078 (trunk) --- docs/rh-log.txt | 1 + src/g_shared/a_movingcamera.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 919ecdfc5..81e4be4a8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ January 2, 2010 (Changes by Graf Zahl) +- fixed: Only ActorMovers should go into STAT_ACTORMOVER, not all PathFollowers. - fixed: SBARINFO's DrawGem command accepted a size value of 0 and divided by it. Reinstated the old '+1' this command had in the old code. - fixed: The floor waggle code used FloatBobOffsets as sine table but this diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 58bde3cff..de67c51d9 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -213,7 +213,6 @@ void APathFollower::BeginPlay () Super::BeginPlay (); PrevNode = CurrNode = NULL; bActive = false; - ChangeStatNum(STAT_ACTORMOVER); } void APathFollower::PostBeginPlay () @@ -508,6 +507,7 @@ class AActorMover : public APathFollower { DECLARE_CLASS (AActorMover, APathFollower) public: + void BeginPlay(); void PostBeginPlay (); void Activate (AActor *activator); void Deactivate (AActor *activator); @@ -517,6 +517,11 @@ protected: IMPLEMENT_CLASS (AActorMover) +void AActorMover::BeginPlay() +{ + ChangeStatNum(STAT_ACTORMOVER); +} + void AActorMover::PostBeginPlay () { Super::PostBeginPlay (); From ff95948017f4b22610aa1f8721199cef19d89c0f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 12:40:07 +0000 Subject: [PATCH 181/241] SVN r2079 (trunk) --- docs/rh-log.txt | 2 ++ src/p_acs.cpp | 1 + src/statnums.h | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 81e4be4a8..707cdec10 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ January 2, 2010 (Changes by Graf Zahl) +- fixed: The ACS thinker needs its own statnum above all actors. Otherwise + order of execution is not guaranteed. - fixed: Only ActorMovers should go into STAT_ACTORMOVER, not all PathFollowers. - fixed: SBARINFO's DrawGem command accepted a size value of 0 and divided by it. Reinstated the old '+1' this command had in the old code. diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 6ffabeec3..d79154609 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1798,6 +1798,7 @@ END_POINTERS TObjPtr DACSThinker::ActiveThinker; DACSThinker::DACSThinker () +: DThinker(STAT_SCRIPTS) { if (ActiveThinker) { diff --git a/src/statnums.h b/src/statnums.h index 201b586da..f699b9c39 100644 --- a/src/statnums.h +++ b/src/statnums.h @@ -60,8 +60,9 @@ enum STAT_MAPMARKER, // Map marker actors STAT_DEFAULT = 100, - STAT_SECTOREFFECT, - STAT_ACTORMOVER, + STAT_SECTOREFFECT, // All sector effects that cause floor and ceiling movement + STAT_ACTORMOVER, // actor movers + STAT_SCRIPTS, // The ACS thinker. This is to ensure that it can't tick before all actors calles PostBeginPlay }; #endif \ No newline at end of file From 435861d671e420bab25f7649d2355f6742c87da6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 12:50:37 +0000 Subject: [PATCH 182/241] - fixed: Trying to show a popup crashed in the SBARINFO code because of a missing NULL pointer check. SVN r2080 (trunk) --- docs/rh-log.txt | 4 +++- src/g_shared/sbarinfo.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 707cdec10..2c7c7eaeb 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ -January 2, 2010 (Changes by Graf Zahl) +January 2, 2010 (Changes by Graf Zahl) +- fixed: Trying to show a popup crashed in the SBARINFO code because of a + missing NULL pointer check. - fixed: The ACS thinker needs its own statnum above all actors. Otherwise order of execution is not guaranteed. - fixed: Only ActorMovers should go into STAT_ACTORMOVER, not all PathFollowers. diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 9a2fe38a4..ccc8ff4af 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -967,7 +967,7 @@ public: script->popups[currentPopup-1].open(); } - lastPopup->Tick(NULL, this, false); + if (lastPopup != NULL) lastPopup->Tick(NULL, this, false); } script->huds[lastHud]->Tick(NULL, this, false); From 92b8ac26c094edc6e9a31ca4fd5c508039108027 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 13:17:47 +0000 Subject: [PATCH 183/241] - fixed: Polyobjects could contain segs that weren't flagged as such. SVN r2081 (trunk) --- docs/rh-log.txt | 1 + src/po_man.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2c7c7eaeb..bfae5c120 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ January 2, 2010 (Changes by Graf Zahl) +- fixed: Polyobjects could contain segs that weren't flagged as such. - fixed: Trying to show a popup crashed in the SBARINFO code because of a missing NULL pointer check. - fixed: The ACS thinker needs its own statnum above all actors. Otherwise diff --git a/src/po_man.cpp b/src/po_man.cpp index 37faf119a..8ed58cf8c 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1545,6 +1545,7 @@ static void TranslateToStartSpot (int tag, int originX, int originY) validcount++; for (i = 0; i < po->numsegs; i++, tempSeg++, tempPt++) { + (*tempSeg)->bPolySeg = true; // this is not set for all segs (*tempSeg)->sidedef->Flags |= WALLF_POLYOBJ; if ((*tempSeg)->linedef->validcount != validcount) { From 1c2cc7bd3a507b9746d92f1ead0c966b31a2be20 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Jan 2010 23:37:43 +0000 Subject: [PATCH 184/241] - fixed: The GAMEINFO parser needs to use C mode. SVN r2089 (trunk) --- docs/rh-log.txt | 1 + src/d_main.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bfae5c120..a79dbdeed 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,5 @@ January 2, 2010 (Changes by Graf Zahl) +- fixed: The GAMEINFO parser needs to use C mode. - fixed: Polyobjects could contain segs that weren't flagged as such. - fixed: Trying to show a popup crashed in the SBARINFO code because of a missing NULL pointer check. diff --git a/src/d_main.cpp b/src/d_main.cpp index 3de2bab7c..60546f68e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1642,6 +1642,7 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char const char *lastSlash = strrchr (fn, '/'); sc.OpenMem("GAMEINFO", data, size); + sc.SetCMode(true); while(sc.GetToken()) { sc.TokenMustBe(TK_Identifier); From 6b5089e53f472cc2e69b15d5aedcd20f7c22c59d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Jan 2010 00:13:37 +0000 Subject: [PATCH 185/241] - reverted r2089 because it didn't do what it was supposed to. SVN r2091 (trunk) --- docs/rh-log.txt | 1 - src/d_main.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a79dbdeed..bfae5c120 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,5 +1,4 @@ January 2, 2010 (Changes by Graf Zahl) -- fixed: The GAMEINFO parser needs to use C mode. - fixed: Polyobjects could contain segs that weren't flagged as such. - fixed: Trying to show a popup crashed in the SBARINFO code because of a missing NULL pointer check. diff --git a/src/d_main.cpp b/src/d_main.cpp index 60546f68e..3de2bab7c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1642,7 +1642,6 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char const char *lastSlash = strrchr (fn, '/'); sc.OpenMem("GAMEINFO", data, size); - sc.SetCMode(true); while(sc.GetToken()) { sc.TokenMustBe(TK_Identifier); From 56ab0e681d045db3d1320f365f6c0235f1bc8e9f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 3 Jan 2010 00:54:34 +0000 Subject: [PATCH 186/241] - Revert revision 2071. SVN r2092 (trunk) --- docs/rh-log.txt | 7 ++++--- src/nodebuild.cpp | 38 ++--------------------------------- src/p_setup.cpp | 51 +---------------------------------------------- src/r_bsp.cpp | 1 - 4 files changed, 7 insertions(+), 90 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index bfae5c120..41565caf1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -31,9 +31,6 @@ January 1, 2010 (Changes by Graf Zahl) - replaced wadlist_t with an array of FStrings and added a list parameter to everything that eventually calls D_AddFile. Also create the list of files loaded on the command line separately to allow further checks on them. -- fixed: The node builder did not check if all segs could be split properly. - Also removed some fudging that tried to work around this case but produced - a broken BSP tree on other maps. - Added Blzut3's Solaris patch. - Fixed: Heretic's Weredragon (Beast) should not have a melee state. @@ -45,6 +42,10 @@ January 1, 2010 (SBARINFO update) - As an extension to the previous you can now use comparison operators on inventory items and armortype in drawswitchableimage. +January 1, 2010 (Changes by Graf Zahl) +- Added Blzut3's Solaris patch. +- Fixed: Heretic's Weredragon (Beast) should not have a melee state. + December 31, 2009 (Changes by Graf Zahl) - fixed: FastProjectile was missing all sky checks when the projectile's move was blocked. diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index 3c87fb6e5..a988ba6e8 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -114,17 +114,6 @@ int FNodeBuilder::CreateNode (DWORD set, fixed_t bbox[4]) DWORD set1, set2; SplitSegs (set, node, splitseg, set1, set2); - - // Check if the set could be split. It may happen that all segs end up on the same side - // in which case we need to create a subsector from such a set. - if (set1 == DWORD_MAX) - { - return 0x80000000 | CreateSubsector (set2, bbox); - } - else if (set2 == DWORD_MAX) - { - return 0x80000000 | CreateSubsector (set1, bbox); - } D(PrintSet (1, set1)); D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); D(PrintSet (2, set2)); @@ -501,9 +490,7 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) { - int score = 1000000; // a high base so that segs that come too close to a splitter - // still can be weighed extremely negatively but preventing - // them from creating a negative score. + int score = 0; int segsInSet = 0; int counts[2] = { 0, 0 }; int realSegs[2] = { 0, 0 }; @@ -780,27 +767,6 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y)); vertnum = VertexMap->SelectVertexClose (newvert); - if (vertnum == seg->v1 || vertnum == seg->v2) - { - // Check if the resulting split vertex matches one of the line's ends. - // In this case this seg must not be split - if ((vertnum == seg->v1 && sidev2 == -1) || (vertnum == seg->v2 && sidev1 == -1)) - { - side = 0; - sidev1 = 0; - seg->next = outset0; - outset0 = set; - } - else - { - side = 1; - sidev2 = 0; - seg->next = outset1; - outset1 = set; - } - break; - } - seg2 = SplitSeg (set, vertnum, sidev1); Segs[seg2].next = outset0; @@ -875,7 +841,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou set = next; } FixSplitSharers (node); - if (GLNodes && outset0 != DWORD_MAX && outset1 != DWORD_MAX) + if (GLNodes) { AddMinisegs (node, splitseg, outset0, outset1); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 6b714cf44..ab467a77e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -2712,7 +2712,6 @@ static void P_GroupLines (bool buildmap) FBoundingBox bbox; bool flaggedNoFronts = false; unsigned int ii, jj; - TArray nosector; for (i = 0; i < (int)countof(times); ++i) { @@ -2723,13 +2722,7 @@ static void P_GroupLines (bool buildmap) times[0].Clock(); for (i = 0; i < numsubsectors; i++) { - side_t *side = segs[subsectors[i].firstline].sidedef; - if (side != NULL) subsectors[i].sector = side->sector; - else - { - subsectors[i].sector = NULL; - nosector.Push(i); - } + subsectors[i].sector = segs[subsectors[i].firstline].sidedef->sector; subsectors[i].validcount = validcount; double accumx = 0.0, accumy = 0.0; @@ -2744,48 +2737,6 @@ static void P_GroupLines (bool buildmap) subsectors[i].CenterX = fixed_t(accumx * 0.5 / subsectors[i].numlines); subsectors[i].CenterY = fixed_t(accumy * 0.5 / subsectors[i].numlines); } - for(unsigned i=0;inumlines; j++) - { - seg_t *seg = &segs[sub->firstline + j]; - if (seg->frontsector != NULL) - { - sub->sector = seg->frontsector; - break; - } - if (seg->PartnerSeg != NULL && seg->PartnerSeg->backsector != NULL) - { - sub->sector = seg->PartnerSeg->backsector; - break; - } - } - // we still haven't found a matching sector. Check the back sides of this subsector's segs next - if (sub->sector == NULL) - { - for(unsigned j=0;jnumlines; j++) - { - seg_t *seg = &segs[sub->firstline + j]; - if (seg->backsector != NULL) - { - sub->sector = seg->backsector; - break; - } - if (seg->PartnerSeg != NULL && seg->PartnerSeg->frontsector != NULL) - { - sub->sector = seg->PartnerSeg->frontsector; - break; - } - } - } - if (sub->sector == NULL) - { - sub->sector = §ors[0]; // prevent crashes. This hopefully does not matter because - // any subsector going through here is malformed. - Printf("Unable to assign a sector to subsector %d\n", subsectors[i].firstline); - } - } times[0].Unclock(); // count number of lines in each sector diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index a0aa40e8d..a1f6f6098 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -1026,7 +1026,6 @@ void R_Subsector (subsector_t *sub) #endif frontsector = sub->sector; - if (sub->sector == NULL) return; frontsector->MoreFlags |= SECF_DRAWN; count = sub->numlines; line = &segs[sub->firstline]; From 8bbd90b200051fba0292088c3e9d61a269eb7f88 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 3 Jan 2010 01:03:44 +0000 Subject: [PATCH 187/241] - Merge latest ZDBSP changes into trunk. SVN r2094 (trunk) --- src/nodebuild.cpp | 31 +++++++++++++++++++++++++++++-- src/nodebuild.h | 3 +++ src/nodebuild_utility.cpp | 8 ++++---- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index a988ba6e8..90aaff492 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -490,7 +490,8 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) { - int score = 0; + // Set the initial score above 0 so that near vertex anti-weighting is less likely to produce a negative score. + int score = 1000000; int segsInSet = 0; int counts[2] = { 0, 0 }; int realSegs[2] = { 0, 0 }; @@ -596,7 +597,28 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) frac = InterceptVector (node, *test); if (frac < 0.001 || frac > 0.999) { - score -= int(1 / frac); + FPrivVert *v1 = &Vertices[test->v1]; + FPrivVert *v2 = &Vertices[test->v2]; + double x = v1->x, y = v1->y; + x += frac * (v2->x - x); + y += frac * (v2->y - y); + if (fabs(x - v1->x) < VERTEX_EPSILON+1 && fabs(y - v1->y) < VERTEX_EPSILON+1) + { + D(Printf("Splitter will produce same start vertex as seg %d\n", i)); + return -1; + } + if (fabs(x - v2->x) < VERTEX_EPSILON+1 && fabs(y - v2->y) < VERTEX_EPSILON+1) + { + D(Printf("Splitter will produce same end vertex as seg %d\n", i)); + return -1; + } + if (frac > 0.999) + { + frac = 1 - frac; + } + int penalty = int(1 / frac); + score = MAX(score - penalty, 1); + D(Printf ("Penalized splitter by %d for being near endpt of seg %d (%f).\n", penalty, i, frac)); } counts[0]++; @@ -767,6 +789,11 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y)); vertnum = VertexMap->SelectVertexClose (newvert); + if (vertnum == seg->v1 || vertnum == seg->v2) + { + Printf("SelectVertexClose selected endpoint of seg %u\n", set); + } + seg2 = SplitSeg (set, vertnum, sidev1); Segs[seg2].next = outset0; diff --git a/src/nodebuild.h b/src/nodebuild.h index d142a289b..d0d59e706 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -243,6 +243,9 @@ private: // Units are in fixed_ts. const double SIDE_EPSILON = 6.5536; +// Vertices within this distance of each other will be considered as the same vertex. +#define VERTEX_EPSILON 6 // This is a fixed_t value + inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy) { // For most cases, a simple dot product is enough. diff --git a/src/nodebuild_utility.cpp b/src/nodebuild_utility.cpp index 3e50368cf..a8a618b9f 100644 --- a/src/nodebuild_utility.cpp +++ b/src/nodebuild_utility.cpp @@ -53,10 +53,6 @@ static const int PO_LINE_START = 1; static const int PO_LINE_EXPLICIT = 5; -// Vertices within this distance of each other vertically and horizontally -// will be considered as the same vertex. -const fixed_t VERTEX_EPSILON = 6; - #if 0 #define D(x) x #else @@ -555,8 +551,12 @@ int FNodeBuilder::FVertexMap::SelectVertexClose (FNodeBuilder::FPrivVert &vert) for (i = 0; i < block.Size(); ++i) { +#if VERTEX_EPSILON <= 1 + if (vertices[block[i]].x == vert.x && vertices[block[i]].y == vert.y) +#else if (abs(vertices[block[i]].x - vert.x) < VERTEX_EPSILON && abs(vertices[block[i]].y - vert.y) < VERTEX_EPSILON) +#endif { return block[i]; } From 4b64df67785d2a07a9efc265a7fd6fe31268123d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Jan 2010 10:04:56 +0000 Subject: [PATCH 188/241] - fixed: The player setup menu used the main menu's line spacing which for all non-Doom games was too wide. - fixed: Strife's dialogues cannot use the new options menu code to draw themselves so now they use a stripped down version of the old code. - Replaced I_MSTime with I_FPSTime in node builder timing because basetime will not be initialized yet if a map is started directly from the commandline. SVN r2096 (trunk) --- docs/rh-log.txt | 10 +++++++- src/m_menu.cpp | 1 + src/m_menu.h | 3 ++- src/m_options.cpp | 10 ++++---- src/p_conversation.cpp | 55 +++++++++++++++++++++++++++++++++++++++--- src/p_setup.cpp | 4 +-- 6 files changed, 71 insertions(+), 12 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 41565caf1..21d2534d0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,12 @@ -January 2, 2010 (Changes by Graf Zahl) +January 3, 2010 (Changes by Graf Zahl) +- fixed: The player setup menu used the main menu's line spacing which + for all non-Doom games was too wide. +- fixed: Strife's dialogues cannot use the new options menu code to draw + themselves so now they use a stripped down version of the old code. +- Replaced I_MSTime with I_FPSTime in node builder timing because basetime + will not be initialized yet if a map is started directly from the commandline. + +January 2, 2010 (Changes by Graf Zahl) - fixed: Polyobjects could contain segs that weren't flagged as such. - fixed: Trying to show a popup crashed in the SBARINFO code because of a missing NULL pointer check. diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 3535cf484..1d1cc6601 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -2142,6 +2142,7 @@ static void M_DrawPlayerSlider (int x, int y, int cur) static void M_PlayerSetupDrawer () { + const int LINEHEIGHT = 16; int x, xo, yo; EColorRange label, value; DWORD color; diff --git a/src/m_menu.h b/src/m_menu.h index 997cf0e7d..f46b6a9e9 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -178,7 +178,7 @@ struct menu_t { int scrolltop; int scrollpos; int y; - void (*PreDraw)(void); + bool (*PreDraw)(void); bool DontDim; void (*EscapeHandler)(void); }; @@ -264,6 +264,7 @@ extern menustack_t MenuStack[16]; extern int MenuStackDepth; extern bool OptionsActive; +extern int skullAnimCounter; extern menu_t *CurrentMenu; extern int CurrentItem; diff --git a/src/m_options.cpp b/src/m_options.cpp index 83b2a038d..9815443f4 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -107,8 +107,6 @@ CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE) EXTERN_CVAR (Bool, longsavemessages) EXTERN_CVAR (Bool, screenshot_quiet) -extern int skullAnimCounter; - EXTERN_CVAR (Bool, cl_run) EXTERN_CVAR (Int, crosshair) EXTERN_CVAR (Bool, freelook) @@ -1651,7 +1649,7 @@ void M_OptDrawer () if (CurrentMenu->PreDraw != NULL) { - CurrentMenu->PreDraw (); + if (CurrentMenu->PreDraw ()) return; } if (CurrentMenu->y != 0) @@ -3002,7 +3000,7 @@ static void DefaultCustomColors () } } -static void ColorPickerDrawer () +static bool ColorPickerDrawer () { DWORD newColor = MAKEARGB(255, int(ColorPickerItems[2].a.fval), @@ -3021,6 +3019,7 @@ static void ColorPickerDrawer () "Old", DTA_CleanNoMove_1, true, TAG_DONE); screen->DrawText (SmallFont, CR_WHITE, x+(48+24-SmallFont->StringWidth("New")/2)*CleanXfac_1, y, "New", DTA_CleanNoMove_1, true, TAG_DONE); + return false; } static void SetColorPickerSliders () @@ -3117,7 +3116,7 @@ CCMD (menu_mouse) MouseOptions (); } -static void DrawJoystickConfigMenuHeader() +static bool DrawJoystickConfigMenuHeader() { FString joyname = SELECTED_JOYSTICK->GetName(); screen->DrawText(BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, @@ -3127,6 +3126,7 @@ static void DrawJoystickConfigMenuHeader() screen->DrawText(SmallFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED, (screen->GetWidth() - SmallFont->StringWidth(joyname) * CleanXfac_1) / 2, (8 + BigFont->GetHeight()) * CleanYfac_1, joyname, DTA_CleanNoMove_1, true, TAG_DONE); + return false; } static void UpdateJoystickConfigMenu(IJoystickConfig *joy) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 23147343b..53667881c 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -117,7 +117,7 @@ static void LoadScriptFile(FileReader *lump, int numnodes); static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeakerType); static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeakerType); static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses); -static void DrawConversationMenu (); +static bool DrawConversationMenu (); static void PickConversationReply (); static void CleanupConversationMenu (); static void ConversationMenuEscaped (); @@ -804,6 +804,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang OptionsActive = true; menuactive = MENU_OnNoPause; ConversationPauseTic = gametic + 20; + M_SwitchMenu (&ConversationMenu); } } @@ -838,10 +839,13 @@ void P_ResumeConversation () // //============================================================================ -static void DrawConversationMenu () +static bool DrawConversationMenu () { const char *speakerName; int i, x, y, linesize; + int width, fontheight; + menuitem_t *item; + int labelofs; player_t *cp = &players[consoleplayer]; @@ -851,7 +855,7 @@ static void DrawConversationMenu () if (CurNode == NULL) { M_ClearMenus (); - return; + return true; } // [CW] Freeze the game depending on MAPINFO options. @@ -925,8 +929,53 @@ static void DrawConversationMenu () screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon), 2, 189, DTA_320x200, true, TAG_DONE); } + + y = CurrentMenu->y; + + if (gameinfo.gametype & GAME_Raven) + { + labelofs = 2; + y -= 2; + fontheight = 9; + } + else + { + labelofs = 0; + fontheight = 8; + } + for (i = 0; i < CurrentMenu->numitems; i++, y += fontheight) + { + item = CurrentMenu->items + i; + + width = SmallFont->StringWidth(item->label); + x = CurrentMenu->indent + 14; + + screen->DrawText (SmallFont, CR_GREEN, x, y, item->label, DTA_Clean, true, TAG_DONE); + + if (item->b.position != 0) + { + char tbuf[16]; + + mysnprintf (tbuf, countof(tbuf), "%d.", item->b.position); + x = CurrentMenu->indent - SmallFont->StringWidth (tbuf); + screen->DrawText (SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE); + } + + if (i == CurrentItem && + (skullAnimCounter < 6 || menuactive == MENU_WaitKey)) + { + int x = (CurrentMenu->indent + 3 - 160) * CleanXfac + screen->GetWidth() / 2; + int yy = (y-1+labelofs - 100) * CleanYfac + screen->GetHeight() / 2; + screen->DrawText (ConFont, CR_RED, x, yy, "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + } + } + return true; } + //============================================================================ // // PickConversationReply diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ab467a77e..100f4bd10 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3574,7 +3574,7 @@ void P_SetupLevel (char *lumpname, int position) { unsigned int startTime, endTime; - startTime = I_MSTime (); + startTime = I_FPSTime (); TArray polyspots, anchors; P_GetPolySpots (map, polyspots, anchors); FNodeBuilder::FLevel leveldata = @@ -3591,7 +3591,7 @@ void P_SetupLevel (char *lumpname, int position) segs, numsegs, subsectors, numsubsectors, vertexes, numvertexes); - endTime = I_MSTime (); + endTime = I_FPSTime (); DPrintf ("BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, numsegs); } From 1aae2895f4cb5c9445e9a5b6d030aa6d4c66b7e2 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 5 Jan 2010 02:56:27 +0000 Subject: [PATCH 189/241] - Fixed: The player setup menu still drew the cursor at the original Y positions. SVN r2098 (trunk) --- src/m_menu.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 1d1cc6601..e817bebbc 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -235,6 +235,7 @@ static int saveSlot; // which slot to save in static size_t saveCharIndex; // which char we're editing static int LINEHEIGHT; +static const int PLAYERSETUP_LINEHEIGHT = 16; static char savegamestring[SAVESTRINGSIZE]; static FString EndString; @@ -2142,7 +2143,7 @@ static void M_DrawPlayerSlider (int x, int y, int cur) static void M_PlayerSetupDrawer () { - const int LINEHEIGHT = 16; + const int LINEHEIGHT = PLAYERSETUP_LINEHEIGHT; int x, xo, yo; EColorRange label, value; DWORD color; @@ -3543,7 +3544,7 @@ void M_Drawer () if (skullAnimCounter < 6) { screen->DrawText (ConFont, CR_RED, x - 16, - currentMenu->y + itemOn*LINEHEIGHT + + currentMenu->y + itemOn*PLAYERSETUP_LINEHEIGHT + (!(gameinfo.gametype & (GAME_DoomStrifeChex)) ? 6 : -1), "\xd", DTA_Clean, true, TAG_DONE); } From f300948916ba2e1a6460246245b593617ec78863 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 5 Jan 2010 13:45:07 +0000 Subject: [PATCH 190/241] - fixed: Action Doom 2 and Harmony IWADs were missing the GI_MAPxx flag. SVN r2100 (trunk) --- src/d_iwad.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 075f5f700..3beb23fba 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -80,8 +80,8 @@ const IWADInfo IWADInfos[NUM_IWAD_TYPES] = { "Blasphemer", "Blasphemer",MAKERGB(115,0,0), MAKERGB(0,0,0), GAME_Heretic, "mapinfo/heretic.txt" }, { "Chex(R) Quest", "Chex1", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex.txt" }, { "Chex(R) Quest 3", "Chex3", MAKERGB(255,255,0), MAKERGB(0,192,0), GAME_Chex, "mapinfo/chex3.txt" }, - { "Action Doom 2: Urban Brawl", "UrbanBrawl",MAKERGB(168,168,0), MAKERGB(168,0,0), GAME_Doom, "mapinfo/doom2.txt" }, - { "Harmony", "Harmony", MAKERGB(110,180,230), MAKERGB(69,79,126), GAME_Doom, "mapinfo/doom2.txt" }, + { "Action Doom 2: Urban Brawl", "UrbanBrawl",MAKERGB(168,168,0), MAKERGB(168,0,0), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx }, + { "Harmony", "Harmony", MAKERGB(110,180,230), MAKERGB(69,79,126), GAME_Doom, "mapinfo/doom2.txt", GI_MAPxx }, //{ "ZDoom Engine", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) }, }; From 4b65749f9276c6f4e30a7699126f80cc3eda1691 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 6 Jan 2010 03:27:37 +0000 Subject: [PATCH 191/241] - Corrected several Strife switches that had the wrong sounds. SVN r2101 (trunk) --- wadsrc/static/animdefs.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wadsrc/static/animdefs.txt b/wadsrc/static/animdefs.txt index 2c492ddb0..f6e1570a7 100644 --- a/wadsrc/static/animdefs.txt +++ b/wadsrc/static/animdefs.txt @@ -150,13 +150,13 @@ switch strife COMP12 on sound world/glassbreak pic COMP04B tics 0 switch strife COMP13 on sound world/glassbreak pic COMP12B tics 0 switch strife COMP17 on sound world/glassbreak pic COMP20B tics 0 switch strife COMP21 on sound world/glassbreak pic COMP28B tics 0 -switch strife WALTEK09 on sound world/glassbreak pic WALTEKB1 tics 0 -switch strife WALTEK10 on sound world/glassbreak pic WALTEKB1 tics 0 -switch strife WALTEK15 on sound world/glassbreak pic WALTEKB1 tics 0 +switch strife WALTEK09 on pic WALTEKB1 tics 0 +switch strife WALTEK10 on pic WALTEKB1 tics 0 +switch strife WALTEK15 on pic WALTEKB1 tics 0 switch strife SWFORC01 on pic SWFORC02 tics 0 switch strife SWEXIT01 on pic SWEXIT02 tics 0 switch strife DORSBK01 on sound switches/stone pic DORSBK02 tics 0 -switch strife SWSLD01 on sound switches/keycard pic SWSLD02 tics 0 +switch strife SWSLD01 on pic SWSLD02 tics 0 switch strife DORWS04 on sound switches/bolt pic DORWS05 tics 0 switch strife SWIRON01 on pic SWIRON02 tics 0 switch strife GLASS09 on sound world/glassbreak pic GLASS10 tics 0 @@ -183,15 +183,15 @@ switch strife SWBRIK01 on pic SWBRIK02 tics 0 switch strife SWIRON03 on pic SWIRON04 tics 0 switch strife SWIRON05 on pic SWIRON06 tics 0 switch strife SWIRON07 on pic SWIRON08 tics 0 -switch strife SWCARD01 on pic SWCARD02 tics 0 +switch strife SWCARD01 on sound switches/keycard pic SWCARD02 tics 0 switch strife SWSIGN01 on pic SWSIGN02 tics 0 switch strife SWLEV01 on pic SWLEV02 tics 0 switch strife SWLEV03 on pic SWLEV04 tics 0 switch strife SWLEV05 on pic SWLEV06 tics 0 -switch strife SWBRN01 on pic SWBRN02 tics 0 +switch strife SWBRN01 on sound switches/keycard pic SWBRN02 tics 0 switch strife SWPIP01 on sound switches/valve pic SWPIP02 tics 0 switch strife SWPALM01 on sound switches/scanner pic SWPALM02 tics 0 -switch strife SWKNOB03 on pic SWKNOB04 tics 0 +switch strife SWKNOB03 on sound switches/knob pic SWKNOB04 tics 0 switch strife ALTSW01 on pic ALTSW02 tics 0 switch strife COMP25 on sound world/glassbreak pic COMP28B tics 0 switch strife COMP29 on sound world/glassbreak pic COMP20B tics 0 From 870628dda52e904b371338268bdc1f29d0b70469 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 6 Jan 2010 04:36:38 +0000 Subject: [PATCH 192/241] - Split conversation initiation out of P_UseTraverse() and into a separate function. It no longer piggy-backs off of Hexen's puzzle item traversal but instead works like Strife, using P_AimLineAttack() to find something to talk to and includes some slight left and right "autoaim". I can think of a few consequences of this: * Using puzzle items on actors has been restored to its original range of 64. * Since talking now depends on P_AimLineAttack() instead of a line use traversal, you can probably set up situations where you can talk to somebody that you couldn't talk to before because some special line was in the way. * You don't need to stick a guard flush against the wall to block players from using a switch behind them, because now the autoaim will get the player. SVN r2102 (trunk) --- src/p_local.h | 2 ++ src/p_map.cpp | 83 +++++++++++++++++++++++++++++--------------------- src/p_user.cpp | 5 ++- 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 27654aafa..fe3b84cd3 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -52,6 +52,7 @@ //#define GRAVITY FRACUNIT #define MAXMOVE (30*FRACUNIT) +#define TALKRANGE (128*FRACUNIT) #define USERANGE (64*FRACUNIT) #define MELEERANGE (64*FRACUNIT) #define MISSILERANGE (32*64*FRACUNIT) @@ -390,6 +391,7 @@ bool P_BounceWall (AActor *mo); bool P_BounceActor (AActor *mo, AActor * BlockingMobj); bool P_CheckSight (const AActor* t1, const AActor* t2, int flags=0); void P_ResetSightCounters (bool full); +bool P_TalkFacing (AActor *player); void P_UseLines (player_t* player); bool P_UsePuzzleItem (AActor *actor, int itemType); void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false); diff --git a/src/p_map.cpp b/src/p_map.cpp index dc056972f..b7f8c04f1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3905,6 +3905,52 @@ void P_AimCamera (AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &Camer } +//========================================================================== +// +// P_TalkFacing +// +// Looks for something within 5.625 degrees left or right of the player +// to talk to. +// +//========================================================================== + +bool P_TalkFacing(AActor *player) +{ + AActor *linetarget; + + P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1*35, true); + if (linetarget == NULL) + { + P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, true); + if (linetarget == NULL) + { + P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1*35, true); + if (linetarget == NULL) + { + return false; + } + } + } + // Dead things can't talk. + if (linetarget->health <= 0) + { + return false; + } + // Fighting things don't talk either. + if (linetarget->flags4 & MF4_INCOMBAT) + { + return false; + } + if (linetarget->Conversation != NULL) + { + // Give the NPC a chance to play a brief animation + linetarget->ConversationAnimation (0); + P_StartConversation (linetarget, player, true, true); + return true; + } + return false; +} + //========================================================================== // // USE LINES @@ -3921,7 +3967,8 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline // [RH] Check for things to talk with or use a puzzle item on if (!in->isaline) { - if (usething==in->d.thing) continue; + if (usething == in->d.thing) + continue; // Check thing // Check for puzzle item use or USESPECIAL flag @@ -3931,38 +3978,10 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline if (P_ActivateThingSpecial(in->d.thing, usething)) return true; } - // Dead things can't talk. - if (in->d.thing->health <= 0) - { - continue; - } - // Fighting things don't talk either. - if (in->d.thing->flags4 & MF4_INCOMBAT) - { - continue; - } - if (in->d.thing->Conversation != NULL) - { - // Give the NPC a chance to play a brief animation - in->d.thing->ConversationAnimation (0); - P_StartConversation (in->d.thing, usething, true, true); - return true; - } continue; } FLineOpening open; - // [RH] The range passed to P_PathTraverse was doubled so that it could - // find things up to 128 units away (for Strife), but it should still reject - // lines further than 64 units away. - if (in->frac > FRACUNIT/2) - { - // don't pass usething here. It will not do what might be expected! - P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac), - it.Trace().y + FixedMul (it.Trace().dy, in->frac)); - if (open.range <= 0) return false; - else continue; - } if (in->d.line->special == 0 || !(in->d.line->activation & (SPAC_Use|SPAC_UseThrough))) { blocked: @@ -4082,7 +4101,6 @@ void P_UseLines (player_t *player) { angle_t angle; fixed_t x1, y1; - fixed_t x2, y2; bool foundline; foundline = false; @@ -4091,16 +4109,13 @@ void P_UseLines (player_t *player) x1 = player->mo->x + (USERANGE>>FRACBITS)*finecosine[angle]; y1 = player->mo->y + (USERANGE>>FRACBITS)*finesine[angle]; - x2 = player->mo->x + (USERANGE>>FRACBITS)*finecosine[angle]*2; - y2 = player->mo->y + (USERANGE>>FRACBITS)*finesine[angle]*2; - // old code: // // P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); // // This added test makes the "oof" sound work on 2s lines -- killough: - if (!P_UseTraverse (player->mo, x2, y2, foundline)) + if (!P_UseTraverse (player->mo, x1, y1, foundline)) { // [RH] Give sector a chance to eat the use sector_t *sec = player->mo->Sector; int spac = SECSPAC_Use; diff --git a/src/p_user.cpp b/src/p_user.cpp index ff3c8c01e..ff1a80dae 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2293,7 +2293,10 @@ void P_PlayerThink (player_t *player) if (!player->usedown) { player->usedown = true; - P_UseLines (player); + if (!P_TalkFacing(player->mo)) + { + P_UseLines(player); + } } } else From 1e5b84ea141582ef8e229c1989fe0f7cd9582d5b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 02:10:05 +0000 Subject: [PATCH 193/241] - Fixed: I forgot to reimplement the number keys for Strife's dialogues when I redid the menus to work with controllers. SVN r2103 (trunk) --- src/m_menu.cpp | 55 ++++++++++++++++++++++++++--------------------- src/m_options.cpp | 54 ++++++++++++++++++---------------------------- 2 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/m_menu.cpp b/src/m_menu.cpp index e817bebbc..229da94db 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -2966,40 +2966,47 @@ bool M_Responder (event_t *ev) { mkey = MKEY_Clear; } - else if (!keyup && !OptionsActive) + else if (!keyup) { - ch = tolower (ch); - if (messageToPrint) + if (OptionsActive) { - // Take care of any messages that need input - ch = tolower (ch); - assert(messageRoutine != NULL); - if (ch != ' ' && ch != 'n' && ch != 'y') - { - return false; - } - D_RemoveNextCharEvent(); - M_EndMessage(ch); - return true; + M_OptResponder(ev); } else { - // Search for a menu item associated with the pressed key. - for (i = (itemOn + 1) % currentMenu->numitems; - i != itemOn; - i = (i + 1) % currentMenu->numitems) + ch = tolower (ch); + if (messageToPrint) { + // Take care of any messages that need input + ch = tolower (ch); + assert(messageRoutine != NULL); + if (ch != ' ' && ch != 'n' && ch != 'y') + { + return false; + } + D_RemoveNextCharEvent(); + M_EndMessage(ch); + return true; + } + else + { + // Search for a menu item associated with the pressed key. + for (i = (itemOn + 1) % currentMenu->numitems; + i != itemOn; + i = (i + 1) % currentMenu->numitems) + { + if (currentMenu->menuitems[i].alphaKey == ch) + { + break; + } + } if (currentMenu->menuitems[i].alphaKey == ch) { - break; + itemOn = i; + S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE); + return true; } } - if (currentMenu->menuitems[i].alphaKey == ch) - { - itemOn = i; - S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE); - return true; - } } } break; diff --git a/src/m_options.cpp b/src/m_options.cpp index 9815443f4..5e95f1a5e 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -2141,11 +2141,10 @@ void M_OptResponder(event_t *ev) CurrentMenu->items[0].label = OldMessage; CurrentMenu->items[0].type = OldType; } - else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown && tolower(ev->data1) == 't') + else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown) { - // Test selected resolution - if (CurrentMenu == &ModesMenu) - { + if (CurrentMenu == &ModesMenu && (ev->data1 == 't' || ev->data1 == 'T')) + { // Test selected resolution if (!(item->type == screenres && GetSelectedSize (CurrentItem, &NewWidth, &NewHeight))) { @@ -2161,6 +2160,23 @@ void M_OptResponder(event_t *ev) S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", 1, ATTN_NONE); SetModesMenu (NewWidth, NewHeight, NewBits); } + else if (ev->data1 >= '0' && ev->data1 <= '9') + { // Activate an item of type numberedmore + int i; + int num = ev->data1 == '0' ? 10 : ev->data1 - '0'; + + for (i = 0; i < CurrentMenu->numitems; ++i) + { + menuitem_t *item = CurrentMenu->items + i; + + if (item->type == numberedmore && item->b.position == num) + { + CurrentItem = i; + M_OptButtonHandler(MKEY_Enter, false); + break; + } + } + } } } @@ -2769,35 +2785,7 @@ void M_OptButtonHandler(EMenuKey key, bool repeat) item->b.key1 = item->c.key2 = 0; } break; -/* - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int lookfor = ch == '0' ? 10 : ch - '0', i; - for (i = 0; i < CurrentMenu->numitems; ++i) - { - if (CurrentMenu->items[i].b.position == lookfor) - { - CurrentItem = i; - item = &CurrentMenu->items[i]; - break; - } - } - if (i == CurrentMenu->numitems) - { - break; - } - // Otherwise, fall through to '\r' below - } -*/ + case MKEY_Enter: if (CurrentMenu == &ModesMenu && item->type == screenres) { From 2228c3798518e02f5b4aaaaf4e7d82f4d3f7857d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 02:15:42 +0000 Subject: [PATCH 194/241] - Fixed: Don't color the teleporter beacon's rebels in single player. SVN r2104 (trunk) --- src/g_strife/a_rebels.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index 855da34fb..6b4e74605 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -95,8 +95,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon) } if (owner != NULL) { - // Rebels are the same color as their owner - rebel->Translation = owner->Translation; + // Rebels are the same color as their owner (but only in nomultiplayer) + if (multiplayer) + { + rebel->Translation = owner->Translation; + } rebel->FriendPlayer = owner->player != NULL ? BYTE(owner->player - players + 1) : 0; // Set the rebel's target to whatever last hurt the player, so long as it's not // one of the player's other rebels. From 74a72931332f9722c5565de18313a034805ef699 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 02:17:49 +0000 Subject: [PATCH 195/241] - Fix spelling error in comment. SVN r2105 (trunk) --- src/g_strife/a_rebels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp index 6b4e74605..a9faf1671 100644 --- a/src/g_strife/a_rebels.cpp +++ b/src/g_strife/a_rebels.cpp @@ -95,7 +95,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Beacon) } if (owner != NULL) { - // Rebels are the same color as their owner (but only in nomultiplayer) + // Rebels are the same color as their owner (but only in multiplayer) if (multiplayer) { rebel->Translation = owner->Translation; From 6ba548511b02c95023785b14fa8bd9c06e55b058 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 03:24:22 +0000 Subject: [PATCH 196/241] - Fixed: Macil2 and the Oracle need to be immune to SpectralLightningV2 as well as V1, since they are both created by the first-stage Sigil. AlienSpectre3 should have also been immune to them but was not. In addition, Macil1 was erroneously immune to V1, when he should not be immune to any spectral damage. (Though, since he's immortal, all that really amounts to is that he can enter his pain state.) SVN r2106 (trunk) --- src/actor.h | 1 + src/g_strife/a_alienspectres.cpp | 34 +++++++++++++++++++ src/g_strife/a_macil.cpp | 26 ++++++++++---- src/g_strife/a_oracle.cpp | 8 +++-- src/g_strife/a_spectral.cpp | 6 ++-- src/g_strife/a_strifestuff.cpp | 2 +- src/namedef.h | 1 + src/p_mobj.cpp | 14 ++++++-- wadsrc/static/actors/strife/alienspectres.txt | 4 +-- wadsrc/static/actors/strife/macil.txt | 2 +- 10 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/actor.h b/src/actor.h index 5fd0619b9..d870e8df2 100644 --- a/src/actor.h +++ b/src/actor.h @@ -982,6 +982,7 @@ inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, repla } AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement); +AActor *Spawn (FName classname, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement); template inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement) diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index 6506cdb1c..b09c1b098 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -13,6 +13,20 @@ #include "doomstat.h" */ +class AAlienSpectre1 : public ASpectralMonster +{ + DECLARE_CLASS (AAlienSpectre1, ASpectralMonster) +}; +IMPLEMENT_CLASS(AAlienSpectre1); + +class AAlienSpectre3 : public AAlienSpectre1 +{ + DECLARE_CLASS (AAlienSpectre3, AAlienSpectre1) +public: + int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); +}; +IMPLEMENT_CLASS(AAlienSpectre3); + static FRandom pr_spectrespawn ("AlienSpectreSpawn"); static FRandom pr_spectrechunk ("212e4"); @@ -190,3 +204,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) S_Sound (CHAN_VOICE, voc, 1, ATTN_NORM); player->player->SetLogNumber (log); } + +//============================================================================ +// +// AAlienSpetre3 :: TakeSpecialDamage +// +// The third spectre type (the Oracle's) is invulnerable to the first stage +// Sigil, just like the Oracle. +// +//============================================================================ + +int AAlienSpectre3::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) +{ + if (inflictor != NULL) + { + FName name = inflictor->GetClass()->TypeName; + if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) + return -1; + } + return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); +} diff --git a/src/g_strife/a_macil.cpp b/src/g_strife/a_macil.cpp index 6557ef7cf..a5b3190ab 100644 --- a/src/g_strife/a_macil.cpp +++ b/src/g_strife/a_macil.cpp @@ -7,29 +7,41 @@ #include "a_strifeglobal.h" */ -// Macil (version 2) --------------------------------------------------------- +// Macil (version 1) --------------------------------------------------------- class AMacil1 : public AActor { DECLARE_CLASS (AMacil1, AActor) +}; + +IMPLEMENT_CLASS (AMacil1) + +// Macil (version 2) --------------------------------------------------------- + +class AMacil2 : public AMacil1 +{ + DECLARE_CLASS (AMacil2, AMacil1) public: int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); }; -IMPLEMENT_CLASS (AMacil1) +IMPLEMENT_CLASS (AMacil2) //============================================================================ // // AMacil2 :: TakeSpecialDamage // -// Macil is invulnerable to the first stage Sigil. +// Macil2 is invulnerable to the first stage Sigil. // //============================================================================ -int AMacil1::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) +int AMacil2::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { - if (inflictor != NULL && inflictor->GetClass()->TypeName == NAME_SpectralLightningV1) - return -1; - + if (inflictor != NULL) + { + FName name = inflictor->GetClass()->TypeName; + if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) + return -1; + } return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); } diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp index 11a9a52e4..d5d119e38 100644 --- a/src/g_strife/a_oracle.cpp +++ b/src/g_strife/a_oracle.cpp @@ -42,7 +42,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) int AOracle::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) { - if (inflictor != NULL && inflictor->GetClass()->TypeName == NAME_SpectralLightningV1) - return -1; + if (inflictor != NULL) + { + FName name = inflictor->GetClass()->TypeName; + if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) + return -1; + } return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); } diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp index 9506b3412..1272d35f8 100644 --- a/src/g_strife/a_spectral.cpp +++ b/src/g_strife/a_spectral.cpp @@ -64,14 +64,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning) x = self->x + pr_zap5.Random2(3) * FRACUNIT * 50; y = self->y + pr_zap5.Random2(3) * FRACUNIT * 50; - flash = Spawn (self->threshold > 25 ? PClass::FindClass("SpectralLightningV2") : - PClass::FindClass("SpectralLightningV1"), x, y, ONCEILINGZ, ALLOW_REPLACE); + flash = Spawn (self->threshold > 25 ? PClass::FindClass(NAME_SpectralLightningV2) : + PClass::FindClass(NAME_SpectralLightningV1), x, y, ONCEILINGZ, ALLOW_REPLACE); flash->target = self->target; flash->velz = -18*FRACUNIT; flash->health = self->health; - flash = Spawn("SpectralLightningV2", self->x, self->y, ONCEILINGZ, ALLOW_REPLACE); + flash = Spawn(NAME_SpectralLightningV2, self->x, self->y, ONCEILINGZ, ALLOW_REPLACE); flash->target = self->target; flash->velz = -18*FRACUNIT; diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 2764a2c0b..aba8228c1 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -21,6 +21,7 @@ // Include all the other Strife stuff here to reduce compile time #include "a_acolyte.cpp" +#include "a_spectral.cpp" #include "a_alienspectres.cpp" #include "a_coin.cpp" #include "a_crusader.cpp" @@ -33,7 +34,6 @@ #include "a_reaver.cpp" #include "a_rebels.cpp" #include "a_sentinel.cpp" -#include "a_spectral.cpp" #include "a_stalker.cpp" #include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" diff --git a/src/namedef.h b/src/namedef.h index 0eb9ce108..a95b4b5a0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -153,6 +153,7 @@ xx(Mauler) xx(AcolyteBlue) xx(SpectralLightningV1) +xx(SpectralLightningV2) xx(TeleportDest) xx(TeleportDest2) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 57ba84030..599f78772 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3674,11 +3674,21 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement) { - const PClass *cls = PClass::FindClass(type); - if (cls == NULL) + FName classname(type, true); + if (classname == NAME_None) { I_Error("Attempt to spawn actor of unknown type '%s'\n", type); } + return Spawn(classname, x, y, z, allowreplacement); +} + +AActor *Spawn (FName classname, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement) +{ + const PClass *cls = PClass::FindClass(classname); + if (cls == NULL) + { + I_Error("Attempt to spawn actor of unknown type '%s'\n", classname.GetChars()); + } return AActor::StaticSpawn (cls, x, y, z, allowreplacement); } diff --git a/wadsrc/static/actors/strife/alienspectres.txt b/wadsrc/static/actors/strife/alienspectres.txt index f0da99f28..2e3273c32 100644 --- a/wadsrc/static/actors/strife/alienspectres.txt +++ b/wadsrc/static/actors/strife/alienspectres.txt @@ -1,7 +1,7 @@ // Alien Spectre 1 ----------------------------------------------------------- -ACTOR AlienSpectre1 : SpectralMonster 129 +ACTOR AlienSpectre1 : SpectralMonster 129 native { Game Strife ConversationID 67,-1,-1 @@ -100,7 +100,7 @@ ACTOR AlienSpectre2 : AlienSpectre1 75 // Alien Spectre 3 ---------------------------------------------------------- // This is the Oracle's personal spectre, so it's a little different. -ACTOR AlienSpectre3 : AlienSpectre1 76 +ACTOR AlienSpectre3 : AlienSpectre1 76 native { Game Strife ConversationID 71,-1,-1 diff --git a/wadsrc/static/actors/strife/macil.txt b/wadsrc/static/actors/strife/macil.txt index fbd52ecad..38cba53c0 100644 --- a/wadsrc/static/actors/strife/macil.txt +++ b/wadsrc/static/actors/strife/macil.txt @@ -56,7 +56,7 @@ ACTOR Macil1 64 native // Macil (version 2) --------------------------------------------------------- -ACTOR Macil2 : Macil1 200 +ACTOR Macil2 : Macil1 200 native { Game Strife ConversationID 50, 49, 50 From 7df898c88ed45073671ecf1cafdd367f3a17f1e5 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 03:27:18 +0000 Subject: [PATCH 197/241] - Fixed: Two Strife pickup messages were off by one character each. SVN r2107 (trunk) --- wadsrc/static/language.enu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index a6f2ecd8a..16ae72997 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1099,7 +1099,7 @@ TXT_FTHROWERPARTS = "You picked up the flame thrower parts."; TXT_REPORT = "You picked up the report."; TXT_INFO = "You picked up the info."; TXT_TARGETER = "You picked up the Targeter."; -TXT_COMMUNICATOR = "You picked up the Communicator"; +TXT_COMMUNICATOR = "You picked up the Communicator."; TXT_COIN = "You picked up the coin."; TXT_XGOLD = "You picked up %d gold."; TXT_BEACON = "You picked up the Teleporter Beacon."; @@ -1147,7 +1147,7 @@ TXT_NEWKEY5 = "You picked up the New Key5."; TXT_ORACLEPASS = "You picked up the Oracle Pass."; TXT_HEGRENADES = "You picked up the HE-Grenade Rounds."; -TXT_PHGRENADES = "You picked up the Phoshorus-Grenade Rounds."; +TXT_PHGRENADES = "You picked up the Phosphorus-Grenade Rounds."; TXT_CLIPOFBULLETS = "You picked up the clip of bullets."; TXT_BOXOFBULLETS = "You picked up the box of bullets."; TXT_MINIMISSILES = "You picked up the mini missiles."; From 8de8924c477a5d9c3bdb6abf455e6893782ebb3c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 03:40:10 +0000 Subject: [PATCH 198/241] - Fixed: The MAPINFO keyword resetinventory only worked when traveling to a redirected map. SVN r2108 (trunk) --- src/g_level.cpp | 20 +++++++++++++------- src/g_mapinfo.cpp | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 6e4cd6f4a..1b0bd1130 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -570,18 +570,24 @@ void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nex return; } - nextlevel = levelname; - - if (strncmp(levelname, "enDSeQ", 6)) + if (strncmp(levelname, "enDSeQ", 6) != 0) { - nextinfo = FindLevelInfo (nextlevel)->CheckLevelRedirect (); - if (nextinfo) + nextinfo = FindLevelInfo (nextlevel); + if (nextinfo != NULL) { - nextlevel = nextinfo->mapname; + level_info_t *nextredir = nextinfo->CheckLevelRedirect(); + if (nextredir != NULL) + { + nextinfo = nextredir; + levelname = nextinfo->mapname; + } } } - if (nextSkill != -1) NextSkill = nextSkill; + nextlevel = levelname; + + if (nextSkill != -1) + NextSkill = nextSkill; g_nomonsters = nomonsters; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 800fa8957..f85b08960 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -85,7 +85,9 @@ level_info_t *FindLevelInfo (const char *mapname) int i; if ((i = FindWadLevelInfo (mapname)) > -1) + { return &wadlevelinfos[i]; + } else { if (TheDefaultLevelInfo.LevelName.IsEmpty()) From fc781ac9eec512794eae213125d330db2eaa526b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 03:51:33 +0000 Subject: [PATCH 199/241] - I guess I can't completely trust Strife1.exe's switch list. Not everything that plays the glass break sound is actually defined with it. SVN r2109 (trunk) --- wadsrc/static/animdefs.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wadsrc/static/animdefs.txt b/wadsrc/static/animdefs.txt index f6e1570a7..79ed3a3e5 100644 --- a/wadsrc/static/animdefs.txt +++ b/wadsrc/static/animdefs.txt @@ -150,9 +150,9 @@ switch strife COMP12 on sound world/glassbreak pic COMP04B tics 0 switch strife COMP13 on sound world/glassbreak pic COMP12B tics 0 switch strife COMP17 on sound world/glassbreak pic COMP20B tics 0 switch strife COMP21 on sound world/glassbreak pic COMP28B tics 0 -switch strife WALTEK09 on pic WALTEKB1 tics 0 -switch strife WALTEK10 on pic WALTEKB1 tics 0 -switch strife WALTEK15 on pic WALTEKB1 tics 0 +switch strife WALTEK09 on sound world/glassbreak pic WALTEKB1 tics 0 +switch strife WALTEK10 on sound world/glassbreak pic WALTEKB1 tics 0 +switch strife WALTEK15 on sound world/glassbreak pic WALTEKB1 tics 0 switch strife SWFORC01 on pic SWFORC02 tics 0 switch strife SWEXIT01 on pic SWEXIT02 tics 0 switch strife DORSBK01 on sound switches/stone pic DORSBK02 tics 0 @@ -169,7 +169,7 @@ switch strife SWTRMG01 on pic SWTRMG04 tics 0 switch strife SWMETL01 on pic SWMETL02 tics 0 switch strife SWWOOD01 on pic SWWOOD02 tics 0 switch strife SWTKBL01 on pic SWTKBL02 tics 0 -switch strife AZWAL21 on pic AZWAL22 tics 0 +switch strife AZWAL21 on sound world/glassbreak pic AZWAL22 tics 0 switch strife SWINDT01 on pic SWINDT02 tics 0 switch strife SWRUST01 on pic SWRUST02 tics 0 switch strife SWCHAP01 on pic SWCHAP02 tics 0 From 99880d392ea3e65238efaab06c203faee03d5e16 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 04:01:30 +0000 Subject: [PATCH 200/241] - Fixed copy-paste fail for DoorCloseSmallWood. SVN r2110 (trunk) --- wadsrc/static/sndseq.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/sndseq.txt b/wadsrc/static/sndseq.txt index 38c0dcc55..cdf760944 100644 --- a/wadsrc/static/sndseq.txt +++ b/wadsrc/static/sndseq.txt @@ -94,7 +94,7 @@ end end :DoorCloseSmallWood - play doors/large_wood_open + play doors/small_wood_close nostopcutoff end From f9937f973c0316dddd52c7717e033ac0534feb15 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 8 Jan 2010 04:14:35 +0000 Subject: [PATCH 201/241] - Fixed: DORWS04 should not make a sound when it switches off. SVN r2111 (trunk) --- wadsrc/static/animdefs.txt | 2 +- wadsrc/static/sndinfo.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/animdefs.txt b/wadsrc/static/animdefs.txt index 79ed3a3e5..388a4f360 100644 --- a/wadsrc/static/animdefs.txt +++ b/wadsrc/static/animdefs.txt @@ -157,7 +157,7 @@ switch strife SWFORC01 on pic SWFORC02 tics 0 switch strife SWEXIT01 on pic SWEXIT02 tics 0 switch strife DORSBK01 on sound switches/stone pic DORSBK02 tics 0 switch strife SWSLD01 on pic SWSLD02 tics 0 -switch strife DORWS04 on sound switches/bolt pic DORWS05 tics 0 +switch strife DORWS04 on sound switches/bolt pic DORWS05 tics 0 off sound switches/boltback pic DORWS04 tics 0 switch strife SWIRON01 on pic SWIRON02 tics 0 switch strife GLASS09 on sound world/glassbreak pic GLASS10 tics 0 switch strife GLASS11 on sound world/glassbreak pic GLASS12 tics 0 diff --git a/wadsrc/static/sndinfo.txt b/wadsrc/static/sndinfo.txt index c69ef903e..c534808bb 100644 --- a/wadsrc/static/sndinfo.txt +++ b/wadsrc/static/sndinfo.txt @@ -1086,6 +1086,7 @@ switches/knob dsswknob switches/keycard dskeycrd switches/stone dsswston switches/bolt dsswbolt +switches/boltback dsempty switches/scanner dsswscan switches/fool dsdifool switches/valve dsvalve From 25c8d42821816d45f07af1fc34c31a62260f1294 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 9 Jan 2010 04:26:56 +0000 Subject: [PATCH 202/241] - Change StrifePlayer's RunHealth to 15. SVN r2112 (trunk) --- wadsrc/static/actors/strife/strifeplayer.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/actors/strife/strifeplayer.txt b/wadsrc/static/actors/strife/strifeplayer.txt index 83d8110dd..d42dc1ba4 100644 --- a/wadsrc/static/actors/strife/strifeplayer.txt +++ b/wadsrc/static/actors/strife/strifeplayer.txt @@ -12,7 +12,7 @@ ACTOR StrifePlayer : PlayerPawn Player.ColorRange 128, 143 Player.DisplayName "Rebel" Player.StartItem "PunchDagger" - Player.RunHealth 16 + Player.RunHealth 15 Player.WeaponSlot 1, PunchDagger Player.WeaponSlot 2, StrifeCrossbow2, StrifeCrossbow Player.WeaponSlot 3, AssaultGun From 5ce77dfbb81e71e317724504e5860cb968fa69f2 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 9 Jan 2010 04:28:49 +0000 Subject: [PATCH 203/241] - Added full stops to more Strife messages. SVN r2113 (trunk) --- wadsrc/static/language.enu | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 16ae72997..4cb444d0f 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1086,7 +1086,7 @@ TXT_LEATHERARMOR = "You picked up the Leather Armor."; TXT_MEDPATCH = "You picked up the Med patch."; TXT_MEDICALKIT = "You picked up the Medical kit."; TXT_SURGERYKIT = "You picked up the Surgery Kit."; -TXT_STRIFEMAP = "You picked up the map"; +TXT_STRIFEMAP = "You picked up the map."; TXT_BELDINSRING = "You picked up the ring."; TXT_OFFERINGCHALICE = "You picked up the Offering Chalice."; TXT_EAR = "You picked up the ear."; @@ -1108,12 +1108,12 @@ TXT_SCANNER = "You picked up the scanner."; TXT_NEEDMAP = "The scanner won't work without a map!\n"; TXT_PRISONPASS = "You picked up the Prison pass."; -TXT_STRIFECROSSBOW = "You picked up the crossbow"; -TXT_ASSAULTGUN = "You picked up the assault gun"; -TXT_MMLAUNCHER = "You picked up the mini missile launcher"; -TXT_FLAMER = "You picked up the flame thrower"; -TXT_MAULER = "You picked up the mauler"; -TXT_GLAUNCHER = "You picked up the Grenade launcher"; +TXT_STRIFECROSSBOW = "You picked up the crossbow."; +TXT_ASSAULTGUN = "You picked up the assault gun."; +TXT_MMLAUNCHER = "You picked up the mini missile launcher."; +TXT_FLAMER = "You picked up the flame thrower."; +TXT_MAULER = "You picked up the mauler."; +TXT_GLAUNCHER = "You picked up the Grenade launcher."; TXT_SIGIL = "You picked up the SIGIL."; @@ -1156,7 +1156,7 @@ TXT_ENERGYPOD = "You picked up the energy pod."; TXT_ENERGYPACK = "You picked up the energy pack."; TXT_POISONBOLTS = "You picked up the poison bolts."; TXT_ELECTRICBOLTS = "You picked up the electric bolts."; -TXT_AMMOSATCHEL = "You picked up the ammo satchel"; +TXT_AMMOSATCHEL = "You picked up the ammo satchel."; // Random dialogs From 6c9748b603a0d9581e3c0efae787aa3ae98ce09c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 16 Jan 2010 07:51:50 +0000 Subject: [PATCH 204/241] - ported a few cleanup changes from Gez's recent GZDoom patch. - fixed: The sound channel structure should not store the sound table's entries' addresses which are stored in a TArray by pointer. In case the array gets reallocated very bad things can happen. This caused some bad crashes when GZDoom's FraggleScript implementation created new sound entries. SVN r2114 (trunk) --- src/actionspecials.h | 8 - src/gameconfigfile.cpp | 2 + src/p_lnspec.cpp | 512 ++++++++++++++++++++--------------------- src/s_sound.cpp | 18 +- src/s_sound.h | 1 - 5 files changed, 265 insertions(+), 276 deletions(-) diff --git a/src/actionspecials.h b/src/actionspecials.h index 552b65e49..e1df60c16 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -110,15 +110,7 @@ DEFINE_SPECIAL(Light_Stop, 117, 1, 1, 1) DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3) DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5) -#if 0 // Skull Tag specials that might be added later -Thing_SetGravity, 122, -1, -1) -Thing_ReverseGravity, 123, -1, -1) -Thing_RevertGravity, 124, -1, -1) -#endif DEFINE_SPECIAL(Thing_Move, 125, 2, 3, 3) -#if 0 // Skull Tag special I doubt I will add -Thing_SetSprite, 126, -1, -1) -#endif DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5) DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4) DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5) diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 09faee2c0..97bdfece9 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -161,6 +161,8 @@ FGameConfigFile::FGameConfigFile () // Create auto-load sections, so users know what's available. // Note that this totem pole is the reverse of the order that // they will appear in the file. + CreateSectionAtStart("Harmony.Autoload"); + CreateSectionAtStart("UrbanBrawl.Autoload"); CreateSectionAtStart("Chex3.Autoload"); CreateSectionAtStart("Chex.Autoload"); CreateSectionAtStart("Strife.Autoload"); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 7a51075b4..5792a8a23 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2966,262 +2966,262 @@ FUNC(LS_StartConversation) lnSpecFunc LineSpecials[256] = { - LS_NOP, - LS_NOP, // Polyobj_StartLine, - LS_Polyobj_RotateLeft, - LS_Polyobj_RotateRight, - LS_Polyobj_Move, - LS_NOP, // Polyobj_ExplicitLine - LS_Polyobj_MoveTimes8, - LS_Polyobj_DoorSwing, - LS_Polyobj_DoorSlide, - LS_NOP, // Line_Horizon - LS_Door_Close, - LS_Door_Open, - LS_Door_Raise, - LS_Door_LockedRaise, - LS_Door_Animated, - LS_Autosave, - LS_NOP, // Transfer_WallLight - LS_Thing_Raise, - LS_StartConversation, - LS_Thing_Stop, - LS_Floor_LowerByValue, - LS_Floor_LowerToLowest, - LS_Floor_LowerToNearest, - LS_Floor_RaiseByValue, - LS_Floor_RaiseToHighest, - LS_Floor_RaiseToNearest, - LS_Stairs_BuildDown, - LS_Stairs_BuildUp, - LS_Floor_RaiseAndCrush, - LS_Pillar_Build, - LS_Pillar_Open, - LS_Stairs_BuildDownSync, - LS_Stairs_BuildUpSync, - LS_ForceField, - LS_ClearForceField, - LS_Floor_RaiseByValueTimes8, - LS_Floor_LowerByValueTimes8, - LS_Floor_MoveToValue, - LS_Ceiling_Waggle, - LS_Teleport_ZombieChanger, - LS_Ceiling_LowerByValue, - LS_Ceiling_RaiseByValue, - LS_Ceiling_CrushAndRaise, - LS_Ceiling_LowerAndCrush, - LS_Ceiling_CrushStop, - LS_Ceiling_CrushRaiseAndStay, - LS_Floor_CrushStop, - LS_Ceiling_MoveToValue, - LS_NOP, // Sector_Attach3dMidtex - LS_GlassBreak, - LS_NOP, // 50: ExtraFloor_LightOnly - LS_Sector_SetLink, - LS_Scroll_Wall, - LS_Line_SetTextureOffset, - LS_Sector_ChangeFlags, - LS_Line_SetBlocking, - LS_Line_SetTextureScale, - LS_NOP, // 57 - LS_NOP, // 58 - LS_NOP, // 59 - LS_Plat_PerpetualRaise, - LS_Plat_Stop, - LS_Plat_DownWaitUpStay, - LS_Plat_DownByValue, - LS_Plat_UpWaitDownStay, - LS_Plat_UpByValue, - LS_Floor_LowerInstant, - LS_Floor_RaiseInstant, - LS_Floor_MoveToValueTimes8, - LS_Ceiling_MoveToValueTimes8, - LS_Teleport, - LS_Teleport_NoFog, - LS_ThrustThing, - LS_DamageThing, - LS_Teleport_NewMap, - LS_Teleport_EndGame, - LS_TeleportOther, - LS_TeleportGroup, - LS_TeleportInSector, - LS_NOP, // 79 - LS_ACS_Execute, - LS_ACS_Suspend, - LS_ACS_Terminate, - LS_ACS_LockedExecute, - LS_ACS_ExecuteWithResult, - LS_ACS_LockedExecuteDoor, - LS_NOP, // 86 - LS_NOP, // 87 - LS_NOP, // 88 - LS_NOP, // 89 - LS_Polyobj_OR_RotateLeft, - LS_Polyobj_OR_RotateRight, - LS_Polyobj_OR_Move, - LS_Polyobj_OR_MoveTimes8, - LS_Pillar_BuildAndCrush, - LS_FloorAndCeiling_LowerByValue, - LS_FloorAndCeiling_RaiseByValue, - LS_NOP, // 97 - LS_NOP, // 98 - LS_NOP, // 99 - LS_NOP, // Scroll_Texture_Left - LS_NOP, // Scroll_Texture_Right - LS_NOP, // Scroll_Texture_Up - LS_NOP, // Scroll_Texture_Down - LS_NOP, // 104 - LS_NOP, // 105 - LS_NOP, // 106 - LS_NOP, // 107 - LS_NOP, // 108 - LS_Light_ForceLightning, - LS_Light_RaiseByValue, - LS_Light_LowerByValue, - LS_Light_ChangeToValue, - LS_Light_Fade, - LS_Light_Glow, - LS_Light_Flicker, - LS_Light_Strobe, - LS_Light_Stop, - LS_NOP, // 118 - LS_Thing_Damage, - LS_Radius_Quake, - LS_NOP, // Line_SetIdentification - LS_NOP, // Thing_SetGravity // [BC] Start - LS_NOP, // Thing_ReverseGravity - LS_NOP, // Thing_RevertGravity - LS_Thing_Move, - LS_NOP, // Thing_SetSprite - LS_Thing_SetSpecial, - LS_ThrustThingZ, // [BC] End - LS_UsePuzzleItem, - LS_Thing_Activate, - LS_Thing_Deactivate, - LS_Thing_Remove, - LS_Thing_Destroy, - LS_Thing_Projectile, - LS_Thing_Spawn, - LS_Thing_ProjectileGravity, - LS_Thing_SpawnNoFog, - LS_Floor_Waggle, - LS_Thing_SpawnFacing, - LS_Sector_ChangeSound, - LS_NOP, // 141 Music_Pause // [BC] Start - LS_NOP, // 142 Music_Change - LS_NOP, // 143 Player_RemoveItem - LS_NOP, // 144 Player_GiveItem - LS_NOP, // 145 Player_SetTeam - LS_NOP, // 146 Player_SetLeader - LS_NOP, // 147 Team_InitFP - LS_NOP, // 148 TeleportAll - LS_NOP, // 149 TeleportAll_NoFog - LS_NOP, // 150 Team_GiveFP - LS_NOP, // 151 Team_UseFP - LS_NOP, // 152 Team_Score - LS_NOP, // 153 Team_Init - LS_Teleport_NoStop, - LS_NOP, // 155 Team_RemoveItem - LS_NOP, // 156 Team_GiveItem // [BC] End - LS_NOP, // 157 - LS_NOP, // 158 (FS_Execute in GZDoom) - LS_NOP, // 159 (Sector_SetPlaneReflection in GZDoom) - LS_NOP, // 160 (Sector_Set3DFloor in GZDoom and Vavoom) - LS_NOP, // 161 (Sector_SetContents in GZDoom and Vavoom) - LS_NOP, // 162 - LS_NOP, // 163 - LS_NOP, // 164 - LS_NOP, // 165 - LS_NOP, // 166 - LS_NOP, // 167 - LS_NOP, // 168 - LS_Generic_Crusher2, - LS_Sector_SetCeilingScale2, - LS_Sector_SetFloorScale2, - LS_Plat_UpNearestWaitDownStay, - LS_NoiseAlert, - LS_SendToCommunicator, - LS_Thing_ProjectileIntercept, - LS_Thing_ChangeTID, - LS_Thing_Hate, - LS_Thing_ProjectileAimed, - LS_ChangeSkill, - LS_Thing_SetTranslation, - LS_NOP, // Plane_Align - LS_NOP, // Line_Mirror - LS_Line_AlignCeiling, - LS_Line_AlignFloor, - LS_Sector_SetRotation, - LS_Sector_SetCeilingPanning, - LS_Sector_SetFloorPanning, - LS_Sector_SetCeilingScale, - LS_Sector_SetFloorScale, - LS_NOP, // Static_Init - LS_SetPlayerProperty, - LS_Ceiling_LowerToHighestFloor, - LS_Ceiling_LowerInstant, - LS_Ceiling_RaiseInstant, - LS_Ceiling_CrushRaiseAndStayA, - LS_Ceiling_CrushAndRaiseA, - LS_Ceiling_CrushAndRaiseSilentA, - LS_Ceiling_RaiseByValueTimes8, - LS_Ceiling_LowerByValueTimes8, - LS_Generic_Floor, - LS_Generic_Ceiling, - LS_Generic_Door, - LS_Generic_Lift, - LS_Generic_Stairs, - LS_Generic_Crusher, - LS_Plat_DownWaitUpStayLip, - LS_Plat_PerpetualRaiseLip, - LS_TranslucentLine, - LS_NOP, // Transfer_Heights - LS_NOP, // Transfer_FloorLight - LS_NOP, // Transfer_CeilingLight - LS_Sector_SetColor, - LS_Sector_SetFade, - LS_Sector_SetDamage, - LS_Teleport_Line, - LS_Sector_SetGravity, - LS_Stairs_BuildUpDoom, - LS_Sector_SetWind, - LS_Sector_SetFriction, - LS_Sector_SetCurrent, - LS_Scroll_Texture_Both, - LS_NOP, // Scroll_Texture_Model - LS_Scroll_Floor, - LS_Scroll_Ceiling, - LS_NOP, // Scroll_Texture_Offsets - LS_ACS_ExecuteAlways, - LS_PointPush_SetForce, - LS_Plat_RaiseAndStayTx0, - LS_Thing_SetGoal, - LS_Plat_UpByValueStayTx, - LS_Plat_ToggleCeiling, - LS_Light_StrobeDoom, - LS_Light_MinNeighbor, - LS_Light_MaxNeighbor, - LS_Floor_TransferTrigger, - LS_Floor_TransferNumeric, - LS_ChangeCamera, - LS_Floor_RaiseToLowestCeiling, - LS_Floor_RaiseByValueTxTy, - LS_Floor_RaiseByTexture, - LS_Floor_LowerToLowestTxTy, - LS_Floor_LowerToHighest, - LS_Exit_Normal, - LS_Exit_Secret, - LS_Elevator_RaiseToNearest, - LS_Elevator_MoveToFloor, - LS_Elevator_LowerToNearest, - LS_HealThing, - LS_Door_CloseWaitOpen, - LS_Floor_Donut, - LS_FloorAndCeiling_LowerRaise, - LS_Ceiling_RaiseToNearest, - LS_Ceiling_LowerToLowest, - LS_Ceiling_LowerToFloor, - LS_Ceiling_CrushRaiseAndStaySilA + /* 0 */ LS_NOP, + /* 1 */ LS_NOP, // Polyobj_StartLine, + /* 2 */ LS_Polyobj_RotateLeft, + /* 3 */ LS_Polyobj_RotateRight, + /* 4 */ LS_Polyobj_Move, + /* 5 */ LS_NOP, // Polyobj_ExplicitLine + /* 6 */ LS_Polyobj_MoveTimes8, + /* 7 */ LS_Polyobj_DoorSwing, + /* 8 */ LS_Polyobj_DoorSlide, + /* 9 */ LS_NOP, // Line_Horizon + /* 10 */ LS_Door_Close, + /* 11 */ LS_Door_Open, + /* 12 */ LS_Door_Raise, + /* 13 */ LS_Door_LockedRaise, + /* 14 */ LS_Door_Animated, + /* 15 */ LS_Autosave, + /* 16 */ LS_NOP, // Transfer_WallLight + /* 17 */ LS_Thing_Raise, + /* 18 */ LS_StartConversation, + /* 19 */ LS_Thing_Stop, + /* 20 */ LS_Floor_LowerByValue, + /* 21 */ LS_Floor_LowerToLowest, + /* 22 */ LS_Floor_LowerToNearest, + /* 23 */ LS_Floor_RaiseByValue, + /* 24 */ LS_Floor_RaiseToHighest, + /* 25 */ LS_Floor_RaiseToNearest, + /* 26 */ LS_Stairs_BuildDown, + /* 27 */ LS_Stairs_BuildUp, + /* 28 */ LS_Floor_RaiseAndCrush, + /* 29 */ LS_Pillar_Build, + /* 30 */ LS_Pillar_Open, + /* 31 */ LS_Stairs_BuildDownSync, + /* 32 */ LS_Stairs_BuildUpSync, + /* 33 */ LS_ForceField, + /* 34 */ LS_ClearForceField, + /* 35 */ LS_Floor_RaiseByValueTimes8, + /* 36 */ LS_Floor_LowerByValueTimes8, + /* 37 */ LS_Floor_MoveToValue, + /* 38 */ LS_Ceiling_Waggle, + /* 39 */ LS_Teleport_ZombieChanger, + /* 40 */ LS_Ceiling_LowerByValue, + /* 41 */ LS_Ceiling_RaiseByValue, + /* 42 */ LS_Ceiling_CrushAndRaise, + /* 43 */ LS_Ceiling_LowerAndCrush, + /* 44 */ LS_Ceiling_CrushStop, + /* 45 */ LS_Ceiling_CrushRaiseAndStay, + /* 46 */ LS_Floor_CrushStop, + /* 47 */ LS_Ceiling_MoveToValue, + /* 48 */ LS_NOP, // Sector_Attach3dMidtex + /* 49 */ LS_GlassBreak, + /* 50 */ LS_NOP, // ExtraFloor_LightOnly + /* 51 */ LS_Sector_SetLink, + /* 52 */ LS_Scroll_Wall, + /* 53 */ LS_Line_SetTextureOffset, + /* 54 */ LS_Sector_ChangeFlags, + /* 55 */ LS_Line_SetBlocking, + /* 56 */ LS_Line_SetTextureScale, + /* 57 */ LS_NOP, // Sector_SetPortal + /* 58 */ LS_NOP, + /* 59 */ LS_NOP, + /* 60 */ LS_Plat_PerpetualRaise, + /* 61 */ LS_Plat_Stop, + /* 62 */ LS_Plat_DownWaitUpStay, + /* 63 */ LS_Plat_DownByValue, + /* 64 */ LS_Plat_UpWaitDownStay, + /* 65 */ LS_Plat_UpByValue, + /* 66 */ LS_Floor_LowerInstant, + /* 67 */ LS_Floor_RaiseInstant, + /* 68 */ LS_Floor_MoveToValueTimes8, + /* 69 */ LS_Ceiling_MoveToValueTimes8, + /* 70 */ LS_Teleport, + /* 71 */ LS_Teleport_NoFog, + /* 72 */ LS_ThrustThing, + /* 73 */ LS_DamageThing, + /* 74 */ LS_Teleport_NewMap, + /* 75 */ LS_Teleport_EndGame, + /* 76 */ LS_TeleportOther, + /* 77 */ LS_TeleportGroup, + /* 78 */ LS_TeleportInSector, + /* 79 */ LS_NOP, + /* 80 */ LS_ACS_Execute, + /* 81 */ LS_ACS_Suspend, + /* 82 */ LS_ACS_Terminate, + /* 83 */ LS_ACS_LockedExecute, + /* 84 */ LS_ACS_ExecuteWithResult, + /* 85 */ LS_ACS_LockedExecuteDoor, + /* 86 */ LS_NOP, + /* 87 */ LS_NOP, + /* 88 */ LS_NOP, + /* 89 */ LS_NOP, + /* 90 */ LS_Polyobj_OR_RotateLeft, + /* 91 */ LS_Polyobj_OR_RotateRight, + /* 92 */ LS_Polyobj_OR_Move, + /* 93 */ LS_Polyobj_OR_MoveTimes8, + /* 94 */ LS_Pillar_BuildAndCrush, + /* 95 */ LS_FloorAndCeiling_LowerByValue, + /* 96 */ LS_FloorAndCeiling_RaiseByValue, + /* 97 */ LS_NOP, + /* 98 */ LS_NOP, + /* 99 */ LS_NOP, + /* 100 */ LS_NOP, // Scroll_Texture_Left + /* 101 */ LS_NOP, // Scroll_Texture_Right + /* 102 */ LS_NOP, // Scroll_Texture_Up + /* 103 */ LS_NOP, // Scroll_Texture_Down + /* 104 */ LS_NOP, + /* 105 */ LS_NOP, + /* 106 */ LS_NOP, + /* 107 */ LS_NOP, + /* 108 */ LS_NOP, + /* 109 */ LS_Light_ForceLightning, + /* 110 */ LS_Light_RaiseByValue, + /* 111 */ LS_Light_LowerByValue, + /* 112 */ LS_Light_ChangeToValue, + /* 113 */ LS_Light_Fade, + /* 114 */ LS_Light_Glow, + /* 115 */ LS_Light_Flicker, + /* 116 */ LS_Light_Strobe, + /* 117 */ LS_Light_Stop, + /* 118 */ LS_NOP, + /* 119 */ LS_Thing_Damage, + /* 120 */ LS_Radius_Quake, + /* 121 */ LS_NOP, // Line_SetIdentification + /* 122 */ LS_NOP, + /* 123 */ LS_NOP, + /* 124 */ LS_NOP, + /* 125 */ LS_Thing_Move, + /* 126 */ LS_NOP, + /* 127 */ LS_Thing_SetSpecial, + /* 128 */ LS_ThrustThingZ, + /* 129 */ LS_UsePuzzleItem, + /* 130 */ LS_Thing_Activate, + /* 131 */ LS_Thing_Deactivate, + /* 132 */ LS_Thing_Remove, + /* 133 */ LS_Thing_Destroy, + /* 134 */ LS_Thing_Projectile, + /* 135 */ LS_Thing_Spawn, + /* 136 */ LS_Thing_ProjectileGravity, + /* 137 */ LS_Thing_SpawnNoFog, + /* 138 */ LS_Floor_Waggle, + /* 139 */ LS_Thing_SpawnFacing, + /* 140 */ LS_Sector_ChangeSound, + /* 141 */ LS_NOP, // 141 Music_Pause // [BC] Start + /* 142 */ LS_NOP, // 142 Music_Change + /* 143 */ LS_NOP, // 143 Player_RemoveItem + /* 144 */ LS_NOP, // 144 Player_GiveItem + /* 145 */ LS_NOP, // 145 Player_SetTeam + /* 146 */ LS_NOP, // 146 Player_SetLeader + /* 147 */ LS_NOP, // 147 Team_InitFP + /* 148 */ LS_NOP, // 148 TeleportAll + /* 149 */ LS_NOP, // 149 TeleportAll_NoFog + /* 150 */ LS_NOP, // 150 Team_GiveFP + /* 151 */ LS_NOP, // 151 Team_UseFP + /* 152 */ LS_NOP, // 152 Team_Score + /* 153 */ LS_NOP, // 153 Team_Init + /* 154 */ LS_Teleport_NoStop, + /* 155 */ LS_NOP, // 155 Team_RemoveItem + /* 156 */ LS_NOP, // 156 Team_GiveItem // [BC] End + /* 157 */ LS_NOP, // SetGlobalFogParameter // in GZDoom + /* 158 */ LS_NOP, // FS_Execute in GZDoom + /* 159 */ LS_NOP, // Sector_SetPlaneReflection in GZDoom + /* 160 */ LS_NOP, // Sector_Set3DFloor in GZDoom and Vavoom + /* 161 */ LS_NOP, // Sector_SetContents in GZDoom and Vavoom + /* 162 */ LS_NOP, + /* 163 */ LS_NOP, + /* 164 */ LS_NOP, + /* 165 */ LS_NOP, + /* 166 */ LS_NOP, + /* 167 */ LS_NOP, + /* 168 */ LS_NOP, + /* 169 */ LS_Generic_Crusher2, + /* 170 */ LS_Sector_SetCeilingScale2, + /* 171 */ LS_Sector_SetFloorScale2, + /* 172 */ LS_Plat_UpNearestWaitDownStay, + /* 173 */ LS_NoiseAlert, + /* 174 */ LS_SendToCommunicator, + /* 175 */ LS_Thing_ProjectileIntercept, + /* 176 */ LS_Thing_ChangeTID, + /* 177 */ LS_Thing_Hate, + /* 178 */ LS_Thing_ProjectileAimed, + /* 179 */ LS_ChangeSkill, + /* 180 */ LS_Thing_SetTranslation, + /* 181 */ LS_NOP, // Plane_Align + /* 182 */ LS_NOP, // Line_Mirror + /* 183 */ LS_Line_AlignCeiling, + /* 184 */ LS_Line_AlignFloor, + /* 185 */ LS_Sector_SetRotation, + /* 186 */ LS_Sector_SetCeilingPanning, + /* 187 */ LS_Sector_SetFloorPanning, + /* 188 */ LS_Sector_SetCeilingScale, + /* 189 */ LS_Sector_SetFloorScale, + /* 190 */ LS_NOP, // Static_Init + /* 191 */ LS_SetPlayerProperty, + /* 192 */ LS_Ceiling_LowerToHighestFloor, + /* 193 */ LS_Ceiling_LowerInstant, + /* 194 */ LS_Ceiling_RaiseInstant, + /* 195 */ LS_Ceiling_CrushRaiseAndStayA, + /* 196 */ LS_Ceiling_CrushAndRaiseA, + /* 197 */ LS_Ceiling_CrushAndRaiseSilentA, + /* 198 */ LS_Ceiling_RaiseByValueTimes8, + /* 199 */ LS_Ceiling_LowerByValueTimes8, + /* 200 */ LS_Generic_Floor, + /* 201 */ LS_Generic_Ceiling, + /* 202 */ LS_Generic_Door, + /* 203 */ LS_Generic_Lift, + /* 204 */ LS_Generic_Stairs, + /* 205 */ LS_Generic_Crusher, + /* 206 */ LS_Plat_DownWaitUpStayLip, + /* 207 */ LS_Plat_PerpetualRaiseLip, + /* 208 */ LS_TranslucentLine, + /* 209 */ LS_NOP, // Transfer_Heights + /* 210 */ LS_NOP, // Transfer_FloorLight + /* 211 */ LS_NOP, // Transfer_CeilingLight + /* 212 */ LS_Sector_SetColor, + /* 213 */ LS_Sector_SetFade, + /* 214 */ LS_Sector_SetDamage, + /* 215 */ LS_Teleport_Line, + /* 216 */ LS_Sector_SetGravity, + /* 217 */ LS_Stairs_BuildUpDoom, + /* 218 */ LS_Sector_SetWind, + /* 219 */ LS_Sector_SetFriction, + /* 220 */ LS_Sector_SetCurrent, + /* 221 */ LS_Scroll_Texture_Both, + /* 222 */ LS_NOP, // Scroll_Texture_Model + /* 223 */ LS_Scroll_Floor, + /* 224 */ LS_Scroll_Ceiling, + /* 225 */ LS_NOP, // Scroll_Texture_Offsets + /* 226 */ LS_ACS_ExecuteAlways, + /* 227 */ LS_PointPush_SetForce, + /* 228 */ LS_Plat_RaiseAndStayTx0, + /* 229 */ LS_Thing_SetGoal, + /* 230 */ LS_Plat_UpByValueStayTx, + /* 231 */ LS_Plat_ToggleCeiling, + /* 232 */ LS_Light_StrobeDoom, + /* 233 */ LS_Light_MinNeighbor, + /* 234 */ LS_Light_MaxNeighbor, + /* 235 */ LS_Floor_TransferTrigger, + /* 236 */ LS_Floor_TransferNumeric, + /* 237 */ LS_ChangeCamera, + /* 238 */ LS_Floor_RaiseToLowestCeiling, + /* 239 */ LS_Floor_RaiseByValueTxTy, + /* 240 */ LS_Floor_RaiseByTexture, + /* 241 */ LS_Floor_LowerToLowestTxTy, + /* 242 */ LS_Floor_LowerToHighest, + /* 243 */ LS_Exit_Normal, + /* 244 */ LS_Exit_Secret, + /* 245 */ LS_Elevator_RaiseToNearest, + /* 246 */ LS_Elevator_MoveToFloor, + /* 247 */ LS_Elevator_LowerToNearest, + /* 248 */ LS_HealThing, + /* 249 */ LS_Door_CloseWaitOpen, + /* 250 */ LS_Floor_Donut, + /* 251 */ LS_FloorAndCeiling_LowerRaise, + /* 252 */ LS_Ceiling_RaiseToNearest, + /* 253 */ LS_Ceiling_LowerToLowest, + /* 254 */ LS_Ceiling_LowerToFloor, + /* 255 */ LS_Ceiling_CrushRaiseAndStaySilA }; #define DEFINE_SPECIAL(name, num, min, max, mmax) {#name, num, min, max, mmax}, diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 8e5284f46..48f5e9e9d 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -187,7 +187,7 @@ void S_NoiseDebug (void) color = (chan->ChanFlags & CHAN_LOOP) ? CR_BROWN : CR_GREY; // Name - Wads.GetLumpName (temp, chan->SfxInfo->lumpnum); + Wads.GetLumpName (temp, S_sfx[chan->SoundID].lumpnum); temp[8] = 0; screen->DrawText (SmallFont, color, 0, y, temp, TAG_DONE); @@ -1068,7 +1068,6 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO { chan->SoundID = sound_id; chan->OrgID = FSoundID(org_id); - chan->SfxInfo = sfx; chan->EntChannel = channel; chan->Volume = volume; chan->ChanFlags |= chanflags; @@ -1101,10 +1100,9 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO void S_RestartSound(FSoundChan *chan) { assert(chan->ChanFlags & CHAN_EVICTED); - assert(chan->SfxInfo != NULL); FSoundChan *ochan; - sfxinfo_t *sfx = chan->SfxInfo; + sfxinfo_t *sfx = &S_sfx[chan->SoundID]; // If this is a singular sound, don't play it if it's already playing. if (sfx->bSingular && S_CheckSingular(chan->SoundID)) @@ -1352,7 +1350,7 @@ bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, floa for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan) { - if (!(chan->ChanFlags & CHAN_EVICTED) && chan->SfxInfo == sfx) + if (!(chan->ChanFlags & CHAN_EVICTED) && &S_sfx[chan->SoundID] == sfx) { FVector3 chanorigin; @@ -1982,10 +1980,10 @@ void S_ChannelEnded(FISoundChannel *ichan) { evicted = true; } - else if (schan->SfxInfo != NULL) + else { unsigned int pos = GSnd->GetPosition(schan); - unsigned int len = GSnd->GetSampleLength(schan->SfxInfo->data); + unsigned int len = GSnd->GetSampleLength(S_sfx[schan->SoundID].data); if (pos == 0) { evicted = !!(schan->ChanFlags & CHAN_JUSTSTARTED); @@ -1995,10 +1993,12 @@ void S_ChannelEnded(FISoundChannel *ichan) evicted = (pos < len); } } + /* else { evicted = false; } + */ if (!evicted) { S_ReturnChannel(schan); @@ -2114,10 +2114,6 @@ static FArchive &operator<<(FArchive &arc, FSoundChan &chan) << chan.Rolloff.MaxDistance << chan.LimitRange; - if (arc.IsLoading()) - { - chan.SfxInfo = &S_sfx[chan.SoundID]; - } return arc; } diff --git a/src/s_sound.h b/src/s_sound.h index 638baf5e5..4dbf52aac 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -169,7 +169,6 @@ struct FSoundChan : public FISoundChannel { FSoundChan *NextChan; // Next channel in this list. FSoundChan **PrevChan; // Previous channel in this list. - sfxinfo_t *SfxInfo; // Sound information. FSoundID SoundID; // Sound ID of playing sound. FSoundID OrgID; // Sound ID of sound used to start this channel. float Volume; From a3ac7ee081af8935254bfe83a47575c71b7878ef Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 18 Jan 2010 05:07:10 +0000 Subject: [PATCH 205/241] - Fixed: Attempt to free a non-heap object in zipdir. SVN r2115 (trunk) --- tools/zipdir/zipdir.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/zipdir/zipdir.c b/tools/zipdir/zipdir.c index 0daf927f9..01a997958 100644 --- a/tools/zipdir/zipdir.c +++ b/tools/zipdir/zipdir.c @@ -1027,9 +1027,13 @@ int append_to_zip(FILE *zip_file, file_sorted_t *filep, FILE *ozip, BYTE *odir) } fprintf(stderr, "Unable to write %s to zip\n", file->path); free(readbuf); - if (compbuf != NULL) + if (compbuf[0] != NULL) { - free(compbuf); + free(compbuf[0]); + } + if (compbuf[1] != NULL) + { + free(compbuf[1]); } return 1; } From 7183a2f7515b55fc10b53acf4036cf6d7cd7ee29 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 18 Jan 2010 19:38:36 +0000 Subject: [PATCH 206/241] - Fixed: DrawSelectedInventory set the wrong variable and thus always used CR_GOLD as its translation. - Fixed: Draw(Switchable)Image didn't handle the alpha value properly. SVN r2116 (trunk) --- src/g_shared/sbarinfo_commands.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index df6bd1b4a..063f9ac3a 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -55,7 +55,12 @@ class CommandDrawImage : public SBarInfoCommand if(texture == NULL) return; - statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), alpha, block->FullScreenOffsets(), + // We must calculate this per frame in order to prevent glitches with cl_capfps true. + fixed_t frameAlpha = block->Alpha(); + if(alpha != FRACUNIT) + frameAlpha = fixed_t(((double) block->Alpha() / (double) FRACUNIT) * ((double) alpha / (double) OPAQUE) * FRACUNIT); + + statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), frameAlpha, block->FullScreenOffsets(), translatable, false, offset); } void Parse(FScanner &sc, bool fullScreenOffsets) @@ -132,7 +137,7 @@ class CommandDrawImage : public SBarInfoCommand void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { texture = NULL; - alpha = block->Alpha(); + alpha = FRACUNIT; if(type == PLAYERICON) texture = TexMan[statusBar->CPlayer->mo->ScoreIcon]; else if(type == AMMO1) @@ -474,6 +479,10 @@ class CommandDrawSwitchableImage : public CommandDrawImage if(drawAlt != 0) //draw 'off' image { texture = statusBar->Images[conditionalImage[drawAlt-1]]; + + // Since we're not going to call our parent's tick() method, + // be sure to set the alpha value properly. + alpha = FRACUNIT; return; } CommandDrawImage::Tick(block, statusBar, hudChanged); @@ -1061,13 +1070,13 @@ class CommandDrawSelectedInventory : public SBarInfoCommandFlowControl, private CommandDrawImage::GetCoordinates(sc, fullScreenOffsets, imgx, imgy); startX = imgx + 30; y = imgy + 24; - translation = CR_GOLD; + normalTranslation = CR_GOLD; if(sc.CheckToken(',')) //more font information { CommandDrawNumber::GetCoordinates(sc, fullScreenOffsets, startX, y); if(sc.CheckToken(',')) { - translation = CommandDrawNumber::GetTranslation(sc); + normalTranslation = CommandDrawNumber::GetTranslation(sc); if(sc.CheckToken(',')) { sc.MustGetToken(TK_IntConst); From 16c638a598af98b41e6c377fe6953e2eae7880fb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 18 Jan 2010 20:15:04 +0000 Subject: [PATCH 207/241] - Fixed: SetMarineSprite tried to access the first owned state of the actor's class - but the weapon carrying marines own no states. SVN r2117 (trunk) --- src/g_doom/a_scriptedmarine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index 701a0930f..150b7eb79 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -104,7 +104,7 @@ void AScriptedMarine::Tick () Super::Tick (); // Override the standard sprite, if desired - if (SpriteOverride != 0 && sprite == GetClass()->ActorInfo->OwnedStates[0].sprite) + if (SpriteOverride != 0 && sprite == SpawnState->sprite) { sprite = SpriteOverride; } From d547e8954829aa64fb47314a08d90841e5b89b14 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 18 Jan 2010 20:55:49 +0000 Subject: [PATCH 208/241] - added a CVAR to disable raw input in case it causes problems (like apparently on Wine.) SVN r2118 (trunk) --- src/win32/i_input.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 7ee8f138f..a40923d7b 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -101,6 +101,7 @@ #include "cmdlib.h" #include "d_event.h" #include "v_text.h" +#include "version.h" // Prototypes and declarations. #include "rawinput.h" @@ -159,6 +160,11 @@ int SessionState = 0; CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Bool, norawinput, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) +{ + Printf("This won't take effect until "GAMENAME" is restarted.\n"); +} + extern int chatmodeon; static void I_CheckGUICapture () @@ -592,7 +598,7 @@ bool I_InitInput (void *hwnd) g_pdi = NULL; g_pdi3 = NULL; - FindRawInputFunctions(); + if (!norawinput) FindRawInputFunctions(); // Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit. DInputDLL = LoadLibrary("dinput8.dll"); From 71b75f0d7afcb6f29099ffce23a69731e7cb56b7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 22 Jan 2010 05:17:57 +0000 Subject: [PATCH 209/241] - Consolidated all conversation reply handling into a single function executed on all machines, so when an NPC need to show the "enough" response, it has enough information available to do so. - Some new Strife Teaser fixes I forgot to commit are in here. - Moved norawinput check into FindRawInputFunctions(). SVN r2120 (trunk) --- src/d_iwad.cpp | 4 +- src/d_main.cpp | 5 +- src/d_net.cpp | 31 +- src/d_protocol.h | 7 +- src/p_conversation.cpp | 287 ++++++++-------- src/p_conversation.h | 14 +- src/version.h | 4 +- src/win32/i_input.cpp | 17 +- zdoom.vcproj | 746 ++++++++++++++++++++--------------------- 9 files changed, 558 insertions(+), 557 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 3beb23fba..3cf9773ce 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -283,11 +283,11 @@ static EIWADType ScanIWAD (const char *iwad) } else if (lumpsfound[Check_invcurs]) { - return IWAD_StrifeTeaser2; + return IWAD_StrifeTeaser2; // Strife0.wad from 14 Mar 1996 } else { - return IWAD_StrifeTeaser; + return IWAD_StrifeTeaser; // Strife0.wad from 22 Feb 1996 } } else if (lumpsfound[Check_map01]) diff --git a/src/d_main.cpp b/src/d_main.cpp index 3de2bab7c..534f30afe 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1046,7 +1046,10 @@ void D_DoStrifeAdvanceDemo () pagetic = 7 * TICRATE; pagename = "PANEL1"; S_Sound (CHAN_VOICE | CHAN_UI, voices[0], 1, ATTN_NORM); - S_StartMusic ("d_intro"); + // The new Strife teaser has D_FMINTR. + // The full retail Strife has D_INTRO. + // And the old Strife teaser has both. (I do not know which one it actually uses, nor do I care.) + S_StartMusic (gameinfo.flags & GI_TEASER2 ? "d_fmintr" : "d_intro"); break; case 4: diff --git a/src/d_net.cpp b/src/d_net.cpp index cf30c5830..264aed1df 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2367,8 +2367,10 @@ void Net_DoCommand (int type, BYTE **stream, int player) } break; - case DEM_CONVERSATION: - P_ConversationCommand (player, stream); + case DEM_CONVREPLY: + case DEM_CONVCLOSE: + case DEM_CONVNULL: + P_ConversationCommand (type, player, stream); break; case DEM_SETSLOT: @@ -2500,29 +2502,8 @@ void Net_SkipCommand (int type, BYTE **stream) skip = 3 + *(*stream + 2) * 4; break; - case DEM_CONVERSATION: - { - t = **stream; - skip = 1; - - switch (t) - { - case CONV_ANIMATE: - skip += 1; - break; - - case CONV_GIVEINVENTORY: - skip += strlen ((char *)(*stream + skip)) + 1; - break; - - case CONV_TAKEINVENTORY: - skip += strlen ((char *)(*stream + skip)) + 3; - break; - - default: - break; - } - } + case DEM_CONVREPLY: + skip = 3; break; case DEM_SETSLOT: diff --git a/src/d_protocol.h b/src/d_protocol.h index eae1f4aa9..a78c39ae2 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -147,14 +147,17 @@ enum EDemoCommand DEM_ADDCONTROLLER, // 48 Player to add to the controller list. DEM_DELCONTROLLER, // 49 Player to remove from the controller list. DEM_KILLCLASSCHEAT, // 50 String: Class to kill. - DEM_CONVERSATION, // 51 Make conversations work. + DEM_UNDONE11, // 51 DEM_SUMMON2, // 52 String: Thing to fabricate, WORD: angle offset DEM_SUMMONFRIEND2, // 53 DEM_SUMMONFOE2, // 54 DEM_ADDSLOTDEFAULT, // 55 DEM_ADDSLOT, // 56 DEM_SETSLOT, // 57 - DEM_SUMMONMBF, + DEM_SUMMONMBF, // 58 + DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number + DEM_CONVCLOSE, // 60 + DEM_CONVNULL, // 61 }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 53667881c..a2840f355 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -125,8 +125,6 @@ static void ConversationMenuEscaped (); static FStrifeDialogueNode *CurNode, *PrevNode; static FBrokenLines *DialogueLines; -static bool Conversation_TakeStuff; - #define NUM_RANDOM_LINES 10 #define NUM_RANDOM_GOODBYES 3 @@ -282,7 +280,7 @@ static void LoadScriptFile(FileReader *lump, int numnodes) { node = ReadTeaserNode (lump, prevSpeakerType); } - StrifeDialogues.Push (node); + node->ThisNodeNum = StrifeDialogues.Push(node); } } @@ -623,18 +621,23 @@ static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount if (itemtype->IsDescendantOf (PClass::FindClass(NAME_QuestItem))) return; - // Don't take keys + // Don't take keys. if (itemtype->IsDescendantOf (RUNTIME_CLASS(AKey))) return; - // Don't take the sigil + // Don't take the sigil. if (itemtype == RUNTIME_CLASS(ASigil)) return; - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_TAKEINVENTORY); - Net_WriteString (itemtype->TypeName.GetChars ()); - Net_WriteWord (amount); + AInventory *item = player->mo->FindInventory (itemtype); + if (item != NULL) + { + item->Amount -= amount; + if (item->Amount <= 0) + { + item->Destroy (); + } + } } CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE) @@ -732,7 +735,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang } // Set up the menu - ::CurNode = CurNode; // only set the global variaböle for the consoleplayer + ::CurNode = CurNode; // only set the global variable for the consoleplayer ConversationMenu.PreDraw = DrawConversationMenu; ConversationMenu.EscapeHandler = ConversationMenuEscaped; @@ -743,10 +746,13 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang FString dlgtext; dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES)); - toSay = GStrings[dlgtext.GetChars()]; - if (toSay==NULL) toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;) + toSay = GStrings[dlgtext]; + if (toSay == NULL) + { + toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;) + } } - DialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac-24*2, toSay); + DialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay); // Fill out the possible choices ShowGold = false; @@ -980,93 +986,155 @@ static bool DrawConversationMenu () // // PickConversationReply // +// Run only on the local machine with the conversation menu up. +// //============================================================================ static void PickConversationReply () { - const char *replyText = NULL; FStrifeDialogueReply *reply = (FStrifeDialogueReply *)ConversationItems[ConversationMenu.lastOn].c.extra; - int i; - player_t *cp = &players[consoleplayer]; + FStrifeDialogueReply *replyscan; + int replynum = 0; - Conversation_TakeStuff = false; + assert(CurNode->ThisNodeNum >= 0 && CurNode->ThisNodeNum < 65536); + assert(StrifeDialogues[CurNode->ThisNodeNum] == CurNode); - M_ClearMenus (); - CleanupConversationMenu (); + // Determine reply number for netcode. if (reply == NULL) { - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_NPCANGLE); - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_CLOSE); + replyscan = NULL; + } + else + { + for (replyscan = CurNode->Children; replyscan != NULL && replyscan != reply; ++replynum, replyscan = replyscan->Next) + { } + } + + M_ClearMenus (); + if (replyscan == NULL) + { + Net_WriteByte(DEM_CONVCLOSE); + } + else + { + // Send dialogue and reply numbers across the wire. + assert(replynum < 256); + Net_WriteByte(DEM_CONVREPLY); + Net_WriteWord(CurNode->ThisNodeNum); + Net_WriteByte(replynum); + } + CleanupConversationMenu (); +} + +//============================================================================ +// +// HandleReply +// +// Run by the netcode on all machines. +// +//============================================================================ + +static void HandleReply(player_t *player, bool isconsole, int nodenum, int replynum) +{ + const char *replyText = NULL; + FStrifeDialogueReply *reply; + FStrifeDialogueNode *node; + AActor *npc; + bool takestuff; + int i; + + if (player->ConversationNPC == NULL || (unsigned)nodenum >= StrifeDialogues.Size()) + { return; } + // Find the reply. + node = StrifeDialogues[nodenum]; + for (i = 0, reply = node->Children; reply != NULL && i != replynum; ++i, reply = reply->Next) + { } + if (reply == NULL) + { + return; + } + + npc = player->ConversationNPC; + // Check if you have the requisite items for this choice for (i = 0; i < 3; ++i) { - if (!CheckStrifeItem (cp, reply->ItemCheck[i], reply->ItemCheckAmount[i])) + if (!CheckStrifeItem(player, reply->ItemCheck[i], reply->ItemCheckAmount[i])) { // No, you don't. Say so and let the NPC animate negatively. - if (reply->QuickNo) + if (reply->QuickNo && isconsole) { - Printf ("%s\n", reply->QuickNo); + Printf("%s\n", reply->QuickNo); } - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_ANIMATE); - Net_WriteByte (2); - - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_NPCANGLE); - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_CLOSE); + npc->ConversationAnimation(2); + npc->angle = player->ConversationNPCAngle; + npc->flags5 &= ~MF5_INCONVERSATION; return; } } // Yay, you do! Let the NPC animate affirmatively. - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_ANIMATE); - Net_WriteByte (1); + npc->ConversationAnimation(1); // If this reply gives you something, then try to receive it. - Conversation_TakeStuff = true; + takestuff = true; if (reply->GiveType != NULL) { if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(AInventory))) { if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { - if (cp->mo->FindInventory(reply->GiveType) != NULL) + if (player->mo->FindInventory(reply->GiveType) != NULL) { - Conversation_TakeStuff = false; + takestuff = false; } } - if (Conversation_TakeStuff) + if (takestuff) { - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_GIVEINVENTORY); - Net_WriteString (reply->GiveType->TypeName.GetChars ()); + AInventory *item = static_cast(Spawn(reply->GiveType, 0, 0, 0, NO_REPLACE)); + // Items given here should not count as items! + if (item->flags & MF_COUNTITEM) + { + level.total_items--; + item->flags &= ~MF_COUNTITEM; + } + if (item->GetClass()->TypeName == NAME_FlameThrower) + { + // The flame thrower gives less ammo when given in a dialog + static_cast(item)->AmmoGive1 = 40; + } + item->flags |= MF_DROPPED; + if (!item->CallTryPickup(player->mo)) + { + item->Destroy(); + takestuff = false; + } } - if (reply->GiveType->IsDescendantOf (RUNTIME_CLASS (ASlideshowStarter))) + if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(ASlideshowStarter))) gameaction = ga_slideshow; } else { // Trying to give a non-inventory item. - Conversation_TakeStuff = false; - Printf("Attempting to give non-inventory item %s\n", reply->GiveType->TypeName.GetChars()); + takestuff = false; + if (isconsole) + { + Printf("Attempting to give non-inventory item %s\n", reply->GiveType->TypeName.GetChars()); + } } } // Take away required items if the give was successful or none was needed. - if (Conversation_TakeStuff) + if (takestuff) { for (i = 0; i < 3; ++i) { - TakeStrifeItem (&players[consoleplayer], reply->ItemCheck[i], reply->ItemCheckAmount[i]); + TakeStrifeItem (player, reply->ItemCheck[i], reply->ItemCheckAmount[i]); } replyText = reply->QuickYes; } @@ -1078,12 +1146,12 @@ static void PickConversationReply () // Update the quest log, if needed. if (reply->LogNumber != 0) { - cp->SetLogNumber (reply->LogNumber); + player->SetLogNumber(reply->LogNumber); } - if (replyText != NULL) + if (replyText != NULL && isconsole) { - Printf ("%s\n", replyText); + Printf("%s\n", replyText); } // Does this reply alter the speaker's conversation node? If NextNode is positive, @@ -1091,39 +1159,44 @@ static void PickConversationReply () // will show the new node right away without terminating the dialogue. if (reply->NextNode != 0) { - int rootnode = FindNode (cp->ConversationNPC->GetDefault()->Conversation); + int rootnode = FindNode (npc->GetDefault()->Conversation); if (reply->NextNode < 0) { - cp->ConversationNPC->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1]; + npc->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1]; if (gameaction != ga_slideshow) { - P_StartConversation (cp->ConversationNPC, cp->mo, cp->ConversationFaceTalker, false); + P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false); return; } else { - S_StopSound (cp->ConversationNPC, CHAN_VOICE); + S_StopSound (npc, CHAN_VOICE); } } else { - cp->ConversationNPC->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1]; + npc->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1]; } } - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_NPCANGLE); + npc->angle = player->ConversationNPCAngle; // [CW] Set these to NULL because we're not using to them // anymore. However, this can interfere with slideshows // so we don't set them to NULL in that case. if (gameaction != ga_slideshow) { - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_SETNULL); + npc->flags5 &= ~MF5_INCONVERSATION; + player->ConversationFaceTalker = false; + player->ConversationNPC = NULL; + player->ConversationPC = NULL; + player->ConversationNPCAngle = 0; } - I_SetMusicVolume (1.f); + if (isconsole) + { + I_SetMusicVolume (1.f); + } } //============================================================================ @@ -1170,12 +1243,7 @@ void CleanupConversationMenu () void ConversationMenuEscaped () { CleanupConversationMenu (); - - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_NPCANGLE); - - Net_WriteByte (DEM_CONVERSATION); - Net_WriteByte (CONV_SETNULL); + Net_WriteByte (DEM_CONVNULL); } //============================================================================ @@ -1186,77 +1254,30 @@ void ConversationMenuEscaped () // //============================================================================ -void P_ConversationCommand (int player, BYTE **stream) +void P_ConversationCommand (int netcode, int pnum, BYTE **stream) { - int type = ReadByte (stream); + player_t *player = &players[pnum]; - switch (type) + if (netcode == DEM_CONVREPLY) { - case CONV_NPCANGLE: - players[player].ConversationNPC->angle = players[player].ConversationNPCAngle; - break; - - case CONV_ANIMATE: - players[player].ConversationNPC->ConversationAnimation (ReadByte (stream)); - break; - - case CONV_GIVEINVENTORY: + int nodenum = ReadWord(stream); + int replynum = ReadByte(stream); + HandleReply(player, pnum == consoleplayer, nodenum, replynum); + } + else + { + assert(netcode == DEM_CONVNULL || netcode == DEM_CONVCLOSE); + if (player->ConversationNPC != NULL) { - AInventory *item = static_cast (Spawn (ReadString (stream), 0, 0, 0, NO_REPLACE)); - // Items given here should not count as items! - if (item->flags & MF_COUNTITEM) - { - level.total_items--; - item->flags &= ~MF_COUNTITEM; - } - if (item->GetClass()->TypeName == NAME_FlameThrower) - { - // The flame thrower gives less ammo when given in a dialog - static_cast(item)->AmmoGive1 = 40; - } - item->flags |= MF_DROPPED; - if (!item->CallTryPickup (players[player].mo)) - { - item->Destroy (); - Conversation_TakeStuff = false; - } + player->ConversationNPC->angle = player->ConversationNPCAngle; + player->ConversationNPC->flags5 &= ~MF5_INCONVERSATION; } - break; - - case CONV_TAKEINVENTORY: + if (netcode == DEM_CONVNULL) { - AInventory *item = players[player].ConversationPC->FindInventory (PClass::FindClass (ReadString (stream))); - - if (item != NULL) - { - item->Amount -= ReadWord (stream); - if (item->Amount <= 0) - { - item->Destroy (); - } - } + player->ConversationFaceTalker = false; + player->ConversationNPC = NULL; + player->ConversationPC = NULL; + player->ConversationNPCAngle = 0; } - break; - - case CONV_SETNULL: - if (players[player].ConversationNPC != NULL) - { - players[player].ConversationNPC->flags5 &= ~MF5_INCONVERSATION; - } - players[player].ConversationFaceTalker = false; - players[player].ConversationNPC = NULL; - players[player].ConversationPC = NULL; - players[player].ConversationNPCAngle = 0; - break; - - case CONV_CLOSE: - if (players[player].ConversationNPC != NULL) - { - players[player].ConversationNPC->flags5 &= ~MF5_INCONVERSATION; - } - break; - - default: - break; } } diff --git a/src/p_conversation.h b/src/p_conversation.h index a6da8a8b6..13658e0f0 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -17,6 +17,7 @@ struct FStrifeDialogueNode ~FStrifeDialogueNode (); const PClass *DropType; const PClass *ItemCheck[3]; + int ThisNodeNum; // location of this node in StrifeDialogues int ItemCheckNode; // index into StrifeDialogues const PClass *SpeakerType; @@ -47,17 +48,6 @@ struct FStrifeDialogueReply FBrokenLines *ReplyLines; }; -// [CW] These are used to make conversations work. -enum -{ - CONV_NPCANGLE, - CONV_ANIMATE, - CONV_GIVEINVENTORY, - CONV_TAKEINVENTORY, - CONV_SETNULL, - CONV_CLOSE, -}; - extern TArray StrifeDialogues; // There were 344 types in Strife, and Strife conversations refer @@ -74,6 +64,6 @@ void P_FreeStrifeConversations (); void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveangle); void P_ResumeConversation (); -void P_ConversationCommand (int player, BYTE **stream); +void P_ConversationCommand (int netcode, int player, BYTE **stream); #endif diff --git a/src/version.h b/src/version.h index 80a8fd861..769e8005c 100644 --- a/src/version.h +++ b/src/version.h @@ -64,11 +64,11 @@ // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x212 +#define DEMOGAMEVERSION 0x213 // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. -#define MINDEMOVERSION 0x211 +#define MINDEMOVERSION 0x213 // SAVEVER is the version of the information stored in level snapshots. // Note that SAVEVER is not directly comparable to VERSION. diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index a40923d7b..e9d2a26bb 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -598,7 +598,7 @@ bool I_InitInput (void *hwnd) g_pdi = NULL; g_pdi3 = NULL; - if (!norawinput) FindRawInputFunctions(); + FindRawInputFunctions(); // Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit. DInputDLL = LoadLibrary("dinput8.dll"); @@ -938,13 +938,16 @@ bool FInputDevice::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP static void FindRawInputFunctions() { - HMODULE user32 = GetModuleHandle("user32.dll"); - - if (user32 == NULL) + if (!norawinput) { - return; // WTF kind of broken system are we running on? - } + HMODULE user32 = GetModuleHandle("user32.dll"); + + if (user32 == NULL) + { + return; // WTF kind of broken system are we running on? + } #define RIF(name,ret,args) \ - My##name = (name##Proto)GetProcAddress(user32, #name); + My##name = (name##Proto)GetProcAddress(user32, #name); #include "rawinput.h" + } } diff --git a/zdoom.vcproj b/zdoom.vcproj index 97a2f1378..793cce76c 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1872,6 +1864,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2061,6 +2061,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2071,14 +2079,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5363,14 +5371,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5649,7 +5649,7 @@ /> Date: Sat, 23 Jan 2010 19:07:18 +0000 Subject: [PATCH 210/241] - Added an input grid for controller-based string entry in the save game and player setup menus (which I had forgotten to do for 2.4.0). If you don't use a controller to activate the string entry mode and keep your hands off the controller while typing, it remains invisible. SVN r2121 (trunk) --- src/m_menu.cpp | 193 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 11 deletions(-) diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 229da94db..88eac1edf 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -82,6 +82,9 @@ #define KEY_REPEAT_DELAY (TICRATE*5/12) #define KEY_REPEAT_RATE (3) +#define INPUTGRID_WIDTH 13 +#define INPUTGRID_HEIGHT 5 + // TYPES ------------------------------------------------------------------- struct FSaveGameNode : public Node @@ -171,6 +174,8 @@ static void M_DrawFiles (); void M_DrawFrame (int x, int y, int width, int height); static void M_DrawSaveLoadBorder (int x,int y, int len); static void M_DrawSaveLoadCommon (); +static void M_DrawInputGrid(); + static void M_SetupNextMenu (oldmenu_t *menudef); static void M_StartMessage (const char *string, void(*routine)(int)); static void M_EndMessage (int key); @@ -276,6 +281,18 @@ static int epi; // Selected episode static const char *saved_playerclass = NULL; +// Heretic and Hexen do not, by default, come with glyphs for all of these +// characters. Oh well. Doom and Strife do. +static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] = + "ABCDEFGHIJKLM" + "NOPQRSTUVWXYZ" + "0123456789+-=" + ".,!?@'\":;[]()" + "<>^#$%&*/_ \b"; +static int InputGridX = INPUTGRID_WIDTH - 1; +static int InputGridY = INPUTGRID_HEIGHT - 1; +static bool InputGridOkay; // Last input was with a controller. + // PRIVATE MENU DEFINITIONS ------------------------------------------------ // @@ -2873,14 +2890,6 @@ bool M_Responder (event_t *ev) // This code previously listened for EV_GUI_KeyRepeat to handle repeating // in the menus, but that doesn't work with gamepads, so now we combine // the multiple inputs into buttons and handle the repetition manually. - // - // FIXME: genStringEnter and messageToPrint do not play well with game - // controllers. In fact, you can still interact with the rest of - // the menu using a controller while the menu waits for input. Especially - // bad if you, say, select quit from the main menu. (Ideally, - // genStringEnter will pop up a keypad if it detects a controller is - // being used to navigate the menu. At the very least, it should - // disable the controller.) if (ev->type == EV_GUI_Event) { // Save game and player name string input @@ -2888,8 +2897,9 @@ bool M_Responder (event_t *ev) { if (ev->subtype == EV_GUI_Char) { + InputGridOkay = false; if (saveCharIndex < genStringLen && - (genStringEnter == 2 || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8)) + (genStringEnter == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8)) { savegamestring[saveCharIndex] = (char)ev->data1; savegamestring[++saveCharIndex] = 0; @@ -2897,8 +2907,7 @@ bool M_Responder (event_t *ev) return true; } ch = ev->data1; - if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && - ch == '\b') + if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b') { if (saveCharIndex > 0) { @@ -3011,10 +3020,23 @@ bool M_Responder (event_t *ev) } break; } + if (!keyup) + { + InputGridOkay = false; + } } else if (ev->type == EV_KeyDown || ev->type == EV_KeyUp) { keyup = ev->type == EV_KeyUp; + // If this is a button down, it's okay to show the input grid if the + // next action causes us to enter genStringEnter mode. If we are + // already in that mode, then we let M_ButtonHandler() turn it on so + // that it will know if a button press happened while the input grid + // was turned off. + if (!keyup && !genStringEnter) + { + InputGridOkay = true; + } ch = ev->data1; switch (ch) { @@ -3145,6 +3167,74 @@ void M_ButtonHandler(EMenuKey key, bool repeat) } return; } + if (genStringEnter) + { + int ch; + + switch (key) + { + case MKEY_Down: + InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT; + break; + + case MKEY_Up: + InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT; + break; + + case MKEY_Right: + InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH; + break; + + case MKEY_Left: + InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH; + break; + + case MKEY_Clear: + if (saveCharIndex > 0) + { + savegamestring[--saveCharIndex] = 0; + } + break; + + case MKEY_Enter: + assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT); + if (InputGridOkay) + { + ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH]; + if (ch == 0) // end + { + if (savegamestring[0] != '\0') + { + genStringEnter = 0; + if (messageToPrint) + { + M_ClearMenus(); + } + genStringEnd(SelSaveGame); + } + } + else if (ch == '\b') // bs + { + if (saveCharIndex > 0) + { + savegamestring[--saveCharIndex] = 0; + } + } + else if (saveCharIndex < genStringLen && + (genStringEnter == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8)) + { + savegamestring[saveCharIndex] = ch; + savegamestring[++saveCharIndex] = 0; + } + } + break; + + default: + break; // Keep GCC quiet + } + InputGridOkay = true; + return; + } if (currentMenu == &SaveDef || currentMenu == &LoadDef) { M_SaveLoadButtonHandler(key); @@ -3359,6 +3449,12 @@ static void M_SaveSelect (const FSaveGameNode *file) } else { + // If we are naming a new save, don't start the cursor on "end". + if (InputGridX == INPUTGRID_WIDTH - 1 && InputGridY == INPUTGRID_HEIGHT - 1) + { + InputGridX = 0; + InputGridY = 0; + } savegamestring[0] = 0; } saveCharIndex = strlen (savegamestring); @@ -3577,6 +3673,10 @@ void M_Drawer () } } } + if (genStringEnter && InputGridOkay) + { + M_DrawInputGrid(); + } } } @@ -3602,6 +3702,77 @@ static void M_ClearSaveStuff () } } +static void M_DrawInputGrid() +{ + const int cell_width = 18 * CleanXfac; + const int cell_height = 12 * CleanYfac; + const int top_padding = cell_height / 2 - SmallFont->GetHeight() * CleanYfac / 2; + + // Darken the background behind the character grid. + // Unless we frame it with a border, I think it looks better to extend the + // background across the full width of the screen. + screen->Dim(0, 0.8f, + 0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/, + screen->GetHeight() - 5 * cell_height, + screen->GetWidth() /*13 * cell_width*/, + 5 * cell_height); + + // Highlight the background behind the selected character. + screen->Dim(MAKERGB(255,248,220), 0.6f, + InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2, + InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(), + cell_width, cell_height); + + for (int y = 0; y < INPUTGRID_HEIGHT; ++y) + { + const int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(); + for (int x = 0; x < INPUTGRID_WIDTH; ++x) + { + int width; + const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2; + const int ch = InputGridChars[y * INPUTGRID_WIDTH + x]; + FTexture *pic = SmallFont->GetChar(ch, &width); + EColorRange color; + FRemapTable *remap; + + // The highlighted character is yellow; the rest are dark gray. + color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY; + remap = SmallFont->GetColorTranslation(color); + + if (pic != NULL) + { + // Draw a normal character. + screen->DrawTexture(pic, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, + DTA_Translation, remap, + DTA_CleanNoMove, true, + TAG_DONE); + } + else if (ch == ' ') + { + // Draw the space as a box outline. We also draw it 50% wider than it really is. + const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4; + const int x2 = x1 + width * 3 * CleanXfac / 2; + const int y1 = yy + top_padding; + const int y2 = y1 + SmallFont->GetHeight() * CleanYfac; + const int palentry = remap->Remap[remap->NumEntries*2/3]; + const uint32 palcolor = remap->Palette[remap->NumEntries*2/3]; + screen->Clear(x1, y1, x2, y1+CleanYfac, palentry, palcolor); // top + screen->Clear(x1, y2, x2, y2+CleanYfac, palentry, palcolor); // bottom + screen->Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palentry, palcolor); // left + screen->Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palentry, palcolor); // right + } + else if (ch == '\b' || ch == 0) + { + // Draw the backspace and end "characters". + const char *const str = ch == '\b' ? "BS" : "ED"; + screen->DrawText(SmallFont, color, + xx + cell_width/2 - SmallFont->StringWidth(str)*CleanXfac/2, + yy + top_padding, str, DTA_CleanNoMove, true, TAG_DONE); + } + } + } +} + // // M_ClearMenus // From 2fc338db88b3aa6cf0f4f173812e3b83d076e22a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 23 Jan 2010 20:48:24 +0000 Subject: [PATCH 211/241] - Removed the integer clobbers from pow_x87_inline, since they interfered with PIC code and appear unneeded. SVN r2122 (trunk) --- src/timidity/timidity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timidity/timidity.h b/src/timidity/timidity.h index e704b6b78..6e630554e 100644 --- a/src/timidity/timidity.h +++ b/src/timidity/timidity.h @@ -161,7 +161,7 @@ extern __inline__ double pow_x87_inline(double x,double y) "fmulp\n\t" : "=t" (result) : "0" (x), "u" (y) - : "st(1)", "st(7)", "%3", "%4" ); + : "st(1)", "st(7)" ); return result; } #define pow pow_x87_inline From e190109c03d73082cd4ef9030d7bfa0a0fd11b5a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 23 Jan 2010 21:26:07 +0000 Subject: [PATCH 212/241] - Made conversation "mini responses" more prominent rather than packing them in with the rest of the generic console output at the top of the screen. SVN r2123 (trunk) --- src/p_conversation.cpp | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index a2840f355..8e32ee8ab 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -57,6 +57,8 @@ #include "g_level.h" #include "d_event.h" #include "doomstat.h" +#include "c_console.h" +#include "sbar.h" // The conversations as they exist inside a SCRIPTxx lump. struct Response @@ -121,6 +123,7 @@ static bool DrawConversationMenu (); static void PickConversationReply (); static void CleanupConversationMenu (); static void ConversationMenuEscaped (); +static void TerminalResponse (const char *str); static FStrifeDialogueNode *CurNode, *PrevNode; static FBrokenLines *DialogueLines; @@ -1067,7 +1070,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply // No, you don't. Say so and let the NPC animate negatively. if (reply->QuickNo && isconsole) { - Printf("%s\n", reply->QuickNo); + TerminalResponse(reply->QuickNo); } npc->ConversationAnimation(2); npc->angle = player->ConversationNPCAngle; @@ -1151,7 +1154,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply if (replyText != NULL && isconsole) { - Printf("%s\n", replyText); + TerminalResponse(replyText); } // Does this reply alter the speaker's conversation node? If NextNode is positive, @@ -1281,3 +1284,35 @@ void P_ConversationCommand (int netcode, int pnum, BYTE **stream) } } } + +//============================================================================ +// +// TerminalResponse +// +// Similar to C_MidPrint, but lower and colored and sized to match the +// rest of the dialogue text. +// +//============================================================================ + +static void TerminalResponse (const char *str) +{ + if (str != NULL) + { + if (StatusBar != NULL) + { + AddToConsole(-1, str); + AddToConsole(-1, "\n"); + // The message is positioned a bit above the menu choices, because + // merchants can tell you something like this but continue to show + // their dialogue screen. I think most other conversations use this + // only as a response for terminating the dialogue. + StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, str, + float(CleanWidth/2) + 0.4f, float(ConversationMenu.y - 110 + CleanHeight/2), CleanWidth, -CleanHeight, + CR_UNTRANSLATED, 3, 1), MAKE_ID('T','A','L','K')); + } + else + { + Printf("%s\n", str); + } + } +} From c363f169d710e17d38b7769a43e4304205c1ebc9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Jan 2010 08:41:40 +0000 Subject: [PATCH 213/241] - added PROP_BUDDHA option to SetPlayerProperty. SVN r2127 (trunk) --- src/p_lnspec.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 5792a8a23..bb94ccea1 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2513,6 +2513,7 @@ enum PROP_UNUSED1, PROP_UNUSED2, PROP_SPEED, + PROP_BUDDHA, }; FUNC(LS_SetPlayerProperty) @@ -2629,6 +2630,9 @@ FUNC(LS_SetPlayerProperty) // Set or clear a flag switch (arg2) { + case PROP_BUDDHA: + mask = CF_BUDDHA; + break; case PROP_FROZEN: mask = CF_FROZEN; break; From 8b9d8137fcf6009eaedb72afc65a2f0c1c8a3bd2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Jan 2010 09:46:31 +0000 Subject: [PATCH 214/241] - fixed: P_SpawnPuff must set the puff's owner before doing any state jumps. SVN r2128 (trunk) --- src/p_mobj.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 599f78772..7db992019 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4446,6 +4446,11 @@ AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t puff = Spawn (pufftype, x, y, z, ALLOW_REPLACE); if (puff == NULL) return NULL; + + // [BB] If the puff came from a player, set the target of the puff to this player. + if ( puff && (puff->flags5 & MF5_PUFFGETSOWNER)) + puff->target = source; + if (source != NULL) puff->angle = R_PointToAngle2(x, y, source->x, source->y); // If a puff has a crash state and an actor was not hit, @@ -4481,10 +4486,6 @@ AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t } } - // [BB] If the puff came from a player, set the target of the puff to this player. - if ( puff && (puff->flags5 & MF5_PUFFGETSOWNER)) - puff->target = source; - return puff; } From 406b692cc96ed6479b7d801a7813a4f43790f7d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Jan 2010 13:00:53 +0000 Subject: [PATCH 215/241] - removed the TakeSpecialDamage hacks for Macil and the Oracle and replaced them by giving the first stage Sigil's projectiles a damage type and using a damage factor to disable damaging these actors. SVN r2129 (trunk) --- src/g_strife/a_alienspectres.cpp | 34 -------------- src/g_strife/a_macil.cpp | 47 ------------------- src/g_strife/a_oracle.cpp | 29 ------------ src/g_strife/a_strifestuff.cpp | 2 +- wadsrc/static/actors/strife/alienspectres.txt | 4 +- wadsrc/static/actors/strife/macil.txt | 5 +- wadsrc/static/actors/strife/oracle.txt | 3 +- wadsrc/static/actors/strife/spectral.txt | 1 + 8 files changed, 9 insertions(+), 116 deletions(-) delete mode 100644 src/g_strife/a_macil.cpp diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index b09c1b098..6506cdb1c 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -13,20 +13,6 @@ #include "doomstat.h" */ -class AAlienSpectre1 : public ASpectralMonster -{ - DECLARE_CLASS (AAlienSpectre1, ASpectralMonster) -}; -IMPLEMENT_CLASS(AAlienSpectre1); - -class AAlienSpectre3 : public AAlienSpectre1 -{ - DECLARE_CLASS (AAlienSpectre3, AAlienSpectre1) -public: - int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); -}; -IMPLEMENT_CLASS(AAlienSpectre3); - static FRandom pr_spectrespawn ("AlienSpectreSpawn"); static FRandom pr_spectrechunk ("212e4"); @@ -204,23 +190,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) S_Sound (CHAN_VOICE, voc, 1, ATTN_NORM); player->player->SetLogNumber (log); } - -//============================================================================ -// -// AAlienSpetre3 :: TakeSpecialDamage -// -// The third spectre type (the Oracle's) is invulnerable to the first stage -// Sigil, just like the Oracle. -// -//============================================================================ - -int AAlienSpectre3::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) -{ - if (inflictor != NULL) - { - FName name = inflictor->GetClass()->TypeName; - if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) - return -1; - } - return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); -} diff --git a/src/g_strife/a_macil.cpp b/src/g_strife/a_macil.cpp deleted file mode 100644 index a5b3190ab..000000000 --- a/src/g_strife/a_macil.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -*/ - -// Macil (version 1) --------------------------------------------------------- - -class AMacil1 : public AActor -{ - DECLARE_CLASS (AMacil1, AActor) -}; - -IMPLEMENT_CLASS (AMacil1) - -// Macil (version 2) --------------------------------------------------------- - -class AMacil2 : public AMacil1 -{ - DECLARE_CLASS (AMacil2, AMacil1) -public: - int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS (AMacil2) - -//============================================================================ -// -// AMacil2 :: TakeSpecialDamage -// -// Macil2 is invulnerable to the first stage Sigil. -// -//============================================================================ - -int AMacil2::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) -{ - if (inflictor != NULL) - { - FName name = inflictor->GetClass()->TypeName; - if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) - return -1; - } - return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); -} diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp index d5d119e38..0eb3f1ac6 100644 --- a/src/g_strife/a_oracle.cpp +++ b/src/g_strife/a_oracle.cpp @@ -7,16 +7,6 @@ #include "thingdef/thingdef.h" */ -class AOracle : public AActor -{ - DECLARE_CLASS (AOracle, AActor) -public: - int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype); -}; - - -IMPLEMENT_CLASS (AOracle) - DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) { @@ -31,22 +21,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) } } - -//============================================================================ -// -// AOracle :: TakeSpecialDamage -// -// The Oracle is invulnerable to the first stage Sigil. -// -//============================================================================ - -int AOracle::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype) -{ - if (inflictor != NULL) - { - FName name = inflictor->GetClass()->TypeName; - if (name == NAME_SpectralLightningV1 || name == NAME_SpectralLightningV2) - return -1; - } - return Super::TakeSpecialDamage(inflictor, source, damage, damagetype); -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index aba8228c1..eef693d0e 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -28,7 +28,7 @@ #include "a_entityboss.cpp" #include "a_inquisitor.cpp" #include "a_loremaster.cpp" -#include "a_macil.cpp" +//#include "a_macil.cpp" #include "a_oracle.cpp" #include "a_programmer.cpp" #include "a_reaver.cpp" diff --git a/wadsrc/static/actors/strife/alienspectres.txt b/wadsrc/static/actors/strife/alienspectres.txt index 2e3273c32..f0da99f28 100644 --- a/wadsrc/static/actors/strife/alienspectres.txt +++ b/wadsrc/static/actors/strife/alienspectres.txt @@ -1,7 +1,7 @@ // Alien Spectre 1 ----------------------------------------------------------- -ACTOR AlienSpectre1 : SpectralMonster 129 native +ACTOR AlienSpectre1 : SpectralMonster 129 { Game Strife ConversationID 67,-1,-1 @@ -100,7 +100,7 @@ ACTOR AlienSpectre2 : AlienSpectre1 75 // Alien Spectre 3 ---------------------------------------------------------- // This is the Oracle's personal spectre, so it's a little different. -ACTOR AlienSpectre3 : AlienSpectre1 76 native +ACTOR AlienSpectre3 : AlienSpectre1 76 { Game Strife ConversationID 71,-1,-1 diff --git a/wadsrc/static/actors/strife/macil.txt b/wadsrc/static/actors/strife/macil.txt index 38cba53c0..ea701dd9f 100644 --- a/wadsrc/static/actors/strife/macil.txt +++ b/wadsrc/static/actors/strife/macil.txt @@ -1,7 +1,7 @@ // Macil (version 1) --------------------------------------------------------- -ACTOR Macil1 64 native +ACTOR Macil1 64 { Game Strife ConversationID 49, 48, 49 @@ -56,7 +56,7 @@ ACTOR Macil1 64 native // Macil (version 2) --------------------------------------------------------- -ACTOR Macil2 : Macil1 200 native +ACTOR Macil2 : Macil1 200 { Game Strife ConversationID 50, 49, 50 @@ -66,6 +66,7 @@ ACTOR Macil2 : Macil1 200 native -NODAMAGE DeathSound "macil/slop" DropItem "None" + DamageFactor "SpectralLow", 0 States { Missile: diff --git a/wadsrc/static/actors/strife/oracle.txt b/wadsrc/static/actors/strife/oracle.txt index 6c0639a96..594eb83af 100644 --- a/wadsrc/static/actors/strife/oracle.txt +++ b/wadsrc/static/actors/strife/oracle.txt @@ -1,7 +1,7 @@ // Oracle ------------------------------------------------------------------- -ACTOR Oracle 199 native +ACTOR Oracle 199 { Game Strife ConversationID 65, 62, 63 @@ -11,6 +11,7 @@ ACTOR Oracle 199 native Monster +NOTDMATCH DamageFactor "Fire", 0.5 + DamageFactor "SpectralLow", 0 MaxDropoffHeight 32 Tag "Oracle" DropItem "Meat" diff --git a/wadsrc/static/actors/strife/spectral.txt b/wadsrc/static/actors/strife/spectral.txt index e3048baa9..fecd77e1f 100644 --- a/wadsrc/static/actors/strife/spectral.txt +++ b/wadsrc/static/actors/strife/spectral.txt @@ -198,6 +198,7 @@ ACTOR SpectralLightningV1 : SpectralLightningDeathShort Height 24 Damage 100 Projectile + DamageType "SpectralLow" +SPECTRAL States { From 8435033e08e0a9509cf7fc93b354710b595ae07e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 25 Jan 2010 08:10:48 +0000 Subject: [PATCH 216/241] - fixed: M_DrawSlider did not print the correct value if the slider's minimum was not 0 or the value was clamped. SVN r2134 (trunk) --- src/m_options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_options.cpp b/src/m_options.cpp index 5e95f1a5e..8b49e96ac 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -1560,10 +1560,10 @@ static void M_DrawSlider (int x, int y, double min, double max, double cur,int f double range; range = max - min; - cur = clamp(cur, min, max) - min; + double ccur = clamp(cur, min, max) - min; M_DrawConText(CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); - M_DrawConText(CR_ORANGE, x + int((5 + ((cur * 78) / range)) * CleanXfac_1), y, "\x13"); + M_DrawConText(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), y, "\x13"); if (fracdigits >= 0) { From 02909bd71cb884f5782f4c36dd52c6abf6106fc3 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 25 Jan 2010 23:18:52 +0000 Subject: [PATCH 217/241] - Fixed: AlienSpectre3 had lost its first level Sigil immunity. SVN r2135 (trunk) --- wadsrc/static/actors/strife/alienspectres.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/actors/strife/alienspectres.txt b/wadsrc/static/actors/strife/alienspectres.txt index f0da99f28..bdd30d8e4 100644 --- a/wadsrc/static/actors/strife/alienspectres.txt +++ b/wadsrc/static/actors/strife/alienspectres.txt @@ -109,6 +109,7 @@ ACTOR AlienSpectre3 : AlienSpectre1 76 Radius 24 +SPAWNCEILING DropItem "Sigil3" + DamageFactor "SpectralLow", 0 states { Spawn: From 5125e11d25118f230cfdc700ddf541140ec029f9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 26 Jan 2010 05:11:04 +0000 Subject: [PATCH 218/241] - Do not call midiOutSetVolume() when playing with the "Microsoft GS Wavetable Synth" on Vista and above, because it doesn't do what you expect. SVN r2136 (trunk) --- src/sound/music_win_mididevice.cpp | 78 ++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index 6a55855f3..151728662 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -41,6 +41,10 @@ #include "doomdef.h" #include "m_swap.h" +#ifndef __GNUC__ +#include +#endif + // MACROS ------------------------------------------------------------------ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -49,6 +53,8 @@ // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +static bool IgnoreMIDIVolume(UINT id); + // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -100,11 +106,18 @@ int WinMIDIDevice::Open(void (*callback)(UINT, void *, DWORD, DWORD), void *user if (err == MMSYSERR_NOERROR) { - // Set master volume to full, if the device allows it on this interface. - VolumeWorks = (MMSYSERR_NOERROR == midiOutGetVolume((HMIDIOUT)MidiOut, &SavedVolume)); - if (VolumeWorks) + if (IgnoreMIDIVolume(DeviceID)) { - VolumeWorks &= (MMSYSERR_NOERROR == midiOutSetVolume((HMIDIOUT)MidiOut, 0xffffffff)); + VolumeWorks = false; + } + else + { + // Set master volume to full, if the device allows it on this interface. + VolumeWorks = (MMSYSERR_NOERROR == midiOutGetVolume((HMIDIOUT)MidiOut, &SavedVolume)); + if (VolumeWorks) + { + VolumeWorks &= (MMSYSERR_NOERROR == midiOutSetVolume((HMIDIOUT)MidiOut, 0xffffffff)); + } } } } @@ -391,4 +404,61 @@ void CALLBACK WinMIDIDevice::CallbackFunc(HMIDIOUT hOut, UINT uMsg, DWORD_PTR dw } } +//========================================================================== +// +// IgnoreMIDIVolume +// +// Should we ignore this MIDI device's volume control even if it works? +// +// Under Windows Vista and up, when using the standard "Microsoft GS +// Wavetable Synth", midiOutSetVolume() will affect the application's audio +// session volume rather than the volume for just the MIDI stream. At first, +// I thought I could get around this by enumerating the streams in the +// audio session to find the MIDI device's stream to set its volume +// manually, but there doesn't appear to be any way to enumerate the +// individual streams in a session. Consequently, we'll just assume the MIDI +// device gets created at full volume like we want. (Actual volume changes +// are done by sending MIDI channel volume messages to the stream, not +// through midiOutSetVolume().) +// +// This is using VC++'s __uuidof extension instead of the the CLSID_ and +// IID_ definitions because I couldn't figure out why it wasn't finding them +// when linking, and __uuidof circumvents that problem. I'd also be +// surprised if w32api includes any WASAPI stuff any time soon, so it's no +// big loss making this VC++-specific for the time being +// +//========================================================================== + +static bool IgnoreMIDIVolume(UINT id) +{ +#ifndef __GNUC__ + MIDIOUTCAPS caps; + + if (MMSYSERR_NOERROR == midiOutGetDevCaps(id, &caps, sizeof(caps))) + { + // The Microsoft GS Wavetable Synth advertises itself as MOD_SWSYNTH with a VOLUME control. + // If the one we're using doesn't match that, we don't need to bother checking the name. + if (caps.wTechnology == MOD_SWSYNTH && (caps.dwSupport & MIDICAPS_VOLUME)) + { + if (strncmp(caps.szPname, "Microsoft GS", 12) == 0) + { + IMMDeviceEnumerator *enumerator; + + // Now try to create an IMMDeviceEnumerator interface. If it succeeds, + // we know we're using the new audio stack introduced with Vista and + // should ignore this MIDI device's volume control. + if (SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, + __uuidof(IMMDeviceEnumerator), (void**)&enumerator)) + && enumerator != NULL) + { + enumerator->Release(); + return true; + } + } + } + } +#endif + return false; +} + #endif From 3f140c0549970700d9dd55af73b20ae522221161 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 28 Jan 2010 23:46:38 +0000 Subject: [PATCH 219/241] - fixed: The line ID arg of Plane_Align was not handled in the wrong place. It was also missing from actionspecials.h and the UDMF spec. SVN r2138 (trunk) --- specs/udmf_zdoom.txt | 1 + src/actionspecials.h | 2 +- src/p_setup.cpp | 6 +++++- src/p_slopes.cpp | 1 - 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index fe64a8021..15512d9fb 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -192,6 +192,7 @@ Note: All fields default to false unless mentioned otherwise. 208: TranslucentLine, arg0 (arg0 must be preserved) 1: Polyobj_StartLine, arg3 5: Polyobj_ExplicitLine, arg4 + 181: Plane_Align, arg2 215: Teleport_Line, arg0 222: Scroll_Texture_Model, arg0 (arg0 must be preserved) diff --git a/src/actionspecials.h b/src/actionspecials.h index e1df60c16..9ee03d477 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -150,7 +150,7 @@ DEFINE_SPECIAL(Thing_Hate, 177, 2, 3, 3) DEFINE_SPECIAL(Thing_ProjectileAimed, 178, 4, 5, 5) DEFINE_SPECIAL(ChangeSkill, 179, 1, 1, 1) DEFINE_SPECIAL(Thing_SetTranslation, 180, 2, 2, 2) -DEFINE_SPECIAL(Plane_Align, 181, -1, -1, 2) +DEFINE_SPECIAL(Plane_Align, 181, -1, -1, 3) DEFINE_SPECIAL(Line_Mirror, 182, -1, 0, 0) DEFINE_SPECIAL(Line_AlignCeiling, 183, 2, 2, 2) DEFINE_SPECIAL(Line_AlignFloor, 184, 2, 2, 2) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 100f4bd10..85c958a1d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1702,7 +1702,11 @@ void P_SetLineID (line_t *ld) case Polyobj_ExplicitLine: ld->id = ld->args[4]; break; - + + case Plane_Align: + ld->id = ld->args[2]; + break; + case Static_Init: if (ld->args[1] == Init_SectorLink) ld->id = ld->args[0]; break; diff --git a/src/p_slopes.cpp b/src/p_slopes.cpp index 0f9098733..99dcb71b2 100644 --- a/src/p_slopes.cpp +++ b/src/p_slopes.cpp @@ -548,7 +548,6 @@ void P_SetSlopes () if (lines[i].special == Plane_Align) { lines[i].special = 0; - lines[i].id = lines[i].args[2]; if (lines[i].backsector != NULL) { // args[0] is for floor, args[1] is for ceiling From 1f6c915abfff181cd71376c8f00b1f01c0a1cf1c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 28 Jan 2010 23:50:20 +0000 Subject: [PATCH 220/241] - Fixed: ZDoom no longer reversed the clipping area on drawbar calls with a border. - Fixed: SBarInfo Interpolated aross a new Game. SVN r2139 (trunk) --- src/g_shared/sbarinfo.cpp | 21 +++++++++++++++++++-- src/g_shared/sbarinfo.h | 1 + src/g_shared/sbarinfo_commands.cpp | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index ccc8ff4af..1344ad1c0 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -156,6 +156,7 @@ class SBarInfoCommand virtual void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)=0; virtual void Parse(FScanner &sc, bool fullScreenOffsets)=0; + virtual void Reset() {} virtual void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) {} protected: @@ -235,6 +236,11 @@ class SBarInfoCommandFlowControl : public SBarInfoCommand commands.Push(cmd); } } + void Reset() + { + for(unsigned int i = 0;i < commands.Size();i++) + commands[i]->Reset(); + } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { for(unsigned int i = 0;i < commands.Size();i++) @@ -653,6 +659,12 @@ void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state) } } +void SBarInfo::ResetHuds() +{ + for(int i = 0;i < NUMHUDS;i++) + huds[i]->Reset(); +} + int SBarInfo::newImage(const char *patchname) { if(patchname[0] == '\0' || stricmp(patchname, "nullimage") == 0) @@ -823,7 +835,7 @@ class DSBarInfo : public DBaseStatusBar public: DSBarInfo (SBarInfo *script=NULL) : DBaseStatusBar(script->height), ammo1(NULL), ammo2(NULL), ammocount1(0), ammocount2(0), armor(NULL), - pendingPopup(POP_None), currentPopup(POP_None), lastHud(0), + pendingPopup(POP_None), currentPopup(POP_None), lastHud(-1), lastInventoryBar(NULL), lastPopup(NULL) { this->script = script; @@ -944,6 +956,10 @@ public: if (CPlayer != NULL) { AttachToPlayer (CPlayer); + + // Reset the huds + script->ResetHuds(); + lastHud = -1; // Reset } } @@ -970,7 +986,8 @@ public: if (lastPopup != NULL) lastPopup->Tick(NULL, this, false); } - script->huds[lastHud]->Tick(NULL, this, false); + if(lastHud != -1) + script->huds[lastHud]->Tick(NULL, this, false); if(lastInventoryBar != NULL && CPlayer->inventorytics > 0) lastInventoryBar->Tick(NULL, this, false); } diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index b10eb440b..6fd7b1f0c 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -97,6 +97,7 @@ struct SBarInfo int GetGameType() { return gameType; } void ParseSBarInfo(int lump); void ParseMugShotBlock(FScanner &sc, FMugShotState &state); + void ResetHuds(); int newImage(const char* patchname); void Init(); SBarInfo(); diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 063f9ac3a..a19471464 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -725,6 +725,10 @@ class CommandDrawNumber : public CommandDrawString else if(value == ARMOR) interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; } + void Reset() + { + drawValue = 0; + } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { int num = valueArgument; @@ -1887,6 +1891,10 @@ class CommandDrawBar : public SBarInfoCommand { sc.MustGetToken(TK_IntConst); border = sc.Number; + + // Flip the direction since it represents the area to clip + if(border != 0) + reverse = !reverse; } sc.MustGetToken(';'); @@ -1895,6 +1903,10 @@ class CommandDrawBar : public SBarInfoCommand else if(type == ARMOR) interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; } + void Reset() + { + drawValue = 0; + } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { fixed_t value = 0; @@ -2300,6 +2312,10 @@ class CommandDrawGem : public SBarInfoCommand else interpolationSpeed = script->interpolateArmor ? script->armorInterpolationSpeed : interpolationSpeed; } + void Reset() + { + drawValue = 0; + } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { goalValue = armor ? statusBar->armor->Amount : statusBar->CPlayer->mo->health; From 787c16301ca95362921d62096d0ae279eaa0abca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 28 Jan 2010 23:51:56 +0000 Subject: [PATCH 221/241] - Fixed SBarInfo problem with hexenarmor. SVN r2140 (trunk) --- src/g_shared/sbarinfo_commands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index a19471464..eac92d86c 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -169,7 +169,7 @@ class CommandDrawImage : public SBarInfoCommand if (item != NULL) texture = TexMan[item->Icon]; } - else if(type == HEXENARMOR_ARMOR || type == HEXENARMOR_SHIELD || type == HEXENARMOR_AMULET || type == HEXENARMOR_ARMOR) + else if(type == HEXENARMOR_ARMOR || type == HEXENARMOR_SHIELD || type == HEXENARMOR_HELM || type == HEXENARMOR_AMULET) { int armorType = type - HEXENARMOR_ARMOR; From 0997c608f2dc1e7c74ef2ccbb15e92647a283b88 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 09:17:44 +0000 Subject: [PATCH 222/241] - added a secret sector color to automap overlay. - added a score display to both alt HUD and sbarinfo. - simplified code for AltHud status values display. SVN r2141 (trunk) --- src/am_map.cpp | 4 +- src/g_shared/sbarinfo_commands.cpp | 6 +++ src/g_shared/shared_hud.cpp | 75 ++++++++++++------------------ src/m_options.cpp | 2 + 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index da5a495ef..8f6871f99 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -167,6 +167,7 @@ CVAR (Color, am_ovtelecolor, 0xffff00, CVAR_ARCHIVE); CVAR (Color, am_intralevelcolor, 0x0000ff, CVAR_ARCHIVE); CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE); CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE); +CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); @@ -770,7 +771,8 @@ static void AM_initColors (bool overlayed) { YourColor.FromCVar (am_ovyourcolor); WallColor.FromCVar (am_ovwallcolor); - SecretSectorColor = SecretWallColor = WallColor; + SecretWallColor = WallColor; + SecretSectorColor.FromCVar (am_ovsecretsectorcolor); ThingColor_Item.FromCVar (am_ovthingcolor_item); ThingColor_Friend.FromCVar (am_ovthingcolor_friend); ThingColor_Monster.FromCVar (am_ovthingcolor_monster); diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index eac92d86c..ebc6dad46 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -599,6 +599,8 @@ class CommandDrawNumber : public CommandDrawString value = AMMO1; else if(sc.Compare("ammo2")) value = AMMO2; + else if(sc.Compare("score")) + value = SCORE; else if(sc.Compare("ammo")) //request the next string to be an ammo type { value = AMMO; @@ -798,6 +800,9 @@ class CommandDrawNumber : public CommandDrawString case SECRETS: num = level.found_secrets; break; + case SCORE: + num = statusBar->CPlayer->mo->Score; + break; case TOTALSECRETS: num = level.total_secrets; break; @@ -925,6 +930,7 @@ class CommandDrawNumber : public CommandDrawString POWERUPTIME, AIRTIME, SELECTEDINVENTORY, + SCORE, CONSTANT }; diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index b2efa1d13..87664c204 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -67,6 +67,7 @@ CVAR (Bool, hud_showsecrets, true,CVAR_ARCHIVE); // Show secrets on HUD CVAR (Bool, hud_showmonsters, true,CVAR_ARCHIVE); // Show monster stats on HUD CVAR (Bool, hud_showitems, false,CVAR_ARCHIVE); // Show item stats on HUD CVAR (Bool, hud_showstats, false, CVAR_ARCHIVE); // for stamina and accuracy. +CVAR (Bool, hud_showscore, false, CVAR_ARCHIVE); // for user maintained score CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green @@ -98,6 +99,7 @@ static FTexture * fragpic; // Frags icon static FTexture * invgems[4]; // Inventory arrows static int hudwidth, hudheight; // current width/height for HUD display +static int statspace; void AM_GetPosition(fixed_t & x, fixed_t & y); @@ -198,37 +200,35 @@ static void DrawHudNumber(FFont *font, int color, int num, int x, int y, int tra // //=========================================================================== +static void DrawStatLine(int x, int &y, const char *prefix, const char *string) +{ + y -= SmallFont->GetHeight()-1; + screen->DrawText(SmallFont, hudcolor_statnames, x, y, prefix, + DTA_KeepRatio, true, + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + + screen->DrawText(SmallFont, hudcolor_stats, x+statspace, y, string, + DTA_KeepRatio, true, + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); +} + static void DrawStatus(player_t * CPlayer, int x, int y) { char tempstr[50]; - int space; + + if (hud_showscore) + { + mysnprintf(tempstr, countof(tempstr), "%i ", CPlayer->mo->Score); + DrawStatLine(x, y, "Sc:", tempstr); + } if (hud_showstats) { - space = SmallFont->StringWidth("Ac: "); - - y -= SmallFont->GetHeight()-1; - screen->DrawText(SmallFont, hudcolor_statnames, x, y, "Ac:", - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - mysnprintf(tempstr, countof(tempstr), "%i ", CPlayer->accuracy); - screen->DrawText(SmallFont, hudcolor_stats, x+space, y, tempstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - - y-=SmallFont->GetHeight()-1; - screen->DrawText(SmallFont, hudcolor_statnames, x, y, "St:", - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - + DrawStatLine(x, y, "Ac:", tempstr); mysnprintf(tempstr, countof(tempstr), "%i ", CPlayer->stamina); - screen->DrawText(SmallFont, hudcolor_stats, x+space, y, tempstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DrawStatLine(x, y, "St:", tempstr); } - else - space=SmallFont->StringWidth("K: "); if (!deathmatch) { @@ -236,41 +236,20 @@ static void DrawStatus(player_t * CPlayer, int x, int y) // work in cooperative hub games if (hud_showsecrets) { - y -= SmallFont->GetHeight()-1; - screen->DrawText(SmallFont, hudcolor_statnames, x, y, "S:", - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - mysnprintf(tempstr, countof(tempstr), "%i/%i ", multiplayer? CPlayer->secretcount : level.found_secrets, level.total_secrets); - screen->DrawText(SmallFont, hudcolor_stats, x+space, y, tempstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DrawStatLine(x, y, "S:", tempstr); } if (hud_showitems) { - y -= SmallFont->GetHeight()-1; - screen->DrawText(SmallFont, hudcolor_statnames, x, y, "I:", - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - mysnprintf(tempstr, countof(tempstr), "%i/%i ", multiplayer? CPlayer->itemcount : level.found_items, level.total_items); - screen->DrawText(SmallFont, hudcolor_stats, x+space, y, tempstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DrawStatLine(x, y, "I:", tempstr); } if (hud_showmonsters) { - y -= SmallFont->GetHeight()-1; - screen->DrawText(SmallFont, hudcolor_statnames, x, y, "K:", - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); - mysnprintf(tempstr, countof(tempstr), "%i/%i ", multiplayer? CPlayer->killcount : level.killed_monsters, level.total_monsters); - screen->DrawText(SmallFont, hudcolor_stats, x+space, y, tempstr, - DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DrawStatLine(x, y, "K:", tempstr); } } } @@ -931,6 +910,10 @@ void HUD_InitHud() KeyTypes.Clear(); UnassignedKeyTypes.Clear(); + statspace = SmallFont->StringWidth("Ac:"); + + + // Now read custom icon overrides int lump, lastlump = 0; diff --git a/src/m_options.cpp b/src/m_options.cpp index 8b49e96ac..9c8199757 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -609,6 +609,7 @@ EXTERN_CVAR (Color, am_ovtelecolor) EXTERN_CVAR (Color, am_intralevelcolor) EXTERN_CVAR (Color, am_interlevelcolor) EXTERN_CVAR (Color, am_secretsectorcolor) +EXTERN_CVAR (Color, am_ovsecretsectorcolor) EXTERN_CVAR (Color, am_thingcolor_friend) EXTERN_CVAR (Color, am_thingcolor_monster) EXTERN_CVAR (Color, am_thingcolor_item) @@ -644,6 +645,7 @@ static menuitem_t MapColorsItems[] = { { colorpicker, "2-sided walls (overlay)", {&am_ovotherwallscolor},{0}, {0}, {0}, {0} }, { colorpicker, "Not-yet-seen walls (overlay)", {&am_ovunseencolor}, {0}, {0}, {0}, {0} }, { colorpicker, "Teleporter (overlay)", {&am_ovtelecolor}, {0}, {0}, {0}, {0} }, + { colorpicker, "Secret sector (overlay)", {&am_ovsecretsectorcolor}, {0}, {0}, {0}, {0} }, { colorpicker, "Actors (overlay) (for cheat)", {&am_ovthingcolor}, {0}, {0}, {0}, {0} }, { colorpicker, "Monsters (overlay) (for cheat)", {&am_ovthingcolor_monster}, {0}, {0}, {0}, {0} }, { colorpicker, "Friends (overlay) (for cheat)", {&am_ovthingcolor_friend}, {0}, {0}, {0}, {0} }, From 0246f2bf4de58b3df3e45c15c4c962f0e6e49228 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 13:08:52 +0000 Subject: [PATCH 223/241] - fixed: Being resurrected by an Arch Vile did not restore flags5 and flags6 to the defaults. SVN r2142 (trunk) --- src/actor.h | 1 - src/p_enemy.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/actor.h b/src/actor.h index d870e8df2..6e8af2498 100644 --- a/src/actor.h +++ b/src/actor.h @@ -909,7 +909,6 @@ public: return GetClass()->ActorInfo->FindState(2, names, exact); } - bool HasSpecialDeathStates () const; }; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 4b80d5b68..eff234af9 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2579,6 +2579,8 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) corpsehit->flags2 = info->flags2; corpsehit->flags3 = info->flags3; corpsehit->flags4 = info->flags4; + corpsehit->flags5 = info->flags5; + corpsehit->flags6 = info->flags6; corpsehit->health = info->health; corpsehit->target = NULL; corpsehit->lastenemy = NULL; From 24a12a04b4108f2e35b93b155c6dd2c599705e6d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 13:48:44 +0000 Subject: [PATCH 224/241] - added a minimum threshold for damage thrust to avoid micro-velocities being set for actors. - fixed: Strife's Oracle is not a living thing and needs the NOBLOOD flag. - fixed: Chex Quest's finale pic was wrong. SVN r2143 (trunk) --- src/p_interaction.cpp | 3 +++ src/p_map.cpp | 4 ++-- wadsrc/static/actors/strife/oracle.txt | 1 + wadsrc/static/mapinfo/chex.txt | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 075d978bc..24d6cfd83 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1062,6 +1062,9 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage thrust = FLOAT2FIXED(fltthrust); + // Don't apply ultra-small damage thrust + if (thrust < FRACUNIT/100) thrust = 0; + // make fall forwards sometimes if ((damage < 40) && (damage > target->health) && (target->z - origin->z > 64*FRACUNIT) diff --git a/src/p_map.cpp b/src/p_map.cpp index b7f8c04f1..7a9d9da19 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4356,8 +4356,8 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b velz *= 0.8f; } angle_t ang = R_PointToAngle2 (bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; - thing->velx += fixed_t (finecosine[ang] * thrust); - thing->vely += fixed_t (finesine[ang] * thrust); + thing->velx += FLOAT2FIXED (finecosine[ang] * thrust); + thing->vely += FLOAT2FIXED (finesine[ang] * thrust); if (bombdodamage) thing->velz += (fixed_t)velz; // this really doesn't work well } diff --git a/wadsrc/static/actors/strife/oracle.txt b/wadsrc/static/actors/strife/oracle.txt index 594eb83af..ca25f2526 100644 --- a/wadsrc/static/actors/strife/oracle.txt +++ b/wadsrc/static/actors/strife/oracle.txt @@ -10,6 +10,7 @@ ACTOR Oracle 199 Height 56 Monster +NOTDMATCH + +NOBLOOD DamageFactor "Fire", 0.5 DamageFactor "SpectralLow", 0 MaxDropoffHeight 32 diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index 2f2f494fb..edfbc8a46 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -11,7 +11,7 @@ gameinfo chatsound = "misc/chat2" finalemusic = "$MUSIC_VICTOR" finaleflat = "FLOOR4_8" - finalepage = "HELP2", "VICTORY2", "ENDPIC" + finalepage = "CREDIT", "VICTORY2", "ENDPIC" infopage = "HELP1", "CREDIT" quitsound = "menu/quit1" borderflat = "FLOOR7_2" From a5e1fe690662e4d4ad7a572bbc0fdee6abed9673 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 14:35:52 +0000 Subject: [PATCH 225/241] - fixed: Sector_SetWind and Sector_SetCurrent were not usable in scripts called from a line. - added Gez's A_Mushroom extension. SVN r2144 (trunk) --- src/g_doom/a_fatso.cpp | 23 ++++++++++++++++------- src/p_lnspec.cpp | 4 ++-- src/p_local.h | 4 ++-- src/p_mobj.cpp | 17 +++++++++-------- src/p_spec.cpp | 3 +++ wadsrc/static/actors/constants.txt | 1 + 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index 484df58ca..73ae4e2b5 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -118,7 +118,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3) // Original idea: Linguica // -AActor * P_OldSpawnMissile(AActor * source, AActor * dest, const PClass *type); +AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const PClass *type); + +enum +{ + MSF_Standard = 0, + MSF_Classic = 1, + MSF_DontHurt = 2, +}; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) { @@ -134,11 +141,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) if (n == 0) n = self->Damage; // GetMissileDamage (0, 1); if (spawntype == NULL) spawntype = PClass::FindClass("FatShot"); - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true); + P_RadiusAttack (self, self->target, 128, 128, self->DamageType, !(flags & MSF_DontHurt)); P_CheckSplash(self, 128<target : self; target->height = self->height; for (i = -n; i <= n; i += 8) { @@ -148,13 +156,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) target->x = self->x + (i << FRACBITS); // Aim in many directions from source target->y = self->y + (j << FRACBITS); target->z = self->z + (P_AproxDistance(i,j) * vrange); // Aim up fairly high - if (flags == 0 && (!(self->state->DefineFlags & SDF_DEHACKED) || !(i_compatflags & COMPATF_MUSHROOM))) - { - mo = P_SpawnMissile (self, target, spawntype); // Launch fireball + if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options + (flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM))) + { // Use old function for MBF compatibility + mo = P_OldSpawnMissile (self, master, target, spawntype); } - else + else // Use normal function { - mo = P_OldSpawnMissile (self, target, spawntype); // Launch fireball + mo = P_SpawnMissile(self, target, spawntype, master); } if (mo != NULL) { // Slow it down a bit diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index bb94ccea1..818de725a 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1853,7 +1853,7 @@ void AdjustPusher (int tag, int magnitude, int angle, DPusher::EPusher type) FUNC(LS_Sector_SetWind) // Sector_SetWind (tag, amount, angle) { - if (ln || arg3) + if (arg3) return false; AdjustPusher (arg0, arg1, arg2, DPusher::p_wind); @@ -1863,7 +1863,7 @@ FUNC(LS_Sector_SetWind) FUNC(LS_Sector_SetCurrent) // Sector_SetCurrent (tag, amount, angle) { - if (ln || arg3) + if (arg3) return false; AdjustPusher (arg0, arg1, arg2, DPusher::p_current); diff --git a/src/p_local.h b/src/p_local.h index fe3b84cd3..1707db26e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -111,9 +111,9 @@ void P_RipperBlood (AActor *mo, AActor *bleeder); int P_GetThingFloorType (AActor *thing); void P_ExplodeMissile (AActor *missile, line_t *explodeline, AActor *target); -AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type); +AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type, AActor* owner = NULL); AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const PClass *type); -AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true); +AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true, AActor *owner = NULL); AActor *P_SpawnMissileAngle (AActor *source, const PClass *type, angle_t angle, fixed_t velz); AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type, angle_t angle, fixed_t velz, fixed_t speed); AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t velz); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7db992019..b589e061e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5042,10 +5042,10 @@ static fixed_t GetDefaultSpeed(const PClass *type) // //--------------------------------------------------------------------------- -AActor *P_SpawnMissile (AActor *source, AActor *dest, const PClass *type) +AActor *P_SpawnMissile (AActor *source, AActor *dest, const PClass *type, AActor *owner) { return P_SpawnMissileXYZ (source->x, source->y, source->z + 32*FRACUNIT, - source, dest, type); + source, dest, type, true, owner); } AActor *P_SpawnMissileZ (AActor *source, fixed_t z, AActor *dest, const PClass *type) @@ -5054,7 +5054,7 @@ AActor *P_SpawnMissileZ (AActor *source, fixed_t z, AActor *dest, const PClass * } AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, - AActor *source, AActor *dest, const PClass *type, bool checkspawn) + AActor *source, AActor *dest, const PClass *type, bool checkspawn, AActor *owner) { if (dest == NULL) { @@ -5071,7 +5071,10 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *th = Spawn (type, x, y, z, ALLOW_REPLACE); P_PlaySpawnSound(th, source); - th->target = source; // record missile's originator + + // record missile's originator + if (owner) th->target = owner; + else th->target = source; float speed = (float)(th->Speed); @@ -5114,14 +5117,14 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, return (!checkspawn || P_CheckMissileSpawn (th)) ? th : NULL; } -AActor * P_OldSpawnMissile(AActor * source, AActor * dest, const PClass *type) +AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const PClass *type) { angle_t an; fixed_t dist; AActor *th = Spawn (type, source->x, source->y, source->z + 4*8*FRACUNIT, ALLOW_REPLACE); P_PlaySpawnSound(th, source); - th->target = source; // record missile's originator + th->target = owner; // record missile's originator th->angle = an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); an >>= ANGLETOFINESHIFT; @@ -5250,8 +5253,6 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, AActor *linetarget; int vrange = nofreeaim? ANGLE_1*35 : 0; - // Note: NOAUTOAIM is implemented only here, and not in the hitscan or rail attack functions. - // That is because it is only justified for projectiles affected by gravity, not for other attacks. if (source && source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM)) { // Keep exactly the same angle and pitch as the player's own aim diff --git a/src/p_spec.cpp b/src/p_spec.cpp index c78e4ebe3..6ac57bb4a 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -2059,11 +2059,13 @@ static void P_SpawnPushers () case Sector_SetWind: // wind for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; ) new DPusher (DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s); + l->special = 0; break; case Sector_SetCurrent: // current for (s = -1; (s = P_FindSectorFromTag (l->args[0],s)) >= 0 ; ) new DPusher (DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s); + l->special = 0; break; case PointPush_SetForce: // push/pull @@ -2092,6 +2094,7 @@ static void P_SpawnPushers () } } } + l->special = 0; break; } } diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index fda6fd5a6..0e1f8f903 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -70,6 +70,7 @@ const int RGF_NOPIERCING = 2; // Flags for A_Mushroom const int MSF_Standard = 0; const int MSF_Classic = 1; +const int MSF_DontHurt = 2; // Flags for A_Blast const int BF_USEAMMO = 1; From 8a2271218007e4af1a26c984fc7c7a142672f395 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 14:49:15 +0000 Subject: [PATCH 226/241] - fixed: Rocket trail particle positioning only worked when the rocket was moving. SVN r2145 (trunk) --- src/p_effect.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 8a4d5bb1f..0ecb53798 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -235,7 +235,18 @@ static void MakeFountain (AActor *actor, int color1, int color2) void P_RunEffect (AActor *actor, int effects) { - angle_t moveangle = R_PointToAngle2(0,0,actor->velx,actor->vely); + angle_t moveangle; + + // 512 is the limit below which R_PointToAngle2 does no longer returns usable values. + if (abs(actor->velx) > 512 || abs(actor->vely) > 512) + { + moveangle = R_PointToAngle2(0,0,actor->velx,actor->vely); + } + else + { + moveangle = actor->angle; + } + particle_t *particle; int i; From fc2f95da0e3d1f7125bb6114cbb1f9f03950ba38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 19:28:41 +0000 Subject: [PATCH 227/241] - revert accidental commit. SVN r2146 (trunk) --- src/p_map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 7a9d9da19..b7f8c04f1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4356,8 +4356,8 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b velz *= 0.8f; } angle_t ang = R_PointToAngle2 (bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; - thing->velx += FLOAT2FIXED (finecosine[ang] * thrust); - thing->vely += FLOAT2FIXED (finesine[ang] * thrust); + thing->velx += fixed_t (finecosine[ang] * thrust); + thing->vely += fixed_t (finesine[ang] * thrust); if (bombdodamage) thing->velz += (fixed_t)velz; // this really doesn't work well } From 3e8435e22cfaaef9d16326af24a64baf9522ffc9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2010 22:53:37 +0000 Subject: [PATCH 228/241] - added Gez's Plane_Copy submission with some extensions and improvements. This line special is the last of the slope creation methods being processed so it can copy any other type of slope. SVN r2147 (trunk) --- src/actionspecials.h | 2 +- src/p_lnspec.cpp | 28 ++++++++++----------- src/p_setup.cpp | 2 ++ src/p_slopes.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/actionspecials.h b/src/actionspecials.h index 9ee03d477..5405b2542 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -106,7 +106,7 @@ DEFINE_SPECIAL(Light_Glow, 114, 4, 4, 4) DEFINE_SPECIAL(Light_Flicker, 115, 3, 3, 3) DEFINE_SPECIAL(Light_Strobe, 116, 5, 5, 5) DEFINE_SPECIAL(Light_Stop, 117, 1, 1, 1) - +DEFINE_SPECIAL(Plane_Copy, 118, -1, -1, 5) DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3) DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 818de725a..db2214ec7 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3088,7 +3088,7 @@ lnSpecFunc LineSpecials[256] = /* 115 */ LS_Light_Flicker, /* 116 */ LS_Light_Strobe, /* 117 */ LS_Light_Stop, - /* 118 */ LS_NOP, + /* 118 */ LS_NOP, // Plane_Copy /* 119 */ LS_Thing_Damage, /* 120 */ LS_Radius_Quake, /* 121 */ LS_NOP, // Line_SetIdentification @@ -3111,22 +3111,22 @@ lnSpecFunc LineSpecials[256] = /* 138 */ LS_Floor_Waggle, /* 139 */ LS_Thing_SpawnFacing, /* 140 */ LS_Sector_ChangeSound, - /* 141 */ LS_NOP, // 141 Music_Pause // [BC] Start - /* 142 */ LS_NOP, // 142 Music_Change - /* 143 */ LS_NOP, // 143 Player_RemoveItem - /* 144 */ LS_NOP, // 144 Player_GiveItem + /* 141 */ LS_NOP, + /* 142 */ LS_NOP, + /* 143 */ LS_NOP, + /* 144 */ LS_NOP, /* 145 */ LS_NOP, // 145 Player_SetTeam - /* 146 */ LS_NOP, // 146 Player_SetLeader - /* 147 */ LS_NOP, // 147 Team_InitFP - /* 148 */ LS_NOP, // 148 TeleportAll - /* 149 */ LS_NOP, // 149 TeleportAll_NoFog - /* 150 */ LS_NOP, // 150 Team_GiveFP - /* 151 */ LS_NOP, // 151 Team_UseFP + /* 146 */ LS_NOP, + /* 147 */ LS_NOP, + /* 148 */ LS_NOP, + /* 149 */ LS_NOP, + /* 150 */ LS_NOP, + /* 151 */ LS_NOP, /* 152 */ LS_NOP, // 152 Team_Score - /* 153 */ LS_NOP, // 153 Team_Init + /* 153 */ LS_NOP, // 153 Team_GivePoints /* 154 */ LS_Teleport_NoStop, - /* 155 */ LS_NOP, // 155 Team_RemoveItem - /* 156 */ LS_NOP, // 156 Team_GiveItem // [BC] End + /* 155 */ LS_NOP, + /* 156 */ LS_NOP, /* 157 */ LS_NOP, // SetGlobalFogParameter // in GZDoom /* 158 */ LS_NOP, // FS_Execute in GZDoom /* 159 */ LS_NOP, // Sector_SetPlaneReflection in GZDoom diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 85c958a1d..202cca409 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -68,6 +68,7 @@ void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt); void P_SetSlopes (); +void P_CopySlopes(); void BloodCrypt (void *data, int key, int len); void P_ClearUDMFKeys(); @@ -3628,6 +3629,7 @@ void P_SetupLevel (char *lumpname, int position) { // [RH] Spawn slope creating things first. P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()]); + P_CopySlopes(); // Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials P_Spawn3DFloors(); diff --git a/src/p_slopes.cpp b/src/p_slopes.cpp index 99dcb71b2..3ebaef144 100644 --- a/src/p_slopes.cpp +++ b/src/p_slopes.cpp @@ -118,9 +118,8 @@ static void P_SlopeLineToPoint (int lineid, fixed_t x, fixed_t y, fixed_t z, boo // //=========================================================================== -static void P_CopyPlane (int tag, fixed_t x, fixed_t y, bool copyCeil) +static void P_CopyPlane (int tag, sector_t *dest, bool copyCeil) { - sector_t *dest = P_PointInSector (x, y); sector_t *source; int secnum; size_t planeofs; @@ -144,6 +143,12 @@ static void P_CopyPlane (int tag, fixed_t x, fixed_t y, bool copyCeil) *(secplane_t *)((BYTE *)dest + planeofs) = *(secplane_t *)((BYTE *)source + planeofs); } +static void P_CopyPlane (int tag, fixed_t x, fixed_t y, bool copyCeil) +{ + sector_t *dest = P_PointInSector (x, y); + P_CopyPlane(tag, dest, copyCeil); +} + //=========================================================================== // // P_SetSlope @@ -571,3 +576,52 @@ void P_SetSlopes () } } +//=========================================================================== +// +// P_CopySlopes +// +//=========================================================================== + +void P_CopySlopes() +{ + for (int i = 0; i < numlines; i++) + { + if (lines[i].special == Plane_Copy) + { + // The args are used for the tags of sectors to copy: + // args[0]: front floor + // args[1]: front ceiling + // args[2]: back floor + // args[3]: back ceiling + // args[4]: copy slopes from one side of the line to the other. + lines[i].special = 0; + for (int s = 0; s < (lines[i].backsector ? 4 : 2); s++) + { + if (lines[i].args[s]) + P_CopyPlane(lines[i].args[s], + (s & 2 ? lines[i].backsector : lines[i].frontsector), s & 1); + } + + if (lines[i].backsector != NULL) + { + if ((lines[i].args[4] & 3) == 1) + { + lines[i].backsector->floorplane = lines[i].frontsector->floorplane; + } + else if ((lines[i].args[4] & 3) == 2) + { + lines[i].frontsector->floorplane = lines[i].backsector->floorplane; + } + if ((lines[i].args[4] & 12) == 4) + { + lines[i].backsector->ceilingplane = lines[i].frontsector->ceilingplane; + } + else if ((lines[i].args[4] & 12) == 8) + { + lines[i].frontsector->ceilingplane = lines[i].backsector->ceilingplane; + } + } + } + } +} + From d2891682ae5f05b6a2592ac387c173368a34ce8a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2010 07:26:50 +0000 Subject: [PATCH 229/241] - fixed positioning of player mugshot background on Doom status bar. SVN r2148 (trunk) --- wadsrc/static/sbarinfo/doom.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/sbarinfo/doom.txt b/wadsrc/static/sbarinfo/doom.txt index fc0784311..cb7f75cb6 100644 --- a/wadsrc/static/sbarinfo/doom.txt +++ b/wadsrc/static/sbarinfo/doom.txt @@ -107,7 +107,7 @@ statusbar normal // Standard Doom Status bar } gamemode cooperative, deathmatch, teamgame { - drawimage translatable "STFBANY", 144, 169; + drawimage translatable "STFBANY", 143, 169; } drawselectedinventory alternateonempty, INDEXFONT, 143, 168 { From 1aa39baa4a05ff2ffd2a5362d350bf41a6199291 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 2 Feb 2010 04:38:15 +0000 Subject: [PATCH 230/241] - Fixed: "Animation in ANIMATED has only one frame" message was missing a newline. SVN r2149 (trunk) --- src/r_anim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_anim.cpp b/src/r_anim.cpp index 2ae96f58e..7daeafd83 100644 --- a/src/r_anim.cpp +++ b/src/r_anim.cpp @@ -179,7 +179,7 @@ void R_InitPicAnims (void) if (pic1 == pic2) { // This animation only has one frame. Skip it. (Doom aborted instead.) - Printf ("Animation %s in ANIMATED has only one frame", anim_p + 10); + Printf ("Animation %s in ANIMATED has only one frame\n", anim_p + 10); continue; } From ecb9d2f24bc2758ff71c08b402e1cf6beda75bb0 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 2 Feb 2010 05:19:43 +0000 Subject: [PATCH 231/241] - Fixed: Closing doors early would never restart the sound sequence if it was manually placed. SVN r2150 (trunk) --- src/p_doors.cpp | 4 +++- src/s_sndseq.cpp | 43 ++++++++++++++++++++++++++++++------------- src/s_sndseq.h | 1 + 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 78fb9e576..29ec1fc6b 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -422,7 +422,9 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, // [RH] If this sector doesn't have a specific sound // attached to it, start the door close sequence. // Otherwise, just let the current one continue. - if (sec->seqType == -1) + // FIXME: This should be check if the sound sequence has separate up/down + // paths, not if it was manually set. + if (sec->seqType == -1 || SN_CheckSequence(sec, CHAN_CEILING) == NULL) { door->DoorSound (false); } diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 93474ae19..381a27866 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -952,6 +952,33 @@ static int FindSequence (FName seqname) return -1; } +//========================================================================== +// +// SN_CheckSequence +// +// Returns the sound sequence playing in the sector on the given channel, +// if any. +// +//========================================================================== + +DSeqNode *SN_CheckSequence(sector_t *sector, int chan) +{ + for (DSeqNode *node = DSeqNode::FirstSequence(); node; ) + { + DSeqNode *next = node->NextSequence(); + if (node->Source() == sector) + { + assert(node->IsKindOf(RUNTIME_CLASS(DSeqSectorNode))); + if ((static_cast(node)->Channel & 7) == chan) + { + return node; + } + } + node = next; + } + return NULL; +} + //========================================================================== // // SN_StopSequence @@ -965,20 +992,10 @@ void SN_StopSequence (AActor *actor) void SN_StopSequence (sector_t *sector, int chan) { - DSeqNode *node; - - for (node = DSeqNode::FirstSequence(); node; ) + DSeqNode *node = SN_CheckSequence(sector, chan); + if (node != NULL) { - DSeqNode *next = node->NextSequence(); - if (node->Source() == sector) - { - assert(node->IsKindOf(RUNTIME_CLASS(DSeqSectorNode))); - if ((static_cast(node)->Channel & 7) == chan) - { - node->StopAndDestroy (); - } - } - node = next; + node->StopAndDestroy(); } } diff --git a/src/s_sndseq.h b/src/s_sndseq.h index 434dccb6f..efadc0565 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -85,6 +85,7 @@ DSeqNode *SN_StartSequence (sector_t *sector, int chan, const char *name, int mo DSeqNode *SN_StartSequence (sector_t *sec, int chan, FName seqname, int modenum); DSeqNode *SN_StartSequence (FPolyObj *poly, int sequence, seqtype_t type, int modenum, bool nostop=false); DSeqNode *SN_StartSequence (FPolyObj *poly, const char *name, int modenum); +DSeqNode *SN_CheckSequence (sector_t *sector, int chan); void SN_StopSequence (AActor *mobj); void SN_StopSequence (sector_t *sector, int chan); void SN_StopSequence (FPolyObj *poly); From 4310b239f491396cd0193e51689e5f7037c347ee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 6 Feb 2010 15:31:26 +0000 Subject: [PATCH 232/241] - Added Gez's submission for Eternity-style skybox definitions. SVN r2151 (trunk) --- src/actionspecials.h | 2 +- src/g_shared/a_skies.cpp | 59 ++++++++ src/p_linkedsectors.cpp | 12 +- src/p_setup.cpp | 44 ++++-- src/p_spec.cpp | 27 ++-- src/p_switch.cpp | 2 +- wadsrc/static/actors/shared/skies.txt | 3 + wadsrc/static/xlat/eternity.txt | 192 ++++++++++++++++++++++++++ 8 files changed, 316 insertions(+), 25 deletions(-) create mode 100644 wadsrc/static/xlat/eternity.txt diff --git a/src/actionspecials.h b/src/actionspecials.h index 5405b2542..5d9471fec 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -159,7 +159,7 @@ DEFINE_SPECIAL(Sector_SetCeilingPanning, 186, 5, 5, 5) DEFINE_SPECIAL(Sector_SetFloorPanning, 187, 5, 5, 5) DEFINE_SPECIAL(Sector_SetCeilingScale, 188, 5, 5, 5) DEFINE_SPECIAL(Sector_SetFloorScale, 189, 5, 5, 5) -DEFINE_SPECIAL(Static_Init, 190, -1, -1, 3) +DEFINE_SPECIAL(Static_Init, 190, -1, -1, 4) DEFINE_SPECIAL(SetPlayerProperty, 191, 3, 3, 3) DEFINE_SPECIAL(Ceiling_LowerToHighestFloor, 192, 2, 2, 2) DEFINE_SPECIAL(Ceiling_LowerInstant, 193, 3, 3, 3) diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 8ca0937c2..0454498e2 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -35,6 +35,7 @@ #include "actor.h" #include "a_sharedglobal.h" #include "p_local.h" +#include "p_lnspec.h" // arg0 = Visibility*4 for this skybox @@ -88,6 +89,64 @@ void ASkyViewpoint::Destroy () Super::Destroy(); } +// For an RR compatible linedef based definition. This searches the viewpoint's sector +// for a skybox line special, gets its tag and transfers the skybox to all tagged sectors. +class ASkyCamCompat : public ASkyViewpoint +{ + DECLARE_CLASS (ASkyCamCompat, ASkyViewpoint) +public: + void BeginPlay (); +}; + +IMPLEMENT_CLASS (ASkyCamCompat) + +extern FTextureID skyflatnum; + +void ASkyCamCompat::BeginPlay () +{ + if (Sector == NULL) + { + Printf("Sector not initialized for SkyCamCompat\n"); + Sector = P_PointInSector(x, y); + } + if (Sector) + { + line_t * refline = NULL; + for (short i = 0; i < Sector->linecount; i++) + { + refline = Sector->lines[i]; + if (refline->special == Sector_SetPortal && refline->args[1] == 2) + { + // We found the setup linedef for this skybox, so let's use it for our init. + int skybox_id = refline->args[0]; + + // Then, change the alpha + alpha = refline->args[4]; + + // Finally, skyboxify all tagged sectors + // This involves changing their texture to the sky flat, because while + // EE works with any texture for its skybox portals, ZDoom doesn't. + for (int secnum =-1; (secnum = P_FindSectorFromTag (skybox_id, secnum)) != -1; ) + { + // plane: 0=floor, 1=ceiling, 2=both + if (refline->args[2] == 1 || refline->args[2] == 2) + { + sectors[secnum].CeilingSkyBox = this; + sectors[secnum].SetTexture(sector_t::ceiling, skyflatnum, false); + } + if (refline->args[2] == 0 || refline->args[2] == 2) + { + sectors[secnum].FloorSkyBox = this; + sectors[secnum].SetTexture(sector_t::floor, skyflatnum, false); + } + } + } + } + } + // Do not call the SkyViewpoint's super method because it would trash our setup + AActor::BeginPlay(); +} + //--------------------------------------------------------------------------- // arg0 = tid of matching SkyViewpoint diff --git a/src/p_linkedsectors.cpp b/src/p_linkedsectors.cpp index b932eb0aa..2d06bc043 100644 --- a/src/p_linkedsectors.cpp +++ b/src/p_linkedsectors.cpp @@ -354,12 +354,22 @@ void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling) { int movetype = ld->args[3]; + // [GZ] Eternity does allow the attached sector to be the control sector, + // this permits elevator effects (ceiling attached to floors), so instead + // of checking whether the two sectors are the same, we prevent a plane + // from being attached to itself. This should be enough to do the trick. + if (ld->frontsector == control) + { + if (ceiling) movetype &= ~LINK_CEILING; + else movetype &= ~LINK_FLOOR; + } + // Make sure we have only valid combinations movetype &= LINK_FLAGMASK; if ((movetype & LINK_FLOORMIRROR) == LINK_FLOORMIRRORFLAG) movetype &= ~LINK_FLOORMIRRORFLAG; if ((movetype & LINK_CEILINGMIRROR) == LINK_CEILINGMIRRORFLAG) movetype &= ~LINK_CEILINGMIRRORFLAG; - if (movetype != 0 && ld->frontsector != NULL && ld->frontsector != control) + if (movetype != 0 && ld->frontsector != NULL)//&& ld->frontsector != control) Needs to be allowed! { AddSingleSector(scrollplane, ld->frontsector, movetype); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 202cca409..0afb49be4 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3418,8 +3418,24 @@ void P_SetupLevel (char *lumpname, int position) else { // We need translators only for Doom format maps. - // If none has been defined in a map use the game's default. - P_LoadTranslator(!level.info->Translator.IsEmpty()? level.info->Translator.GetChars() : gameinfo.translator.GetChars()); + const char *translator; + + if (!level.info->Translator.IsEmpty()) + { + // The map defines its own translator. + translator = level.info->Translator.GetChars(); + } + else + { + // Has the user overridden the game's default translator with a commandline parameter? + translator = Args->CheckValue("-xlat"); + if (translator == NULL) + { + // Use the game's default. + translator = gameinfo.translator.GetChars(); + } + } + P_LoadTranslator(translator); } CheckCompatibility(map); @@ -3561,17 +3577,23 @@ void P_SetupLevel (char *lumpname, int position) } else if (!map->isText) // regular nodes are not supported for text maps { - times[7].Clock(); - P_LoadSubsectors (map); - times[7].Unclock(); + // If all 3 node related lumps are empty there's no need to output a message. + // This just means that the map has no nodes and the engine is supposed to build them. + if (map->Size(ML_SEGS) != 0 || map->Size(ML_SSECTORS) != 0 || map->Size(ML_NODES) != 0) + { + times[7].Clock(); + P_LoadSubsectors (map); + times[7].Unclock(); - times[8].Clock(); - if (!ForceNodeBuild) P_LoadNodes (map); - times[8].Unclock(); + times[8].Clock(); + if (!ForceNodeBuild) P_LoadNodes (map); + times[8].Unclock(); - times[9].Clock(); - if (!ForceNodeBuild) P_LoadSegs (map); - times[9].Unclock(); + times[9].Clock(); + if (!ForceNodeBuild) P_LoadSegs (map); + times[9].Unclock(); + } + else ForceNodeBuild = true; } else ForceNodeBuild = true; } diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 6ac57bb4a..95bee9eb3 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -912,19 +912,20 @@ void P_SetupPortals() } } -inline void SetPortal(sector_t *sector, INTBOOL ceiling, AStackPoint *portal) +inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal) { - if (ceiling) + // plane: 0=floor, 1=ceiling, 2=both + if (plane > 0) { if (sector->CeilingSkyBox == NULL) sector->CeilingSkyBox = portal; } - else + if (plane == 2 || plane == 0) { if (sector->FloorSkyBox == NULL) sector->FloorSkyBox = portal; } } -void P_SpawnPortal(line_t *line, int sectortag, INTBOOL ceiling, int alpha) +void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha) { for (int i=0;iv1->x + line->v2->x) >> 1; @@ -954,7 +955,7 @@ void P_SpawnPortal(line_t *line, int sectortag, INTBOOL ceiling, int alpha) for (int s=-1; (s = P_FindSectorFromTag(sectortag,s)) >= 0;) { - SetPortal(§ors[s], ceiling, reference); + SetPortal(§ors[s], plane, reference); } for (int j=0;j= 0;) { - SetPortal(§ors[s], ceiling, reference); + SetPortal(§ors[s], plane, reference); } } } @@ -1211,8 +1212,12 @@ void P_SpawnSpecials (void) case Sector_SetPortal: // arg 0 = sector tag - // arg 1 = type (must be 0, other values reserved for later use) - // arg 2 = 0:floor, 1:ceiling + // arg 1 = type + // - 0: normal (handled here) + // - 1: copy (handled by the portal they copy) + // - 2: EE-style skybox (handled by the camera object) + // other values reserved for later use + // arg 2 = 0:floor, 1:ceiling, 2:both // arg 3 = 0: anchor, 1: reference line // arg 4 = for the anchor only: alpha if (lines[i].args[1] == 0 && lines[i].args[3] == 0) diff --git a/src/p_switch.cpp b/src/p_switch.cpp index f3b642b05..b7eeb784d 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -535,7 +535,7 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) // to keep compatibility with Eternity's implementation. if (!P_GetMidTexturePosition(line, sideno, &checktop, &checkbot)) return false; - return user->z < checktop || user->z + user->height > checkbot; + return user->z < checktop && user->z + user->height > checkbot; } else { diff --git a/wadsrc/static/actors/shared/skies.txt b/wadsrc/static/actors/shared/skies.txt index d652f5505..3b531d527 100644 --- a/wadsrc/static/actors/shared/skies.txt +++ b/wadsrc/static/actors/shared/skies.txt @@ -14,6 +14,9 @@ ACTOR SkyPicker 9081 native +DONTSPLASH } +Actor SkyCamCompat : SkyViewpoint 9083 native +{ +} ACTOR StackPoint : SkyViewpoint native { diff --git a/wadsrc/static/xlat/eternity.txt b/wadsrc/static/xlat/eternity.txt new file mode 100644 index 000000000..ad270beb4 --- /dev/null +++ b/wadsrc/static/xlat/eternity.txt @@ -0,0 +1,192 @@ +#include "xlat/doom.txt" + +// xlat file for Eternity levels. +// Many specials are unsupported, especially portal stuff. +// Some unsupported linedefs wouldn't be hard to add to ZDoom, +// or are already there but implemented differently. Others are +// practically impossible, or aren't worth the effort. + +define Unsupported (0) + +// The tag for such a line is actually a key to find, in an ExtraData lump +// indicated for the current level by the EMAPINFO lump, what line special +// to actually use. This is how parameterized linedefs are used by Eternity +// in the Doom format. "xlating" this would thus be quite complicated... +270 = 0, Unsupported() // "ExtraDataSpecial" + +// These two are standard MBF specials, no need to redefine them, they're in xlat/doom.txt +// 271 = 0, Static_Init (tag, Init_TransferSky, 0) +// 272 = 0, Static_Init (tag, Init_TransferSky, 1) + +// Small script starters. Small is considered deprecated now anyway. +273 = 0, Unsupported() // "WR_StartScript_1S" +274 = 0, Unsupported() // "W1_StartScript" +275 = 0, Unsupported() // "W1_StartScript_1S" +276 = 0, Unsupported() // "SR_StartScript" +277 = 0, Unsupported() // "S1_StartScript" +278 = 0, Unsupported() // "GR_StartScript" +279 = 0, Unsupported() // "G1_StartScript" +280 = 0, Unsupported() // "WR_StartScript" + +// 3D mid-textures +281 = 0, Sector_Attach3DMidtex(tag, 0, 0) // "3DMidTex_MoveWithFloor" +282 = 0, Sector_Attach3DMidtex(tag, 0, 1) // "3DMidTex_MoveWithCeiling" + +// Plane portals are not supported in ZDoom, though they probably wouldn't be too hard to implement. +283 = 0, Unsupported() // "Portal_PlaneCeiling" +284 = 0, Unsupported() // "Portal_PlaneFloor" +285 = 0, Unsupported() // "Portal_PlaneFloorCeiling" +286 = 0, Unsupported() // "Portal_HorizonCeiling" +287 = 0, Unsupported() // "Portal_HorizonFloor" +288 = 0, Unsupported() // "Portal_HorizonFloorCeiling" +289 = 0, Unsupported() // "Portal_LineTransfer" + +// Skybox portals +290 = 0, Sector_SetPortal(tag, 2, 1, 1, 0) // "Portal_SkyboxCeiling" +291 = 0, Sector_SetPortal(tag, 2, 0, 1, 0) // "Portal_SkyboxFloor" +292 = 0, Sector_SetPortal(tag, 2, 2, 1, 0) // "Portal_SkyboxFloorCeiling" + +// Sector specials +293 = 0, Sector_SetWind(tag, 0, 0, 1) // "TransferHereticWind" +294 = 0, Sector_SetCurrent(tag, 0, 0, 1) // "TransferHereticCurrent" + +// Anchored portals -- Sector_SetPortal needs to allow to set both floor and ceiling, though. +295 = 0, Sector_SetPortal(tag, 0, 1, 1, 0) // "Portal_AnchoredCeiling" +296 = 0, Sector_SetPortal(tag, 0, 0, 1, 0) // "Portal_AnchoredFloor" +297 = 0, Sector_SetPortal(tag, 0, 2, 1, 0) // "Portal_AnchoredFloorCeiling" +298 = 0, Sector_SetPortal(tag, 0, 1, 0, 0) // "Portal_AnchorLine" +299 = 0, Sector_SetPortal(tag, 0, 0, 0, 0) // "Portal_AnchorLineFloor" + +// Parameterized linedefs +// They are never used directly in Doom-format maps. Instead, it passes through ExtraData and 270. +// Hexen format is incomplete; and Quasar wants to use ZDoom-compatible special values for UDMF. +// So there is no need to bother with them and they are listed only for completeness' sake. +/* + 300: "Door_Raise" + 301: "Door_Open" + 302: "Door_Close" + 303: "Door_CloseWaitOpen" + 304: "Door_WaitRaise" + 305: "Door_WaitClose" + 306: "Floor_RaiseToHighest" + 307: "Floor_LowerToHighest" + 308: "Floor_RaiseToLowest" + 309: "Floor_LowerToLowest" + 310: "Floor_RaiseToNearest" + 311: "Floor_LowerToNearest" + 312: "Floor_RaiseToLowestCeiling" + 313: "Floor_LowerToLowestCeiling" + 314: "Floor_RaiseToCeiling" + 315: "Floor_RaiseByTexture" + 316: "Floor_LowerByTexture" + 317: "Floor_RaiseByValue" + 318: "Floor_LowerByValue" + 319: "Floor_MoveToValue" + 320: "Floor_RaiseInstant" + 321: "Floor_LowerInstant" + 322: "Floor_ToCeilingInstant" + 323: "Ceiling_RaiseToHighest" + 324: "Ceiling_ToHighestInstant" + 325: "Ceiling_RaiseToNearest" + 326: "Ceiling_LowerToNearest" + 327: "Ceiling_RaiseToLowest" + 328: "Ceiling_LowerToLowest" + 329: "Ceiling_RaiseToHighestFloor" + 330: "Ceiling_LowerToHighestFloor" + 331: "Ceiling_ToFloorInstant" + 332: "Ceiling_LowerToFloor" + 333: "Ceiling_RaiseByTexture" + 334: "Ceiling_LowerByTexture" + 335: "Ceiling_RaiseByValue" + 336: "Ceiling_LowerByValue" + 337: "Ceiling_MoveToValue" + 338: "Ceiling_RaiseInstant" + 339: "Ceiling_LowerInstant" + 340: "Stairs_BuildUpDoom" + 341: "Stairs_BuildDownDoom" + 342: "Stairs_BuildUpDoomSync" + 343: "Stairs_BuildDownDoomSync" +*/ + +// Two-way portals are not supported yet either +344 = 0, Unsupported() // "Portal_TwowayCeiling" +345 = 0, Unsupported() // "Portal_TwowayFloor" +346 = 0, Unsupported() // "Portal_TwowayAnchorLine" +347 = 0, Unsupported() // "Portal_TwowayAnchorLineFloor" + +// More parameterized linedefs +/* + 348: "Polyobj_StartLine" + 349: "Polyobj_ExplicitLine" + 350: "Polyobj_DoorSlide" + 351: "Polyobj_DoorSwing" + 352: "Polyobj_Move" + 353: "Polyobj_OR_Move" + 354: "Polyobj_RotateRight" + 355: "Polyobj_OR_RotateRight" + 356: "Polyobj_RotateLeft" + 357: "Polyobj_OR_RotateLeft" +*/ + +// Eternity's linked portals, vertical link version (floor-to-ceiling) +358 = 0, Unsupported() // "Portal_LinkedCeiling" +359 = 0, Unsupported() // "Portal_LinkedFloor" +360 = 0, Unsupported() // "Portal_LinkedAnchorLine" +361 = 0, Unsupported() // "Portal_LinkedAnchorLineFloor" + +// Even more parameterized linedefs +/* + 362: "Pillar_Build" + 363: "Pillar_BuildAndCrush" + 364: "Pillar_Open" + 365: "ACS_Execute" + 366: "ACS_Suspend" + 367: "ACS_Terminate" + 368: "Light_RaiseByValue" + 369: "Light_LowerByValue" + 370: "Light_ChangeToValue" + 371: "Light_Fade" + 372: "Light_Glow" + 373: "Light_Flicker" + 374: "Light_Strobe" + 375: "Radius_Quake" +*/ + +// Eternity's linked portals, horizontal link version (wall-to-wall) +376 = 0, Unsupported() // "Portal_LinkedLineToLine" +377 = 0, Unsupported() // "Portal_LinkedLineToLineAnchor" + +// The famous Hexen linedef +// 378 = Line_SetIdentification + +// Attached sectors == linked sectors; However, the implementation in Eternity +// is based on front sectors of tagged lines, not on sector tags. So instead +// of Sector_SetLink, we pass through Static_Init to translate those. +379 = 0, Static_Init(tag, 3, 1) // "Attach_SetCeilingControl" +380 = 0, Static_Init(tag, 3, 0) // "Attach_SetFloorControl" +381 = 0, Static_Init(0, 3, 0, 1) // "Attach_FloorToControl" +382 = 0, Static_Init(0, 3, 1, 2) // "Attach_CeilingToControl" +383 = 0, Static_Init(0, 3, 0, 5) // "Attach_MirrorFloorToControl" +384 = 0, Static_Init(0, 3, 0, 10) // "Attach_MirrorCeilingToControl" + +// Attach tagged portal to front sector +385 = 0, Sector_SetPortal(0, 1, 2, tag) // "Apply_PortalToFrontsector" + +// Slopes! +386 = 0, Plane_Align (1, 0) // "Slope_FrontsectorFloor" +387 = 0, Plane_Align (0, 1) // "Slope_FrontsectorCeiling" +388 = 0, Plane_Align (1, 1) // "Slope_FrontsectorFloorAndCeiling" +389 = 0, Plane_Align (2, 0) // "Slope_BacksectorFloor" +390 = 0, Plane_Align (0, 2) // "Slope_BacksectorCeiling" +391 = 0, Plane_Align (2, 2) // "Slope_BacksectorFloorAndCeiling" +392 = 0, Plane_Align (2, 1) // "Slope_BackFloorAndFrontCeiling" +393 = 0, Plane_Align (1, 2) // "Slope_BackCeilingAndFrontFloor" +394 = 0, Plane_Copy (tag, 0) // "Slope_FrontFloorToTaggedSlope" +395 = 0, Plane_Copy (0, tag) // "Slope_FrontCeilingToTaggedSlope" +396 = 0, Plane_Copy(tag, tag)// "Slope_FrontFloorAndCeilingToTaggedSlope" + +// Last parameterized linedefs +// 397 = Floor_Waggle +// 398 = Thing_Spawn +// 399 = Thing_SpawnNoFog +// 400 = Teleport_EndGame From 12a819cf7ca317c13a6902fe35c49267ab55474c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 7 Feb 2010 08:22:23 +0000 Subject: [PATCH 233/241] - fixed GCC compile error in A_Mushroom. SVN r2152 (trunk) --- src/g_doom/a_fatso.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index 73ae4e2b5..2a824a072 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -146,7 +146,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) // Now launch mushroom cloud AActor *target = Spawn("Mapspot", 0, 0, 0, NO_REPLACE); // We need something to aim at. - AActor *master = (flags & MSF_DontHurt) ? self->target : self; + AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self; target->height = self->height; for (i = -n; i <= n; i += 8) { From 113a438b0110d22beb2a2e1e8ab0d64c019a8801 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 11 Feb 2010 17:10:01 +0000 Subject: [PATCH 234/241] - Fixed: Voodoo dolls must not check reactiontime in P_SlideMove. SVN r2153 (trunk) --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index b7f8c04f1..ebcb701f6 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2346,7 +2346,7 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps) hitcount = 3; slidemo = mo; - if (mo->player && mo->reactiontime > 0) + if (mo->player && mo->player->mo == mo && mo->reactiontime > 0) return; // player coming right out of a teleporter. retry: From 33460a315a92d1270fabf1a3335fb4644fa709d3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 12 Feb 2010 22:44:54 +0000 Subject: [PATCH 235/241] - fixed: DefHexenBindings still referred to some of Heretic's items that once were merged with the Hexen variants. SVN r2155 (trunk) --- src/c_bind.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/c_bind.cpp b/src/c_bind.cpp index f7450aaa5..d96b5a742 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -159,8 +159,8 @@ static const FBinding DefHexenBindings[] = { "9", "use ArtiBlastRadius" }, { "8", "use ArtiTeleport" }, { "7", "use ArtiTeleportOther" }, - { "6", "use ArtiEgg" }, - { "5", "use ArtiInvulnerability" }, + { "6", "use ArtiPork" }, + { "5", "use ArtiInvulnerability2" }, { "scroll", "+showscores" }, { NULL } }; From 1df19e63755311497bd2f2b74359262cdf7ce5ed Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 12 Feb 2010 23:18:41 +0000 Subject: [PATCH 236/241] - last fix was incomplete. SVN r2156 (trunk) --- src/gameconfigfile.cpp | 13 +++++++++++-- src/version.h | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 97bdfece9..e9f90a23d 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -271,8 +271,8 @@ void FGameConfigFile::DoGlobalSetup () SetValueForKey ("9", "use ArtiBlastRadius"); SetValueForKey ("8", "use ArtiTeleport"); SetValueForKey ("7", "use ArtiTeleportOther"); - SetValueForKey ("6", "use ArtiEgg"); - SetValueForKey ("5", "use ArtiInvulnerability"); + SetValueForKey ("6", "use ArtiPork"); + SetValueForKey ("5", "use ArtiInvulnerability2"); } } if (last < 204) @@ -330,6 +330,15 @@ void FGameConfigFile::DoGlobalSetup () dim->ResetToDefault (); } } + if (last < 210) + { + if (SetSection ("Hexen.Bindings")) + { + // These 2 were misnamed in earlier versions + SetValueForKey ("6", "use ArtiPork"); + SetValueForKey ("5", "use ArtiInvulnerability2"); + } + } } } } diff --git a/src/version.h b/src/version.h index 769e8005c..de017995c 100644 --- a/src/version.h +++ b/src/version.h @@ -59,7 +59,7 @@ // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to // be able to migrate in FGameConfigFile::DoGlobalSetup(). -#define LASTRUNVERSION "209" +#define LASTRUNVERSION "210" // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. From 784aef89287856605cf42763b9d8322789546a00 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 13 Feb 2010 05:15:32 +0000 Subject: [PATCH 237/241] - Added checks for open and closed scripts sharing the same number to ensure that FBehavior::FindScript() will always return the closed version. See Hexen MAP30 and MAP33. SVN r2157 (trunk) --- src/p_acs.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d79154609..c899c5844 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1396,7 +1396,7 @@ void FBehavior::LoadScriptsDirectory () switch (Format) { case ACS_Old: - scripts.dw = (DWORD *)(Data + ((DWORD *)Data)[1]); + scripts.dw = (DWORD *)(Data + ((DWORD *)Data)[1]); // FIXME: Has this been byte-swapped before-hand? NumScripts = scripts.dw[0]; if (NumScripts != 0) { @@ -1473,6 +1473,25 @@ void FBehavior::LoadScriptsDirectory () if (NumScripts > 1) { qsort (Scripts, NumScripts, sizeof(ScriptPtr), SortScripts); + // Check for duplicates because ACC originally did not enforce + // script number uniqueness across different script types. We + // only need to do this for old format lumps, because the ACCs + // that produce new format lumps won't let you do this. + if (Format == ACS_Old) + { + for (i = 0; i < NumScripts - 1; ++i) + { + if (Scripts[i].Number == Scripts[i+1].Number) + { + Printf("Script %d appears more than once.\n", Scripts[i].Number); + // Make the closed version the first one. + if (Scripts[i+1].Type == SCRIPT_Closed) + { + swap(Scripts[i], Scripts[i+1]); + } + } + } + } } if (Format == ACS_Old) @@ -1589,6 +1608,15 @@ const ScriptPtr *FBehavior::FindScript (int script) const const ScriptPtr *ptr = BinarySearch ((ScriptPtr *)Scripts, NumScripts, &ScriptPtr::Number, (WORD)script); + // If the preceding script has the same number, return it instead. + // See the note by the script sorting above for why. + if (ptr > Scripts) + { + if (ptr[-1].Number == script) + { + ptr--; + } + } return ptr; } From 6ec30761c6c62ca830cac2d1ed787d8eb5361fcd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 13 Feb 2010 08:56:08 +0000 Subject: [PATCH 238/241] - Added Boom's stairbuilding fix when one step couldn't be built due to an active thinker in the sector. This is compatibility optioned with COMPAT_STAIRINDEX. Also added a compatibility setting for Eternal Doom MAP25 which relies on Doom's original broken behavior. - added a few sanity checks for duplicate actor names in DECORATE. ZDoom will now print more warnings and all crash cases should be properly handled but since this is still an error this will not work properly in all circumstances. For example, if you have a duplicate name all classes that inherit from the original definition will not survive a savegame if they reference a state belonging to that class at the point of saving. - Print 'tried to register class more than once' in red to highlight it. - fixed: actors may not replace themselves. SVN r2158 (trunk) --- src/dobjtype.cpp | 3 ++- src/info.cpp | 20 ++++++++++++++++++-- src/p_floor.cpp | 7 ++++++- src/p_mobj.cpp | 4 +++- src/thingdef/thingdef_parse.cpp | 6 ++++++ wadsrc/static/compatibility.txt | 5 +++++ 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2243023d0..63d4a8423 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -37,6 +37,7 @@ #include "actor.h" #include "templates.h" #include "autosegs.h" +#include "v_text.h" TArray PClass::m_RuntimeActors; TArray PClass::m_Types; @@ -185,7 +186,7 @@ void PClass::InsertIntoHash () else if (lexx == 0) { // This type has already been inserted // ... but there is no need whatsoever to make it a fatal error! - Printf ("Tried to register class '%s' more than once.\n", TypeName.GetChars()); + Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars()); break; } else diff --git a/src/info.cpp b/src/info.cpp index 88a0ff7d2..89628e5b7 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -39,6 +39,7 @@ #include "m_fixed.h" #include "c_dispatch.h" #include "d_net.h" +#include "v_text.h" #include "gi.h" @@ -142,15 +143,26 @@ void FActorInfo::StaticSetActorNums () void FActorInfo::RegisterIDs () { + const PClass *cls = PClass::FindClass(Class->TypeName); + bool set = false; + if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype)) { if (SpawnID != 0) { - SpawnableThings[SpawnID] = Class; + SpawnableThings[SpawnID] = cls; + if (cls != Class) + { + Printf(TEXTCOLOR_RED"Spawn ID %d refers to hidden class type '%s'\n", SpawnID, cls->TypeName.GetChars()); + } } if (DoomEdNum != -1) { - DoomEdMap.AddType (DoomEdNum, Class); + DoomEdMap.AddType (DoomEdNum, cls); + if (cls != Class) + { + Printf(TEXTCOLOR_RED"Editor number %d refers to hidden class type '%s'\n", DoomEdNum, cls->TypeName.GetChars()); + } } } // Fill out the list for Chex Quest with Doom's actors @@ -158,6 +170,10 @@ void FActorInfo::RegisterIDs () (GameFilter & GAME_Doom)) { DoomEdMap.AddType (DoomEdNum, Class, true); + if (cls != Class) + { + Printf(TEXTCOLOR_RED"Editor number %d refers to hidden class type '%s'\n", DoomEdNum, cls->TypeName.GetChars()); + } } } diff --git a/src/p_floor.cpp b/src/p_floor.cpp index fd06ff0c1..a03b50583 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -663,7 +663,9 @@ manual_stair: if ( (ok = (tsec != NULL)) ) { - height += stairstep; + // Doom bug: Height was changed before discarding the sector as part of the stairs. + // Needs to be compatibility optioned because some maps (Eternall MAP25) depend on it. + if (i_compatflags & COMPATF_STAIRINDEX) height += stairstep; // if sector's floor already moving, look for another //jff 2/26/98 special lockout condition for retriggering @@ -673,6 +675,9 @@ manual_stair: sec = tsec; continue; } + + if (!(i_compatflags & COMPATF_STAIRINDEX)) height += stairstep; + } newsecnum = (int)(tsec - sectors); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b589e061e..13c75eb99 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2829,9 +2829,11 @@ void AActor::Tick () AActor *onmo; int i; - assert (state != NULL); + //assert (state != NULL); if (state == NULL) { + Printf("Actor of type %s at (%f,%f) left without a state\n", GetClass()->TypeName.GetChars(), + x/65536., y/65536.); Destroy(); return; } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 85930b09c..7712fe43b 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -1072,6 +1072,12 @@ static FActorInfo *ParseActorHeader(FScanner &sc, Baggage *bag) // Get actor name sc.MustGetString (); replaceName = sc.String; + + if (replaceName == typeName) + { + sc.ScriptMessage ("Cannot replace class %s with itself", typeName.GetChars()); + FScriptPosition::ErrorCounter++; + } } // Now, after the actor names have been parsed, it is time to switch to C-mode diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index a4fd90659..685fda086 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -24,6 +24,11 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15 resetplayerspeed } +6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25 +{ + stairs +} + 10E1E2B36302D31AC4AE68C84B5DC457 // Eternal Doom MAP28 { // What's really sad is that I got a separate bug report for this map From 8a843e4b3c646f2410b31e7318b2e3f383bfcecf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 14 Feb 2010 08:13:50 +0000 Subject: [PATCH 239/241] - tempnam would set the errno to 2 on the Mac even though everything seemed to be working as expected. SVN r2161 (trunk) --- tools/updaterevision/updaterevision.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/updaterevision/updaterevision.c b/tools/updaterevision/updaterevision.c index 3f0dce4e9..55e81bc40 100644 --- a/tools/updaterevision/updaterevision.c +++ b/tools/updaterevision/updaterevision.c @@ -30,15 +30,21 @@ int main(int argc, char **argv) // Use svnversion to get the revision number. If that fails, pretend it's // revision 0. Note that this requires you have the command-line svn tools installed. sprintf (run, "svnversion -cn %s", argv[1]); - if ((name = tempnam(NULL, "svnout")) != NULL && - (stream = freopen(name, "w+b", stdout)) != NULL && - system(run) == 0 && - errno == 0 && - fseek(stream, 0, SEEK_SET) == 0 && - fgets(currev, sizeof currev, stream) == currev && - (isdigit(currev[0]) || (currev[0] == '-' && currev[1] == '1'))) + if ((name = tempnam(NULL, "svnout")) != NULL) { - gotrev = 1; +#ifdef __APPLE__ + // tempnam will return errno of 2 even though it is successful for our purposes. + errno = 0; +#endif + if((stream = freopen(name, "w+b", stdout)) != NULL && + system(run) == 0 && + errno == 0 && + fseek(stream, 0, SEEK_SET) == 0 && + fgets(currev, sizeof currev, stream) == currev && + (isdigit(currev[0]) || (currev[0] == '-' && currev[1] == '1'))) + { + gotrev = 1; + } } if (stream != NULL) { From ea11eb9e3d2764bd4980e76f0c8ab827c777977d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 14 Feb 2010 08:24:00 +0000 Subject: [PATCH 240/241] - fixed: The Boom stair fix was done for Hexen stairs but must only be in the code for Doom stairs. SVN r2162 (trunk) --- src/p_floor.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_floor.cpp b/src/p_floor.cpp index a03b50583..00407a36c 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -663,9 +663,7 @@ manual_stair: if ( (ok = (tsec != NULL)) ) { - // Doom bug: Height was changed before discarding the sector as part of the stairs. - // Needs to be compatibility optioned because some maps (Eternall MAP25) depend on it. - if (i_compatflags & COMPATF_STAIRINDEX) height += stairstep; + height += stairstep; // if sector's floor already moving, look for another //jff 2/26/98 special lockout condition for retriggering @@ -676,8 +674,6 @@ manual_stair: continue; } - if (!(i_compatflags & COMPATF_STAIRINDEX)) height += stairstep; - } newsecnum = (int)(tsec - sectors); } @@ -701,13 +697,17 @@ manual_stair: if (!igntxt && tsec->GetTexture(sector_t::floor) != texture) continue; - height += stairstep; + // Doom bug: Height was changed before discarding the sector as part of the stairs. + // Needs to be compatibility optioned because some maps (Eternall MAP25) depend on it. + if (i_compatflags & COMPATF_STAIRINDEX) height += stairstep; // if sector's floor already moving, look for another //jff 2/26/98 special lockout condition for retriggering if (tsec->PlaneMoving(sector_t::floor) || tsec->stairlock) continue; + if (!(i_compatflags & COMPATF_STAIRINDEX)) height += stairstep; + ok = true; break; } From 4b04b944148c08579f1721290cead4c314219204 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 14 Feb 2010 23:59:17 +0000 Subject: [PATCH 241/241] - fixed: The monster pack's Afrit no longer worked. SVN r2165 (trunk) --- src/p_mobj.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 13c75eb99..9a0f9c692 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2232,7 +2232,9 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz) // old code for boss cube disabled //if ((mo->flags & MF_MISSILE) && (!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP))) - if (mo->flags & MF_MISSILE) + // We can't remove this completely because it was abused by some DECORATE definitions + // (e.g. the monster pack's Afrit) + if ((mo->flags & MF_MISSILE) && ((mo->flags & MF_NOGRAVITY) || !(mo->flags & MF_NOCLIP))) { mo->z = mo->floorz; if (mo->BounceFlags & BOUNCE_Floors)