From 1dc13e0ca274cce648b702dfac758620c451810d Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 12 Nov 2008 03:25:48 +0000 Subject: [PATCH] Initial changes for multi-player mode THIS VERSION MAY BE BUGGY!! --- data/sprites/d2climb1.png | Bin 0 -> 464 bytes data/sprites/d2climb2.png | Bin 0 -> 465 bytes data/sprites/d2slam1.png | Bin 0 -> 798 bytes data/sprites/d2slam2.png | Bin 0 -> 758 bytes data/sprites/d2slam3.png | Bin 0 -> 869 bytes data/sprites/d2slam4.png | Bin 0 -> 1062 bytes data/sprites/d2slam5.png | Bin 0 -> 991 bytes data/sprites/d2swim1.png | Bin 0 -> 1303 bytes data/sprites/d2swim2.png | Bin 0 -> 1298 bytes data/sprites/dwarf2die.png | Bin 0 -> 573 bytes data/sprites/dwarf2shoot.png | Bin 0 -> 991 bytes data/sprites/p1ready.png | Bin 0 -> 4917 bytes data/sprites/p2dwarf.png | Bin 0 -> 694 bytes data/sprites/p2dwarffall.png | Bin 0 -> 762 bytes data/sprites/p2dwarfjump.png | Bin 0 -> 761 bytes data/sprites/p2ready.png | Bin 0 -> 3420 bytes data/world1/level1.dat | 3 +- data/world1/level10.dat | 1 + data/world1/level100.dat | 3 +- data/world1/level101.dat | 3 +- data/world1/level102.dat | 1 + data/world1/level103.dat | 1 + data/world1/level104.dat | 1 + data/world1/level105.dat | 3 +- data/world1/level106.dat | 3 +- data/world1/level107.dat | 1 + data/world1/level108.dat | 1 + data/world1/level109.dat | 1 + data/world1/level11.5.dat | 1 + data/world1/level11.dat | 1 + data/world1/level110.dat | 1 + data/world1/level111.dat | 1 + data/world1/level112.dat | 1 + data/world1/level113.dat | 1 + data/world1/level114.dat | 3 +- data/world1/level115.dat | 1 + data/world1/level117.dat | 1 + data/world1/level12.dat | 3 +- data/world1/level13.dat | 1 + data/world1/level14.dat | 1 + data/world1/level2.dat | 3 +- data/world1/level20.dat | 1 + data/world1/level21.dat | 3 +- data/world1/level22.dat | 1 + data/world1/level23.dat | 1 + data/world1/level3.dat | 1 + data/world1/level4.dat | 3 +- data/world1/level40.dat | 1 + data/world1/level403.dat | 3 +- data/world1/level404.dat | 3 +- data/world1/level405.dat | 6 +- data/world1/level406.dat | 3 +- data/world1/level407.dat | 1 + data/world1/level408.dat | 7 +- data/world1/level41.dat | 3 +- data/world1/level411.dat | 1 + data/world1/level412.dat | 5 +- data/world1/level42.dat | 9 +- data/world1/level5.5.dat | 1 + data/world1/level5.dat | 3 +- data/world1/level6.dat | 1 + data/world1/level7.5.dat | 1 + data/world1/level7.dat | 1 + data/world1/level8.5.dat | 1 + data/world1/level8.dat | 3 +- data/world1/level9.dat | 3 +- data/world1/level99.dat | 1 + data/world1/theisland.dat | 5 +- defs.h | 16 +- edit.c | 6 +- globals.h | 5 +- rc.c | 2481 +++++++++++++++++++++++----------- rc.h | 19 +- shared.c | 163 ++- shared.h | 4 + 75 files changed, 1901 insertions(+), 906 deletions(-) create mode 100644 data/sprites/d2climb1.png create mode 100644 data/sprites/d2climb2.png create mode 100644 data/sprites/d2slam1.png create mode 100644 data/sprites/d2slam2.png create mode 100644 data/sprites/d2slam3.png create mode 100644 data/sprites/d2slam4.png create mode 100644 data/sprites/d2slam5.png create mode 100644 data/sprites/d2swim1.png create mode 100644 data/sprites/d2swim2.png create mode 100644 data/sprites/dwarf2die.png create mode 100644 data/sprites/dwarf2shoot.png create mode 100644 data/sprites/p1ready.png create mode 100644 data/sprites/p2dwarf.png create mode 100644 data/sprites/p2dwarffall.png create mode 100644 data/sprites/p2dwarfjump.png create mode 100644 data/sprites/p2ready.png diff --git a/data/sprites/d2climb1.png b/data/sprites/d2climb1.png new file mode 100644 index 0000000000000000000000000000000000000000..0bd143e97f8c5fc74128c31f4d60613032fd957d GIT binary patch literal 464 zcmV;>0WbcEP)vu7=#4p>&b=j=#IXQe4~NPN8$Z1}A+5l^Zne9~ z8{TfVf}H|bBLdJyDS#7d$n~>YFqbOBKE`n=rWw%*(={<6S{hV&&Ng{NM!{ogEz0`< zdMQL~&rA&}DrjGE;$m-a1>x@|}YC`IqwE;Kk-$$c#oosbD z%A7@cU-5@4=-o(2iSoX!ZmJdRs>2defTK0Q`)d6B>}cIQ{A#QgO<66PQn#DGvKL^g z)7$D;Ql)OTXL}DZ5BhFJEv*(!5>l~&Rb8NNLZ`RgGrj>^IDwnNvsvr_0000JL7 literal 0 HcmV?d00001 diff --git a/data/sprites/d2climb2.png b/data/sprites/d2climb2.png new file mode 100644 index 0000000000000000000000000000000000000000..444f0c0e5429b07ef988af126544bd795a7f5318 GIT binary patch literal 465 zcmV;?0WSWDP)d02unW zzwX;f*9u#4R!1Z&c^L%o>3`)P9EYK1`{^8j2?TJ@(Ao-bo2k_inWK8pzsd)<^VRUS zO)NUv#F=qo?W8NE64ECHpoYOnk4`yQ#K84FjlhZpw60}Z=Ar-ZUt>0@>TFWgtyZH) zM^Z@cywO@nDOd){)MzaLB!#*aG0=#CZWQcVjY1D3bx=w_!s~q;2;HAa00000NkvXX Hu0mjfpaQ_; literal 0 HcmV?d00001 diff --git a/data/sprites/d2slam1.png b/data/sprites/d2slam1.png new file mode 100644 index 0000000000000000000000000000000000000000..5935297e0f883d149676e78f4ad96ec7d2d47ef4 GIT binary patch literal 798 zcmV+(1L6FMP)X1^@s6)5{gA00006VoOIv0OSAw z0RIUUHSGWZ010qNS#tmY3x)sy3x)wf2W7Va000McNliru*b58=B?#|aAawu$0;@?x zK~y-)os(TilTjGQfA3uB3ZZVwLc7o))M`Q(5*aHDGISQ?2bkDJMCcYWEduGHi;$5Q zGjv*3UYM&aLc+{-6ItqwshgjW9}r!r6)IYqY~ysXwl?2)bM%K74u|vn&h!7D=amSd z@o}dBr1th#csw2!78Z$*-;3MrAvZUN{DKRkFP_^{Q&O~&uSQK6m6aN4XsoBK)F=QP zLqh=AyX=xmib~jcJ}fLppG{e*QDmOVM5BoTU~cXkpZfbnTU!g~&Ym{}o|iVUNhq5D zffmEUt`-+F^7V^oXsidoW_!xcojU+{-Oz%RMTJ-5hF;`TIO<_U}Nk`U#!rlJkJ9TC=%PJLX zLZD5EXL)&v?9*AwnTde(rU&FU4OLYDTq!JMc5z9%W;Ecewd(fYvn^?NbQJ~ z4XsM3`7e#>SHz9U&%rQzjRkv+Mc&n49ZtL{MS6i+(H?N`V5Rh|d4)Z3zZu>qFI2ij z1(0>!Bs)AhI!nRD1o|%RC+^U#kllSqObmwEYb-%s87Yzg#wR8ioR!%1%PoTp&)gPD zHU&VEWu9r%ZduXE)pY>UyDzi47DM#bb)qEL60Ig`+fVPIG=L{nSVpuWw8h#2m~lvY9S=pBA96)Dufp93Mr&6 znJB3s*kjS6P3epqaT+KTku)Em<|4<^Ho1s=O?)kMZga2q&RmxrxZLmKob$i`|2gL# z`0s3Ta#Y6i=jG>*>tpOzfXiH^nxuhXNF)hcjy}$A!b*L6Jw91}vK)sa6@bOX9{{qo zt%Zw~mu|%7B_$vwD^67)r6e5w20&KUZd%(~qW)H^V8ZM1QB_rm+g(k1dfKKGyA7|$ z2OuoT1n_!%^4$5e^!ECB_qIpl+lc%DV0vcOS~tsFr84?N?Zxw#>e(pAZURJS^DqE2 z{fz*WlpN!-+pV6B%&=yi&BKOYJ`hu;2e2xPBx*5@x(QI-F{8vg|3+XO1(oveE+#jQO-VLD$}nhQZET$ z@JKgDhicV(#=T{+5sC1$y#s)rzJQjQUs1L(xiIP4`cP2y&5tcWB@*D~o9p7qvv%`t zCfAMVfXr>WdR3n3tJRQ5@+*o)wjL;YpC4ODIOukx5z$*5AhDCJ0YIU%L0E}P2o~D! zjJu**cx4QBy8f1WE;zWCi4Pg%4SZ#6?!KkvApDA=0Z|AmM2}K8p=;V5nx~^mg=%5%_c#)9tzB4zH6_~pBK!~4RrSLMxVN~8jkN#i7F+agz2mabxom&7Qgt4<|pxN@**0OW`2CBcnL0FLb2$57}8CAm2Q z;C=r9r!QTM%q)HLmMcUATqG@ZhM<&+0*`AXd32X9tBMNr)WC?)&4_~7(rD>b~ z8a>nmWZb5aD^9s zAAtA=UuG80SulT%R|gad__!_kXr56hFNqfu6TqOp&F(id%Qk1D^v#{M0RDjt-sV6{ z4FFm1JYub*Ld-=A&r5rPI=IU>oiy4mLUkMl6RNWfcDwNucfGSkz(RRRYS^;P*$BX| v#1ldVsiR@oP8d)aZSH5=mWoq@gSxuE_?;E7VaxZS00000NkvXXu0mjfFTRpT literal 0 HcmV?d00001 diff --git a/data/sprites/d2slam4.png b/data/sprites/d2slam4.png new file mode 100644 index 0000000000000000000000000000000000000000..2d6b40878545a62520b14b9b85825c175ce84909 GIT binary patch literal 1062 zcmV+>1ljwEP)WFU8GbZ8({Xk{QrNlj4iWF>9@00W9iL_t(Y$E}uKOjBnV z$A2%h6Brsgks2BlFw0_Hh0SD=s6j!z*rdxc-NhKovR$|;iNW;5nC!x2euNc`7mnV| zkA)ex3k}R_%wi;D#8s0?*_te7xY^PX5~eb!qNVRH+H=}N&yl+9xoX~X-rxWEKhOKT zJpzLWhlkal5)gsFWdO#?0l~cpy#`9dp&?~I_r#3SjZ#3@4uvq0kGTC z!Lp?`G5PnDYoWb{0#0XLwhI8+ytSF);-YLP^8ER;JS%&E0;9#vjhl4vmTfIaDTzj7 z0F;+6rN@6VAM=QO1XNgW?>TI?vh1>n>jQ(&Um{o4N=71o0?6&HZxIMwR)JbPP0Z!x zAV=Vfy?b$0SE~XVc;9w609K2Ir-_92zWc`^-TpqGPXf3VMHrUo$eume7B40ojnek< zMeXFQ-|`Rr-QAi%tJe!4gb+D!OL3yt)1D1&=n-{y zM|JP7?(Eb%FsfZTUK(6ctIIkY4)Ez;G1J7{ih{_7w;oUcN`QF(Q6FV~zj)yB$a{)I znq8JNm0lb05J>Ki<%$)!6(ysVx?sneU=|Ad= z1C;swhD}Zj==P7?w&1Ey z$RfISRAQF7&VigtgVQ1f7a{;8->FK?!QI1VJz%ENE8YxD;HpoUJJ1@E20u@{80(e; z^@y%YFEC;Jha;9`T&SNa1NCPm|3he#{L83C`!x9va0%p;N9)1J?F{_Y+JsPhVN`qd g+r@AL%VrQ+~OY?4a_ZBx`b+a%IAfg<7s>P2cP7m z`QCo#dCv1b-+2$%K+_^kDw~*ioa#w%S_b_ok*rBst(95B5F3 z4}h=3XN{5s=<@n_qPz@1D5Aubk3;18L(?KA>DbsAaq+@M+1S)bY3Vuu78dR@ef>Ja zp&?#sZLk03*6pdH9qetWPg}RQw@F1&NTpKTxf7$NrizM+a)v`g0OTUi>A)&592%m_ z>yrlA$jIlEm2EUzcjf9ek*`Iz4&1Iy+?e}=1D)(hgPm!6 z8a*u{sp|}$`j|JH8qIo(-=AMV+PoP-eN+OtwpRl%7oBHY_%Q*HOeXp8qf>^+lP!M# zLe30ij?w4ZUTu;a>z_OiC4kfEG|Ibx`{Szm=(wuNEC({rTn*}@(khUNx#)b_`YClj z-9fH^fX9RSs4a<|!%U|we!mb_a?iVFK#p*as&5R1!~?Ha&ibomCSfkLMjJ#{$m6PN zroYmvN}wd%qb>r=nF0oUbP9mps;c$JW3i>x9MkpT9`$wLhgpC1v~}Rw2^hFBwjl;xy@A!xvfxEi^K*~L;_r``;riscI4LktbCa*`UlzWW};R$g&hC@ N002ovPDHLkV1hD&+gbns literal 0 HcmV?d00001 diff --git a/data/sprites/d2swim1.png b/data/sprites/d2swim1.png new file mode 100644 index 0000000000000000000000000000000000000000..eb717a3fde2f7dd31ad4152ca7ab0af2a3a0fa47 GIT binary patch literal 1303 zcmV+y1?c*TP)Mmr=?~+q(~PuN1Dp2T$_kKF_`9 zod5Gb=iKu=&`<1kn>kP@$tq09VM~bZ6YI(V5OJINr^0dc_~`027uO97XSr? z`K(&GmggaY664a+Gx&Ty+S?xx6BCWs>tn@=Gyn_+z{;2c)Do`v_H6HYb`4$!IU7UDKavG2rWM(zBRRqigf9XfIs;G;-49e+WC%gOwSI{x#EYyW6- zodP(qJNH(L(;4>e!Muq_cJCohqmk`%PX5HDOP7ZRzISV^uyb$J{GJ`9M0K3j+= zadKh)VZ~PXUhw)D%WH4`ntP&nCV+MS*Qk6xw1Oa|MiE#FwV<2c!2*@LW1zy#J2~PD z;XR&bHH`1Q#~iafZuO@0HCNXyUdH(=SE#stT`@HQ4diNN82`3`ah98AQT1&s>>8-# z^9t=i^s}6FpE6HVtFKL)2)uq`iO}oyV%xl#aed!+WMzuEMMnZV*Go$tbG0&zy83Yd zaY~NwIaM7aZT`pCRraMMqYt!05j?10u0tjZy*HGcb$T@ShXb6`{UQr{^dmlb)3tH|P(ai3sP2Qyor9q@k9ojc&9 z`+e32I6cdL>9>m?Hq^CsV~C#INs2Ag<)|AQRlo5Y3Z`uT#4GwQ9^U7ntILb_hzpfE zn6wN5$3G8-^63MJn!9`Hus4tj>lk8Vy3h)$7EvU+_4Zh|GiQ95+v6id6@qSp7r!9# z^TSZ`ZA0I=s?S9%OiF3HJff@5fiI$IY6{}uAqP!1tpq+QY>eNQ((2!8%- zc0AuZSHGhVzhA(!=4mmX7F0yKA5o}LWB1v8H*blZ(kTG@c-W6;qvTeUt$0N N002ovPDHLkV1l<(UL literal 0 HcmV?d00001 diff --git a/data/sprites/d2swim2.png b/data/sprites/d2swim2.png new file mode 100644 index 0000000000000000000000000000000000000000..76ce1a54c0efe082ad764c6b38ba6e9f442643cb GIT binary patch literal 1298 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 N002ovPDHLkV1nX(%@6

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 literal 0 HcmV?d00001 diff --git a/data/sprites/p2dwarffall.png b/data/sprites/p2dwarffall.png new file mode 100644 index 0000000000000000000000000000000000000000..89286cdf1d8585c2738ec7ffc1a030b6b2421f46 GIT binary patch literal 762 zcmVkl5hnfLpB-uL@{Zy3mm znVFcxCJvUDf3(VR+7$)^enZjN_=He|qr@uTX$Pu0S%t^r24HdV2Y~G9jZ#-z?>DOv zb1@Hq^r@Pdi+SXR>m2}tgU?B&QYZ7q1+py5_82oEe+R6qA#0En#fgWG?2B=@AV0 zWia5E>3H(EU!U7GO!28&8mRC1;NE+}b>{%6tUS)rQe2zcyCqKky)rm*0za0qY}I;l9enj047sm!(eWg0~~H$6Al%mh($ literal 0 HcmV?d00001 diff --git a/data/sprites/p2dwarfjump.png b/data/sprites/p2dwarfjump.png new file mode 100644 index 0000000000000000000000000000000000000000..77840a3d69453b420fd939282457a83c7554f221 GIT binary patch literal 761 zcmV@BM`gEiFYP4mw|1 zxtJ|RbxLfguS-jso|zSj$ScbhuR4MJjeb0yLI5^4egVk-fiPDtx769?h-_t!j=mz9 zOtQJTh1YwEL?THb&;&q5g-^JG8Ls*V!T<~njZji@0)W@!6HL#{ifq*gJ5W>eB{SKo zcp}N%+MkA1@a1c$`O%2WfBg%Rn$F0LDTg0>R+nWm+S(mohWIc}Fg5n#csDIkSSYxia*v_%i?(?-Yq;O#|S@`g+Ql734(-Hz0s_ z_jXN?S*8`>RBF}P+tz_ZY4M;5N}DqS_#xEI>Clg?&H|;+1R%P1?xulkub{C|NCMQh z-r{deVSOW?y;vay$NrHg5cvfv)iv9=z8u30JFTj?PTQf*g?SYrb@=EzV|LE2-j{AK z2rG19UQNweRb(|6ka;nL8Aj>{=h$2T1DJzkhn_mW3-hT*P7%k=kz_8U4!te6NBD?^ rk^qZeRRM6JI&lzWsa@>5%~}5ero19Uc2-z)00000NkvXXu0mjfRrOci literal 0 HcmV?d00001 diff --git a/data/sprites/p2ready.png b/data/sprites/p2ready.png new file mode 100644 index 0000000000000000000000000000000000000000..79d4c94e4e5e18990a08f1ec2695b841bf7c3796 GIT binary patch literal 3420 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 literal 0 HcmV?d00001 diff --git a/data/world1/level1.dat b/data/world1/level1.dat index 592a33b..e11fecd 100644 --- a/data/world1/level1.dat +++ b/data/world1/level1.dat @@ -7,7 +7,6 @@ Use X to jump, Z to catch the rat. Then use Down+Z to slam and kill a monster! endhelp monsters -0 3 19 14 7 19 14 12 19 16 30 15 @@ -28,6 +27,8 @@ monsters 16 35 19 17 36 19 14 17 19 +0 4 19 +134 19 19 endmonsters exitdir 1 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, diff --git a/data/world1/level10.dat b/data/world1/level10.dat index 4c39598..7145b2d 100644 --- a/data/world1/level10.dat +++ b/data/world1/level10.dat @@ -6,6 +6,7 @@ Plants don't move, but can still kill you! endhelp monsters 0 3 28 +134 29 28 23 37 15 18 33 7 18 11 13 diff --git a/data/world1/level100.dat b/data/world1/level100.dat index b1b87e0..e008c89 100644 --- a/data/world1/level100.dat +++ b/data/world1/level100.dat @@ -6,6 +6,8 @@ Snails become dangerous slugs when killed! endhelp monsters 0 18 13 +134 21 13 +23 22 13 49 29 20 49 19 24 1 30 28 @@ -16,7 +18,6 @@ monsters 6 34 7 49 28 7 49 8 7 -23 22 13 14 20 13 17 30 16 17 9 16 diff --git a/data/world1/level101.dat b/data/world1/level101.dat index 4c61fc0..a1fa8e9 100644 --- a/data/world1/level101.dat +++ b/data/world1/level101.dat @@ -5,8 +5,8 @@ help endhelp monsters 0 3 28 +134 36 28 23 21 12 -49 25 28 12 29 8 12 13 8 1 20 12 @@ -51,6 +51,7 @@ monsters 15 17 12 15 29 15 15 11 15 +49 20 28 endmonsters exitdir 2 44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44, diff --git a/data/world1/level102.dat b/data/world1/level102.dat index cb9c592..0c68c2f 100644 --- a/data/world1/level102.dat +++ b/data/world1/level102.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 2 2 +134 4 2 23 31 17 15 12 21 15 14 21 diff --git a/data/world1/level103.dat b/data/world1/level103.dat index 450edc9..e7ba0ed 100644 --- a/data/world1/level103.dat +++ b/data/world1/level103.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 2 13 +134 37 13 23 17 26 60 18 6 60 4 27 diff --git a/data/world1/level104.dat b/data/world1/level104.dat index 11329cb..7b2070e 100644 --- a/data/world1/level104.dat +++ b/data/world1/level104.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 8 5 +134 12 5 23 32 5 49 17 14 6 19 21 diff --git a/data/world1/level105.dat b/data/world1/level105.dat index b287d49..1a1d219 100644 --- a/data/world1/level105.dat +++ b/data/world1/level105.dat @@ -5,7 +5,8 @@ help Drop through the bottom of this level. endhelp monsters -0 8 19 +0 18 19 +134 22 19 23 24 19 7 27 21 7 11 21 diff --git a/data/world1/level106.dat b/data/world1/level106.dat index 4b9bb4c..1f72596 100644 --- a/data/world1/level106.dat +++ b/data/world1/level106.dat @@ -4,7 +4,8 @@ hurryup 60 help endhelp monsters -0 19 11 +0 18 11 +134 20 11 23 19 18 18 33 13 18 4 13 diff --git a/data/world1/level107.dat b/data/world1/level107.dat index 4808ac6..789f4de 100644 --- a/data/world1/level107.dat +++ b/data/world1/level107.dat @@ -6,6 +6,7 @@ Jump in the direction of the logs... endhelp monsters 0 2 22 +134 4 22 23 20 17 12 9 12 1 27 4 diff --git a/data/world1/level108.dat b/data/world1/level108.dat index 4b239f9..bee2cc5 100644 --- a/data/world1/level108.dat +++ b/data/world1/level108.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 19 8 +134 21 8 23 11 8 1 5 28 1 29 20 diff --git a/data/world1/level109.dat b/data/world1/level109.dat index ba88c79..2c7f26f 100644 --- a/data/world1/level109.dat +++ b/data/world1/level109.dat @@ -10,6 +10,7 @@ Send bugs/ideas to rob@nethack.net endhelp monsters 0 5 20 +134 6 20 1 17 27 14 7 20 14 13 20 diff --git a/data/world1/level11.5.dat b/data/world1/level11.5.dat index 3202f65..02b3a06 100644 --- a/data/world1/level11.5.dat +++ b/data/world1/level11.5.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 1 2 +134 5 2 23 19 2 1 13 10 16 6 28 diff --git a/data/world1/level11.dat b/data/world1/level11.dat index 4d5a753..a56886b 100644 --- a/data/world1/level11.dat +++ b/data/world1/level11.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 17 28 +134 21 28 23 19 19 6 23 18 6 14 10 diff --git a/data/world1/level110.dat b/data/world1/level110.dat index e518e50..7110e3f 100644 --- a/data/world1/level110.dat +++ b/data/world1/level110.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 2 23 +134 28 23 23 10 3 12 20 18 1 31 19 diff --git a/data/world1/level111.dat b/data/world1/level111.dat index 2f0b703..2cc36e0 100644 --- a/data/world1/level111.dat +++ b/data/world1/level111.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 3 27 +134 37 27 1 31 15 1 17 15 49 30 27 diff --git a/data/world1/level112.dat b/data/world1/level112.dat index 37ee0c7..602c02b 100644 --- a/data/world1/level112.dat +++ b/data/world1/level112.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 17 25 +134 24 25 23 26 9 18 14 18 18 6 18 diff --git a/data/world1/level113.dat b/data/world1/level113.dat index 21c293c..ac563ef 100644 --- a/data/world1/level113.dat +++ b/data/world1/level113.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 19 28 +134 21 28 23 19 4 6 33 15 1 33 22 diff --git a/data/world1/level114.dat b/data/world1/level114.dat index 2d76626..dff23c0 100644 --- a/data/world1/level114.dat +++ b/data/world1/level114.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 6 4 +0 4 4 +134 5 4 49 30 18 49 16 18 1 36 1 diff --git a/data/world1/level115.dat b/data/world1/level115.dat index 382f9b4..8c81be9 100644 --- a/data/world1/level115.dat +++ b/data/world1/level115.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 20 22 +134 20 2 23 20 9 12 34 14 12 4 14 diff --git a/data/world1/level117.dat b/data/world1/level117.dat index b74cca3..1b92e83 100644 --- a/data/world1/level117.dat +++ b/data/world1/level117.dat @@ -6,6 +6,7 @@ Watch out for water currents! endhelp monsters 0 20 8 +134 22 8 23 21 18 7 33 1 7 4 1 diff --git a/data/world1/level12.dat b/data/world1/level12.dat index c19bb58..d8c7594 100644 --- a/data/world1/level12.dat +++ b/data/world1/level12.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 19 18 +0 18 18 +134 19 18 23 19 21 6 13 9 6 23 9 diff --git a/data/world1/level13.dat b/data/world1/level13.dat index d52bf08..19a9b77 100644 --- a/data/world1/level13.dat +++ b/data/world1/level13.dat @@ -6,6 +6,7 @@ Jump on trampolines to bounce high! endhelp monsters 0 2 24 +134 11 25 23 28 6 6 11 12 6 28 24 diff --git a/data/world1/level14.dat b/data/world1/level14.dat index 77a6a8a..e6cff4b 100644 --- a/data/world1/level14.dat +++ b/data/world1/level14.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 20 28 +134 21 28 23 16 4 6 22 22 6 17 19 diff --git a/data/world1/level2.dat b/data/world1/level2.dat index 4552f85..ba06e0b 100644 --- a/data/world1/level2.dat +++ b/data/world1/level2.dat @@ -8,7 +8,8 @@ Stand on this ledge then slam! Collect all flowers for a bonus! endhelp monsters -0 4 10 +0 2 10 +134 4 10 14 6 10 14 12 10 14 25 10 diff --git a/data/world1/level20.dat b/data/world1/level20.dat index e7acbe8..4c3db7f 100644 --- a/data/world1/level20.dat +++ b/data/world1/level20.dat @@ -6,6 +6,7 @@ Slam monsters into King Rat to damage it! endhelp monsters 0 6 8 +134 33 8 14 11 8 45 16 20 endmonsters diff --git a/data/world1/level21.dat b/data/world1/level21.dat index fb030de..3571005 100644 --- a/data/world1/level21.dat +++ b/data/world1/level21.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 20 17 +0 19 17 +134 20 17 23 14 20 18 26 4 18 7 4 diff --git a/data/world1/level22.dat b/data/world1/level22.dat index 8e2b1cf..02f1eb7 100644 --- a/data/world1/level22.dat +++ b/data/world1/level22.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 4 10 +134 32 8 6 25 12 15 10 18 15 26 18 diff --git a/data/world1/level23.dat b/data/world1/level23.dat index 84b9c07..863714c 100644 --- a/data/world1/level23.dat +++ b/data/world1/level23.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 6 17 +134 7 17 17 26 2 17 22 2 16 24 2 diff --git a/data/world1/level3.dat b/data/world1/level3.dat index af0c863..2a51b33 100644 --- a/data/world1/level3.dat +++ b/data/world1/level3.dat @@ -7,6 +7,7 @@ But don't fall on them! endhelp monsters 0 4 27 +134 33 27 23 20 15 1 19 15 1 5 7 diff --git a/data/world1/level4.dat b/data/world1/level4.dat index 478ff76..9de3bdc 100644 --- a/data/world1/level4.dat +++ b/data/world1/level4.dat @@ -5,7 +5,8 @@ help Drop through bridges with Down+X endhelp monsters -0 24 8 +0 18 8 +134 23 8 23 20 8 1 10 4 1 11 12 diff --git a/data/world1/level40.dat b/data/world1/level40.dat index 79b19aa..c4f7d7b 100644 --- a/data/world1/level40.dat +++ b/data/world1/level40.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 6 8 +134 33 8 128 12 27 endmonsters exitdir 1 diff --git a/data/world1/level403.dat b/data/world1/level403.dat index 8a9c62d..db9c3d9 100644 --- a/data/world1/level403.dat +++ b/data/world1/level403.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 5 25 +134 10 25 1 28 24 7 20 15 7 11 9 @@ -15,7 +16,7 @@ monsters 1 34 16 1 27 28 1 32 20 -132 30 13 488 472 +132 30 13 488 224 488 472 endmonsters exitdir 1 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,0,0,0,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, diff --git a/data/world1/level404.dat b/data/world1/level404.dat index d8e995f..5e0b753 100644 --- a/data/world1/level404.dat +++ b/data/world1/level404.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 6 28 +134 17 28 23 23 14 6 23 5 1 25 20 @@ -29,7 +30,7 @@ monsters 16 25 1 16 22 1 133 32 19 -132 12 26 291 246 +132 12 26 200 432 291 246 endmonsters exitdir 1 57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,57, diff --git a/data/world1/level405.dat b/data/world1/level405.dat index dcda7a8..8407e31 100644 --- a/data/world1/level405.dat +++ b/data/world1/level405.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 3 17 +134 36 17 23 19 9 6 30 2 6 26 20 @@ -35,9 +36,8 @@ monsters 16 31 6 16 5 8 16 35 17 -1 36 17 -132 8 18 239 304 -132 31 18 371 304 +132 8 18 136 304 239 304 +132 31 18 504 304 371 304 endmonsters exitdir 1 57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,57, diff --git a/data/world1/level406.dat b/data/world1/level406.dat index 528e936..f4f6308 100644 --- a/data/world1/level406.dat +++ b/data/world1/level406.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 5 8 +0 4 8 +134 6 8 23 18 9 60 26 25 60 16 27 diff --git a/data/world1/level407.dat b/data/world1/level407.dat index 79b213e..4fd33a4 100644 --- a/data/world1/level407.dat +++ b/data/world1/level407.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 4 22 +134 6 22 23 19 14 133 4 12 133 30 5 diff --git a/data/world1/level408.dat b/data/world1/level408.dat index b65f007..458acec 100644 --- a/data/world1/level408.dat +++ b/data/world1/level408.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 21 14 +0 20 14 +134 22 14 23 21 23 133 34 27 133 12 4 @@ -24,8 +25,8 @@ monsters 17 1 10 17 1 19 17 2 19 -132 30 20 488 336 188 336 188 171 492 171 -132 11 10 184 176 491 176 491 330 186 330 +132 30 20 488 336 488 336 188 336 188 171 492 171 +132 11 10 184 176 184 176 491 176 491 330 186 330 endmonsters exitdir 1 61,61,61,61,61,61,61,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,61,61,61,61,61,61,61,61, diff --git a/data/world1/level41.dat b/data/world1/level41.dat index cf949ae..28200d5 100644 --- a/data/world1/level41.dat +++ b/data/world1/level41.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 7 28 +134 30 28 1 35 13 1 2 13 15 14 5 @@ -27,7 +28,7 @@ monsters 15 33 19 15 24 8 15 23 8 -132 19 6 312 442 +132 19 6 312 112 312 442 15 18 5 15 20 5 16 19 5 diff --git a/data/world1/level411.dat b/data/world1/level411.dat index 7ccb103..2f6ddd8 100644 --- a/data/world1/level411.dat +++ b/data/world1/level411.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 6 2 +134 5 5 23 28 14 60 31 5 60 10 8 diff --git a/data/world1/level412.dat b/data/world1/level412.dat index 9abf913..6fb1568 100644 --- a/data/world1/level412.dat +++ b/data/world1/level412.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 2 3 +0 1 3 +134 2 3 23 6 23 133 33 23 133 24 17 @@ -14,7 +15,7 @@ monsters 133 23 20 133 32 9 133 7 19 -132 2 4 40 80 40 80 40 80 40 80 40 80 40 434 179 434 179 73 322 73 322 434 467 434 467 73 603 73 603 434 468 434 468 73 468 73 323 73 323 434 180 434 180 73 +132 2 4 40 80 40 80 40 80 40 80 40 80 40 80 40 434 179 434 179 73 322 73 322 434 467 434 467 73 603 73 603 434 468 434 468 73 468 73 323 73 323 434 180 434 180 73 6 20 25 6 34 2 15 5 3 diff --git a/data/world1/level42.dat b/data/world1/level42.dat index b26d5fa..9b557f0 100644 --- a/data/world1/level42.dat +++ b/data/world1/level42.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 15 22 +0 16 22 +134 22 22 23 20 9 12 35 9 12 5 9 @@ -26,9 +27,9 @@ monsters 16 5 22 1 29 23 1 7 23 -132 6 20 536 336 -132 37 17 34 288 -132 31 14 137 240 +132 6 20 104 336 536 336 +132 37 17 600 288 34 288 +132 31 14 504 240 137 240 endmonsters exitdir 1 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, diff --git a/data/world1/level5.5.dat b/data/world1/level5.5.dat index 344e0ac..752c4de 100644 --- a/data/world1/level5.5.dat +++ b/data/world1/level5.5.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 1 17 +134 37 17 23 20 15 15 36 9 7 29 1 diff --git a/data/world1/level5.dat b/data/world1/level5.dat index 105ee77..1dce42a 100644 --- a/data/world1/level5.dat +++ b/data/world1/level5.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 4 27 +0 2 28 +134 6 28 23 18 16 1 10 4 1 23 8 diff --git a/data/world1/level6.dat b/data/world1/level6.dat index 60d37c8..3f14e7e 100644 --- a/data/world1/level6.dat +++ b/data/world1/level6.dat @@ -6,6 +6,7 @@ Rolling logs will push you along. endhelp monsters 0 5 25 +134 34 25 23 19 1 17 21 1 15 8 21 diff --git a/data/world1/level7.5.dat b/data/world1/level7.5.dat index 1db0c04..4a4ca3b 100644 --- a/data/world1/level7.5.dat +++ b/data/world1/level7.5.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 4 28 +134 35 28 23 33 28 12 9 3 12 34 3 diff --git a/data/world1/level7.dat b/data/world1/level7.dat index 08f0d16..c92e9e1 100644 --- a/data/world1/level7.dat +++ b/data/world1/level7.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 2 28 +134 34 28 23 27 10 6 21 4 1 7 8 diff --git a/data/world1/level8.5.dat b/data/world1/level8.5.dat index 5da86f9..365ac13 100644 --- a/data/world1/level8.5.dat +++ b/data/world1/level8.5.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 1 20 +134 2 20 23 37 20 6 36 7 6 2 9 diff --git a/data/world1/level8.dat b/data/world1/level8.dat index cc012c0..6d343c7 100644 --- a/data/world1/level8.dat +++ b/data/world1/level8.dat @@ -4,7 +4,8 @@ hurryup 60 help endhelp monsters -0 20 12 +0 19 12 +134 21 12 23 20 12 16 11 5 16 12 9 diff --git a/data/world1/level9.dat b/data/world1/level9.dat index 2ffc97b..4c89210 100644 --- a/data/world1/level9.dat +++ b/data/world1/level9.dat @@ -4,7 +4,8 @@ hurryup 30 help endhelp monsters -0 5 26 +0 2 26 +134 6 26 23 27 6 18 28 26 18 35 3 diff --git a/data/world1/level99.dat b/data/world1/level99.dat index c742443..1fb4c99 100644 --- a/data/world1/level99.dat +++ b/data/world1/level99.dat @@ -5,6 +5,7 @@ help endhelp monsters 0 12 13 +134 16 13 23 17 10 17 1 13 17 7 13 diff --git a/data/world1/theisland.dat b/data/world1/theisland.dat index bf0340e..0ff9418 100644 --- a/data/world1/theisland.dat +++ b/data/world1/theisland.dat @@ -4,7 +4,9 @@ hurryup 90 help endhelp monsters -0 32 7 +0 30 7 +134 32 7 +23 21 6 1 33 23 1 4 23 17 34 23 @@ -42,7 +44,6 @@ monsters 7 12 22 12 10 20 12 30 20 -23 21 6 endmonsters exitdir 1 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, diff --git a/defs.h b/defs.h index 24f7688..c1fdbc3 100644 --- a/defs.h +++ b/defs.h @@ -325,7 +325,7 @@ #define S_SLOPE 2 // Sprite types -#define MAXPTYPES 134 +#define MAXPTYPES 135 #define P_PLAYER 0 #define P_RAT 1 #define P_CHEESE 2 @@ -465,6 +465,7 @@ #define P_RANDOM 131 #define P_PLATFORM 132 #define P_FLY 133 +#define P_PLAYER2 134 #define FLY_FLYTIME 150 @@ -486,6 +487,14 @@ #define CARDFONTY 6 #define CARDFONTSIZE 10 + +// score display +#define P1SCOREX 20 +#define P1LIVESX 20 + +#define SCOREY 7 +#define LIVESY 25 + // card display (in top left of main screen) #define CARDX 20 #define CARDY 55 @@ -702,6 +711,8 @@ typedef struct level_s { struct level_s *prev; int p1x; /* player 1 start pos */ int p1y; + int p2x; /* player 2 start pos */ + int p2y; int powerupx; /* powerup position */ int powerupy; /* powerup position */ int gotpowerup; /* has the random powerup appeared yet? */ @@ -873,7 +884,7 @@ extern SDL_Color black; extern SDL_Surface *screen, *temps, *levelbg, *head, *head5, *icecube; extern SDL_Surface *healthbar[]; extern SDL_Surface *greenbox, *redbox; -extern sprite_t *sprite, *lastsprite, *player, *boss, *mask; +extern sprite_t *sprite, *lastsprite, *player, *player2, *boss; extern level_t *curlevel; extern tiletype_t fakeblock; extern int gtime; @@ -905,6 +916,7 @@ extern char *deathtext[]; extern char *bifftext[]; extern spriteinfo_t spriteinfo[]; +extern int want1up,want2up; extern int gotcard; extern int curcard; diff --git a/edit.c b/edit.c index 393c628..4079043 100644 --- a/edit.c +++ b/edit.c @@ -135,6 +135,9 @@ int main (int argc, char **argv) { exit(1); } + want1up = B_TRUE; + want2up = B_TRUE; + atexit(cleanup); @@ -323,7 +326,7 @@ int main (int argc, char **argv) { /* checks */ // can only have one player/powerup pos - if ((selsprite == P_PLAYER) || (selsprite == P_POWERUPPOS)) { + if ((selsprite == P_PLAYER) || (selsprite == P_PLAYER2) || (selsprite == P_POWERUPPOS)) { /* does a player start pos already exist? */ sprite_t *s; for (s = sprite ; s ; s = s->next) { @@ -1128,6 +1131,7 @@ int isplacablesprite(int sid) { if (sid == P_PLATFORM) return B_TRUE; if (sid == P_HELP) return B_TRUE; if (sid == P_PLAYER) return B_TRUE; + if (sid == P_PLAYER2) return B_TRUE; if (sid == P_POWERUPPOS) return B_TRUE; if (ismonster(sid) && (sid != P_BLACKCLOUD)) return B_TRUE; if (isfruit(sid) == FT_GEM) return B_TRUE; diff --git a/globals.h b/globals.h index bd44a52..f8c1311 100644 --- a/globals.h +++ b/globals.h @@ -9,6 +9,8 @@ int numlevels; int maxlevid; +int want1up,want2up; + int gamemode; // easy or hard? int showhelp; // show help text? @@ -35,9 +37,8 @@ SDL_Surface *redbox; // for gunner SDL_Surface *healthbar[HEALTHFRAMES]; // for boss health sprite_t *sprite; // head of sprite linked list sprite_t *lastsprite; // tail of sprite linked list -sprite_t *player; // pointer to the player's sprite +sprite_t *player, *player2; // pointer to the player's sprite sprite_t *boss; // point to current boss on level (normally NULL) -sprite_t *mask; // point to scuba mask Mix_Music *music, *fastmusic, *normalmusic,*bossmusic,*hiscoremusic; Mix_Chunk *sfx[MAXFX]; diff --git a/rc.c b/rc.c index 331e8e4..fedfc48 100644 --- a/rc.c +++ b/rc.c @@ -33,6 +33,9 @@ SDL_Surface *screen; SDL_Surface *credittext; +int globpowerup; +int globtimer; + TTF_Font *font[MAXLETTERHEIGHT]; char hiscoreserver[BUFLEN]; @@ -44,12 +47,12 @@ int gothiscore = -1; int havejoysticks; -int joybuttons; -int joyanalog; -int joythresh; -SDL_Joystick *joy; +int joybuttons[2]; +int joyanalog[2]; +int joythresh[2]; +SDL_Joystick *joy[2]; Uint8 *keys; -int joyx,joyy,joybut[MAXJOYBUTTONS], joymap[MAXJOYBUTTONS]; +int joyx[2],joyy[2],joybut[2][MAXJOYBUTTONS], joymap[MAXJOYBUTTONS]; Mix_Music *curmusic = NULL; // pointer to currently playing music @@ -132,7 +135,6 @@ int levelcompletetime; int oldlevelcomplete; sprite_t *sprite = NULL; /* main sprite list */ -sprite_t *player = NULL; sprite_t *lastsprite; sprite_t *lastmet; @@ -350,11 +352,17 @@ int main (int argc, char **argv) { if (skipto <= 0) { dotitlescreen(); srand(time(NULL)); + } else { + // cheat + want1up = B_TRUE; + want2up = B_TRUE; } // shuffle cards shufflecards(); + + startgame(); // main loop @@ -369,18 +377,20 @@ int main (int argc, char **argv) { */ if (levelcomplete == LV_CLEAR) { sprite_t *s2, *nexts; + sprite_t *pp; addoutlinetext(320,240,TEXTSIZE_LEVEL,"Level Complete!",&green,&black,LEVELWINDELAY, TT_NORM); levelcomplete = LV_WAIT; playfx(FX_WINLEVEL); // turn off certain powerups - if (player->powerup == PW_CLOCK) { + if (globpowerup == PW_CLOCK) { Mix_ResumeMusic(); - losepowerup(player); + globpowerup = -1; } else if ((curlevel->iced == WATER_INPROGRESS) || (curlevel->iced == WATER_COMPLETE)) { curlevel->iced = B_FALSE; undoflood(); - } else if (player->powerup == PW_GUNNER) { - losepowerup(player); + } else if (haspowerupany(PW_GUNNER)) { + pp = haspowerupany(PW_GUNNER); + losepowerup(pp); } // kill all cards, so we don't have a pokereffect during endoflevel @@ -392,15 +402,22 @@ int main (int argc, char **argv) { } // stop teleporting - if (player->teleporting) { - stopteleporting(player); + if (player) { + if (player->teleporting) { + stopteleporting(player); + } + } + if (player2) { + if (player2->teleporting) { + stopteleporting(player2); + } } } else if (levelcomplete == LV_WAIT) { int mcount = 0; sprite_t *s2; /* when all monsters have become fruits */ - for (s2 = sprite->next ; s2 ; s2 = s2->next) { + for (s2 = sprite; s2 ; s2 = s2->next) { if (ismonster(s2->id)) { if (s2->id != P_BLACKCLOUD) { mcount++; @@ -425,7 +442,7 @@ int main (int argc, char **argv) { * Special effects #1 - ones which change the level by * modifiying tiles, etc. */ - if (player->powerup != PW_CLOCK) { + if (globpowerup != PW_CLOCK) { // for each animated tile on the level... for (animtile = curlevel->animtiles; animtile && *animtile != -1; animtile++) { int offset,numframes; @@ -463,13 +480,15 @@ int main (int argc, char **argv) { } } // gunner effect - red overlay - if (player->powerup == PW_GUNNER) { + if (haspowerupany(PW_GUNNER)) { if (levelcomplete != LV_DOPOKER) { SDL_BlitSurface(redbox,NULL,screen,NULL); } if (uncaughtmonsters() <= 0) { + sprite_t *pp; // finish if no monsters are left alive & uncaught - losepowerup(player); + pp = haspowerupany(PW_GUNNER); + losepowerup(pp); } } @@ -507,6 +526,11 @@ int main (int argc, char **argv) { dogravity(player); checkwrap(player); dotileeffects(player); + if (player2) { + dogravity(player2); + checkwrap(player2); + dotileeffects(player2); + } } else { sprite_t *s; switch (levelcomplete) { @@ -528,9 +552,11 @@ int main (int argc, char **argv) { break; case LV_GAMEOVER: // no collision detection or player movement /* gravity */ - for (s = sprite->next ; s ; s = s->next) { - dogravity(s); - checkwrap(s); + for (s = sprite; s ; s = s->next) { + if (!isplayer(s)) { + dogravity(s); + checkwrap(s); + } } break; case LV_DOPOKER: // do nothing @@ -543,7 +569,7 @@ int main (int argc, char **argv) { * Special effects #2 - ones which need to happen * after sprite movement */ - if (player->hasbell) { + if ((player && player->hasbell) || (player2 && player2->hasbell)) { /* check for bell sound */ /* play a bell sound if the powerup will be a permenant one */ @@ -586,11 +612,17 @@ int main (int argc, char **argv) { // player netting if (levelcomplete != LV_DOPOKER) { drawnetting(player); + drawnetting(player2); } // cannon firing - if ((levelcomplete != LV_DOPOKER) && (levelcomplete != LV_HELPFREEZE) && (player->powerup == PW_CANNONFIRE)) { // cannon firing - docannoneffect(); + if ((levelcomplete != LV_DOPOKER) && (levelcomplete != LV_HELPFREEZE)) { // cannon firing + if (haspowerup(player, PW_CANNONFIRE)) { + docannoneffect(player); + } + if (haspowerup(player2, PW_CANNONFIRE)) { + docannoneffect(player2); + } } @@ -600,7 +632,6 @@ int main (int argc, char **argv) { } - // warning for cloud if (!isbosslevel(curlevelnum)) { if ((gtime >= nexthurryup + 10) && (gtime < nexthurryup+15)) { // 15 secs after hurryup @@ -684,7 +715,7 @@ int main (int argc, char **argv) { */ if (!paused) { /* is screen shaking? */ - if (player->powerup == PW_BOMB) { + if (globpowerup == PW_BOMB) { if (timer % 5 == 0) { int amt; SDL_Rect area; @@ -703,28 +734,28 @@ int main (int argc, char **argv) { SDL_FillRect(screen, &area, SDL_MapRGB(screen->format,black.r,black.g,black.b)); } - if (--player->timer1 == 0) { - losepowerup(player); + if (--globtimer == 0) { + globpowerup = -1; } - } else if (player->powerup == PW_SPRAYUP) { // green overlay for fly spray + } else if (globpowerup == PW_SPRAYUP) { // green overlay for fly spray if (levelcomplete != LV_DOPOKER) { SDL_SetAlpha(greenbox, SDL_SRCALPHA, sprayalpha); sprayalpha += 5; if (sprayalpha >= 100) { - player->powerup = PW_SPRAYDOWN; + globpowerup = PW_SPRAYDOWN; } SDL_BlitSurface(greenbox,NULL,screen,NULL); } - } else if (player->powerup == PW_SPRAYDOWN) { // green overlay for fly spray + } else if (globpowerup == PW_SPRAYDOWN) { // green overlay for fly spray if (levelcomplete != LV_DOPOKER) { SDL_SetAlpha(greenbox, SDL_SRCALPHA, sprayalpha); sprayalpha -= 5; if (sprayalpha <= 0) { - player->powerup = PW_SPRAYUP; + globpowerup = PW_SPRAYUP; } SDL_BlitSurface(greenbox,NULL,screen,NULL); } - } else if (player->powerup == PW_RATSHAKE) { // horizontal shake due to rat + } else if (globpowerup == PW_RATSHAKE) { // horizontal shake due to rat // shake screen if (timer % 5 == 0) { int amt; @@ -753,10 +784,10 @@ int main (int argc, char **argv) { } - if (--player->timer1 == 0) { - losepowerup(player); + if (--globtimer == 0) { + globpowerup = -1; } - } else if (player->powerup == PW_SNAILSHAKE) { // vertical shake due to king snail + } else if (globpowerup == PW_SNAILSHAKE) { // vertical shake due to king snail // shake screen if (timer % 5 == 0) { int amt; @@ -779,8 +810,8 @@ int main (int argc, char **argv) { SDL_FillRect(screen, &area, SDL_MapRGB(screen->format,black.r,black.g,black.b)); } - if (--player->timer1 == 0) { - losepowerup(player); + if (--globtimer == 0) { + globpowerup = -1; } } @@ -801,7 +832,7 @@ int main (int argc, char **argv) { if (toggletimer > 0) toggletimer--; - if (player->powerup == PW_GUNNER) { + if (haspowerup(player, PW_GUNNER) || haspowerup(player2, PW_GUNNER)) { // delay between shots if (gundelay > 0) { gundelay--; @@ -833,7 +864,6 @@ int main (int argc, char **argv) { } // end outside loop return 0; - } void tick(void) { @@ -868,7 +898,7 @@ void tick(void) { // handle visual countdown timers if (levelcomplete == LV_INPROGRESS) { // clock - if (player->powerup == PW_CLOCK) { + if (globpowerup == PW_CLOCK) { char tempm[SMALLBUFLEN]; // text if (clocktime > 0) { @@ -884,7 +914,7 @@ void tick(void) { if (clocktime < 0) { // finished! Mix_ResumeMusic(); - losepowerup(player); + globpowerup = -1; } } @@ -908,8 +938,11 @@ void tick(void) { } } // handle gunner effect - if (player->powerup == PW_GUNNER) { + if (haspowerupany(PW_GUNNER)) { + sprite_t *pp; char tempm[SMALLBUFLEN]; + + pp = haspowerupany(PW_GUNNER); // text if (guntime > 0) { sprintf(tempm, "%d",guntime); @@ -924,7 +957,7 @@ void tick(void) { guntime--; if (guntime < 0) { // finished! - losepowerup(player); + losepowerup(pp); } } } @@ -937,17 +970,15 @@ void tick(void) { if (!levelcomplete) { // all sprites get angry and un-iced for (s = sprite; s; s = s->next) { - if ((s != player) && (ismonster(s->id))) { + if (!isplayer(s) && (ismonster(s->id))) { s->angry = B_TRUE; s->iced = B_FALSE; } } // rings are disabled - if ((player->powerup == PW_RINGWALK) || (player->powerup == PW_RINGJUMP)) { - losepowerup(player); - } - + disablepowerups(PW_RINGWALK); + disablepowerups(PW_RINGJUMP); addoutlinetext(320,240,TEXTSIZE_HURRY, "Hurry up!", &yellow,&black,HURRYDELAY, TT_NORM); @@ -989,7 +1020,8 @@ void tick(void) { /* 5 seconds after level completion */ if (levelcomplete == LV_FINAL) { if (gtime - levelcompletetime >= 5) { - if (!player->dead) { + if (playersalive()) { + sprite_t *newsp; int x,y; levelcomplete = LV_CLOUD; switch (curlevel->exitdir) { @@ -1012,7 +1044,18 @@ void tick(void) { break; } - puffin(P_PINKCLOUD, x, y, "pinkcloud", 0); + if (player) { + newsp = addsprite(P_PINKCLOUD, x, y, "pinkcloud_1"); + newsp->timer1 = LV_CLOUD; + newsp->owner = player; + puffin(-1, x, y, "nothing", 0); + } + if (player2) { + newsp = addsprite(P_PINKCLOUD, x, y, "pinkcloud_2"); + newsp->timer1 = LV_CLOUD; + newsp->owner = player2; + puffin(-1, x, y, "nothing", 0); + } } } @@ -1027,9 +1070,10 @@ void nextlevel(void) { sprite_t *cloudp; int x,y; - // remove the player + // remove the players if (!firstlevel) { removesprite(player); + removesprite(player2); } /* in case we skipped the level due to a powerup etc */ @@ -1042,15 +1086,23 @@ void nextlevel(void) { } // don't want the player flashing while scrolling - player->invuln = 0; + if (player) player->invuln = 0; + if (player2) player2->invuln = 0; // not on a trampoline! - player->ontramp = B_FALSE; - player->trampx = -1; - player->trampy = -1; + if (player) { + player->ontramp = B_FALSE; + player->trampx = -1; + player->trampy = -1; + } + if (player2) { + player2->ontramp = B_FALSE; + player2->trampx = -1; + player2->trampy = -1; + } // load next level data - if ((player->powerup == PW_PHONE) && (!isbosslevel(curlevelnum))) { + if (haspowerupany(PW_PHONE) && !isbosslevel(curlevelnum)) { // don't add monsters loadlevel(curworld,curlevelnum, B_FALSE); } else { @@ -1070,19 +1122,24 @@ void nextlevel(void) { // now the player gets invincibility makeinvuln(player); + makeinvuln(player2); // phone is cancelled on boss levels - if (player->powerup == PW_PHONE) { + if (haspowerupany(PW_PHONE)) { if (isbosslevel(curlevelnum)) { - losepowerup(player); + sprite_t *pp; + pp = haspowerupany(PW_PHONE); + losepowerup(pp); skiplevels = 0; } } /* reset game stats */ - if (player->powerup == PW_PHONE) { + if (haspowerupany(PW_PHONE)) { +printf("phone\n"); levelcomplete = LV_CLOUD; } else { +printf("no phone\n"); levelcomplete = LV_INIT; levelcompletetime = -1; } @@ -1099,7 +1156,7 @@ void nextlevel(void) { // don't play bell on boss levels playedbell = BELL_DONEFLASH; } else { - if (player->hasbell) { + if ((player && player->hasbell) || (player2 && player2->hasbell)) { playedbell = B_FALSE; } else { playedbell = BELL_DONEFLASH; @@ -1128,33 +1185,65 @@ void nextlevel(void) { addoutlinetext(320,240+18,TEXTSIZE_LEVEL2,msg,&cyan,&black,LEVELDELAY, TT_NORM); /* reset player stats */ - player->netting = B_FALSE; - player->slamming = B_FALSE; - player->jumping = B_FALSE; - player->netcaught = 0; + if (player) { + player->netting = B_FALSE; + player->slamming = B_FALSE; + player->jumping = B_FALSE; + player->netcaught = 0; - // make sure player is at the right position - player->x = (curlevel->p1x * TILEW) + (TILEW/2); - player->y = (curlevel->p1y * TILEH) + TILEH-2; + // make sure player is at the right position + player->x = (curlevel->p1x * TILEW) + (TILEW/2); + player->y = (curlevel->p1y * TILEH) + TILEH-2; + } + if (player2) { + player2->netting = B_FALSE; + player2->slamming = B_FALSE; + player2->jumping = B_FALSE; + player2->netcaught = 0; + + // make sure player2 is at the right position + player2->x = (curlevel->p2x * TILEW) + (TILEW/2); + player2->y = (curlevel->p2y * TILEH) + TILEH-2; + } // remove powerup, phone is a special case - if (player->powerup == PW_PHONE) { + if (haspowerupany(PW_PHONE)) { +printf("skipping it\n"); skiplevels--; if (skiplevels <= 0) { - losepowerup(player); +printf("fnishedphone\n"); + disablepowerups(PW_PHONE); } } else { - losepowerup(player); +printf("noone has phone\n"); + // lose ALL temp powerups + if (player) losepowerup(player); + if (player2) losepowerup(player2); } + // remove level powerup effect (bomb etc) + globpowerup = -1; + // add initial fading cloud - cloudp = addsprite(P_PINKCLOUD, player->x,player->y + (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2),"initial_pinkcloud"); - cloudp->size = 1.0; + if (player) { + cloudp = addsprite(P_PINKCLOUD, player->x,player->y + (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2),"initial_pinkcloud_1"); + cloudp->timer1 = LV_INPROGRESS; + cloudp->size = 1.0; + cloudp->owner = player; + } + if (player2) { + cloudp = addsprite(P_PINKCLOUD, player2->x,player2->y + (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2),"initial_pinkcloud_2"); + cloudp->timer1 = LV_INPROGRESS; + cloudp->size = 1.0; + cloudp->owner = player2; + } if (cheat) { - player->speed = 2; + if (player) player->speed = 2; + if (player2) player2->speed = 2; + } // haven't got a card yet @@ -1257,13 +1346,13 @@ void jump(sprite_t *s, int dir) { } // stop climbing s->climbing = B_FALSE; - if (s == player) { + if (isplayer(s) ) { // stop recoiling if (s->recoiling) { s->recoiling = B_FALSE; } else { // play sound effect - if (player->ontramp) { + if (s->ontramp) { playfx(FX_SPRING); } else { playfx(FX_JUMP); @@ -1285,17 +1374,21 @@ void die(sprite_t *s) { /* if this is the player, hurryup time counter resets */ // We already do this in the cloud movement routine, but // this handles cases where the cloud hasn't appeared yet. - if (s == player) { + if (isplayer(s)) { // if we have armour, we lose it instead of dying - if (player->armour) { + if (s->armour) { // lose armour - player->armour = B_FALSE; - player->id = P_PLAYER; + s->armour = B_FALSE; + if (s == player) { + s->id = P_PLAYER; + } else { + s->id = P_PLAYER2; + } // become invulnerable temporarily - makeinvuln(player); + makeinvuln(s); // bounce back - player->recoiling = B_TRUE; - jump(player, -player->dir); + s->recoiling = B_TRUE; + jump(s, -s->dir); // play sound playfx(FX_OW); // don't process rest of the death code @@ -1303,10 +1396,10 @@ void die(sprite_t *s) { } else { int tnum; - if (player->powerup == PW_CLOCK) { + if (globpowerup == PW_CLOCK) { Mix_ResumeMusic(); } - losepowerup(player); + globpowerup = -1; resethurryup(curlevel); if (curmusic == fastmusic) { @@ -1314,22 +1407,23 @@ void die(sprite_t *s) { } // turn off attributes - player->climbing = B_FALSE; - player->swimming = B_FALSE; - player->slamming = B_FALSE; - player->netting = B_FALSE; + s->climbing = B_FALSE; + s->swimming = B_FALSE; + s->slamming = B_FALSE; + s->netting = B_FALSE; // kill mask sprite - if (mask) { - mask->dead = D_FINAL; + for (s2 = sprite ; s2 ; s2 = s2->next) { + if ((s2->id == P_MASK) && (s2->owner == s)) { + s2->dead = D_FINAL; + } } - // reset powerup types curpoweruptype = 0; /* lose a life */ - player->lives--; + s->lives--; /* play sound */ @@ -1337,10 +1431,10 @@ void die(sprite_t *s) { // draw text tnum = rand() % MAXDEATHTEXT; - addoutlinetext(player->x,player->y,TEXTSIZE_DEATH,deathtext[tnum],&red,&black,DIEDELAY, TT_NORM); + addoutlinetext(s->x,s->y,TEXTSIZE_DEATH,deathtext[tnum],&red,&black,DIEDELAY, TT_NORM); /* release anything we've caught */ - for (s2 = sprite->next ; s2 ; s2 = s2->next) { + for (s2 = sprite; s2 ; s2 = s2->next) { if (s2->caughtby == s) { uncatch(s2); s2->angry = B_TRUE; @@ -1354,25 +1448,29 @@ void die(sprite_t *s) { } // un-ice everything if player dies + /* for (s2 = sprite->next ; s2 ; s2 = s2->next) { if (s2->iced) { s2->iced = B_FALSE; } } + */ // undo water effect + /* if (curlevel->iced == WATER_COMPLETE) { undoflood(); curlevel->iced = B_FALSE; } + */ } } else if (s == boss) { // boss effects sprite_t *ss; // stop screen shaking and rats falling - if (player->powerup == PW_RATSHAKE) { - losepowerup(player); - } else if (player->powerup == PW_SNAILSHAKE) { - losepowerup(player); + if (globpowerup == PW_RATSHAKE) { + globpowerup = -1; + } else if (globpowerup == PW_SNAILSHAKE) { + globpowerup = -1; } // reset timers s->timer1 = 0; @@ -1401,13 +1499,32 @@ void die(sprite_t *s) { } } else if ((s->id == P_SNAIL) && (s->lives > 0)) { // snails can't die but turn into slugs instead sprite_t *newsp; + sprite_t *catcher; + + if (s->caughtby) { + catcher = s->caughtby; + } else { + double dist1, dist2; + // pick closest one + if (player) dist1 = getdistance(player->x,player->y,s->x,s->y); + else dist1 = 99999; + if (player2) dist2 = getdistance(player2->x,player2->y,s->x,s->y); + else dist2 = 99999; + + if (dist1 < dist2) { + catcher = player; + } else { + catcher = player2; + } + + } // create a slug here newsp = addsprite(P_SLUG, s->x,s->y, "slug" ); puffin(-1, s->x, s->y, "nothing", 0); // create the illusion of a puff - newsp->dir = player->dir; // facing away from player + newsp->dir = catcher->dir; // facing away from player // make sure it can't be netted right away! - if (player->powerup != PW_CLOCK) { + if (globpowerup != PW_CLOCK) { newsp->invuln = SLUGINVULNTIME; } @@ -1417,7 +1534,7 @@ void die(sprite_t *s) { s->invuln = INVULNTIME*2; // make sure this lasts until we die // -bounce back s->recoiling = B_TRUE; - jump(s,player->dir); // ie. away from the player + jump(s,catcher->dir); // ie. away from the player playfx(FX_CRACK); @@ -1456,7 +1573,7 @@ void checklevelend(void) { if (!levelcomplete) { mcount = 0; /* any monsters left? */ - for (s2 = sprite->next ; s2 ; s2 = s2->next) { + for (s2 = sprite; s2 ; s2 = s2->next) { if (ismonster(s2->id) && !s2->dead) { if (s2->id != P_BLACKCLOUD) { mcount++; @@ -1475,7 +1592,7 @@ int countmonsters(int montype) { int mcount; mcount = 0; /* any monsters left? */ - for (s2 = sprite->next ; s2 ; s2 = s2->next) { + for (s2 = sprite; s2 ; s2 = s2->next) { if (ismonster(s2->id) && !s2->dead) { if (s2->id != P_BLACKCLOUD) { if ((montype == -1) || (s2->id == montype)) { @@ -1494,7 +1611,7 @@ int uncaughtmonsters(void) { int mcount; mcount = 0; /* any monsters left? */ - for (s2 = sprite->next ; s2 ; s2 = s2->next) { + for (s2 = sprite; s2 ; s2 = s2->next) { if (ismonster(s2->id) && !s2->dead && !s2->caughtby) { if (s2->id != P_BLACKCLOUD) { mcount++; @@ -1526,7 +1643,7 @@ void checkcollideplatform(sprite_t *s) { for (s2 = sprite ; s2 ; s2 = s2->next) { // only monsters and players and fruits can be on platforms - if (!ismonster(s2->id) && (s2 != player) && (!isfruit(s2->id))) { + if (!ismonster(s2->id) && (!isplayer(s2)) && (!isfruit(s2->id))) { continue; } @@ -1722,10 +1839,10 @@ void checkcollide(sprite_t *s) { /* COLLISION! */ // are we the player? - if (s == player) { + if (isplayer(s)) { //if (isfruit(s2->id) && (s2->teleporting == 0)) { if (isfruit(s2->id)) { - getfruit(player, s2, 1); + getfruit(s, s2, 1); } else if (ismonster(s2->id) || isbullet(s2->id)) { if (s2->iced) { // monster dies @@ -1822,7 +1939,7 @@ int movesprite(sprite_t *s) { int rv; tiletype_t *tt; - if ((s == player) && (player->powerup == PW_GUNNER)) { + if ((isplayer(s)) && (s->powerup == PW_GUNNER)) { return B_FALSE; } @@ -1830,7 +1947,7 @@ int movesprite(sprite_t *s) { if (levelcomplete == LV_INIT) { // most things can't move in this state //if ((s->id != P_PUFF) && (s != player)) { - if (!iseffect(s->id) && (s != player)) { + if (!iseffect(s->id) && (!isplayer(s))) { // caught or dead sprites can move, in case // the player catches something before level start time if ((!s->caughtby) && (!s->dead)) return B_FALSE; @@ -1840,8 +1957,8 @@ int movesprite(sprite_t *s) { } // only player can move if you have a clock - if (player->powerup == PW_CLOCK) { - if (!iseffect(s->id) && (s != player) && !s->caughtby && !s->dead) { + if (globpowerup == PW_CLOCK) { + if (!iseffect(s->id) && (!isplayer(s)) && !s->caughtby && !s->dead) { return B_FALSE; } } @@ -1866,7 +1983,7 @@ int movesprite(sprite_t *s) { /* timer */ if (s->doomcount) { - if (player->powerup != PW_GUNNER) { + if (s->powerup != PW_GUNNER) { s->doomcount--; } if (s->doomcount == 0) { @@ -1926,14 +2043,14 @@ int movesprite(sprite_t *s) { s->dead = D_BOUNCING; s->bounces = 0; - if (s == player) { + if (isplayer(s)) { s->jumpspeed = 8; s->jumping = 1; } } return B_FALSE; } else if (s->dead == D_BOUNCING) { /* dying */ - if (s == player) { + if (isplayer(s)) { /* shoot up in the air, then fall */ s->y -= s->jumpspeed; @@ -1963,7 +2080,7 @@ int movesprite(sprite_t *s) { } return B_FALSE; } else if (s->dead == D_LASTBOUNCE) { /* final fall */ - if (s == player) { + if (isplayer(s)) { /* just delay... */ s->jumpspeed++; if (s->jumpspeed == 50) { @@ -2129,7 +2246,7 @@ int movesprite(sprite_t *s) { // we get a card instead (and also haven't got a card yet htis // level) if (!gotcard) { - if ((isfruit(s->timer3) == FT_PERM) && haspowerup(player, s->timer3)) { + if ((isfruit(s->timer3) == FT_PERM) && (haspowerup(player, s->timer3) || haspowerup(player2, s->timer3))) { sprite_t *search; int found; found = B_FALSE; @@ -2175,21 +2292,42 @@ int movesprite(sprite_t *s) { // is it a points fruit appearing on top of us? if (isfruit(newsp->id) == FT_FRUIT) { int xdiff,ydiff; - /* now check for collision with us */ - xdiff = player->x - newsp->x; - if (xdiff < 0) xdiff = -xdiff; - ydiff = (player->y-(player->img->h/2)) - (newsp->y-(newsp->img->h/2)); - if (ydiff < 0) ydiff = -ydiff; - - // appeared on top of us - if ((xdiff <= player->img->w/2 + newsp->img->w/2) && - (ydiff <= player->img->h/2 + newsp->img->h/2)) { - if ((!player->dead) && (player->powerup != PW_GUNNER)) { - // bonus! - getfruit(player, newsp, 4); - addoutlinetext(player->x,player->y - (player->img->h*1.5), TEXTSIZE_MULTI, "Nice catch!", &green,&black,MULTIDELAY, TT_NORM); + int gotit = B_FALSE; + /* now check for collision with players */ + if (player) { + xdiff = player->x - newsp->x; + if (xdiff < 0) xdiff = -xdiff; + ydiff = (player->y-(player->img->h/2)) - (newsp->y-(newsp->img->h/2)); + if (ydiff < 0) ydiff = -ydiff; + + // appeared on top of us + if ((xdiff <= player->img->w/2 + newsp->img->w/2) && + (ydiff <= player->img->h/2 + newsp->img->h/2)) { + if ((!player->dead) && (player->powerup != PW_GUNNER)) { + // bonus! + getfruit(player, newsp, 4); + addoutlinetext(player->x,player->y - (player->img->h*1.5), TEXTSIZE_MULTI, "Nice catch!", &green,&black,MULTIDELAY, TT_NORM); + gotit = B_TRUE; + } } } + if (!gotit && player2) { + xdiff = player2->x - newsp->x; + if (xdiff < 0) xdiff = -xdiff; + ydiff = (player2->y-(player2->img->h/2)) - (newsp->y-(newsp->img->h/2)); + if (ydiff < 0) ydiff = -ydiff; + + // appeared on top of us + if ((xdiff <= player2->img->w/2 + newsp->img->w/2) && + (ydiff <= player2->img->h/2 + newsp->img->h/2)) { + if ((!player2->dead) && (player2->powerup != PW_GUNNER)) { + // bonus! + getfruit(player2, newsp, 4); + addoutlinetext(player2->x,player2->y - (player2->img->h*1.5), TEXTSIZE_MULTI, "Nice catch!", &green,&black,MULTIDELAY, TT_NORM); + } + } + } + } @@ -2206,12 +2344,13 @@ int movesprite(sprite_t *s) { // timer2 is the target x position // timer3 is the target y position // + // move towards end position moveto(s, s->timer2, s->timer3, CARDSPEED, CARDSPEED); // are we there yet? if ((s->x == s->timer2) && (s->y == s->timer3)) { - gaincard(player, s->timer1); + gaincard(s->owner, s->timer1); s->dead = D_FINAL; } } else if (s->id == P_FIVECARDS) { @@ -2243,8 +2382,8 @@ int movesprite(sprite_t *s) { SDL_SetAlpha(blackness, SDL_SRCALPHA, 200); - for (i = 0; i < player->numcards; i++) { - if (player->usedcard[i] == B_FALSE) { + for (i = 0; i < s->owner->numcards; i++) { + if (s->owner->usedcard[i] == B_FALSE) { // hide it //SDL_FillRect(s->img, &area, SDL_MapRGB(screen->format, 0, 0, 0)); SDL_BlitSurface(blackness, NULL, s->img, &area); @@ -2268,19 +2407,19 @@ int movesprite(sprite_t *s) { Mix_ResumeMusic(); // do effect! - dopokereffect(player,pokereffect); + dopokereffect(s->owner,pokereffect); // clear player cards for (i = 0; i < MAXCARDS; i++) { - player->card[i] = -1; + s->owner->card[i] = -1; } - player->numcards = 0; + s->owner->numcards = 0; // shuffle cards shufflecards(); // kill all monsters (if not skipping levels) - if (player->powerup != PW_PHONE) { + if (s->owner->powerup != PW_PHONE) { for (s2 = sprite; s2 ; s2 = nexts) { nexts = s2->next; if (isbullet(s2->id)) { @@ -2291,7 +2430,7 @@ int movesprite(sprite_t *s) { if (s2->caughtby) { uncatch(s2); - player->netcaught--; + s2->caughtby->netcaught--; } die(s2); } @@ -2307,15 +2446,15 @@ int movesprite(sprite_t *s) { } else if (s->id == P_MASK) { // mask effect // stay on top of player if (player->slamming) { - s->y = player->y + MASKOFFSETSLAMY; - s->x = player->x + (MASKOFFSETSLAMX*player->dir); + s->y = s->owner->y + MASKOFFSETSLAMY; + s->x = s->owner->x + (MASKOFFSETSLAMX*s->owner->dir); } else { - s->y = player->y + MASKOFFSETY; - s->x = player->x + (MASKOFFSETX*player->dir); + s->y = s->owner->y + MASKOFFSETY; + s->x = s->owner->x + (MASKOFFSETX*s->owner->dir); } // die if player doesn't have a mask - if (!player->hasmask) { + if (!s->owner->hasmask) { s->dead = D_FINAL; } } else if (s->id == P_STAR) { // shuriken effect @@ -2377,8 +2516,8 @@ int movesprite(sprite_t *s) { } // move in figure 8 around player - s->x = player->x; - s->y = player->y; + s->x = s->owner->x; + s->y = s->owner->y; degs = (double)s->timer3 * ((double)M_PI/(double)180); @@ -2406,14 +2545,14 @@ int movesprite(sprite_t *s) { s->timer4--; } } else if (s->id == P_CANNON) { // cannon effect - // die if player dies - if (player->dead) { + // die if owner dies + if (s->owner->dead) { s->dead = D_FINAL; - } else if (player->powerup == PW_CANNON) { + } else if (s->owner->powerup == PW_CANNON) { int targx,targy; // try to stay behind player - targx = player->x - (player->dir * 32); - targy = player->y; + targx = s->owner->x - (player->dir * 32); + targy = s->owner->y; if (s->x < targx) { s->x += 2; if (s->x > targx) s->x = targx; @@ -2434,38 +2573,37 @@ int movesprite(sprite_t *s) { } else if (s->id == P_GLOVE) { // boxing glove effect // dies when the player finshes netting - if (!player->netting) { + if (!s->owner->netting) { s->dead = D_FINAL; } else { // keep it at the end of the net - s->x = player->x + (player->netdir * player->netlen); - s->y = player->y - (player->img->h/2) + 5; - s->dir = player->dir; + s->x = s->owner->x + (s->owner->netdir * s->owner->netlen); + s->y = s->owner->y - (s->owner->img->h/2) + 5; + s->dir = s->owner->dir; } } else if (s->id == P_MACE) { // mace slam effect // dies when the player finishes slamming - if (!player->slamming) { + if (!s->owner->slamming) { s->dead = D_FINAL; } else { double dist; // keep it at the end of the slam - dist = (player->slamangle * (180/M_PI))/2; + dist = (s->owner->slamangle * (180/M_PI))/2; - s->x = player->x + cos(player->slamangle-(180*(M_PI/180)))*dist*player->dir; - s->y = player->y + sin(player->slamangle-(180*(M_PI/180)))*dist + imageset[P_MACEPOWERUP].img[F_WALK1]->h/2; - s->dir = player->dir; + s->x = s->owner->x + cos(s->owner->slamangle-(180*(M_PI/180)))*dist*s->owner->dir; + s->y = s->owner->y + sin(s->owner->slamangle-(180*(M_PI/180)))*dist + imageset[P_MACEPOWERUP].img[F_WALK1]->h/2; + s->dir = s->owner->dir; } } else if (s->id == P_RAT) { if (!s->falling) { int move = B_FALSE; - int xdiff, absxdiff; + int xdiff ,absxdiff; tiletype_t *tunder; - /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + /* distance to closest player */ + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); // tile in front and below tt = gettileat(s->x + s->dir*getspeed(s) + (s->dir * (s->img->w/2)),s->y + (TILEH/2),NULL,NULL); @@ -2478,12 +2616,12 @@ int movesprite(sprite_t *s) { move = B_TRUE; } else { if (s->angry || boss) { - if (player->y > s->y) { + if ((player && (player->y > s->y)) || (player2 && (player2->y > s->y))) { /* if player is below, fall off */ if (xdiff <= (TILEW*8)) { move = B_TRUE; } - } else if (player->y == s->y) { + } else if ((player && (player->y == s->y)) || (player2 && player2->y == s->y)) { /* if player is at same level and close, jump */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,D_RIGHT); @@ -2509,16 +2647,19 @@ int movesprite(sprite_t *s) { } if ((s->angry) || (boss)) { - if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { + if ((!s->jumping) && (!s->jumptimer)) { + /* if player is above us, jump */ - if (player->y < s->y) { + if ( (player && (!player->dead) && (player->y < s->y)) || + (player2 && (!player2->dead) && (player2->y < s->y))) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { /* jump right */ jump(s, 1); } else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) { /* jump left */ jump(s, -1); - } else if (s->y - player->y <= (TILEH*6)) { + } else if ((player && (s->y - player->y <= (TILEH*6))) || + (player2 && (s->y - player2->y <= (TILEH*6)))) { if ((xdiff >= 0) && (xdiff < (TILEW*2))) { /* jump up */ jump(s, 0); @@ -2552,18 +2693,19 @@ int movesprite(sprite_t *s) { int move = B_FALSE; int xdiff, absxdiff; - /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + /* distance to closest player */ + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); tt = gettileat(s->x + s->dir+getspeed(s) + (s->dir * (s->img->w/2)),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { - if ((player->y > s->y) && (s->angry || boss)) { - /* if player is below, fall off */ - if (xdiff <= (TILEW*8)) { - move = B_TRUE; + if (s->angry || boss) { + if ((player && (player->y > s->y)) || (player2 && (player2->y > s->y))) { + /* if player is below, fall off */ + if (xdiff <= (TILEW*8)) { + move = B_TRUE; + } } } } else { @@ -2583,10 +2725,17 @@ int movesprite(sprite_t *s) { // jump? if (boss) { - if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { + if ((!s->jumping) && (!s->jumptimer)) { /* if player is above us or at same level...*/ - if (player->y <= (s->y-TILEH)) { - int ydiff = s->y - player->y; + if ( (player && (!player->dead) && (player->y <= s->y-TILEH)) || + (player2 && (!player2->dead) && (player2->y <= s->y-TILEH))) { + int ydiff; + + if (player && (!player->dead) && (player->y <= s->y-TILEH)) { + ydiff = s->y - player->y; + } else { + ydiff = s->y - player2->y; + } if ((ydiff >= (TILEH*4)) && (ydiff <= (TILEH*8))) { // player between 4 and 8 tiles above if (xdiff <= (TILEW*16)) { // if closeish horizontally @@ -2620,20 +2769,19 @@ int movesprite(sprite_t *s) { int xdiff, absxdiff; - /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + /* distance to closest player */ + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { - if (player->y > s->y ) { + if ((player && (player->y > s->y)) || (player2 && (player2->y > s->y))) { /* if player is below and nearby, fall off */ if (xdiff <= (TILEW*16)) { move = B_TRUE; } - } else if (player->y == s->y) { + } else if ((player && (player->y == s->y)) || (player2 && player2->y == s->y)) { /* if player is at same level and close, try to jump over the gap */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*9))) { jump(s,D_RIGHT); @@ -2659,11 +2807,19 @@ int movesprite(sprite_t *s) { /* moves like an angry rat all the time */ - if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { + if ((!s->jumping) && (!s->jumptimer)) { /* if player is above us or at same level...*/ - if (player->y <= s->y) { - int ydiff = s->y - player->y; + if ( (player && (!player->dead) && (player->y <= s->y)) || + (player2 && (!player2->dead) && (player2->y <= s->y))) { + int ydiff; + + if (player && (!player->dead) && (player->y <= s->y-TILEH)) { + ydiff = s->y - player->y; + } else { + ydiff = s->y - player2->y; + } + if ((ydiff >= (TILEH*4)) && (ydiff <= (TILEH*8))) { // player between 4 and 8 tiles above if (xdiff <= (TILEW*16)) { // if closeish horizontally /* jump up */ @@ -2709,16 +2865,28 @@ int movesprite(sprite_t *s) { } // if player is in front, charge! - if (player->dead) { + if (!playersalive()) { canseeplayer = B_FALSE; } else { - ydis = abs(s->y - player->y); - if (ydis > 2) { - canseeplayer = B_FALSE; - } else if ((s->dir < 0) && (player->x > s->x)) { - canseeplayer = B_FALSE; - } else if ((s->dir > 0) && (player->x < s->x)) { - canseeplayer = B_FALSE; + if (player) { + ydis = abs(s->y - player->y); + if (ydis > 2) { + canseeplayer = B_FALSE; + } else if ((s->dir < 0) && (player->x > s->x)) { + canseeplayer = B_FALSE; + } else if ((s->dir > 0) && (player->x < s->x)) { + canseeplayer = B_FALSE; + } + } + if ((canseeplayer == B_FALSE) && (player2)) { + ydis = abs(s->y - player2->y); + if (ydis > 2) { + canseeplayer = B_FALSE; + } else if ((s->dir < 0) && (player->x > s->x)) { + canseeplayer = B_FALSE; + } else if ((s->dir > 0) && (player->x < s->x)) { + canseeplayer = B_FALSE; + } } } @@ -2731,7 +2899,7 @@ int movesprite(sprite_t *s) { // dec timer s->timer2--; if (s->timer2 == 0) { - if (player->dead) { + if (!playersalive()) { // reset timer s->timer2 = KR_WALKTIME; } else { @@ -2774,8 +2942,8 @@ int movesprite(sprite_t *s) { playfx(FX_BOSSWALL); // shake the screen via a fake player powerup - player->powerup = PW_RATSHAKE; - player->timer1 = RATSHAKETIME; + globpowerup = PW_RATSHAKE; + globtimer = RATSHAKETIME; } } else if (s->timer1 == KRS_STUN) { s->timer2--; @@ -2784,18 +2952,19 @@ int movesprite(sprite_t *s) { s->timer2 = KR_WALKTIME; } } else if (s->timer1 == KRS_JUMP) { - // jump to player height + // jump to closest player height if (!s->jumping) { int ydis; int try; int tot; int n; - if ((player->dead) || (player->y > s->y)) { // player below or dead + if ((!playersalive()) || isplayerbelow(s) ) { // player below or dead try = 2; } else { // get distance - ydis = abs(s->y - player->y); + ydis = getydisttoplayer(s); + ydis = abs(ydis); // figure out how much we need to jump for (try = 2; try < (KR_MAXJUMP-1); try++) { tot = 0; @@ -2821,7 +2990,7 @@ int movesprite(sprite_t *s) { } } else if (s->timer1 == KRS_FALL) { // fall to player height - if (!s->jumping && (s->y >= player->y)) { + if (!s->jumping && ((player && (s->y >= player->y)) || (player2 && (s->y >= player2->y))) ) { // back to normal state but lower timer s->timer1 = KRS_WALK; s->timer2 = KR_WALKTIME; // low delay @@ -2847,7 +3016,7 @@ int movesprite(sprite_t *s) { // dec timer s->timer2--; if (s->timer2 == 0) { - if (player->dead) { + if (!playersalive()) { // reset timer s->timer2 = KR_WALKTIME; } else { @@ -2931,11 +3100,12 @@ int movesprite(sprite_t *s) { s->jumptimer = getjumpdelay(s->id); s->jumpdir = 0; - if ((player->dead) || (player->y > s->y)) { // player below or dead + if ((!playersalive()) || isplayerbelow(s)) { // player below or dead try = 2; } else { // get distance - ydis = abs(s->y - player->y); + ydis = getydisttoplayer(s); + ydis = abs(ydis); // figure out how much we need to jump for (try = 2; try < (KR_MAXJUMP-1); try++) { tot = 0; @@ -2973,8 +3143,8 @@ int movesprite(sprite_t *s) { // shake the screen via a fake player powerup playfx(FX_BOSSWALL); - player->powerup = PW_SNAILSHAKE; - player->timer1 = SNAILSHAKETIME; + globpowerup = PW_SNAILSHAKE; + globtimer = SNAILSHAKETIME; } } else if (s->timer1 == KSS_PAUSE3) { @@ -3043,19 +3213,19 @@ int movesprite(sprite_t *s) { /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { - if (player->y >= (s->y+TILEH/2) ) { + double ycutoff = s->y + (TILEH/2); + if ((player && (player->y >= ycutoff)) || (player2 && (player2->y >= ycutoff ))) { /* if player is below and nearby, fall off */ if (xdiff <= (TILEW*16)) { move = B_TRUE; } - } else if (player->y == s->y) { + } else if ((player && (player->y == s->y)) || (player2 && (player2->y == s->y ))) { /* if player is at same level and close, jump */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,D_RIGHT); @@ -3081,16 +3251,18 @@ int movesprite(sprite_t *s) { /* moves like an angry rat all the time */ - if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { + if ((playersalive()) && (!s->jumping) && (!s->jumptimer)) { + sprite_t *abovep; /* if player is above us...*/ - if (player->y < s->y) { + abovep = isplayerabove(s); + if (abovep) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { // if 2-3 tiles right /* jump right */ jump(s, D_RIGHT); } else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) { // if 2-3 tiles left /* jump left */ jump(s, D_LEFT); - } else if (s->y - player->y <= (TILEH*6)) { // player less than 6 tiles above + } else if (s->y - abovep->y <= (TILEH*6)) { // player less than 6 tiles above if ((xdiff >= 0) && (xdiff < (TILEW*4))) { // ... and within 4 tiles /* jump up */ jump(s, 0); @@ -3121,25 +3293,26 @@ int movesprite(sprite_t *s) { /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { - if ((player->y > s->y) && (s->angry)) { - /* if player is below, fall off */ - if (xdiff <= (TILEW*8)) { - move = B_TRUE; - } - } else if (player->y == s->y) { - if (s->angry) { - /* if player is at same level and close, jump */ - if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { - jump(s,D_RIGHT); - } else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { - jump(s,D_LEFT); + if (s->angry) { + if ((player && (player->y > s->y)) || (player2 && (player2->y > s->y))) { + /* if player is below, fall off */ + if (xdiff <= (TILEW*8)) { + move = B_TRUE; + } + } else if ((player && (player->y == s->y)) || (player2 && player2->y == s->y)) { + if (s->angry) { + /* if player is at same level and close, jump */ + if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { + jump(s,D_RIGHT); + } else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { + jump(s,D_LEFT); + } } } } @@ -3148,17 +3321,26 @@ int movesprite(sprite_t *s) { } /* shoot */ - ydiff = player->y - s->y; - if (ydiff < 0) ydiff =-ydiff; + ydiff = getydisttoplayer(s); + ydiff = abs(ydiff); + // if there's a player close up/down... if (ydiff <= (TILEH*4)) { sprite_t *ss; + sprite_t *closeplayer; int shoot = B_FALSE; + if (player && (s->y - player->y <= (TILEH*4)) ) { + closeplayer = player; + } else { + closeplayer = player2; + } + + if (s->bullet == NULL) { // if we don't already have a bullet // if we are facing the player - if ( (player->x < s->x) && (s->dir == D_LEFT) ) { + if ( (closeplayer->x < s->x) && (s->dir == D_LEFT) ) { shoot = B_TRUE; - } else if ( (player->x > s->x) && (s->dir == D_RIGHT) ) { + } else if ( (closeplayer->x > s->x) && (s->dir == D_RIGHT) ) { shoot = B_TRUE; } } @@ -3194,7 +3376,8 @@ int movesprite(sprite_t *s) { if (s->angry) { if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { /* if player is above us, jump */ - if (player->y < s->y) { + if ( (player && (!player->dead) && (player->y < s->y)) || + (player2 && (!player2->dead) && (player2->y < s->y))) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { /* jump right */ jump(s, 1); @@ -3329,16 +3512,15 @@ int movesprite(sprite_t *s) { } } else { // walking - move like a rat double myspeed = getspeed(s) * 0.75; - double playerdist; + double playerdist1,playerdist2,playerdist; if (!s->falling) { int move = B_FALSE; int xdiff, absxdiff; tiletype_t *tunder; /* distance to player */ - xdiff = player->x - s->x; - if (xdiff < 0) absxdiff = -xdiff; - else absxdiff = xdiff; + xdiff = getxdisttoplayer(s); + absxdiff = abs(xdiff); // tile in front and below tt = gettileat(s->x + s->dir*myspeed + (s->dir * (s->img->w/2)),s->y + (TILEH/2),NULL,NULL); @@ -3367,7 +3549,22 @@ int movesprite(sprite_t *s) { s->moved = MV_WALK; // take off if player is close - playerdist = getdistance(player->x,player->y,s->x,s->y); + if (player) { + playerdist = getdistance(player->x,player->y,s->x,s->y); + } else { + playerdist = 9999; + } + if (player2) { + playerdist2 = getdistance(player2->x,player2->y,s->x,s->y); + } else { + playerdist2 = 9999; + } + if (playerdist1 < playerdist2) { + playerdist = playerdist1; + } else { + playerdist = playerdist2; + } + if (playerdist <= (TILEW*10)) { s->timer1 = 0; s->flies = F_FLYHORZ; @@ -3474,10 +3671,10 @@ int movesprite(sprite_t *s) { /* walk back and forwards */ /* drop if player is close */ - xdiff = player->x - s->x; - if (xdiff < 0) xdiff =-xdiff; + xdiff = getxdisttoplayer(s); + xdiff = abs(xdiff); - if ((player->y > s->y) && (xdiff <= (TILEW*2)) && (s->timer1 == 0)) { + if (isplayerbelow(s) && (xdiff <= (TILEW*2)) && (s->timer1 == 0)) { s->timer1 = 200; s->flies = B_FALSE; s->falling = B_TRUE; @@ -3512,20 +3709,20 @@ int movesprite(sprite_t *s) { s->dead = D_FINAL; } } else if (s->id == P_PINKCLOUD) { - if (levelcomplete == LV_CLOUD) { + if (s->timer1 == LV_CLOUD) { SDL_Surface *ts; double targx,targy; double amtleft; double xdis,ydis,dis; int turnsleft; - if (!player->dead) { + if (!s->owner->dead) { /* If small, grow and move towards player's feet (at a speed which will get us there when we are fully grown. */ - targx = player->x; - targy = player->y + (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2); + targx = s->owner->x; + targy = s->owner->y + (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2); if (s->img->w < imageset[P_PINKCLOUD].img[F_WALK1]->w) { // grow @@ -3545,12 +3742,11 @@ int movesprite(sprite_t *s) { s->x = targx; s->y = targy; s->rotated = 0; - if (levelcomplete == LV_CLOUD) { - levelcomplete = LV_CLOUDLOOP; - // stop the player teleporting if required - if (player->teleporting) { - stopteleporting(player); - } + + s->timer1 = LV_CLOUDLOOP; + // stop the player teleporting if required + if (s->owner->teleporting) { + stopteleporting(s->owner); } } else { @@ -3586,7 +3782,7 @@ int movesprite(sprite_t *s) { keeponscreen(s); } } - } else if (levelcomplete == LV_CLOUDLOOP) { + } else if (s->timer1 == LV_CLOUDLOOP) { // make sure we are on the screen!! // should never happen, but... @@ -3596,14 +3792,14 @@ int movesprite(sprite_t *s) { if (s->y >= 480) s->y = 240; // stick player to us - player->x = s->x; - player->y = s->y - (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2); + s->owner->x = s->x; + s->owner->y = s->y - (imageset[P_PINKCLOUD].img[F_WALK1]->h / 2); // turn off player attributes - player->climbing = B_FALSE; - player->netting = B_FALSE; - player->slamming = B_FALSE; - player->jumping = B_FALSE; + s->owner->climbing = B_FALSE; + s->owner->netting = B_FALSE; + s->owner->slamming = B_FALSE; + s->owner->jumping = B_FALSE; // keep turning towards exit (2 degrees at a time) s->angle += (PCTURN * (M_PI/180)); @@ -3646,16 +3842,27 @@ int movesprite(sprite_t *s) { if (s->x < s->img->w/2) { s->x = s->img->w/2; } - if (s->y < player->img->h/2) { - s->y = player->img->h/2; + if (s->y < s->owner->img->h/2) { + s->y = s->owner->img->h/2; } // if we've done at least one revolution and moving right... - if (s->rotated >= 360 * (M_PI/180)) { - if (s->xs > abs(s->ys)) { - // level clear! - levelcomplete = LV_NEXTLEV; + if (s->rotated >= 360 * (M_PI/180)) { // done one revolution + if (s->xs > abs(s->ys)) { // and moving right + sprite_t *c; + int ready = B_TRUE; + // and other cloud is finished... + for (c = sprite ; c ; c = c->next) { + if ((c->id == P_PINKCLOUD) && (c->timer1 != LV_CLOUDLOOP)) { + ready = B_FALSE; + } + } + + if (ready) { + // level clear! + levelcomplete = LV_NEXTLEV; + } return B_TRUE; } } @@ -3676,7 +3883,7 @@ int movesprite(sprite_t *s) { s->y -= PCSHRINKSPEED; } } else if (s->id == P_BLACKCLOUD) { - if ((player->dead) || (levelcomplete)) { + if ((player && player->dead) || (player2 && player2->dead) || (levelcomplete)) { if (s->size <= 0.2) { s->dead = D_FINAL; /* reset hurryup timer */ @@ -3696,12 +3903,12 @@ int movesprite(sprite_t *s) { } else { if (!s->invuln) { if ((s->xs == -99) || (s->ys == -99)) { - if (player->y > s->y) { + if (isplayerabove(s)) { s->ys = 0.5; } else { s->ys = -0.5; } - if (player->x > s->x) { + if (isplayerright(s)) { s->xs = 1; } else { s->xs = -1; @@ -3766,6 +3973,8 @@ void dotileeffects(sprite_t *s) { int state = 0; int tilex,tiley; + if (!s) return; + if (iseffect(s->id) || isbullet(s->id)) { return; } @@ -3775,8 +3984,8 @@ void dotileeffects(sprite_t *s) { } // no tile efffects for machine gun - if (player->powerup == PW_GUNNER) { - if (s == player) { + if (haspowerupany(PW_GUNNER)) { + if (isplayer(s)) { return; } } @@ -3787,7 +3996,7 @@ void dotileeffects(sprite_t *s) { // teleporters if ((tt->id == T_TELEPORT) || (tt->id == T_TELEPORT2)) { //if (!isendoflev()) { // can't enter teleporters after level end to avoid cloud moving too far - if (s == player || ismonster(s->id)) { + if (isplayer(s) || ismonster(s->id)) { if (s->id != P_BLACKCLOUD) { if (!s->teleporting) { playfx(FX_TELEPORT); @@ -3831,7 +4040,7 @@ void dotileeffects(sprite_t *s) { // CHECKS WHICH COULD APPLY TO TILES UNDER AND SLIGHTLY LEFT/RIGHT OF US while (!finished) { if (tt->id == T_RIGHT) { - if (player->powerup != PW_CLOCK) { + if (globpowerup != PW_CLOCK) { if (!ismonster(s->id) && !isfruit(s->id)) { movex(s, 1.5); } else if (s->id == P_PLANT) { @@ -3840,7 +4049,7 @@ void dotileeffects(sprite_t *s) { finished = B_TRUE; } } else if (tt->id == T_LEFT) { - if (player->powerup != PW_CLOCK) { + if (globpowerup != PW_CLOCK) { if (!ismonster(s->id) && !isfruit(s->id)) { movex(s, -1.5); } else if (s->id == P_PLANT) { @@ -3849,8 +4058,8 @@ void dotileeffects(sprite_t *s) { } finished = B_TRUE; } else if ((tt->id == T_ICE) || (tt->id == T_ICETOP)) { - if (s == player) { - if (player->powerup != PW_CLOCK) { + if (isplayer(s)) { + if (globpowerup != PW_CLOCK) { if (!s->moved) { movex(s, s->dir*s->speed); s->moved = MV_ICE; @@ -3929,17 +4138,17 @@ void dotileeffects(sprite_t *s) { // initial transition to a new level void drawlevel(void) { int x,y; - int dstx,dsty,xdis,ydis; + int dstx[2],dsty[2],xdis[2],ydis[2]; double turns; - double pspeed; - double dist; + double pspeed[2]; + double dist[2]; SDL_Rect area,dst; int speed = 16; - SDL_Surface *playerbg; - SDL_Surface *cloudbg; + SDL_Surface *playerbg, *playerbg2; + SDL_Surface *cloudbg,*cloudbg2; - sprite_t tempcloud; - sprite_t *cloud; + sprite_t tempcloud, tempcloud2; + sprite_t *cloud, *cloud2; if (temps) { @@ -3955,34 +4164,57 @@ void drawlevel(void) { SDL_DisplayFormat(temps); - // init cloud - cloud = &tempcloud; - cloud->id = P_PINKCLOUD; - cloud->iceimg = NULL; - setdefaults(cloud); - // redo image - cloud->img =rotozoomSurfaceXY(imageset[P_PINKCLOUD].img[F_WALK1],0,1,1,0); + // init clouds + if (player) { + cloud = &tempcloud; + cloud->id = P_PINKCLOUD; + cloud->iceimg = NULL; + setdefaults(cloud); + // redo image + cloud->img =rotozoomSurfaceXY(imageset[P_PINKCLOUD].img[F_WALK1],0,1,1,0); + // set player image + player->img = imageset[player->id].img[F_SHOOT]; + // create buffer for player background + playerbg = SDL_CreateRGBSurface(SDL_SWSURFACE, + player->img->w+1, player->img->h+1, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_DisplayFormat(playerbg); + // create buffer for cloud background + cloudbg = SDL_CreateRGBSurface(SDL_SWSURFACE, + cloud->img->w+1, cloud->img->h+1, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_DisplayFormat(cloudbg); - // set player image - player->img = imageset[player->id].img[F_SHOOT]; - - - - // create buffer for player background - playerbg = SDL_CreateRGBSurface(SDL_SWSURFACE, - player->img->w+1, player->img->h+1, - screen->format->BitsPerPixel, screen->format->Rmask, - screen->format->Gmask,screen->format->Bmask, - screen->format->Amask); - SDL_DisplayFormat(playerbg); - // create buffer for cloud background - cloudbg = SDL_CreateRGBSurface(SDL_SWSURFACE, - cloud->img->w+1, cloud->img->h+1, - screen->format->BitsPerPixel, screen->format->Rmask, - screen->format->Gmask,screen->format->Bmask, - screen->format->Amask); - SDL_DisplayFormat(cloudbg); + } + if (player2) { + cloud2 = &tempcloud2; + cloud2->id = P_PINKCLOUD; + cloud2->iceimg = NULL; + setdefaults(cloud2); + // redo image + cloud2->img =rotozoomSurfaceXY(imageset[P_PINKCLOUD].img[F_WALK1],0,1,1,0); + // set player image + player2->img = imageset[player2->id].img[F_SHOOT]; + // create buffer for player background + playerbg2 = SDL_CreateRGBSurface(SDL_SWSURFACE, + player2->img->w+1, player2->img->h+1, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_DisplayFormat(playerbg2); + // create buffer for cloud background + cloudbg2 = SDL_CreateRGBSurface(SDL_SWSURFACE, + cloud2->img->w+1, cloud2->img->h+1, + screen->format->BitsPerPixel, screen->format->Rmask, + screen->format->Gmask,screen->format->Bmask, + screen->format->Amask); + SDL_DisplayFormat(cloudbg2); + } // draw the full level onto the temporary surface for (x = 0; x < LEVELW; x++) { @@ -3992,13 +4224,25 @@ void drawlevel(void) { } - // figure out where the player's new start position is - dstx = (curlevel->p1x * TILEW) + (TILEW/2); - dsty = (curlevel->p1y * TILEH) + TILEH-2; + // figure out where the players' new start positions are + if (player) { + dstx[0] = (curlevel->p1x * TILEW) + (TILEW/2); + dsty[0] = (curlevel->p1y * TILEH) + TILEH-2; + } + if (player2) { + dstx[1] = (curlevel->p2x * TILEW) + (TILEW/2); + dsty[1] = (curlevel->p2y * TILEH) + TILEH-2; + } // figure out distance to newposition - xdis = player->x - dstx; if (xdis < 0) xdis = -xdis; - ydis = player->y - dsty; if (ydis < 0) ydis = -ydis; + if (player) { + xdis[0] = player->x - dstx[0]; if (xdis[0] < 0) xdis[0] = -xdis[0]; + ydis[0] = player->y - dsty[0]; if (ydis[0] < 0) ydis[0] = -ydis[0]; + } + if (player2) { + xdis[1] = player2->x - dstx[1]; if (xdis[1] < 0) xdis[1] = -xdis[1]; + ydis[1] = player2->y - dsty[1]; if (ydis[1] < 0) ydis[1] = -ydis[1]; + } @@ -4021,12 +4265,14 @@ void drawlevel(void) { if (turns < 1) turns = 1; // figure out how fast player needs to move to get there in time - //pxspeed = ceil((double)xdis / (double)turns); if (pxspeed < 1) pxspeed = 1; - //pyspeed = ceil((double)ydis / (double)turns); if (pyspeed < 1) pyspeed = 1; - //if (pxspeed > pyspeed) pspeed = pxspeed; - // else pspeed = pyspeed; - dist = sqrt((xdis*xdis) + (ydis*ydis)); - pspeed = dist / turns; + if (player) { + dist[0] = sqrt((xdis[0]*xdis[0]) + (ydis[0]*ydis[0])); + pspeed[0] = dist[0] / turns; + } + if (player2) { + dist[1] = sqrt((xdis[1]*xdis[1]) + (ydis[1]*ydis[1])); + pspeed[1] = dist[1] / turns; + } // just to be sure //pspeed += 1; @@ -4037,10 +4283,17 @@ void drawlevel(void) { // the real one along. for (x = 0; x < 640; x += speed) { // move player - moveto(player,dstx,dsty,pspeed,pspeed); + if (player) moveto(player,dstx[0],dsty[0],pspeed[0],pspeed[0]); + if (player2) moveto(player2,dstx[1],dsty[1],pspeed[1],pspeed[1]); // set cloud location - cloud->x = player->x; - cloud->y = player->y + (cloud->img->h / 2); + if (player) { + cloud->x = player->x; + cloud->y = player->y + (cloud->img->h / 2); + } + if (player2) { + cloud2->x = player2->x; + cloud2->y = player2->y + (cloud2->img->h / 2); + } // shuffle real screen area.x = 0; @@ -4066,15 +4319,28 @@ void drawlevel(void) { dst.h = 0; SDL_BlitSurface(temps, &area, screen, &dst); - // remember area behind player - player->img = imageset[player->id].img[F_SHOOT]; - grabbehind(player, playerbg); - grabbehind(cloud, cloudbg); + // remember area behind players + if (player) { + player->img = imageset[player->id].img[F_SHOOT]; + grabbehind(player, playerbg); + grabbehind(cloud, cloudbg); + } + if (player2) { + player2->img = imageset[player2->id].img[F_SHOOT]; + grabbehind(player2, playerbg2); + grabbehind(cloud2, cloudbg2); + } // draw player if (curlevelnum != 1) { - drawsprite(player); - drawsprite(cloud); + if (player) { + drawsprite(player); + drawsprite(cloud); + } + if (player2) { + drawsprite(player2); + drawsprite(cloud2); + } } // update screen @@ -4082,18 +4348,32 @@ void drawlevel(void) { SDL_UpdateRect(screen, 0,0,640,480); SDL_framerateDelay(&manager); - // remove player + // remove players if (curlevelnum != 1) { - area.x = player->x - player->img->w/2; - area.y = player->y - player->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(playerbg, NULL, screen, &area ); - area.x = cloud->x - cloud->img->w/2; - area.y = cloud->y - cloud->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(cloudbg, NULL, screen, &area ); + if (player) { + area.x = player->x - player->img->w/2; + area.y = player->y - player->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg, NULL, screen, &area ); + area.x = cloud->x - cloud->img->w/2; + area.y = cloud->y - cloud->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg, NULL, screen, &area ); + } + if (player2) { + area.x = player2->x - player2->img->w/2; + area.y = player2->y - player2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg2, NULL, screen, &area ); + area.x = cloud2->x - cloud2->img->w/2; + area.y = cloud2->y - cloud2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg2, NULL, screen, &area ); + } } } } else if (oldexitdir == D_UP) { @@ -4101,10 +4381,17 @@ void drawlevel(void) { // the real one along. for (y = 0; y < 480; y += speed) { // move player - moveto(player,dstx,dsty,pspeed,pspeed); + if (player) moveto(player,dstx[0],dsty[0],pspeed[0],pspeed[0]); + if (player2) moveto(player2,dstx[1],dsty[1],pspeed[1],pspeed[1]); // set cloud location - cloud->x = player->x; - cloud->y = player->y + (cloud->img->h / 2); + if (player) { + cloud->x = player->x; + cloud->y = player->y + (cloud->img->h / 2); + } + if (player2) { + cloud2->x = player2->x; + cloud2->y = player2->y + (cloud2->img->h / 2); + } // shuffle real screen area.x = 0; @@ -4131,14 +4418,28 @@ void drawlevel(void) { SDL_BlitSurface(temps, &area, screen, &dst); // remember area behind player - player->img = imageset[player->id].img[F_SHOOT]; - grabbehind(player, playerbg); - grabbehind(cloud, cloudbg); + if (player) { + player->img = imageset[player->id].img[F_SHOOT]; + grabbehind(player, playerbg); + grabbehind(cloud, cloudbg); + } + if (player2) { + player2->img = imageset[player2->id].img[F_SHOOT]; + grabbehind(player2, playerbg2); + grabbehind(cloud2, cloudbg2); + } + // draw player if (curlevelnum != 1) { - drawsprite(player); - drawsprite(cloud); + if (player) { + drawsprite(player); + drawsprite(cloud); + } + if (player2) { + drawsprite(player2); + drawsprite(cloud2); + } } // update screen @@ -4146,18 +4447,32 @@ void drawlevel(void) { SDL_UpdateRect(screen, 0,0,640,480); SDL_framerateDelay(&manager); - // remove player + // remove players if (curlevelnum != 1) { - area.x = player->x - player->img->w/2; - area.y = player->y - player->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(playerbg, NULL, screen, &area ); - area.x = cloud->x - cloud->img->w/2; - area.y = cloud->y - cloud->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(cloudbg, NULL, screen, &area ); + if (player) { + area.x = player->x - player->img->w/2; + area.y = player->y - player->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg, NULL, screen, &area ); + area.x = cloud->x - cloud->img->w/2; + area.y = cloud->y - cloud->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg, NULL, screen, &area ); + } + if (player2) { + area.x = player2->x - player2->img->w/2; + area.y = player2->y - player2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg2, NULL, screen, &area ); + area.x = cloud2->x - cloud2->img->w/2; + area.y = cloud2->y - cloud2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg2, NULL, screen, &area ); + } } } } else if (oldexitdir == D_DOWN) { @@ -4165,10 +4480,17 @@ void drawlevel(void) { // the real one along. for (y = 0; y < 480; y += speed) { // move player - moveto(player,dstx,dsty,pspeed,pspeed); + if (player) moveto(player,dstx[0],dsty[0],pspeed[0],pspeed[0]); + if (player2) moveto(player2,dstx[1],dsty[1],pspeed[1],pspeed[1]); // set cloud location - cloud->x = player->x; - cloud->y = player->y + (cloud->img->h / 2); + if (player) { + cloud->x = player->x; + cloud->y = player->y + (cloud->img->h / 2); + } + if (player2) { + cloud2->x = player2->x; + cloud2->y = player2->y + (cloud2->img->h / 2); + } // shuffle real screen area.x = 0; @@ -4194,15 +4516,28 @@ void drawlevel(void) { dst.h = 0; SDL_BlitSurface(temps, &area, screen, &dst); - // remember area behind player - player->img = imageset[player->id].img[F_SHOOT]; - grabbehind(player, playerbg); - grabbehind(cloud, cloudbg); + // remember area behind players + if (player) { + player->img = imageset[player->id].img[F_SHOOT]; + grabbehind(player, playerbg); + grabbehind(cloud, cloudbg); + } + if (player2) { + player2->img = imageset[player2->id].img[F_SHOOT]; + grabbehind(player2, playerbg2); + grabbehind(cloud2, cloudbg2); + } // draw player if (curlevelnum != 1) { - drawsprite(player); - drawsprite(cloud); + if (player) { + drawsprite(player); + drawsprite(cloud); + } + if (player2) { + drawsprite(player2); + drawsprite(cloud2); + } } // update screen @@ -4210,18 +4545,33 @@ void drawlevel(void) { SDL_UpdateRect(screen, 0,0,640,480); SDL_framerateDelay(&manager); - // remove player + + // remove players if (curlevelnum != 1) { - area.x = player->x - player->img->w/2; - area.y = player->y - player->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(playerbg, NULL, screen, &area ); - area.x = cloud->x - cloud->img->w/2; - area.y = cloud->y - cloud->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(cloudbg, NULL, screen, &area ); + if (player) { + area.x = player->x - player->img->w/2; + area.y = player->y - player->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg, NULL, screen, &area ); + area.x = cloud->x - cloud->img->w/2; + area.y = cloud->y - cloud->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg, NULL, screen, &area ); + } + if (player2) { + area.x = player2->x - player2->img->w/2; + area.y = player2->y - player2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg2, NULL, screen, &area ); + area.x = cloud2->x - cloud2->img->w/2; + area.y = cloud2->y - cloud2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg2, NULL, screen, &area ); + } } } } else { // RIGHT right, or default @@ -4229,10 +4579,17 @@ void drawlevel(void) { // the real one along. for (x = 0; x < 640; x += speed) { // move player - moveto(player,dstx,dsty,pspeed,pspeed); + if (player) moveto(player,dstx[0],dsty[0],pspeed[0],pspeed[0]); + if (player2) moveto(player2,dstx[1],dsty[1],pspeed[1],pspeed[1]); // set cloud location - cloud->x = player->x; - cloud->y = player->y + (cloud->img->h / 2); + if (player) { + cloud->x = player->x; + cloud->y = player->y + (cloud->img->h / 2); + } + if (player2) { + cloud2->x = player2->x; + cloud2->y = player2->y + (cloud2->img->h / 2); + } // shuffle real screen area.x = speed; @@ -4258,15 +4615,28 @@ void drawlevel(void) { dst.h = 0; SDL_BlitSurface(temps, &area, screen, &dst); - // remember area behind player - player->img = imageset[player->id].img[F_SHOOT]; - grabbehind(player, playerbg); - grabbehind(cloud, cloudbg); + // remember area behind players + if (player) { + player->img = imageset[player->id].img[F_SHOOT]; + grabbehind(player, playerbg); + grabbehind(cloud, cloudbg); + } + if (player2) { + player2->img = imageset[player2->id].img[F_SHOOT]; + grabbehind(player2, playerbg2); + grabbehind(cloud2, cloudbg2); + } // draw player if (curlevelnum != 1) { - drawsprite(player); - drawsprite(cloud); + if (player) { + drawsprite(player); + drawsprite(cloud); + } + if (player2) { + drawsprite(player2); + drawsprite(cloud2); + } } // update screen @@ -4274,25 +4644,46 @@ void drawlevel(void) { SDL_UpdateRect(screen, 0,0,640,480); SDL_framerateDelay(&manager); - // remove player + // remove players if (curlevelnum != 1) { - area.x = player->x - player->img->w/2; - area.y = player->y - player->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(playerbg, NULL, screen, &area ); - area.x = cloud->x - cloud->img->w/2; - area.y = cloud->y - cloud->img->h; - area.w = 0; - area.h = 0; - SDL_BlitSurface(cloudbg, NULL, screen, &area ); + if (player) { + area.x = player->x - player->img->w/2; + area.y = player->y - player->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg, NULL, screen, &area ); + area.x = cloud->x - cloud->img->w/2; + area.y = cloud->y - cloud->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg, NULL, screen, &area ); + } + if (player2) { + area.x = player2->x - player2->img->w/2; + area.y = player2->y - player2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(playerbg2, NULL, screen, &area ); + area.x = cloud2->x - cloud2->img->w/2; + area.y = cloud2->y - cloud2->img->h; + area.w = 0; + area.h = 0; + SDL_BlitSurface(cloudbg2, NULL, screen, &area ); + } } } } - SDL_FreeSurface(playerbg); - SDL_FreeSurface(cloudbg); - SDL_FreeSurface(cloud->img); + if (player) { + SDL_FreeSurface(playerbg); + SDL_FreeSurface(cloudbg); + SDL_FreeSurface(cloud->img); + } + if (player2) { + SDL_FreeSurface(playerbg2); + SDL_FreeSurface(cloudbg2); + SDL_FreeSurface(cloud2->img); + } levelcomplete = B_FALSE; } @@ -4304,6 +4695,8 @@ double getspeed(sprite_t *s ) { if (s == player) { speed = s->speed; + } else if (s == player2) { + speed = s->speed; } else if (id == P_SNAIL) { if (s->recoiling) { speed = 2; @@ -4344,8 +4737,8 @@ double getspeed(sprite_t *s ) { } } - if ((player->powerup == PW_SPRAYUP) || (player->powerup == PW_SPRAYDOWN)) { - if (s != player) { + if ((globpowerup == PW_SPRAYUP) || (globpowerup == PW_SPRAYDOWN)) { + if (!isplayer(s)) { speed /= 2; } } @@ -4482,6 +4875,7 @@ void drawscore(void) { SDL_Color scorecol; int i; int numtoshow; + int numtoshow2; int scoreval; if (forcegoodcard) { @@ -4494,51 +4888,145 @@ void drawscore(void) { scorecol = red; } - if (wantframerate) { - scoreval = fps; - sprintf(tempm, "%d fps",scoreval); - } else { - scoreval = player->score; - addcommas(tempm, scoreval); + if (player) { + + if (wantframerate) { + scoreval = fps; + sprintf(tempm, "%d fps",scoreval); + } else { + scoreval = player->score; + addcommas(tempm, scoreval); + } + + + /* shadow */ + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, black); + area.x = P1SCOREX-2; + area.y = SCOREY; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); + /* score */ + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, scorecol); + area.x = P1SCOREX; + area.y = SCOREY-2; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); + + // lives + + // show 1 less than lives + numtoshow = player->lives-1; + area.x = P1LIVESX; + area.y = LIVESY; + area.w = 0; + area.h = 0; + + // show "x5" for lots of lives + while (numtoshow >= 5) { + SDL_BlitSurface(head5, NULL, screen, &area); + area.x += (head->w + 3); + numtoshow -= 5; + } + + for (i = 0; i < numtoshow; i++) { + SDL_BlitSurface(head, NULL, screen, &area); + area.x += (head->w + 3); + } + + + // cards + if (levelcomplete != LV_DOPOKER) { + area.x = CARDX; + area.y = CARDY; + area.w = 0; + area.h = 0; + for (i = 0; i < player->numcards; i++) { + SDL_Surface *cardimg; + cardimg = imageset[player->card[i]].img[F_WALK1]; + SDL_BlitSurface(cardimg, NULL, screen, &area); + area.x += (cardimg->w + 2); + } + } } + if (player2) { + if (wantframerate) { + scoreval = fps; + sprintf(tempm, "%d fps",scoreval); + } else { + scoreval = player2->score; + addcommas(tempm, scoreval); + } - /* shadow */ - score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, black); - area.x = 18; - area.y = 7; - area.w = 0; - area.h = 0; - SDL_BlitSurface(score, NULL, screen, &area); - SDL_FreeSurface(score); - /* score */ - score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, scorecol); - area.x = 20; - area.y = 5; - area.w = 0; - area.h = 0; - SDL_BlitSurface(score, NULL, screen, &area); - SDL_FreeSurface(score); - // lives - - // show 1 less than lives - numtoshow = player->lives-1; - area.x = 20; - area.y = 25; - area.w = 0; - area.h = 0; + /* shadow */ + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, black); + area.x = 640 - score->w - P1SCOREX - 2; + area.y = SCOREY-2; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); + /* score */ + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, scorecol); + area.x = 640 - score->w - P1SCOREX; + area.y = SCOREY; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); - // show "x5" for lots of lives - while (numtoshow >= 5) { - SDL_BlitSurface(head5, NULL, screen, &area); - area.x += (head->w + 3); - numtoshow -= 5; - } + // lives + + // show 1 less than lives + numtoshow = player2->lives-1; + area.x = 640 - P1LIVESX; + area.y = LIVESY; + area.w = 0; + area.h = 0; - for (i = 0; i < numtoshow; i++) { - SDL_BlitSurface(head, NULL, screen, &area); - area.x += (head->w + 3); + // go left correct amount + numtoshow2 = numtoshow; + while (numtoshow2 >= 5) { + area.x -= (head->w + 3); + numtoshow2 -= 5; + } + for (i = 0; i < numtoshow2; i++) { + area.x -= (head->w + 3); + } + + // now start displaying + + // show "x5" for lots of lives + while (numtoshow >= 5) { + SDL_BlitSurface(head5, NULL, screen, &area); + area.x += (head->w + 3); + numtoshow -= 5; + } + + for (i = 0; i < numtoshow; i++) { + SDL_BlitSurface(head, NULL, screen, &area); + area.x += (head->w + 3); + } + + + // cards + if (levelcomplete != LV_DOPOKER) { + area.x = 640 - CARDX - (5*(imageset[P_FIRSTCARD].img[F_WALK1]->w + 2)); + area.y = CARDY; + area.w = 0; + area.h = 0; + for (i = 0; i < player2->numcards; i++) { + SDL_Surface *cardimg; + cardimg = imageset[player2->card[i]].img[F_WALK1]; + SDL_BlitSurface(cardimg, NULL, screen, &area); + area.x += (cardimg->w + 2); + } + } } // level # @@ -4561,20 +5049,6 @@ void drawscore(void) { SDL_FreeSurface(score); - // cards - if (levelcomplete != LV_DOPOKER) { - area.x = 20; - area.y = 55; - area.w = 0; - area.h = 0; - for (i = 0; i < player->numcards; i++) { - SDL_Surface *cardimg; - cardimg = imageset[player->card[i]].img[F_WALK1]; - SDL_BlitSurface(cardimg, NULL, screen, &area); - area.x += (cardimg->w + 2); - } - } - drawcredits(); } @@ -4750,6 +5224,8 @@ void drawnetting(sprite_t *s) { int sx; int xx; SDL_Rect area; + + if (!s) return; if (s->netting) { int y,yy; @@ -4832,7 +5308,7 @@ void drawnetting(sprite_t *s) { drawdotline16(screen,s->x,s->y - s->img->h/2,x, y, *col1,*col2); // add sparkles - for (ii = 0 ; ii < player->netmax; ii++) { + for (ii = 0 ; ii < s->netmax; ii++) { addsprite(P_SPARKLE, s->netxstart + (rand() % 8) - 4, s->netystart + (rand() % 8) - 4, "sparkle"); } } @@ -4869,6 +5345,8 @@ void removesprite(sprite_t *s) { int startx,starty,endx,endy; int x,y; + if (s == NULL) return; + // find topleft-most tile gettileat(s->x - s->img->w, s->y - s->img->h,&startx,&starty); @@ -5128,19 +5606,21 @@ void dogravity(sprite_t *s) { tiletype_t *tt; int tilex,tiley; + if (!s) return; if (s->id == P_PINKCLOUD) return; +if (s->id == P_TICK) printf("9 dogravity for tick\n"); // only player can move if you have a clock - if (player->powerup == PW_CLOCK) { - if (!iseffect(s->id) && (s != player) && !s->caughtby && !s->dead) { + if (globpowerup == PW_CLOCK) { + if (!iseffect(s->id) && (!isplayer(s)) && !s->caughtby && !s->dead) { return; } } - // no gravity for player if you have the machine gun - if (player->powerup == PW_GUNNER) { - if (s == player) { + // no gravity for players if you have the machine gun + if (haspowerupany(PW_GUNNER)) { + if (isplayer(s)) { return; } } @@ -5165,6 +5645,7 @@ void dogravity(sprite_t *s) { } +if (s->id == P_TICK) printf("0 dogravity for tick\n"); if (s->dead) return; if (s->flies && !s->iced) return; // no gravity if you fly, but ice cancels flying if (s->id != P_KSSHELL) { @@ -5172,6 +5653,7 @@ void dogravity(sprite_t *s) { } if (isbullet(s->id)) return; + //if (isonladder(s) && !s->falling && !s->jumping) { /* if (isonladder(s) ) { @@ -5192,7 +5674,7 @@ void dogravity(sprite_t *s) { } // update water stats - if (s == player || ismonster(s->id)) { + if (isplayer(s) || ismonster(s->id)) { if (isinwater(s)) { if (!s->swimming) { // we just entered the water @@ -5206,17 +5688,28 @@ void dogravity(sprite_t *s) { } // give player a mask if they don't have one - if ((s == player) && (s->hasmask)) { - if (mask == NULL) { - mask = addsprite(P_MASK, player->x + MASKOFFSETX*player->dir, player->y + MASKOFFSETY, "mask"); + if (isplayer(s) && (s->hasmask)) { + sprite_t *ms; + int found = B_FALSE; + // is there one already? + for (ms = sprite; ms ; ms = ms->next) { + if ((ms->id == P_MASK) && (ms->owner == s)) { + found = B_TRUE; + break; + } + } + + if (!found) { + ms = addsprite(P_MASK, s->x + MASKOFFSETX*s->dir, s->y + MASKOFFSETY, "mask"); + ms->owner = s; } } // adjust x pos so we don't get stuck in a wall - if (s == player) adjustx(s, F_SWIM1); + if (isplayer(s)) adjustx(s, F_SWIM1); else adjustx(s, F_WALK1); - if (s == player) { + if (isplayer(s)) { // dim the music Mix_VolumeMusic(MIX_MAX_VOLUME/3); } @@ -5231,14 +5724,18 @@ void dogravity(sprite_t *s) { } } else { if (s->swimming) { + sprite_t *ms; // exitted the water s->swimming = B_FALSE; - if (s == player) { + if (isplayer(s)) { Mix_VolumeMusic(MIX_MAX_VOLUME); } // get rid of the mask - if (mask) { - mask->dead = D_FINAL; + for (ms = sprite; ms ; ms = ms->next) { + if ((ms->id == P_MASK) && (ms->owner == s)) { + s->dead = D_FINAL; + break; + } } } } @@ -5284,17 +5781,17 @@ void dogravity(sprite_t *s) { } // handle ring - if (s == player) { - if (player->powerup == PW_RINGJUMP) { + if (isplayer(s)) { + if (s->powerup == PW_RINGJUMP) { if (timer % 2 == 0) { int xx,yy; // add sparkle - xx = player->x + (rand() % player->img->w) - (player->img->w/2); - yy = player->y - (rand() % (player->img->h/2)); + xx = s->x + (rand() % s->img->w) - (s->img->w/2); + yy = s->y - (rand() % (s->img->h/2)); addsprite(P_SPARKLE, xx, yy, "sparkle"); // gain points - addscore(player, 65); + addscore(s, 65); } } } @@ -5337,6 +5834,7 @@ void dogravity(sprite_t *s) { } if ((s->id == P_KINGRAT) && (s->timer1 == KRS_FALL)) { // special case // king rat drops until he is at player height + // TODO: 2player if ((player->dead) || (s->y < player->y)) { // above player ontheground = B_FALSE; } else { // above player @@ -5481,14 +5979,16 @@ void dogravity(sprite_t *s) { curfruittype = 0; // if we have a mace, add an explosion and play a thump sound - if (player->powerup == PW_MACE) { + if (s->powerup == PW_MACE) { // play sound playfx(FX_MACE); // find location of mace for (s2 = sprite; s2 ; s2 = s2->next) { if (s2->id == P_MACE) { - break; + if (s2->owner == s) { + break; + } } } @@ -5544,13 +6044,13 @@ void dogravity(sprite_t *s) { } } - if ((player->powerup == PW_MACE) && (s2->id == P_SNAIL)) { + if ((s->powerup == PW_MACE) && (s2->id == P_SNAIL)) { // turn into a slug so that it really dies s2->id = P_SLUG; } die(s2); - if ((player->powerup == PW_MACE) || (s2->id != P_SNAIL)) { + if ((s->powerup == PW_MACE) || (s2->id != P_SNAIL)) { pointsinc *= 2; psize += 10; gotsomething++; @@ -5571,7 +6071,7 @@ void dogravity(sprite_t *s) { } // if we have a powerup, centre of net is the mace position - if (player->powerup == PW_MACE) { + if (s->powerup == PW_MACE) { xnet = macex; ynet = macey; } @@ -5579,7 +6079,7 @@ void dogravity(sprite_t *s) { // only check for hitting something if we already had a monster caught, // or we have a mace - if (gotsomething || (player->powerup == PW_MACE)) { + if (gotsomething || (s->powerup == PW_MACE)) { /* kill anything we hit */ for (s2 = sprite; s2 ; s2 = s2->next) { if ((s2->caughtby != s) && !s2->dead && !s2->invuln && (ismonster(s2->id))) { @@ -5637,7 +6137,7 @@ void dogravity(sprite_t *s) { if (s3->caughtby) { uncatch(s3); - player->netcaught--; + s->caughtby->netcaught--; } die(s3); } @@ -5656,7 +6156,7 @@ void dogravity(sprite_t *s) { s2->willbecome = -1; } else { // if player isn't fast, give a speed. - if (player->speed != PLAYERFAST) { + if (!haspowerupany(P_SPEED)) { s2->willbecome = P_SPEED; } else if (!gotcard & (gotsomething >= 4)) { // card for killing 5 at once s2->willbecome = getrandomcard(); @@ -5673,7 +6173,7 @@ void dogravity(sprite_t *s) { } } - } else if (player->powerup == PW_MACE) { + } else if (s->powerup == PW_MACE) { s2->willbecome = P_DIAMOND; } else { // should never happen @@ -5824,17 +6324,17 @@ int movex(sprite_t *s,double amt) { s->moved = MV_WALK; // rings - if (s == player) { - if (player->powerup == PW_RINGWALK) { - if (isonground(player) && !player->swimming) { + if (isplayer(s)) { + if (s->powerup == PW_RINGWALK) { + if (isonground(s) && !s->swimming) { int xx,yy; // add sparkle - xx = player->x + (rand() % player->img->w) - (player->img->w/2); - yy = player->y - (rand() % (player->img->h/2)); + xx = s->x + (rand() % s->img->w) - (s->img->w/2); + yy = s->y - (rand() % (s->img->h/2)); addsprite(P_SPARKLE, xx, yy, "sparkle"); // gain points - addscore(player, 15); + addscore(s, 15); } } } @@ -5876,108 +6376,123 @@ void adjustheight(sprite_t *s) { } } -int dofruiteffect(sprite_t *s) { +int dofruiteffect(sprite_t *pp, sprite_t *s) { if (s->id == P_SPEED) { playfx(FX_POWERUP); - player->speed = PLAYERFAST; + pp->speed = PLAYERFAST; addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, "Speed up!", &white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_BIGSPEED) { + // both players playfx(FX_POWERUP); - player->permspeed = B_TRUE; - player->speed = PLAYERFAST; + if (player) { + player->permspeed = B_TRUE; + player->speed = PLAYERFAST; + } + if (player2) { + player2->permspeed = B_TRUE; + player2->speed = PLAYERFAST; + } addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_LIFE, "SUPER SPEED UP!", &cyan,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_BIGSCUBA) { + // both players playfx(FX_POWERUP); - player->permmask = B_TRUE; - player->hasmask = B_TRUE; + if (player) { + player->permmask = B_TRUE; + player->hasmask = B_TRUE; + } + if (player2) { + player2->permmask = B_TRUE; + player2->hasmask = B_TRUE; + } addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_LIFE, "PERMENANT MASK!", &cyan,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_NUMNETS) { playfx(FX_POWERUP); - if (player->netmax < 4) { - player->netmax++; + if (pp->netmax < 4) { + pp->netmax++; } - sprintf(tempm, "%d nets!",player->netmax); + sprintf(tempm, "%d nets!",pp->netmax); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_BIGNET) { playfx(FX_POWERUP); - player->netbig = B_TRUE; + pp->netbig = B_TRUE; sprintf(tempm, "Big net!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_TROPHY) { // all powerups playfx(FX_POWERUP); - player->netmax = 4; // all nets - player->netbig = B_TRUE; // big net - player->speed = 2; // fast + pp->netmax = 4; // all nets + pp->netbig = B_TRUE; // big net + pp->speed = 2; // fast sprintf(tempm, "Full power!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_MASKPOWERUP) { playfx(FX_POWERUP); - player->hasmask = B_TRUE; + pp->hasmask = B_TRUE; sprintf(tempm, "Scuba Mask!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_BELL) { // all powerups playfx(FX_BELL); // different sound effect - player->hasbell = B_TRUE; + pp->hasbell = B_TRUE; sprintf(tempm, "Powerup Detector!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_RINGGOLD) { // points for walking playfx(FX_POWERUP); - player->powerup = PW_RINGWALK; + pp->powerup = PW_RINGWALK; sprintf(tempm, "Walk Ring!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_RINGSILVER) { // points for walking playfx(FX_POWERUP); - player->powerup = PW_RINGJUMP; + pp->powerup = PW_RINGJUMP; sprintf(tempm, "Jump Ring!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_MACEPOWERUP) { playfx(FX_POWERUP); - player->powerup = PW_MACE; + pp->powerup = PW_MACE; sprintf(tempm, "Mace Slam!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_BOXING) { playfx(FX_POWERUP); - player->powerup = PW_BOXING; + pp->powerup = PW_BOXING; sprintf(tempm, "Boxing Glove!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_HELMET) { int xx,yy; playfx(FX_ARMOR); - player->id = P_ARMOUR; // change how the player looks - player->armour = B_TRUE; + // TODO: player2 + pp->id = P_ARMOUR; // change how the player looks + pp->armour = B_TRUE; sprintf(tempm, "Armour!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); // add puffs - for (xx = player->x - TILEW; xx <= player->x + TILEW; xx += TILEW) { - for (yy = player->y - TILEW*2; yy <= player->y; yy += TILEH) { + for (xx = pp->x - TILEW; xx <= pp->x + TILEW; xx += TILEW) { + for (yy = pp->y - TILEW*2; yy <= pp->y; yy += TILEH) { puffin(-1, xx, yy, "nothing", 0); } } return B_TRUE; } else if (s->id == P_GEMBOOST) { playfx(FX_POWERUP); - if (player->gemboost <= 1) { - player->gemboost = 2; + if (pp->gemboost <= 1) { + pp->gemboost = 2; } else { - player->gemboost = 3; + pp->gemboost = 3; } - sprintf(tempm, "Bonus x%d!",player->gemboost); + sprintf(tempm, "Bonus x%d!",pp->gemboost); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_FTODIAMOND) { @@ -6062,7 +6577,7 @@ int dofruiteffect(sprite_t *s) { } else if (s->id == P_CLOCK) { // Freeze monsters playfx(FX_POWERUP); - player->powerup = PW_CLOCK; + globpowerup = PW_CLOCK; clocktime = CLOCKTIME; sprintf(tempm, "Freeze time!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); @@ -6099,25 +6614,28 @@ int dofruiteffect(sprite_t *s) { playfx(FX_SPRAY); sprintf(tempm, "Fly Spray!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - player->powerup = PW_SPRAYUP; + globpowerup = PW_SPRAYUP; sprayalpha = 0; return B_TRUE; } else if (s->id == P_CANNONPOWERUP) { + sprite_t *newsp; // cannon playfx(FX_POWERUP); sprintf(tempm, "Fusion Cannon"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - player->powerup = PW_CANNON; - puffin(P_CANNON, player->x, player->y,"cannon", 0); + pp->powerup = PW_CANNON; + puffin(-1, pp->x, pp->y,"nothign", 0); + newsp = addsprite(P_CANNON, pp->x, pp->y, "cannon"); + newsp->owner = pp; return B_TRUE; } else if (s->id == P_HONEY) { playfx(FX_POWERUP); - player->netsticky = B_TRUE; + pp->netsticky = B_TRUE; sprintf(tempm, "Sticky net!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); return B_TRUE; } else if (s->id == P_LIFE) { - extralife(player); + extralife(pp); return B_TRUE; } else if (s->id == P_PHONE) { sprite_t *s2, *nexts; @@ -6132,7 +6650,7 @@ int dofruiteffect(sprite_t *s) { sprintf(tempm, "Telephone!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); // set powerup - player->powerup = PW_PHONE; + pp->powerup = PW_PHONE; skiplevels = 1; // kill all enemies for (s2 = sprite; s2 ; s2 = nexts) { @@ -6141,8 +6659,10 @@ int dofruiteffect(sprite_t *s) { s2->dead = D_FINAL; if (s2->caughtby) { + sprite_t *pl; + pl = s2->caughtby; uncatch(s2); - player->netcaught--; + pl->netcaught--; } } } @@ -6173,7 +6693,7 @@ int dofruiteffect(sprite_t *s) { // add a starburst ang = (rand() % 360) * (M_PI/180); for (n = 0; n < 8; n++) { - sp = addsprite(P_STAR, player->x, player->y, "star"); + sp = addsprite(P_STAR, pp->x, pp->y, "star"); /* switch (n) { case 0: sp->xs = 0; sp->ys = -STARSPEED; break; @@ -6204,8 +6724,8 @@ int dofruiteffect(sprite_t *s) { sprite_t *s2, *nexts; // make the screen shake - player->powerup = PW_BOMB; - player->timer1 = BOMBSHAKETIME; + globpowerup = PW_BOMB; + globtimer = BOMBSHAKETIME; // kill all monsters playfx(FX_BOOM); @@ -6220,8 +6740,10 @@ int dofruiteffect(sprite_t *s) { s2->lives = 0; // for snails if (s2->caughtby) { + sprite_t *pl; + pl = s2->caughtby; uncatch(s2); - player->netcaught--; + pl->netcaught--; } die(s2); } @@ -6232,7 +6754,7 @@ int dofruiteffect(sprite_t *s) { sprintf(tempm, "Shield!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); // temp invincibility - player->invuln = SHIELDTIME; + pp->invuln = SHIELDTIME; return B_TRUE; } else if (s->id == P_CLOVER) { playfx(FX_POWERUP); @@ -6245,53 +6767,60 @@ int dofruiteffect(sprite_t *s) { playfx(FX_POWERUP); sprintf(tempm, "Extra Long Net!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - player->powerup = PW_ACCORDION; + pp->powerup = PW_ACCORDION; return B_TRUE; } else if (s->id == P_WINGBOOTS) { playfx(FX_POWERUP); sprintf(tempm, "Double jump!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - player->doublejump = B_TRUE; + pp->doublejump = B_TRUE; return B_TRUE; } else if (s->id == P_GUN) { playfx(FX_ALARM); sprintf(tempm, "Machine gunner!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - gunorigx = player->x; - gunorigy = player->y; + gunorigx = pp->x; + gunorigy = pp->y; guntime = 10; gundelay = 0; // used to control shooting speed // turn off netting etc player->netting = B_FALSE; player->slamming = B_FALSE; player->powerup = PW_GUNNER; + if (player2) { + player2->netting = B_FALSE; + player2->slamming = B_FALSE; + player2->powerup = PW_GUNNER; + } + return B_TRUE; } else if (s->id == P_ZAPPOWERUP) { sprite_t *newsp; playfx(FX_POWERUP); sprintf(tempm, "Bug Zapper!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY, TT_NORM); - puffin(-1, player->x, player->y, "bzpuff", 0); - newsp = addsprite(P_ZAPPER, player->x,player->y, "bugzapper" ); + puffin(-1, pp->x, pp->y, "bzpuff", 0); + newsp = addsprite(P_ZAPPER, pp->x,pp->y, "bugzapper" ); newsp->timer1 = 0; newsp->timer2 = ZAPPERDELAY; newsp->timer3 = 0; newsp->doomcount = 800; + newsp->owner = pp; return B_TRUE; } else if (s->id == P_SKULL) { playfx(FX_SKULL); sprintf(tempm, "Power Down!"); addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&black,&grey,POINTSDELAY, TT_NORM); - player->netmax = 1; - player->netsticky = B_FALSE; - player->netbig = B_FALSE; + pp->netmax = 1; + pp->netsticky = B_FALSE; + pp->netbig = B_FALSE; return B_TRUE; } else if (s->id == P_HELP) { playfx(FX_POWERUP); addoutlinetext(320,240,TEXTSIZE_HELP, s->name, &white,&black,HELPDELAY,TT_HELP); return B_TRUE; } else if (iscard(s->id)) { - if (player->numcards < MAXCARDS) { + if (pp->numcards < MAXCARDS) { sprite_t *newc; int cardwidth,cardheight; @@ -6304,13 +6833,20 @@ int dofruiteffect(sprite_t *s) { // add a "card" effect. it will move slowly towards the corner. newc = addsprite(P_MOVINGCARD,s->x, s->y, "moving_card"); + newc->owner = pp; + // timer1 is the actual cardid // timer2 is the target x position // timer3 is the target y position cardwidth = imageset[P_FIRSTCARD].img[F_WALK1]->w; cardheight = imageset[P_FIRSTCARD].img[F_WALK1]->h; newc->timer1 = s->id; - newc->timer2 = CARDX + (player->numcards * (cardwidth+2)) + (cardwidth/2); + if (pp == player) { + newc->timer2 = CARDX + (pp->numcards * (cardwidth+2)) + (cardwidth/2); + } else if (pp == player2) { + int cardx2 = 640 - CARDX - (5*(imageset[P_FIRSTCARD].img[F_WALK1]->w + 2)); + newc->timer2 = cardx2 + (pp->numcards * (cardwidth+2)) + (cardwidth/2); + } newc->timer3 = CARDY + cardheight; // set image @@ -6334,7 +6870,7 @@ int dofruiteffect(sprite_t *s) { } /* if so, create a left/right stream of flowers */ if (!found) { - int howmany = (STREAMWID + 1) * player->gemboost; + int howmany = (STREAMWID + 1) * pp->gemboost; int puffdelay; // RIGHT @@ -6534,12 +7070,8 @@ void playmusic(Mix_Music *toplay) { //music = toplay; Mix_PlayMusic(toplay, -1); - if (player) { - if (player->swimming) { - Mix_VolumeMusic(MIX_MAX_VOLUME/3); - } else { - Mix_VolumeMusic(MIX_MAX_VOLUME); - } + if ((player && player->swimming) || (player2 && player2->swimming)) { + Mix_VolumeMusic(MIX_MAX_VOLUME/3); } else { Mix_VolumeMusic(MIX_MAX_VOLUME); } @@ -6788,7 +7320,7 @@ int addscore(sprite_t *s, int amt) { s->score += amt; // each multiple of 100,000 - if (s == player) { + if (isplayer(s)) { if ((s->score / 100000) > (oldscore / 100000)) { extralife(s); } @@ -6921,14 +7453,33 @@ void checksprites(void) { s->moved = MV_NONE; nextsprite = s->next; if (s->dead == D_FINAL) { - if (s == player) { - if (player->lives > 0) { + if (isplayer(s)) { + int alldead; + if (s->lives > 0) { /* if we have lives left, go back to start position */ setdefaults(s); - s->x = (curlevel->p1x * TILEW) + (TILEW/2); - s->y = (curlevel->p1y * TILEH) + (TILEH/2); - makeinvuln(player); + if (s == player) { + s->x = (curlevel->p1x * TILEW) + (TILEW/2); + s->y = (curlevel->p1y * TILEH) + (TILEH/2); + } else { + s->x = (curlevel->p2x * TILEW) + (TILEW/2); + s->y = (curlevel->p2y * TILEH) + (TILEH/2); + } + makeinvuln(s); } else { + // permenantly dead - do nothing? + } + + // is everyone dead? + alldead = B_TRUE; + if (player) { + if ((player->dead != D_FINAL) || (player->lives > 0)) alldead = B_FALSE; + } + if (player2) { + if ((player2->dead != D_FINAL) || (player2->lives > 0)) alldead = B_FALSE; + } + + if (alldead) { if (levelcomplete != LV_GAMEOVER) { // special type - when it expires, gameover timer will start addoutlinetext(320,240,TEXTSIZE_GAMEOVER,"Game Over",&red,&black,GAMEOVERDELAY,TT_GAMEOVER); @@ -6968,8 +7519,8 @@ void checkcollideall(void) { /* check collisions for player and effects */ for (s = sprite ; s ; s = s->next) { - if (s == player) { - if (player->powerup != PW_GUNNER) { + if (isplayer(s)) { + if (s->powerup != PW_GUNNER) { checkcollide(s); } } else if (needscollisions(s->id)) { @@ -7003,6 +7554,7 @@ void drawallsprites(void) { // check if sprite has passed off bottom/top of screen void checkwrap(sprite_t *s) { + if (!s) return; if (!s->dead) { if (!iseffect(s->id)) { /* if we've fallen off the bottom... */ @@ -7093,6 +7645,7 @@ void togglefullscreen(void) { } void initsdl(void) { + int i; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) { printf("SDL_Init: %s\n", SDL_GetError()); exit(1); @@ -7127,27 +7680,31 @@ void initsdl(void) { SDL_ShowCursor(SDL_DISABLE); // find joysticks + havejoysticks = 0; SDL_InitSubSystem(SDL_INIT_JOYSTICK); - joy = SDL_JoystickOpen(0); - if (joy) { - printf("%d joystick(s) detected and enabled.\n",SDL_NumJoysticks()); - SDL_JoystickEventState(SDL_ENABLE); - havejoysticks = B_TRUE; - joybuttons = SDL_JoystickNumButtons(joy); - printf("Joy 1 has %d buttons\n",joybuttons); - if (joybuttons >= 15) { // ps3 controller? - joyanalog = B_TRUE; - } else { - joyanalog = B_FALSE; - } - if (joyanalog) { - joythresh = JOYTHRESH_ANA; - } else { - joythresh = JOYTHRESH_DIG; - } + for (i = 0; i < 2; i++) { + joy[i] = SDL_JoystickOpen(0); + if (joy[i]) { + printf("Joystick #1 found.\n"); + havejoysticks++; + joybuttons[i] = SDL_JoystickNumButtons(joy[i]); + printf("Joy %d has %d buttons\n",i,joybuttons[i]); + if (joybuttons[i] >= 15) { // ps3 controller? + joyanalog[i] = B_TRUE; + } else { + joyanalog[i] = B_FALSE; + } + if (joyanalog[i]) { + joythresh[i] = JOYTHRESH_ANA; + } else { + joythresh[i] = JOYTHRESH_DIG; + } + } + } + if (havejoysticks) { setjoymappings(); + SDL_JoystickEventState(SDL_ENABLE); } else { - havejoysticks = B_FALSE; printf("No joysticks found.\n"); } @@ -7174,7 +7731,7 @@ void getfruit(sprite_t *giveto, sprite_t *fruit, int multiplier) { } /* handle fruit effects */ - if (!dofruiteffect(fruit)) { + if (!dofruiteffect(giveto, fruit)) { playfx(FX_FRUIT); if (multiplier <= 1) { sprintf(tempm, "%d", modscore); @@ -7264,7 +7821,16 @@ void undoflood(void) { } +sprite_t *haspowerupany(int pid) { + if (player && haspowerup(player,pid)) return player; + if (player2 && haspowerup(player2,pid)) return player2; + + return NULL; +} + + int haspowerup(sprite_t *s, int pid) { + if (!s) return B_FALSE; switch (pid) { case P_SPEED: if (s->speed != 1) { @@ -7316,6 +7882,8 @@ int haspowerup(sprite_t *s, int pid) { return B_TRUE; } break; + default: + if (s->powerup == pid) return B_TRUE; } return B_FALSE; } @@ -7349,7 +7917,14 @@ void gaincard(sprite_t *s, int cardid) { // generate FIVECARDS sprite - newsp = addsprite(P_FIVECARDS, CARDX, CARDY, "fivecards"); + + if (s == player) { + newsp = addsprite(P_FIVECARDS, CARDX, CARDY, "fivecards"); + } else { + int cardx2 = 640 - CARDX - (5*(imageset[P_FIRSTCARD].img[F_WALK1]->w + 2)); + newsp = addsprite(P_FIVECARDS, cardx2, CARDY, "fivecards"); + } + newsp->owner = s; // create blank image newsp->img = SDL_CreateRGBSurface(SDL_SWSURFACE, @@ -7363,9 +7938,9 @@ void gaincard(sprite_t *s, int cardid) { area.y = 0; area.w = 0; area.h = 0; - for (i = 0; i < player->numcards; i++) { + for (i = 0; i < s->numcards; i++) { SDL_Surface *cardimg; - cardimg = imageset[player->card[i]].img[F_WALK1]; + cardimg = imageset[s->card[i]].img[F_WALK1]; if (cardimg == NULL){ printf("ERROR! Card image is null!!\n"); fflush(stdout); @@ -7381,7 +7956,7 @@ void gaincard(sprite_t *s, int cardid) { newsp->y += (newsp->img->h); // figure out what happened - pokereffect = getpokereffect(player); + pokereffect = getpokereffect(s); getpokermsg2(pokereffect, msg); // display BIG message @@ -7757,7 +8332,7 @@ void dopokereffect(sprite_t *pl, int effect) { sprintf(tempmsg, "Skip 3 levels!"); addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY,TT_NORM); // set powerup - player->powerup = PW_PHONE; + pl->powerup = PW_PHONE; skiplevels = 2; // kill all enemies for (s2 = sprite; s2 ; s2 = nexts) { @@ -7767,7 +8342,7 @@ void dopokereffect(sprite_t *pl, int effect) { if (s2->caughtby) { uncatch(s2); - player->netcaught--; + s2->caughtby->netcaught--; } } } @@ -7786,7 +8361,7 @@ void dopokereffect(sprite_t *pl, int effect) { sprintf(tempmsg, "Skip 5 levels!"); addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY,TT_NORM); // set powerup - player->powerup = PW_PHONE; + pl->powerup = PW_PHONE; skiplevels = 4; // kill all enemies for (s2 = sprite; s2 ; s2 = nexts) { @@ -7796,7 +8371,7 @@ void dopokereffect(sprite_t *pl, int effect) { if (s2->caughtby) { uncatch(s2); - player->netcaught--; + s2->caughtby->netcaught--; } } } @@ -7822,7 +8397,7 @@ void dopokereffect(sprite_t *pl, int effect) { sprintf(tempmsg, "Skip 7 levels!"); addoutlinetext(pl->x,pl->y - pl->img->h/2, TEXTSIZE_BONUS, tempmsg,&cyan,&black,POKERMSGDELAY,TT_NORM); // set powerup - player->powerup = PW_PHONE; + pl->powerup = PW_PHONE; skiplevels = 6; // kill all enemies for (s2 = sprite; s2 ; s2 = nexts) { @@ -7832,7 +8407,7 @@ void dopokereffect(sprite_t *pl, int effect) { if (s2->caughtby) { uncatch(s2); - player->netcaught--; + s2->caughtby->netcaught--; } } } @@ -7930,7 +8505,8 @@ void handleinput(void) { playfx(FX_COIN); } if (levelcomplete == LV_HELPFREEZE) { - if ((event.key.keysym.sym == SDLK_z) || (event.key.keysym.sym == SDLK_c)) { + if ((event.key.keysym.sym == SDLK_z) || (event.key.keysym.sym == SDLK_c) || + (event.key.keysym.sym == SDLK_s) || (event.key.keysym.sym == SDLK_f)) { levelcomplete = oldlevelcomplete; } } @@ -7957,7 +8533,7 @@ void handleinput(void) { // toggle fullscreen - if (keydown(SDLK_f)) { + if (keydown(0, SDLK_F3)) { if (toggletimer == 0) { // always pause first paused = B_TRUE; @@ -7967,17 +8543,17 @@ void handleinput(void) { } // pause - if (keydown(SDLK_p)) { + if (keydown(0, SDLK_p)) { if (toggletimer == 0) { togglepause(); toggletimer = 80; } } // quit - if (keydown(SDLK_ESCAPE)) { + if (keydown(0, SDLK_ESCAPE)) { exit(1); } - if (keydown(SDLK_F2)) { // show framerate + if (keydown(0, SDLK_F2)) { // show framerate if (toggletimer == 0) { if (wantframerate) { wantframerate = B_FALSE; @@ -7988,22 +8564,16 @@ void handleinput(void) { } } if (cheat) { - if (keydown(SDLK_q)) { + if (keydown(0, SDLK_q)) { gtime = nexthurryup-1; //gtime = nexthurryup+14; } - if (keydown(SDLK_b)) { - player->lives = 1; - //gtime = nexthurryup+14; - } - if (keydown(SDLK_i)) { + if (keydown(0, SDLK_t)) { if (player->numcards == 0) { - /* - gaincard(player, getrandomcard()); - gaincard(player, getrandomcard()); - gaincard(player, getrandomcard()); - gaincard(player, getrandomcard()); - */ + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); gaincard(player, P_CARDD4); gaincard(player, P_CARDD5); gaincard(player, P_CARDD1); @@ -8011,13 +8581,28 @@ if (cheat) { gaincard(player, P_CARDD10); } } + if (keydown(0, SDLK_y)) { + if (player2->numcards == 0) { + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); + //gaincard(player, getrandomcard()); + gaincard(player2, P_CARDD4); + gaincard(player2, P_CARDD5); + gaincard(player2, P_CARDD1); + gaincard(player2, P_CARDDJ); + gaincard(player2, P_CARDD10); + } + } +/* if (keydown(SDLK_l)) { if (toggletimer == 0) { addscore(player, 100001); toggletimer = 30; } } - if (keydown(SDLK_v)) { // cheat + */ + if (keydown(0, SDLK_v)) { // cheat if (toggletimer == 0) { // all powerups playfx(FX_POWERUP); @@ -8033,7 +8618,7 @@ if (cheat) { toggletimer = 80; } } - if (keydown(SDLK_n)) { + if (keydown(0, SDLK_n)) { if (toggletimer == 0) { // nextlevel(); sprite_t *s2, *nexts; @@ -8055,7 +8640,7 @@ if (cheat) { if (s2->caughtby) { uncatch(s2); - player->netcaught--; + s2->caughtby->netcaught--; } die(s2); } @@ -8064,13 +8649,16 @@ if (cheat) { } } - if (keydown(SDLK_d)) { +/* + if (keydown(0, SDLK_d)) { if (toggletimer == 0) { // dump sprites dumpsprites(); toggletimer = 50; } } +*/ + /* if (keydown(SDLK_d)) { sprite_t *s2,*nexts; // set powerup @@ -8088,6 +8676,7 @@ if (cheat) { } } } + */ } @@ -8095,147 +8684,30 @@ if (cheat) { /* ************************************************************ Player movement ************************************************************/ - if ((!paused) && (!levelcomplete != LV_DOPOKER) && (levelcomplete != LV_CLOUDLOOP)) { - if (player->powerup == PW_GUNNER) { - // move crosshairs - if (keydown(SDLK_RIGHT)) { - if (player->x < 640-(TILEW/2)) { - player->x += GUNNERSPEED; - } - } - if (keydown(SDLK_LEFT)) { - if (player->x > (TILEW/2)) { - player->x -= GUNNERSPEED; - } - } - if (keydown(SDLK_DOWN)) { - if (player->y < 480-(TILEH/2)) { - player->y += GUNNERSPEED; - } - } - if (keydown(SDLK_UP)) { - if (player->y > (TILEH/2)) { - player->y -= GUNNERSPEED; - } - } - if (keydown(SDLK_z)) { - // shoot - add explosion - if (gundelay == 0) { - playfx(FX_GUN); - addsprite(P_SMASH, player->x, player->y+(TILEH/2), "gunexplosion"); - gundelay = GUNNERDELAY; + if ((!paused) && (!levelcomplete != LV_DOPOKER) ) { + // is cloud touching the player? + if (levelcomplete == LV_CLOUD) { + sprite_t *c; + int hitplayer1 = B_FALSE,hitplayer2 = B_FALSE; + for (c = sprite ; c ; c = c->next) { + if (player) { + if ((c->owner == player) && (c->timer1 == LV_CLOUDLOOP)) { + // can't move + hitplayer1 = B_TRUE; + } + } + if (player2) { + if ((c->owner == player2) && (c->timer1 == LV_CLOUDLOOP)) { + // can't move + hitplayer2 = B_TRUE; + } } } + if (!hitplayer1) doplayermovement(player); + if (!hitplayer2) doplayermovement(player2); } else { - if ((!player->dead) && (!player->teleporting)) { - int moveok = B_FALSE; - if (player->climbing) { - tiletype_t *tt; - // can only move left/right if we're at the bottom of a ladder - tt = gettileat(player->x,player->y, NULL,NULL); - if (tt->solid) { - moveok = B_TRUE; - } - tt = gettileat(player->x,player->y+TILEH, NULL,NULL); - if (tt->solid ) { - moveok = B_TRUE; - } - } else moveok = B_TRUE; - - if (moveok) { - if (keydown(SDLK_RIGHT)) { - if (canmove(player)) { - movex(player, getspeed(player)); - } - if (canturn(player)) { - player->dir = D_RIGHT; - } - } else if (keydown(SDLK_LEFT)) { - if (canmove(player)) { - movex(player, -getspeed(player)); - } - if (canturn(player)) { - player->dir = D_LEFT; - } - } - } - - if (keydown(SDLK_UP)) { - if ((player->swimming) && (player->hasmask)) { - // swimming - swimup(player); - } else if (!player->netting && !player->slamming && !player->jumping) { - // climbing - if (player->climbing) { - int ladderx = isladderabove(player); - // if tile above is non-solid, or a ladder - if (ladderx || !isroofabove(player)) { - // lock to ladder - if (ladderx) { - player->x = ladderx; // lock to ladder - } - // continue climbing - player->y -= getspeed(player); - player->jumping = 0; - player->falling = 0; - player->climbing = B_TRUE; - player->moved = MV_WALK; - } - } else {// not climbing - int ladderx = isladderabove(player); - if (ladderx) { - player->x = ladderx; // lock to ladder - // start climbing - player->y -= getspeed(player); - player->jumping = 0; - player->falling = 0; - player->climbing = B_TRUE; - player->moved = MV_WALK; - } - - } - } - } - if (keydown(SDLK_DOWN)) { - if ((player->swimming) && (player->hasmask)) { - // swimming - swimdown(player); - } else if (!player->netting && !player->slamming && !player->jumping) { - int ladderx = isonladder(player); - if (ladderx) { - player->y += getspeed(player); - player->jumping = 0; - player->falling = 0; - player->climbing = B_TRUE; - player->moved = MV_WALK; - // lock player to centre of ladder - player->x = ladderx; - } - } - } - // Jump - if (keydown(SDLK_x)) { - trytojump(player); - } else if (player->jumping && player->doublejump) { - // have to let go of jump button to double jump - if (!player->doublejumpready) { - player->doublejumpready = B_TRUE; - } - } - // Shoot - if (keydown(SDLK_z)) { - if (keydown(SDLK_DOWN)) { - trytoslam(player); - } else { - trytoshoot(player); - } - } - - // Slam - if (keydown(SDLK_c)) { - trytoslam(player); - } - } + doplayermovement(player); + doplayermovement(player2); } } // ignore other events @@ -8246,6 +8718,9 @@ if (cheat) { void swimup(sprite_t *pl) { + int pnum; + if (pl == player) pnum = 0; + if (pl == player2) pnum = 1; pl->falling = B_FALSE; if (!isroofabove(pl)) { // is there water above us too? @@ -8264,9 +8739,9 @@ void swimup(sprite_t *pl) { int whichway; // if not, jump up pl->climbing = B_FALSE; - if (keydown(SDLK_RIGHT)) { + if (keydown(pnum, SDLK_RIGHT)) { whichway = 1; - } else if (keydown(SDLK_LEFT)) { + } else if (keydown(pnum, SDLK_LEFT)) { whichway = -1; } else { whichway = 0; @@ -8295,6 +8770,11 @@ void swimdown(sprite_t *pl) { void trytojump(sprite_t *pl) { + int pnum; + + if (pl == player) pnum = 0; + if (pl == player2) pnum = 1; + // can't jump while slamming if (pl->slamming) return; @@ -8309,7 +8789,7 @@ void trytojump(sprite_t *pl) { if (!pl->falling || (pl->doublejump && pl->doublejumpready && !pl->useddoublejump)) { if (isonground(pl) || isonladder(pl) || pl->doublejump ) { /* dropping through a bridge */ - if (keydown(SDLK_DOWN)) { + if (keydown(pnum,SDLK_DOWN)) { if (isonbridge(pl) && !pl->falling) { /* drop down */ pl->dropping = B_TRUE; @@ -8318,9 +8798,9 @@ void trytojump(sprite_t *pl) { } } else { // jumping int whichway; - if (keydown(SDLK_RIGHT)) { + if (keydown(pnum,SDLK_RIGHT)) { whichway = 1; - } else if (keydown(SDLK_LEFT)) { + } else if (keydown(pnum,SDLK_LEFT)) { whichway = -1; } else { whichway = 0; @@ -8355,7 +8835,7 @@ void trytoslam(sprite_t *pl) { // use existing mace if it is there found = B_FALSE; for (s = sprite; s ; s = s->next) { - if (s->id == P_MACE) { + if ((s->id == P_MACE) && (s->owner == pl)) { s->x = pl->x; s->y = pl->y - (imageset[pl->id].img[F_SHOOT]->h / 2) + 5; found = B_TRUE; @@ -8363,9 +8843,11 @@ void trytoslam(sprite_t *pl) { } if (!found) { - addsprite(P_MACE, pl->x, + sprite_t *newsp; + newsp = addsprite(P_MACE, pl->x, pl->y - (imageset[pl->id].img[F_SHOOT]->h / 2) + 5, "mace"); + newsp->owner = pl; } } @@ -8410,7 +8892,7 @@ void trytoshoot(sprite_t *pl) { // use existing glove if it is there found = B_FALSE; for (s = sprite; s ; s = s->next) { - if (s->id == P_GLOVE) { + if ((s->id == P_GLOVE) && (s->owner == pl)) { s->x = pl->x; s->y = pl->y - (imageset[pl->id].img[F_SHOOT]->h / 2) + 5; found = B_TRUE; @@ -8418,35 +8900,49 @@ void trytoshoot(sprite_t *pl) { } if (!found) { - addsprite(P_GLOVE, pl->x, + sprite_t *newsp; + newsp = addsprite(P_GLOVE, pl->x, pl->y - (imageset[pl->id].img[F_SHOOT]->h / 2) + 5, "glove"); + newsp->owner = pl; } } } } } -int keydown(int checkfor) { +int keydown(int whichplayer, int checkfor) { + // adjust checkfor bsaed on player + if (whichplayer == 1) { + if (checkfor == SDLK_RIGHT) checkfor = SDLK_l; + if (checkfor == SDLK_LEFT) checkfor = SDLK_j; + if (checkfor == SDLK_UP) checkfor = SDLK_i; + if (checkfor == SDLK_DOWN) checkfor = SDLK_k; + if (checkfor == SDLK_z) checkfor = SDLK_s; + if (checkfor == SDLK_x) checkfor = SDLK_d; + if (checkfor == SDLK_c) checkfor = SDLK_f; + + } // check for keypress if (keys[checkfor]) { return B_TRUE; } + // check for joystick if (havejoysticks) { //if (joybut[keytojoybutton(checkfor)]) return B_TRUE; - if (joybuttondown(checkfor)) return B_TRUE; - if ((checkfor == SDLK_UP) && (joyy <= -joythresh)) return B_TRUE; - if ((checkfor == SDLK_DOWN) && (joyy >= joythresh)) return B_TRUE; - if ((checkfor == SDLK_LEFT) && (joyx <= -joythresh)) return B_TRUE; - if ((checkfor == SDLK_RIGHT) && (joyx >= joythresh)) return B_TRUE; + if (joybuttondown(whichplayer, checkfor)) return B_TRUE; + if ((checkfor == SDLK_UP) && (joyy[whichplayer] <= -joythresh[whichplayer])) return B_TRUE; + if ((checkfor == SDLK_DOWN) && (joyy[whichplayer] >= joythresh[whichplayer])) return B_TRUE; + if ((checkfor == SDLK_LEFT) && (joyx[whichplayer] <= -joythresh[whichplayer])) return B_TRUE; + if ((checkfor == SDLK_RIGHT) && (joyx[whichplayer] >= joythresh[whichplayer])) return B_TRUE; } return B_FALSE; } // draw cannon lasers and check for collision from them -void docannoneffect(void) { +void docannoneffect(sprite_t *pp) { if (timer % 2 == 0) { int found; sprite_t *s; @@ -8455,14 +8951,16 @@ void docannoneffect(void) { found = B_FALSE; for (s = sprite; s ; s = s->next) { if (s->id == P_CANNON) { - found = B_TRUE; + if (s->owner == pp) { + found = B_TRUE; + } break; } } if (!found) { printf("weird error - no cannon!!\n"); - losepowerup(player); + losepowerup(pp); } else { int initx,inity; int i; @@ -8470,7 +8968,7 @@ void docannoneffect(void) { int xx,yy; sprite_t *s3; - initsize = player->timer3; + initsize = pp->timer3; if (initsize > CANNONSIZE) initsize = CANNONSIZE; // calc init positions @@ -8513,9 +9011,9 @@ void docannoneffect(void) { } // dec size if (timer % 8 == 0) { - player->timer3--; - if (player->timer3 <= 0) { - losepowerup(player); + pp->timer3--; + if (pp->timer3 <= 0) { + losepowerup(pp); s->dead = D_FINAL; SDL_BlitSurface(temps, NULL, screen, NULL); } @@ -8530,6 +9028,7 @@ void dotitlescreen(void) { SDL_Surface *titlebg; SDL_Surface *cointext, *text, *text2, *easy, *norm, *ver; SDL_Surface *help, *helpon, *helpoff; + SDL_Surface *p1ready,*p2ready; SDL_Event event; SDL_Rect area; int timer = 0; @@ -8537,6 +9036,18 @@ void dotitlescreen(void) { int texton = B_TRUE; int htstart = 0, htime = 0,hticks; + + // clear all sprites!! + want1up = B_FALSE; + want2up = B_FALSE; + + while (sprite) { + killsprite(sprite); + } + sprite = NULL; + player = NULL; + player2 = NULL; + // reset gothiscore setting gothiscore = -1; @@ -8549,9 +9060,23 @@ void dotitlescreen(void) { exit(1); } + // load ready text + sprintf(tempst, "%s/sprites/p1ready.png",datadir); + p1ready = IMG_Load(tempst); + if (!p1ready) { + printf("cannot load p1 ready img (%s)\n",tempst); + exit(1); + } + sprintf(tempst, "%s/sprites/p2ready.png",datadir); + p2ready = IMG_Load(tempst); + if (!p2ready) { + printf("cannot load p2 ready img (%s)\n",tempst); + exit(1); + } + // set up text cointext = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Insert Coin", white); - text = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Press 1UP to start", red); + text = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Press 1UP or 2UP to start", red); text2 = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Select game mode:", red); easy = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Easy Mode", red2); norm = TTF_RenderText_Solid(font[TEXTSIZE_TITLE], "Normal Mode", red2); @@ -8572,26 +9097,30 @@ void dotitlescreen(void) { blinkspeed = 20; + // wait for keypress titledone = B_FALSE; while (!titledone) { if (SDL_PollEvent(&event)) { + int j; switch (event.type) { case SDL_JOYAXISMOTION: - joyx = SDL_JoystickGetAxis(joy,0); - joyy = SDL_JoystickGetAxis(joy,1); + for (j = 0; j < 2; j++) { + joyx[j] = SDL_JoystickGetAxis(joy[j],0); + joyy[j] = SDL_JoystickGetAxis(joy[j],1); - if (joyy <= -6000) handletitleinput(SDLK_UP); - if (joyy >= 6000) handletitleinput(SDLK_DOWN); - if (joyx <= -6000) handletitleinput(SDLK_LEFT); - if (joyx >= 6000) handletitleinput(SDLK_RIGHT); + if (joyy[j] <= -6000) handletitleinput(j, SDLK_UP); + if (joyy[j] >= 6000) handletitleinput(j, SDLK_DOWN); + if (joyx[j] <= -6000) handletitleinput(j, SDLK_LEFT); + if (joyx[j] >= 6000) handletitleinput(j, SDLK_RIGHT); + } break; case SDL_KEYUP: - handletitleinput(event.key.keysym.sym); + handletitleinput(0, event.key.keysym.sym); break; case SDL_JOYBUTTONUP: - handletitleinput(joybuttontokey(event.jbutton.button)); + handletitleinput(event.jbutton.which, joybuttontokey(event.jbutton.button)); break; } @@ -8660,6 +9189,20 @@ void dotitlescreen(void) { //} } else if (titlemode == TS_SELECTMODE) { SDL_Surface *desc; + + // who is in? + if (want1up) { + area.x = 20; + area.y = (480/2) - (p1ready->h/2); + SDL_BlitSurface(p1ready, NULL, screen, &area); + } + if (want2up) { + area.x = 640 - p2ready->w - 20; + area.y = (480/2) - (p2ready->h/2); + SDL_BlitSurface(p2ready, NULL, screen, &area); + } + + // "select mode" area.x = 320 - (text2->w/2)+2; area.y = 240 - (text2->h*3)+2; @@ -8765,6 +9308,7 @@ void dotitlescreen(void) { SDL_BlitSurface(desc, NULL, screen, &area); SDL_FreeSurface(desc); } + } else if (titlemode == TS_HISCORES) { drawhiscores(); } @@ -8810,6 +9354,8 @@ void dotitlescreen(void) { SDL_FreeSurface(text2 ); SDL_FreeSurface(easy ); SDL_FreeSurface(norm ); + SDL_FreeSurface(p1ready); + SDL_FreeSurface(p2ready); } void startgame(void) { @@ -8853,6 +9399,21 @@ void startgame(void) { player->usedcard[c] = 0; } } + if (player2) { + int c; + setdefaults(player2); + player2->permspeed = B_FALSE; + player2->permbignet = B_FALSE; + player2->permnumnets = B_FALSE; + player2->permmask = B_FALSE; + player2->permarmour = B_FALSE; + player2->permsticky = B_FALSE; + player2->numcards = 0; + for (c = 0; c < MAXCARDS; c++) { + player2->card[c] = -1; + player2->usedcard[c] = 0; + } + } // is we're skipping to a level, do so now if (skipto >= 0) { @@ -8864,10 +9425,17 @@ void startgame(void) { } // allocate player - if (player == NULL) { - addsprite(P_PLAYER, 32, 450, "Player" ); - player = lastsprite; - } + if (want1up) { + if (player == NULL) { + player = addsprite(P_PLAYER, 32, 450, "Player 1" ); + } + } + if (want2up) { + if (player2 == NULL) { + player2 = addsprite(P_PLAYER2, 32, 450, "Player 2" ); + } + } + // pre-load initial level /* @@ -8877,18 +9445,36 @@ void startgame(void) { */ // more initial variables - makeinvuln(player); - player->score = 0; - if (gamemode == GM_EASY) { - player->permarmour = B_TRUE; - player->armour = B_TRUE; - player->id = P_ARMOUR; - } else { - player->permarmour = B_FALSE; - player->armour = B_FALSE; - player->id = P_PLAYER; - } - player->lives = 3; + if (player) { + makeinvuln(player); + player->score = 0; + if (gamemode == GM_EASY) { + player->permarmour = B_TRUE; + player->armour = B_TRUE; + player->id = P_ARMOUR; + } else { + player->permarmour = B_FALSE; + player->armour = B_FALSE; + player->id = P_PLAYER; + } + player->lives = 3; + } + + if (player2) { + makeinvuln(player2); + player2->score = 0; + if (gamemode == GM_EASY) { + player2->permarmour = B_TRUE; + player2->armour = B_TRUE; + player2->id = P_ARMOUR; + } else { + player2->permarmour = B_FALSE; + player2->armour = B_FALSE; + player2->id = P_PLAYER2; + } + player2->lives = 3; + } + forcegoodcard = B_FALSE; nextforcegoodcard = B_FALSE; @@ -8916,6 +9502,7 @@ void uncatch(sprite_t *s) { } void makeinvuln(sprite_t *s) { + if (!s) return; if (s->id == P_BLACKCLOUD) { s->invuln = INVULNTIME/2; } else { @@ -8925,33 +9512,30 @@ void makeinvuln(sprite_t *s) { void setjoymappings(void) { - if (joy && havejoysticks) { - // ps3 - joymap[4] = SDLK_UP; - joymap[5] = SDLK_RIGHT; - joymap[6] = SDLK_DOWN; - joymap[7] = SDLK_LEFT; - joymap[14] = SDLK_x; //x == jump - joymap[13] = SDLK_c; //circle = slam - joymap[12] = SDLK_z; // square/triangle = shoot - joymap[15] = SDLK_z; - // mame (directions are joystick) - joymap[0] = SDLK_z; - joymap[1] = SDLK_x; - joymap[2] = SDLK_c; - joymap[3] = SDLK_c; - - } + // ps3 + joymap[4] = SDLK_UP; + joymap[5] = SDLK_RIGHT; + joymap[6] = SDLK_DOWN; + joymap[7] = SDLK_LEFT; + joymap[14] = SDLK_x; //x == jump + joymap[13] = SDLK_c; //circle = slam + joymap[12] = SDLK_z; // square/triangle = shoot + joymap[15] = SDLK_z; + // mame (directions are joystick) + joymap[0] = SDLK_z; + joymap[1] = SDLK_x; + joymap[2] = SDLK_c; + joymap[3] = SDLK_c; } int joybuttontokey(int buttonnum) { return joymap[buttonnum]; } -int joybuttondown(int key) { +int joybuttondown(int whichplayer, int key) { int i; - for (i = 0; i < joybuttons; i++) { - if ((joymap[i] == key) && (joybut[i])) return B_TRUE; + for (i = 0; i < joybuttons[whichplayer]; i++) { + if ((joymap[i] == key) && (joybut[whichplayer][i])) return B_TRUE; } return B_FALSE; } @@ -8967,7 +9551,7 @@ int keytojoybutton(int key) { */ -void handletitleinput(int key) { +void handletitleinput(int whichplayer, int key) { if (key == SDLK_ESCAPE) { // quit exit(0); @@ -8988,6 +9572,8 @@ void handletitleinput(int key) { } } else if ((key == SDLK_1) || (key == SDLK_2) || (key == SDLK_RETURN)) { if (credits > 0) { + if ((key == SDLK_1) || (key == SDLK_RETURN)) want1up = B_TRUE; + if (key == SDLK_2) want2up = B_TRUE; playfx(FX_1UP); credits--; titlemode = TS_SELECTMODE; @@ -9007,6 +9593,18 @@ void handletitleinput(int key) { } else if ((key == SDLK_z) || (key == SDLK_RETURN)) { playfx(FX_1UP); titledone = B_TRUE; + } else if ((key == SDLK_1) || (key == SDLK_2) || (key == SDLK_RETURN)) { + // another player joining + if (credits > 0) { + if ((key == SDLK_1) || (key == SDLK_RETURN)) want1up = B_TRUE; + if (key == SDLK_2) want2up = B_TRUE; + playfx(FX_1UP); + credits--; + printf("1up = %d,2up = %d\n",want1up,want2up); + } + } else if ((key == SDLK_5) || (key == SDLK_6)) { + credits++; + playfx(FX_COIN); } } } @@ -9322,14 +9920,15 @@ void checkhiscores(void){ getinput(); if (keytimer == 0) { + // TODO: player2 // check for scrolling - if (keydown(SDLK_UP)) { // scroll through letters + if (keydown(0, SDLK_UP)) { // scroll through letters if (curlet == 'a') curlet = '*'; else if (curlet == '*') curlet = ' '; else if (curlet == ' ') curlet = 'z'; else curlet--; keytimer = 5; - } else if (keydown(SDLK_DOWN)) { // scroll through letters + } else if (keydown(0, SDLK_DOWN)) { // scroll through letters if (curlet == 'z') curlet = ' '; else if (curlet == ' ') curlet = '*'; else if (curlet == '*') curlet = 'a'; @@ -9353,6 +9952,7 @@ void checkhiscores(void){ key = event.key.keysym.sym; break; case SDL_JOYBUTTONUP: + // TODO: player2 key = joybuttontokey(event.jbutton.button); break; @@ -9627,13 +10227,15 @@ void drawhiscores(void) { // read keyboard info void getinput(void) { - int i; + int i,j; keys = SDL_GetKeyState(NULL); if (havejoysticks) { - joyx = SDL_JoystickGetAxis(joy,0); - joyy = SDL_JoystickGetAxis(joy,1); - for (i = 0; i < joybuttons; i++) { - joybut[i] = SDL_JoystickGetButton(joy,i); + for (j = 0; j < 2; j++) { + joyx[j] = SDL_JoystickGetAxis(joy[j],0); + joyy[j] = SDL_JoystickGetAxis(joy[j],1); + for (i = 0; i < joybuttons[j]; i++) { + joybut[j][i] = SDL_JoystickGetButton(joy[j],i); + } } } } @@ -9675,13 +10277,22 @@ void stopteleporting(sprite_t *s) { } } + +void disablepowerups(int pid) { + if (haspowerup(player, pid)) { + losepowerup(player); + } + if (haspowerup(player2, pid)) { + losepowerup(player2); + } +} void losepowerup(sprite_t *s) { if (s->powerup == PW_GUNNER) { // go back to original position - player->x = gunorigx; - player->y = gunorigy; + s->x = gunorigx; + s->y = gunorigy; // invulnerable for a little while - player->invuln = INVULNTIME/2; + s->invuln = INVULNTIME/2; } s->powerup = B_FALSE; @@ -9701,3 +10312,225 @@ double getdistance(double x1, double y1, double x2, double y2) { return 0; } else return sqrt((xdis*xdis) + (ydis*ydis)); } + + + +void doplayermovement(sprite_t *pl) { + int pnum; + + if (!pl) return; + + if (pl == player) pnum = 0; + if (pl == player2) pnum = 1; + + if (pl->powerup == PW_GUNNER) { + // move crosshairs + if (keydown(pnum,SDLK_RIGHT)) { + if (pl->x < 640-(TILEW/2)) { + pl->x += GUNNERSPEED; + } + } + if (keydown(pnum,SDLK_LEFT)) { + if (pl->x > (TILEW/2)) { + pl->x -= GUNNERSPEED; + } + } + if (keydown(pnum,SDLK_DOWN)) { + if (pl->y < 480-(TILEH/2)) { + pl->y += GUNNERSPEED; + } + } + if (keydown(pnum,SDLK_UP)) { + if (pl->y > (TILEH/2)) { + pl->y -= GUNNERSPEED; + } + } + if (keydown(pnum,SDLK_z)) { + // shoot - add explosion + if (gundelay == 0) { + playfx(FX_GUN); + addsprite(P_SMASH, pl->x, pl->y+(TILEH/2), "gunexplosion"); + gundelay = GUNNERDELAY; + } + } + } else { + if ((!pl->dead) && (!pl->teleporting)) { + int moveok = B_FALSE; + if (pl->climbing) { + tiletype_t *tt; + // can only move left/right if we're at the bottom of a ladder + tt = gettileat(pl->x,pl->y, NULL,NULL); + if (tt->solid) { + moveok = B_TRUE; + } + tt = gettileat(pl->x,pl->y+TILEH, NULL,NULL); + if (tt->solid ) { + moveok = B_TRUE; + } + } else moveok = B_TRUE; + + if (moveok) { + if (keydown(pnum,SDLK_RIGHT)) { + if (canmove(pl)) { + movex(pl, getspeed(pl)); + } + if (canturn(pl)) { + pl->dir = D_RIGHT; + } + } else if (keydown(pnum,SDLK_LEFT)) { + if (canmove(pl)) { + movex(pl, -getspeed(pl)); + } + if (canturn(pl)) { + pl->dir = D_LEFT; + } + } + } + + if (keydown(pnum,SDLK_UP)) { + if ((pl->swimming) && (pl->hasmask)) { + // swimming + swimup(pl); + } else if (!pl->netting && !pl->slamming && !pl->jumping) { + // climbing + if (pl->climbing) { + int ladderx = isladderabove(pl); + // if tile above is non-solid, or a ladder + if (ladderx || !isroofabove(pl)) { + // lock to ladder + if (ladderx) { + pl->x = ladderx; // lock to ladder + } + // continue climbing + pl->y -= getspeed(pl); + pl->jumping = 0; + pl->falling = 0; + pl->climbing = B_TRUE; + pl->moved = MV_WALK; + } + } else {// not climbing + int ladderx = isladderabove(pl); + if (ladderx) { + pl->x = ladderx; // lock to ladder + // start climbing + pl->y -= getspeed(pl); + pl->jumping = 0; + pl->falling = 0; + pl->climbing = B_TRUE; + pl->moved = MV_WALK; + } + + } + } + } + if (keydown(pnum,SDLK_DOWN)) { + if ((pl->swimming) && (pl->hasmask)) { + // swimming + swimdown(pl); + } else if (!pl->netting && !pl->slamming && !pl->jumping) { + int ladderx = isonladder(pl); + if (ladderx) { + pl->y += getspeed(pl); + pl->jumping = 0; + pl->falling = 0; + pl->climbing = B_TRUE; + pl->moved = MV_WALK; + // lock player to centre of ladder + pl->x = ladderx; + } + } + } + // Jump + if (keydown(pnum,SDLK_x)) { + trytojump(pl); + } else if (pl->jumping && pl->doublejump) { + // have to let go of jump button to double jump + if (!pl->doublejumpready) { + pl->doublejumpready = B_TRUE; + } + } + // Shoot + if (keydown(pnum,SDLK_z)) { + if (keydown(pnum,SDLK_DOWN)) { + trytoslam(pl); + } else { + trytoshoot(pl); + } + } + + // Slam + if (keydown(pnum,SDLK_c)) { + trytoslam(pl); + } + } + } +} + +double getxdisttoplayer(sprite_t *s) { + double xdiff1,xdiff2,xdiff; + /* distance to closest player */ + if (player) { + xdiff1 = player->x - s->x; + } else { + xdiff1 = 9999; + } + + if (player2) { + xdiff2 = player2->x - s->x; + } else { + xdiff2 = 9999; + } + + if (xdiff1 < xdiff2) { + xdiff = xdiff1; + } else { + xdiff = xdiff2; + } + + return xdiff; +} + +double getydisttoplayer(sprite_t *s) { + double ydiff1,ydiff2,ydiff; + /* distance to closest player */ + if (player) { + ydiff1 = player->y - s->y; + } else { + ydiff1 = 9999; + } + + if (player2) { + ydiff2 = player2->y - s->y; + } else { + ydiff2 = 9999; + } + + if (ydiff1 < ydiff2) { + ydiff = ydiff1; + } else { + ydiff = ydiff2; + } + + return ydiff; +} + + +sprite_t *isplayerbelow(sprite_t *s) { + if (player && !player->dead && player->y > s->y) return player; + if (player2 && !player2->dead && player2->y > s->y) return player2; + + return NULL; +} + +sprite_t *isplayerabove(sprite_t *s) { + if (player && !player->dead && player->y < s->y) return player; + if (player2 && !player2->dead && player2->y < s->y) return player2; + + return NULL; +} +sprite_t *isplayerright(sprite_t *s) { + if (player && !player->dead && player->x > s->x) return player; + if (player2 && !player2->dead && player2->x > s->x) return player2; + + return NULL; +} diff --git a/rc.h b/rc.h index 7fd3005..2d8c609 100644 --- a/rc.h +++ b/rc.h @@ -24,7 +24,7 @@ int isongroundpoint(sprite_t *s, int x, int y); int isonladder(sprite_t *s); int isonbridge(sprite_t *s); int isladderabove(sprite_t *s); -int dofruiteffect(sprite_t *s); +int dofruiteffect(sprite_t *pp, sprite_t *s); void checkcollide(sprite_t *s); void checkcollideplatform(sprite_t *s); void die(sprite_t *s); @@ -70,25 +70,26 @@ void togglefullscreen(void); void initsdl(void); void getfruit(sprite_t *giveto, sprite_t *fruit, int multiplier); int haspowerup(sprite_t *s, int pid); +sprite_t *haspowerupany(int pid); void gaincard(sprite_t *s, int cardid); int getpokereffect(sprite_t *pl); void dopokereffect(sprite_t *pl, int effect); char *getpokermsg(int effect); char *getpokermsg2(int effect, char *buf); void handleinput(void); -int keydown(int checkfor); +int keydown(int whichplayer, int checkfor); void trytojump(sprite_t *pl); void trytoslam(sprite_t *pl); void trytoshoot(sprite_t *pl); -void docannoneffect(void); +void docannoneffect(sprite_t *pp); void dotitlescreen(void); void startgame(void); void uncatch(sprite_t *s); void makeinvuln(sprite_t *s); -void handletitleinput(int key); +void handletitleinput(int whichplayer, int key); void setjoymappings(void); //int keytojoybutton(int key); -int joybuttondown(int key); +int joybuttondown(int whichplayer, int key); int joybuttontokey(int buttonnum); void drawcredits(void); int drawoutlinetext(SDL_Surface *where,int x, int y, int size, char *msg, SDL_Color *col, SDL_Color *bgcol); @@ -104,8 +105,16 @@ int isendoflev(void); void keeponscreen(sprite_t *s); void stopteleporting(sprite_t *s); void losepowerup(sprite_t *s); +void disablepowerups(int pid); int easymode(void); int uncaughtmonsters(void); void swimup(sprite_t *pl); void swimdown(sprite_t *pl); double getdistance(double x1, double y1, double x2, double y2); +void doplayermovement(sprite_t *pl); +double getxdisttoplayer(sprite_t *s); +double getydisttoplayer(sprite_t *s); +int playersalive(void); +sprite_t *isplayerbelow(sprite_t *s); +sprite_t *isplayerabove(sprite_t *s); +sprite_t *isplayerright(sprite_t *s); diff --git a/shared.c b/shared.c index fe12b59..9612c5d 100644 --- a/shared.c +++ b/shared.c @@ -43,6 +43,8 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { int leveldone; int tempanim[LEVELW*LEVELH]; + sprite_t *ss, *nextss; + int numenemies = 0; @@ -105,13 +107,15 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { killtext(text); } - /* clear sprite linked list (leave player) */ - if (sprite != NULL) { - while (sprite->next) { - killsprite(sprite->next); + /* clear sprite linked list (leave players) */ + for (ss = sprite ; ss ; ss = nextss) { + nextss = ss->next; + if (!isplayer(ss)) { + killsprite(ss); } } + /* read tileset */ /* fgets(buf, BUFLEN, f); @@ -288,6 +292,9 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { if (monid == P_PLAYER) { level->p1x = x; level->p1y = y; + } else if (monid == P_PLAYER2) { + level->p2x = x; + level->p2y = y; } else if (monid == P_POWERUPPOS) { level->powerupx = x; level->powerupy = y; @@ -485,8 +492,14 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { printf("Level is missing player 1 start position.\n"); return B_TRUE; } + if ((level->p2x == 0) || (level->p2y == 0)) { + printf("Level is missing player 2 start position.\n"); + return B_TRUE; + } #endif + +printf("p1 is %d,%d p2 s %d,%d\n",level->p1x,level->p1y,level->p2x, level->p2y); /* free help texts */ for (i = 0; i < numhelp; i++) { free(help[i]); @@ -494,10 +507,17 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { /* add player if required */ - if (player == NULL) { - addsprite(P_PLAYER, (curlevel->p1x * TILEW) + (TILEW/2), - (curlevel->p1y * TILEH) + TILEH-2 , "Player" ); - player = lastsprite; + if (want1up) { + if (player == NULL) { + player = addsprite(P_PLAYER, (curlevel->p1x * TILEW) + (TILEW/2), + (curlevel->p1y * TILEH) + TILEH-2 , "Player 1" ); + } + } + if (want2up) { + if (player2 == NULL) { + player2 = addsprite(P_PLAYER2, (curlevel->p2x * TILEW) + (TILEW/2), + (curlevel->p2y * TILEH) + TILEH-2 , "Player 2" ); + } } // don't move player to start of the level if they already exist, becuase they're @@ -512,6 +532,8 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { player->x = (curlevel->p1x * TILEW) + (TILEW/2); player->y = (curlevel->p1y * TILEH) + TILEH-2 ; + player2->x = (curlevel->p2x * TILEW) + (TILEW/2); + player2->y = (curlevel->p2y * TILEH) + TILEH-2 ; #endif /*else { @@ -570,7 +592,6 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { resethurryup(level); boss = NULL; - mask = NULL; printf("Done.\n"); /* @@ -586,7 +607,7 @@ printf(".\n"); void setdefaults(sprite_t *s) { - if (s == player) { + if (isplayer(s)) { // player powerup stats if (s->permspeed) { s->speed = 2; @@ -750,7 +771,7 @@ void setdefaults(sprite_t *s) { } - if (s != player) { + if (!isplayer(s)) { s->score = getpoints(s->id); } @@ -1132,6 +1153,24 @@ int loadimagesets(void) { loadspriteimage(P_PLAYER,F_SWIM2, "sprites/dswim2.png"); imageset[P_PLAYER].numimages = 18; + loadspriteimage(P_PLAYER2,F_WALK1, "sprites/p2dwarf.png"); + loadspriteimage(P_PLAYER2,F_JUMP, "sprites/p2dwarfjump.png"); + loadspriteimage(P_PLAYER2,F_FALL, "sprites/p2dwarffall.png"); + loadspriteimage(P_PLAYER2,F_CAUGHT, "sprites/p2dwarf.png"); + loadspriteimage(P_PLAYER2,F_DEAD, "sprites/dwarf2die.png"); + /* next 3 are auto generated */ + loadspriteimage(P_PLAYER2,F_CLIMB1, "sprites/d2climb1.png"); + loadspriteimage(P_PLAYER2,F_CLIMB2, "sprites/d2climb2.png"); + loadspriteimage(P_PLAYER2,F_SHOOT, "sprites/dwarf2shoot.png"); + loadspriteimage(P_PLAYER2,F_SLAM1, "sprites/d2slam1.png"); + loadspriteimage(P_PLAYER2,F_SLAM2, "sprites/d2slam2.png"); + loadspriteimage(P_PLAYER2,F_SLAM3, "sprites/d2slam3.png"); + loadspriteimage(P_PLAYER2,F_SLAM4, "sprites/d2slam4.png"); + loadspriteimage(P_PLAYER2,F_SLAM5, "sprites/d2slam5.png"); + loadspriteimage(P_PLAYER2,F_SWIM1, "sprites/d2swim1.png"); + loadspriteimage(P_PLAYER2,F_SWIM2, "sprites/d2swim2.png"); + imageset[P_PLAYER2].numimages = 18; + loadspriteimage(P_ARMOUR,F_WALK1, "sprites/armor.png"); loadspriteimage(P_ARMOUR,F_JUMP, "sprites/armorjump.png"); loadspriteimage(P_ARMOUR,F_FALL, "sprites/armorfall.png"); @@ -1676,16 +1715,21 @@ void drawsprite(sprite_t *s) { int frame = 0; // don't show caught mosnters in gunner mode - if ((s != player) && (s->caughtby == player) && (player->powerup == PW_GUNNER)) { - return; + if (!isplayer(s) && (s->caughtby) ) { + if ((player) && (player->powerup == PW_GUNNER)) { + return; + } + if ((player2) && (player2->powerup == PW_GUNNER)) { + return; + } } - if ((s == player) && (levelcomplete == LV_NEXTLEV)) { + if (isplayer(s) && (levelcomplete == LV_NEXTLEV)) { frame = F_SHOOT; if (curlevel->exitdir == D_RIGHT) { - player->dir = 1; + s->dir = 1; } else if (curlevel->exitdir == D_LEFT) { - player->dir = -1; + s->dir = -1; } } else { /* select frame */ @@ -1726,8 +1770,8 @@ void drawsprite(sprite_t *s) { frame = s->timer1; } else if (s->id == P_MASK) { // only draw this if the player is swimming - if (player->swimming) { - if (player->dir > 0) { + if (s->owner->swimming) { + if (s->owner->dir > 0) { frame = 0; } else { frame = 1; @@ -1744,7 +1788,7 @@ void drawsprite(sprite_t *s) { } } else if (s->dead) { - if (s == player) { + if (isplayer(s)) { frame = F_DEAD; } else if (s == boss) { frame = F_DEAD; @@ -1795,7 +1839,7 @@ void drawsprite(sprite_t *s) { } else { frame = F_CLIMB1; } - } else if ((s->swimming) && (s == player) && !s->slamming) { + } else if ((s->swimming) && isplayer(s) && !s->slamming) { if ((timer/12) % 2 == 0) { frame = F_SWIM1; } else { @@ -1893,13 +1937,13 @@ void drawsprite(sprite_t *s) { frame += MAXFRAMES; } } else if ((s->id == P_WINGLEFT) || (s->id == P_WINGRIGHT)) { - if (player->dir == -1) { + if (s->owner->dir == -1) { frame += MAXFRAMES; } } /* make red if required */ if (s->angry && s->id != P_BLACKCLOUD) { - if (s != player) { + if (!isplayer(s)) { frame += (MAXFRAMES*2); } } @@ -1985,7 +2029,7 @@ void drawsprite(sprite_t *s) { if ((s->invuln) && (levelcomplete != LV_HELPFREEZE)) { if (timer % 2 == 0) { //SDL_BlitSurface(s->img, NULL, screen, &area); - if (s == player) { + if (isplayer(s)) { drawplayer(s, &area); } else { doblit(s->img, screen, &area); @@ -1993,7 +2037,7 @@ void drawsprite(sprite_t *s) { } } else if ((s->doomcount > 0) && (s->doomcount <= 150) && (levelcomplete != LV_HELPFREEZE)) { if ((timer/2) % 2 == 0) { - if (s == player) { + if (isplayer(s)) { drawplayer(s, &area); } else { doblit(s->img, screen, &area); @@ -2005,7 +2049,7 @@ void drawsprite(sprite_t *s) { doblit(s->img, screen, &area); } } else { - if (s == player) { + if (isplayer(s)) { drawplayer(s, &area); } else { doblit(s->img, screen, &area); @@ -2086,14 +2130,16 @@ void killsprite(sprite_t *s) { } // remove mask pointer + /* if (mask == s) { mask = NULL; } + */ if (s->caughtby) { s->caughtby = NULL; s->caughtstate = B_FALSE; - player->netcaught--; + s->caughtby->netcaught--; } s->zapping = NULL; @@ -2882,6 +2928,7 @@ int randompowerup(void) { int num; num = rand() % 34; +return getrandomcard(); switch (num) { case 0: default: @@ -3300,23 +3347,44 @@ int getrandomcard(void) { } } } + if (player2) { + for (i = 0; i < player2->numcards; i++) { + if (player2->card[i] == cardid) { + gotit = B_TRUE; + } + } + } // are we forcing it to be good? - if ((forcegoodcard) && (player->numcards > 0)) { - int okay = B_FALSE; - int csuit,cval; - for (i = 0; i < player->numcards; i++) { - cval = getcardvalue(player->card[i]); - csuit = getcardsuit(player->card[i]); - if (csuit == getcardsuit(cardid)) okay = B_TRUE; - if (cval == (getcardvalue(cardid))) okay = B_TRUE; - if (cval == (getcardvalue(cardid)+1)) okay = B_TRUE; - if (cval == (getcardvalue(cardid)-1)) okay = B_TRUE; + if (forcegoodcard) { + if ((player && player->numcards > 0) || (player2 && player2->numcards > 0)) { + int okay = B_FALSE; + int csuit,cval; + if (player) { + for (i = 0; i < player->numcards; i++) { + cval = getcardvalue(player->card[i]); + csuit = getcardsuit(player->card[i]); + if (csuit == getcardsuit(cardid)) okay = B_TRUE; + if (cval == (getcardvalue(cardid))) okay = B_TRUE; + if (cval == (getcardvalue(cardid)+1)) okay = B_TRUE; + if (cval == (getcardvalue(cardid)-1)) okay = B_TRUE; + } + } + if (player2) { + for (i = 0; i < player2->numcards; i++) { + cval = getcardvalue(player2->card[i]); + csuit = getcardsuit(player2->card[i]); + if (csuit == getcardsuit(cardid)) okay = B_TRUE; + if (cval == (getcardvalue(cardid))) okay = B_TRUE; + if (cval == (getcardvalue(cardid)+1)) okay = B_TRUE; + if (cval == (getcardvalue(cardid)-1)) okay = B_TRUE; + } + } + // if not a good card, go to next one + if (!okay) { + gotit = B_TRUE; + } } - // if not a good card, go to next one - if (!okay) { - gotit = B_TRUE; - } } } @@ -3518,7 +3586,7 @@ void drawplayer(sprite_t *s, SDL_Rect *where) { #ifndef __EDITOR - if (player->powerup == PW_GUNNER) { + if (s->powerup == PW_GUNNER) { // just draw crosshairs // box drawbox16(screen, s->x-(TILEW/2),s->y-(TILEH/2),s->x+(TILEW/2),s->y+(TILEH/2), &green, NULL); @@ -3641,3 +3709,16 @@ void resethurryup(level_t *lev) { nexthurryup += 15; } } + + +int isplayer(sprite_t *s) { + if (player && (s == player)) return B_TRUE; + if (player2 && (s == player2)) return B_TRUE; + return B_FALSE; +} + +int playersalive(void) { + if (player && player->dead) return B_FALSE; + if (player2 && player2->dead) return B_FALSE; + return B_TRUE; +} diff --git a/shared.h b/shared.h index 87ecbdf..4a4c124 100644 --- a/shared.h +++ b/shared.h @@ -63,9 +63,13 @@ int getworld(int lev); int getlevel(int lev); void drawplayer(sprite_t *s, SDL_Rect *where); void resethurryup(level_t *lev); +int isplayer(sprite_t *s); +int isplayer(sprite_t *s); +int playersalive(); // for doco void setfruitinfo(void); void setinfo(int id, char *name, char *desc, char *file); void dumpinfo(void); #endif +