* ֨9Ng/sGp'\4ҽҽ3}ҽҽҽҽҽҽҽҽҽҽҽҽ3}3}ҽҽҽҽҽҽҽ3}3}3}3}3}3}3}3}3}3}3}3}A]A]A]3}ɢq}oBA]ɢGp Gp  uu*FZYQnNo"Gp Gp  u uNo"No"Gp Gp Gp Gp Gp Gp Gp  u u u u u u uGp ҽҽGp Gp Gp Gp Gp Y!ҽҽ u uhhGp ؚ u uҽҽҽҽҽҽҽҽʁ)ʁ)ʁ)ʁ)ʁ)ҽʁ)ҽҽʁ)ҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽʁ)ҽʁ)ҽҽؚؚؚ u uh uh uu) uu) uu) uu) u u'ҽҽ uҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽOOOGp hOGp hOҽOҽҽOҽҽhOҽOOҽOOҽOO3}3}Gp ؚؚؚIPu:u:VDu:֎ u uu:֋ؚؚVDؚؚVDؚhؚؚؚؚؚؚؚؚؚҽҽҽҽҽҽҽҽA"QAGp Gp X5hGp A"QAK!/#;A"QAA"QAؚA"QA3} Ե3} Ե8~`n8~`nҽҽҽҽҽҽҽҽҽҽҽҽؚ3}ؚؚؚؚؚ3}ؚؚؚҽҽҽؚҽҽؚؚؚҽؚؚҽؚGp hؚҽҽҽҽҽҽؚؚؚҽҽҽҽؚؚؚؚؚؚҽҽҽҽҽ8~`n8~`n8~`nҽҽҽʁ)ҽҽҽҽҽʁ)hhʁ)ʁ)ʁ)ҽҽҽҽҽҽ}L}L}L}Lҽ}Lҽҽҽҽҽ}L}L}L}L}L3}3}}L}L}Lҽ}LҽGp Gp X5hҽҽGp ҽҽҽҽhҽҽҽҽh3}3}}Lh}L}L}L}Lhh Ʌҽ}Lҽҽ}L}Lҽҽ}Lh}L}L}L}Lhh Ʌҽ}Lҽҽ}L}LҽҽҽҽҽhҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽhҽҽhҽҽҽҽҽҽҽҽҽҽҽҽҽҽҽhҽҽGp ؚؚؚؚؚؚؚGp Gp ؚؚҽҽҽҽҽҽҽҽ uhGp ҽҽҽҽҽҽGp 3}3}n%Gp Gp Gp YQnGp 3}3}n%Gp Gp YQnGp Gp Gp Gp Gp Gp Gp Gp Gp Gp Gp YQnYQn uʁ)K!/#;Gp K!/#;K!/#;Gp hҽhhqYԉhSG}LhhqYSG}LK!/#;ؚK!/#;ҽҽҽҽҽҽ W *x $?v y U$V$H I Y${ $@| $@g$$L>h$$fff?i$$L>J K L $BM $AO ][P ]]Q ]NU ]EV ]SW ]Wf ]Receiving Server State...h ]mi ] Target:m ] No Target{$MPractice Roundn $@d o q ZloxPkZmv"t"p"No"}/@$?QN$>$L"M"rq$?*}/u ZloxPkZmv"t"p"No"}/@$?QN$>$u=L"M"rq$?*}/C%ZloxPkZmv"t"p"No"}/@$?QN$>$Q8>L"M"rq$?*}/D%ZloxPkZmv"t"p"No"}/@$?QN$>$=L"M"rq$?*}/| ZloxPkZmv"t"dp"o"}/@$?QN$>$L"M"rq$?*}/~ ZloxPkZmv"ot"cp"o"}/@$?QN$>$u=L"M"rq$?*}/G%ZloxPkZmv"t"p"o"}/@$>QN$>$Q8>L" M"%rq$?*}/H%ZloxPkZmv"t"p"o"}/@${.>QN$>$=L"%M"Zrq$?*}/CZloxPkZmv"Vt"p"o"}/@$?QN$>$u=L"M"rq$?*}/J%ZloxPkZmv"Vt"p"o"}/@$?QN$>$Q8>L"M"rq$?*}/K%ZloxPkZmv"Vt"p"o"}/@$?QN$>$=L"M"rq$?*}/GZloxPkZmv"wt"p"o"9}/@$?QN$>$L"M"rq$?*}/HZloxPkZmv"wt"p"o"9}/@$?QN$>$u=L"M"rq$?*}/N%ZloxPkZmv"wt"p"o"9}/@$?QN$>$Q8>L"M"rq$?*}/O%ZloxPkZmv"wt"p"o"9}/@$?QN$>$=L"M"rq$?*}/LZloxPkZmv"t"[p"o"p}/@$q= ?QN$>$L"dM"rq$?*}/MZdIPo"@$q= ?QN$>$L"M"*V"}/OZdIPo"@$q= ?QN$>$L"nM"*V"}/QZdIPo"@$q= ?QN$>$u=L"<M"*V"}/T%ZdIPo"@$q= ?QN$>$Q8>L"<M"*V"}/E$* }/ob2&6y n%Yввввв_ ._ ._ ._ ._ ._ ._ ._ .3},e,e,e u,e'yؚؚؚ,e3}3} u,eؚA]A]A]3}ɢq}oBA]q}oBɢA],e,ezVGB,ezVGBJ,e o>+j63}ɢɢ,e,eq}oBA],eYQn,e}L,e,e,ehh,e u,eh u uh u u,e,e,ehq}oB,ehq}oB,e,e,e,ehh,eh,ehh,ehh3},e,eh,eh,eYQnnSG,e,e}L,e,ezVGBJ,eYQn,eYQn,e,e,eɢ,e,eɢ,e,e,ė,e,e$,ė,e ~jU,ė,eh,e,e,eh,eɢ,eh,eɢ,eh,eh|\fF,e,e,eɢ,eɢ,e,eYQn,eYQn,e,e,e'yؚؚؚGp ؚؚؚ,eؚ}L}L,e}L,e}L,e,eYQn,eYQn u,e,eYQn,eh,eYQn,eh,e̎ u uYQnGp Gp Gp YQn3},e,e,e,e,e,eh u u,e,e,eYQn,eYQn3},eYQnGp Gp ,eؚؚGp ؚؚ'yؚؚؚ uؚ uh uؚؚ u uؚVD uؚؚ u uؚVD uؚؚؚVDؚؚؚؚVDؚ'yؚGp ؚؚؚؚؚGp 'yؚؚؚؚؚGp 'yؚGp ؚؚؚؚؚؚؚؚؚؚؚؚؚؚؚؚYQnؚzVGBؚzVGB u3},eؚzVGB uؚ,eؚؚ'ؚ'ؚؚؚVDؚؚGp  o>+Gp 'yؚGp ؚؚؚؚ'''''''yؚؚؚؚ3}Gp Gp Gp Gp Gp - =1- =1- =13}Gp Gp Gp Gp 'yؚؚؚ3}ؚ3},e,e,e,ezVGBGp 3},e,e,ezVGB u,eʁ)ʁ)Gp Gp Gp Gp Gp Gp Gp ''Gp ''Gp ''''''Gp Gp ''Gp ''Gp Gp ''3}3},e,e,ezVGB,ezVGB,ezVGB,e,e8f,e,eYQn,eYQn,e'''3}'3}ؚؚhGp Gp Gp Gp zVGBYQnؚؚؚ'ؚy"~ ؚؚؚ3},e,e,ezVGBؚvÎ u u u,e''''3},e,e'',ezVGB,ezVGB u u,ezVGB,ezVGB u u,e3},e,e'' u'' u u,e''- =1''- =1- =13},e ʎ uzVGB- =1,e3}3},e,e,ezVGB u,e3} u u u3} u^-^-^-^-3} uʁ)^-Gp - =1 uYQn _- =1Gp Gp 3},e u uYQn uYQn,e- =1- =1- =13},e,e,eh,eh,eGp - =13}'yؚؚؚ3}ؚGp Gp - =1 u u u u u?4+?4hhzVGBhzVGB,ezVGB,ezVGBGp 3}- =13} uzVGB'yؚؚؚ3}ؚ3}||h|3} uzVGB|zVGB|| we b`DIFHc "^ " ^""<g "i "JMPair of RoundsJRound Time LimitJReset CountdownJReinforcements TimeJPractice TimeN]?>Number of pair of rounds (Attack and defense) for this match.N&%Specifies how long each round lasts.N65Specifies how much time there is between each round.N10Specifies time between reinforcements spawning.NHFSpecifies how much time lasts the online practice round. (In seconds)z%i>A waypoint on the HUD indicates the location of an objective.UBe on the look out for HUD warnings and alarm sounds when an objective is in danger.]When a new spawn area has been enabled, Press %SWITCHWEAPON 10% to teleport to it instantly.|Press %BASEPATH 0% or %BASEPATH 1% to highlight the current objective, show a path to it, and slide out the objective list.>Monitor the respawn countdown to know when to expect backups.FSome weapons are better at destroying enemy Spider Mines than others.:You can be hurt or killed by vehicles exploding near you.g\ g\ T"U|"$@@^$@DK$M] xGame.xPawnf ]! UT2k4Assault.ScoreBoard_AssaultJ$]GUI2K4.CustomHUDMenuAssaulte ]UT2k4Assault.HUD_Assaultb ]UT2k4Assault.ASMapList] -AS\ -ASK"| "Y ]UT2K4Assault.ASMutatorT  ] Assault\]SIn each round, one team takes the role of the attacker, while the other team defends, in recreations of famous (or infamous) scenarios. After a pair of rounds, the most successful attacking team scores a point.R ]UT2004Thumbnails.AssaultShotsO -AS}/ ~q782E9:9:$-G@2#O K|;ҽ|;ҽҽҽ|;|;ҽ uu)'''''ҽ uu)ҽҽҽҽҽҽҽҽh m$L S @$?Z M-= info pod =-\ S1StSnn}/J\+cB Y7bSG}L3}3}3}3}3}3}3}3}3}3}3}3}hhh3} u,e,e,e,e3},e,e,e3}Zs,e,eʁ)h3}Zs,eʁ) u7rhh7rh3}7r7rh7r3}7rhҽҽҽҽҽҽҽ|;|;ҽ|;|;ҽҽ'ҽҽҽҽҽ uu) u uu) u3} u u u u3}3} u,e,e,e,e,e,e3}3}Zs u u u3}3}3}3}pp3}qYԉh3}Zspppphp,eqYqYԇ,eqYqYԇ,eqYqYqYqYqYԎ uqYԎ u,eh,e,eqYqYqYqYԌ3}3}Zs3},eqYԌ3}qYqYԇ,e3}3}Zs3}3}Zs *s]XWeapons.ShockRiflem r$z$>k$ lSM"[$Sp"Sv%a%_%l"ZX"%W $ $Q$BP$B|$S}/g%@ $ $SSl` S}/}/U }/}/t}/}/` }/}/o}/}/e}/}/e}/}/p}/}/Q}/}/}/}/g#U}/|}/}/{}/}/X }/}/h}/}/4}/@G7WB2+X5_ ._ .3},e u,en3},e un,e3},e u,e,e3},e u,e,eؚ,eʁ)h3}Zsh e U&] dropped the Power Core!S&]Power Core dropped!R&]Power Core picked up!O&] picked up the Power Core!K&]Power Core reset!@&E%%R${%{"rF@G$:AHBb$:P@BCE(G$HCH$@"SVSSYi$Bh $@@$@?b:@?f.$A5$AVF[ $A}/}/@}/}/P }/}/P}/Iy1:@O'5M7<(T_ .VD3}Zs3}n%VD3},e uVD,e}L3}Zs}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}L}Lu!K>3}Zs}Lhh u}L}L}L}L}L}L}L'5M7<}L}L}L'5M7<'5M7<}L}L'5M7<'5M7<'5M7<3}3}3}}L yDjC$@@k#$?l#$?U $33>_ $`jFH$>s#"v#G,`ZrS}/}/}(}/}/e }/}/t }/}/}/}/g}/}/W}/}/}/}/Z}/}/}/}/@}/}/y'@}/i}/U}/}/u}/}/g$@&}/s"@&}/z}/}/@}/c}/_}/}/I"}/}/z!}/}/j}/}/y c}/~}/}/}/}/~E}/SU}/p7 }/}/M}/}/R!}/}/M!}/}/FE}/f}/}/a:}/o}/}/C@}/|}/j}/}/N}/}/E}/Uo8s g*}/ʁ)ʁ)ʁ)ʁ)ʁ)}L}L u}L}L}L}L3}ʁ)3}3}ʁ)ʁ)3} "xn$@#@rSVA}/}/A }/}/}/Y`0|@ SkY}L'5M7<'5M7<}L'5M7<}L,e'5M7<'5M7<}L'5M7<}L,e}L}L}L'5M7<}L u'5M7<}L'5M7<}L}L'5M7<'5M7<}L'5M7<}L,e'5M7<'5M7<}L'5M7<}L,e}L}L}L'5M7<}L u'5M7<}L'5M7<}L'5M7<}L}L}L}L,ehh'5M7<}L}L}L}L,e}L̇,e,e,e,e,e,ezVGB,ezVGBJ̌3}Zs3}n%3}n%'5M7< T"1TSV}/}/t}/}/S}/}/~}/}/}/}/C@}/}/}/}/}/}/S }/}/\}/}/e(}/}/|-}/}/X }/|O~@2A]׿e]ɢ,e,eq}oB3}Zs3}n%3}n%'5M7<'5M7<3}n%3}h b`DIFHv yI%1}/}/}/}/N@}/}/w}/}/Q}/}/.}/}/=}/}/l }/}/e$}/}/]}/}/F}/}/^"}/}/n }/Ya"]-!&-9:9:$9:9:$GB Y7HZgqCySG3}3}3}3} u u u u u u u u u u u u u uqYqY|;|;ҽҽҽҽҽҽҽ u uҽ8~`nҽg*}/g*}/g*}/g*}/'g*}/g*}/ u u u u u u u3}3}ʁ)ʁ) u ug*}/g*}/g*}/g*}/g*}/g*}/g*}/ u u| 9@| 9@Ƅʁ)ʁ)ʁ) *M$L>ZZ$@F$E}/X$AH:B{:HCBz:HBQ$'7p#$An#$?m#$Bj#h#Z: CAmz$?nWj]_^: Bc]manning a turretz]Energy TurretTSFKLMP$PFR$b$c$U$V$Q$"Dh"Zt x`$@#@eS.$B5$BFSZ$}/}/L }/}/`}/}/}/}/Q}/}/}/}/m ~}/G}/}/}/}/2}/qWEOX 1--9:9:$9:9:$GBY7h SG u u,e3}3}Zs u u3}ܝܝ܌3}3}3}3}3}3}ʁ)3}3}hh3} uzVGBzVGB3}uhʁ)ʁ)ʁ)ʁ)ʁ)ʁ)}L}L}L u3}3}}L3},e,e}L}L,e u}L3},e,e}L,e}L3},e,e}L,e}L}L}L}L}L u u3}3}ʁ)ʁ)ʁ)ʁ) u u u uҽҽҽ3},eҽҽҽҽҽҽҽҽҽҽ u u u u u u u,e,e,e,eʁ),e3}Zs,e,eʁ)3}Zsh3}Zs,eʁ)ܝ܌3}3}3}n% *I $DJ $tN ]Speed:\$BR $@Fk"h"mz$?nq"`$]SpringSpaceFighterW&"X&"d!$Y#A#TSO N SLMP$PFb$Dc$DQ$zCh"Zs L#$DK#$Y?`.$pB5$AH:PMN$BO$@}/}/Y}/}/^ }/}/r"}/}/n}/}/d }/}/T}/}/}/}/}/}/}/}/}/}/r}/}/i#}/}/j}/}/G 8}/}/}/~ }/}/Z}/}/B }/}/L/}/'}/j# }/}/_) }/}/}/}/b}/}/N}/}/}}/}/@}/}/3}/}/P}/}/C}/qT2aU]\" E "F "W]DummySn}/}/]}/}/}/}/v}/}/Z }/}/^}/}/l@}/}/H(@}/}/p @}/}/B}/}/}/}/W@}/}/@}/}/v'}/}/\}/gKp8m yg{"g*}/ `$= >r}/}/I }/}/l}/}/}/}/B}/}/z}/}/]}/}/}/}/C}/}/}/}/}/}/t"@}/@}/D}/}/E}/}/Y5}/}/@8}/jL} ICJ ? ף<JL?IJ H G}/X}/}/u}/}/Q !8}/u}/}/p}/}/h}/}/m}/}/P}/}/}/}/t:}/D }/}/}/}/Z }/}/@}/}/V}/}/_&}/}/n:BgQ0\@2 u:؂u_ .VD3}Zs3}n%3}n%VD q ]= My Messagel VS}/}/}/}/u}/}/_ }/g}/Y }/g}/z(}/}/N ]}/S }/}/i }/}/}/}/R}/}/}/}/}/}/v7} wB1 G}/t&}/}/J}/xw0e2ZNo" ͅҽҽҽҽҽҽu)ҽҽҽҽ- =1- =1ډ- =1ډҽu)ҽҽҽҽҽҽ- =1ҽ- =1ҽҽu)ҽҽҽҽ- =1Jҽҽu)ҽҽu)ҽu)ҽҽҽu)- =1zVGBҽ- =1zVGBҽҽҽҽҽҽҽzVGBҽzVGBҽҽҽҽu)ҽҽҽu)ҽҽҽҽҽҽu)ҽҽzVGBҽҽҽ, ҽYQnYQnYQnYQnҽҽYQnYQnҽҽҽYQnYQnYQnҽҽYQnYQnҽҽҽYQnYQnYQnҽҽYQnYQnҽҽҽҽҽҽҽҽzVGBҽu)ҽҽҽu)ҽҽҽҽҽzVGBҽҽzVGBҽu)ҽҽu)ҽҽҽҽҽҽzVGB8fҽҽzVGB8f\fF8f\fFzVGBҽzVGB8f\fFҽzVGBҽҽzVGBҽҽzVGB3}ҽҽGp Gp Gp Gp Gp Gp Gp Gp Gp Gp Gp ,e,eYQn,eGp Gp ,eGp ,e,ezVGB,ezVGBJGp  W b`DIFHg ]Remaining round time:v]Round:h ]/i ] ( Defender )j ] ( Attacker )m ]'& You were killed. Reinforcements inp ]Waiting for reinforcements..._&] Automatically respawning in...^&]You've won the round!\&]You've lost the round.Z&]Practice round over.}/}/}/}/a }/}/t)}/}/o&=}/h-}/}/S}/}/F+:}/f(}/}/k}/}/}/}/K}/}/_ @}/}/f@}/}/p}/}/}/}/M}/}/|8s}/}/}/B }/}/Z&}/}/w}/}/y}/}/V}/}/T}/}/I}/}/}/}/}/}/b E}/{4}/}/~  }/}/^}/}/K@}/~}/l }/}/}/}/}/}/J}/}/j}/}/}/}/F"}/}/G}/}/}/Zum5j *$--9:9:$GB Y7R3Bk,a!@ff> G}/l}/}/v"}/}/v@}/}/||n}/ }/}/m}/}/x }/}/}/}/{ }/`|9X ~ ֟ Ki yS}/}/N }/}/}/}/U'}/}/g\E}/}/}/Y@}/}/A}/}/ WZHn%  *-_-c 9:9:$ w_*a/!&.__$9=,dwd*w.d*.dL"_$'dd -QaW( G}/}/Qw1I @Q }8 Z Z Z Z Z Z Z Z Z Z Z JY{V;W;X;zY;Z;[;;1S?}/}/T @\}/u1q%; a/!c -' -'Q --T/tn!}/ nR !}/ R R &R   R  9?  9:F+% F+ D+  B+/ a2 q%q% B+q%D+q% 10 O/ [#c   - -a --h  M/ - -e& --@+ - -* --*-@+-e&-e& we%* - 'we%*e%   G}/@)\}/E\}/d}/}/}/}/v@}/}/}/}/i}/}/^ |d96N6N}?6Noo6N6N}?6N6N6N}6N6N}N G }/H/}/}/a @}/}/vbAI9:9:$pppp9V client damage type 9V^ by 9Va _r* - wa* wa x  ray  y ax r^*^ b^ B^ -Z %9?&pw*f baoB^wa*awb9?,f VbaoB^^-  f%fvfQ-w^* f%I!^^ 'fo#o-Z  I9?fao^BJ%- w*@(wa*ias  w^*^-i%Bbi^o}}w*E"aof^Bb? G}/p @}/}/c E}/e E}/f }/}/`}/}/}/}/g }/}/M}/}/L}/}/P}/}/X}/}/h }/}/R@}/}/Y }/}/w @}/}/P}/}/o }/}/A}/}/}/}/q}/}/v@}/}/}/}/B!K 4r* {]%]% 9:9:$mM !}//a0 'KM ll10-r -_-_9:t9:$ae( G}/}/}/ }x jKh x 9?&-(x Ow*9?&*v  G}/S}/}/z}/}/ H7T@o w*K\%[%-}& -T-}& w[%*r[%* w\%*r\%[%\% -}& G}/O}/}/}/}/^ }/}/}/A}/D }/}/t@}/}/G}/}/D}/}/B+:}/U =}/W =}/Z}/}/W"=}/V }/}/V}/}/[ }/}/}/u}/` }/}/{}/}/b Q^}/w}/}/y&}/}/l }/}/^@Q}/f }/}/g }/}/h }/}/i }/}/}/}/{&}/}/l}/}/B@}/}/p }/}/q }/}/{}/}/A+}/}gq2s jF݋ؚؚؚؚ uVD uzVGBzVGBJ u uu) u' u' u' u u b`DIFHU ]You are Attacking!!W ]You are Defending!!vlvkr *p *` W S_ ] >$>}/}/l}/}/a}/}/~}/}/x }/}/O,}/}/a) }/}/w$}/}/s8}/E @8}/F 8}/}/}/H:}/x}/}/I8}/F}/}/M :}/{}/}/s}/}/V }/}/~}/[Zv 2l\ nMy p'3}n%\fFؚؚؚ\fFؚ\fFؚ\fF\fF\fF\fF||8f|8f| uʁ) u|A_t$ u uʁ)| v|ؚؚؚؚؚ'3}WSFؚؚ\fFؚؚؚؚؚؚؚؚ\fFؚ\fFؚؚ\fFؚ\fFؚؚؚؚ\fF\fF\fF\fFؚ\fF\fFؚؚؚ'3}WSFؚؚؚؚؚ'3}WSFؚؚؚؚؚؚؚؚؚؚؚؚؚؚؚؚؚ\fF\fF\fF\fF e b`DIFH{H}/}/}/}/dY _sXK D NY  V K GY  V D WNNGG6ONW6OGWO G }/j}/}/}/}/P.}/}/d~}/n ~}/D}/}/\}/}/| }/}/K%}/}/}/}/Y}/ }/I}/}/D)}/}/j}/}/}/}/U@}/}/}/}/\}/}/v}/mR8` BVzX?4 "n$@@#0rSXSeSVAB}/}/B}/}/Y}/}/}/}/` gVAYMB-z-9:9:$9:9:$w@ * w@ -@ -r.* w*2wpV>BB.- Bw@ * w@ r.*V333?Wr@ *%tlr@ &t,9:9:$JCC` V@ CXY G}/G}/}/feDSTOv!D-`'L9:9:$@ai ai 89 G}/}/}/e}/}/k}/}/}/O_Uijsn@hh3}SGh3}3}3}SG܉hb^ܓW=ܓW=ܓW=ܓW=ܓW=ܓW=ܓW=ܓW=ܓW=܌3}hhh3}3}SGhBBBBBBSGBhBBhB3}h3}3}SGhBBBBBBBBBBBBBBBBSGBhBBBB3}hBBBBBBhBBB3}h uʁ)I.BBB w t "u "w Tv :A xB{ z  o$$u=I$$Cq$$@Fr$D`  j k Iz~N}/}/e}/}/bu"9UgJu" ף<E:K(u" #=Eu" ף=m9:9:$u" ף<9:9:$u" #=au"( G}/mVE#H9:9:$ GVeG9?,Be?eeD).lw*eA9DeD)VVeB*9?,dA,#* G}/g k p }/`Eg 3Xa@'6%69DE9?,9DE9?,69DE9DE9?,?66?66 G}/or { } }/D8u}/_|B}/uA I K }/p,8C}/G8}/P 8}/]%:}/S8}/}/}/}/}/T/:}/\ }/}/~}/}/R :}/F}/}/Y}/}/T =}/e*=}/\=}/k}/}/j47f|-f  r* R-e ]99Y-e '-`TT. 7pA]zDT]Y 99zDzDVTY B~?D7?t9:.%9?69?d6%rc qrc .9?%r.(?u~u7FZw~w7FYy~y7FruuwwyyYF{EYY{7wE7uF7yxY9:.%D6x%6% 6x%6%6x%y99xTQ~Q.9?%Q7~.QQb b xF{EQ{6x9DQ9?,n NewRotation.Roll:9S6xStrafeAccel:9UQ- '-'xa+x G}/r*=}/h:}/`=}/}/}/g}/}/}/}/OaeQ  G}/@}/}/e&:}/QPVX9  GFt1C @k*00ܓW=W=ҽW=ҽW=ҽW=ҽW=ҽ3}6 JYJKL1ST?}/}/V@}/}/u4}/}/q}/}/b.@}/}/z }/}/t}/}/V@}/}/u}/}/}}/}/QE}/}/}/DEQ PH @KιQ }8 }/Tz1J @PܓW=W=W=W=ҽ JYw1ST?}/}/c}/}/Q}/}/}/XK @T$2e  X $>}/}/o@}/}/X}/}/J}/}/i.@}/}/d}/^N2N @\*FܓW=W=W=W=W=W=W=W=~(~(~(W=ҽW=W=W=W=W=W= JYrs1S?}/}/PE}/_R]}/]R_e9O b^6hSGSG \ Zv+p "r "I$+FM}/P}/l]TranslocatorFirep$>aaB: Bc:D}$@i:?F:D$@C$p}?F$>r$u}/}/o p q }/q}/}/H}/}/I}/ZMn7R B Y6KPZgqCy3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}3}hh *_AEyM$?ZZ$@F$@E}/X$ AH:HB{:BHBz:HBQ$ #c]manning a Minigun TurretzMMinigun TurretQ$Ch"3$= >T$D.$pB}/}/J}/}/r}/}/q }/}/s}/}/Q}/}/f}/}/s }/}/R}/}/y}/}/}/}/K }/}/RU}/}/}/`@}/}/_}/}/DGK}/K}/}/O+@}/}/E'}/}/}/}/}/}/}/}/iU}/o}/}/M@c}/}/}/c}/}/s}/}/P}/}/{}/}/|}/}/M+}/}/p}/}/U}/}/Z }/}/}/}/Fr s t }/^~G}/PE\d5w 2MH\fF||}Lh|h||3}|hhhzVGB}L|hh|hqYԋؚ'ؚhؚhh|zVGB||}LhhzVGBؚ}L E 7ؚؚ3}WSF'yؚؚ|||h||||h|}Lؚ'ؚؚ||ؚؚ|||h||X8 ||3}X8 |hX8 ||||||||||X8 3}|h||||3},e,e,e,e,e|,e|h|hh||h|hqYԟ|||hh|hh|||h|||||||||||h|||zVGB|,e3}\fF\fF3}3}n%|3}n%}L3}n%ؚ'u!K>u!K>,e}L3}n%|,e}L,e3}n%3}n%,e}L3}n%|}Lhؚ''h8f8f8fؚؚؚؚؚؚؚؚ|h|3}| e b`DIFHu$$M#"R#SW#}/}/a}/}/D}/}/s}/}/Q@}/}/R@}/}/S@}/}/T@}/}/R@}/}/b*@}/}/@ }/}/}/}/nv U+9:^ 9:$'a/!&k9:^ 9:$h. 79:v '. 79:v '( G}/o|ew.|*U9=.|V{b .| D b w..|*L.| G}/qdL[id G}/}/}/^ pE &' G}/[}/}/tO %j9:9:$ 3a/!& .x$[Attackers Win! G}/Y}/}/x% ^9:I 9:$9=,Y9=yK9:I 9:$Y9=9:$9:Y G}/]}/}/qW !4;*W !Fq6W  G}/z}/}/{a<TKw*a4wc*caKwR*Ra G}/}F {O%U(9:9:$ r* F9:%Y i-{ a!apr*ai . / w*-'a*%  % %>&>-($$ $C$$Aa**a . /a+ a*pw*O*6F @ F -'a)\>(9:9:$ rc*car /j wc*c-'ca*c"tca**ca /jca+ ca*c"wc*c =9:s 9:s EU'p=rU'*U' 9?a _  9PCLK G }/I |O x]uwg*.\.%_gT ]U $ G}/~BahG}/ wC, r* =-{Y ?K-{vziz9D9?S @wziziz%z9D9?S wz%z%q!}/q9D9?9D9?q9?zw9?6@ q!F@ %? G}/A9w*-( G}/Ep1-{''w*Sq!a G }/FK -{ -{(w**"aR @ @?-9:9:$rR*RaZ . / wR*R-(R-(R-'Ra*qRa**Ra . /Ra+ Ra*wR*R O G }/ G|A !+{|z G}/*}/}/J}/}/KO39:9:$a/!& *w**nw***-w.**.*@'Kw**r**}(**t}(a** E *. Q*(**G G}/Ig C-:9:9:$ Xr*ae . / -9:9:$g#@g#g#g#7w*X g#S$. /a S$g S$e/Wo x&99  b kx&S$o #g `/o!x&r)66%6o!66%6o!66%6o!66%6o!66%6o!66%6o!6%g r)6%6%w &X  G}/}/}/TA U?Va/!&Y9:a9:$V. 79:A '. 79:A '( G}/Y}/}/bRO39:9:$a/!& @rY* CYwC*wC*C-)U9=C9:c9:$ wx *wCx  .q !}/ q !}/Cq b-fYa/!F.Y@'. QC( G}/ZSLC0- rS*rS* Qa/!& SF ''X !}/ X !}/SX .QS( G}/Mm /c1%`lI O U  I 6m O 6m U 6m  G}/][e,S.[@- rS*rS* bSrbrbw.b*wb*b-)U9=bLS S d % G}/I }/}/}/}/Q K U59:Q 9:$'a/!&k9:Q 9:$h. 79:K '. 79:K '( G}/YQli%" QOI G}/F0b$V 9:9:$9:e 9:l(9:e &YwI *I aI *9:e &{(a# BrE!*E!a }# {(rI *b$6b$6b$I a }! b$wE!*E!a;9:e ,;wI *I x!c9:e ,cwI *I w!l(e &9:e d( G}/Z A0V gw E-V ir*&iq*:-V J$BJ$ G}/f\ [#Q-\ -F-\ ---Gg--G( G}/gS"H-K -G-G's$%s$7_S"s$_ wS"*S"%S"-rS"*S"a/!-G(s$--K  -Gg'- -K -Gg( G}/hLLq Y--G rL*rL*U9=L u$%u$7_F"u$_  wF"*F"%F"- rF"*F"a/!F" ULu$`H G}/pet Te.K--G re*re* ve<w.v*\rvrvrvrv:wv*v-)U9=vLe e d % G}/}/}/a/n UaJ 9:v 9:$'a/!&k9:v 9:$h. 79:n '. 79:n '( G}/sbS"--GH G}/o ho &v".jv"v"v".Z[!v"v". $o  G}/wHM- -GH G}/ r\b_w*w.*.. G}/tvy&.$ G}/}/}/zG--GH G}/}/}/x}/}/ {yO3L--3-H0-Gg'Ia(I-Gg( G}/v X(!'W/a9 'X(;:X(n|7__X(10T-g( G}/}/}/}/}/}/}/A}BGqla/!&K9:^9:$.q&.q% G}/}/u}/M0gA@{xwz*--TzBgzijk G}/a$}/}/Et`%^a$b"twa$*- -ra$*8#Ta$B(t G}/ Fr9rwr*wr*B66r r(r errra @' G}/^!-_a @' G}/L[FI@w#*4w#*#h#a~ G}/}/}/W}/}/ NKx5mJER r#*#-9:X9:W(' G}/}/}/ OmD*'R r#* rm*(jw*#-m G '#D m 9?mb#D G}/P~U#aP br#*pppp9V could not spawn flag of type '9VP ' at 9X #.r!#a  #pB G}/Qo~ G}/#b}/k1V i$5dV eR rd*rd*da/!W p.dphpaV  G}/c}/}/y ^ `:qc^ l^ -H/ wc*wc*ca/!W'( G}/s@}/}/e}g*-($ G}/fiKe- '-'tPCH6+?i.wwi*i-i-'w*-q w*S  G}/jhE VVe<E q!t G}/}/}/nidEdVd G}/ml9dV# G}/}/}/j}/}/_~2^fXd G}/}/}/um|vc G}/}/}/o}/}/p}/}/d3n!{f/a0 n?,n-1?7bbn10/a0 Z c7CCZ 10/a0 u[ 7KK[ 10R a K!R w  G }/q}/}/s}/}/[|tADc G}/ra3wR *R aR *b!c! G }/vTx D-\ -rw*w*y&y!%rry&*ay& a-(-` -w.*.-E'-(T--\ --` -M w.*.- M!T G}/}/}/x}/}/y}/}/g3Ww i`W-a -}w*w*{&y!%}r{&*a{& a-(-l -w*a/!c.-E'-(W--a --l  G}/}zbb G}/~|hb G"}/BSCb G}/AAjF[% r *  h%6K66K$uAKuA]uA[uAbuu=r* .-{6Iu6\u6[u6`u6W uuu=6I66I$uAIuA\6[ U&uA[uA`w *9? ~ 9?,9?% [b6o u6C"u6m*uuu=6o 66o $uAo uAC"uAm*w` *` -_ 6W"%6V%u6e*u6o&u6r*u6W"uuu=6V%66V%$uAV%uAe*6o&uAo&uAr* h%dAT dAU er* .-{dAW w *9? ~ 9?,9?% [bL!Aw` *` -_ 6W"%dAW" G}/}/}/o3ok p\r * m h%o% h A 9: d9:$o j#@o,<A o@,<6T @6U A ,<.@, 6[6[, 6T 6T , 6U 6U , m6[6[6T 6T 6U 6U 6W  UYw` *w$ h A  `)` _#I` -_  w$%w$6W"a $ (6W"w$ G}/^C@D*b G}/DR b G}/HQa G}/{3Jl = G}/}/ }/EH } =*H k jH `H  G}/JFra G}/NPa G}/}/}/K}/}/L}/}/ PMOra G}/}/}/SONa G}/}/}/Q}/}/TRG` G}/UE` G}/V_` G}/^}` G}/\d]ha@( a}/G }/] }/}/Z4u)nU=6Hu)K.6Hu)J.H G}/Y}/}/@][C_\H-w*h_w.*w.*w.*.Z - (- (- '-', 9:9:$}a|-  w}*}a*q!]E.%] <] q!t G }/jtu <DY!w}*}A}*Bw*A*-($9:9:$P*a Q  u  G}/H}/}/}/}/m_b-W u G}/^gPU G}/NXr  G}/ZZj.W6dt)I.6dt)G.6X{#ZLZ6d6XhZLZ6dX G}/}/}/[TJR9:& KT'z z =Ga9:t T9P\wG*Ga* G}/h^q0Lgdw^*^a/!u^- S^ ES^ G}/igep"$h%;h7bphb1pRp-  }pegpe$ejoKepd joNepd o1@epd jo6e$repp-jd pepk(d n+?p_xed n11-f+uepp-jod pepk(d n+?1p_xed n?h G}/}/}/DcG5 rc*(x9:c9:c&c-c U(c 999?%(' G}/q5{Sf'Pr* r * Ert *t a A"Ert * w r!*(w r!p$ r!t Xf9?%$$wG *p$G wR *R |t X'$t r G f9?%Mwp$*t T{p$ G}/p$}/}/s5N\x\Bg_ -na/!h -nG x@cx -ns7-ns?wsBw?5b(Bw9:_ %659C9<$?9?,Xw659C9<$w??PBnEBn5$566QP?6QE?a/!h {n gf5v5z5Qn  (ZZw*5/aPEBBw*! v9=_5b'b(Xb(9?&X5&9:_ %659C9<9C9<$?9?,XwG659C9<$wP?nE?n546QP9?, 6QE9?, 54a BPBE?C?CBBv'kYv'9?%6Q9?,0{5Qv'?B G}/o }/}/ x3xf-{.3r{*r{*(xj{-U{x\`'Dl l o x a#pBx rxibix Ba!]6iiXX Al@ma!tXXHBl@@l?Tja=iM6`9DUDX9?6j9?6M6`9DUDX9?6j9?6M6`9DUDX9?6j9?6MM`A#4B6AlHC\o aA`wap q \x (# A A A*\p q 9?, ' G}/ H.$ID2% $P.r*$9=,$$$aLOCAL CONTROLLER.P$@.i pi I$P.$a-- SPACEFIGHTER.P$@.e f g $>aѨpp-- GetAxes, X:9Xe , Y:9Xf , Z:9Xg .P$@.$aѨ-- Acceleration:9X.P$@.h 99$=aѨp-- Gear:9UT A% Forward Velocity:9Uh .P$@.$aѨ-- DDSn .P$@. G}/}/}/B JP @WH=-P 8B -P 5- a!ta:(En!( G}/`%t4cnH-`%c]99 G}/| Mej -| e]99 G}/Z%cav. 7w*a.w}*}aZ% G}/ f~ k (%9:9:$Xg G }/jf\ T-f 'aQw.*-.o  G}/}/}/Y 20}/@}/}/}/}/S}/}/k K-TG9/a!~@? G}/b5rHAr[dT-i-r&a | { ?CBBBr&a | { BBBB G}/t5{{k{@{$cc]]{66\c?6\]?{Rc]H h-g-{_H 6{${66\cH>6\]>{*QcH Hz?]? G}/}/}/jk y<$Ijy#?/wy*yaFwz*za G}/}}/}/E }/}/dG}Ɠ#9:G9:V'( G}/ nCfl.Grl*wll-(C~l-UlC`'D S S E WaVC A a=C ~69DUD T 9?6A 9?6~69DUD T 9?6A 9?6~6%~`E aUwaf g `E (# A A A*`f g 9?, ' G}/}/}/oMf4.Iw.*.-.K"M cM>M>Y L Y MN J[L [MN Hp6m9?p9?@6|9?p9?6|<9?p9?6|[9?9D[%mm9?p9?@6|[9?9D[%V6V9DY 6V9D[a+V+Jwy*9:y9:$yW+wz*9:z9:$zWz OV G}/Z%qa7wy*ya.wz*zaZ% G }/}/}/rpM ' G}/C:f S%wE *yaE  _ JwH *zaH  _  G }/T*T:!r $9:9:$_ T* G }/v }/}/s }/}/jjI%.,& r*r.* w#.wjw#w#-{jw#-E'|jw# G}/ KY(G Ę9:f ,['}09:f ,[(}}9:f ,v%}v7KswvKg*%vKgY({vKR -} vKR !e pwG *2wG *G Y(['pwG *G Y(['}vE G}/zGK]%ot&p*#-'o$a(((w.*w.*w.Z *w.Z Z *w.*G.w.Z *G.Z &wG*G-G-'Bw*-q 9:9:$9:9:$a?(lNr* -,wG*wt&*rt&w*Z a+S Z a+BBwZ *Z a+Z a a@(liw*S a G}/u79U%-a G}/}/}/xl[ܝWfmT-i.-l w*w.*.U#, G}/C{|Oa$ G}/|c(waDc(G G *G lAwc(G  wG *[( G}/}/}/}/}/@}/}/IAfN1$ G}/}/}/D}/}/E}/}/F}/}/G}/}/NHAL# G}/}/}/}58m7T<'r * r* r* 8e(f(b%9b7CbCr*-\/'9:o9:$9:o9:$! v9=/'9:o9:$# v9=/Rr,8e(f(/|8  6|9?%6|8/6|9?%6|8/ 9:o9:$838B9=D $689C9<S?9?9:S,V $689C9<S?9<S?X 68ST8|bG G}/J}/}/L}/}/OMbJM# G}/Q|I" G"}/SSH" G}/}/}/TRDG" G}/URF" G}/XQE{" G}/}/}/ZVYD[" G}/}/ }/[YrC3" G}/`PB" G}/}/}/]}/}/^}/}/b_OA! G}/}/}/faN@! G}/}/}/c}/}/gdG?S! G}/hE>! G}/i_=! G}/^:  G}/nyt-G i}/}/}/Kyt[wp*J9?pp?fJjpp^ppw.p*P.pXP?$fC?jEC?^B9=p E&a fECC9=,9=,9=, Ej-~&a fECC&a fECCfB?jE A?^zC?jI9?,?^_J6$`,zf?IE?-a fJEAAfB?jEB?^zB?jI9?,>?^J{>b'b(Pb(9=,9=,9=,?P6$`,zf?IE?&a fEBB G }/k}/}/@my4 !}/ G}/}/}/o}/}/J }/}/}/}/B$}/}/Q9O/0>m h g B$M:-a6B$m 6B$Oh 6B$g 6B$ G}/}/}/ wuc r*(\qw*qa/!o9= Ko$o$o$o$'( G}/ `%u oh5'wu * w*\ u  G}/A6 B59: %2,9: &2 G }/}&}/}/}/}/xPgòWBPWP_Wb'b(W9?&Xb(XP-f9?%Wb'b(W9?&Xb(XU$W G}/Z%OD'(u%n%w*Z  G}/}/}/W}/}/ F~C+F G}/{G_ϴ#6O9=,lG{>6O9C9<$9?,@@G?6O$6O$G+?6O9=,6O9C9?,@@G>?6O$6O9C9?,@@?G?6O9=,6O$O G }/}/}/O}/}/B}/}/AH@i(Q  ]99_9?%(DH Q  ~6D9?%6DH(6D9?%6DH(' G }/ND* G}/}/}/G}/}/H}/}/I}/}/}/}/E[a U\_\_4^b^bn\[_\[_^[b^[b G }/J}/}/nMI) G}/Q[V-d-m  G}/@}/}/Vas&9:^9:$Fra* rs*sa/!N h`.swa9:^9:$ wo *9Vo 9:^9:$ G}/LzHCUv$6U6t %4dt#??vR&4dt#vR%4dt#?vR&4dt#?vR%dt#??vR&dt#?vR6%W9?9D6%9D6&%dt#?vR&dt#vR6&W9?9D6%9D6&{hahMx6%66%W6%66%4x6%9?%6%/6%M6%MU6%9?%6%6%6% ah(=A9? D@A9?C96%W6&W=-l  6%W=?6&W=?6%46&4@j-l  6%4@?6&4@?N66%WQ66%4xNQ&a =@BBN66&W==Q66%4xNQ&a =@BN66%WQ66&4@@NQ&a =@BN66&W==Q66&4@@NQ&a =@ G }/f}/}/X`g ,3r~*~!}/f!}/Gf~e-d f!}/(9:n (a/!&9:F9:$. 79:Z (. 79:Z ('f!}/ f(' G"}/C}/}/D5WO[ +-diCf-d G}/E!3-m -d G}/ d0v} Hr*}>w@*@is!Z}9:.X s!Bs!Qs!Q Av s!BBv s!ZY~wY*Y Av Bv G}/ j0nw {U.nRw.n*U-(nADS!YU-'@pnn.pa w..p*.n ..pA9:.p9:$ no$ uS!ZnA@pnS!zDn  G}/J@}/}/a^R P1j."rj*jh%9:jd9:$N%jhjAj9:jd9:$Njj#JLT N{JJJJppJQ9Sj~ R9Sja)J G}/E@}/}/c`S )F.99:Fd9:$FS w.*#.Y.-`#.a!ZEb*9SFUE FU%.a!ZER9SFUEE G}/q@}/}/LbT B.qwB*w.*w.* w.*W9=.9:W9:9@B-NqqSqqTq G}/RKdwd9?99I6daJ9Pd6sa6sa6saBK s 6B6B6D6B6B6DB G }/lRuVH iwC$*C$RC$-U-E/QC$iQC$wQ*R$Q$$$R$!}/$$$ G }/}/}/h}/}/Z}/}/d}/}/qjU GYPwZ*wZ*GZ%oMlV G }/@}/}/m}/}/n}/}/o}/}/r}[ :!} %\ &`  G }/\`V J>`O x{|w`*`a/!=.`G *M+.`l-K+.`h!'-K+O %`$%O+$$  &`$&O+$$  u`M+O %;u`*O % G }/X}/}/@}/}/ vL A rL RoundLimit%l 9RoundTimeLimit&l UResetTimeDelay,l uReinforcementsFreq,l PracticeTimeLimit,l  L  G(}/ B3aD h_ aa4bRoundLimitQk$$Text3;1:999a8bRoundTimeLimitQk$$Text3;0:999a;bResetTimeDelayQk$$Text3;0:999 'a?bReinforcementsFreqQk$$Text3;0:999 'a>bPracticeTimeLimitQk$$Text3;0:999 ' G }/ x"K N "@"RoundLimit9SB@"RoundTimeLimit9SD@"ResetTimeDelay9S@"ReinforcementsFreq9Ss@"PracticeTimeLimit9Ss" G}/ D3uJu G}/ wab9%9?%&9?%)%&9?,w*a/!7%&r%-.$%$4.$&$r&-.$%$.$&$sw*a/!F&%.$& $&%.$% $. $o-$ G}/{X+_0G  X+!}/fwf*fa/!)9:q ,f9:q .f$X+NPQff0 G}/}pL #wep%bwp*K}ppY *bpp G}/N}/}/ H3J  -S)' G}/}}/}/C6mCmxmVm@V?V?"X?9?,Vr *w* .w*w*` .Yffx`w *V O`9:N9:V rG *G Rw`9:N9:VNV9:a*~ a*9= G}/l}/}/N6y| r *y 39: d9:$ p h A  h% p& p39: d9:$ 3p3, 3,3,$%$83,$&$`3,x$,$3,<$,$ 3,$,$3,$,$$3,  3%$3&$$$ G}/ Fw A xl.w !rl*7?%{%{7?{?`l N  w  N {4@T  G}/~}/}/ Imjikwm*wm*wm*t9=mvttwm*m*w*~jmtvw~*~{v/a0 Y&|9WY&v0Y&10~w~*G!A ~tmoG!K#K#G!u#~~~$r.u#*Warning - PATHS NOT DEFINED or NO PLAYERSTART with positive rating稨 Player:mH Team:9RtPlayer.Event:9Wmk!K# /a0 ~{w.~*Z&.~Z&tG!A ~Z&mw.~*G!9?,2G!9?,G!K#K#G!u#~107?%r%r7?B r?sm.u#tu{B .Ymd!B rwm*m!}/u# G}/BHo 5_r *v:9: d9:$ S kw.  *w` *` -`#[ Nb*[[9S U[J U%a!Zo [ NR*[ NU[[9S UV[[ G}/[@}/}/Ll}Dz+u.lQ .^ JwQ *Q Ul P lltP *P al Q ^ wu*uR l u-ua uku-Ol G}/g}/}/NKgX vrg*ASGameInfo::SpawnAndPossessPawn - PawnClass == None. PawnClassName:X (r*ASGameInfo::SpawnAndPossessPawn - Pawn == None. PawnClassName:X (2ag   r2*2ag   r2*2agr2*2t2*2ag(222 }2' G}/R }/}/OP JfMwP *R 9VP V R MwV *V   G}/ PmOJwz.Ymd!Sw.m*.mOwww.m*.mORm G}/T Q`Hw *^&. Hw^&*^&@' j 9= ^%.Y d!{^%K ^%.Y d!;w * a    a+  Ow *.-ow. *w. *  . a.w. *. a. }_r *O R  a    a+    # F ('Ow. * z^%. l$. w * 4s     G}/ O3rE  rwr*wr*_&.Yrd!{_&Kr_&.Yrd!w.r*d.r G}/] }/}/[` }s] .Gr] *` R` -(n9:] O9:` '( G}/V}/}/ \Ejcm.FlrF*FRV%wV*V- }VFVVV\`wF*$wE bF(*B  9:F aB E E `Z,\E&9:FrF*E$!}/$$$E#$F$$$`FE9:FrF*E$!}/$$$CE#$F$$$`E$!}/$$$ G}/t3e OΉ \ Mre *_!}/$9=9:$9:e $$_e $9=9:$9:e $$re *_!}/$e $$_e $e $$ G}/^^PgKWD.O~ D-t '1%w1*9:D9:11--u '1R-t (11K-u -t D9:D9:~ .OS1%*w1*9:.O9:11-1-i!1^- J9:D9:~ r1^^-*\O1 11,Twi!*\_!}/$9=, $ G}/ u3k mV~1#- &Pk  k  G}/}/}/b_ysp&9:X  G}/}/}/maq-p 9:X  G}/}/}/F4P7oP9:X  G}/G4Y!ptbASGameInfo::BeginRoundR[ s"%9:9:$J a[[ [9<J 9?,9?&X c$T!X 9=9:$9:c$g!*i!*.-N9:X %.O$.~ 9:J .d$] .A9?&[.hs" 9<J 9?,9?% e$%.he$ .hD,<7-{.U%Ssz i"%wi"*i"9=9:$9:X i"9?&i"i"\-S)J SY!hwY!*H*Y!ZY!a/!wY!*Y!-E Y!Y!H*i!L*[rAS_BeginRoundp9RJ *P& G}/pkA^3## ASGameInfo::StartNewRound ##J p G}/tC ;M^ k G}/}/}/ I3lVU-rx y w c *h > ly x mh c  G}/ I4um#Z\7u2u&.d$H.d$I'ul-u&.d$.d$I'um-.j#.h.A_I'$9=, G}/yoxN?\ % ASGameInfo::EndRound - Reason:U9:o9:$ wg!*wg!*ng!wq*nqzle$%$[.d$.j#.h.A9:o9:$wn*na/!V!.Ynb#rEndRound_Trophyn9<J 9?,9?&e$] o9:X -C*'rAS_attackers_winp9SonIwz*zzk&9:zzo&9:X rAS_defenders_winp9Sonmo9<J 9?,9?%y i!xq-C* w`$*`$O* rz* wg!*zg!bwz*z- 'Wwz*w.vz*-B*'V!_wV!*A*V!QwV!*V!-r".V!Bwr"* -B*.vzX!r"z3r" C zr" zr"~ V!} V!A*kASGameInfo::EndRound ObjectiveFocus == None !!!!!!!!!9:J g$*roundlimit-q!U _z($9=,& G}/N'}/}/ W4@Yi6?>&%&|&%%*E$wE$*N'.E$wN'*w*- rN'E$E$  ' G}/@}/}/x}/}/y}/G}/Axi) G}/ RBUj)G}/}/}/E}/}/MGF N/'id- % -{_Ss.YG-`#'(a'f' G}/}/}/ Oj F@(%j a/!N- % -{nSs9?CSs9?sS9?C j  G}/ X-k GEk yk a/!F G}/ W9] @-{ % s%SkSsCS%.Us@@Ss.U%W@wW*^".W)w^"*^"o .Y^"-`#E ^".Y^"-`#(WWc&-(9?9?,<9?%4%D,WDwW*-wW*Wa/!BW ~?WW % , F &.O$_"%w_"*_"[_"9?&_"_"11%k.h%"] .h[x$*practicetimelimitx$*roundtimelimit G}/}/}/N^kD:5^^a/!SG.^( G}/UF5cek)G}/}/}/QXp#rX*rX* z"wz"*{w.z"*.z"d _%,Xz"z"7XiX G}/XHdr9- \-- w7HHd s %HHd s &H G}/B7uFe# G}/Y\^J+\a/!W.\uG\e# G}/aZhk rZ* ]wZ*wZ*^ZZ G}/ bZD H:wZ*^Z Z G}/ cN F& .a)B, G}/ eH j@ 79:J %9:9:$k=p G}/ M5M@ t MgD%CMRoundTimeLimitDs"%CMPracticeTimeLimits"B%CMRoundLimitBg$B,c$9=%CMFirstAttackingTeam9:c$%CMResetTimeDelays%CMReinforcementsFreqs%D&,<g$,s"qw* G}/ O5z!d  /a0 AI )7??I 10z%wz*z9=9:$9:X z9?&zzI/a0 y"`$!P%10 G}/ G[9 G}/}/A}/B 5}/}/}/m`ma/!Pm $(ow.m*r.m*.m- (.m Ymm  G}/p9\S9:9:$SSU%U G}/rKsMy 0## ASGRI::SetupAssaultObjectivePriority/a0 KdK-K9=,1rj*#9:K9:jjK10rj* Y*/a0 KK-19:K9:j稨 Assault Priority:9R}DefensePriority:9RKInfo:KDestruction:K K}9:K9:j0rY*#9:K9:YYK10jY}rY*_)9=9:}& G}/{f  r* b?{. /O,.Gh*R,| 9Ph*{ N{|  G}/6f?s G}/r!}/}/y[I-\-Q  G}/K}/}/zxOCX#-\-\iK G}/C!:)-Q -\&-p,$ G}/v//============================================================================= // Weapon_Turret //============================================================================= class Weapon_Turret_Minigun extends Weapon config(user) HideDropDown CacheExempt; #exec OBJ LOAD FILE=..\Animations\AS_Vehicles_M.ukx simulated function ClientStartFire(int mode) { local PlayerController PC; if ( mode == 1 ) { PC = PlayerController(Instigator.Controller); if ( PC.DesiredFOV == PC.DefaultFOV ) PC.DesiredFOV = ASTurret(Instigator).MinPlayerFOV; else PC.DesiredFOV = PC.DefaultFOV; PlayerController(Instigator.Controller).bAltFire = 0; } else super.ClientStartFire( mode ); } simulated function PawnUnpossessed() { if ( (Instigator != None) && (PlayerController(Instigator.Controller) != None) ) PlayerController(Instigator.Controller).DesiredFOV = PlayerController(Instigator.Controller).DefaultFOV; } /* BestMode() choose between regular or alt-fire */ function byte BestMode() { return 0; } simulated function bool HasAmmo() { return true; } //============================================================================= // defaultproperties //============================================================================= {{2f 6c@qYԉhh uh uh u u uZgqCy u uh u *YbY~ J${.?L${.?OSd@$pBQR: I"Y: sjW]Turret weapon"$@@}/}/r//============================================================================= // WA_Turret_Minigun // Inpired from the original UT2003 minigun weapon... //============================================================================= class WA_Turret_Minigun extends xWeaponAttachment; #exec OBJ LOAD FILE=..\StaticMeshes\AS_Weapons_SM.usx #exec OBJ LOAD FILE=..\Textures\VMParticleTextures.utx var int CurrentCannonRoll; var int CannonRollSpeed, CurrentRollSpeed, RollSpeedAcc; var bool bFiring; // Shell case var class mShellCaseEmitterClass; var xEmitter mShellCaseEmitter; var() vector mShellEmitterOffset; // Muzzle flash var class mMuzFlashClass; var xEmitter mMuzFlash3rd; // Tracer FX var class mTracerClass; var() editinline Emitter mTracer; var() float mTracerInterval; var() float mTracerPullback; var() float mTracerMinDistance; var() float mTracerSpeed; var float mLastTracerTime; var float Spread; // Smoke var() class SmokeEmitterClass; var() xEmitter SmokeEmitter; var Sound FiringSound, WindingSound; var byte OldSpawnHitCount; var vector mOldHitLocation; var float LastFireTime; simulated function PostBeginPlay() { local Rotator R; super.PostBeginPlay(); R = GetBoneRotation( 'CannonBone' ); CurrentCannonRoll = R.Yaw; } simulated function Destroyed() { StopFiring(); if ( mMuzFlash3rd != None ) mMuzFlash3rd.Destroy(); if ( mShellCaseEmitter != None ) mShellCaseEmitter.Destroy(); if ( SmokeEmitter != None ) SmokeEmitter.Destroy(); super.Destroyed(); } simulated event ThirdPersonEffects() { local rotator R; local PlayerController PC; if ( (Level.NetMode == NM_DedicatedServer) || (Instigator == None) ) return; if ( FlashCount > 0 ) { LastFireTime = Level.TimeSeconds; if ( !bFiring || (GetStateName() != 'Firing') ) StartFiring(); // Muzzle Flash spawning if ( mMuzFlash3rd == None ) { mMuzFlash3rd = Spawn( mMuzFlashClass,,, ASVehicle(Instigator).GetFireStart(), Instigator.Rotation ); if ( mMuzFlash3rd != None ) { mMuzFlash3rd.bHardAttach = true; mMuzFlash3rd.SetBase( Instigator ); mMuzFlash3rd.mMeshNodes[0] = StaticMesh'AS_Weapons_SM.MuzzleFlash.ASMinigun_Muzzle'; mMuzFlash3rd.Skins[0] = Shader'VMParticleTextures.TankFiringP.tankMuzzleSHAD'; mMuzFlash3rd.mSizeRange[0] = 0.3; mMuzFlash3rd.mSizeRange[1] = 0.4; // Setting dynamic light effect on muzzle flash... mMuzFlash3rd.bDynamicLight = false; mMuzFlash3rd.LightType = LT_Pulse; mMuzFlash3rd.LightEffect = LE_NonIncidence; mMuzFlash3rd.LightPeriod = 3; mMuzFlash3rd.LightBrightness = 150; mMuzFlash3rd.LightHue = 30; mMuzFlash3rd.LightSaturation = 150; mMuzFlash3rd.LightRadius = 8.0; } } else { // Update location/rotation mMuzFlash3rd.SetBase( None ); mMuzFlash3rd.SetLocation( ASVehicle(Instigator).GetFireStart() ); mMuzFlash3rd.SetRotation( Instigator.Rotation ); mMuzFlash3rd.SetBase( Instigator ); } // Muzzle flash update if ( mMuzFlash3rd != None ) { mMuzFlash3rd.Trigger(Self, None); R.Roll = Rand(16384); mMuzFlash3rd.SetRelativeRotation( R ); // Dynamic Light mMuzFlash3rd.bDynamicLight = true; SetTimer(0.14, false); } // Shell Case spawning if ( Level.DetailMode != DM_Low ) { if ( mShellCaseEmitter == None ) { mShellCaseEmitter = Spawn( mShellCaseEmitterClass,,, GetFireStart( mShellEmitterOffset ), Instigator.Rotation ); if ( mShellCaseEmitter != None ) { mShellCaseEmitter.bHardAttach = true; mShellCaseEmitter.SetBase( Instigator ); mShellCaseEmitter.SetRelativeRotation( Rot(0,-16384,0) ); } } else { // Update location/rotation mShellCaseEmitter.SetBase( None ); mShellCaseEmitter.SetLocation( GetFireStart( mShellEmitterOffset ) ); mShellCaseEmitter.SetRotation( Instigator.Rotation ); mShellCaseEmitter.SetBase( Instigator ); mShellCaseEmitter.SetRelativeRotation( Rot(0,-16384,0) ); } // Shellcase update if ( mShellCaseEmitter != None ) mShellCaseEmitter.mStartParticles++; } // Impact effect if ( OldSpawnHitCount != SpawnHitCount ) { OldSpawnHitCount = SpawnHitCount; GetHitInfo(); PC = Level.GetLocalPlayerController(); if ( (Instigator.Controller == PC) || (VSize(PC.ViewTarget.Location - mHitLocation) < 5000) ) Spawn(class'HitEffect'.static.GetHitEffect(mHitActor, mHitLocation, mHitNormal),,, mHitLocation, Rotator(mHitNormal)); } // Tracer FX UpdateTracer(); } else StopFiring(); super.ThirdPersonEffects(); } /* Firing state: Updates cannon rotation */ state Firing { simulated function Tick(float deltaTime) { local rotator R; if ( Instigator == None ) return; if ( bFiring && (Level.TimeSeconds - LastFireTime > 0.5) ) StopFiring(); if ( bFiring ) { // Increase rotation rate... if ( CurrentRollSpeed < CannonRollSpeed ) CurrentRollSpeed += RollSpeedAcc * 4.f * deltaTime; // faster acceleration when shooting else if ( CurrentRollSpeed > CannonRollSpeed ) CurrentRollSpeed = CannonRollSpeed; } else { // decrease rotation rate... if ( CurrentRollSpeed > 0 ) CurrentRollSpeed -= RollSpeedAcc * deltaTime; // If rotation rate is null, exit state.. if ( CurrentRollSpeed < 0 ) { CurrentRollSpeed = 0; GotoState(''); } } // Rotating cannon CurrentCannonRoll = (CurrentCannonRoll + CurrentRollSpeed * deltatime) % 65536; R.Roll = CurrentCannonRoll; Instigator.SetBoneRotation('CannonBone', R, 0, 1.f); } } simulated function Timer() { // Shut down dynamic light if ( mMuzFlash3rd != None ) mMuzFlash3rd.bDynamicLight = false; } simulated Event StartFiring() { bFiring = true; if ( Instigator != None ) Instigator.AmbientSound = FiringSound; GotoState('Firing'); } simulated Event StopFiring() { if ( !bFiring ) return; bFiring = false; if ( Instigator != None ) { Instigator.AmbientSound = None; Instigator.PlaySound( WindingSound,, 4.f,, Instigator.SoundRadius, 0.75 ); if ( !Level.bDropDetail && Level.DetailMode != DM_Low ) { if ( SmokeEmitter == None ) { SmokeEmitter = Spawn( SmokeEmitterClass,,, ASVehicle(Instigator).GetFireStart(), Instigator.Rotation ); if ( SmokeEmitter != None ) { SmokeEmitter.bOnlyOwnerSee = false; SmokeEmitter.bHidden = false; SmokeEmitter.bHardAttach = true; SmokeEmitter.SetBase( Instigator ); } } else { // Update location/rotation SmokeEmitter.SetBase( None ); SmokeEmitter.SetLocation( ASVehicle(Instigator).GetFireStart() ); SmokeEmitter.SetRotation( Instigator.Rotation ); SmokeEmitter.SetBase( Instigator ); } if ( SmokeEmitter != None ) SmokeEmitter.Trigger( Self, Instigator ); } } } /* UpdateHit - used to update properties so hit effect can be spawn client side */ function UpdateHit(Actor HitActor, vector HitLocation, vector HitNormal) { SpawnHitCount++; mHitLocation = HitLocation; mHitActor = HitActor; mHitNormal = HitNormal; } simulated function UpdateTracer() { local float hitDist; //local rotator RelRot; local vector SpawnLoc, SpawnDir, SpawnVel; if ( Level.NetMode == NM_DedicatedServer ) return; // Spawn Tracer effect if ( mTracer == None ) { mTracer = Spawn( mTracerClass,,, ASVehicle(Instigator).GetFireStart(), Instigator.Rotation ); } if ( Level.bDropDetail || Level.DetailMode == DM_Low ) mTracerInterval = 2 * default.mTracerInterval; else mTracerInterval = default.mTracerInterval; if ( mTracer != None && Level.TimeSeconds >= mLastTracerTime + mTracerInterval) { SpawnLoc = ASVehicle(Instigator).GetFireStart(); mTracer.SetLocation( SpawnLoc ); hitDist = VSize( mHitLocation - SpawnLoc ) - mTracerPullback; // If the hit location is exactly the same as last time, we assume it isn't correct so we just use the gun rotation instead. if ( mHitLocation == mOldHitLocation ) SpawnDir = vector( Instigator.Rotation ) + VRand()*FRand()*class'FM_Turret_Minigun_Fire'.default.Spread ; else SpawnDir = Normal( mHitLocation - SpawnLoc ); mOldHitLocation = mHitLocation; if(hitDist > mTracerMinDistance) { SpawnVel = SpawnDir * mTracerSpeed; mTracer.Emitters[0].StartVelocityRange.X.Min = SpawnVel.X; mTracer.Emitters[0].StartVelocityRange.X.Max = SpawnVel.X; mTracer.Emitters[0].StartVelocityRange.Y.Min = SpawnVel.Y; mTracer.Emitters[0].StartVelocityRange.Y.Max = SpawnVel.Y; mTracer.Emitters[0].StartVelocityRange.Z.Min = SpawnVel.Z; mTracer.Emitters[0].StartVelocityRange.Z.Max = SpawnVel.Z; mTracer.Emitters[0].LifetimeRange.Min = hitDist / mTracerSpeed; mTracer.Emitters[0].LifetimeRange.Max = mTracer.Emitters[0].LifetimeRange.Min; mTracer.SpawnParticle(1); } mLastTracerTime = Level.TimeSeconds; } } simulated function vector GetFireStart( vector RelOffset ) { local vector X, Y, Z; GetViewAxes(X, Y, Z); return Instigator.Location + X*RelOffset.X + Y*RelOffset.Y + Z*RelOffset.Z; } simulated function GetViewAxes( out vector xaxis, out vector yaxis, out vector zaxis ) { GetAxes( Instigator.Rotation, xaxis, yaxis, zaxis ); } //============================================================================= // defaultproperties //============================================================================= }/v$//============================================================================= // Trigger_ASUseAndRespawn //============================================================================= // Triggered using the "Use" key and respawns Player. // Optionnal PSM_Override_Tag allows to force player to respawn is a specific // Spawning Area (overriding its bEnabled status) //============================================================================= class Trigger_ASUseAndRespawn extends SVehicleTrigger placeable; var() enum AT_AssaultTeam { AT_All, AT_Attackers, AT_Defenders, } AssaultTeam; var() name PSM_Override_Tag; // To force Player to use a specific PlayerSpawnManager var float LastFailTime; //used by AI // Check if a Team is valid function bool ApprovePlayerTeam(byte Team) { if ( AssaultTeam == AT_All ) return true; if ( Level.Game.IsA('ASGameInfo') ) { if ( AssaultTeam == AT_Attackers ) { if ( ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } else if ( !ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } return false; } function Touch( Actor Other ) { local xPawn User; local Controller C; User = xPawn(Other); if ( !bEnabled || (User == None) || (User.Controller == None) ) return; C = User.Controller; if ( ((C.RouteGoal == self) || (C.Movetarget == self)) && (AIController(C) != None) ) { if ( (C.PlayerReplicationInfo != None) && !C.PlayerReplicationInfo.bOnlySpectator && ApprovePlayerTeam(C.PlayerReplicationInfo.Team.TeamIndex) ) UsedBy(User); return; } // Send a string message to the toucher. User.ReceiveLocalizedMessage(class'Vehicles.BulldogMessage', 0); } function UsedBy( Pawn user ) { if ( !bEnabled || (User == None) || (User.Controller == None) ) return; if ( !Level.Game.IsA('ASGameInfo') ) return; User.PlayTeleportEffect(true, true); // Force player to use a specific Spawn area if ( PSM_Override_Tag != '' && PSM_Override_Tag != 'None' ) User.Controller.Event = PSM_Override_Tag; ASGameInfo(Level.Game).RespawnPlayer( User.Controller, false ); } //============================================================================= // defaultproperties //============================================================================= WVL@ X8 h3}Zshh,e3}n%ḣ,e,e,e,ezVGB,ezVGBJ̌3}Zs3}n%3}n% 1V}/}/r~//============================================================================= // Trigger_ASUseAndRespawn //============================================================================= // Allows Player to Possess a Pawn with the "Use" Key. // Pawn is found using its Tag name. // // Several Pawns are supported. // - EventFull is called when no more Pawns can be possessed // - EventNonFull is called when a Pawn to possess is freed //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class Trigger_ASUseAndPossess extends SVehicleTrigger placeable; var() enum AT_AssaultTeam { AT_All, AT_Attackers, AT_Defenders, } AssaultTeam; var() name PawnTag; // Tag of Pawn(s) to possess var() name EventFull; // called when there's no more pawns to possess var() name EventNonFull; // '' when there is a free spot available var bool bFullCapacity; var Array FactoryList; event PostBeginPlay() { local ASVehicleFactory ASVF; ForEach DynamicActors(class'ASVehicleFactory', ASVF) if ( ASVF.VehicleTag == PawnTag ) FactoryList[FactoryList.Length] = ASVF; super.PostBeginPlay(); if ( !bEnabled ) NotifyAvailability( false ); } event Trigger( Actor Other, Pawn EventInstigator ) { bEnabled = !bEnabled; if ( bEnabled ) { // Check capacity, we might try to enable something that doesn't have any Pawns to possess... UpdateCapacity(); if ( !bFullCapacity ) NotifyAvailability( true ); } else { SetCollision( false ); if ( !bFullCapacity ) NotifyAvailability( false ); } } event VehicleSpawned() { if ( bEnabled && bFullCapacity ) // free spot, only check if full UpdateCapacity(); } event VehicleDestroyed() { if ( bEnabled && !bFullCapacity ) // one less spot... check only if not full UpdateCapacity(); } event VehicleUnPossessed() { if ( bEnabled && bFullCapacity ) // free spot, only check if full UpdateCapacity(); } event VehiclePossessed() { if ( bEnabled && !bFullCapacity ) // free spot, only check if full UpdateCapacity(); } // Check if a Team is valid function bool ApprovePlayerTeam(byte Team) { if ( AssaultTeam == AT_All ) return true; if ( Level.Game.IsA('ASGameInfo') ) { if ( AssaultTeam == AT_Attackers ) { if ( ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } else if ( !ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } return false; } function Touch( Actor Other ) { local xPawn User; local Controller C; User = xPawn(Other); if ( !bEnabled || bFullCapacity || (User == None) || (User.Controller == None) ) return; C = User.Controller; if ( (AIController(C) != None) && ((C.RouteGoal == self) || (C.Movetarget == self) || (C.RouteGoal == myMarker) || (C.Movetarget == myMarker) ) ) { if ( (C.PlayerReplicationInfo != None) && !C.PlayerReplicationInfo.bOnlySpectator && ApprovePlayerTeam(C.PlayerReplicationInfo.Team.TeamIndex) ) UsedBy(User); return; } // Send a string message to the toucher. User.ReceiveLocalizedMessage(class'Vehicles.BulldogMessage', 0); } function UsedBy( Pawn user ) { local Vehicle V; local int i; if ( !bEnabled || bFullCapacity || (User == None) || (User.Controller == None) || !ApprovePlayerTeam( User.GetTeamNum() ) ) return; for (i=0; i 0) && !V.bDeleteMe ) { if ( V.Controller == None || !V.Controller.IsA('PlayerController') ) { V.TryToDrive( User ); break; } } } UpdateCapacity(); } function UpdateCapacity() { local Vehicle V; local bool bOldCapacity; local int i; bOldCapacity = bFullCapacity; bFullCapacity = true; // Check if there is a Pawn left to possess... for (i=0; i 0) && !V.bDeleteMe ) { if ( V.Controller == None || !V.Controller.IsA('PlayerController') ) bFullCapacity = false; } } if ( bEnabled && bOldCapacity && !bFullCapacity ) NotifyAvailability( true ); if ( bEnabled && !bOldCapacity && bFullCapacity ) NotifyAvailability( false ); } /* Reset() reset actor to initial state - used when restarting level without reloading. */ function Reset() { local bool bOldEnabled; bOldEnabled = bEnabled; super.Reset(); if ( bOldEnabled != bEnabled || (bEnabled && bFullCapacity) ) NotifyAvailability( bEnabled ); bFullCapacity = false; } /* Called when the controller changes its status from "FULL or DISABLED" to "AVAILABLE" */ event NotifyAvailability( bool bAvailableSpace ) { SetCollision( bAvailableSpace ); if ( bAvailableSpace ) TriggerEvent( EventNonFull, Self, None); else TriggerEvent( EventFull, Self, None); } event PrevVehicle( ASVehicleFactory ASVF, Vehicle V ) { local int i, CurrentIndex; local ASVehicleFactory newASVF; local PlayerController PC; local Vector ExitPos; PC = PlayerController(V.Controller); if ( !bEnabled || bFullCapacity || (V==None) || (PC==None) ) return; // Lookup current ASVF index for (i=0; i 0 i = CurrentIndex - 1; while ( i >= 0 ) { if ( FactoryList[i].Child != None && ( FactoryList[i].Child.Controller == None || !FactoryList[i].Child.Controller.IsA('PlayerController') ) ) { newASVF = FactoryList[i]; break; } i--; } // Scan fron Length -> CurrentIndex if ( newASVF == None ) { i = FactoryList.Length - 1; while ( i > CurrentIndex ) { if ( FactoryList[i].Child != None && ( FactoryList[i].Child.Controller == None || !FactoryList[i].Child.Controller.IsA('PlayerController') ) ) { newASVF = FactoryList[i]; break; } i--; } } // Exit current vehicle, and possess next one if ( newASVF != None ) { if ( !V.bRelativeExitPos ) ExitPos = V.ExitPositions[0]; V.KDriverLeave( true ); newASVF.Child.TryToDrive( PC.Pawn ); if ( !newASVF.Child.bRelativeExitPos ) newASVF.Child.ExitPositions[0] = ExitPos; } } event NextVehicle( ASVehicleFactory ASVF, Vehicle V ) { local int i, CurrentIndex; local ASVehicleFactory newASVF; local PlayerController PC; local Vector ExitPos; PC = PlayerController(V.Controller); if ( !bEnabled || bFullCapacity || (V==None) || (PC==None) ) return; // Lookup current ASVF index for (i=0; i Length - 1 i = CurrentIndex + 1; while ( i < FactoryList.Length ) { if ( FactoryList[i].Child != None && ( FactoryList[i].Child.Controller == None || !FactoryList[i].Child.Controller.IsA('PlayerController') ) ) { newASVF = FactoryList[i]; break; } i++; } // Scan from 0 -> CurrentIndex - 1 if ( newASVF == None ) { i = 0; while ( i < CurrentIndex ) { if ( FactoryList[i].Child != None && ( FactoryList[i].Child.Controller == None || !FactoryList[i].Child.Controller.IsA('PlayerController') ) ) { newASVF = FactoryList[i]; break; } i++; } } // Exit current vehicle, and possess next one if ( newASVF != None ) { if ( !V.bRelativeExitPos ) ExitPos = V.ExitPositions[0]; V.KDriverLeave( true ); newASVF.Child.TryToDrive( PC.Pawn ); if ( !newASVF.Child.bRelativeExitPos ) newASVF.Child.ExitPositions[0] = ExitPos; } } //============================================================================= // defaultproperties //============================================================================= }/zD//============================================================================= // Trigger_ASTurretControlPanel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= // Specific "Turret Controller" version of the trigger. // Features default mesh and special effects. //============================================================================= class Trigger_ASTurretControlPanel extends Trigger_ASUseAndPossess placeable; #exec obj load file=Dom-Goose.utx var(MonitorEffects) Material StatusTex[4]; var byte Status, OldStatus; var FX_TurretControlPanel_Lights LightFX; var FX_DamageSmoke DamageEffect; replication { unreliable if ( bNetDirty && (Role==ROLE_Authority) ) Status; } simulated event PostBeginPlay() { super.PostBeginPlay(); // Setup for skin work Skins.Length = 2; Skins[0] = None; Skins[1] = StatusTex[0]; UpdateCapacity(); } simulated event Destroyed() { if ( LightFX != None ) LightFX.Destroy(); if ( DamageEffect !=None) DamageEffect.Destroy(); super.Destroyed(); } event VehicleSpawned() { UpdateCapacity(); } event VehicleDestroyed() { UpdateCapacity(); } event VehiclePossessed() { UpdateCapacity(); } event VehicleUnPossessed() { UpdateCapacity(); } function UpdateCapacity() { local Vehicle V; local bool bOldCapacity, bdead; local int i; bOldCapacity = bFullCapacity; bFullCapacity = true; bDead = true; // Check if there is a Pawn left to possess... for (i=0; i0 && !V.bDeleteMe ) { bDead = false; if ( V.Controller == None || !V.Controller.IsA('PlayerController') ) bFullCapacity = false; } } } if ( bEnabled ) { if ( !bDead ) { if ( bOldCapacity != bFullCapacity ) NotifyAvailability( !bFullCapacity ); } else ChangeStatus( 1 ); // Dead } else ChangeStatus( 0 ); // Disabled; } /* Called when the controller changes its status from "FULL or DISABLED" to "AVAILABLE" */ event NotifyAvailability( bool bAvailableSpace ) { if ( bAvailableSpace ) TriggerEvent( EventNonFull, Self, None); else TriggerEvent( EventFull, Self, None); if ( bAvailableSpace ) ChangeStatus( 2 ); // Has Space else ChangeStatus( 3 ); // Full } function ChangeStatus(byte NewStatus) { if ( Status == NewStatus ) return; Status = NewStatus; if ( Level.NetMode != NM_DedicatedServer ) // Fake replication on a listen server PostNetReceive(); } simulated function PostNetReceive() { local Rotator R; local vector v; if ( Level.NetMode != NM_DedicatedServer && Status != OldStatus ) { if ( Status <= 1 ) // Disabled or Dead { if ( LightFX != None ) { LightFX.Destroy(); LightFX = None; } if ( Status == 1 ) { V = Location + (vect(40,0,0) << Rotation); if ( DamageEffect == None ) DamageEffect = Spawn(class'FX_DamageSmoke', Self,, V, Rotation); } } else if ( LightFX == None ) { R = Rotation; R.Yaw = R.Yaw + 32768; LightFX = Spawn(class'FX_TurretControlPanel_Lights',,, Location, R); if ( DamageEffect != None ) DamageEffect.Destroy(); } if ( Status == 2 ) // Space Available { if ( LightFX != None ) LightFX.SetColorGreen(); } if ( Status == 3 ) // Full { if ( LightFX != None ) LightFX.SetColorRed(); } OldStatus = Status; Skins[1] = StatusTex[Status]; } } function Reset() { super.Reset(); if ( LightFX != None ) LightFX.Destroy(); if ( DamageEffect != None ) DamageEffect.Destroy(); Status = 0; UpdateCapacity(); } //============================================================================= // defaultproperties //============================================================================= k\J0pF-9:9:$GB ]FjkY}!;}#D#3}}!;}#D#}!;}!;3}'5M7<}L}L}L}L,e}!;}#D# V VVV"NSj StSpnn$?b:@ C# rS5$BFAUB}/}/C//============================================================================= // Trigger_ASTeamUseTrigger: if a player stands within proximity of this trigger, and hits Use, // it will send Trigger/UnTrigger to actors whose names match 'EventName'. //============================================================================= class Trigger_ASTeamUseTrigger extends Triggers; var() enum AT_AssaultTeam { AT_All, AT_Attackers, AT_Defenders, } AssaultTeam; var() localized string Message; function bool SelfTriggered() { return true; } function UsedBy( Pawn user ) { TriggerEvent(Event, self, user); } function Touch( Actor Other ) { if ( Pawn(Other) != None && ApprovePlayerTeam( Pawn(Other).GetTeamNum() ) ) { // Send a string message to the toucher. if( Message != "" ) Pawn(Other).ClientMessage( Message ); if ( AIController(Pawn(Other).Controller) != None ) UsedBy(Pawn(Other)); } } // Check if a Team is valid function bool ApprovePlayerTeam(byte Team) { if ( AssaultTeam == AT_All ) return true; if ( Level.Game.IsA('ASGameInfo') ) { if ( AssaultTeam == AT_Attackers ) { if ( ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } else if ( !ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } return false; } ^mQ 2 _uE؂u3}Zs3}n%3}n%hhh }/}/p"//============================================================================= // Trigger_ASTeam: triggers for all pawns with matching team //============================================================================= class Trigger_ASTeam extends Trigger; var() enum EPSM_AssaultTeam { EPSM_Attackers, EPSM_Defenders, } AssaultTeam; var() bool bTimed; function PostBeginPlay() { Super.PostBeginPlay(); if ( bTimed ) SetTimer(2.5, true); } function Timer() { local Controller P; for ( P=Level.ControllerList; P!=None; P=P.NextController ) if ( (P.Pawn != None) && (abs(Location.Z - P.Pawn.Location.Z) < CollisionHeight + P.CollisionHeight) && (VSize(Location - P.Pawn.Location) < CollisionRadius) ) Touch(P.Pawn); SetTimer(2.5, true); } function bool IsRelevant( actor Other ) { local Actor Inst; Inst = FindInstigator( Other ); if ( Inst != None ) { if( !bInitiallyActive || !Level.Game.bTeamGame || (Inst.Instigator == None) || !Level.Game.IsOnTeam(Inst.Instigator.Controller, GetAssaultTeamIndex()) ) return false; } return Super.IsRelevant(Other); } function Touch( actor Other ) { // ugly speed hack ship it (tm) // if trigger has been disabled (bTriggerOnceOnly), skip touch event // ugly hack to fix robot factory touch event (rarely) called twice from Volume.AssociatedActor, // causing ScriptedTrigger to skip an Action, and therefore not enabling a PlayerSpawn manager... if ( bTriggerOnceOnly && bCollideActors != bSavedInitialCollision && !bCollideActors ) return; super.Touch( Other ); } function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( (InstigatedBy != None) && Level.Game.bTeamGame && Level.Game.IsOnTeam(InstigatedBy.Controller, GetAssaultTeamIndex()) ) Super.TakeDamage(Damage, instigatedBy, HitLocation, Momentum, DamageType); } function int GetAssaultTeamIndex() { if ( Level.Game.IsA('ASGameInfo') ) { if ( AssaultTeam == EPSM_Attackers ) return ASGameInfo(Level.Game).GetAttackingTeam(); return ( 1 - ASGameInfo(Level.Game).GetAttackingTeam() ); } return 0; } `Ra@2b[֌3}Zs3}n%3}n%3}Zs3}Zsh3}Zsʁ)3}Zsʁ)h3},e,e,eh,e,eh,e,e }/}/c//============================================================================= // Trigger_ASRoundEnd // //============================================================================= class Trigger_ASRoundEnd extends Triggers; event Trigger( Actor Other, Pawn EventInstigator ) { if ( Role < Role_Authority ) return; if ( !Level.Game.IsA('ASGameInfo') ) return; ASGameInfo(Level.Game).EndRound(ERER_AttackersWin, EventInstigator, "Attackers Win!"); } cu\@dFp؂u3}Zs3}n% VS}/}/I//============================================================================= // Trigger_ASMessageTrigger //============================================================================= // Broadcasts a message to all players //============================================================================= class Trigger_ASMessageTrigger extends Triggers; var() enum EPSM_AssaultTeam { EMT_Attackers, EMT_Defenders, EMT_All, } AssaultTeam; var() Sound AnnouncerSound; // Announcer Sound played var() localized string Message; // Message displayed var() byte AnnouncementLevel; var bool bSoundsPrecached; var() AnnouncerQueueManager.EAPriority Priority; event Trigger( Actor Other, Pawn EventInstigator ) { local byte RealTeam; RealTeam = GetTeamNum(); if ( AnnouncerSound != None && ASGameInfo(Level.Game).IsPlaying() ) ASGameInfo(Level.Game).QueueAnnouncerSound( AnnouncerSound.Name, AnnouncementLevel, RealTeam, Priority, 210 ); } function byte GetTeamNum() { local byte DefendingTeam; if ( AssaultTeam == EMT_All ) return 255; DefendingTeam = Level.Game.GetDefenderNum(); if ( AssaultTeam == EMT_Defenders ) return DefendingTeam; return 1 - DefendingTeam; } simulated function PrecacheAnnouncer(AnnouncerVoice V, bool bRewardSounds) { if ( !bRewardSounds &&(AnnouncerSound != None) && !bSoundsPrecached ) { bSoundsPrecached = true; V.PrecacheSound(AnnouncerSound.Name); } } //============================================================================= // defaultproperties //============================================================================= }/q//============================================================================= // Trigger_ASForceTeamRespawn //============================================================================= // Triggered actor that will respawn a whole Assault Team. //============================================================================= class Trigger_ASForceTeamRespawn extends Triggers; event Trigger( Actor Other, Pawn EventInstigator ) { local Controller C; local Pawn OldPawn; if ( Role < Role_Authority || !Level.Game.IsA('ASGameInfo') ) return; for ( C = Level.ControllerList; C != None; C = C.NextController ) if ( (C.PlayerReplicationInfo != None) && !C.PlayerReplicationInfo.bOnlySpectator ) { if ( Vehicle(C.Pawn) != None ) Vehicle(C.Pawn).KDriverLeave( true ); if ( C.Pawn != None && C.Pawn.Weapon == None ) { OldPawn = C.Pawn; C.UnPossess(); OldPawn.Destroy(); C.Pawn = None; Level.Game.RestartPlayer( C ); } ASGameInfo(Level.Game).RespawnPlayer( C, false ); } } hLA@jA"؂u3}Zs3},e,e,ezVGB,e,e}L,e,eh,e,eh,e3}Zs3}n%,e VS}/}/T$//============================================================================= // Trigger_ASForcePlayerRespawn //============================================================================= // Triggered Actor that will respawn the Instigator. //============================================================================= class Trigger_ASForcePlayerRespawn extends Triggers; var() enum EPSM_AssaultTeam { EPSM_Attackers, EPSM_Defenders, } AssaultTeam; var() enum EFTR_Constraint { EFTRC_All, EFTRC_PawnClass, } Constraint; var() class ConstraintPawnClass; // Trigger will only be relevant to a specific Pawn class ? var() name PSM_OverrideTag; // force player to use a specific PlayerStartManager var() bool bTryToRepossess; // Try to repossess old Pawn instead of Spawning a new one (when driving a vehicle...) event Trigger( Actor Other, Pawn EventInstigator ) { local Controller C; if ( Role < Role_Authority || !Level.Game.IsA('ASGameInfo') ) return; if ( EventInstigator == None ) return; C = EventInstigator.Controller; if ( (C!=None) && (C.PlayerReplicationInfo != None) && !C.PlayerReplicationInfo.bOnlySpectator && ApprovePlayerTeam(C.PlayerReplicationInfo.Team.TeamIndex) ) { // Pawn class constraint if ( Constraint == EFTRC_PawnClass && ConstraintPawnClass != None && C.PawnClass != ConstraintPawnClass ) return; // Force player to use a specific PlayerSpawnManager if ( PSM_OverrideTag != '' && PSM_OverrideTag != 'None' ) C.Event = PSM_OverrideTag; // Try to repossess OldPawn if possible if ( bTryToRepossess && EventInstigator.IsA('Vehicle') ) Vehicle(EventInstigator).KDriverLeave( true ); ASGameInfo(Level.Game).RespawnPlayer( C, false ); } } // Check if a Team is valid function bool ApprovePlayerTeam(byte Team) { if ( Level.Game.IsA('ASGameInfo') ) { if ( AssaultTeam == EPSM_Attackers ) { if ( ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } else if ( !ASGameInfo(Level.Game).IsAttackingTeam(Team) ) return true; } return false; } //============================================================================= // defaultproperties //============================================================================= vQD@wO~+؂u3}Zs3}n%3}n%3}Zsh,e,ezVGB,ezVGBJ,e,eh}L3}n% l VS}/}/{//============================================================================= // ScoreBoard_Assault //============================================================================= class ScoreBoard_Assault extends ScoreBoardTeamDeathMatch; var localized string RemainingRoundTime, CurrentRound, RoundSeparator; var localized string Defender, Attacker; var localized string WaitForReinforcements, WaitingToSpawnReinforcements, AutoRespawn; var localized string YouWonRound, YouLostRound, PracticeRoundOver; function String GetTitleString() { local string InfoString; local byte OwnerTeam; local ASGameReplicationInfo ASGRI; ASGRI = ASGameReplicationInfo(GRI); InfoString = super.GetTitleString(); if ( ASGRI != None && Controller(Owner) != None && Controller(Owner).PlayerReplicationInfo != None && Controller(Owner).PlayerReplicationInfo.Team != None ) { OwnerTeam = Controller(Owner).PlayerReplicationInfo.Team.TeamIndex; if ( OwnerTeam == byte(ASGRI.bTeamZeroIsAttacking) ) InfoString = InfoString@Defender; else InfoString = InfoString@Attacker; } return InfoString; } function String GetRestartString() { local string RestartString; local ASGameReplicationInfo ASGRI; ASGRI = ASGameReplicationInfo(GRI); if ( ASGRI.RoundWinner != ERW_None ) { return ASGRI.GetRoundWinnerString(); /* if ( ASGRI.IsPracticeRound() ) return PracticeRoundOver; if ( Controller(Owner).GetTeamNum() == ASGRI.RoundWinner ) return YouWonRound; return YouLostRound; */ } if ( Controller(Owner).PlayerReplicationInfo != None && ASPlayerReplicationInfo(Controller(Owner).PlayerReplicationInfo).bAutoRespawn && !Controller(Owner).IsInState('PlayerWaiting') ) { RestartString = AutoRespawn @ ASGRI.ReinforcementCountDown; return RestartString; } if ( ASGRI.ReinforcementCountDown > 0 && !Controller(Owner).IsInState('PlayerWaiting') ) { RestartString = WaitForReinforcements @ ASGRI.ReinforcementCountDown; } else RestartString = super.GetRestartString(); return RestartString; } function String GetDefaultScoreInfoString() { local string AssaultInfoString; local int RemainingRoundTimeVal; local ASGameReplicationInfo ASGRI; ASGRI = ASGameReplicationInfo(GRI); if ( ASGRI == None ) return super.GetDefaultScoreInfoString(); // remaining round time if ( ASGRI.RoundTimeLimit > 0 && ASGRI.RoundWinner == ERW_None ) { RemainingRoundTimeVal = Max(0, ASGRI.RoundTimeLimit-ASGRI.RoundStartTime+ASGRI.RemainingTime); if ( ASGRI.RoundWinner != ERW_None ) RemainingRoundTimeVal = ASGRI.RoundOverTime; AssaultInfoString = RemainingRoundTime@FormatTime( RemainingRoundTimeVal ); } // current round if ( AssaultInfoString != "" ) AssaultInfoString = AssaultInfoString@spacer; // add spacer AssaultInfoString = AssaultInfoString@CurrentRound@ASGRI.CurrentRound$RoundSeparator$ASGRI.MaxRounds; //if ( AssaultInfoString == "" ) // return super.GetDefaultScoreInfoString(); return AssaultInfoString; } function DrawTeam(int TeamNum, int PlayerCount, int OwnerOffset, Canvas Canvas, int FontReduction, int BoxSpaceY, int PlayerBoxSizeY, int HeaderOffsetY) { local int i, OwnerPos, NetXPos, NameXPos, BoxTextOffsetY, ScoreXPos, ScoreYPos, BoxXPos, BoxWidth, LineCount,NameY; local float XL,YL,IconScale,ScoreBackScale,ScoreYL,MaxNamePos,LongestNameLength, oXL, oYL, tx, ty; local string PlayerName[MAXPLAYERS], OrdersText, LongestName, temp; local font MainFont, ReducedFont; local bool bHaveHalfFont, bNameFontReduction; local int SymbolUSize, SymbolVSize, OtherTeam, LastLine; local Font BackupFont; local float TrophiesXOffset; BoxWidth = 0.47 * Canvas.ClipX; BoxXPos = 0.5 * (0.5 * Canvas.ClipX - BoxWidth); BoxWidth = 0.5 * Canvas.ClipX - 2*BoxXPos; BoxXPos = BoxXPos + TeamNum * 0.5 * Canvas.ClipX; NameXPos = BoxXPos + 0.05 * BoxWidth; ScoreXPos = BoxXPos + 0.6 * BoxWidth; NetXPos = BoxXPos + 0.72 * BoxWidth; bHaveHalfFont = HaveHalfFont(Canvas, FontReduction); // draw background box Canvas.Style = ERenderStyle.STY_Alpha; Canvas.DrawColor = HUDClass.default.WhiteColor; Canvas.SetPos(BoxXPos, HeaderOffsetY); Canvas.DrawTileStretched( TeamBoxMaterial[TeamNum], BoxWidth, PlayerCount * (PlayerBoxSizeY + BoxSpaceY)); // draw team header IconScale = Canvas.ClipX/4096; ScoreBackScale = Canvas.ClipX/1024; if ( GRI.TeamSymbols[TeamNum] != None ) { SymbolUSize = GRI.TeamSymbols[TeamNum].USize; SymbolVSize = GRI.TeamSymbols[TeamNum].VSize; } else { SymbolUSize = 256; SymbolVSize = 256; } ScoreYPos = HeaderOffsetY - SymbolVSize * IconScale - BoxSpaceY; Canvas.DrawColor = 0.75 * HUDClass.default.WhiteColor; Canvas.SetPos(BoxXPos, ScoreYPos - BoxSpaceY); Canvas.DrawTileStretched( Material'InterfaceContent.ScoreBoxA', BoxWidth, HeaderOffsetY + BoxSpaceY - ScoreYPos); Canvas.Style = ERenderStyle.STY_Normal; Canvas.DrawColor = TeamColors[TeamNum]; Canvas.SetPos((0.25 + 0.5*TeamNum) * Canvas.ClipX - (SymbolUSize + 32) * IconScale, ScoreYPos); if ( GRI.TeamSymbols[TeamNum] != None ) Canvas.DrawIcon(GRI.TeamSymbols[TeamNum],IconScale); MainFont = Canvas.Font; Canvas.Font = HUDClass.static.LargerFontThan(MainFont); Canvas.StrLen("TEST",XL,ScoreYL); if ( ScoreYPos == 0 ) ScoreYPos = HeaderOffsetY - ScoreYL; else ScoreYPos = ScoreYPos + 0.5 * SymbolVSize * IconScale - 0.5 * ScoreYL; Canvas.SetPos((0.25 + 0.5*TeamNum) * Canvas.ClipX + 32*IconScale,ScoreYPos); Canvas.DrawText(int(GRI.Teams[TeamNum].Score)); Canvas.Font = MainFont; Canvas.DrawColor = HUDClass.default.WhiteColor; IconScale = Canvas.ClipX/1024; if ( PlayerCount <= 0 ) return; // draw lines between sections if ( TeamNum == 0 ) Canvas.DrawColor = HUDClass.default.RedColor; else Canvas.DrawColor = HUDClass.default.BlueColor; if ( OwnerOffset >= PlayerCount ) LastLine = PlayerCount+1; else LastLine = PlayerCount; for ( i=1; i FMax(LongestNameLength,MaxNamePos) ) { LongestName = PlayerName[i]; LongestNameLength = XL; } } if ( OwnerOffset >= PlayerCount ) { playername[OwnerOffset] = GRI.PRIArray[OwnerOffset].PlayerName; Canvas.StrLen(playername[OwnerOffset], XL, YL); if ( XL > FMax(LongestNameLength,MaxNamePos) ) { LongestName = PlayerName[i]; LongestNameLength = XL; } } if ( LongestNameLength > 0 ) { bNameFontReduction = true; Canvas.Font = GetSmallerFontFor(Canvas,FontReduction+1); Canvas.StrLen(LongestName, XL, YL); if ( XL > MaxNamePos ) { Canvas.Font = GetSmallerFontFor(Canvas,FontReduction+2); Canvas.StrLen(LongestName, XL, YL); if ( XL > MaxNamePos ) Canvas.Font = GetSmallerFontFor(Canvas,FontReduction+3); } ReducedFont = Canvas.Font; } for ( i=0; i MaxNamePos ) playername[i] = left(playername[i], MaxNamePos/XL * len(PlayerName[i])); } if ( OwnerOffset >= PlayerCount ) { playername[OwnerOffset] = PRIArray[OwnerOffset].PlayerName; Canvas.StrLen(playername[OwnerOffset], XL, YL); if ( XL > MaxNamePos ) playername[OwnerOffset] = left(playername[OwnerOffset], MaxNamePos/XL * len(PlayerName[OwnerOffset])); } if ( Canvas.ClipX < 512 ) NameY = 0.5 * YL; else if ( !bHaveHalfFont ) NameY = 0.125 * YL; Canvas.Style = ERenderStyle.STY_Normal; Canvas.DrawColor = HUDClass.default.WhiteColor; Canvas.SetPos(0.5 * Canvas.ClipX, HeaderOffsetY + 4); BoxTextOffsetY = HeaderOffsetY + 0.5 * PlayerBoxSizeY - 0.5 * YL; Canvas.DrawColor = HUDClass.default.WhiteColor; if ( OwnerOffset == -1 ) { for ( i=0; i 0 ) { TrophiesXOffset = ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset; ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset += 32; Canvas.SetPos( ScoreXPos - (TrophiesXOffset+8)*IconScale, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + ty*0.5 - 16*IconScale); Canvas.DrawTile( Texture'HudContent.Generic.HUD', 32*IconScale, 32*IconScale, 227, 406, 53, 42); // If more than one, display number... if ( ASPlayerReplicationInfo(PRIArray[i]).DestroyedVehicles > 1 ) { temp = String(ASPlayerReplicationInfo(PRIArray[i]).DestroyedVehicles); Canvas.StrLen( temp, XL, YL ); Canvas.SetPos( ScoreXPos - (TrophiesXOffset-16+8)*IconScale - XL*0.5, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + ty*0.5 - YL*0.5); Canvas.DrawText(temp, true); } } } // Objective Disabled Trophy for ( i=0; i 0 ) { TrophiesXOffset = ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset; ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset += 32; Canvas.SetPos( ScoreXPos - (TrophiesXOffset+8)*IconScale, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + ty*0.5 - 16*IconScale); Canvas.DrawTile( Texture'AS_FX_TX.Icons.ScoreBoard_Objective_Final', 32*IconScale, 32*IconScale, 0, 0, 128, 128); // If more than one, display number... if ( ASPlayerReplicationInfo(PRIArray[i]).DisabledObjectivesCount > 1 ) { temp = String(ASPlayerReplicationInfo(PRIArray[i]).DisabledObjectivesCount); Canvas.StrLen( temp, XL, YL ); Canvas.SetPos( ScoreXPos - (TrophiesXOffset-16+8)*IconScale - XL*0.5, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + ty*0.5 - YL*0.5); Canvas.DrawText(temp, true); } } } // Round Won Trophies for ( i=0; i 0 ) { TrophiesXOffset = ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset; ASPlayerReplicationInfo(PRIArray[i]).TrophiesXOffset += 32; Canvas.SetPos( ScoreXPos - (TrophiesXOffset+8)*IconScale, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY +ty*0.5 - 16*IconScale); Canvas.DrawTile( Texture'AS_FX_TX.Icons.ScoreBoard_Objective_Single', 32*IconScale, 32*IconScale, 0, 0, 128, 128); // If more than one, display number... if ( ASPlayerReplicationInfo(PRIArray[i]).DisabledFinalObjective > 1 ) { temp = String(ASPlayerReplicationInfo(PRIArray[i]).DisabledFinalObjective); Canvas.StrLen( temp, XL, YL ); Canvas.SetPos( ScoreXPos - (TrophiesXOffset-16+8)*IconScale - XL*0.5, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + ty*0.5 - YL*0.5); Canvas.DrawText(temp, true); } } } Canvas.Font = BackupFont; // draw owner line if ( OwnerOffset >= 0 ) { if ( OwnerOffset >= PlayerCount ) { OwnerPos = (PlayerBoxSizeY + BoxSpaceY)*PlayerCount + BoxTextOffsetY; // draw extra box Canvas.Style = ERenderStyle.STY_Alpha; Canvas.SetPos(BoxXPos, HeaderOffsetY + (PlayerBoxSizeY + BoxSpaceY)*PlayerCount); Canvas.DrawTileStretched( TeamBoxMaterial[TeamNum], BoxWidth, PlayerBoxSizeY); Canvas.Style = ERenderStyle.STY_Normal; if ( PRIArray[OwnerOffset].HasFlag != None ) { Canvas.DrawColor = HUDClass.default.WhiteColor; Canvas.SetPos(NameXPos - 48*IconScale, OwnerPos - 16*IconScale); Canvas.DrawTile( FlagIcon, 64*IconScale, 32*IconScale, 0, 0, 256, 128); } } else OwnerPos = (PlayerBoxSizeY + BoxSpaceY)*OwnerOffset + BoxTextOffsetY; Canvas.DrawColor = HUDClass.default.GoldColor; Canvas.SetPos(NameXPos, OwnerPos-0.5*YL+NameY); if ( bNameFontReduction ) Canvas.Font = ReducedFont; Canvas.DrawText(playername[OwnerOffset],true); if ( bNameFontReduction ) Canvas.Font = GetSmallerFontFor(Canvas,FontReduction); Canvas.SetPos(ScoreXPos, OwnerPos); if ( PRIArray[OwnerOffset].bOutOfLives ) Canvas.DrawText(OutText,true); else Canvas.DrawText(int(PRIArray[OwnerOffset].Score),true); } // draw flag icons Canvas.DrawColor = HUDClass.default.WhiteColor; if ( TeamNum == 0 ) OtherTeam = 1; /* if ( (GRI.FlagState[OtherTeam] != EFlagState.FLAG_Home) && (GRI.FlagState[OtherTeam] != EFlagState.FLAG_Down) ) { for ( i=0; i= 0) && (Canvas.ClipX >= 512) ) { BoxTextOffsetY = HeaderOffsetY + 0.5*PlayerBoxSizeY + NameY; Canvas.DrawColor = HUDClass.default.CyanColor; if ( FontReduction > 3 ) bHaveHalfFont = false; if ( Canvas.ClipX >= 1280 ) Canvas.Font = GetSmallFontFor(Canvas.ClipX, FontReduction+2); else Canvas.Font = GetSmallFontFor(Canvas.ClipX, FontReduction+1); Canvas.StrLen("Test", XL, YL); for ( i=0; i= ScoreXPos - NameXPos ) OrdersText = "("$PRIArray[i].GetCallSign()$") "$TeamPlayerReplicationInfo(PRIArray[i]).Squad.GetShortOrderStringFor(TeamPlayerReplicationInfo(PRIArray[i])); } Canvas.DrawText(OrdersText,true); } if ( bHaveHalfFont || !PRIArray[i].bBot ) { Canvas.SetPos(NameXPos, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY + LineCount*YL); Canvas.DrawText(PRIArray[i].GetLocationName(),true); } } if ( OwnerOffset >= PlayerCount ) { Canvas.SetPos(NameXPos, (PlayerBoxSizeY + BoxSpaceY)*i + BoxTextOffsetY); Canvas.DrawText(PRIArray[OwnerOffset].GetLocationName(),true); } } if ( Level.NetMode == NM_Standalone ) return; Canvas.Font = MainFont; Canvas.StrLen("Test",XL,YL); BoxTextOffsetY = HeaderOffsetY + 0.5 * PlayerBoxSizeY - 0.5 * YL; DrawNetInfo(Canvas,FontReduction,HeaderOffsetY,PlayerBoxSizeY,BoxSpaceY,BoxTextOffsetY,OwnerOffset,PlayerCount,NetXPos); } //============================================================================= // defaultproperties //============================================================================= }/FI//============================================================================= // PlayerSpawnManager // // In Assault Player.PlayerReplicationInfo.Team and PlayerStart.TeamNumber do not match! // The SpawnManager makes the connection between the team number and the right PlayerStart // Taking in account things like: // - which team is attacking or defending // - multiple (consecutively triggered or not) spawn areas // - forced pawn class with specific spawn areas // // How to use: // - Add a PlayerSpawnManager for each Spawn area in the level // - Due to the way UT handles playerstarts, // you must have PlayerStart actors with TeamNumber=0 in the Level // // Parameters are self explanatory // //============================================================================= class PlayerSpawnManager extends Info placeable; var() enum EPSM_AssaultTeam { EPSM_Attackers, EPSM_Defenders, } AssaultTeam; var() enum EPSM_ForcePossessPawn { EPSM_None, // No Force.. EPSM_ForcedPawnClass, // Forces Pawn class override at spawn EPSM_ForceDefaultPawnClass, // Forces controller to use his default Pawn Class when spawning } OverridePawnClass; var() class ForcedPawnClass; var() int PlayerStartTeam; // TeamNumber of the PlayerStart actors the manager is pointing to var() bool bEnabled; // Spawn manager active? // backup var bool BACKUP_bEnabled; var() bool bAllowTeleporting; // Allow players to teleport there when it's enabled. // Memory/Network/CPU optimizations // When PlayerSpawnManager is trigger disabled, auto kill vehicles and shutdown vehicle factories var() editinline array DisabledVehicleFactoriesTag; // Disable vehicle factories (and kill child) simulated function PostBeginPlay() { super.PostBeginPlay(); BACKUP_bEnabled = bEnabled; } simulated function UpdatePrecacheMaterials() { super.UpdatePrecacheMaterials(); if ( (ForcedPawnClass != None) && ( Level.NetMode != NM_DedicatedServer ) ) ForcedPawnClass.static.StaticPrecache( Level ); } function SetEnabled( bool bNewStatus ) { local ASVehicleFactory ASVF; local int i; if ( bNewStatus == bEnabled ) return; bEnabled = bNewStatus; if ( !bEnabled ) { if ( DisabledVehicleFactoriesTag.Length > 0 ) { ForEach DynamicActors(class'ASVehicleFactory', ASVF) for (i=0; i 0) && ( Dist > DrawDistThresHold) ) return false; // Check Min Distance if ( Dist < CollisionRadius ) return false; // Target is located behind camera if ((Location - CamLoc) Dot vector(CamRot) < 0) return false; if ( !bOverrideVisibilityCheck ) { // Simple Line check to see if we hit geometry TargetDir = Location - CamLoc; TargetDir.Z = 0; TargetLocation = Location - 2.f * CollisionRadius * vector(rotator(TargetDir)); return FastTrace( Location, CamLoc ); } return true; } /* Render Info Pod. Visibility checking and Color is done in HUD_Assault */ simulated function Render( Canvas C, Vector IPScreenPos, PlayerController PC ) { C.Style = InfoPodDrawStyle; switch ( InfoType ) { case EIPT_PlainText : DrawInfoPod_PlainText( C, IPScreenPos, PC ); break; case EIPT_TextBrackets : DrawInfoPod_TextBrackets( C, IPScreenPos, PC ); break; case EIPT_Texture : DrawInfoPod_Texture( C, IPScreenPos ); break; } } /* Draw InfoPod Plain Text */ simulated function DrawInfoPod_PlainText( Canvas C, Vector IPScreenPos, PlayerController PC ) { local float XL, YL; local string FinalString; FinalString = class'HUD_Assault'.default.IP_Bracket_Open @ POD_Message @ class'HUD_Assault'.default.IP_Bracket_Close; C.Font = PC.myHUD.GetFontSizeIndex( C, FontSize - 8 ); C.StrLen(FinalString, XL, YL); // Clipping if ( IPScreenPos.X + XL*0.5 > C.ClipX ) IPScreenPos.X = C.ClipX - XL*0.5; if ( IPScreenPos.Y + YL*0.5 > C.ClipY ) IPScreenPos.Y = C.ClipY - YL*0.5; // Drawing... C.SetPos(IPScreenPos.X - XL*0.5, IPScreenPos.Y - YL*0.5); C.DrawText(FinalString, false); } /* Draw InfoPod Text Brackets (Draws an additional box surrounding the InfoPod's collision cylinder) */ simulated function DrawInfoPod_TextBrackets( Canvas C, Vector IPScrO, PlayerController PC ) { local string Description; // Info Pod Description C.Font = PC.myHUD.GetFontSizeIndex( C, FontSize - 8 ); Description = class'HUD_Assault'.default.IP_Bracket_Open @ POD_Message @ class'HUD_Assault'.default.IP_Bracket_Close; class'HUD_Assault'.static.Draw_2DCollisionBox( C, Self, IPScrO, Description, DrawScale, false ); } /* Draw InfoPod Texture */ simulated function DrawInfoPod_Texture( Canvas C, Vector IPScrO ) { local float W, H; if ( POD_Texture != None ) { W = POD_Texture.MaterialUSize() * TextureScale * C.SizeX / 640.f; H = POD_Texture.MaterialVSize() * TextureScale * C.SizeY / 480.f; C.SetPos(IPScrO.X - W*0.5, IPScrO.Y - H*0.5); C.DrawTile(POD_Texture, W, H, 0.f, 0.f, POD_Texture.MaterialUSize(), POD_Texture.MaterialVSize()); } } }/T//============================================================================= // HUD_Assault //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class HUD_Assault extends HudCTeamDeathMatch config; #EXEC OBJ LOAD FILE=InterfaceContent.utx #EXEC OBJ LOAD FILE=AS_FX_TX.utx #exec OBJ LOAD File="MenuSounds.uax" #EXEC OBJ LOAD FILE=AssaultFilmGrain.utx // Objective notification var config float ObjectiveScale; // Size scale of visible objective reticles var config bool bOnHUDObjectiveNotification; // Show objectives on screen var config bool bShowInfoPods; // show InfoPods var config bool bDrawAllObjectives; // Draw ALL objectives on screen (2D arrows) var config bool bShow3DArrow; // 3d arrow pointing at current objective. var config bool bObjectiveReminder; // objective reminder at spawn var config bool bDrawRadar; // Show Radar var config bool bDrawRadarCardinalPoints; var config bool bShowWillowWhisp; var bool bForceSpawnNotification; var bool bShowObjectiveBoard, bForceObjectiveBoard; var Array OBJ; // List of objectives in the level var Array InfoPods; // List of infopods var Array MTrigger; // list of message triggers var Array BehindObjectiveArrows; var ObjectivePointingArrow OBJPointingArrow; var byte BehindObjectiveCount; var float OBJ_ReAppearTime; var float OBJ_FadedOutTime; var float Global_Delta; var float fBlink, fPulse; // Vehicle Radar var float ASRadarScale; var config float ASRadarPosX, ASRadarPosY; // Radar position var float LastRadarUpdate; var Array RadarVehicleCache; // Health Bar var Material HealthBarBackMat; var Material HealthBarMat; var float HealthBarWidth; var float HealthBarHeight; var int OldRemainingRoundTime; var localized string IP_Bracket_Open, IP_Bracket_Close; var localized string Cardinal_North, Cardinal_East, Cardinal_South, Cardinal_West; var localized string NoGameReplicationInfoString, MetersString, TargetString, NoTargetString, PracticeRoundString; var float AttackerProgressUpdateTime; var config float ObjectiveProgressPulseTime; // Current objective Color pulse when announced var byte ObjectiveProgress, OldObjectiveProgress; var ASGameReplicationInfo ASGRI; var ASPlayerReplicationInfo ASPRI; var GameObjective CurrentObjective; var Vehicle TrackedVehicle; var float NextTrackedVehicleSearch; var() SpriteWidget RoundTimeBackGround, ReinforceBackground, TeleportBackground, VSBackground; var() SpriteWidget RoundTimeIcon, ReinforceIcon, TeleportIcon, VSIcon; var() SpriteWidget ReinforcePulse, TeleportPulse, VSPulse; var() SpriteWidget RoundTimeBackGroundDisc, ReinforceBackGroundDisc, TeleportBackgroundDisc, VSBackgroundDisc; var() SpriteWidget RoundTimeSeparator; var() NumericWidget RoundTimeMinutes, RoundTimeSeconds, ReinforceSprNum, TeleportSprNum; // Spawn notification var float NextSpawnNotification; var byte PrevTeam; var() ObjectiveProgressDisplay ObjectiveBoard; // intro cinematic var float IntroTitleFade; // Override simulated function DrawTimer(Canvas C); simulated function DrawAdrenaline( Canvas C ); /* toggles displaying objectiveboard */ exec function ShowObjectiveBoard() { bShowObjectiveBoard = !bShowObjectiveBoard; } simulated function PrecacheFonts(Canvas C) { Super.PrecacheFonts(C); C.Font = GetFontSizeIndex(C,-1); C.SetPos(0,0); C.DrawText("Aa1"); C.Font = GetFontSizeIndex(C,-3); C.SetPos(0,0); C.DrawText("Aa1"); } simulated event PostBeginPlay() { local GameObjective GO; local InfoPod IP; local Trigger_ASMessageTrigger MT; super.PostBeginPlay(); // Caching level objectives ForEach AllActors(class'GameObjective', GO ) { if ( GO.bBotOnlyObjective ) // ignore bot only objectives continue; OBJ[OBJ.Length] = GO; } // Caching InfoPods ForEach AllActors(class'InfoPod', IP ) InfoPods[InfoPods.Length] = IP; ForEach AllActors(class'Trigger_ASMessageTrigger', MT) MTrigger[MTrigger.Length] = MT; ObjectiveBoard = Spawn(class'ObjectiveProgressDisplay', Owner); ObjectiveBoard.Initialize( Self ); } simulated event Destroyed() { if ( ObjectiveBoard != None ) { ObjectiveBoard.Destroy(); ObjectiveBoard = None; } Release_BehindObjectiveArrows(); Release_ObjectivePointingArrow(); super.Destroyed(); } //simulated function DrawHudPassD (Canvas C); // Alternate Texture Pass simulated function DrawHudPassA (Canvas C) // Alpha Pass { local bool bOldShowWeaponInfo, bOldShowPersonalInfo; local class AmmoClass; // Ammo Count bOldShowWeaponInfo = bShowWeaponInfo; if ( PawnOwner != None && PawnOwner.Weapon != None ) { AmmoClass = PawnOwner.Weapon.GetAmmoClass(0); if ( (AmmoClass == None) || ClassIsChildOf(AmmoClass,class'Ammo_Dummy') ) bShowWeaponInfo = false; } // Healh info bOldShowPersonalInfo = bShowPersonalInfo; if ( (ASVehicle(PawnOwner) != None) && ASVehicle(PawnOwner).bCustomHealthDisplay ) bShowPersonalInfo = false; super.DrawHudPassA( C ); bShowWeaponInfo = bOldShowWeaponInfo; bShowPersonalInfo = bOldShowPersonalInfo; // Vehicle Radar if ( bDrawRadar && Vehicle(PawnOwner) != None && Vehicle(PawnOwner).bHasRadar ) DrawRadarPassA( C ); } simulated function DrawHudPassB (Canvas C) // Additive Pass { super.DrawHudPassB( C ); // Vehicle Radar if ( bDrawRadar && Vehicle(PawnOwner) != None && Vehicle(PawnOwner).bHasRadar ) DrawRadarPassB( C ); } simulated function DrawHudPassC (Canvas C) // Alpha Pass { local bool bOldShowWeaponInfo, bOldShowPersonalInfo; local class AmmoClass; DrawAssaultHUDLayer( C ); // Ammo Count bOldShowWeaponInfo = bShowWeaponInfo; if ( PawnOwner != None && PawnOwner.Weapon != None ) { AmmoClass = PawnOwner.Weapon.GetAmmoClass(0); if ( (AmmoClass == None) || ClassIsChildOf(AmmoClass,class'Ammo_Dummy') ) bShowWeaponInfo = false; } // Healh info bOldShowPersonalInfo = bShowPersonalInfo; if ( PawnOwner != None && PawnOwner.IsA('ASVehicle') && ASVehicle(PawnOwner).bCustomHealthDisplay ) bShowPersonalInfo = false; super.DrawHudPassC( C ); bShowWeaponInfo = bOldShowWeaponInfo; bShowPersonalInfo = bOldShowPersonalInfo; } /* Specific function to use Canvas.DrawActor() Clear Z-Buffer once, prior to rendering all actors */ function CanvasDrawActors( Canvas C, bool bClearedZBuffer ) { if ( PawnOwner != None && bShow3DArrow && !bHideHUD ) { if ( !bClearedZBuffer ) C.DrawActor(None, false, true); // Clear the z-buffer here Draw3dObjectiveArrow( C ); super.CanvasDrawActors( C, true ); } else super.CanvasDrawActors( C, bClearedZBuffer ); } simulated function DrawAssaultHUDLayer( Canvas C ) { // Draw InfoPods if ( bShowInfoPods ) DrawInfoPods( C ); // On-HUD objective notification disabled ? if ( bOnHUDObjectiveNotification ) DrawObjectives( C ); UpdateActorTracking( C ); if ( ASGRI != None && ASGRI.IsPracticeRound() ) DrawPracticeRoundInfo( C ); if ( PawnOwner != None && ObjectiveBoard != None && ASGRI != None ) { ObjectiveBoard.ShowStatus( ShouldShowObjectiveBoard() ); ObjectiveBoard.PostRender( C, Global_Delta, ASGRI.IsDefender( PawnOwner.GetTeamNum() ) ); } } simulated function bool ShouldShowObjectiveBoard() { if ( ObjectiveBoard == None || ASGRI == None ) return false; if ( ObjectiveBoard.AnyOptionalObjectiveCritical() ) return true; return ( bShowObjectiveBoard || bForceObjectiveBoard || AttackerProgressUpdateTime > 0 ); } simulated function UpdateTeamHud() { local int RoundTime, Minutes, Seconds; local int TeleportCount; super.UpdateTeamHud(); if ( ASGRI == None ) return; if ( ASGRI.RoundTimeLimit > 0 ) // freeze time when round is over { RoundTime = Max(0, ASGRI.RoundTimeLimit-ASGRI.RoundStartTime+ASGRI.RemainingTime); if ( ASGRI.RoundWinner != ERW_None ) RoundTime = ASGRI.RoundOverTime; Minutes = RoundTime / 60; Seconds = RoundTime - Minutes * 60; RoundTimeMinutes.Value = Minutes; RoundTimeSeconds.Value = Min(Seconds, 60); if ( Minutes > 9 ) { RoundTimeSeparator.OffsetX = default.RoundTimeSeparator.OffsetX + 32; //100 RoundTimeMinutes.OffsetX = default.RoundTimeMinutes.OffsetX + 32; //020 RoundTimeSeconds.OffsetX = default.RoundTimeSeconds.OffsetX + 32; //110 } else { RoundTimeSeparator.OffsetX = default.RoundTimeSeparator.OffsetX; //100 RoundTimeMinutes.OffsetX = default.RoundTimeMinutes.OffsetX; //020 RoundTimeSeconds.OffsetX = default.RoundTimeSeconds.OffsetX; //110 } } ReinforceSprNum.Value = Min(ASGRI.ReinforcementCountDown, 999); if ( ASPRI != None ) { TeleportCount = Min(ASGRI.RoundTimeLimit - ASGRI.RoundStartTime + ASGRI.RemainingTime + ASGRI.MaxTeleportTime - ASPRI.TeleportTime, 999); if ( ASPRI.bTeleportToSpawnArea && TeleportCount >= 0 && TeleportCount != TeleportSprNum.Value ) PlayerOwner.ViewTarget.PlaySound(sound'MenuSounds.J_MouseOver', SLOT_None,,,,,false); TeleportSprNum.Value = TeleportCount; } } simulated function ShowTeamScorePassA(Canvas C) { local float PosY; if ( ASGRI == None ) return; // // HUDBase texture // /* Round Time Limit */ if ( ASGRI.RoundTimeLimit > 0 ) { RoundTimeBackground.Tints[TeamIndex] = HudColorBlack; RoundTimeBackground.Tints[TeamIndex].A = 150; DrawSpriteWidget (C, RoundTimeBackground); DrawSpriteWidget (C, RoundTimeBackgroundDisc); DrawSpriteWidget (C, RoundTimeSeparator); DrawSpriteWidget (C, RoundTimeIcon); PosY += 0.06 * HUDScale; } if ( Level.Game == None || !ASGameInfo(Level.Game).bDisableReinforcements ) { ReinforceBackground.PosY = PosY; ReinforceBackgroundDisc.PosY = PosY; ReinforcePulse.PosY = PosY; ReinforceIcon.PosY = PosY; ReinforceSprNum.PosY = PosY; PosY += 0.06 * HUDScale; /* Reinforcements count down */ ReinforceBackground.Tints[TeamIndex] = HudColorBlack; ReinforceBackground.Tints[TeamIndex].A = 150; DrawSpriteWidget (C, ReinforceBackground); DrawSpriteWidget (C, ReinforceBackgroundDisc); ReinforcePulse.Tints[TeamIndex] = HudColorHighLight; if ( ASGRI.ReinforcementCountDown < 1 ) // Pulse when reinforcements arrive DrawSpriteWidget( C, ReinforcePulse ); DrawSpriteWidget (C, ReinforceIcon); } /* second attack wave comparison */ if ( ASGRI != None && (ASGRI.CurrentRound % 2 == 0) && !ASGRI.IsPracticeRound() && IsVSRelevant() ) { VSBackground.PosY = PosY; VSBackgroundDisc.PosY = PosY; VSIcon.PosY = PosY; PosY += 0.06 * HUDScale; VSBackground.Tints[TeamIndex] = HudColorBlack; VSBackground.Tints[TeamIndex].A = 150; DrawSpriteWidget (C, VSBackground); DrawSpriteWidget (C, VSBackgroundDisc); DrawSpriteWidget (C, VSIcon); } /* Teleport */ if ( ASPRI !=None && ASPRI.bTeleportToSpawnArea && TeleportSprNum.Value >= 0 ) { TeleportBackground.PosY = PosY; TeleportBackgroundDisc.PosY = PosY; TeleportPulse.PosY = PosY; TeleportIcon.PosY = PosY; TeleportSprNum.PosY = PosY; PosY += 0.06 * HUDScale; TeleportBackground.Tints[TeamIndex] = HudColorBlack; TeleportBackground.Tints[TeamIndex].A = 150; DrawSpriteWidget (C, TeleportBackground); DrawSpriteWidget (C, TeleportBackgroundDisc); TeleportPulse.Tints[TeamIndex] = HudColorHighLight; DrawSpriteWidget( C, TeleportPulse ); DrawSpriteWidget (C, TeleportIcon); } // // Numeric // /* Round Time Limit */ if ( ASGRI.RoundTimeLimit > 0 ) { DrawNumericWidget (C, RoundTimeMinutes, DigitsBig); DrawNumericWidget (C, RoundTimeSeconds, DigitsBig); } /* reinforcements */ if ( Level.Game == None || !ASGameInfo(Level.Game).bDisableReinforcements ) DrawNumericWidget (C, ReinforceSprNum, DigitsBig); /* second attack wave comparison */ if ( ASGRI != None && (ASGRI.CurrentRound % 2 == 0) && !ASGRI.IsPracticeRound() && IsVSRelevant() ) DrawTeamVS( C ); /* Teleport */ if ( ASPRI !=None && ASPRI.bTeleportToSpawnArea && TeleportSprNum.Value >= 0 ) DrawNumericWidget (C, TeleportSprNum, DigitsBig); } /* give ref on 2nd attacking team to beat 1st team (is the team on par for current objective?) */ simulated function DrawTeamVS( Canvas C ) { local bool bIsBehindOtherTeam; local int RelativeTime, hours, minutes, seconds, playerteam;; local string output; local float ScreenX, ScreenY, TotalScaleX, TotalScaleY, TextureDX, TextureDY, XL, YL, Progress; // ref. previous team objective completed time if ( CurrentObjective.ObjectiveDisabledTime > 0 ) { RelativeTime = CurrentObjective.ObjectiveDisabledTime - (ASGRI.RoundStartTime-ASGRI.RemainingTime); bIsBehindOtherTeam = RelativeTime < 0; hours = Abs(RelativeTime) / 3600; minutes = (Abs(RelativeTime) - hours*3600) / 60; seconds = Abs(RelativeTime) - hours*3600 - minutes*60; if ( hours > 0 ) output = hours $ ":"; if ( minutes > 9 ) output = output $ minutes $ ":"; else output = output $ "0" $ minutes $ ":"; if ( seconds > 9 ) output = output $ seconds; else output = output $ "0" $ seconds; } else // ref on progress on the same objective { Progress = CurrentObjective.SavedObjectiveProgress - CurrentObjective.GetObjectiveProgress(); bIsBehindOtherTeam = Progress < 0; output = int(Abs(Progress*100)) $ "%"; } // match up widget position voodoo magic crap... TotalScaleX = HudCanvasScale * ResScaleX * HudScale; TotalScaleY = HudCanvasScale * ResScaleY * HudScale; TextureDX = Abs(VSBackgroundDisc.TextureCoords.X2 - VSBackgroundDisc.TextureCoords.X1 + 1.0f) * TotalScaleX * VSBackgroundDisc.TextureScale; TextureDY = Abs(VSBackground.TextureCoords.Y2 - VSBackground.TextureCoords.Y1 + 1.0f) * TotalScaleY * VSBackground.TextureScale; ScreenX = (VSBackgroundDisc.PosX * HudCanvasScale * C.SizeX) + (((1.0f - HudCanvasScale) * 0.5f) * C.SizeX); ScreenY = (VSBackground.PosY * HudCanvasScale * C.SizeY) + (((1.0f - HudCanvasScale) * 0.5f) * C.SizeY); ScreenX += VSBackgroundDisc.OffsetX * TotalScaleX + TextureDX*1; ScreenY += VSBackground.OffsetY * TotalScaleY + TextureDY*0.45; // And finally... we can draw! C.Font = GetMediumFont( C.ClipX * HUDScale ); C.TextSize( output, XL, YL ); C.Style = ERenderStyle.STY_Alpha; // defender version if ( PawnOwner == None ) playerteam = PlayerOwner.GetTeamNum(); else playerteam = PawnOwner.GetTeamNum(); if ( ASGRI.IsDefender(playerteam) ) bIsBehindOtherTeam = !bIsBehindOtherTeam; if ( bIsBehindOtherTeam ) { output = "-" $ output; C.DrawColor = C.MakeColor( 255, 0, 0, 255 ); } else C.DrawColor = C.MakeColor( 0, 255, 0, 255 ); C.SetPos( ScreenX, ScreenY - YL/2); C.DrawText( output, false ); } /* Can we compare progress of second attacking team, with the first one ? */ simulated function bool IsVSRelevant() { if ( ASGRI.RoundWinner != ERW_None || CurrentObjective == None || (CurrentObjective.ObjectiveDisabledTime == 0 && (CurrentObjective.SavedObjectiveProgress == 0 || CurrentObjective.SavedObjectiveProgress == 1 || (CurrentObjective.SavedObjectiveProgress - CurrentObjective.GetObjectiveProgress() > 0) )) ) return false; return true; } simulated function ShowTeamScorePassC(Canvas C); simulated function DrawSpectatingHud (Canvas C) { super.DrawSpectatingHud( C ); UpdateTeamHud(); ShowTeamScorePassA( C ); DrawAssaultHUDLayer( C ); } // // Radar // function DrawRadarPassA( Canvas C ) { local float Dist, RadarWidth, DotSize, OffsetY, XL, YL, OffsetScale; local vector Start, DotPos, ViewX, ViewY, Z; if ( PawnOwner == None ) return; ASRadarScale = default.ASRadarScale * HUDScale; RadarWidth = 0.5 * ASRadarScale * C.ClipX; C.Style = ERenderStyle.STY_Alpha; // Radar background C.DrawColor = GetTeamColor( PawnOwner.GetTeamNum() ); C.SetPos(ASRadarPosX*C.ClipX - RadarWidth, ASRadarPosY*C.ClipY+RadarWidth); C.DrawTile( Material'AS_FX_TX.AssaultRadar', RadarWidth, RadarWidth, 0, 512, 512, -512); C.SetPos(ASRadarPosX*C.ClipX, ASRadarPosY*C.ClipY+RadarWidth); C.DrawTile( Material'AS_FX_TX.AssaultRadar', RadarWidth, RadarWidth, 512, 512, -512, -512); C.SetPos(ASRadarPosX*C.ClipX - RadarWidth, ASRadarPosY*C.ClipY); C.DrawTile( Material'AS_FX_TX.AssaultRadar', RadarWidth, RadarWidth, 0, 0, 512, 512); C.SetPos(ASRadarPosX*C.ClipX, ASRadarPosY*C.ClipY); C.DrawTile( Material'AS_FX_TX.AssaultRadar', RadarWidth, RadarWidth, 512, 0, -512, 512); Start = PawnOwner.Location; OffsetY = ASRadarPosY + RadarWidth/C.ClipY; C.DrawColor = WhiteColor; OffsetScale = ASRadarScale*0.0000835; GetAxes( PawnOwner.GetViewRotation(), ViewX, ViewY, Z ); // Cardinal Points display if ( bDrawRadarCardinalPoints ) { Dist = 5500; C.Font = GetConsoleFont( C ); C.StrLen(Cardinal_North, XL, YL); DotPos = GetRadarDotPosition( C, Vect(0,-100,0), ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*XL, DotPos.Y - 0.5*YL ); C.DrawText( Cardinal_North, false ); C.StrLen(Cardinal_East, XL, YL); DotPos = GetRadarDotPosition( C, Vect(100,0,0), ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*XL, DotPos.Y - 0.5*YL ); C.DrawText( Cardinal_East, false ); C.StrLen(Cardinal_South, XL, YL); DotPos = GetRadarDotPosition( C, Vect(0,100,0), ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*XL, DotPos.Y - 0.5*YL ); C.DrawText( Cardinal_South, false ); C.StrLen(Cardinal_West, XL, YL); DotPos = GetRadarDotPosition( C, Vect(-100,0,0), ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*XL, DotPos.Y - 0.5*YL ); C.DrawText( Cardinal_West, false ); } // Draw Center C.DrawColor = WhiteColor; DotSize = 12*C.ClipX*HUDScale/1600; DotPos = GetRadarDotPosition( C, PawnOwner.Location-Start, ViewX, ViewY, 0.f, OffsetY); C.SetPos( DotPos.X - 0.5*DotSize, DotPos.Y - 0.5*DotSize ); C.DrawTile(Material'HudContent.Generic.HUD', DotSize, DotSize,340,432,78,78); } simulated function DrawRadarPassB( Canvas C ) { local Vehicle P; local float Dist, RadarWidth, DotSize, OffsetY; local vector Start, DotPos, ViewX, ViewY, Z; local float MaxSmartRange, OffsetScale; local int i; if ( PawnOwner == None ) return; Start = PawnOwner.Location; ASRadarScale = default.ASRadarScale * HUDScale; RadarWidth = 0.5 * ASRadarScale * C.ClipX; OffsetY = ASRadarPosY + RadarWidth/C.ClipY; MaxSmartRange = 30000; DotSize = 20*C.ClipX*HUDScale/1600; C.Style = ERenderStyle.STY_Additive; OffsetScale = ASRadarScale*0.0000835; GetAxes( PawnOwner.GetViewRotation(), ViewX, ViewY, Z ); // Draw nearby vehicles if ( Level.TimeSeconds > LastRadarUpdate+1 ) { LastRadarUpdate = Level.TimeSeconds; RadarVehicleCache.Length = 0; // Clear cache ForEach DynamicActors(class'Vehicle', P) { if ( (P!=PawnOwner) && (P.GetTeamNum() != PawnOwner.GetTeamNum()) && (P!=TrackedVehicle) && (P.Health > 0) && !P.bDeleteMe && P.IndependentVehicle() ) { RadarVehicleCache[RadarVehicleCache.Length] = P; Dist = GetRadarDotDist( P.Location-Start, ViewX, ViewY ); if ( Dist < MaxSmartRange ) { Dist = ApplySmartRangeDist( Dist*0.5 ); // Show current Target on radar if ( PawnOwner.IsA('ASVehicle_SpaceFighter') && ASVehicle_SpaceFighter(PawnOwner).CurrentTarget == P ) C.DrawColor = GetTeamColor(P.GetTeamNum())*(1.f-fPulse) + C.MakeColor(64,200,64)*fPulse; else C.DrawColor = GetTeamColor( P.GetTeamNum() ); DotPos = GetRadarDotPosition( C, P.Location-Start, ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*DotSize, DotPos.Y - 0.5*DotSize ); C.DrawTile(Material'HudContent.Generic.HUD', DotSize, DotSize,340,432,78,78); } } } } else // Use cached vehicles, to minize use of expensive DynamicActors iterator. { for (i=0; i 0) && !P.bDeleteMe && P.IndependentVehicle() ) { Dist = GetRadarDotDist( P.Location - Start, ViewX, ViewY ); if ( Dist < MaxSmartRange ) { Dist = ApplySmartRangeDist( Dist*0.5 ); // Show current Target on radar if ( PawnOwner.IsA('ASVehicle_SpaceFighter') && ASVehicle_SpaceFighter(PawnOwner).CurrentTarget == P ) C.DrawColor = GetTeamColor(P.GetTeamNum())*(1.f-fPulse) + C.MakeColor(64,200,64)*fPulse; else C.DrawColor = GetTeamColor( P.GetTeamNum() ); DotPos = GetRadarDotPosition( C, P.Location-Start, ViewX, ViewY, Dist*OffsetScale, OffsetY ); C.SetPos( DotPos.X - 0.5*DotSize, DotPos.Y - 0.5*DotSize ); C.DrawTile(Material'HudContent.Generic.HUD', DotSize, DotSize,340,432,78,78); } } } } } function float ApplySmartRangeDist( float Dist ) { // "Smart Range" if ( Dist > 3000 ) Dist = (Dist-3000)*0.25 + 2000; else if ( Dist > 1000 ) Dist = (Dist-1000)*0.5 + 1000; return FMin(Dist, 5500); // Small hack so dots stay inside the Radar... } function float GetRadarDotDist( Vector Dist, Vector ViewX, Vector ViewY ) { local vector DotProjected; // Top view 2D projection relatively to player's rotation coordinate system DotProjected.X = Dist Dot Normal(ViewX); DotProjected.Y = Dist Dot Normal(ViewY); return VSize( DotProjected ); } function vector GetRadarDotPosition( Canvas C, Vector Dist, Vector ViewX, Vector ViewY, float OffsetScale, float OffsetY ) { local vector ScreenPosition, DotProjected; // Top view 2D projection relatively to player's rotation coordinate system DotProjected.X = Normal(Dist) Dot Normal(ViewX); DotProjected.Y = Normal(Dist) Dot Normal(ViewY); ScreenPosition.X = ASRadarPosX * C.ClipX + OffsetScale*C.ClipX * DotProjected.Y; ScreenPosition.Y = OffsetY * C.ClipY - OffsetScale*C.ClipX * DotProjected.X; return ScreenPosition; } // // Actor Tracking // /* Tracked Actors indicators */ simulated function UpdateActorTracking( Canvas C ) { local Vehicle V; local vector ScreenPos; // Tracked Vehicle (Assumes only 1 per Assault Level) (eg. JunkYard's PRV or Glacier's Ion Plasma Tank) if ( TrackedVehicle == None && NextTrackedVehicleSearch < Level.TimeSeconds ) { NextTrackedVehicleSearch = Level.TimeSeconds + 1; ForEach DynamicActors(class'Vehicle', V) if ( V.bHUDTrackVehicle ) { TrackedVehicle = V; break; } } // FIXME -- Check that PlayerOwner.Pawn != WeaponPawn attached to TrackedVehicle //if ( TrackedVehicle != None && TrackedVehicle != PlayerOwner.Pawn ) if ( TrackedVehicle != None && (TrackedVehicle!=PawnOwner) && TrackedVehicle.Health > 0 && !TrackedVehicle.bDeleteMe ) { C.DrawColor = GetTeamColor( TrackedVehicle.Team ); C.DrawColor.A = 128; if ( DrawActorTracking( C, TrackedVehicle, false, ScreenPos ) ) DrawTrackedVehicleIcon( C, TrackedVehicle, ScreenPos.X, ScreenPos.Y, 1.f ); } // Tracked GameObject (eg. JunkYard Energy Core) if ( ASGRI != None && ASGRI.GameObject != None && PawnOwner != None && ASGRI.GameObject.HolderPRI != PawnOwner.PlayerReplicationInfo ) { C.DrawColor = GoldColor; C.DrawColor.A = 128; if ( DrawActorTracking( C, ASGRI.GameObject, false, ScreenPos ) ) DrawTrackedGameObjectIcon( C, ScreenPos.X, ScreenPos.Y, 1.f ); } } simulated function DrawTrackedVehicleIcon( Canvas C, Vehicle TrackedVehicle, float X, float Y, float Scale ) { local float SizeScale, SizeX, SizeY, Ratio; if ( TrackedVehicle.VehicleIcon.Material == None ) return; SizeScale = ObjectiveScale * HUDScale * Scale; Ratio = TrackedVehicle.VehicleIcon.SizeX / TrackedVehicle.VehicleIcon.SizeY; SizeX = 32*SizeScale*ResScaleX; SizeY = (32/Ratio)*SizeScale*ResScaleY; if ( TrackedVehicle.VehicleIcon.bIsGreyScale ) C.DrawColor = GetTeamColor( 1 - TrackedVehicle.Team ); else C.DrawColor = WhiteColor; C.DrawColor.A = 127 + 128*fPulse; C.Style = ERenderStyle.STY_Alpha; C.SetPos(X - SizeX*0.5, Y - SizeY*0.5); C.DrawTile( TrackedVehicle.VehicleIcon.Material , SizeX, SizeY, TrackedVehicle.VehicleIcon.X, TrackedVehicle.VehicleIcon.Y, TrackedVehicle.VehicleIcon.SizeX, TrackedVehicle.VehicleIcon.SizeY); } simulated function DrawTrackedGameObjectIcon( Canvas C, float X, float Y, float Scale ) { local float Size; Size = 16.f * ResScaleX * ObjectiveScale * HUDScale * Scale; C.DrawColor = WhiteColor; C.DrawColor.A = 127 + 128*fPulse; C.Style = ERenderStyle.STY_Alpha; C.SetPos(X - Size * 0.5, Y - Size * 1.f); C.DrawTile( Material'HudContent.Generic.HUD', Size, Size, 79, 223, 37, 41); } simulated function bool DrawActorTracking( Canvas C, Actor A, bool bOptionalIndicator, out vector ScreenPos ) { local Vector CamLoc; local Rotator CamRot; local float ProgressPct; C.GetCameraLocation( CamLoc, CamRot ); if ( A.IsA('Pawn') ) ProgressPct = float(Pawn(A).Health) / Pawn(A).HealthMax; if ( !IsTargetInFrontOfPlayer( C, A, ScreenPos, CamLoc, CamRot ) ) { if ( !A.IsA('GameObjective') || bDrawAllObjectives ) { DrawActorTracking_Behind( C, A, bOptionalIndicator, CamLoc, CamRot, ScreenPos ); if ( ProgressPct > 0 ) DrawObjectiveStatusOverlay( C, ProgressPct, false, ScreenPos, ObjectiveScale*0.67 ); return true; } return false; } else if ( VSize(A.Location - CamLoc) > 2048 || !FastTrace( A.Location, CamLoc) ) { DrawActorTracking_Obstructed( C, A, bOptionalIndicator, CamLoc, ScreenPos ); if ( ProgressPct > 0 ) DrawObjectiveStatusOverlay( C, ProgressPct, false, ScreenPos, ObjectiveScale*0.67 ); return true; } if ( ProgressPct > 0 ) { ScreenPos.Y -= 48 * ResScaleX; DrawHealthBar( C, ScreenPos, ProgressPct, 1.f, C.DrawColor ); } return false; } simulated function DrawActorTracking_Obstructed( Canvas C, Actor A, bool bOptionalIndicator, vector CamLoc, out vector ScreenPos ) { local String DistanceText; local float XL, YL, tileX, tileY, width, height; local vector IndicatorPos; C.Style = ERenderStyle.STY_Alpha; DistanceText = IP_Bracket_Open $ int(VSize(A.Location-CamLoc)*0.01875.f) $ MetersString $ IP_Bracket_Close; C.Font = GetConsoleFont( C ); C.StrLen(DistanceText, XL, YL); XL = XL*0.5; YL = YL*0.5; tileX = 64.f * 0.45 * ResScaleX * ObjectiveScale * HUDScale; tileY = 64.f * 0.45 * ResScaleY * ObjectiveScale * HUDScale; width = FMax(tileX*0.5, XL); height = tileY*0.5 + YL*2; ClipScreenCoords( C, ScreenPos.X, ScreenPos.Y, width, height ); // Objective Icon IndicatorPos.X = ScreenPos.X; IndicatorPos.Y = ScreenPos.Y - height + YL + tileY*0.5; DrawObjectiveIcon( C, bOptionalIndicator, IndicatorPos.X - tileX*0.5, IndicatorPos.Y - tileY*0.5, tileX, tileY ); // Distance reading C.SetPos(IndicatorPos.X - XL, IndicatorPos.Y + tileY*0.5 ); C.DrawText(DistanceText, false); ScreenPos = IndicatorPos; } simulated function DrawActorTracking_Behind( Canvas C, Actor A, bool bOptionalIndicator, vector CamLoc, rotator CamRot, out vector ScreenPos ) { local vector Orientation; local float tileX, tileY; local TexRotator Arrow; C.Style = ERenderStyle.STY_Alpha; Orientation = GetTargetOrientation( A, CamLoc, CamRot ); Orientation = ExpandTargetOrientationToCanvas( C, Orientation ); ScreenPos.X = C.ClipX * 0.5 + C.ClipX * Orientation.X * 0.5; ScreenPos.Y = C.ClipY * 0.5 - C.ClipY * Orientation.Y * 0.5; // Setup texture Arrow = Get_BehindObjectiveArrow(); tileX = 128.f * 0.45 * ResScaleX * ObjectiveScale * HUDScale; tileY = 128.f * 0.45 * ResScaleY * ObjectiveScale * HUDScale; ClipScreenCoords( C, ScreenPos.X, ScreenPos.Y, tileX*0.5, tileY*0.5 ); // Setup Texture properly Arrow.Rotation.Yaw = Atan( Orientation.Y, Orientation.X ) * 32768 / PI; if ( bOptionalIndicator ) Arrow.Material = Texture'AS_FX_TX.HUD.Objective_Optional_Indicator'; else Arrow.Material = Texture'AS_FX_TX.HUD.Objective_Primary_Indicator'; C.SetPos(ScreenPos.X - tileX*0.5, ScreenPos.Y - tileY*0.5); C.DrawTile( Arrow, tileX, tileY, 0.0, 0.0, 128, 128); BehindObjectiveCount++; } // // Objectives // /* On-HUD Objective notification */ simulated function DrawObjectives(Canvas C) { local int i; local GameObjective GO; local vector ScreenPos; local vector CamLoc; local rotator CamRot; BehindObjectiveCount = 0; // Keep track of number of required materials // On Screen objective notification for (i=0; i Global_Delta*6.f || (GO.DrawTime > OBJ_ReAppearTime)) ) GO.DrawTime = 0.f; GO.DrawTime += Global_Delta; GO.LastDrawTime = Level.TimeSeconds; // If not faded out, draw objective HUD icon if ( !bFadeOut || (GO.DrawTime <= OBJ_FadedOutTime) ) { if ( bFadeOut && (GO.DrawTime > (OBJ_FadedOutTime - 1.f)) ) FadeOutEffect = OBJ_FadedOutTime - GO.DrawTime; else FadeOutEffect = 1.f; C.DrawColor = ObjColor * FadeOutEffect; if ( bProgressPulsing == 0 ) C.DrawColor.A = 63 + 128 * fPulse * FadeOutEffect; else C.DrawColor.A = 127 * FadeOutEffect; AppearEffect = 0.5 / FMin(GO.DrawTime, 0.5); tileX = 64.f * ResScaleX * AppearEffect * ObjectiveScale * HUDScale; tileY = 64.f * ResScaleY * AppearEffect * ObjectiveScale * HUDScale; C.Style = ERenderStyle.STY_Alpha; C.SetPos(ScreenPos.X - tileX*0.5, ScreenPos.Y - tileY*0.5); if ( GO.IsA('UseObjective') ) { if ( GO.UseDescription != "" ) { UseString = IP_Bracket_Open @ GO.UseDescription @ IP_Bracket_Close; C.Font = GetConsoleFont( C ); } Draw_2DCollisionBox( C, GO, ScreenPos, UseString, GO.DrawScale, false ); } else if ( GO.ObjectiveTypeIcon != None ) C.DrawTile( GO.ObjectiveTypeIcon, tileX, tileY, 0.0, 0.0, 64, 64); // Defense Shield Overlay if ( PawnOwner != None && ASGRI.IsDefender( PawnOwner.GetTeamNum() ) ) { if ( GO.IsCritical() ) C.DrawColor = GreenColor*fPulse + GoldColor*(1-fPulse); else C.DrawColor = GreenColor; if ( bProgressPulsing == 0 ) C.DrawColor.A = (63 + 128 * fPulse) * FadeOutEffect; else C.DrawColor.A = 127 * FadeOutEffect; tileX = 1.25*ObjectiveScale*HUDScale*ResScaleX; tileY = 1.25*ObjectiveScale*HUDScale*ResScaleY; C.SetPos(ScreenPos.X - tileX * 32, ScreenPos.Y - tileY * 32); C.DrawTile( Texture'AS_FX_TX.HUD.OBJ_Status', 64*tileX, 64*tileY, 191.0, 191.0, 64, 64); } } // Draw Objective Progress ProgressPct = GO.GetObjectiveProgress(); if ( ProgressPct > 0 ) { ScreenPos.Y -= 48 * ResScaleX; DrawHealthBar( C, ScreenPos, ProgressPct, 1.f, ObjColor ); } } simulated function DrawCriticalObjectiveOverlay( Canvas C, vector ScreenPos, float Scale ) { local float SizeScale, SizeX, SizeY; SizeScale = 0.33 * HUDScale * Scale; SizeX = 24 * SizeScale * ResScaleX; SizeY = 62 * SizeScale * ResScaleY; C.DrawColor = WhiteColor; C.SetPos(ScreenPos.X - SizeX * 0.5, ScreenPos.Y - SizeY * 0.5); C.DrawTile( FinalBlend'HudContent.Generic.HUDPulse', SizeX, SizeY, 344, 210, 20, 62); } /* Draw Objective status overlay (health or completion progress) */ simulated function DrawObjectiveStatusOverlay( Canvas C, float Progress, bool bCriticalFlash, vector ScreenPos, float Scale ) { local float SizeScale, SizeX, SizeY, PosX, PosY; if ( Progress <= 0 ) return; SizeScale = 0.5 * HUDScale * Scale; SizeX = 64 * SizeScale * ResScaleX; SizeY = 64 * SizeScale * ResScaleY; C.DrawColor = GetGYRColorRamp( Progress ); if ( bCriticalFlash ) C.DrawColor = C.DrawColor*fPulse + GoldColor*(1-fPulse); C.DrawColor.A = 128; C.SetPos(ScreenPos.X - SizeX * 0.5, ScreenPos.Y - SizeY * 0.5); // texture coords if ( Progress > 0.6 ) { PosX = 64 * (10 - Ceil(Progress*10)); PosY = 0; } else if ( Progress > 0.2 ) { PosX = 64 * (6 - Ceil(Progress*10)); PosY = 64; } else { PosX = 64 * (2 - Ceil(Progress*10)); PosY = 128; } C.DrawTile( Texture'AS_FX_TX.HUD.OBJ_Status', SizeX, SizeY, PosX, PosY, 64, 64); } simulated function DrawObjectiveIcon( Canvas C, bool bOptionalObjective, float posX, float posY, float tileX, float tileY ) { C.SetPos(posX, posY); if ( bOptionalObjective ) C.DrawTile( Texture'AS_FX_TX.HUD.OBJ_Status', tileX, tileY, 191.0, 127.0, 64, 64); else C.DrawTile( Texture'AS_FX_TX.HUD.OBJ_Status', tileX, tileY, 127.0, 127.0, 64, 64); } /* Allocate new "Behind Objective Arrow" material when necessary */ simulated function TexRotator Get_BehindObjectiveArrow() { Local TexRotator Arrow; if ( BehindObjectiveArrows.Length <= BehindObjectiveCount || BehindObjectiveArrows[BehindObjectiveCount] == None ) { Arrow = TexRotator(Level.ObjectPool.AllocateObject(class'TexRotator')); Arrow.UOffset = 64; Arrow.VOffset = 64; BehindObjectiveArrows[BehindObjectiveCount] = Arrow; } return BehindObjectiveArrows[BehindObjectiveCount]; } simulated function Release_BehindObjectiveArrows() { local int i; for (i=0; i 0 ); } else if ( CurrentObjective != None ) { TrackedActor = CurrentObjective; if ( ObjectiveBoard != None && ObjectiveBoard.AnyPrimaryObjectivesCritical() ) OBJPointingArrow.SetYellowColor( true ); else OBJPointingArrow.SetTeamSkin( CurrentObjective.DefenderTeamIndex, AttackerProgressUpdateTime > 0 ); } if ( TrackedActor != None ) OBJPointingArrow.Render( C, PlayerOwner, TrackedActor ); } simulated function Release_ObjectivePointingArrow() { if ( OBJPointingArrow != None ) OBJPointingArrow.Destroy(); } /* Draws little health bar... */ simulated function DrawHealthBar(Canvas C, vector HBScreenPos, float Health, float MaxHealth, Color ObjColor) { local float HealthPct; C.DrawColor = ObjColor; C.Style = ERenderStyle.STY_Alpha; HealthBarWidth = default.HealthBarWidth * ResScaleX * HUDScale; HealthBarHeight = default.HealthBarHeight * ResScaleY * HUDScale; C.SetPos(HBScreenPos.X - HealthBarWidth*0.5, HBScreenPos.Y - HealthBarHeight*0.5); C.DrawTileStretched(HealthBarBackMat, HealthBarWidth, HealthBarHeight); HealthPct = Health / MaxHealth; C.DrawColor = GetGYRColorRamp( HealthPct ); C.DrawColor.A = 200; C.SetPos(HBScreenPos.X - HealthBarWidth*0.49, HBScreenPos.Y - HealthBarHeight*0.3 ); C.DrawTileStretched(HealthBarMat, HealthBarWidth*HealthPct*0.98, HealthBarHeight*0.6); } /* returns true if Objective can be displayed */ simulated function bool CheckObjectivePriority(GameObjective GO) { if ( GO.ObjectivePriority <= ObjectiveProgress ) return true; return false; } /* Return true if GameObjective is visible */ simulated final function bool IsObjectiveVisible( Canvas C, GameObjective Target, out vector ScreenPos, Vector CamLoc, Rotator CamRot ) { local vector TargetLocation, TargetDir; local float Dist; // Check if in same Zone if ( !Target.bOverrideZoneCheck && PawnOwner != None && PawnOwner.Region.Zone != Target.Region.Zone ) return false; Dist = VSize(Target.Location - CamLoc); // Check Distance Threshold if ( (Target.DrawDistThresHold > 0) && ( Dist > Target.DrawDistThresHold) ) return false; // Target is located behind camera if ( !IsTargetInFrontOfPlayer( C, Target, ScreenPos, CamLoc, CamRot ) ) return false; if ( !Target.bOverrideVisibilityCheck ) { // Simple Line check to see if we hit geometry TargetDir = Target.Location - CamLoc; TargetDir.Z = 0; TargetLocation = Target.Location - 2.f * Target.CollisionRadius * vector(rotator(TargetDir)); if ( !FastTrace( TargetLocation, CamLoc ) ) return false; } return true; } // // Objective Progress // event AnnouncementPlayed( Name AnnouncerSound, byte Switch ) { local int i; if ( Switch == 200 ) // Highlight current objective + waypoint HighlightCurrentObjective( true ); else if ( Switch == 201 ) // Highlight current objective HighlightCurrentObjective( false ); else if ( Switch == 210 ) // ASMessageTrigger { for (i=0; i NextSpawnNotification) ) { NextSpawnNotification = Level.TimeSeconds + 30; bForceSpawnNotification = false; return true; } return false; } // // InfoPods // /* main InfoPod drawing routine */ simulated function DrawInfoPods( Canvas C ) { local InfoPod IP; local vector IPScreenPos, CamLoc; local int i; local rotator CamRot; if ( ASGRI == None || PawnOwner == None || PlayerOwner == None ) return; C.GetCameraLocation( CamLoc, CamRot ); for (i=0; i= C.ClipX ) continue; if ( IPScreenPos.Y <= 0 || IPScreenPos.Y >= C.ClipY ) continue; // Color if ( IP.Team == EIP_All ) C.DrawColor = WhiteColor; else C.DrawColor = GetTeamColor( PawnOwner.GetTeamNum() ); // Opacity effect switch ( IP.InfoEffect ) { case EIPE_Blink : C.DrawColor.A = (IP.DrawOpacity*0.5 + IP.DrawOpacity*2*fBlink); break; case EIPE_Pulse : C.DrawColor.A = (IP.DrawOpacity*0.5 + IP.DrawOpacity*0.5*fPulse); break; default : C.DrawColor.A = IP.DrawOpacity; } IP.Render( C, IPScreenPos, PlayerOwner ); } } // // Custom HUDs // static function DrawCustomHealthInfo( Canvas C, PlayerController PC, bool bSkaarj ) { local float XL, YL; local float XO, YO; local float HealthPct; local float ScaleX, ScaleY; local float myfPulse; if ( PC.Pawn != None ) HealthPct = FClamp( float(PC.Pawn.Health) / PC.Pawn.HealthMax, 0.f, 1.f ); else HealthPct = 0.f; ScaleX = PC.myHUD.ResScaleX * PC.myHUD.HUDScale; ScaleY = PC.myHUD.ResScaleY * PC.myHUD.HUDScale; // Ugly hack FIXME if ( HUD_Assault(PC.myHUD) != None ) myfPulse = HUD_Assault(PC.myHUD).fPulse; else myfPulse = 1.f; C.Style = ERenderStyle.STY_Alpha; XL = 256 * 0.5 * ScaleX; YL = 128 * 0.5 * ScaleY; // Team color overlay C.DrawColor = GetTeamColor( PC.GetTeamNum() ); C.SetPos( 0, C.ClipY - YL ); C.DrawTile(Texture'AS_FX_TX.HUD.SpaceHUD_Health_Grey', XL, YL, 0, 0, 256, 128); // Solid Background C.DrawColor = C.MakeColor(255, 255, 255); C.SetPos( 0, C.ClipY - YL ); if ( bSkaarj ) C.DrawTile(Texture'AS_FX_TX.HUD.SpaceHUD_Health_Solid_Skaarj', XL, YL, 0, 0, 256, 128); else C.DrawTile(Texture'AS_FX_TX.HUD.SpaceHUD_Health_Solid', XL, YL, 0, 0, 256, 128); // Health Bar XL = 80 * 0.5 * ScaleX; YL = 10 * 0.5 * ScaleY; XO = 147 * 0.5 * ScaleX; YO = C.ClipY - 20 * 0.5 * ScaleY; C.DrawColor = GetGYRColorRamp( HealthPct ); C.DrawColor.A = 96; C.SetPos( XO - XL*0.5, YO - YL*0.5 ); C.DrawTile(Texture'InterfaceContent.WhileSquare', XL*HealthPct, YL, 0, 0, 8, 8); // Health Icon XL = 64 * 0.5 * ScaleX; YL = 64 * 0.5 * ScaleY; XO = 114 * 0.5 * ScaleX; YO = C.ClipY - 62 * 0.5 * ScaleY; if ( HealthPct < 0.34 ) { C.DrawColor = C.DrawColor * myfPulse + C.MakeColor(255, 255, 255) * (1.f-myfPulse); C.DrawColor.A = 96; } C.SetPos( XO - XL*0.5, YO - YL*0.5 ); C.DrawTile(Texture'AS_FX_TX.HUD.SpaceHUD_HealthIcon', XL, YL, 0, 0, 64, 64); } function bool CustomHUDColorAllowed() { return false; } // // Helper // static function Color GetTeamColor( byte Team ) { if ( Team == 0 ) return default.HudColorRed; else if ( Team == 1 ) return default.HudColorBlue; else return default.GreenColor; } simulated function Color GetObjectiveColor( GameObjective GO, optional out byte bProgressPulsing ) { local Color ObjColor; ObjColor = GetTeamColor( GO.DefenderTeamIndex ); if ( GO.IsCritical() ) { ObjColor = ObjColor * (1-fPulse) + GoldColor * fPulse; } else if ( !GO.bOptionalObjective ) // Objective Progress Pulsing { if ( AttackerProgressUpdateTime > 0 ) { ObjColor = ObjColor * (1-fPulse) + WhiteColor * fPulse; bProgressPulsing = 1; } } return ObjColor; } /* returns Green (1.f) -> Yellow -> Red (0.f) Color Ramp */ static function Color GetGYRColorRamp( float Pct ) { local Color GYRColor; GYRColor.A = 255; if ( Pct < 0.34 ) { GYRColor.R = 128 + 127 * FClamp(3.f*Pct, 0.f, 1.f); GYRColor.G = 0; GYRColor.B = 0; } else if ( Pct < 0.67 ) { GYRColor.R = 255; GYRColor.G = 255 * FClamp(3.f*(Pct-0.33), 0.f, 1.f); GYRColor.B = 0; } else { GYRColor.R = 255 * FClamp(3.f*(1.f-Pct), 0.f, 1.f); GYRColor.G = 255; GYRColor.B = 0; } return GYRColor; } /* returns true if target is projected on visible canvas area */ static function bool IsTargetInFrontOfPlayer( Canvas C, Actor Target, out Vector ScreenPos, Vector CamLoc, Rotator CamRot ) { // Is Target located behind camera ? if ( (Target.Location - CamLoc) Dot vector(CamRot) < 0) return false; // Is Target on visible canvas area ? ScreenPos = C.WorldToScreen( Target.Location ); if ( ScreenPos.X <= 0 || ScreenPos.X >= C.ClipX ) return false; if ( ScreenPos.Y <= 0 || ScreenPos.Y >= C.ClipY ) return false; return true; } /* Clip Screen Coordinates to fit Canvas visible area */ static function ClipScreenCoords( Canvas C, out float X, out float Y, optional float XL, optional float YL ) { if ( X < XL ) X = XL; if ( Y < YL ) Y = YL; if ( X > C.ClipX - XL ) X = C.ClipX - XL; if ( Y > C.ClipY - YL ) Y = C.ClipY - YL; } /* Draws Brackets around an Actor's collision cylinder */ static function Draw_2DCollisionBox( Canvas C, Actor A, Vector ScrPos, String Description, float ColExpand, bool bSizeOverride ) { local vector TmpScrCorner[2], ScrCornerY[2], ScrCornerX[2]; local float XL, YL, X, Y, BXL, BYL; local vector CameraLocation; local rotator CameraRotation; C.GetCameraLocation( CameraLocation, CameraRotation ); C.Style = ERenderStyle.STY_Alpha; // Get Box Height... if ( CameraLocation.Z < A.Location.Z ) { ScrCornerY[0] = GetScreenCorner( C, A, Vect( 1, 0, 1), ScrPos, CameraRotation, ColExpand ); // Top Front ScrCornerY[1] = GetScreenCorner( C, A, Vect(-1, 0,-1), ScrPos, CameraRotation, ColExpand ); // Bottom Back } else { ScrCornerY[0] = GetScreenCorner( C, A, Vect(-1, 0, 1), ScrPos, CameraRotation, ColExpand ); // Top Back ScrCornerY[1] = GetScreenCorner( C, A, Vect( 1, 0,-1), ScrPos, CameraRotation, ColExpand ); // Bottom Front } // Get Width of box... TmpScrCorner[0] = GetScreenCorner( C, A, Vect( 0, 1, 1), ScrPos, CameraRotation, ColExpand ); // Left Top TmpScrCorner[1] = GetScreenCorner( C, A, Vect( 0, 1,-1), ScrPos, CameraRotation, ColExpand ); // Left Bottom ScrCornerX[0].X = Max( TmpScrCorner[0].X, TmpScrCorner[1].X ); TmpScrCorner[0] = GetScreenCorner( C, A, Vect( 0,-1, 1), ScrPos, CameraRotation, ColExpand ); // Right Top TmpScrCorner[1] = GetScreenCorner( C, A, Vect( 0,-1,-1), ScrPos, CameraRotation, ColExpand ); // Right Bottom ScrCornerX[1].X = Max( TmpScrCorner[0].X, TmpScrCorner[1].X ); // Description Text if ( Description != "" ) { C.StrLen(Description, XL, YL); // Description Clipping TmpScrCorner[0].X = ScrPos.X - ScrCornerX[0].X; TmpScrCorner[0].Y = ScrPos.Y - ScrCornerY[0].Y - YL; if ( TmpScrCorner[0].X < 0 ) TmpScrCorner[0].X = 0; if ( TmpScrCorner[0].X + XL > C.ClipX ) TmpScrCorner[0].X = C.ClipX - XL; if ( TmpScrCorner[0].Y < 0 ) TmpScrCorner[0].Y = 0; // Drawing Description C.SetPos(TmpScrCorner[0].X, TmpScrCorner[0].Y); C.DrawText(Description, false); } BXL = 16.f * C.SizeX / 640.f; BYL = 16.f * C.SizeY / 480.f; // Maximum BOX overlapping (skip drawing when too small) if ( ScrCornerX[0].X + ScrCornerX[1].X < BXL ) { if ( !bSizeOverride ) return; ScrCornerX[0].X = BXL*0.5; ScrCornerX[1].X = BXL*0.5; } if ( ScrCornerY[0].Y + ScrCornerY[1].Y < BYL ) { if ( !bSizeOverride ) return; ScrCornerY[0].Y = BYL*0.5; ScrCornerY[1].Y = BYL*0.5; } // Top left corner X = FMax( ScrPos.X - ScrCornerX[0].X, 0 ); Y = FMax( ScrPos.Y - ScrCornerY[0].Y, YL ); C.SetPos(X, Y); C.DrawTile(Material'AS_FX_TX.Icons.InfoBracket_FB', BXL, BYL, 0.f, 0.f, 32.f, 32.f); // Top right corner X = FMin( ScrPos.X + ScrCornerX[1].X - BXL, C.ClipX - BXL ); Y = FMax( ScrPos.Y - ScrCornerY[0].Y, YL ); C.SetPos(X, Y); C.DrawTile(Material'AS_FX_TX.Icons.InfoBracket_FB', BXL, BYL, 0.f, 0.f, -32.f, 32.f); // Bottom left corner X = FMax( ScrPos.X - ScrCornerX[0].X, 0 ); Y = FMin( ScrPos.Y + ScrCornerY[1].Y - BYL, C.ClipY - BYL ); C.SetPos(X, Y); C.DrawTile(Material'AS_FX_TX.Icons.InfoBracket_FB', BXL, BYL, 0.f, 0.f, 32.f, -32.f); // Bottom right corner X = FMin( ScrPos.X + ScrCornerX[1].X - BXL, C.ClipX - BXL ); Y = FMin( ScrPos.Y + ScrCornerY[1].Y - BYL, C.ClipY - BYL ); C.SetPos(X, Y); C.DrawTile(Material'AS_FX_TX.Icons.InfoBracket_FB', BXL, BYL, 0.f, 0.f, -32.f, -32.f); } /* Helper to get cylinder's "corners" (edges on projected canvas) */ static function vector GetScreenCorner( Canvas C, Actor A, Vector CornerVect, Vector IPScrO, Rotator CameraRotation, float ColExpand ) { local vector IPDir, IPCorner, IPScreenCorner; // Finding "corner's" 3D location... IPDir = -1 * Vector(CameraRotation); IPDir.Z = 0; // we just need the horizontal direction.. IPCorner = CornerVect >> Normalize( Rotator(IPDir) ); // Rotate vector to point to specified "corner"... // Expand by collision radius... IPCorner.X *= A.CollisionRadius * ColExpand; IPCorner.Y *= A.CollisionRadius * ColExpand; IPCorner.Z *= A.CollisionHeight * ColExpand; // Screen coordinates of IP's "corner" IPScreenCorner = C.WorldToScreen( A.Location + IPCorner ); IPScreenCorner.X = Abs( IPScreenCorner.X - IPScrO.X ); IPScreenCorner.Y = Abs( IPScreenCorner.Y - IPScrO.Y ); return IPScreenCorner; } /* return vector X, Y components of target orientation (on a 1 unit circle) */ final static function vector GetTargetOrientation( Actor Target, vector CamLoc, rotator CamRot ) { local vector X, Y, Z; local vector Orientation; local float Dist, DirY, DirZ; // Project onto Camera Y/Z plane GetAxes( CamRot, X, Y, Z ); DirY = Normal(Target.Location - CamLoc) Dot Normal(Y); DirZ = Normal(Target.Location - CamLoc) Dot Normal(Z); // Normalize vector (so it describes a 1 unit circle) Dist = Sqrt(DirY*DirY + DirZ*DirZ); Orientation.X = DirY / Dist; Orientation.Y = DirZ / Dist; return Orientation; } /* Expand normalized orientation to canvas' edges */ final static function vector ExpandTargetOrientationToCanvas( Canvas C, vector Orientation ) { local float Edge; // Find Canvas' edge if ( Abs(Orientation.X) > Abs(Orientation.Y) ) Edge = 1.f / Abs(Orientation.X); else if ( Abs(Orientation.X) < Abs(Orientation.Y) ) Edge = 1.f / Abs(Orientation.Y); Orientation.X = Orientation.X * Edge; Orientation.Y = Orientation.Y * Edge; return Orientation; } simulated function DrawTextWithBackground( Canvas C, String Text, Color TextColor, float XO, float YO ) { local float XL, YL, XL2, YL2; C.StrLen( Text, XL, YL ); XL2 = XL + 64 * ResScaleX; YL2 = YL + 8 * ResScaleY; C.DrawColor = C.MakeColor(0, 0, 0, 150); C.SetPos( XO - XL2*0.5, YO - YL2*0.5 ); C.DrawTile(Texture'HudContent.Generic.HUD', XL2, YL2, 168, 211, 166, 44); C.DrawColor = TextColor; C.SetPos( XO - XL*0.5, YO - YL*0.5 ); C.DrawText( Text, false ); } // // Misc HUD stuffs // simulated function Tick(float DeltaTime) { super.Tick( DeltaTime ); Global_Delta = DeltaTime; fBlink += DeltaTime; while ( fBlink > 0.5 ) fBlink -= 0.5; fPulse = Abs(1.f - 4*fBlink); if ( ASGRI == None && PlayerOwner.GameReplicationInfo != None ) ASGRI = ASGameReplicationInfo(PlayerOwner.GameReplicationInfo); if ( PawnOwner != None && PawnOwner.PlayerReplicationInfo != None ) ASPRI = ASPlayerReplicationInfo(PawnOwner.PlayerReplicationInfo); AttackerProgressUpdateTime = FMax(AttackerProgressUpdateTime - Global_Delta, 0); if ( ASGRI != None ) { ObjectiveProgress = ASGRI.ObjectiveProgress; if ( OldObjectiveProgress != ObjectiveProgress || CurrentObjective == None || !CurrentObjective.IsActive() ) { NotifyUpdatedObjective(); if ( OldObjectiveProgress != ObjectiveProgress ) OldObjectiveProgress = ObjectiveProgress; } } if ( PrevTeam != PlayerOwner.GetTeamNum() ) { TeamChanged(); PrevTeam = PlayerOwner.GetTeamNum(); } } simulated event TeamChanged() { bForceSpawnNotification = true; } simulated function DrawPracticeRoundInfo( Canvas C ) { local Color myColor; local float Seconds; if ( PlayerOwner == None || ASGRI == None || ScoreBoard == None || ASGRI.RoundTimeLimit == 0) return; C.Font = GetFontSizeIndex( C, 0 ); C.Style = ERenderStyle.STY_Alpha; myColor = GoldColor*(1.f-fPulse) + WhiteColor * fPulse; Seconds = Max(0, ASGRI.RoundTimeLimit-ASGRI.RoundStartTime+ASGRI.RemainingTime); if ( ASGRI.RoundWinner != ERW_None ) Seconds = ASGRI.RoundOverTime; DrawTextWithBackground( C, PracticeRoundString @ ScoreBoard.FormatTime(Seconds), myColor, C.ClipX*0.5, C.ClipY*0.67 ); } function CheckCountdown(GameReplicationInfo GRI) { local int RemainingRoundTime; if ( ASGRI == None ) { super.CheckCountdown( GRI ); return; } // Don't play time notifications when round has ended. if ( ASGRI.RoundWinner != ERW_None ) return; RemainingRoundTime = ASGRI.RoundTimeLimit - ASGRI.RoundStartTime + ASGRI.RemainingTime; if ( ASGRI.RoundTimeLimit == 0 ) // if RoundTimeLimit disabled, then announce global time limit super.CheckCountdown( ASGRI ); if ( (RemainingRoundTime < 1) || (RemainingRoundTime == OldRemainingRoundTime) || (ASGRI.RoundWinner != ERW_None) ) return; OldRemainingRoundTime = RemainingRoundTime; if ( OldRemainingRoundTime > 300 ) return; if ( OldRemainingRoundTime > 30 ) { if ( OldRemainingRoundTime == 300 ) PlayerOwner.QueueAnnouncement(LongCountName[0], 1); else if ( OldRemainingRoundTime == 180 ) PlayerOwner.QueueAnnouncement(LongCountName[1], 1); else if ( OldRemainingRoundTime == 120 ) PlayerOwner.QueueAnnouncement(LongCountName[2], 1); else if ( OldRemainingRoundTime == 60 ) PlayerOwner.QueueAnnouncement(LongCountName[3], 1); return; } if ( OldRemainingRoundTime == 30 ) PlayerOwner.QueueAnnouncement( LongCountName[4], 1 ); else if ( OldRemainingRoundTime == 20 ) PlayerOwner.QueueAnnouncement( LongCountName[5], 1, AP_InstantPlay ); else if ( (OldRemainingRoundTime <= 10) && (OldRemainingRoundTime > 0) ) PlayerOwner.QueueAnnouncement( CountDownName[OldRemainingRoundTime - 1], 1, AP_InstantOrQueueSwitch, 1 ); } simulated function String GetInfoString() { local string InfoString; //local int PTeam; if ( ASGRI == None ) return NoGameReplicationInfoString; if ( ASGRI.RoundWinner != ERW_None ) { return ASGRI.GetRoundWinnerString(); /* if ( ASGRI.IsPracticeRound() ) return class'ScoreBoard_Assault'.default.PracticeRoundOver; if ( PawnOwner == None ) PTeam = PlayerOwner.GetTeamNum(); else PTeam = PawnOwner.GetTeamNum(); if ( PTeam == ASGRI.RoundWinner ) InfoString = class'ScoreBoard_Assault'.default.YouWonRound; else InfoString = class'ScoreBoard_Assault'.default.YouLostRound; return InfoString; */ } if ( GUIController(PlayerOwner.Player.GUIController).ActivePage!=None) return AtMenus; if ( ASPRI != None && ASPRI.bAutoRespawn ) { InfoString = class'ScoreBoard_Assault'.default.AutoRespawn; InfoString = InfoString @ ASGRI.ReinforcementCountDown; return InfoString; } if ( ASGRI.ReinforcementCountDown > 0 && !PlayerOwner.IsInState('PlayerWaiting') ) { if ( PlayerOwner.IsDead() ) InfoString = class'ScoreBoard_Assault'.default.WaitForReinforcements; else InfoString = class'ScoreBoard_Assault'.default.WaitingToSpawnReinforcements; InfoString = InfoString @ ASGRI.ReinforcementCountDown; } else InfoString = super.GetInfoString(); return InfoString; } // debug to show current valid playerstarts exec function ShowSpawnAreas() { local NavigationPoint N; local PlayerStart PS; local PlayerSpawnManager PSM; log("=============="); log("ShowSpawnAreas"); log("=============="); // Log PlayerSpawmManagers foreach AllActors(class'PlayerSpawnManager', PSM) { log("PlayerSpawnManager:" @ PSM @ "bEnabled:" @ PSM.bEnabled @ "Tag:" @ PSM.Tag ); // log PlayerStarts if ( PSM.bEnabled ) for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) { PS = PlayerStart(N); if ( PS == None ) continue; if ( PS.TeamNumber == PSM.PlayerStartTeam ) log( " " @ PS ); } } log("=============="); log("End..........."); log("=============="); } simulated function UpdatePrecacheStaticMeshes() { super.UpdatePrecacheStaticMeshes(); Level.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.fX.ObjectiveArrow' ); } simulated function UpdatePrecacheMaterials() { super.UpdatePrecacheMaterials(); Level.AddPrecacheMaterial(Material'AS_FX_TX.Skins.Obj_3dArrow_Blue'); Level.AddPrecacheMaterial(Material'AS_FX_TX.Skins.Obj_3dArrow_Yellow'); Level.AddPrecacheMaterial(Material'AS_FX_TX.Skins.Obj_3dArrow_Red'); Level.AddPrecacheMaterial(Material'AS_FX_TX.HUD.OBJ_Status'); Level.AddPrecacheMaterial(Material'InterfaceContent.Menu.BorderBoxD'); Level.AddPrecacheMaterial(Material'ONSInterface-TX.HealthBar'); Level.AddPrecacheMaterial(Material'AS_FX_TX.Icons.ScoreBoard_Objective_Final'); Level.AddPrecacheMaterial(Material'AS_FX_TX.Icons.ScoreBoard_Objective_Single'); Level.AddPrecacheMaterial(Material'AS_FX_TX.Icons.InfoBracket'); Level.AddPrecacheMaterial(Material'AS_FX_TX.HUD.Objective_Primary_Indicator'); Level.AddPrecacheMaterial(Material'AS_FX_TX.HUD.Objective_Optional_Indicator'); } /* Called when viewing a Matinee cinematic */ simulated function DrawCinematicHUD( Canvas C ) { IntroTitleFade += Global_Delta; // Draw level title if ( IntroTitleFade < 10 ) DrawIntroTitle( C ); super.DrawCinematicHUD( C ); // Film Grain Overlay if ( !Level.IsSoftwareRendering() && Level.DetailMode > DM_LOW ) { C.SetPos(0,0); C.Style = ERenderStyle.STY_Alpha; C.DrawTile( Material'AssaultFilmGrain.FGfb', C.ClipX, C.ClipY, 0, 0, C.ClipX*0.67, C.ClipY*0.67); } } simulated function DrawIntroTitle( Canvas C ) { local int FontIndex; local String LevelTitle; local float XL, YL; C.DrawColor = WhiteColor; C.Style = ERenderStyle.STY_Alpha; FontIndex = 8; LevelTitle = Level.Title; do // make sure name is not too big { C.Font = GetFontSizeIndex( C, FontIndex-- ); C.TextSize( LevelTitle, XL, YL ); } until ( (XL < C.ClipX*0.67) && (YL < C.ClipY*0.67) ) if ( IntroTitleFade < 1 ) // Hidden C.DrawColor.A = 0; else if ( IntroTitleFade < 3 ) // fade in C.DrawColor.A = 255 * ((IntroTitleFade-1)*0.5); else if ( IntroTitleFade > 6 ) // fade out C.DrawColor.A = 255 * (1.f - ((IntroTitleFade-6)/4)); else C.DrawColor.A = 255; // normal C.SetPos( (C.ClipX-XL)*0.5, (C.ClipY-YL)*0.5 ); C.DrawText( LevelTitle, false ); } //============================================================================= // defaultproperties //============================================================================= }/s'//============================================================================== // GameObject_EnergyCore //============================================================================== // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================== class GameObject_EnergyCore extends GameObject; var localized string PlayerDroppedMessage, DroppedMessage, EnergyCorePickedUp, PlayerPickedUpEnergyCore, PlayerCoreReset; var name Announcer_EnergyCore_Dropped, Announcer_EnergyCore_PickedUp, Announcer_EnergyCore_Reset; var bool bSoundsPrecached; function bool CanBePickedUpBy(Pawn P) { return ( P.GetTeamNum() != Level.Game.GetDefenderNum() && !P.IsA('Vehicle') ); } function bool ValidHolder(Actor Other) { if ( super.ValidHolder( Other ) && Other.IsA('Pawn') ) return CanBePickedUpBy( Pawn(Other) ); return false; } function SetHolder(Controller C) { local Controller Ctrl; if ( C == None || C.Pawn == None ) return; for ( Ctrl=Level.ControllerList; Ctrl!=None; Ctrl=Ctrl.nextController ) if ( PlayerController(Ctrl) != None ) PlayerController(Ctrl).ReceiveLocalizedMessage(class'Message_PowerCore', 3, C.PlayerReplicationInfo ); super.SetHolder( C ); HomeBase.DisableObjective( C.Pawn ); } function ClearHolder() { super.ClearHolder(); } function Drop(vector newVel) { local Controller C; if ( Holder != None && Holder.PlayerReplicationInfo != None ) { for ( C=Level.ControllerList; C!=None; C=C.nextController ) if ( PlayerController(C) != None ) PlayerController(C).ReceiveLocalizedMessage(class'Message_PowerCore', 0, Holder.PlayerReplicationInfo ); } else { for ( C=Level.ControllerList; C!=None; C=C.nextController ) if ( PlayerController(C) != None ) PlayerController(C).ReceiveLocalizedMessage(class'Message_PowerCore', 1); } super.Drop( newVel ); } function HolderDied() { Drop( vect(0,0,0) ); } function LogReturned() { local Controller C; for ( C=Level.ControllerList; C!=None; C=C.nextController ) if ( PlayerController(C) != None ) PlayerController(C).ReceiveLocalizedMessage(class'Message_PowerCore', 4); } simulated function PrecacheAnnouncer(AnnouncerVoice V, bool bRewardSounds) { if ( !bRewardSounds && !bSoundsPrecached ) { bSoundsPrecached = true; V.PrecacheSound( Announcer_EnergyCore_Dropped ); V.PrecacheSound( Announcer_EnergyCore_PickedUp ); } } }/Q class FX_SpaceFighter_Trail_Red extends Emitter notplaceable; #exec OBJ LOAD FILE=AS_FX_TX.utx simulated function PreBeginPlay() { if ( Level.DetailMode == DM_Low ) { TrailEmitter(Emitters[0]).MaxPointsPerTrail = 100; } super.PreBeginPlay(); } simulated function SetBlueColor() { Emitters[0].Texture = Texture'AS_FX_TX.Trails.Trail_blue'; Emitters[1].ColorScale[0].Color = class'Canvas'.static.MakeColor(96, 160, 255); Emitters[1].ColorScale[1].Color = class'Canvas'.static.MakeColor(48, 128, 255); Emitters[1].ColorScale[2].Color = class'Canvas'.static.MakeColor(48, 128, 255); Emitters[2].ColorScale[1].Color = class'Canvas'.static.MakeColor(64, 112, 220); Emitters[2].ColorScale[2].Color = class'Canvas'.static.MakeColor(64, 112, 220); } }/ o1KOUl<9:t9:$0w * a * ae(i[-_9:t9:$ wK*;w *m"  KK   *;m"X#`m" m" K "b$K m" m"aK *KfK-_f-_ G}/L}/}/m"}/}/JEfA-_-E>-_ r *9:t9:$ae( G}/r1U&^h,- r* x#L//aA U&?-W+'w.U&*.U&d v&,x#10-W+-b&b x#a?( na wn*x#% neae(ASVehicleFactory::SpawnVehicle - Couldn't spawn vehicle9V G}/b class FX_SpaceFighter_Explosion_Directional extends FX_SpaceFighter_Explosion notplaceable; }/S//============================================================================= // FX_SpaceFighter_Explosion //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class FX_SpaceFighter_Explosion extends Emitter notplaceable; #exec OBJ LOAD FILE=ExplosionTex.utx #exec OBJ LOAD FILE=EpicParticles.utx #exec OBJ LOAD FILE=VMParticleTextures.utx var Sound ExplosionSound[11]; var byte bPlayed[11]; auto State Explosion { Begin: PlayUniqueRandomExplosion(); PlayUniqueRandomExplosion(); Sleep(0.33); PlayUniqueRandomExplosion(); } simulated function PlayUniqueRandomExplosion() { local int Num; Num = Rand(42) % 11; if ( bPlayed[Num] > 0 ) { // try again if already played this sound... PlayUniqueRandomExplosion(); return; } PlaySound(ExplosionSound[Num],, 4,, 1600); bPlayed[Num] = 1; } }/S Sc:~"^9:k&k$k9=yU9:k%9=9:$9:k[k G}/k}/}/Wclass FX_SpaceFighter_3rdpMuzzle extends Emitter notplaceable; #exec OBJ LOAD FILE=EpicParticles.utx simulated function SetRedColor() { Emitters[0].ColorScale[0].Color = class'Canvas'.static.MakeColor(200, 80, 48); } simulated function SetScale( float Scale ) { Emitters[0].StartSizeRange.X.Min = 75.f * Scale; Emitters[0].StartSizeRange.X.Max = Emitters[0].StartSizeRange.X.Min; } }/R[Ih#i-c'-_-r x#%:w * a *^-_9:t9:$ae(-c( G}/U9]$,-c -_ )r *^ G}/ VSu ge%iHS G}/Eclass FX_Minigun_ShellSpewer extends ShellSpewer notplaceable; }/d}/}/K//============================================================================= // FX_Laser_Blue //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class FX_Laser_Blue extends Emitter notplaceable; #exec OBJ LOAD FILE=AS_FX_TX.utx simulated function SetRedColor() { Emitters[0].ColorScale[0].Color = class'Canvas'.static.MakeColor(200, 80, 48); Emitters[0].ColorScale[1].Color = Emitters[0].ColorScale[0].Color; Emitters[1].ColorScale[0].Color = Emitters[0].ColorScale[0].Color; Emitters[1].ColorScale[1].Color = Emitters[0].ColorScale[0].Color; } simulated function SetScale( float Scale, optional float LengthScale ) { if ( LengthScale == 0.f ) LengthScale = 1.f; Emitters[0].StartSizeRange.X.Min = 150 * Scale; Emitters[0].StartSizeRange.X.Max = Emitters[0].StartSizeRange.X.Min; Emitters[0].StartLocationOffset.X = 150 * Scale * LengthScale; Emitters[1].StartLocationOffset.X = -120 - 30 * Scale * LengthScale; Emitters[1].StartSizeRange.X.Min = 30 * Scale; Emitters[1].StartSizeRange.X.Max = Emitters[1].StartSizeRange.X.Min; BeamEmitter(Emitters[1]).BeamEndPoints[0].Offset.X.Min = 600 * Scale * LengthScale; BeamEmitter(Emitters[1]).BeamEndPoints[0].Offset.X.Max = BeamEmitter(Emitters[1]).BeamEndPoints[0].Offset.X.Min; } }/d//============================================================================= // FM_Turret_Minigun_Fire //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class FM_Turret_Minigun_Fire extends InstantFire; function DoFireEffect() { local Vector StartTrace, HL, HN; local Rotator R; local Actor HitActor; if ( Instigator == None ) return; Instigator.MakeNoise(1.0); StartTrace = ASVehicle(Instigator).GetFireStart(); HitActor = ASVehicle(Instigator).CalcWeaponFire( HL, HN ); R = Rotator(Normal(HL-StartTrace) + VRand()*FRand()*Spread); DoTrace(StartTrace, R); } simulated function bool AllowFire() { return true; } //============================================================================= // defaultproperties //============================================================================= }/wclass FM_Turret_Minigun_AltFire extends WeaponFire; simulated function bool AllowFire() { return true; } }/}/k}/y F{!Ey /a9 k{A@{|n7FF{10 G}/S dJS |7F%J%|J7F7.Z g+.Z g+JFJFJ G}/O fwH+PO wM7F%F%MF7FFFHF G}/u//============================================================================= // DECO_SpaceFighter_Skaarj //============================================================================= class DECO_SpaceFighter_Skaarj extends DECO_SpaceFighter; #exec OBJ LOAD FILE=..\StaticMeshes\AS_Vehicles_SM.usx //============================================================================= // defaultproperties //============================================================================= }/h~b7P~M7F%K%MK7FKFbK GVj_ BlVzX $ff@}/}/t //============================================================================= // DECO_SpaceFighter //============================================================================= class DECO_SpaceFighter extends Decoration; #exec OBJ LOAD FILE=..\StaticMeshes\AS_Vehicles_SM.usx function Landed(vector HitNormal); function HitWall (vector HitNormal, actor Wall); function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType); singular function PhysicsVolumeChange( PhysicsVolume NewVolume ); function Trigger( actor Other, pawn EventInstigator ); singular function BaseChange(); function Bump( actor Other ); //============================================================================= // defaultproperties //============================================================================= }/k,AAUR9:9:$ wa AAa DF\ G}/~//============================================================================= // ASVehicle_SpaceFighter //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_SpaceFighter extends ASVehicle abstract config(User); // Movement var Quat SpaceFighterRotation; // Space Fighter actual rotation (using quaternions instead of rotators) var float YawAccel, PitchAccel, RollAccel; var float DesiredVelocity; // Range: EngineMinVelocity -> 1000 var() const float EngineMinVelocity; // minimum forward velocity var() const float VehicleRotationSpeed; var() const float RotationInertia; var() float StrafeAccel, StrafeAccelRate, MaxStrafe; var() float RollAutoCorrectSpeed; var bool bInitialized; // this to catch first tick when match is started and velocity reset (so ship would always have a rotation==(0,0,0)) var bool bPostNetCalled; var bool bGearUp; // Once flying animation is played var bool bSpeedFilterWarmup; var bool bAutoTarget; // automatically target closest Vehicle var bool bTargetClosestToCrosshair; var bool bRocketLoaded; var bool bHumanShip; var Rotator ShotDownRotation; var int TopGunCount; var name FlyingAnim; // Camera var Rotator LastCamRot; var float myDeltaTime; var float LastTimeSeconds; var float CamRotationInertia; // HUD var string DelayedDebugString; var localized string Text_Speed; // FX var Emitter TrailEmitter; var float TrailOffset; var Emitter SmokeTrail; var class ShotDownFXClass; // Engine Speed smooth filter (for velocity jerkyness on low and jerky FPS) const SpeedFilterFrames = 20; var float SpeedFilter[SpeedFilterFrames]; var int NextSpeedFilterSlot; var float SmoothedSpeedRatio; // Rockets var Vector RocketOffset; // Shield effect actors var class GenericShieldEffect[2]; var float NextShieldTime; // Target locking var Vehicle CurrentTarget; var float MaxTargetingRange; var float LastAutoTargetTime; var Vector CrosshairPos; var Sound TargetAcquiredSound; var Texture WeaponInfoTexture, SpeedInfoTexture; var Sound RocketLoadedSound; replication { reliable if ( bNetDirty && bNetOwner && Role==ROLE_Authority ) CurrentTarget; reliable if ( Role < ROLE_Authority ) ServerPrevTarget, ServerNextTarget, ServerSetTarget; } function BlowUp( vector HitNormal ); // Blow up space ship simulated function PostNetBeginPlay() { super.PostNetBeginPlay(); bPostNetCalled = true; PlayTakeOff(); if ( ASGameInfo(Level.Game) != None ) bThumped = ASGameInfo(Level.Game).DivertSpaceFighter(); } simulated function PlayTakeOff(); simulated event TeamChanged() { // Add Trail FX if ( Level.NetMode != NM_DedicatedServer ) { SetTrailFX(); AdjustFX(); } } simulated function SetTrailFX(); simulated function Destroyed() { if ( TrailEmitter != None ) TrailEmitter.Destroy(); if ( SmokeTrail != None ) SmokeTrail.Destroy(); super.Destroyed(); } function PossessedBy(Controller C) { super.PossessedBy(C); // Don't start at full speed Velocity = EngineMinVelocity * Vector(Rotation); Acceleration = Velocity; } function vector GetBotError(vector StartLocation) { local vector ErrorDir, VelDir; Controller.ShotTarget = Pawn(Controller.Target); ErrorDir = Normal((Controller.Target.Location - Location) Cross vect(0,0,1)); if ( Controller.Target != OldTarget ) { BotError = (1500 - 100 * Level.Game.GameDifficulty) * ErrorDir; OldTarget = Controller.Target; } VelDir = Normal(Controller.Target.Velocity); BotError += (100 - 200 *FRand()) * (ErrorDir + VelDir); if ( (Level.Game.GameDifficulty < 6) && (VSize(BotError) < 120) ) { if ( (BotError Dot VelDir) < 0 ) BotError += 10 * VelDir; else BotError -= 10 * VelDir; } if ( (Pawn(OldTarget) != None) && Pawn(OldTarget).bStationary ) BotError *= 0.6; BotError = Normal(BotError) * FMin(VSize(BotError), FMin(1500 - 100*Level.Game.GameDifficulty,0.2 * VSize(Controller.Target.Location - StartLocation))); return BotError; } simulated function ClientKDriverEnter(PlayerController PC) { super.ClientKDriverEnter( PC ); // Don't start at full speed Velocity = EngineMinVelocity * Vector(Rotation); Acceleration = Velocity; } // Called from the PlayerController when player wants to get out. function bool KDriverLeave( bool bForceLeave ) { if ( bForceLeave ) // Hack so you can't exit SpaceFighters with the "Use" Key. { if ( super.KDriverLeave( bForceLeave ) ) { if ( !bDeleteMe && !IsInState('Dying') ) Destroy(); } else return false; } else { TargetUnSet(); return false; } } function DriverDied() { TakeDamage(default.Health*2, Self, Location, vect(0,0,0), None); } // return false if out of range, can't see target, etc. function bool CanAttack(Actor Other) { // check that can see target if ( Controller != None ) return Controller.LineOfSightTo(Other); return false; } //============================================================================= // Movement //============================================================================= simulated function UpdateRocketAcceleration(float DeltaTime, float YawChange, float PitchChange) { local vector X,Y,Z; local float CurrentSpeed; local float EngineAccel; local float RotationSmoothFactor; local float RollChange; local Rotator NewRotation; if ( !bPostNetCalled || Controller == None ) return; if ( !bInitialized ) { // Laurent -- Velocity Override // When Player Spawns with the spaceship as Pawn, velocity is reset at start match // since Rotation is overwritten later by Rotator(Velocity), it gets reset to Rotation(0,0,0) // And therefore not using the one set in PlayerStart.Rotation Acceleration = EngineMinVelocity * Vector(Rotation); SpaceFighterRotation = QuatFromRotator( Rotation ); bInitialized = true; } // Only allow space fighter to change gear once landing gear is up. // (small hack for fins animations) if ( bGearUp ) DesiredVelocity = FClamp( DesiredVelocity+PlayerController(Controller).aForward*DeltaTime/15.f, EngineMinVelocity, 1000.f); else DesiredVelocity = EngineMinVelocity; CurrentSpeed = FClamp( (Velocity Dot Vector(Rotation)) * 1000.f / AirSpeed, 0.f, 1000.f); EngineAccel = (DesiredVelocity - CurrentSpeed) * 100.f; RotationSmoothFactor = FClamp(1.f - RotationInertia * DeltaTime, 0.f, 1.f); if ( PlayerController(Controller).bDuck > 0 && Abs(Rotation.Roll) > 500 ) { // Auto Correct Roll if ( Rotation.Roll < 0 ) RollChange = RollAutoCorrectSpeed; else RollChange = -RollAutoCorrectSpeed; } else if ( PlayerController(Controller).aUp > 0 ) // Rolling RollChange = PlayerController(Controller).aStrafe * 0.66; // Rotation Acceleration YawAccel = RotationSmoothFactor*YawAccel + DeltaTime*VehicleRotationSpeed*YawChange; PitchAccel = RotationSmoothFactor*PitchAccel + DeltaTime*VehicleRotationSpeed*PitchChange; RollAccel = RotationSmoothFactor*RollAccel + DeltaTime*VehicleRotationSpeed*RollChange; YawAccel = FClamp( YawAccel, -AirSpeed, AirSpeed ); PitchAccel = FClamp( PitchAccel, -AirSpeed, AirSpeed ); RollAccel = FClamp( RollAccel, -AirSpeed, AirSpeed ); // Perform new rotation GetAxes( QuatToRotator(SpaceFighterRotation), X, Y, Z ); SpaceFighterRotation = QuatProduct(SpaceFighterRotation, QuatProduct(QuatFromAxisAndAngle(Y, DeltaTime*PitchAccel), QuatProduct(QuatFromAxisAndAngle(Z, -1.0 * DeltaTime * YawAccel), QuatFromAxisAndAngle(X, DeltaTime * RollAccel)))); NewRotation = QuatToRotator( SpaceFighterRotation ); // If autoadjusting roll, clamp to 0 if ( PlayerController(Controller).bDuck > 0 && ((NewRotation.Roll < 0 && Rotation.Roll > 0) || (NewRotation.Roll > 0 && Rotation.Roll < 0)) ) { NewRotation.Roll = 0; RollAccel = 0; } Acceleration = Vector(NewRotation) * DesiredVelocity; // strafing StrafeAccel = RotationSmoothFactor*StrafeAccel; if ( PlayerController(Controller).aUp == 0 ) StrafeAccel += DeltaTime*StrafeAccelRate*PlayerController(Controller).aStrafe; StrafeAccel = FClamp( StrafeAccel, -MaxStrafe, MaxStrafe); GetAxes( NewRotation, X, Y, Z ); Acceleration += StrafeAccel * Y; // Adjust Rolling based on Stafing NewRotation.Roll += StrafeAccel * 15; DelayedDebugString = "NewRotation.Roll:" @ NewRotation.Roll @ "StrafeAccel:" @ StrafeAccel; // Take complete control on Rotation bRotateToDesired = true; bRollToDesired = true; DesiredRotation = NewRotation; SetRotation( NewRotation ); } function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if ( Role == Role_Authority ) { if ( !bPostNetCalled ) return; UpdateAutoTargetting(); // Hack when spacefighter gets stuck... kill!! if ( VSize(Velocity) < 100 ) TakeDamage(default.Health*2, Self, Location, vect(0,0,0), None); } } function DisplayDebug(Canvas Canvas, out float YL, out float YPos) { local vector X,Y,Z; local float ForwardVelocity; local Controller C; super.DisplayDebug(Canvas, YL, YPos); if ( Controller == None ) { Canvas.SetDrawColor(255,0,0); Canvas.DrawText("LOCAL CONTROLLER"); YPos += YL; Canvas.SetPos(4,YPos); C = Level.GetLocalPlayerController(); C.DisplayDebug(Canvas,YL,YPos); } Canvas.DrawText("-- SPACEFIGHTER"); YPos += YL; Canvas.SetPos(4,YPos); GetAxes(Rotation, X, Y, Z); Canvas.DrawText("-- GetAxes, X:"@String(X)$", Y:"@String(Y)$", Z:"@String(Z)); YPos += YL; Canvas.SetPos(4,YPos); Canvas.DrawText("-- Acceleration:"@String(Acceleration)); YPos += YL; Canvas.SetPos(4,YPos); // Debug stuffs ForwardVelocity = Velocity Dot Vector(Rotation); Canvas.DrawText("-- Gear:"@DesiredVelocity/10.0$"% Forward Velocity:"@String(ForwardVelocity)); YPos += YL; Canvas.SetPos(4,YPos); Canvas.DrawText("-- DDS"@DelayedDebugString); YPos += YL; Canvas.SetPos(4,YPos); } simulated function rotator GetViewRotation() { if ( IsLocallyControlled() && Health > 0 ) return QuatToRotator(SpaceFighterRotation); // true rotation else return Rotation; } simulated function SpecialCalcFirstPersonView(PlayerController PC, out actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) { local vector x, y, z; local rotator R; CameraLocation = Location; ViewActor = Self; R = GetViewRotation(); GetAxes(R, x, y, z); // First-person view. CameraRotation = Normalize(R + PC.ShakeRot); // amb CameraLocation = CameraLocation + PC.ShakeOffset.X * x + PC.ShakeOffset.Y * y + PC.ShakeOffset.Z * z; // Camera position is locked to vehicle CameraLocation = CameraLocation + (FPCamPos >> GetViewRotation()); } // Special calc-view for vehicles simulated function bool SpecialCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) { local vector CamLookAt, HitLocation, HitNormal; local PlayerController PC; local float CamDistFactor; local vector CamDistance; local Rotator CamRotationRate; local Rotator TargetRotation; PC = PlayerController(Controller); // Only do this mode if we have a playercontroller viewing this vehicle if ( PC == None || PC.ViewTarget == None ) return false; ViewActor = Self; if ( !PC.bBehindView ) // First Person View { SpecialCalcFirstPersonView( PC, ViewActor, CameraLocation, CameraRotation); return true; } // 3rd person view myDeltaTime = Level.TimeSeconds - LastTimeSeconds; LastTimeSeconds = Level.TimeSeconds; CamLookAt = ViewActor.Location + (Vect(60, 0, 0) >> ViewActor.Rotation); // Camera Rotation if ( ViewActor == Self ) // Client Hack to camera roll is not affected by strafing TargetRotation = GetViewRotation(); else TargetRotation = ViewActor.Rotation; if ( IsInState('ShotDown') ) // shotdown { TargetRotation.Yaw += 32768; Normalize( TargetRotation ); CamRotationInertia = default.CamRotationInertia * 10.f; CamDistFactor = 2.0; } else if ( IsInState('Dying') ) // dead { CamRotationInertia = default.CamRotationInertia * 50.f; CamDistFactor = 3.0; } else { CamDistFactor = 1 - (DesiredVelocity / AirSpeed); } CamRotationRate = Normalize(TargetRotation - LastCamRot); CameraRotation.Yaw = CalcInertia(myDeltaTime, CamRotationInertia, CamRotationRate.Yaw, LastCamRot.Yaw); CameraRotation.Pitch = CalcInertia(myDeltaTime, CamRotationInertia, CamRotationRate.Pitch, LastCamRot.Pitch); CameraRotation.Roll = CalcInertia(myDeltaTime, CamRotationInertia, CamRotationRate.Roll, LastCamRot.Roll); LastCamRot = CameraRotation; // Camera Location CamDistance = Vect(-180, 0, 80); CamDistance.X -= CamDistFactor * 200.0; // Adjust Camera location based on ship's velocity CameraLocation = CamLookAt + (CamDistance >> CameraRotation); if ( Trace( HitLocation, HitNormal, CameraLocation, ViewActor.Location, false, vect(10, 10, 10) ) != None ) CameraLocation = HitLocation + HitNormal * 10; return true; } // // Targeting // simulated function bool IsTargetRelevant( Vehicle Target ) { if ( Target == None ) return false; if ( Target.Team == Team || Target.Health < 1 || Target.bDeleteMe || VSize(Location - Target.Location) > MaxTargetingRange ) return false; // Target is located behind spacefighter if ( (Target.Location - Location) Dot vector(Rotation) < 0 ) return false; return true; } simulated function PrevWeapon() { ServerPrevTarget( false ); } simulated function NextWeapon() { ServerNextTarget( false ); } exec function TargetClosestToCrosshair() { bTargetClosestToCrosshair = true; //Flag it to be done next time we have a Canvas } function ServerNextTarget( bool bTryOnce ) { local float CurrentTargetDist, BestDist, Dist; local Controller C; local Vehicle V, BestV; local int numtargets; BestDist = MaxTargetingRange; if ( !IsTargetRelevant( CurrentTarget ) ) CurrentTarget = None; if ( CurrentTarget != None ) CurrentTargetDist = VSize(Location - CurrentTarget.Location); else CurrentTargetDist = 0; for (C = Level.ControllerList; C != None; C = C.NextController) { V = Vehicle(C.Pawn); if ( V != None && V != CurrentTarget && IsTargetRelevant( V ) ) { Dist = VSize(Location - V.Location); numtargets++; if ( Dist > CurrentTargetDist && Dist < BestDist && LineOfSightTo( V ) ) { BestV = V; BestDist = Dist; } } } if ( BestV != None ) ServerSetTarget( BestV ); else if ( !bTryOnce && CurrentTarget != None && numtargets>0 ) { CurrentTarget = None; ServerNextTarget( true ); } } function ServerPrevTarget( bool bTryOnce ) { local float CurrentTargetDist, BestDist, Dist; local Controller C; local Vehicle V, BestV; local int numtargets; if ( !IsTargetRelevant( CurrentTarget ) ) CurrentTarget = None; if ( CurrentTarget != None ) CurrentTargetDist = VSize(Location - CurrentTarget.Location); else CurrentTargetDist = MaxTargetingRange; for (C = Level.ControllerList; C != None; C = C.NextController) { V = Vehicle(C.Pawn); if ( V != None && V != CurrentTarget && IsTargetRelevant( V ) ) { numtargets++; Dist = VSize(Location - V.Location); if ( Dist < CurrentTargetDist && Dist > BestDist && LineOfSightTo( V ) ) { BestV = V; BestDist = Dist; } } } if ( BestV != None ) ServerSetTarget( BestV ); else if ( !bTryOnce && CurrentTarget != None && numtargets>0 ) { CurrentTarget = None; ServerPrevTarget( true ); } } /* Acquired a new Target */ function ServerSetTarget(Vehicle NewTarget) { if ( PlayerController(Controller) != None ) PlayerController(Controller).ClientPlaySound( TargetAcquiredSound ); CurrentTarget = NewTarget; bAutoTarget = false; } /* Erase current target, and turns on auto targetting */ function TargetUnSet() { CurrentTarget = None; bAutoTarget = true; } /* Lock closest visible enemy */ function UpdateAutoTargetting() { local float BestDist, Dist; local Controller C; local Vehicle V, BestV; if ( Role != ROLE_Authority ) return; // If player chosen target destroyed, begin autotargeting again if ( CurrentTarget == None || CurrentTarget.Health < 1 || CurrentTarget.bDeleteMe || VSize(CurrentTarget.Location - Location) > MaxTargetingRange ) { if ( CurrentTarget != None ) { PlayerController(Controller).ClientPlaySound( LockedOnSound ); CurrentTarget = None; } bAutoTarget = true; } // Only check target once per second to save CPU if ( !bAutoTarget || LastAutoTargetTime + 1 > Level.TimeSeconds ) return; LastAutoTargetTime = Level.TimeSeconds; if ( CurrentTarget == None ) BestDist = MaxTargetingRange; else BestDist = VSize(Location - CurrentTarget.Location); // Automatically target closest visible enemy vehicle for (C = Level.ControllerList; C != None; C = C.NextController) { V = Vehicle(C.Pawn); if ( V != None && V != CurrentTarget && IsTargetRelevant( V ) ) { Dist = VSize(Location - V.Location); if ( V.IsA('ASVehicle_SpaceFighter') ) // Target SpaceFighters first over turrets. Dist = Dist * 0.67; if ( (BestV == None || Dist < BestDist) && LineOfSightTo( V ) ) { BestV = V; BestDist = Dist; } } } if ( BestV != None ) ServerSetTarget( BestV ); } //============================================================================= // Collision //============================================================================= // dealing damage based on impact normal and vehicle velocity simulated function VehicleCollision(Vector HitNormal, Actor Other) { local float Damage; local float NormalSpeed; local Pawn Inst; if ( Role < Role_Authority ) return; NormalSpeed = Abs( Velocity Dot HitNormal ); Damage = (NormalSpeed-200) / 100.0; if ( Damage > 1.f ) { Damage *= Damage; Inst = Pawn(Other); // Force death with other Pawn's collision if ( Instigator != None ) Damage += HealthMax; TakeDamage(Damage, Inst, Location-HitNormal*CollisionRadius, HitNormal*Damage*100.f, None); } else if ( VSize(Velocity) < 100 ) TakeDamage(default.Health*2, Self, Location, vect(0,0,0), None); } simulated function Landed( vector HitNormal ) { VehicleCollision(HitNormal, None); } simulated function HitWall(vector HitNormal, actor Wall) { VehicleCollision(HitNormal, Wall); } simulated singular function Touch(Actor Other) { local Vector HitNormal; if ( Other!=None && !Other.IsA('Projectile') && Other.bBlockActors ) { HitNormal = Normal(Location - Other.Location); VehicleCollision(HitNormal, Other); } } simulated function Bump( Actor Other ) { local Vector HitNormal; if ( Other != None && !Other.IsA('Projectile') && Other.bBlockActors ) { HitNormal = Normal(Location - Other.Location); VehicleCollision(HitNormal, Other); } } function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( bHumanShip && (Level.NetMode != NM_Client) ) { if ( Level.NetMode == NM_Standalone ) { if ( (InstigatedBy != None) && (InstigatedBy != self) && (!bThumped || InstigatedBy.bStationary) && (PlayerController(Instigator.Controller) == None) && (PlayerReplicationInfo != None) && (Level.GetLocalPlayerController().PlayerReplicationInfo.Team != PlayerReplicationInfo.Team) ) Damage *= 0.3; } else if ( Deathmatch(Level.Game).bPlayersVsBots ) { if ( (InstigatedBy != None) && (InstigatedBy != self) && (PlayerController(Instigator.Controller) == None) ) Damage *= 0.7; } } // Using HitFxTicker to play various client side deaths... if ( instigatedBy == None ) HitFxTicker = 0; //TearOffDeath = Death_Geometry; // geometry collision else if ( instigatedBy == Self ) HitFxTicker = 1; //TearOffDeath = Death_Self; // suicide else HitFxTicker = 2; //TearOffDeath = Death_Pawn; // killed by player if ( Role == Role_Authority ) DoShieldEffect(HitLocation, Normal(Location - HitLocation) ); super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType); } //============================================================================= // FX //============================================================================= function DoShieldEffect(vector HitLocation, vector HitNormal) { local Actor ShieldEffect; if ( Team > 1 ) return; if ( EffectIsRelevant(HitLocation, true) && NextShieldTime < Level.TimeSeconds ) { NextShieldTime = Level.TimeSeconds + 0.1; ShieldEffect = Spawn(GenericShieldEffect[Team], Self,, HitLocation, rotator(-HitNormal)); if ( ShieldEffect != None ) ShieldEffect.SetBase( Self ); } } event AnimEnd( int Channel ) { Disable('AnimEnd'); bGearUp = true; if ( Level.NetMode != NM_DedicatedServer ) { if ( HasAnim(FlyingAnim) ) PlayAnim( FlyingAnim, 0.0001 ); StopAnimating(); Timer(); // Call Timer to adjust FX } } simulated function AdjustFX(); simulated function Timer() { local float NewTimerRate; // Adjust FX AdjustFX(); // Update Frequency (for Super High details) if ( IsLocallyControlled() ) NewTimerRate = 0.02; else if ( EffectIsRelevant(Location, false) ) // if this pawn is relevant to local player NewTimerRate = 0.04; else NewTimerRate = 0.08; // Not relevant if ( Level.DetailMode == DM_High ) // High details NewTimerRate += 0.02; else if ( Level.DetailMode == DM_Low ) // Low details NewTimerRate += 0.04; SetTimer(NewTimerRate, false); } simulated function Vector GetRocketSpawnLocation() { return RocketOffset; } simulated final function MyRandSpin(float spinRate) { DesiredRotation = RotRand(true); RotationRate.Yaw = 0; RotationRate.Pitch = Max( FRand()*SpinRate/8, SpinRate / 30 ); RotationRate.Roll = Max( FRand()*SpinRate, SpinRate / 8 ); if ( FRand() > 0.5 ) RotationRate.Pitch = -RotationRate.Pitch; if ( FRand() > 0.5 ) RotationRate.Roll = -RotationRate.Roll; } // Spawn Explosion FX simulated function Explode( vector HitLocation, vector HitNormal ) { if ( SmokeTrail != None ) { SmokeTrail.Kill(); SmokeTrail = None; } if ( TrailEmitter != None ) { TrailEmitter.Kill(); TrailEmitter = None; } bDynamicLight = false; LightType = LT_None; //if ( HitNormal != vect(0,0,0) ) // SetRotation( Rotator(-HitNormal) ); // Hack to position camera well.. if ( Level.NetMode != NM_DedicatedServer ) ExplosionEffect = Spawn(class'FX_SpaceFighter_Explosion', Self,, HitLocation, Rotation); } simulated event PlayDying(class DamageType, vector HitLoc) { local vector HitNormal; if ( Level.Game != None ) Level.Game.DiscardInventory( Self ); // Make sure player controller is actually possessing the vehicle.. (since we forced it in ClientKDriverEnter) if ( PlayerController(Controller) != None && PlayerController(Controller).Pawn != Self ) Controller = None; if ( PlayerController(Controller) != None ) { PlayerController(Controller).SetViewTarget( Self ); DestroyPrevController = Controller; } bCanTeleport = false; bReplicateMovement = false; bTearOff = true; bPlayedDeath = true; if ( HitFxTicker == 2 ) { ShotDownRotation = Rotation; if ( Level.NetMode != NM_DedicatedServer ) { SmokeTrail = Spawn(ShotDownFXClass, Self,, Location); if ( SmokeTrail != None ) SmokeTrail.SetBase( Self ); } GotoState('ShotDown'); } else { if ( HitFxTicker == 0 ) HitNormal = Normal( TearOffMomentum ); // Set Directional explosion based on HitNormal Explode( Location, HitNormal ); GotoState('Dying'); } } // // Shot down in flames // state ShotDown { ignores Trigger, HeadVolumeChange, PhysicsVolumeChange, Falling, BreathTimer; event ChangeAnimation() {} event StopPlayFiring() {} function PlayFiring(float Rate, name FiringMode) {} function PlayWeaponSwitch(Weapon NewWeapon) {} function PlayTakeHit(vector HitLoc, int Damage, class damageType) {} simulated function PlayNextAnimation() {} event FellOutOfWorld(eKillZType KillType) { } function ReduceCylinder() { } function LandThump() { } event AnimEnd(int Channel) { } function LieStill() {} singular function BaseChange() { } function Died(Controller Killer, class damageType, vector HitLocation) {} function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) {} function VehicleSwitchView(bool bUpdating) {} function DriverDied(); function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot); function UpdateRocketAcceleration(float DeltaTime, float YawChange, float PitchChange); simulated function Timer() { BlowUp( vect(0,0,0) ); } simulated function VehicleCollision(Vector HitNormal, Actor Other) { BlowUp( HitNormal ); } // Blow up Space Fighter simulated function BlowUp( vector HitNormal ) { Explode( Location, HitNormal ); GotoState('Dying'); } simulated function BeginState() { local PlayerController PC; // Set random spin rate... bRotateToDesired = true; bRollToDesired = true; MyRandSpin( 200000 ); Acceleration.Z -= VSize(Velocity)*0.67; //SetPhysics( PHYS_Falling ); PC = PlayerController(Controller); if ( PC != None && !PC.bBehindView ) PC.bBehindView = true;// Force Behindview if ( Driver != None && bDrawDriverInTP ) Destroyed_HandleDriver(); if ( Controller != None ) Controller.PawnDied( Self ); } simulated function EndState() { AmbientSound = None; bDynamicLight = false; LightType = LT_None; } Begin: SetTimer(4.0, false); } //============================================================================= // defaultproperties //============================================================================= }/G#//============================================================================= // ASVehicle_Sentinel_Floor //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel_Floor extends ASVehicle_Sentinel; static function StaticPrecache(LevelInfo L) { super.StaticPrecache( L ); L.AddPrecacheMaterial( Material'AS_Weapons_TX.Sentinels.FloorTurret' ); // Skins L.AddPrecacheMaterial( Material'AS_FX_TX.Beams.LaserTex' ); // Firing Effect L.AddPrecacheMaterial( Material'AS_FX_TX.Flares.Laser_Flare' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect L.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); L.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); L.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); L.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); L.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.FloorTurretSwivel' ); } simulated function UpdatePrecacheStaticMeshes() { Level.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.FloorTurretSwivel' ); super.UpdatePrecacheStaticMeshes(); } simulated function UpdatePrecacheMaterials() { Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Sentinels.FloorTurret' ); // Skins Level.AddPrecacheMaterial( Material'AS_FX_TX.Beams.LaserTex' ); // Firing Effect Level.AddPrecacheMaterial( Material'AS_FX_TX.Flares.Laser_Flare' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect Level.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); Level.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); Level.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); Level.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); super.UpdatePrecacheMaterials(); } }/S//============================================================================= // ASVehicle_Sentinel_Ceiling //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel_Ceiling extends ASVehicle_Sentinel; static function StaticPrecache(LevelInfo L) { super.StaticPrecache( L ); L.AddPrecacheMaterial( Material'AS_Weapons_TX.Sentinels.CeilingTurret' ); // Skins L.AddPrecacheMaterial( Material'AS_FX_TX.Beams.LaserTex' ); // Firing Effect L.AddPrecacheMaterial( Material'AS_FX_TX.Flares.Laser_Flare' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect L.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); L.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); L.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); L.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); } simulated function UpdatePrecacheMaterials() { Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Sentinels.CeilingTurret' ); // Skins Level.AddPrecacheMaterial( Material'AS_FX_TX.Beams.HotBolt_2' ); // Firing Effect Level.AddPrecacheMaterial( Material'AS_FX_TX.Flares.Laser_Flare' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect Level.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); Level.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); Level.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); Level.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); super.UpdatePrecacheMaterials(); } }/WB//============================================================================= // ASVehicle_Sentinel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel extends ASTurret abstract; Var bool bActive, bOldActive; var bool bSpawnCampProtection; // when true, sentinels are more powerful var Sound OpenCloseSound; Replication { reliable if ( (bNetInitial || bNetDirty) && Role==ROLE_Authority ) bActive; } simulated function PostNetBeginPlay() { super.PostNetBeginPlay(); if ( bSpawnCampProtection ) RotationRate *= 100; } simulated function PostNetReceive() { super.PostNetReceive(); if ( bActive != bOldActive ) { bOldActive = bActive; if ( bActive ) PlayOpening(); else PlayClosing(); } } /* awake sleeping sentinel */ function AwakeSentinel() { ASSentinelController(Controller).Awake(); } function bool Awake() { return false; } function bool GoToSleep() { return false; } simulated function PlayClosing(); simulated function PlayOpening(); simulated function PlayFiring(optional float Rate, optional name FiringMode ) { PlayAnim('Fire', 0.75); } simulated function PlayIdleOpened() { PlayAnim('IdleOpen', 1, 0.0); if ( Level.NetMode != NM_DedicatedServer ) { if ( TurretBase != None && TurretBase.Mesh != None ) TurretBase.GotoState('Active'); if ( TurretSwivel != None && TurretSwivel.Mesh != None ) TurretSwivel.GotoState('Active'); } } simulated function PlayIdleClosed() { PlayAnim('IdleClosed', 1, 0.0); if ( Level.NetMode != NM_DedicatedServer ) { if ( TurretBase != None && TurretBase.Mesh != None ) TurretBase.GotoState('Sleeping'); if ( TurretSwivel != None && TurretSwivel.Mesh != None ) TurretSwivel.GotoState('Sleeping'); } } auto state Sleeping { function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( Role == Role_Authority ) AwakeSentinel(); } simulated event AnimEnd( int Channel ) { PlayIdleClosed(); } function bool Awake() { if ( Role == Role_Authority ) bActive = true; PlayOpening(); return true; } simulated function PlayOpening() { PlayAnim('Open', 0.33, 0.0); if ( Level.NetMode != NM_DedicatedServer ) { if ( OpenCloseSound != None ) PlaySound( OpenCloseSound ); if ( TurretBase != None && TurretBase.Mesh != None ) TurretBase.GotoState('Opening'); if ( TurretSwivel != None && TurretSwivel.Mesh != None ) TurretSwivel.GotoState('Opening'); } GotoState('Opening'); } Begin: if ( bActive ) PlayOpening(); else PlayIdleClosed(); } state Active { simulated event AnimEnd( int Channel ) { PlayIdleOpened(); } function bool GoToSleep() { if ( Role == Role_Authority ) bActive = false; PlayClosing(); return true; } simulated function PlayClosing() { PlayAnim('Close', 0.33, 0.0); if ( Level.NetMode != NM_DedicatedServer ) { if ( OpenCloseSound != None ) PlaySound( OpenCloseSound ); if ( TurretBase != None && TurretBase.Mesh != None ) TurretBase.GotoState('Closing'); if ( TurretSwivel != None && TurretSwivel.Mesh != None ) TurretSwivel.GotoState('Closing'); } GotoState('Closing'); } Begin: PlayIdleOpened(); } state Closing { simulated event AnimEnd( int Channel ) { if ( Role == Role_Authority ) ASSentinelController(Controller).AnimEnded(); GotoState('Sleeping'); } function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType); } state Opening { simulated event AnimEnd( int Channel ) { if ( Role == Role_Authority ) ASSentinelController(Controller).AnimEnded(); GotoState('Active'); } function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType); } }/l#//============================================================================= // ASVehicleFactory_Turret // Specific factory for ASTurret (MotherShip Energy turrets) //============================================================================= class ASVehicleFactory_Turret extends ASVehicleFactory; var Array VTarray; function PostBeginPlay() { local Trigger_ASUseAndPossess VT; super.PostBeginPlay(); // Cache triggers used to possess Turret foreach DynamicActors(class'Trigger_ASUseAndPossess', VT) { if ( VT.PawnTag == VehicleTag ) VTarray[VTarray.Length] = VT; } } function VehicleSpawned() { local int i; super.VehicleSpawned(); // Assigned EntryTriggers to Turret... if ( VTarray.Length > 0 ) for (i=0; i 0 ) for (i=0; i 0 ) for (i=0; i 0 ) for (i=0; i 0 ) for (i=0; i 0 ) for (i=0; i`M"$?b:C#0.$5$B}/}/} //============================================================================= // ASVehicleFactory_SentinelCeiling // Specific factory for Ceiling Sentinels //============================================================================= class ASVehicleFactory_SentinelCeiling extends ASVehicleFactory; var() bool bSpawnCampProtection; // makes sentinels super strong function VehicleSpawned() { super.VehicleSpawned(); ASVehicle_Sentinel(Child).bSpawnCampProtection = bSpawnCampProtection; } //============================================================================= // defaultproperties //============================================================================= '{J2q @ f'5M7`]"$?b: #0.$5$B}/}/k //============================================================================= // ASVehicleFactory_MinigunTurret // Specific factory for Minigun Turret //============================================================================= class ASVehicleFactory_MinigunTurret extends ASVehicleFactory; var() name ObjectiveTag[6]; function VehicleSpawned() { local ASTurret T; local int i; Super.VehicleSpawned(); T = ASTurret(Child); if ( T == None ) return; for ( i=0; i<6; i++ ) T.ObjectiveTag[i] = ObjectiveTag[i]; } //============================================================================= // defaultproperties //============================================================================= 'CF2u @Dh!'5M7#`.$pB5$BB}/}/E//============================================================================= // ASVehicleFactory_LinkTurret //============================================================================= class ASVehicleFactory_LinkTurret extends ASVehicleFactory_Turret; //============================================================================= // defaultproperties //============================================================================= | Ex @FWL| 9@ d ]&%UT2k4AssaultFull.ASTurret_LinkTurret$>5$B}/}/v//============================================================================= // ASVehicleFactory //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= // Factory to spawn vehicles in Assault // - Supports startup or trigger spawning // - round reset // - respawn when killed // - progress respawn // - ON/OFF triggering // // Note: Assault factories can only spawn and handle a single vehicle at a time //============================================================================= class ASVehicleFactory extends SVehicleFactory placeable; var() bool bEnabled; var() bool bVehicleTeamLock; // Vehicle is locked to specific team. var() bool bEnter_TeamUnlocks; // When a player enters vehicle, it is unlocked. var() bool bHUDTrackVehicle; // If true, Vehicle will tracked on HUD. (For Objectives in Assault) var() bool bRespawnWhenDestroyed; // when vehicle is destroyed spawn a new one var() bool bSpawnProtected; var() bool bHighScoreKill; // vehicle is considered important and awards 5 points upon destruction var() bool bKeyVehicle; // Hint for AI to hunt down vehicle (when vehicle is considered an objective like in Glacier or Junkyard) var() bool bSpawnBuildEffect; var bool BACKUP_bEnabled; var bool bSoundsPrecached; var bool bResetting; var() byte VehicleTeam; var() enum EASVF_TriggeredFunction { EAVSF_ToggleEnabled, EAVSF_TriggeredSpawn, EAVSF_SpawnProgress, } TriggeredFunction; // published var() name VehicleTag; // Tag to set on vehicle (to use with possess triggers for example) var() name VehicleEvent; // Event to set on vehicle (triggered when vehicle is destroyed) var() name NextFactoryTag; // next Factory to enable with Spawn Progress... var() name VehiclePossessedEvent; var() String VehicleClassStr; var() float RespawnDelay; var() int VehicleHealth; // health vehicle gets (values <= 0 mean vehicle default) var() float VehicleDriverDamageMult; // multiplier to damage on vehicle's driver (applied to all positions vehicle has) var() float VehicleDamageMomentumScale; var() float VehicleLinkHealMult; var() Sound Announcement_Destroyed; var() byte VehicleAmbientGlow; var() float AIVisibilityDist; // AI Sight Radius // internal var Vehicle Child; var float SpawnDelay; // Spawn delay to avoid spawning vehicles during resetting... var ASVehicleFactory NextFactory; var() int MaxSpawnBlockCount; var int BlockCount; var Emitter BuildEffect; var class BuildEffectClass; var DestroyVehicleObjective MyDestroyVehicleObjective; simulated function PostBeginPlay() { if ( VehicleClass == None && VehicleClassStr != "" ) VehicleClass = class(DynamicLoadObject(VehicleClassStr, class'Class')); if ( Role == Role_Authority ) { if ( NextFactoryTag != '' ) ForEach AllActors(class'ASVehicleFactory', NextFactory, NextFactoryTag) break; BACKUP_bEnabled = bEnabled; // Should the vehicle spawn at startup ? if ( bEnabled && TriggeredFunction != EAVSF_TriggeredSpawn ) SetTimer(SpawnDelay, false); } } simulated function UpdatePrecacheMaterials() { if ( bSpawnBuildEffect ) { Level.AddPrecacheMaterial( Material'VMParticleTextures.buildEffects.PC_buildBorderNew' ); Level.AddPrecacheMaterial( Material'VMParticleTextures.buildEffects.PC_buildStreaks' ); } if ( VehicleClass == None && VehicleClassStr != "" ) VehicleClass = class(DynamicLoadObject(VehicleClassStr, class'Class')); if ( VehicleClass != None ) VehicleClass.static.StaticPrecache( Level ); super.UpdatePrecacheMaterials(); } simulated function UpdatePrecacheStaticMeshes() { if ( bSpawnBuildEffect ) Level.AddPrecacheStaticMesh( StaticMesh'VMStructures.CoreGroup.CoreShieldSM' ); super.UpdatePrecacheStaticMeshes(); } function bool SelfTriggered() { return true; } event Trigger( Actor Other, Pawn EventInstigator ) { local Vehicle AliveChild; if ( TriggeredFunction == EAVSF_TriggeredSpawn ) { // if Factory already has a child, destroy it... if ( Child != None ) { Child.Destroy(); Child = None; return; } // Spawn vehicle SetTimer(SpawnDelay, false); } else { if ( bEnabled && TriggeredFunction == EAVSF_SpawnProgress && NextFactory != None ) { // Spawn progress, we disable current vehicle factory and switch child to next one. if ( Child != None ) { AliveChild = Child; Child.ParentFactory = NextFactory; NextFactory.Child = Child; Child = None; // If vehicle left alone at initial spawn location, make it respawn at new spawn location. if ( AliveChild.IsVehicleEmpty() && (VSize(AliveChild.Location - Location) > VSize(AliveChild.Location - NextFactory.Location) || !FastTrace(NextFactory.Location, AliveChild.Location)) ) { AliveChild.Destroy(); NextFactory.Child = None; } } NextFactory.SetEnabled( !NextFactory.bEnabled ); } SetEnabled( !bEnabled ); } } function SetEnabled( bool bNewEnabled ) { bEnabled = bNewEnabled; if ( bEnabled && (Child == None) && (TriggeredFunction != EAVSF_TriggeredSpawn) ) { SetTimer(SpawnDelay, false); } } function ShutDown() { SetEnabled( false ); if ( Child != None ) { if ( Child.Driver != None ) Child.KDriverLeave( true ); if ( !Child.bDeleteMe && !Child.IsInState('Dying') ) Child.Destroy(); Child = None; } } function SpawnVehicle() { local Pawn P; local bool bBlocked; local Vehicle CreatedVehicle; if ( !Level.Game.bAllowVehicles || VehicleClass == None ) return; if ( BlockCount < MaxSpawnBlockCount ) { foreach CollidingActors(class'Pawn', P, VehicleClass.default.CollisionRadius * 1.5) { bBlocked = true; if ( PlayerController(P.Controller) != None ) PlayerController(P.Controller).ReceiveLocalizedMessage(class'Message_ASKillMessages', 2+BlockCount ); } if ( bBlocked ) { if ( bSpawnBuildEffect ) SpawnBuildEffect(); BlockCount++; SetTimer(1.5, false); //try again later return; } } CreatedVehicle = Spawn(VehicleClass,,, Location, Rotation); if ( CreatedVehicle != None ) { BlockCount = 0; Child = CreatedVehicle; VehicleSpawned(); } else { SetTimer(SpawnDelay, false); // try again log("ASVehicleFactory::SpawnVehicle - Couldn't spawn vehicle"@String(VehicleClass)); } } function SpawnBuildEffect() { local rotator YawRot; local int TeamNum; TeamNum = SetVehicleTeam(); YawRot = Rotation; YawRot.Roll = 0; YawRot.Pitch = 0; BuildEffect = Spawn(BuildEffectClass,,, Location, YawRot); } function VehicleSpawned() { local Vehicle V; // Make sure Vehicle is not destroyed when player exits if ( !Child.IsA('ASVehicle') ) { Child.bEjectDriver = true; // in Assault, force ejecting drivers when vehicle is destroyed Child.bSpawnProtected = true; // Force spawn protection on ONS vehicles in Assault } else Child.bSpawnProtected = bSpawnProtected; if ( VehicleTag != '' ) Child.Tag = VehicleTag; if ( VehicleEvent != '' ) Child.Event = VehicleEvent; if ( VehicleHealth < 1 ) VehicleHealth = Child.Health; Child.Health = VehicleHealth; Child.HealthMax = Child.Health; if ( VehicleAmbientGlow > 0 ) Child.AmbientGlow = VehicleAmbientGlow; Child.MomentumMult *= VehicleDamageMomentumScale; Child.DriverDamageMult *= VehicleDriverDamageMult; foreach Child.BasedActors(class'Vehicle', V) { V.DriverDamageMult *= VehicleDriverDamageMult; V.MomentumMult *= VehicleDamageMomentumScale; V.HealthMax = Child.HealthMax; } Child.LinkHealMult = VehicleLinkHealMult; Child.SetTeamNum( SetVehicleTeam() ); Child.PrevTeam = Child.Team; Child.bTeamLocked = bVehicleTeamLock; // Vehicle is locked to specific team. Child.bEnterringUnlocks = bEnter_TeamUnlocks; // When a player enters vehicle, it is unlocked. Child.ParentFactory = Self; Child.SightRadius = AIVisibilityDist; Child.bHUDTrackVehicle = bHUDTrackVehicle; Child.bKeyVehicle = bKeyVehicle; Child.bHighScoreKill = bHighScoreKill; Child.bNoFriendlyFire = bHighScoreKill || bKeyVehicle || bHUDTrackVehicle; if ( bHUDTrackVehicle || MyDestroyVehicleObjective != None ) Child.bAlwaysRelevant = true; if ( MyDestroyVehicleObjective != None ) MyDestroyVehicleObjective.VehicleSpawned( Child ); } function byte SetVehicleTeam() { local byte DefendingTeam; // Set to defenders by default if ( VehicleTeam > 1 ) VehicleTeam = 1; DefendingTeam = Level.Game.GetDefenderNum(); // Check Attackers if ( VehicleTeam == 0 ) return (1 - DefendingTeam); else return DefendingTeam; } function Reset() { bResetting = true; bEnabled = BACKUP_bEnabled; BlockCount = 0; // Force vehicle destruction at round reset if ( Child != None ) { Child.Destroy(); Child = None; } // Spawn at startup if ( bEnabled && TriggeredFunction != EAVSF_TriggeredSpawn ) SetTimer(SpawnDelay, false); bResetting = false; } function Timer() { if ( bResetting || !bEnabled ) return; // Spawn vehicle if ( Child == None ) SpawnVehicle(); } event VehiclePossessed( Vehicle V ) { TriggerEvent(VehiclePossessedEvent, Self, V); } event VehicleDestroyed( Vehicle V ) { local Controller C; Child = None; if ( !bEnabled || bResetting ) return; if ( Role == Role_Authority && Announcement_Destroyed != None ) { if ( Level.Game.IsA('ASGameInfo') ) ASGameInfo(Level.Game).QueueAnnouncerSound( Announcement_Destroyed.Name, 1, 255 ); else { for ( C = Level.ControllerList; C != None; C = C.NextController ) if ( PlayerController(C) != None ) PlayerController(C).PlayStatusAnnouncement(Announcement_Destroyed.Name, 1, true); } } if ( bRespawnWhenDestroyed ) SetTimer(RespawnDelay, false); } simulated function PrecacheAnnouncer(AnnouncerVoice V, bool bRewardSounds) { if ( !bRewardSounds && !bSoundsPrecached && (Announcement_Destroyed != None) ) { bSoundsPrecached = true; V.PrecacheSound(Announcement_Destroyed.Name); } } //============================================================================= // defaultproperties //============================================================================= }/p//============================================================================= // ASVehicle //============================================================================= // Base class for non Karma vehicles //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle extends Vehicle Abstract; #exec OBJ LOAD FILE=ONSInterface-TX.utx var() String DefaultWeaponClassName; // Default vehicle weapon class // This applies when players start game in vehicle without the "standard" possess procedure // FX var() Vector VehicleProjSpawnOffset; // Projectile Spawn Offset var Pawn DamLastInstigator; var float DamLastDamageTime; var Material DefaultCrosshair, CrosshairHitFeedbackTex; var float CrosshairScale; var bool bCHZeroYOffset; // For dual cannons, just trace from the center. var bool bCustomHealthDisplay; var float LastCalcWeaponFire; // avoid multiple traces the same tick var Actor LastCalcHA; var vector LastCalcHL, LastCalcHN; var() Sound LockedOnSound; var Controller DestroyPrevController; var Emitter ExplosionEffect, DebugFX; var vector BotError; var Actor OldTarget; // Function override function PlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class damageType, vector Momentum) {} function ClientDying(class DamageType, vector HitLocation) {} simulated function Tick(float DeltaTime); simulated event PostBeginPlay() { super.PostBeginPlay(); if ( Level.Game != None ) BotError = (1000 - 50 * Level.Game.GameDifficulty) * VRand(); // Hack to instance correctly the skeletal collision boxes GetBoneCoords(''); SetCollision(false, false); SetCollision(true, true); } simulated event Destroyed() { if ( Level.Game != None ) Level.Game.DiscardInventory( Self ); super.Destroyed(); } function AddDefaultInventory() { GiveWeapon( DefaultWeaponClassName ); if ( Controller != None ) Controller.ClientSwitchToBestWeapon(); } function PossessedBy(Controller C) { Level.Game.DiscardInventory( Self ); super.PossessedBy( C ); NetUpdateTime = Level.TimeSeconds - 1; bStasis = false; C.Pawn = Self; AddDefaultInventory(); if ( Weapon != None ) { Weapon.NetUpdateTime = Level.TimeSeconds - 1; Weapon.Instigator = Self; PendingWeapon = None; Weapon.BringUp(); } } function UnPossessed() { if ( Weapon != None ) { Weapon.PawnUnpossessed(); Weapon.ImmediateStopFire(); Weapon.ServerStopFire( 0 ); Weapon.ServerStopFire( 1 ); } NetUpdateTime = Level.TimeSeconds - 1; super.UnPossessed(); } event bool KDriverLeave( bool bForceLeave ) { local bool bLeft; local Pawn ExDriver; local Controller ExController; if ( Controller != None ) Controller.StopFiring(); ExController = Controller; ExDriver = Driver; bLeft = super.KDriverLeave( bForceLeave ); if ( bLeft && ExDriver != None && ExDriver.Weapon == None && ExController != None && ExController.Pawn == ExDriver ) ExController.SwitchToBestWeapon(); return bLeft; } simulated function ClientKDriverEnter( PlayerController PC ) { super.ClientKDriverEnter( PC ); // force controller here, because it's not replicated yet... PC.Pawn = Self; Controller = PC; SetOwner( PC ); if ( Weapon != None ) { PendingWeapon = None; Weapon.BringUp(); } else PC.SwitchToBestWeapon(); } simulated function ClientKDriverLeave(PlayerController PC) { if ( PC != None && Weapon != None ) Weapon.PawnUnpossessed(); super.ClientKDriverLeave( PC ); } simulated function bool StopWeaponFiring() { if ( Weapon == None ) return false; Weapon.PawnUnpossessed(); if ( Weapon.IsFiring() ) { if ( Controller != None ) { if ( !Controller.IsA('PlayerController') ) Weapon.ServerStopFire( Weapon.BotMode ); else { Controller.StopFiring(); Weapon.ServerStopFire( 0 ); Weapon.ServerStopFire( 1 ); } } else { Weapon.ServerStopFire( 0 ); Weapon.ServerStopFire( 1 ); } return true; } return false; } function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { local int actualDamage; local bool bAlreadyDead; local Controller Killer; if ( Role < ROLE_Authority ) { log(self$" client damage type "$damageType$" by "$instigatedBy); return; } if ( Level.Game == None ) return; // Spawn Protection: Cannot be destroyed by a player until possessed if ( bSpawnProtected && instigatedBy != None && instigatedBy != Self ) return; // Prevent multiple damage the same tick (for splash damage deferred by turret bases for example) if ( Level.TimeSeconds == DamLastDamageTime && instigatedBy == DamLastInstigator ) return; DamLastInstigator = instigatedBy; DamLastDamageTime = Level.TimeSeconds; if ( damagetype == None ) DamageType = class'DamageType'; Damage *= DamageType.default.VehicleDamageScaling; momentum *= DamageType.default.VehicleMomentumScaling * MomentumMult; bAlreadyDead = (Health <= 0); NetUpdateTime = Level.TimeSeconds - 1; // force quick net update if ( Weapon != None ) Weapon.AdjustPlayerDamage( Damage, InstigatedBy, HitLocation, Momentum, DamageType ); if ( (InstigatedBy != None) && InstigatedBy.HasUDamage() ) Damage *= 2; actualDamage = Level.Game.ReduceDamage(Damage, self, instigatedBy, HitLocation, Momentum, DamageType); if ( DamageType.default.bArmorStops && (actualDamage > 0) ) actualDamage = ShieldAbsorb( actualDamage ); if ( bShowDamageOverlay && DamageType.default.DamageOverlayMaterial != None && actualDamage > 0 ) SetOverlayMaterial( DamageType.default.DamageOverlayMaterial, DamageType.default.DamageOverlayTime, true ); Health -= actualDamage; if ( HitLocation == vect(0,0,0) ) HitLocation = Location; if ( bAlreadyDead ) return; PlayHit(actualDamage,InstigatedBy, hitLocation, damageType, Momentum); if ( Health <= 0 ) { if ( bRemoteControlled && Driver != None ) KDriverLeave( false ); // pawn died if ( instigatedBy != None ) Killer = instigatedBy.GetKillerController(); else if ( (DamageType != None) && DamageType.default.bDelayedDamage ) Killer = DelayedDamageInstigatorController; Health = 0; TearOffMomentum = momentum; Died(Killer, damageType, HitLocation); } else { if ( Controller != None ) Controller.NotifyTakeHit(instigatedBy, HitLocation, actualDamage, DamageType, Momentum); } MakeNoise(1.0); } // Spawn Explosion FX simulated function Explode( vector HitLocation, vector HitNormal ) { if ( Level.NetMode != NM_DedicatedServer ) ExplosionEffect = Spawn(class'FX_SpaceFighter_Explosion', Self,, HitLocation, Rotation); } simulated final function float CalcInertia(float DeltaTime, float FrictionFactor, float OldValue, float NewValue) { local float Friction; Friction = 1.f - FClamp( (0.02*FrictionFactor) ** DeltaTime, 0.f, 1.f); return OldValue*Friction + NewValue; } simulated event PlayDying(class DamageType, vector HitLoc) { Explode( Location, vect(0,0,1) ); if ( Level.Game != None ) Level.Game.DiscardInventory( Self ); // Make sure player controller is actually possessing the vehicle.. (since we forced it in ClientKDriverEnter) if ( PlayerController(Controller) != None && PlayerController(Controller).Pawn != Self ) Controller = None; if ( PlayerController(Controller) != None ) { if ( bDrawDriverInTP && Driver != None ) // view driver dying PlayerController(Controller).SetViewTarget( Driver ); else PlayerController(Controller).SetViewTarget( Self ); } bCanTeleport = false; bReplicateMovement = false; bTearOff = true; bPlayedDeath = true; GotoState('Dying'); } function name GetWeaponBoneFor(Inventory I) { return ''; } // explode state Dying { ignores Trigger, Bump, HitWall, HeadVolumeChange, PhysicsVolumeChange, Falling, BreathTimer; //simulated function PlayDying(class DamageType, vector HitLoc) {} event ChangeAnimation() {} event StopPlayFiring() {} function PlayFiring(float Rate, name FiringMode) {} function PlayWeaponSwitch(Weapon NewWeapon) {} function PlayTakeHit(vector HitLoc, int Damage, class damageType) {} simulated function PlayNextAnimation() {} event FellOutOfWorld(eKillZType KillType) { } function Landed(vector HitNormal) { } function ReduceCylinder() { } function LandThump() { } event AnimEnd(int Channel) { } function LieStill() {} singular function BaseChange() { } function Died(Controller Killer, class damageType, vector HitLocation) {} function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) {} function UpdateRocketAcceleration(float DeltaTime, float YawChange, float PitchChange) { } function VehicleSwitchView(bool bUpdating) {} function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot); function DriverDied(); simulated function Timer() { if ( !bDeleteMe ) Destroy(); } function BeginState() { local PlayerController PC, LocalPlayer; LocalPlayer = Level.GetLocalPlayerController(); AmbientSound = None; Velocity = vect(0,0,0); Acceleration = Velocity; bHidden = true; SetPhysics( PHYS_None ); SetCollision(false, false, false); // Make sure player controller is actually possessing the vehicle.. (since we forced it in ClientKDriverEnter) if ( PlayerController(Controller) != None && PlayerController(Controller).Pawn != Self ) Controller = None; // Clear previous controller if not currently viewing this vehicle. if ( PlayerController(DestroyPrevController) != None && PlayerController(DestroyPrevController).ViewTarget != Self ) DestroyPrevController = None; if ( PlayerController(Controller) != None ) PC = PlayerController(Controller); else if ( PlayerController(DestroyPrevController) != None ) PC = PlayerController(DestroyPrevController); // Force behind view if ( PC != None && !PC.bBehindView ) PC.bBehindView = true; if ( Driver != None && bDrawDriverInTP ) Destroyed_HandleDriver(); // If server, wait a second for replication if ( Level.NetMode == NM_DedicatedServer || Level.NetMode == NM_ListenServer ) SetTimer(1.f, false); else if ( (Driver == None || !bDrawDriverInTP) && ( (PC != None ) || (LocalPlayer != None && LocalPlayer.ViewTarget == Self) ) ) { // If owned by player, or spectated wait a bit so explosion can be viewed // (if there viewtarget is not already set on driver's dead body) if ( Controller != None ) { DestroyPrevController = Controller; Controller.SetRotation( Rotation ); Controller.PawnDied( Self ); DestroyPrevController.SetRotation( Rotation ); } else if ( DestroyPrevController != None ) { DestroyPrevController.SetRotation( Rotation ); DestroyPrevController.SetLocation( Location ); } SetTimer(5.f, false); } else { // if not owned and not spectated then destroy right away if ( Controller != None ) Controller.PawnDied( Self ); Destroy(); } } } // // HUD // simulated function DrawHUD(Canvas C) { local PlayerController PC; // Don't draw if player is dead... if ( Health < 1 || Controller == None || PlayerController(Controller) == None ) return; PC = PlayerController(Controller); DrawVehicleHUD( C, PC ); if ( !PC.MyHUD.bShowScoreboard ) { DrawWeaponInfo( C, PC.myHUD ); if ( bCustomHealthDisplay ) DrawHealthInfo( C, PC ); } } simulated function SpecialDrawCrosshair( Canvas C ) { local vector ScreenPos; local PlayerController PC; PC = PlayerController(Controller); // Don't draw if player is dead... if ( Health < 1 || PC == None || PC.MyHUD.bShowScoreboard ) return; DrawCrosshair( C, ScreenPos ); if ( WeaponHitsCrosshairsHL() ) DrawCrosshairAlignment( C, ScreenPos ); DrawEnemyName( C, HUDCDeathMatch(PC.myHUD) ); } simulated function DrawVehicleHUD( Canvas C, PlayerController PC ); simulated function DrawWeaponInfo( Canvas C, HUD H ); simulated function DrawHealthInfo( Canvas C, PlayerController PC ); simulated function bool DrawCrosshair( Canvas C, out vector ScreenPos ) { local vector HitLocation; local float RatioX, RatioY; local float tileX, tileY; local float SizeX, SizeY; HitLocation = GetCrosshairWorldLocation(); ScreenPos = C.WorldToScreen( HitLocation ); SizeX = DefaultCrosshair.MaterialUSize(); SizeY = DefaultCrosshair.MaterialVSize(); RatioX = C.SizeX / 640.0; RatioY = C.SizeY / 480.0; tileX = CrosshairScale * SizeX * RatioX; tileY = CrosshairScale * SizeY * RatioX; // Clip Crosshair position class'HUD_Assault'.static.ClipScreenCoords( C, ScreenPos.X, ScreenPos.Y, TileX*0.5, TileY*0.5 ); C.Style = ERenderStyle.STY_Alpha; C.DrawColor = class'Canvas'.static.MakeColor(255, 255, 255, 255); C.SetPos(ScreenPos.X - tileX*0.5, ScreenPos.Y - tileY*0.5); C.DrawTile( DefaultCrosshair, tileX, tileY, 0.0, 0.0, SizeX, SizeY); return true; } /* Check if weapon fires where crosshair is aiming at (because of offset between VehicleProjSpawnOffset and POV in 3rd person view) */ simulated function bool WeaponHitsCrosshairsHL() { local vector DesiredHL, DesiredHN, HL, HN; local Actor DesiredHitActor, HitActor; DesiredHitActor = CalcWeaponFire( DesiredHL, DesiredHN ); if ( DesiredHitActor == None ) return true; HitActor = PerformTrace( HL, HN, DesiredHL, GetFireStart() ); if ( HL == DesiredHL ) return true; return false; } /* Visual feedback that weapon will hit where crosshair is aiming at */ simulated function DrawCrosshairAlignment( Canvas C, Vector ScreenPos ) { local float RatioX, RatioY; RatioX = C.SizeX / 640.0; RatioY = C.SizeY / 480.0; C.DrawColor = C.MakeColor(0,255,0,192); C.Style = ERenderStyle.STY_Alpha; C.SetPos( ScreenPos.X - 16*RatioX, ScreenPos.Y - 16*RatioY ); C.DrawTile(CrosshairHitFeedbackTex, 32*RatioX, 32*RatioY, 0.0, 0.0, CrosshairHitFeedbackTex.MaterialUSize(), CrosshairHitFeedbackTex.MaterialVSize() ); } simulated function DrawEnemyName( Canvas C, HUDCDeathMatch H ) { local actor HitActor; local vector HitLocation, HitNormal; if ( H.bNoEnemyNames || (Controller == None) ) return; HitActor = CalcWeaponFire( HitLocation, HitNormal ); if ( Pawn(HitActor) != None && HitActor != Self && Pawn(HitActor).PlayerReplicationInfo != None && Team != Pawn(HitActor).GetTeamNum() ) { if ( (H.NamedPlayer != Pawn(HitActor).PlayerReplicationInfo) || (Level.TimeSeconds - H.NameTime > 0.5) ) { H.DisplayEnemyName(C, Pawn(HitActor).PlayerReplicationInfo); H.NameTime = Level.TimeSeconds; } H.NamedPlayer = Pawn(HitActor).PlayerReplicationInfo; } } //Notify vehicle that an enemy has locked on to it event NotifyEnemyLockedOn() { super.NotifyEnemyLockedOn(); if ( PlayerController(Controller) != None && LockedOnSound != None ) PlayerController(Controller).ClientPlaySound( LockedOnSound ); } /* Return world location of crosshair's == vehicle's focus point */ simulated function vector GetCrosshairWorldLocation() { return GetFireStart( 65536 ); // far focus point to ensure trace hit } /* Returns world location of vehicle fire start */ simulated function vector GetFireStart( optional float XOffset ) { local Vector StartOffset, X, Y, Z; GetAxes(Rotation, X, Y, Z); StartOffset = VehicleProjSpawnOffset; if ( bCHZeroYOffset ) StartOffset.Y = 0; return Location + X*(StartOffset.X+XOffset) + Y*StartOffset.Y + Z*StartOffset.Z; } function vector GetBotError(vector StartLocation) { Controller.ShotTarget = Pawn(Controller.Target); if ( Controller.Target != OldTarget ) { BotError = (1500 - 100 * Level.Game.GameDifficulty) * VRand(); OldTarget = Controller.Target; } BotError += 100 * VRand() + (100 - 200 *FRand()) * Normal(Controller.Target.Velocity); if ( (Pawn(OldTarget) != None) && Pawn(OldTarget).bStationary ) BotError *= 0.6; BotError = Normal(BotError) * FMin(VSize(BotError), FMin(1500 - 100*Level.Game.GameDifficulty,0.2 * VSize(Controller.Target.Location - StartLocation))); return BotError; } /* Trace from View to CrossHair, and return HitActor, HitLocation and HitNormal */ simulated function Actor CalcWeaponFire( out vector HitLocation, out Vector HitNormal ) { local vector Target, StartLocation, CannonLocation; local Actor A; local Rotator Rot; local vector X, Y, Z; local float Angle; // Avoid multiple traces the same tick if ( LastCalcWeaponFire == Level.TimeSeconds ) { //log("ASVehicle::CalcWeaponFire" @ Level.TimeSeconds ); HitLocation = LastCalcHL; HitNormal = LastCalcHN; return LastCalcHA; } CannonLocation = GetFireStart(); if ( PlayerController(Controller) != None ) { PlayerController(Controller).PlayerCalcView(A, StartLocation, Rot ); } else { StartLocation = CannonLocation; Rot = Rotation; } Target = GetCrosshairWorldLocation(); if ( Controller != None ) { if ( Controller.Target == None ) Controller.Target = Controller.Enemy; if ( Controller.Target != None ) Target += GetBotError(StartLocation); } A = PerformTrace( HitLocation, HitNormal, Target, StartLocation ); // Make sure Turret cannot hit something located behind it's Cannon. GetAxes(Rot, X, Y, Z); Angle = (HitLocation - CannonLocation) Dot X; if ( A == None || Angle < 0 ) { HitLocation = Target; HitNormal = vect(0,0,0); } // Save results, because can be called several times per tick LastCalcWeaponFire = Level.TimeSeconds; LastCalcHA = A; LastCalcHL = HitLocation; LastCalcHN = HitNormal; return A; } simulated function Actor PerformTrace( out vector HitLocation, out Vector HitNormal, vector End, vector Start ) { local Actor A; local bool bDriverBlockZeroExtent; // Trace through vehicle or driver bBlockZeroExtentTraces = false; if ( Driver != None ) { bDriverBlockZeroExtent = Driver.bBlockZeroExtentTraces; Driver.bBlockZeroExtentTraces = false; } A = Trace(HitLocation, HitNormal, End, Start, true); if ( A == None ) { HitLocation = End; HitNormal = vect(0,0,0); } bBlockZeroExtentTraces = true; if ( Driver != None ) Driver.bBlockZeroExtentTraces = bDriverBlockZeroExtent; return A; } static function StaticPrecache(LevelInfo L) { super.StaticPrecache( L ); L.AddPrecacheMaterial( default.NoEntryTexture ); L.AddPrecacheMaterial( default.TeamBeaconTexture ); L.AddPrecacheMaterial( default.TeamBeaconBorderMaterial ); L.AddPrecacheMaterial( default.CrosshairHitFeedbackTex ); L.AddPrecacheMaterial( default.DefaultCrosshair ); L.AddPrecacheMaterial( default.VehicleIcon.Material ); } simulated function UpdatePrecacheMaterials() { Level.AddPrecacheMaterial( default.NoEntryTexture ); Level.AddPrecacheMaterial( default.TeamBeaconTexture ); Level.AddPrecacheMaterial( default.TeamBeaconBorderMaterial ); Level.AddPrecacheMaterial( default.CrosshairHitFeedbackTex ); Level.AddPrecacheMaterial( default.DefaultCrosshair ); Level.AddPrecacheMaterial( VehicleIcon.Material ); super.UpdatePrecacheMaterials(); } //============================================================================= // defaultproperties //============================================================================= }/h //============================================================================= // ASTurret_Minigun_Swivel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASTurret_Minigun_Swivel extends ASTurret_Base; simulated function UpdateSwivelRotation( Rotator TurretRotation ) { local Rotator SwivelRotation; SwivelRotation = TurretRotation; SwivelRotation.Pitch = 0; SetRotation( SwivelRotation ); } //============================================================================= // defaultproperties //============================================================================= }/q//============================================================================= // ASTurret_Minigun_Base //============================================================================= class ASTurret_Minigun_Base extends ASTurret_Base; //============================================================================= // defaultproperties //============================================================================= }/z.//============================================================================= // ASTurret_Minigun //============================================================================= class ASTurret_Minigun extends ASTurret; function Pawn CheckForHeadShot(Vector loc, Vector ray, float AdditionalScale) { local vector X, Y, Z, newray; local float Angle, Side; GetAxes(Rotation, X, Y, Z); if ( Driver != None ) { // Remove the Z component of the ray newray = ray; newray.Z = 0; Angle = abs(newray dot X); Side = NewRay dot Y; if ( Angle < 0.7 && Side < 0 && Driver.IsHeadShot(loc, ray, AdditionalScale) ) // left return Driver; else if ( Angle < 0.82 && Side > 0 && Driver.IsHeadShot(loc, ray, AdditionalScale) ) // right return Driver; } return None; } static function StaticPrecache(LevelInfo L) { super.StaticPrecache( L ); L.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ASMinigun1' ); // Skins L.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ASMinigun2' ); L.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ChaingunTop' ); //L.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ChaingunTopALPHA' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect L.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); L.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); L.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); L.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); L.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); L.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.ASMinigun_Base' ); L.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.ASMinigun_Swivel' ); } simulated function UpdatePrecacheStaticMeshes() { Level.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.ASMinigun_Base' ); Level.AddPrecacheStaticMesh( StaticMesh'AS_Weapons_SM.ASMinigun_Swivel' ); super.UpdatePrecacheStaticMeshes(); } simulated function UpdatePrecacheMaterials() { Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ASMinigun1' ); // Skins Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ASMinigun2' ); Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ChaingunTop' ); //Level.AddPrecacheMaterial( Material'AS_Weapons_TX.Minigun.ChaingunTopALPHA' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp7_frames' ); // Explosion Effect Level.AddPrecacheMaterial( Material'EpicParticles.Flares.SoftFlare' ); Level.AddPrecacheMaterial( Material'AW-2004Particles.Fire.MuchSmoke2t' ); Level.AddPrecacheMaterial( Material'AS_FX_TX.Trails.Trail_red' ); Level.AddPrecacheMaterial( Material'ExplosionTex.Framed.exp1_frames' ); Level.AddPrecacheMaterial( Material'EmitterTextures.MultiFrame.rockchunks02' ); super.UpdatePrecacheMaterials(); } }/c"//============================================================================= // ASTurret_Base //============================================================================= class ASTurret_Base extends Actor Abstract; var float LastUpdateFreq; simulated event PostBeginPlay() { super.PostBeginPlay(); if ( bMovable || (Level.NetMode != NM_DedicatedServer && DrawType == DT_Mesh) ) SetTimer( 0.02 + FRand()*0.1, false); } simulated function UpdateSwivelRotation( Rotator TurretRotation ); function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { // Defer damage to Turret... if ( Owner.Role == Role_Authority && InstigatedBy != Owner ) { //log("ASTurret_Base::TakeDamage - Deferring damage to Pawn..."); Owner.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType) ; } } simulated event Timer() { local float UpdateFreq; UpdateFreq = 0.15; // hack to fix a hack :) if ( PlayerController(Vehicle(Owner).Controller) != None && PlayerController(Vehicle(Owner).Controller).ViewTarget != Owner ) Vehicle(Owner).Controller = None; if ( Vehicle(Owner).Controller == None || PlayerController(Vehicle(Owner).Controller) == None || !Vehicle(Owner).IsLocallyControlled() ) { if ( Level.NetMode != NM_DedicatedServer && DrawType == DT_Mesh ) UpdateOverlay(); if ( bMovable ) UpdateSwivelRotation( Owner.Rotation ); if ( EffectIsRelevant(Location, true) ) UpdateFreq = 0.02; else UpdateFreq = 0.1; if ( Level.bDropDetail || Level.DetailMode == DM_Low ) UpdateFreq += 0.02; } // else Update is performed every frame from ASTurret.UpdateRocketAcceleration() LastUpdateFreq = UpdateFreq; SetTimer( UpdateFreq, false ); } simulated function UpdateOverlay() { if ( Owner.OverlayMaterial != OverlayMaterial || Owner.OverlayTimer != OverlayTimer ) SetOverlayMaterial( Owner.OverlayMaterial, Owner.OverlayTimer, false ); } //============================================================================= // defaultproperties //============================================================================= }/b//============================================================================= // ASTurret //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASTurret extends ASVehicle abstract; // Static base var class TurretBaseClass; var ASTurret_Base TurretBase; var Rotator OriginalRotation; // Swivel (follows Turret's rotation Yaw only) var class TurretSwivelClass; var ASTurret_Base TurretSwivel; // Movement var float YawAccel, PitchAccel; var() const float RotationInertia; var() const Range RotPitchConstraint; // Min=0d,-90d Max=0d,+90d 16384=0d 0=90d var() const float RotationSpeed; var() vector CamAbsLocation, CamRelLocation, CamDistance; // Camera var Rotator LastCamRot; var float LastTimeSeconds; var() float CamRotationInertia; // Zooming var bool bZooming; var() float DesiredPlayerFOV, MinPlayerFOV, OldFOV, ZoomSpeed, ZoomWeaponOffsetAdjust; var material ZoomTick, ZoomTickTex; var Texture WeaponInfoTexture; var() name ObjectiveTag[6]; var array EntryTriggers; replication { reliable if ( bNetInitial && Role==ROLE_Authority) OriginalRotation; reliable if ( Role 8000) || !FastTrace(Objective.Location, Location) ) return false; } return true; } function float BotDesireability(Actor S, int TeamIndex, Actor Objective) { if ( !StronglyRecommended(S, TeamIndex, Objective) ) return 0; else if (Health <= 0 || Occupied() || (bTeamLocked && GetTeamNum() != TeamIndex)) return 0; return ((MaxDesireability * 0.5) + (MaxDesireability * 0.5 * (float(Health) / HealthMax))); } simulated function PrevWeapon() { ServerSwitchTurret( false ); } simulated function NextWeapon() { ServerSwitchTurret( true ); } function ServerSwitchTurret( bool bNextTurret ) { if ( ASVehicleFactory_Turret(ParentFactory) == None ) return; if ( bNextTurret ) ASVehicleFactory_Turret(ParentFactory).NextVehicle( Self ); else ASVehicleFactory_Turret(ParentFactory).PrevVehicle( Self ); } simulated event PostBeginPlay() { if ( Role == Role_Authority ) OriginalRotation = Rotation; // Save original Rotation to place client versions well... super.PostBeginPlay(); } function PossessedBy(Controller C) { local PlayerController PC; super.PossessedBy(C); PC = PlayerController(C); if ( PC != None ) PC.SetFOV( PC.DefaultFOV ); } simulated event PostNetBeginPlay() { // Static (non rotating) base if ( TurretBaseClass != None ) TurretBase = Spawn(TurretBaseClass, Self,, Location, OriginalRotation); // Swivel, rotates left/right (Yaw) if ( TurretSwivelClass != None ) TurretSwivel = Spawn(TurretSwivelClass, Self,, Location, OriginalRotation); super.PostNetBeginPlay(); } simulated function bool HasAmmo() { return true; } simulated event Destroyed() { if ( TurretBase != None ) TurretBase.Destroy(); if ( TurretSwivel != None ) TurretSwivel.Destroy(); super.Destroyed(); } simulated function UpdateRocketAcceleration(float DeltaTime, float YawChange, float PitchChange) { local int Pitch; local rotator NewRotation; if ( PlayerController(Controller) != None && PlayerController(Controller).bFreeCamera ) { PlayerController(Controller).UpdateRotation( DeltaTime, 0); return; } // Make sure Delta is not too big... if ( DeltaTime > 0.3 ) DeltaTime = 0.3; YawAccel = RotationInertia*YawAccel + DeltaTime*RotationSpeed*YawChange; PitchAccel = RotationInertia*PitchAccel + DeltaTime*RotationSpeed*PitchChange; Pitch = Rotation.Pitch & 65535; // Pitch constraint if ( (Pitch > 16384 - RotPitchConstraint.Max) && (Pitch < 49152 + RotPitchConstraint.Min) ) { if ( Pitch > 49152 - RotPitchConstraint.Min ) PitchAccel = Max(PitchAccel,0); else if ( Pitch < 16384 + RotPitchConstraint.Max ) PitchAccel = Min(PitchAccel,0); } NewRotation = Rotation; NewRotation.Yaw += YawAccel; NewRotation.Pitch += PitchAccel; SetRotation( NewRotation ); if ( IsLocallyControlled() ) { if ( TurretBase != None && TurretBase.DrawType == DT_Mesh ) TurretBase.UpdateOverlay(); if ( TurretSwivel != None ) { if ( TurretSwivel.DrawType == DT_Mesh ) TurretSwivel.UpdateOverlay(); TurretSwivel.UpdateSwivelRotation( NewRotation ); } } } // Special calc-view for vehicles simulated function bool SpecialCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) { local vector CamLookAt, HitLocation, HitNormal; local PlayerController PC; local float DeltaTime; local Rotator CamRotationRate; PC = PlayerController(Controller); // Only do this mode if we have a playercontroller viewing this vehicle if ( PC == None || PC.ViewTarget != self || PC.bFreeCamera ) return false; ViewActor = Self; if ( !PC.bBehindView ) // First Person View { SpecialCalcFirstPersonView( PC, ViewActor, CameraLocation, CameraRotation); return true; } // 3rd person view DeltaTime = Level.TimeSeconds - LastTimeSeconds; LastTimeSeconds = Level.TimeSeconds; CamLookAt = Location + CamAbsLocation + (CamRelLocation >> ViewActor.Rotation); // Camera Rotation CamRotationRate = Normalize(ViewActor.Rotation - LastCamRot); CameraRotation.Yaw = CalcInertia(DeltaTime, CamRotationInertia, CamRotationRate.Yaw, LastCamRot.Yaw); CameraRotation.Pitch = CalcInertia(DeltaTime, CamRotationInertia, CamRotationRate.Pitch, LastCamRot.Pitch); CameraRotation.Roll = 0; LastCamRot = CameraRotation; CameraLocation = CamLookAt + (CamDistance >> CameraRotation); if ( Trace( HitLocation, HitNormal, CameraLocation, CamLookAt, false, vect(10, 10, 10) ) != None ) CameraLocation = HitLocation + HitNormal * 10; return true; } simulated function SpecialCalcFirstPersonView(PlayerController PC, out actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) { local vector x, y, z; local rotator R; CameraLocation = Location; ViewActor = Self; R = GetViewRotation(); GetAxes(R, x, y, z); // First-person view. CameraRotation = Normalize(R + PC.ShakeRot); // amb CameraLocation = CameraLocation + PC.ShakeOffset.X * x + PC.ShakeOffset.Y * y + PC.ShakeOffset.Z * z; // Camera position is locked to vehicle CameraLocation = CameraLocation + (FPCamPos >> GetViewRotation()); } simulated function rotator GetViewRotation() { return Rotation; } simulated function PlayFiring(optional float Rate, optional name FiringMode ) { if ( FiringMode == '0' ) PlayAnim('FireR', 0.45); else PlayAnim('FireL', 0.45); } // Spawn Explosion FX simulated function Explode( vector HitLocation, vector HitNormal ) { super.Explode( HitLocation, Vect(0,0,1) ); // Overriding Explosion direction if ( TurretBase != None ) TurretBase.Destroy(); if ( TurretSwivel != None ) TurretSwivel.Destroy(); } simulated function DrawHealthInfo( Canvas C, PlayerController PC ) { class'HUD_Assault'.static.DrawCustomHealthInfo( C, PC, true ); } simulated function Actor PerformTrace( out vector HitLocation, out Vector HitNormal, vector End, vector Start ) { local Actor HitActor; // Disable base and swivel collision if ( TurretBase != None ) TurretBase.bBlockZeroExtentTraces = false; if ( TurretSwivel != None ) TurretSwivel.bBlockZeroExtentTraces = false; HitActor = super.PerformTrace(HitLocation, HitNormal, End, Start ); if ( TurretBase != None ) TurretBase.bBlockZeroExtentTraces = true; if ( TurretSwivel != None ) TurretSwivel.bBlockZeroExtentTraces = true; return HitActor; } simulated function bool DrawCrosshair( Canvas C, out vector ScreenPos ) { local float RatioX, RatioY; local float tileX, tileY; local float SizeX, SizeY; local float ZoomPct; local playercontroller pc; super.DrawCrosshair( C, ScreenPos ); PC = PlayerController(Controller); SizeX = ZoomTickTex.MaterialUSize(); SizeY = ZoomTickTex.MaterialVSize(); RatioX = C.SizeX / 640.0; RatioY = C.SizeY / 480.0; tileX = CrosshairScale * SizeX * RatioX; tileY = CrosshairScale * SizeY * RatioX; C.Style = ERenderStyle.STY_Additive; C.DrawColor = class'Canvas'.static.MakeColor(255, 255, 255); C.SetPos( ScreenPos.X - tileX, ScreenPos.Y - tileY ); C.DrawTile( ZoomTickTex, tileX*2,tileY*2, 0.0, 0.0, SizeX, SizeY); ZoomPct = 1-(PC.FOVAngle-MinPlayerFOV) / (PC.DefaultFOV - MinPlayerFOV); C.SetPos( ScreenPos.X - tileX, ScreenPos.Y - tileY ); TexRotator(ZoomTick).Rotation.Yaw = 32767 * ZoomPct; C.DrawTile( ZoomTick, tileX*2,tileY*2, 0.0, 0.0, SizeX, SizeY); PostZoomAdjust( ZoomPct ); return true; } simulated function PostZoomAdjust( float ZoomPct ) { // Fudge the weapon effects so they look right if ( !bDrawMeshInFP && Weapon != None ) Weapon.SmallViewOffset.X = Weapon.default.SmallViewOffset.X - (ZoomWeaponOffsetAdjust * ZoomPct); } simulated function RawInput(float DeltaTime, float aBaseX, float aBaseY, float aBaseZ, float aMouseX, float aMouseY, float aForward, float aTurn, float aStrafe, float aUp, float aLookUp) { local playerController PC; local float NewFOV; if ( PlayerController(Controller) != None ) { PC = PlayerController(Controller); if ( aForward!=0 ) { bZooming = true; if ( aForward>0 ) { if ( PC.FOVAngle > MinPlayerFOV ) NewFOV = PC.FOVAngle - ((PC.DefaultFOV - MinPlayerFOV)*DeltaTime*ZoomSpeed); else NewFOV = MinPlayerFOV; } else { if ( PC.FOVAngle < PC.DefaultFOV ) NewFOV = PC.FOVAngle + ((PC.DefaultFOV - MinPlayerFOV)*DeltaTime*ZoomSpeed); else NewFOV = PC.DefaultFOV; } } else bZooming = false; if ( bZooming ) PC.SetFOV( FClamp(NewFOV, MinPlayerFOV, PC.DefaultFOV) ); if ( OldFOV == 0 ) OldFOV = PC.FOVAngle; if ( OldFOV != PC.FOVAngle ) PlaySound(Sound'WeaponSounds.LightningGun.LightningZoomIn', SLOT_Misc,,,,,false); OldFOV = PC.FOVAngle; } super.RawInput(DeltaTime, aBaseX, aBaseY, aBaseZ, aMouseX, aMouseY, aForward, aTurn, aStrafe, aUp, aLookUp); } simulated function ClientKDriverEnter( PlayerController PC ) { OldFOV = PC.FOVAngle; super.ClientKDriverEnter( PC ); } static function StaticPrecache(LevelInfo L) { super.StaticPrecache( L ); L.AddPrecacheMaterial( default.ZoomTick ); L.AddPrecacheMaterial( default.ZoomTickTex ); } simulated function UpdatePrecacheMaterials() { Level.AddPrecacheMaterial( default.ZoomTick ); Level.AddPrecacheMaterial( default.ZoomTickTex ); super.UpdatePrecacheMaterials(); } //============================================================================= // defaultproperties //============================================================================= }/n_//============================================================================= // AssaultTeamAI //============================================================================= class ASTeamAI extends TeamAI; var SquadAI CurrentDefenseSquad; function CriticalObjectiveWarning(GameObjective G, Pawn NewEnemy) { local SquadAI S; for ( S=Squads; S!=None; S=S.NextSquad ) if ( S.SquadObjective == G ) S.CriticalObjectiveWarning(NewEnemy); } function GameObjective GetPriorityAttackObjectiveFor(SquadAI AttackSquad) { local GameObjective O, OldObjective; local float BestDist, R; local bool bSwitch; local SquadAI S; for ( O=Objectives; O!=None; O=O.NextObjective ) O.bIsBeingAttacked = false; for ( S=Squads; S!=None; S=S.NextSquad ) if ( (S != AttackSquad) && (S.SquadObjective != None) && (S.Size > 0) ) S.SquadObjective.bIsBeingAttacked = true; if ( AttackSquad != None ) PickedObjective = AttackSquad.SquadObjective; if ( (PickedObjective == None) || PickedObjective.bDisabled || !PickedObjective.bActive || (PickedObjective.DefenderTeamIndex == Team.TeamIndex) || !UnrealMPGameInfo(Level.Game).CanDisableObjective( PickedObjective ) ) { OldObjective = PickedObjective; PickedObjective = None; } BestDist = 800; for ( O=Objectives; O!=None; O=O.NextObjective ) { if ( !O.bDisabled && O.bActive && !O.bIgnoredObjective && (O.DefenderTeamIndex != Team.TeamIndex) && UnrealMPGameInfo(Level.Game).CanDisableObjective( O ) ) { if ( PickedObjective == None ) bSwitch = true; else if ( (OldObjective != None) && (VSize(O.Location - OldObjective.Location) < BestDist) ) bSwitch = true; else if ( O.bIsBeingAttacked ) { if ( !PickedObjective.bIsBeingAttacked || O.bOptionalObjective ) continue; else if ( PickedObjective.bOptionalObjective || (FRand() < 0.35) ) bSwitch = true; } else if ( PickedObjective.bIsBeingAttacked ) bSwitch = true; else { R = FRand(); if ( PickedObjective.bOptionalObjective ) { // sometimes skip optional objectives, but prioritize them at highest priority if ( PickedObjective.DefensePriority >= O.DefensePriority ) R *= 1.4; else R *= 0.6; } else if ( PickedObjective.DefensePriority > O.DefensePriority ) R *= 1.4; else if ( PickedObjective.DefensePriority < O.DefensePriority ) R *= 0.7; bSwitch = ( R < 0.3 ); } if ( bSwitch ) { PickedObjective = O; if ( OldObjective != None ) BestDist = VSize(O.Location - OldObjective.Location); } } } return PickedObjective; } function GameObjective GetLeastDefendedObjective() { local GameObjective O, Best; for ( O=Objectives; O!=None; O=O.NextObjective ) { if ( !O.bDisabled && O.bActive && !O.bIgnoredObjective && (O.DefenderTeamIndex == Team.TeamIndex) && UnrealMPGameInfo(Level.Game).CanDisableObjective(O) ) { if ( (O.DefenseSquad != None) && (O.DefenseSquad.SquadObjective != O) ) O.DefenseSquad = None; if ( Best == None ) Best = O; else if ( O.DefenseSquad == None ) { if ( (Best.DefenseSquad != None) || (!O.bOptionalObjective && (Best.DefensePriority > O.DefensePriority)) ) Best = O; } else if ( Best.DefenseSquad == None ) Best = Best; else if ( O.DefenseSquad.Size < Best.DefenseSquad.Size ) Best = O; else if ( Best.bOptionalObjective && (Best.DefenseSquad.Size >= Best.DefenseSquad.MaxSquadSize) ) Best = O; } } return Best; } /* SetOrders() Called when player gives orders to bot */ function SetOrders(Bot B, name NewOrders, Controller OrderGiver) { local TeamPlayerReplicationInfo PRI; PRI = TeamPlayerReplicationInfo(B.PlayerReplicationInfo); if ( HoldSpot(B.GoalScript) != None ) { PRI.bHolding = false; B.FreeScript(); } if ( NewOrders == 'Hold' ) { PRI.bHolding = true; PutBotOnSquadLedBy(OrderGiver,B); B.GoalScript = PlayerController(OrderGiver).ViewTarget.Spawn(class'HoldSpot'); if ( Vehicle(PlayerController(OrderGiver).ViewTarget) != None ) HoldSpot(B.GoalScript).HoldVehicle = Vehicle(PlayerController(OrderGiver).ViewTarget); if ( PlayerController(OrderGiver).ViewTarget.Physics == PHYS_Ladder ) B.GoalScript.SetPhysics(PHYS_Ladder); } else if ( NewOrders == 'Follow' ) { B.FreeScript(); PutBotOnSquadLedBy(OrderGiver,B); } else if ( NewOrders == 'Freelance' ) { PutOnFreelance(B); return; } } function bool PutOnDefense(Bot B) { local GameObjective O; O = GetLeastDefendedObjective(); if ( O != None ) { if ( O.DefenseSquad == None ) { O.DefenseSquad = AddSquadWithLeader(B, O); return true; } else if ( O.DefenseSquad.Size < O.DefenseSquad.MaxSquadSize ) { O.DefenseSquad.AddBot(B); return true; } } if ( (CurrentDefenseSquad == None) || (CurrentDefenseSquad.Size >= CurrentDefenseSquad.MaxSquadSize) ) CurrentDefenseSquad = AddSquadWithLeader(B,None); else CurrentDefenseSquad.AddBot(B); return true; } /* SetBotOrders - based on RosterEntry recommendations FIXME - need assault type pick leader when leader dies for attacking freelance squad - backs up defenders under attack, or joins in attacks */ function SetBotOrders(Bot NewBot, RosterEntry R) { local SquadAI HumanSquad; local name NewOrders; if ( Objectives == None ) SetObjectiveLists(); if ( (R != None) && R.RecommendSupport() ) NewOrders = 'FOLLOW'; else if ( Team.TeamIndex == ASGameInfo(Level.Game).CurrentAttackingTeam ) NewOrders = 'ATTACK'; else NewOrders = 'DEFEND'; // log(NewBot$" set Initial orders "$NewOrders); if ( (NewOrders == 'DEFEND') && PutOnDefense(NewBot) ) return; if ( NewOrders == 'ATTACK' ) { PutOnOffense(NewBot); return; } if ( NewOrders == 'FOLLOW' ) { // Follow any human player HumanSquad = AddHumanSquad(); if ( HumanSquad != None ) { HumanSquad.AddBot(NewBot); return; } } PutOnOffense(NewBot); } }/Aclass AssaultSquadAI extends SquadAI; var Pawn FocusPawn; var bool bVehicleEntriesInitialized; var array EntryTriggers; function Reset() { Super.Reset(); FocusPawn = None; } function bool ShouldSuppressEnemy(Bot B) { return ( (VSize(B.Pawn.Location - B.FocalPoint) > 300) && (Level.TimeSeconds - B.LastSeenTime < 8) ); } simulated function String GetOrderStringFor(TeamPlayerReplicationInfo PRI) { if ( (LeaderPRI != None) && !LeaderPRI.bBot ) { // FIXME - holding replication if ( PRI.bHolding ) return HoldString; return SupportString@LeaderPRI.PlayerName@SupportStringTrailer; } if ( bFreelance || (SquadObjective == None) ) return FreelanceString; else { GetOrders(); if ( CurrentOrders == 'defend' ) { if ( SquadObjective.Objective_Info_Defender != SquadObjective.Default.Objective_Info_Defender ) return SquadObjective.Objective_Info_Defender; return DefendString@SquadObjective.GetHumanReadableName(); } if ( CurrentOrders == 'attack' ) { if ( SquadObjective.Objective_Info_Attacker != SquadObjective.Default.Objective_Info_Attacker ) return SquadObjective.Objective_Info_Attacker; return AttackString@SquadObjective.GetHumanReadableName(); } } return string(CurrentOrders); } function bool NeverBail(Pawn P) { if ( Team.Size == 1 ) return false; if ( (Team.Size == 2) && P.bStationary ) return false; return true; } function float MaxVehicleDist(Pawn P) { if ( GetOrders() != 'Attack' ) return 3000; if ( SquadObjective == None ) return 8000; return FMin(8000, VSize(P.Location - SquadObjective.Location)); } function Vehicle GetKeyVehicle(Bot B) { local Vehicle V; if ( ASGameInfo(Level.Game).KeyVehicle != None ) return ASGameInfo(Level.Game).KeyVehicle; V = Vehicle(SquadLeader.Pawn); if ( (V != None) && V.bKeyVehicle ) ASGameInfo(Level.Game).KeyVehicle = V; if ( (V == None) || (B.Enemy == None) || V.bKeyVehicle ) return V; return None; } function Vehicle GetLinkVehicle(Bot B) { local Vehicle V; if ( (ASGameInfo(Level.Game).KeyVehicle != None) && B.SameTeamAs(ASGameInfo(Level.Game).KeyVehicle.Controller) ) return ASGameInfo(Level.Game).KeyVehicle; if ( (SquadObjective != None) && (SquadObjective.DefenderTeamIndex == Team.TeamIndex) && (DestroyVehicleObjective(SquadObjective) != None) && (DestroyVehicleObjective(SquadObjective).TargetVehicle != None) ) return DestroyVehicleObjective(SquadObjective).TargetVehicle; V = Vehicle(SquadLeader.Pawn); if ( V == None ) return None; if ( V.bKeyVehicle ) ASGameInfo(Level.Game).KeyVehicle = V; if ( (B.Enemy == None) || Vehicle(SquadLeader.Pawn).bKeyVehicle ) return Vehicle(SquadLeader.Pawn); return None; } function BotEnteredVehicle(Bot B) { if ( PlayerController(SquadLeader) == None ) PickNewLeader(); Super.BotEnteredVehicle(B); } // don't actually merge squads in assault function MergeWith(SquadAI S) { if ( SquadObjective != S.SquadObjective ) { SquadObjective = S.SquadObjective; NetUpdateTime = Level.Timeseconds - 1; } } function PickNewLeader() { local Bot B; for ( B=SquadMembers; B!=None; B=B.NextSquadMember ) if ( (Vehicle(B.Pawn) != None) && !B.Pawn.bStationary ) break; if ( B == None ) { // pick a leader that isn't out of the game for ( B=SquadMembers; B!=None; B=B.NextSquadMember ) if ( !B.PlayerReplicationInfo.bOutOfLives ) break; } if ( SquadLeader != B ) { SquadLeader = B; if ( SquadLeader == None ) LeaderPRI = None; else LeaderPRI = TeamPlayerReplicationInfo(SquadLeader.PlayerReplicationInfo); NetUpdateTime = Level.Timeseconds - 1; } } function bool AssignSquadResponsibility(Bot B) { local Trigger_ASUseAndRespawn T,Best; local float BestDist, NewDist; local int i; local Controller C; local class FocusPawnClass; if ( (SquadObjective == None) || SquadObjective.bDisabled || !SquadObjective.bActive || !UnrealMPGameInfo(Level.Game).CanDisableObjective( SquadObjective ) ) { Team.AI.FindNewObjectiveFor(self,true); if ( (SquadObjective == None) || SquadObjective.bDisabled || !SquadObjective.bActive ) { if ( (PlayerController(SquadLeader) != None) && (HoldSpot(B.GoalScript) == None) ) { if (CheckVehicle(B)) return true; return TellBotToFollow(B,SquadLeader); } if ( B.Enemy == None && !B.Pawn.bStationary ) { // suggest inventory hunt if ( B.FindInventoryGoal(0) ) { B.SetAttractionState(); return true; } } return false; } } if ( (Vehicle(B.Pawn) != None) && !B.Pawn.bStationary && Vehicle(B.Pawn).bKeyVehicle && (SquadObjective.DefenderTeamIndex != Team.TeamIndex) ) { if ( SquadObjective.bDisabled || !SquadObjective.bActive ) { B.GoalString = "Objective already disabled"; return false; } B.GoalString = "Disable Objective "$SquadObjective; return SquadObjective.TellBotHowToDisable(B); } // hack for getting into spacefighters if ( SquadObjective.bMustBoardVehicleFirst ) { if ( Vehicle(B.Pawn) == None ) { if ( Trigger_ASUseAndRespawn(B.RouteGoal) != None ) { if ( B.Pawn.ReachedDestination(B.RouteGoal) ) { Trigger_ASUseAndRespawn(B.RouteGoal).UsedBy(B.Pawn); B.GoalString = "Getting in vehicle"; return Super.AssignSquadResponsibility(B); } } else { if ( !bVehicleEntriesInitialized ) { bVehicleEntriesInitialized = true; ForEach DynamicActors(class'Trigger_ASUseAndRespawn', T) EntryTriggers[EntryTriggers.Length] = T; } for ( i=0; i T.LastFailTime ) { NewDist = VSize(B.Pawn.Location - T.Location); if ( (Best == None) || (NewDist < BestDist) ) { Best = T; BestDist = NewDist; } } } B.RouteGoal = Best; } if ( B.RouteGoal != None ) { B.MoveTarget = B.FindPathToward(B.RouteGoal, false); if ( B.MoveTarget != None ) { B.GoalString = "Move to vehicle entry trigger "$B.RouteGoal; B.SetAttractionState(); return true; } else { Trigger_ASUseAndRespawn(B.RouteGoal).LastFailTime = Level.TimeSeconds + 10; } } } else if ( B.Pawn.bThumped && (B.Enemy != None) && (ProximityObjective(SquadObjective) == None) ) return false; else if ( GetOrders() == 'Defend' ) { if ( B.Enemy == None ) { for ( i=0; i ObjectiveConstraintClass() { if ( DestroyableObjective(SquadObjective) != None ) return DestroyableObjective(SquadObjective).ConstraintPawnClass; if ( ProximityObjective(SquadObjective) != None ) return ProximityObjective(SquadObjective).ConstraintPawnClass; return None; } function bool MustKeepEnemy(Pawn E) { if ( (E.PlayerReplicationInfo != None) && (E.PlayerReplicationInfo.HasFlag != None) ) return true; if ( (SquadObjective != None) && SquadObjective.NearObjective(E) ) return true; if ( (Vehicle(E) != None) && Vehicle(E).bKeyVehicle ) return true; return false; } function byte PriorityObjective(Bot B) { if ( B.PlayerReplicationInfo.HasFlag != None ) return 2; if ( (Vehicle(B.Pawn) != None) && Vehicle(B.Pawn).bKeyVehicle ) return 2; return 0; } function float ModifyThreat(float current, Pawn NewThreat, bool bThreatVisible, Bot B) { local class FocusPawnClass; if ( GetOrders() == 'Defend' ) { FocusPawnClass = ObjectiveConstraintClass(); if ( (FocusPawnClass != None) && !ClassIsChildOf(NewThreat.Class,FocusPawnClass) ) return current - 0.5; } if ( bThreatVisible && (NewThreat.PlayerReplicationInfo != None) && ((NewThreat.PlayerReplicationInfo.HasFlag != None) || ((Vehicle(NewThreat) != None) && Vehicle(NewThreat).bKeyVehicle)) ) { if ( (VSize(B.Pawn.Location - NewThreat.Location) < 2500) || B.Pawn.Weapon.bSniping ) return current + 6; else return current + 1.5; } else if ( (SquadObjective != None) && (SquadObjective.DefenderTeamIndex == Team.TeamIndex) && (SquadObjective.MyBaseVolume != None) && NewThreat.IsInVolume(SquadObjective.MyBaseVolume) ) return current + 1.5; else if ( NewThreat.IsHumanControlled() ) return current + 0.5; else if ( NewThreat.bStationary && bThreatVisible ) return current + 0.3; else return current; } function name GetOrders() { bFreelanceAttack = true; return Super.GetOrders(); } function float AssessThreat( Bot B, Pawn NewThreat, bool bThreatVisible ) { local float ThreatValue, Dist; if ( (Vehicle(B.Pawn) == None) || !Vehicle(B.Pawn).bKeyVehicle ) return Super.AssessThreat(B, NewThreat, bThreatVisible); ThreatValue = 1; Dist = VSize(NewThreat.Location - B.Pawn.Location); if ( Dist < 4000 ) { ThreatValue += 0.2; if ( Dist < 2500 ) ThreatValue += 0.2; if ( Dist < 1500 ) ThreatValue += 0.2; if ( Dist < 1000 ) ThreatValue += 0.2; } if ( bThreatVisible ) ThreatValue += 3; if ( (NewThreat != B.Enemy) && (B.Enemy != None) ) { if ( !bThreatVisible ) ThreatValue -= 5; else if ( Level.TimeSeconds - B.LastSeenTime > 2 ) ThreatValue += 1; ThreatValue -= 0.5; } ThreatValue = ModifyThreat(ThreatValue,NewThreat,bThreatVisible,B); return ThreatValue; } }/Q//============================================================================= // ASOBJ_EnergyCore_Spawn //============================================================================= // Created by Laurent Delayen (C) 2003 Epic Games //============================================================================= class ASOBJ_EnergyCore_Spawn extends GameObjective placeable; var() Sound TakenSound; var GameObject_EnergyCore myFlag; var class FlagType; function BeginPlay() { super.BeginPlay(); SpawnFlag(); } function SpawnFlag() { myFlag = Spawn(FlagType, Self); if ( myFlag == None ) { warn(Self$" could not spawn flag of type '"$FlagType$"' at "$location); return; } else { myFlag.HomeBase = Self; ASGameReplicationInfo(Level.Game.GameReplicationInfo).GameObject = myFlag; } Spawn(class'XGame.xBombBase', Self,, Location-vect(0,0,60), Rotation); } function bool BotNearObjective(Bot B) { if ( !IsActive() || (myFlag == None) || (B==None) ) return false; if ( (MyBaseVolume != None) && myFlag.bHome && B.Pawn.IsInVolume(MyBaseVolume) ) return true; return ( (VSize(myFlag.Position().Location - B.Pawn.Location) < 2000) && B.LineOfSightTo(myFlag.Position()) ); } function bool BetterObjectiveThan(GameObjective Best, byte DesiredTeamNum, byte RequesterTeamNum) { if ( !IsActive() || myFlag==None || !myFlag.bHome || (RequesterTeamNum == DesiredTeamNum) ) return false; return true; } /* Need a work around for clients... simulated function bool IsActive() { if ( super.IsActive() ) return ( myFlag != None && myFlag.bHome ); return false; } */ function Reset() { super.Reset(); if ( MyFlag != None ) { if ( MyFlag.Holder != None ) MyFlag.ClearHolder(); MyFlag.Destroy(); } SpawnFlag(); } _Gb@2`بؚ+++++|h+ʁ)|h|++3}ZsGp  e DIFHu tp!t ^J]Energy Core Spawng! eL u  }BCE%JG$CH$@" SY$@@f.$pB5$pBV] }/}/h#//============================================================================= // ASOBJ_EnergyCore_Delivery //============================================================================= // Created by Laurent Delayen (C) 2003 Epic Games //============================================================================= class ASOBJ_EnergyCore_Delivery extends ProximityObjective; #exec OBJ LOAD FILE=AnnouncerAssault.uax var GameObject_EnergyCore EC; function bool IsRelevant( Pawn Instigator, bool bAliveCheck ) { Local PlayerReplicationInfo PRI; PRI = Instigator.PlayerReplicationInfo; if ( super.IsRelevant( Instigator, bAliveCheck ) && (PRI != None) && (PRI.HasFlag != None) && PRI.HasFlag.IsA('GameObject_EnergyCore') ) return true; return false; } /* triggered by intro cinematic to auto complete objective */ function CompleteObjective( Pawn Instigator ) { super.DisableObjective( Instigator ); } function DisableObjective(Pawn Instigator) { local PlayerReplicationInfo PRI; local GameObject_EnergyCore EnergyCore; PRI = Instigator.PlayerReplicationInfo; if ( !IsActive() || PRI == None || PRI.HasFlag == None || !PRI.HasFlag.IsA('GameObject_EnergyCore') ) return; EnergyCore = GameObject_EnergyCore(PRI.HasFlag); EnergyCore.ClearHolder(); EnergyCore.Destroy(); super.DisableObjective( Instigator ); } /* TellBotHowToDisable() tell bot what to do to disable me. return true if valid/useable instructions were given */ function bool TellBotHowToDisable(Bot B) { if ( B.PlayerReplicationInfo.HasFlag != None ) { if ( EC == None ) EC = GameObject_EnergyCore(B.PlayerReplicationInfo.HasFlag); B.GoalString = "Take Energy Core to vehicle"; return B.Squad.FindPathToObjective(B,self); } if ( EC == None ) { ForEach DynamicActors(class'GameObject_EnergyCore', EC) break; if ( EC == None ) { log("NO ENERGY CORE"); return false; } } if ( EC.Holder != None ) { B.GoalString = "Protect Energy Core holder"; if ( VSize(EC.Holder.Location - B.Pawn.Location) < 1200 ) return false; return B.Squad.FindPathToObjective(B,EC.Holder); } B.GoalString = "Go pick up Energy Core"; return B.Squad.FindPathToObjective(B,EC); } aj1{ @!2 b,h 7|zVGB|zVGB||\fF+|+n|h|\fF+||\fFhzVGBzVGB?4zVGB++hzVGBzVGB?4 e DIFH^J]Energy Core Deliverye L u  }/}/kclass ASMutator extends DMMutator HideDropDown CacheExempt; function bool IsRelevant(Actor Other, out byte bSuperRelevant) { if ( Other.IsA('AdrenalinePickup') ) { bSuperRelevant = 0; return false; } if ( Controller(Other) != None && MessagingSpectator(Other) == None ) { Controller(Other).bAdrenalineEnabled = false; Controller(Other).PlayerReplicationInfoClass = class'ASPlayerReplicationInfo'; } return Super.IsRelevant(Other, bSuperRelevant); } cm~ 6dr_ 2ʁ),e,e e b`DIFH}/}//class ASMapList extends MapList config; eB 6go cH b`DIFH}/}/TP//============================================================================= // ASGameReplicationInfo. //============================================================================= class ASGameReplicationInfo extends GameReplicationInfo; var int RoundTimeLimit; // in seconds, unlike ASGameInfo.RoundTimeLimit which is in minutes var int RoundStartTime, CurrentRound, MaxRounds, ReinforcementCountDown, PracticeTimeLimit; var bool bTeamZeroIsAttacking; // true when Red Team is Attacking var int RoundOverTime; // time set when round is over (so all clients show the same time) var int MaxTeleportTime; // Objective Progress // Shown on HUD, and on briefing screen... var byte ObjectiveProgress, MaxObjectivePriority; var GameObjective Objectives; var GameObject GameObject; enum ERoundWinner { ERW_None, ERW_PracticeRoundEnded, ERW_RedAttacked, ERW_BlueAttacked, ERW_RedDefended, ERW_BlueDefended, ERW_RedMoreObjectives, ERW_BlueMoreObjectives, ERW_RedMoreProgress, ERW_BlueMoreProgress, ERW_RedGotSameOBJFaster, ERW_BlueGotSameOBJFaster, ERW_Draw, }; var ERoundWinner RoundWinner; var localized String ERW_PracticeRoundEndedStr, ERW_RedAttackedStr, ERW_BlueAttackedStr, ERW_RedDefendedStr, ERW_BlueDefendedStr; var localized String ERW_DefendersStr, ERW_AttackersStr, ERW_RedMoreObjectivesStr, ERW_BlueMoreObjectivesStr; var localized String ERW_RedMoreProgressStr, ERW_BlueMoreProgressStr, ERW_RedGotSameOBJFasterStr, ERW_BlueGotSameOBJFasterStr; var localized String ERW_DrawStr; replication { reliable if ( bNetDirty && (Role == ROLE_Authority) ) RoundStartTime, CurrentRound, bTeamZeroIsAttacking, ObjectiveProgress, ReinforcementCountDown, RoundWinner, GameObject, RoundTimeLimit, RoundOverTime; reliable if ( bNetInitial && (Role==ROLE_Authority) ) MaxRounds; } simulated function PreBeginPlay() { super.PreBeginPlay(); SecondCount = Level.TimeSeconds; SetTimer(1, true); } simulated function PostNetBeginPlay() { super.PostNetBeginPlay(); SetupAssaultObjectivePriority(); } /* Converts default objective DefensePriority ordering (downwards) to ordered upwards (without gaps) for easier handling 0 is the first objective, 1 the second and so on... */ simulated function SetupAssaultObjectivePriority() { local GameObjective GO, BestGO, NextBestGO; local byte CurrentPriority; log("## ASGRI::SetupAssaultObjectivePriority"); // Caching GameObjectives foreach AllActors(class'GameObjective', GO) { if ( GO.bBotOnlyObjective ) // ignore bot only objectives { GO.ObjectivePriority = 255; continue; } if ( BestGO == None || GO.DefensePriority > BestGO.DefensePriority ) BestGO = GO; } if ( BestGO == None ) return; // Building Assault Priority Order... do { NextBestGO = None; foreach AllActors(class'GameObjective', GO) { if ( GO.bBotOnlyObjective ) // ignore bot only objectives continue; // Current Assault Priority: Assign if ( GO.DefensePriority == BestGO.DefensePriority ) { log( " Assault Priority:" @ CurrentPriority @ "DefensePriority:" @ GO.DefensePriority @ "Info:" @ GO.Objective_Info_Attacker @ "Destruction:" @ GO.DestructionMessage ); GO.ObjectivePriority = CurrentPriority; } else if ( (GO.DefensePriority < BestGO.DefensePriority) && ( NextBestGO == None || GO.DefensePriority > NextBestGO.DefensePriority ) ) { NextBestGO = GO; // Next Assault priority ( for next cycle ) } } BestGO = NextBestGO; CurrentPriority++; } until ( NextBestGO == None ) MaxObjectivePriority = CurrentPriority - 1; } simulated function Timer() { if ( Level.NetMode != NM_DedicatedServer ) { if ( Level.TimeSeconds - SecondCount >= Level.TimeDilation ) { if ( ReinforcementCountDown > 0 ) // Reinforcements countdown.. ReinforcementCountDown--; } } super.Timer(); } /* round 0 is either practice round (in network) or intro cinematic (standalone only) */ simulated function bool IsPracticeRound() { return ( CurrentRound == 0 ); } simulated function bool IsDefender( byte Team ) { return ( Team == byte(bTeamZeroIsAttacking) ); } simulated function String GetRoundWinnerString() { switch ( RoundWinner ) { case ERW_None : return ""; case ERW_PracticeRoundEnded : return ERW_PracticeRoundEndedStr; case ERW_RedAttacked : return ERW_RedAttackedStr; case ERW_BlueAttacked : return ERW_BlueAttackedStr; case ERW_RedDefended : return ERW_RedDefendedStr; case ERW_BlueDefended : return ERW_BlueDefendedStr; case ERW_RedMoreObjectives : return ERW_RedMoreObjectivesStr; case ERW_BlueMoreObjectives : return ERW_BlueMoreObjectivesStr; case ERW_RedMoreProgress : return ERW_RedMoreProgressStr; case ERW_BlueMoreProgress : return ERW_BlueMoreProgressStr; case ERW_RedGotSameOBJFaster : return ERW_RedGotSameOBJFasterStr; case ERW_BlueGotSameOBJFaster : return ERW_BlueGotSameOBJFasterStr; case ERW_Draw : return ERW_DrawStr; } } }/`//============================================================================= // ASGameInfo //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASGameInfo extends xTeamGame config; // Config var() config int RoundLimit; // number of pair of rounds var int MaxRounds; // converted to actual number of rounds played var() config int RoundTimeLimit; // max round duration (in minutes) var() config int PracticeTimeLimit; // practice duration (in seconds) var config int ReinforcementsFreq; // Reinforcement frequency (seconds, 0 = no reinforcements) var int ReinforcementsValidTime; // delay while players are allowed to join last reinforcement var int ReinforcementsCount; var int SuccessfulAssaultTimeLimit; // if first attacking team sucessfully attacked, defenders will have to beat that time to win. const ASPROPNUM = 5; var localized string ASPropsDisplayText[ASPROPNUM]; var localized string ASPropDescText[ASPROPNUM]; var(LoadingHints) private localized array ASHints; // internal var byte CurrentAttackingTeam; // Current Attacking team index var byte FirstAttackingTeam; var byte CurrentRound; var int RoundStartTime; var bool bDisableReinforcements; var name NewRoundSound; var name AttackerWinRound[2]; var name DefenderWinRound[2]; var name DrawGameSound; var GameObjective CurrentObjective, LastDisabledObjective; var vehicle KeyVehicle; var Array SpawnManagers; // Handling player spawning var SceneManager CurrentMatineeScene; // SP matinee intro cinematic var ASCinematic_SceneManager EndCinematic; // MP outro cinematic var bool bWeakObjectives; // cheat enum ERER_Reason { ERER_AttackersWin, ERER_AttackersLose, }; function Reset() {} // we handle the reset... /* CheckReady() If tournament game, make sure that there is a valid game winning criterion */ function CheckReady() {} function bool DivertSpaceFighter() { /* local float R; R = RoundStartTime - RemainingTime; if ( R < 100 ) return ( FRand() < 0.5 ); else if ( R > 240 ) return ( FRand() < 0.25 ); */ return ( FRand() < 0.4 ); } function bool AllowTransloc() { return false; } static function bool NeverAllowTransloc() { return true; } function TweakSkill(Bot B) { if ( Level.NetMode != NM_Standalone ) return; if ( (B.Pawn != None) && B.Pawn.IsA('ASVehicle_SpaceFighter_Skaarj') ) B.Skill = AdjustedDifficulty; else if ( Level.GetLocalPlayerController().PlayerReplicationInfo.Team != B.PlayerReplicationInfo.Team ); B.Skill = FMax(B.Skill, AdjustedDifficulty + 1.5); } function PostBeginPlay() { local GameObjective GO; local PlayerSpawnManager PSM; super.PostBeginPlay(); // Caching PlayerSpawnManagers ForEach AllActors(class'PlayerSpawnManager', PSM) SpawnManagers[SpawnManagers.Length] = PSM; // Force objective DefenderTeamIndex for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { GO.DefenderTeamIndex = 1 - CurrentAttackingTeam; GO.NetUpdateTime = Level.TimeSeconds - 1; } ForEach AllActors(class'ASCinematic_SceneManager', EndCinematic, 'OutroScene') break; } // // Log a player in. // Fails login if you set the Error string. // PreLogin is called before Login, but significant game time may pass before // Login is called, especially if content is downloaded. // event PlayerController Login ( string Portal, string Options, out string Error ) { local PlayerController PC; local bool bSpectator; PC = super.Login( Portal, Options, Error ); if ( PC != None ) { if ( Level.NetMode == NM_StandAlone ) { bSpectator = ( ParseOption( Options, "SpectatorOnly" ) ~= "1" ); CurrentRound = 1; // No PracticeRound offline if ( !bQuickStart && !bSpectator && !PC.PlayerReplicationInfo.bOnlySpectator ) TriggerEvent('IntroScene', Self, None); // try to play Matinee intro } } return PC; } // Parse options for this game... event InitGame( string Options, out string Error ) { super.InitGame( Options, Error ); RoundTimeLimit = Max( 0, GetIntOption( Options, "RoundTimeLimit", RoundTimeLimit ) ); PracticeTimeLimit = Max( 0, GetIntOption( Options, "PracticeTimeLimit", PracticeTimeLimit ) ); RoundLimit = Max( 0, GetIntOption( Options, "RoundLimit", RoundLimit ) ); MaxRounds = RoundLimit * 2; // number of rounds played FirstAttackingTeam = Max(0, GetIntOption( Options, "FirstAttackingTeam", FirstAttackingTeam )); ResetTimeDelay = Max(0, GetIntOption( Options, "ResetTimeDelay", ResetTimeDelay )); ReinforcementsFreq = Max(0, GetIntOption( Options, "ReinforcementsFreq", ReinforcementsFreq )); // Disable TimeLimit TimeLimit = 0; RemainingTime = (RoundTimeLimit + ResetTimeDelay + 1) * 60 * (MaxRounds + 2) + PracticeTimeLimit; if ( GameReplicationInfo != None ) GameReplicationInfo.RemainingTime = RemainingTime; } function StartMatch() { super.StartMatch(); // If just played intro, reset everything if ( CurrentRound == 0 && Level.NetMode == NM_StandAlone ) StartNewRound(); else BeginRound(); } function InitGameReplicationInfo() { super.InitGameReplicationInfo(); ASGameReplicationInfo(GameReplicationInfo).MaxRounds = RoundLimit * 2; } function Logout(Controller Exiting) { if ( Exiting.PlayerReplicationInfo.HasFlag != None ) GameObjectDropped( Exiting.PlayerReplicationInfo.HasFlag ); super.Logout(Exiting); } function DiscardInventory( Pawn Other ) { if ( Other == None ) return; if ( (Other.PlayerReplicationInfo != None) && (Other.PlayerReplicationInfo.HasFlag != None) ) GameObjectDropped( Other.PlayerReplicationInfo.HasFlag ); super.DiscardInventory(Other); } function GameObjectDropped( Decoration D ) { if ( D.IsA('GameObject_EnergyCore') ) GameObject_EnergyCore(D).HolderDied(); else D.Drop( vect(0,0,0) ); } function BroadCast_AssaultRole_Message( PlayerController C ) { if ( !GameReplicationInfo.bMatchHasBegun || !IsPlaying() || bGameEnded || bWaitingToStartMatch ) return; if ( IsAttackingTeam( C.GetTeamNum() ) ) C.ReceiveLocalizedMessage( class'Message_AssaultTeamRole', 0, C.PlayerReplicationInfo ); else C.ReceiveLocalizedMessage( class'Message_AssaultTeamRole', 1, C.PlayerReplicationInfo ); } State MatchInProgress { function Timer() { local Controller C; local PlayerController PC; local GameObjective GO; super.Timer(); if ( !bDisableReinforcements && ResetCountDown == 0 && ReinforcementsFreq > 0 ) { ReinforcementsCount++; if ( ReinforcementsCount > ReinforcementsFreq+ReinforcementsValidTime ) { ReinforcementsCount = 0; ASGameReplicationInfo(GameReplicationInfo).ReinforcementCountDown = ReinforcementsFreq; } else if ( ReinforcementsCount >= ReinforcementsFreq ) { ASGameReplicationInfo(GameReplicationInfo).ReinforcementCountDown = 0; // Auto respawn "ready" players for ( C=Level.ControllerList; C!=None; C=C.NextController ) { PC = PlayerController(C); if ( PC != None && PC.IsDead() && ASPlayerReplicationInfo(PC.PlayerReplicationInfo).bAutoRespawn ) { RestartPlayer( PC ); ASPlayerReplicationInfo(PC.PlayerReplicationInfo).bAutoRespawn = false; } } } } // If TimeLimit is disabled, keep timing (but ignore TimeLimit criteria to end game) if ( TimeLimit < 1 ) { GameReplicationInfo.bStopCountDown = false; RemainingTime--; } GameReplicationInfo.RemainingTime = RemainingTime; // Force all players to re-synch time every 10 seconds if ( RemainingTime % 60 == 0 ) GameReplicationInfo.RemainingMinute = RemainingTime; if ( ResetCountDown > 0 ) { ResetCountDown--; if ( ResetCountDown < 3 ) { // blow up all redeemer guided warheads for ( C=Level.ControllerList; C!=None; C=C.NextController ) if ( (C.Pawn != None) && C.Pawn.IsA('RedeemerWarhead') ) C.Pawn.Fire(1); } if ( (ResetCountDown > 0) && (ResetCountDown < 10) ) { BroadcastLocalizedMessage(class'TimerMessage', ResetCountDown); if ( ResetCountDown == 1 ) { // pre-reset objectives, so they are properly setup when players respawn in network... (for replication) ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress = 0; GameReplicationInfo.NetUpdateTime = Level.TimeSeconds; for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { GO.Reset(); GO.NetUpdateTime = Level.TimeSeconds - 1; } } } else if ( ResetCountDown == 0 ) StartNewRound(); } else { if ( ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit > 0 && ((RoundStartTime-RemainingTime) >= ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit) ) { if ( IsPracticeRound() ) EndRound(ERER_AttackersLose, None, "practicetimelimit"); // Start new round else EndRound(ERER_AttackersLose, None, "roundtimelimit"); // Start new round } } } function float SpawnWait(AIController B) { if ( B.IsA('xBot') && GameReplicationInfo.bMatchHasBegun && ResetCountDown == 0 && !bDisableReinforcements ) { if ( ReinforcementsCount >= ReinforcementsFreq ) return (ReinforcementsValidTime - (ReinforcementsCount - ReinforcementsFreq)) * FRand(); else return (ReinforcementsFreq - ReinforcementsCount) + ReinforcementsValidTime * FRand(); } else return super.SpawnWait( B ); } // Player Can be restarted ? function bool PlayerCanRestart( PlayerController aPlayer ) { if ( GameReplicationInfo.bMatchHasBegun && ResetCountDown == 0 && !bDisableReinforcements ) { if ( ReinforcementsCount < ReinforcementsFreq ) { ASPlayerReplicationInfo(aPlayer.PlayerReplicationInfo).bAutoRespawn = true; return false; } else return true; } else return true; } function bool PlayerCanRestartGame( PlayerController aPlayer ) { return false; } function bool IsPlaying() { return ASGameReplicationInfo(GameReplicationInfo).RoundWinner == ERW_None && ResetCountDown == 0; } } State MatchOver { function EndRound(ERER_Reason RoundEndReason, Pawn Instigator, String Reason) {} } /* cinematic started... */ event SceneStarted( SceneManager SM, Actor Other ) { if ( Other != None && Other.IsA('ASCinematic_SceneManager') ) { // just use same event notifications as matinee.. no point in having 12000 different events.. if ( Other == EndCinematic ) GotoState('MPOutroCinematic'); return; } CurrentMatineeScene = SM; if ( SM.Tag == 'IntroScene' ) GotoState('SPIntroCinematic'); } /* Matinee intro cinematic */ state SPIntroCinematic { function BeginState() { Level.GetLocalPlayerController().bHideVehicleNoEntryIndicator = true; CurrentRound = 0; TriggerEvent('StartRound', Self, None); } event SceneStarted( SceneManager SM, Actor Other ) { HighlightCurrentPhysicalObjectives(); CurrentMatineeScene = SM; } function bool IsPlayingIntro() { return true; } function bool CanDisableObjective( GameObjective GO ) { return true; } event SceneEnded( SceneManager SM, Actor Other ) { // is Cinematic over ? if ( SM.NextSceneTag == '' || SM.NextSceneTag == 'None' || SM.bAbortCinematic ) GotoState('MatchInProgress'); } event SceneAbort() { local PlayerController PC; PC = Level.GetLocalPlayerController(); if ( PC != None ) PC.ConsoleCommand("stopsounds"); CurrentMatineeScene.AbortScene(); } function EndRound(ERER_Reason RoundEndReason, Pawn Instigator, String Reason); function EndState() { local PlayerController PC; PC = Level.GetLocalPlayerController(); PC.bHideVehicleNoEntryIndicator = false; // When cinematic is over, force player to press fire before starting match if ( PC != None && PC.PlayerReplicationInfo != None ) PC.GotoState('PlayerWaiting'); GotoState('PendingMatch'); } } auto State PendingMatch { function EndRound(ERER_Reason RoundEndReason, Pawn Instigator, String Reason); Begin: if ( bQuickStart ) StartMatch(); } /* network friendly outro */ state MPOutroCinematic { event SceneEnded( SceneManager SM, Actor Other ) { GotoState('MatchInProgress'); } function BeginState() { local Controller C, NextC; local PlayerController PC; C = Level.ControllerList; // Set all players to RoundEnded state... while ( C != None ) { NextC = C.NextController; if ( C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator ) { PC = PlayerController(C); if ( PC != None ) PC.ClientRoundEnded(); C.RoundHasEnded(); } C = NextC; } } function bool PlayerCanRestartGame( PlayerController aPlayer ) { return false; } function EndState() { // if RoundLimit reached, END GAME if ( CurrentRound >= MaxRounds ) { // need to override DeathMatch::EndGame because it's not supporting Reason="roundlimit" super(GameInfo).EndGame(None, "roundlimit"); if ( bGameEnded ) GotoState('MatchOver'); return; } ResetCountDown = ResetTimeDelay+1; QueueAnnouncerSound( NewRoundSound, 1, 255 ); } } /* End of Game */ function bool CheckEndGame(PlayerReplicationInfo Winner, string Reason) { local PlayerController PC; local Controller C; if ( Teams[1].Score > Teams[0].Score ) GameReplicationInfo.Winner = Teams[1]; else if ( Teams[1].Score < Teams[0].Score ) GameReplicationInfo.Winner = Teams[0]; else GameReplicationInfo.Winner = None; for ( C=Level.ControllerList; C!=None; C=C.nextController ) { PC = PlayerController(C); if ( PC != None ) { //if ( !PC.PlayerReplicationInfo.bOnlySpectator ) // PlayWinMessage(PC, (PC.PlayerReplicationInfo.Team == GameReplicationInfo.Winner)); if ( CurrentGameProfile != None ) CurrentGameProfile.bWonMatch = (PC.PlayerReplicationInfo.Team == GameReplicationInfo.Winner); } } EndTime = Level.TimeSeconds + EndTimeDelay; return true; } function PlayEndOfMatchMessage() { local controller C; if ( ((Teams[0].Score == 0) || (Teams[1].Score == 0)) && (Teams[0].Score + Teams[1].Score >= 3) ) { for ( C = Level.ControllerList; C != None; C = C.NextController ) { if ( C.IsA('PlayerController') ) { if ( Teams[0].Score > Teams[1].Score ) { if ( (C.PlayerReplicationInfo.Team == Teams[0]) || C.PlayerReplicationInfo.bOnlySpectator ) PlayerController(C).QueueAnnouncement(AltEndGameSoundName[0], 1); else PlayerController(C).QueueAnnouncement(AltEndGameSoundName[1], 1); } else { if ( (C.PlayerReplicationInfo.Team == Teams[1]) || C.PlayerReplicationInfo.bOnlySpectator ) PlayerController(C).QueueAnnouncement(AltEndGameSoundName[0], 1); else PlayerController(C).QueueAnnouncement(AltEndGameSoundName[1], 1); } } } } else { for ( C = Level.ControllerList; C != None; C = C.NextController ) { if ( C.IsA('PlayerController') ) { if ( Teams[1].Score > Teams[0].Score ) PlayerController(C).QueueAnnouncement(EndGameSoundName[1], 1); // Blue teams wins else if ( Teams[1].Score < Teams[0].Score ) PlayerController(C).QueueAnnouncement(EndGameSoundName[0], 1); // Red team wins else PlayerController(C).QueueAnnouncement(DrawGameSound, 1); // Draw Game } } } } function EndRound(ERER_Reason RoundEndReason, Pawn Instigator, String Reason) { local int ScoringTeam; local PlayerReplicationInfo PRI; local PlayerController PC; local Controller C, NextC; local GameObjective ObjectiveFocus; local bool bObjectiveHasEndCam, bSuccessfulAttack; // Ignore EndRound during reset countdown if ( !IsPlaying() || ResetCountDown > 0 ) return; log("ASGameInfo::EndRound - Reason:"@Reason); // Find real round end instigator if ( RoundEndReason == ERER_AttackersWin && LastDisabledObjective != None && LastDisabledObjective.DisabledBy != None ) PRI = LastDisabledObjective.DisabledBy; else if ( Instigator != None ) PRI = Instigator.PlayerReplicationInfo; ObjectiveFocus = GetCurrentObjective(); SuccessfulAssaultTimeLimit = 0; if ( IsPracticeRound() ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_PracticeRoundEnded; ASGameReplicationInfo(GameReplicationInfo).RoundOverTime = ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit - ASGameReplicationInfo(GameReplicationInfo).RoundStartTime + RemainingTime; } else { if ( RoundEndReason == ERER_AttackersWin ) { // Reward player who instigated the win! if ( PRI != None && PRI.IsA('ASPlayerReplicationInfo') ) { ASPlayerReplicationInfo(PRI).DisabledFinalObjective++; //log("EndRound Trophy given to" @ PRI.Owner.GetHumanReadableName() ); GameEvent("EndRound_Trophy", "", PRI); } if ( CurrentRound % 2 == 1 ) SuccessfulAssaultTimeLimit = RoundStartTime - RemainingTime; ScoringTeam = CurrentAttackingTeam; bSuccessfulAttack = true; GameEvent("AS_attackers_win", ""$ScoringTeam, PRI); } else { // If didn't win the round, save progress of current objective if ( ObjectiveFocus != None ) { //log("Saving progress of current objective:" @ ObjectiveFocus.Objective_Info_Attacker @ ObjectiveFocus.GetObjectiveProgress() ); ObjectiveFocus.SavedObjectiveProgress = ObjectiveFocus.GetObjectiveProgress(); Teams[1-ObjectiveFocus.DefenderTeamIndex].CurrentObjectiveProgress = ObjectiveFocus.SavedObjectiveProgress; } ScoringTeam = 1 - CurrentAttackingTeam; GameEvent("AS_defenders_win", ""$ScoringTeam, PRI); } AnnounceScore( ScoringTeam ); if ( CurrentRound % 2 == 0 ) // Every pair of rounds, once both teams have attacked, update teams score. SetPairOfRoundWinner(); } TriggerEvent('EndRound', Self, Instigator); // Play End of Round cinematic... if ( bSuccessfulAttack && EndCinematic != None ) { EndCinematic.Trigger( Self, None ); return; } // If failed to attack display current objective, otherwise, display last disabled (=final one) if ( ObjectiveFocus == None && LastDisabledObjective != None ) ObjectiveFocus = LastDisabledObjective; if ( ObjectiveFocus != None ) { ObjectiveFocus.bAlwaysRelevant = true; if ( ObjectiveFocus.EndCamera != None && ASCinematic_Camera(ObjectiveFocus.EndCamera) != None ) bObjectiveHasEndCam = true; C = Level.ControllerList; while ( C != None ) { NextC = C.NextController; if ( C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator ) { PC = PlayerController(C); if ( PC != None ) { if ( bObjectiveHasEndCam ) // Objective has a special End Cam setup... ASCinematic_Camera(ObjectiveFocus.EndCamera).ViewFixedObjective( PC, ObjectiveFocus ); else // Otherwise, just spectate objective in behindview/freecam { PC.ClientSetViewTarget( ObjectiveFocus ); PC.SetViewTarget( ObjectiveFocus ); } PC.ClientRoundEnded(); } C.RoundHasEnded(); } C = NextC; } } else log("ASGameInfo::EndRound ObjectiveFocus == None !!!!!!!!!"); // if RoundLimit reached, END GAME if ( CurrentRound >= MaxRounds ) { // need to override DeathMatch::EndGame because it's not supporting Reason="roundlimit" super(GameInfo).EndGame(None, "roundlimit"); if ( bGameEnded ) GotoState('MatchOver'); return; } QueueAnnouncerSound( NewRoundSound, 1, 255 ); ResetCountDown = ResetTimeDelay+1; } function PracticeRoundEnded() { local Controller C; // Practice Round Ended, reset scores! for ( C = Level.ControllerList; C != None; C = C.NextController ) if ( C.PlayerReplicationInfo != None ) { C.PlayerReplicationInfo.Kills = 0; C.PlayerReplicationInfo.Score = 0; C.PlayerReplicationInfo.Deaths = 0; if ( TeamPlayerReplicationInfo(C.PlayerReplicationInfo) != None ) TeamPlayerReplicationInfo(C.PlayerReplicationInfo).Suicides = 0; if ( ASPlayerReplicationInfo(C.PlayerReplicationInfo) != None ) { ASPlayerReplicationInfo(C.PlayerReplicationInfo).DisabledObjectivesCount = 0; ASPlayerReplicationInfo(C.PlayerReplicationInfo).DisabledFinalObjective = 0; } } bFirstBlood = false; Teams[0].Score = 0; Teams[1].Score = 0; Teams[0].NetUpdateTime = Level.TimeSeconds - 1; Teams[1].NetUpdateTime = Level.TimeSeconds - 1; } /* Awards points once both teams have attacked, every couple of rounds */ function SetPairOfRoundWinner() { local byte WinningTeam; WinningTeam = GetPairOfRoundWinner(); if ( WinningTeam < 2 ) { Teams[WinningTeam].Score += 1.0; Teams[WinningTeam].NetUpdateTime = Level.TimeSeconds - 1; TeamScoreEvent(WinningTeam, 1, "pair_of_round_winner"); } } /* Called when both teams have attacked in a row, and returns the winner */ function byte GetPairOfRoundWinner() { // Team who disabled the highest number of objectives if ( Teams[0].ObjectivesDisabledCount > Teams[1].ObjectivesDisabledCount ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_RedMoreObjectives; return 0; } if ( Teams[0].ObjectivesDisabledCount < Teams[1].ObjectivesDisabledCount ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_BlueMoreObjectives; return 1; } // If teams completed the same number of objectives, without successfully attacking, // winner is the one who got their current objective the closest to completion (when relevant) if ( Teams[0].CurrentObjectiveProgress != Teams[1].CurrentObjectiveProgress && Teams[0].CurrentObjectiveProgress > 0.f && Teams[0].CurrentObjectiveProgress < 1.f ) { if ( Teams[0].CurrentObjectiveProgress < Teams[1].CurrentObjectiveProgress ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_RedMoreProgress; return 0; } ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_BlueMoreProgress; return 1; } // Teams disabled the same number of objectives... compare time! if ( Teams[0].LastObjectiveTime > Teams[1].LastObjectiveTime ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_BlueGotSameOBJFaster; return 1; } if ( Teams[0].LastObjectiveTime < Teams[1].LastObjectiveTime ) { ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_RedGotSameOBJFaster; return 0; } ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_Draw; return 255; } function AnnounceScore( int ScoringTeam ) { local name ScoreSound; if ( IsAttackingTeam( ScoringTeam ) ) { if ( ScoringTeam == 1 ) ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_BlueAttacked; else ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_RedAttacked; ScoreSound = AttackerWinRound[ScoringTeam]; } else { if ( ScoringTeam == 1 ) ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_BlueDefended; else ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_RedDefended; ScoreSound = DefenderWinRound[ScoringTeam]; } ASGameReplicationInfo(GameReplicationInfo).RoundOverTime = ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit - ASGameReplicationInfo(GameReplicationInfo).RoundStartTime + RemainingTime; QueueAnnouncerSound( ScoreSound, 1, 255 ); } // directly skip to next round exec function NewRound() { StartNewRound(); } // Start new round... reset everything, swap teams... function StartNewRound() { log("## ASGameInfo::StartNewRound ##"); CurrentRound++; BeginRound(); } function ResetLevel() { local Controller C, NextC; local Actor A; log("ResetLevel"); // Force bTeamScoreRounds to avoid having TeamScores reset to 0 bTeamScoreRounds = true; if ( !bDisableReinforcements ) { ASGameReplicationInfo(GameReplicationInfo).ReinforcementCountDown = 0; ReinforcementsCount = ReinforcementsFreq; // Start reinforcements right away } // Reset ALL controllers first C = Level.ControllerList; while ( C != None ) { NextC = C.NextController; if ( C.PlayerReplicationInfo == None || !C.PlayerReplicationInfo.bOnlySpectator ) { if ( PlayerController(C) != None ) PlayerController(C).ClientReset(); C.Reset(); } C = NextC; } // Reset ALL actors (except controllers) foreach AllActors(class'Actor', A) if ( !A.IsA('Controller') ) A.Reset(); } // Round begins... function BeginRound() { local Controller C, NextC; local GameObjective GO; log("ASGameInfo::BeginRound"); // Is Practice Round disabled ? if ( IsPracticeRound() && PracticeTimeLimit == 0 && Level.NetMode != NM_StandAlone ) CurrentRound++; if ( IsPracticeRound() ) PracticeRoundEnded(); // Set Attacking and Defending teams... if ( IsPracticeRound() || CurrentRound % 2 == 1 ) { CurrentAttackingTeam = FirstAttackingTeam; BeginNewPairOfRounds(); } else CurrentAttackingTeam = 1 - FirstAttackingTeam; LastDisabledObjective = None; CurrentObjective = None; ASGameReplicationInfo(GameReplicationInfo).bTeamZeroIsAttacking = (CurrentAttackingTeam == 0); ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress = 0; ASGameReplicationInfo(GameReplicationInfo).CurrentRound = CurrentRound; ASGameReplicationInfo(GameReplicationInfo).RoundWinner = ERW_None; RoundStartTime = RemainingTime; // local round start stamp ASGameReplicationInfo(GameReplicationInfo).RoundStartTime = RemainingTime; // replicated round start stamp GameReplicationInfo.RemainingTime = RemainingTime; // for new players joining.. GameReplicationInfo.RemainingMinute = RemainingTime; // re-synch current players GameReplicationInfo.NetUpdateTime = Level.TimeSeconds - 1; // Set Round Time Limit if ( IsPracticeRound() ) ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit = PracticeTimeLimit; // Practice Round else if ( CurrentRound % 2 == 0 && SuccessfulAssaultTimeLimit != 0 ) ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit = SuccessfulAssaultTimeLimit; // First team succeeded => second team must beat this time. else ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit = RoundTimeLimit * 60; // default round time limit if ( !bDisableReinforcements ) { ASGameReplicationInfo(GameReplicationInfo).ReinforcementCountDown = 0; ReinforcementsCount = ReinforcementsFreq; // Start reinforcements right away } ResetLevel(); // Force objective DefenderTeamIndex for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { GO.DefenderTeamIndex = 1 - CurrentAttackingTeam; GO.NetUpdateTime = Level.TimeSeconds - 1; } if ( bWeakObjectives ) WeakObjectives(); HighlightCurrentPhysicalObjectives(); // re spawn players C = Level.ControllerList; while ( C != None ) { NextC = C.NextController; if ( C.IsA('PlayerController') && C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator ) RestartPlayer( C ); C = NextC; } TriggerEvent('StartRound', Self, None); if ( !IsPracticeRound() ) GameEvent("AS_BeginRound", ""$CurrentRound, None); SetGameSpeed( GameSpeed ); } /* Begin a new pair of rounds (both teams get to attack) */ function BeginNewPairOfRounds() { local GameObjective GO; // Reset Objective tracking to define a pair of round winner Teams[0].LastObjectiveTime = 0; Teams[0].ObjectivesDisabledCount = 0; Teams[0].CurrentObjectiveProgress = 0; Teams[1].LastObjectiveTime = 0; Teams[1].ObjectivesDisabledCount = 0; Teams[1].CurrentObjectiveProgress = 0; for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { GO.ObjectiveDisabledTime = 0; GO.SavedObjectiveProgress = 0; } } function bool IsAttackingTeam(int TeamNumber) { return ( TeamNumber == CurrentAttackingTeam ); } function int GetAttackingTeam() { return CurrentAttackingTeam; } function int GetDefenderNum() { return (1 - CurrentAttackingTeam); } function GameObjective GetCurrentObjective() { local GameObjective GO; // Try to find currently active objective... if ( CurrentObjective == None ) for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( (ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress == GO.ObjectivePriority) && GO.IsActive() && ( !GO.bOptionalObjective || CurrentObjective == None ) ) CurrentObjective = GO; } return CurrentObjective; } function bool IsPlayingIntro() { return false; } function bool IsPracticeRound() { return ASGameReplicationInfo(GameReplicationInfo).IsPracticeRound(); } function bool IsPlaying() { return false; } function ScoreObjective( PlayerReplicationInfo Scorer, float Score ) { // NOTE: Score awarding hardcoded and moved to ObjectiveDisabled (see below). if ( GameRulesModifiers != None ) GameRulesModifiers.ScoreObjective(Scorer, Score); } /* Is objective allowed to be disabled ? */ function bool CanDisableObjective( GameObjective GO ) { local ASGameReplicationInfo ASGRI; if ( !IsPlaying() ) return false; if ( GO.bBotOnlyObjective ) return true; ASGRI = ASGamereplicationInfo(GameReplicationInfo); if ( GO.ObjectivePriority <= ASGRI.ObjectiveProgress ) return true; return false; } function ObjectiveDisabled( GameObjective DisabledObjective ) { local int ForcedScore; local int ObjectiveDisabledTime; local Controller C; ObjectiveDisabledTime = RoundStartTime - RemainingTime; DisabledObjective.ObjectiveDisabledTime = ObjectiveDisabledTime; if ( IsPlaying() && DisabledObjective.DisabledBy != None ) { // Hardcoded score if ( DisabledObjective.bOptionalObjective ) ForcedScore = 5; else ForcedScore = 10; /* AwardAssaultScore can change DisabledBy, to award the Trophy to another player */ DisabledObjective.AwardAssaultScore( ForcedScore ); //log("ObjectiveCompleted Trophy given to" @ DisabledObjective.DisabledBy.Owner.GetHumanReadableName() ); GameEvent("ObjectiveCompleted_Trophy", DisabledObjective.ObjectivePriority @ ObjectiveDisabledTime @ DisabledObjective.Objective_Info_Attacker, DisabledObjective.DisabledBy); ASPlayerReplicationInfo(DisabledObjective.DisabledBy).DisabledObjectivesCount++; if ( PlayerController(DisabledObjective.DisabledBy.Owner) != None ) { PlayerController(DisabledObjective.DisabledBy.Owner).ReceiveLocalizedMessage(class'Message_Awards', 0); for ( C=Level.ControllerList; C!=None; C=C.nextController ) if ( PlayerController(C) != None && C != DisabledObjective.DisabledBy.Owner ) PlayerController(C).ReceiveLocalizedMessage(class'Message_Awards', 1, DisabledObjective.DisabledBy); } //ScoreEvent(DisabledObjective.DisabledBy, ForcedScore, "Objective_Disabled"); } //else if ( DisabledObjective.DisabledBy == None && !IsPlayingIntro() ) // log("DisabledObjective.DisabledBy == None" @ DisabledObjective ); if ( !DisabledObjective.bOptionalObjective ) { Teams[1-DisabledObjective.DefenderTeamIndex].ObjectivesDisabledCount++; Teams[1-DisabledObjective.DefenderTeamIndex].LastObjectiveTime = ObjectiveDisabledTime; } if ( IsPlaying() && DisabledObjective.DisabledBy != None ) { if ( DisabledObjective.Announcer_DisabledObjective == None ) QueueAnnouncerSound( '', 1, 255 ); else QueueAnnouncerSound( DisabledObjective.Announcer_DisabledObjective.Name, 1, 255 ); } LastDisabledObjective = DisabledObjective; super.ObjectiveDisabled( DisabledObjective ); } function FindNewObjectives(GameObjective DisabledObjective) { if ( !bGameEnded && ResetCountDown < 1 ) UpdateObjectiveProgression( DisabledObjective ); // Objective has just been disabled, update progress... super.FindNewObjectives( DisabledObjective ); } /* here we keep track of objective progression through a simple progress index... This index allows objectives to be shown in order on HUD, and Briefing screen to show the status of the assault... */ function UpdateObjectiveProgression( GameObjective DisabledObjective ) { local GameObjective GO; local bool bIncPriority, bObjPriority; local byte CurrentProgressIndex, BackupProgressIndex; CurrentProgressIndex = ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress; BackupProgressIndex = CurrentProgressIndex; bIncPriority = true; for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { // Check objective progression... if ( (CurrentProgressIndex == GO.ObjectivePriority) && !GO.bOptionalObjective ) { // Prioritization is relevant, we found at least one objective matching... bObjPriority = true; if ( GO.IsActive() ) { // There is at least one Objective with current priority left to disable... bIncPriority = false; break; } } } // Objective Prioritization is relevant and all current priority objectives are disabled ? // So increase progress index... if ( bObjPriority && bIncPriority ) CurrentProgressIndex++; // Update progress... if ( CurrentProgressIndex != BackupProgressIndex ) ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress++; HighlightCurrentPhysicalObjectives(); // Update Current Objective for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( (ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress == GO.ObjectivePriority) && !GO.bDisabled && !GO.bOptionalObjective ) { CurrentObjective = GO; if ( !DisabledObjective.bAnnounceNextObjective || (CurrentProgressIndex == BackupProgressIndex && GO.Announcer_ObjectiveInfo == DisabledObjective.Announcer_ObjectiveInfo && !DisabledObjective.bOptionalObjective) ) break; // Announce Next Objective... if ( IsPlaying() ) AnnounceNextObjective( GO ); return; } } if ( CurrentObjective != None && IsPlaying() ) QueueAnnouncerSound( '', 1, 255,, 200 ); } function HighlightCurrentPhysicalObjectives() { local GameObjective GO; for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( (ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress >= GO.ObjectivePriority) && GO.IsActive() ) GO.HighlightPhysicalObjective( true ); else GO.HighlightPhysicalObjective( false ); } } function AnnounceNextObjective( GameObjective NewObjective ) { if ( !IsPlaying() ) return; // Attackers if ( NewObjective.Announcer_ObjectiveInfo == None ) QueueAnnouncerSound( '', 1, 1 - NewObjective.DefenderTeamIndex, AP_NoDuplicates, 200 ); else QueueAnnouncerSound( NewObjective.Announcer_ObjectiveInfo.Name, 1, 1 - NewObjective.DefenderTeamIndex, AP_NoDuplicates, 200 ); // Defenders if ( NewObjective.Announcer_DefendObjective == None ) QueueAnnouncerSound( '', 1, NewObjective.DefenderTeamIndex, AP_NoDuplicates, 200 ); else QueueAnnouncerSound( NewObjective.Announcer_DefendObjective.Name, 1, NewObjective.DefenderTeamIndex, AP_NoDuplicates, 200 ); } function ShowPathTo(PlayerController P, int TeamNum) { local GameObjective G, Best; local class WWclass; local ASGameReplicationInfo ASGRI; ASGRI = ASGamereplicationInfo(GameReplicationInfo); Best = GetCurrentObjective(); if ( Best == None || !Best.IsActive() ) { for ( G=Teams[0].AI.Objectives; G!=None; G=G.NextObjective ) if ( !G.bOptionalObjective && CheckObjectivePriority( G ) ) { Best = G; break; } } if ( Best != None ) { // Spawn Willow Whisp if ( P.FindPathToward(Best, false) != None ) { WWclass = class(DynamicLoadObject(PathWhisps[Best.DefenderTeamIndex], class'Class')); Spawn(WWclass, P,, P.Pawn.Location); } if ( TeamNum != 255 && IsPlaying() ) { // Announce objective if ( P.GetTeamNum() == 1 - Best.DefenderTeamIndex ) { // Attacker if ( Best.Announcer_ObjectiveInfo == None ) P.QueueAnnouncement( '', 1, AP_NoDuplicates, 201 ); else P.QueueAnnouncement( Best.Announcer_ObjectiveInfo.Name, 1, AP_NoDuplicates, 201 ); } else if ( P.GetTeamNum() == Best.DefenderTeamIndex ) { // Defenders if ( Best.Announcer_DefendObjective == None ) P.QueueAnnouncement( '', 1, AP_NoDuplicates, 201 ); else P.QueueAnnouncement( Best.Announcer_DefendObjective.Name, 1, AP_NoDuplicates, 201 ); } else P.QueueAnnouncement( '', 1, AP_NoDuplicates, 201 ); } } } /* returns true if Objective is relevant (priority wise) */ function bool CheckObjectivePriority(GameObjective GO) { local ASGameReplicationInfo ASGRI; ASGRI = ASGamereplicationInfo(GameReplicationInfo); if ( ASGRI == None || !GO.IsActive() || GO.bDisabled ) return false; if ( ASGRI.ObjectiveProgress >= GO.ObjectivePriority ) return true; return false; } /* new Spawn Area enabled, give the opportunity to that team to teleport there Only for currently alive players, of the team who got a new spawn area activated, during 15 seconds */ event NewSpawnAreaEnabled( bool bDefenders ) { local Controller C; local PlayerController PC; for ( C=Level.ControllerList; C!=None; C=C.NextController ) { PC = PlayerController(C); if ( bDefenders && C.GetTeamNum() != GetDefenderNum() ) continue; if ( !bDefenders && C.GetTeamNum() == GetDefenderNum() ) continue; if ( C.IsInState('Dead') || C.Pawn == None || C.Pawn.Health < 1 ) continue; if ( PC != None && (PC.IsDead() || PC.IsSpectating()) ) continue; if ( C.Pawn != None && ASPlayerReplicationInfo(C.PlayerReplicationInfo) != None ) { ASPlayerReplicationInfo(C.PlayerReplicationInfo).bTeleportToSpawnArea = true; if ( AIController(C) != None ) ASPlayerReplicationInfo(C.PlayerReplicationInfo).TeleportTime = Level.TimeSeconds; else ASPlayerReplicationInfo(C.PlayerReplicationInfo).TeleportTime = ASGameReplicationInfo(GameReplicationInfo).RoundTimeLimit - ASGameReplicationInfo(GameReplicationInfo).RoundStartTime + RemainingTime; // NOTE: Bots are forced to teleport in ASPlayerReplicationInfo::Timer() // Bots are not teleported instantly because it is very likely that 2 spawn areas exist at the same time // (new and old), and bot might be teleported to the old one. } } } /* Teleport Player to new Spawn Location */ event NoTranslocatorKeyPressed( PlayerController PC ) { local ASGameReplicationInfo ASGRI; local ASPlayerReplicationInfo ASPRI; if ( PC == None || ASPlayerReplicationInfo(PC.PlayerReplicationInfo) == None ) return; ASPRI = ASPlayerReplicationInfo(PC.PlayerReplicationInfo); if ( ASPRI.bTeleportToSpawnArea == false ) return; ASGRI = ASGameReplicationInfo(GameReplicationInfo); if ( ASGRI.RoundTimeLimit - ASGRI.RoundStartTime + RemainingTime + ASGRI.MaxTeleportTime < ASPRI.TeleportTime ) return; TeleportPlayerToSpawn( PC ); } /* Teleport player to current spawn area */ function TeleportPlayerToSpawn( Controller C ) { local vector PrevLocation; PrevLocation = C.Pawn.Location; ASPlayerReplicationInfo(C.PlayerReplicationInfo).bTeleportToSpawnArea = false; RespawnPlayer( C, false ); if ( C.Pawn.IsA('xPawn') ) xPawn(C.Pawn).DoTranslocateOut( PrevLocation ); } function Killed( Controller Killer, Controller Killed, Pawn KilledPawn, class damageType ) { //log("ASGameinfo::Killed Killer:" @ Killer @ "Killed" @ Killed @ "KilledPawn" @ KilledPawn ); if ( Killed != None && ASPlayerReplicationInfo(Killed.PlayerReplicationInfo) != None ) ASPlayerReplicationInfo(Killed.PlayerReplicationInfo).bTeleportToSpawnArea = false; super.Killed( Killer, Killed, KilledPawn, damageType ); } function int VehicleScoreKill( Controller Killer, Controller Killed, Vehicle DestroyedVehicle, out string KillInfo ) { if ( DestroyedVehicle.bKeyVehicle || DestroyedVehicle.bHighScoreKill ) { if ( Killer == Killed || Killer.GetTeamNum() == DestroyedVehicle.GetTeamNum() ) return super.VehicleScoreKill( Killer, Killed, DestroyedVehicle, KillInfo ); // Destroyed vehicles trophys if ( ASPlayerReplicationInfo(Killer.PlayerReplicationInfo) != None ) { GameEvent("VehicleDestroyed_Trophy", DestroyedVehicle.VehicleNameString, Killer.PlayerReplicationInfo); ASPlayerReplicationInfo(Killer.PlayerReplicationInfo).DestroyedVehicles++; // Wrecker! announcer if ( PlayerController(Killer) != None && ASPlayerReplicationInfo(Killer.PlayerReplicationInfo).DestroyedVehicles > 2 ) PlayerController(Killer).ReceiveLocalizedMessage(class'Message_ASKillMessages', 1); } } return super.VehicleScoreKill( Killer, Killed, DestroyedVehicle, KillInfo ); } function bool CriticalPlayer(Controller Other) { local GameObjective GO; if ( Other.Pawn == None || Other.PlayerReplicationInfo == None || !IsAttackingTeam(Other.GetTeamNum()) ) return super.CriticalPlayer( Other ); for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( !GO.IsActive() || !GO.IsCritical() || (ASGameReplicationInfo(GameReplicationInfo).ObjectiveProgress < GO.ObjectivePriority) ) continue; if ( GO.MyBaseVolume != None && GO.MyBaseVolume.Encompasses( Other.Pawn ) ) return true; } return super.CriticalPlayer( Other ); } function SpecialEvent(PlayerReplicationInfo Who, string Desc) { if ( !IsPracticeRound() ) super.SpecialEvent( Who, Desc ); } function KillEvent(string Killtype, PlayerReplicationInfo Killer, PlayerReplicationInfo Victim, class Damage) { if ( !IsPracticeRound() ) super.KillEvent(KillType, Killer, Victim, Damage); } function ScoreEvent(PlayerReplicationInfo Who, float Points, string Desc) { if ( !IsPracticeRound() ) super.ScoreEvent( Who, Points, Desc); } function TeamScoreEvent(int Team, float Points, string Desc) { if ( !IsPracticeRound() ) super.TeamScoreEvent( Team, Points, Desc); } function RestartPlayer( Controller aPlayer ) { local String PawnOverrideClass; super.RestartPlayer( aPlayer ); if ( aPlayer != None && aPlayer.PlayerReplicationInfo != None ) { PawnOverrideClass = ASPlayerReplicationInfo(aPlayer.PlayerReplicationInfo).PawnOverrideClass; if ( PawnOverrideClass != "" ) { SpawnAndPossessPawn(aPlayer, PawnOverrideClass); ASPlayerReplicationInfo(aPlayer.PlayerReplicationInfo).PawnOverrideClass = ""; } } if ( PlayerController(aPlayer) != None ) BroadCast_AssaultRole_Message( PlayerController(aPlayer) ); } function RespawnPlayer( Controller C, optional bool bClearSpecials ) { local String PawnOverrideClass; local vehicle DrivenVehicle; if ( C.Pawn != None ) { DrivenVehicle = Vehicle(C.Pawn); if ( DrivenVehicle != None ) DrivenVehicle.KDriverLeave( true ); // Force the driver out of the car } C.StartSpot = FindPlayerStart(C, C.PlayerReplicationInfo.Team.TeamIndex); PawnOverrideClass = ASPlayerReplicationInfo(C.PlayerReplicationInfo).PawnOverrideClass; if ( PawnOverrideClass != "" ) { SpawnAndPossessPawn(C, PawnOverrideClass); ASPlayerReplicationInfo(C.PlayerReplicationInfo).PawnOverrideClass = ""; } if ( C.StartSpot != None ) { C.SetLocation( C.StartSpot.Location ); C.SetRotation( C.StartSpot.Rotation ); } if ( C.Pawn != None ) { if ( bClearSpecials && xPawn(C.Pawn) != None ) { if (xPawn(C.Pawn).CurrentCombo != None) { C.Adrenaline = 0; xPawn(C.Pawn).CurrentCombo.Destroy(); } if ( xPawn(C.Pawn).UDamageTimer != None ) { xPawn(C.Pawn).UDamageTimer.Destroy(); xPawn(C.Pawn).DisableUDamage(); } } if ( C.Pawn.Weapon == None ) { AddDefaultInventory( C.Pawn ); } SetPlayerDefaults( C.Pawn ); C.Pawn.SetLocation( C.StartSpot.Location ); C.Pawn.SetRotation( C.StartSpot.Rotation ); C.Pawn.Velocity = vect(0,0,0); C.Pawn.PlayTeleportEffect(false, true); if ( (Bot(C) != None) && (PawnOverrideClass == "") ) Bot(C).Squad.ReTask(Bot(C)); } if ( C.StartSpot != None ) C.ClientSetLocation(C.StartSpot.Location, C.StartSpot.Rotation); } function AddDefaultInventory( pawn PlayerPawn ) { if ( ASPlayerReplicationInfo(PlayerPawn.Controller.PlayerReplicationInfo).PawnOverrideClass == "" ) { if ( UnrealPawn(PlayerPawn) != None ) UnrealPawn(PlayerPawn).AddDefaultInventory(); else if ( ASVehicle(PlayerPawn) != None ) ASVehicle(PlayerPawn).AddDefaultInventory(); } SetPlayerDefaults(PlayerPawn); } function class GetDefaultPlayerClass(Controller C) { local String PawnClassName; local class PawnClass; if ( C != None ) { // Laurent -- returns Engine.Pawn which is abstract = player dies right away // PawnClassName = PC.GetDefaultURL( "Class" ); PawnClassName = String(C.default.PawnClass); PawnClass = class( DynamicLoadObject( PawnClassName, class'Class') ); if ( PawnClass != None ) return( PawnClass ); } return( class( DynamicLoadObject( DefaultPlayerClassName, class'Class' ) ) ); } // Force a specific PawnClass to be used when (re)spawning function bool SpawnAndPossessPawn(Controller C, String PawnClassName) { local class PawnClass; local Pawn P; PawnClass = class(DynamicLoadObject(PawnClassName, class'Class')); if ( PawnClass == None ) { log("ASGameInfo::SpawnAndPossessPawn - PawnClass == None. PawnClassName:"@PawnClassName); return false; } // Override Controller.PawnClass if ( C.Pawn == None ) // Controller doesn't have a Pawn yet... { log("ASGameInfo::SpawnAndPossessPawn - Pawn == None. PawnClassName:"@PawnClassName); return false; } // Spawn Pawn and possess.. P = Spawn(PawnClass, C,, C.Pawn.LastStartSpot.Location, C.Pawn.LastStartSpot.Rotation); if ( P == None ) // make sure it never fails... { P = Spawn(PawnClass, C,, C.Location, C.Rotation); if ( P == None ) { P = Spawn(PawnClass, C); if ( P == None ) { P = C.Pawn; C.UnPossess(); P.Controller = None; P.Destroy(); C.PawnClass = PawnClass; return false; } } } P.Anchor = C.Pawn.LastStartSpot; P.LastStartSpot = C.Pawn.LastStartSpot; P.LastStartTime = Level.TimeSeconds; C.PreviousPawnClass = C.Pawn.Class; PossessPawn( C, P ); return true; } function PossessPawn( Controller C, Pawn P ) { local Vehicle V; local Pawn OldPawn; local PlayerController PC; PC = PlayerController(C); // vehicle specifics V = Vehicle(P); if ( V != None ) { V.TryToDrive( C.Pawn ); return; } OldPawn = C.Pawn; C.UnPossess(); OldPawn.Controller = None; OldPawn.Destroy(); C.Possess( P ); if ( PC != None ) { PC.ClientSetRotation( C.Pawn.Rotation ); PC.bBehindView = PC.Pawn.PointOfView(); PC.ClientSetBehindView( PC.bBehindView ); } AddDefaultInventory( C.Pawn ); } function NavigationPoint FindPlayerStart( Controller Player, optional byte InTeam, optional string incomingName ) { local NavigationPoint N, BestStart; local int i; local string PawnOverrideClass; local byte Team, T; local float BestRating, NewRating; local Teleporter Tel; // Fix for InTeam not working correctly in GameInfo if ( (Player != None) && (Player.PlayerReplicationInfo != None) && Player.PlayerReplicationInfo.Team != None ) Team = Player.PlayerReplicationInfo.Team.TeamIndex; else Team = InTeam; if ( Player != None ) Player.StartSpot = None; if ( GameRulesModifiers != None ) { N = GameRulesModifiers.FindPlayerStart(Player,InTeam,incomingName); if ( N != None ) return N; } // if incoming start is specified, then just use it if ( incomingName!="" ) foreach AllActors( class 'Teleporter', Tel ) if ( string(Tel.Tag)~=incomingName ) return Tel; for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) { NewRating = RatePlayerStart(N, Team, Player); if ( NewRating > BestRating ) { BestRating = NewRating; BestStart = N; } } if ( PlayerStart(BestStart) == None ) { log("Warning - PATHS NOT DEFINED or NO PLAYERSTART with positive rating"); log(" Player:" @ Player.GetHumanReadableName() @ "Team:" @ Team @ "Player.Event:" @ Player.Event ); DebugShowSpawnAreas(); BestRating = -100000000; ForEach AllActors( class 'NavigationPoint', N ) // consider all playerstarts... { if ( PlayerStart(N) != None ) T = PlayerStart(N).TeamNumber; else T = Team; NewRating = RatePlayerStart(N, T, Player); if ( InventorySpot(N) != None ) NewRating -= 50; NewRating += 20 * FRand(); if ( NewRating > BestRating ) { BestRating = NewRating; BestStart = N; } } //Assert(true); } // Checking if PlayerStart requires controller to spawn with a forced Pawn class if ( SpawnManagers.Length > 0 ) for (i=0; i 0 ) { for (i=0; i 0 ) for (i=0; i DamageType ) { if ( (instigatedBy == injured) && (class(DamageType) != None) ) Momentum *= 0.3; return Super.ReduceDamage(Damage,injured,instigatedby,hitlocation,momentum,damagetype); } function int AdjustDestroyObjectiveDamage( int Damage, Controller InstigatedBy, GameObjective GO ) { local PlayerController LocalPlayer; if ( AIController(InstigatedBy) == None || InstigatedBy.PlayerReplicationInfo == None ) return Damage; LocalPlayer = Level.GetLocalPlayerController(); if ( (Level.NetMode == NM_StandAlone || bPlayersVsBots) && (LocalPlayer == None || LocalPlayer.GetTeamNum() != InstigatedBy.GetTeamNum()) ) return Damage * GO.BotDamageScaling; return Damage; } // // Cheats // function WeakObjectives() { super.WeakObjectives(); bWeakObjectives = true; } /* // remove me exec function function CompleteObjective() { DisableNextObjective(); } exec function WinRound() { EndRound(ERER_AttackersWin, None, "consolecommand"); } exec function FinishRound() { EndRound(ERER_AttackersLose, None, "consolecommand"); } */ function DisableNextObjective() { local GameObjective GO; for ( GO=Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) if ( CheckObjectivePriority( GO ) ) { GO.CompleteObjective( None ); break; } } function QueueAnnouncerSound( name ASound, byte AnnouncementLevel, byte Team, optional AnnouncerQueueManager.EAPriority Priority, optional byte Switch ) { local Controller C; if ( !IsPlayingIntro() && (ASound != '') ) { for ( C=Level.ControllerList; C!=None; C=C.NextController ) { if ( C.IsA('PlayerController') && ((Team==255) || (C.GetTeamNum()==Team)) ) PlayerController(C).QueueAnnouncement( ASound, AnnouncementLevel, Priority, Switch ); } } } static function PrecacheGameAnnouncements(AnnouncerVoice V, bool bRewardSounds) { Super.PrecacheGameAnnouncements(V,bRewardSounds); if ( !bRewardSounds ) { V.PrecacheSound('Draw_Game'); V.PrecacheSound('New_assault_in'); V.PrecacheSound('You_are_attacking'); V.PrecacheSound('You_are_defending'); V.PrecacheSound('Red_team_attacked'); V.PrecacheSound('Blue_team_attacked'); V.PrecacheSound('Red_team_defended'); V.PrecacheSound('Blue_team_defended'); } } /* OBSOLETE UpdateAnnouncements() - preload all announcer phrases used by this actor */ simulated function UpdateAnnouncements() {} function GetServerDetails(out ServerResponseLine ServerState) { super.GetServerDetails( ServerState ); AddServerDetail( ServerState, "RoundLimit", RoundLimit); AddServerDetail( ServerState, "RoundTimeLimit", RoundTimeLimit ); AddServerDetail( ServerState, "ResetTimeDelay", ResetTimeDelay); AddServerDetail( ServerState, "ReinforcementsFreq", ReinforcementsFreq ); AddServerDetail( ServerState, "PracticeTimeLimit", PracticeTimeLimit); } static event bool AcceptPlayInfoProperty(string PropertyName) { if ( InStr(PropertyName, "bAllowTrans") != -1 ) return false; if ( PropertyName ~= "TimeLimit" ) return false; if ( InStr(PropertyName, "GoalScore") != -1 ) return false; return Super.AcceptPlayInfoProperty(PropertyName); } static function FillPlayInfo(PlayInfo PlayInfo) { local int i; super.FillPlayInfo( PlayInfo ); // Always begin with calling parent PlayInfo.AddSetting(default.GameGroup, "RoundLimit", default.ASPropsDisplayText[i++], 0, 1, "Text", "3;1:999"); PlayInfo.AddSetting(default.GameGroup, "RoundTimeLimit", default.ASPropsDisplayText[i++], 0, 1, "Text", "3;0:999"); PlayInfo.AddSetting(default.GameGroup, "ResetTimeDelay", default.ASPropsDisplayText[i++], 0, 1, "Text", "3;0:999",, ,True); PlayInfo.AddSetting(default.GameGroup, "ReinforcementsFreq", default.ASPropsDisplayText[i++], 0, 1, "Text", "3;0:999",, ,True); PlayInfo.AddSetting(default.GameGroup, "PracticeTimeLimit", default.ASPropsDisplayText[i++], 0, 1, "Text", "3;0:999",, ,True); } static event string GetDescriptionText(string PropName) { switch( PropName ) { case "RoundLimit": return default.ASPropDescText[0]; case "RoundTimeLimit": return default.ASPropDescText[1]; case "ResetTimeDelay": return default.ASPropDescText[2]; case "ReinforcementsFreq": return default.ASPropDescText[3]; case "PracticeTimeLimit": return default.ASPropDescText[4]; } return super.GetDescriptionText( PropName ); } static function bool AllowMutator( string MutatorClassName ) { if ( MutatorClassName == "" ) return false; if ( static.IsVehicleMutator(MutatorClassName) ) return false; if ( MutatorClassName ~= "UnrealGame.MutLowGrav" ) return false; if ( MutatorClassName ~= "xGame.MutQuadJump" ) return false; if ( MutatorClassName ~= "xGame.MutInstagib" ) return false; if ( MutatorClassName ~= "xGame.MutZoomInstagib" ) return false; return super.AllowMutator(MutatorClassName); } static function array GetAllLoadHints(optional bool bThisClassOnly) { local int i; local array Hints; if ( !bThisClassOnly || default.ASHints.Length == 0 ) Hints = Super.GetAllLoadHints(); for ( i = 0; i < default.ASHints.Length; i++ ) Hints[Hints.Length] = default.ASHints[i]; return Hints; } //============================================================================= // defaultproperties //============================================================================= }/j//============================================================================= // Ammo_Dummy //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class Ammo_Dummy extends Ammunition; #EXEC OBJ LOAD FILE=InterfaceContent.utx )%SSY.$*@}/$@?*@}/$?*}/ "6:C^:'Z 8Z$=$L>}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y9$$=}/$)\=$?}/$>$?}/$?$@?}/Z 8Z$C$C}/ Z$B$B}/Z$B$B}/}/$HB$Z$@$@}/PZ$L=$L=}/}/E YLB }/Q Z 8Z$D$D}/ Z$$}/Z$$}/}/~ $?}/li"n""L$"SY$*@}/$?*@}/ "6:Z 8Z$A$A}/ Z$B$B}/Z$B$B}/}/$D$Z$ A$ A}/}/i(S)%SSY$*@}/$?*}/ "'Z 8Z$$ #=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y+$$?}/$>$>}/$?$}/Z 8Z$B$B}/ Z$B$B}/Z$B$B}/}/$D $Z$?$?}/}/}t$@@q(S;S[:;Y$*}/$?*}/W$Z 8Z$?$@}/ Z$?$?}/Z$?$?}/}/c2KZ$B$B}/Z 8Z$@$@}/ Z$B$B}/Z$B$B}/}/$A$Z$+?$?}/XZ$$H}/W}/(S;)%SSh"2KZ$B$B}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$?}/$?$?}/Z 8Z$C$C}/ Z$B$B}/Z$B$B}/}/H$@0S"Z"$Z$?$?}/}/}Mv"t$HBqG$@?S"Z 8Z$@$@}/ Z$B$B}/Z$B$B}/}/$D$Z$#tI$#tI}/}/)%SY=$*`}/$?*0}/$fff?*0}/$?*}/ "6:AZ 8Z$$?}/ Z$$}/Z$$}/}/,Y9$$?}/$>$@}/$@?$@}/$?$@}/Z 8Z$@@$@}/ Z$B$B}/Z$B$B}/}/$D $Z$?$?}/QZ 8Z$$}/ Z$$}/Z$$}/}/}/SY=$*}/$>*@p}/$(?*@p}/$?*}/4$(? "6:A^:'Z 8Z$L=$L=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$A$HB}/ Z$B$B}/Z$B$B}/}/$ A0$Z$?$@}/}/}/k }/}/d$}/m:`6V!)-9:9:$G2YQnB,,e,e,e}L}L}L}L}L3}3}n%3}Zs,eؚ,ehؚɢ3}n% we b`DIFH}/}/L#}/}/x5}/}/G#}/}/])}/}/U!}/}/n@}/t0}/W}/}/g }/}/z)}/}/j}/}/~, }/},}/s.}/}/h}/}/\#}/}/T }/}/}}/}/b}/}/`}/}/@'}/}/~! @}/}/~(}/}/Z(}/}/^(}/}/S!}/}/S }/}/] }/}/l'}/}/}/v:h8I@vÄʁ)y"~ 3},e,e,ezVGB u u u u u u o%$@\N1n }/}/a}/}/ }/}/v$}/}/B*}/}/E#}/}/w(}/}/}/}/u#}/}/l }/}/}/}/Q$}/}/N#}/}/k}/}/}/}/~#}/}/K&}/}/}/}/}/}/E!}/}!}/] }/}/}/}/v!}/}/I#}/}/s!}/}/L }/}/}/}/g1}/}/x!=K!}/G)}/}/Z}/}/g)}/}/s}/}/q(}/}/c$}/}/w"}/}/P*}/}/}/}/W }/}/u }/}/v*}/}/_# }/}/G }/Y}/~"}/}/}/}/U @}/}/E.}/}/l( }/}/j }/}/y)}/}/w&}/}/}/}/J'}/}/f}/}/a }/}/m(}/}/L$}/}/b=}/J$}/}/d+}/}/V"}/}/W!}/}/p"}/A"}/f }/}/}/}/s-}/}/@$}/}/}/}/}/}/R'}/}/V$@}/}/b1}/}/l/}/P}/}/}/F*}/}/}/}/j)}/}/}/}/x-}/}/}/}#}/v)}/}/Y&}/}/i,}/}/\ }/}/^* }/W9i3f!2vK!/#;׿e]ؚؚ'ҽؚҽؚҽҽؚ'ҽ'ҽ''ؚ''ؚ'ؚ'ؚ''ؚ''ؚ'ؚ''ؚ''ؚ'ؚ''ؚ''ؚ'ؚ'ҽ'ҽ'ؚ'ؚҽҽ'ҽ'ҽҽ'ҽ'ҽҽ'ҽ'ҽ''ҽ'ҽҽҽҽҽ''ҽҽҽ'''''ҽҽҽҽ'ؚҽ''''''ҽҽ'ؚҽ''ҽ''''ҽ'ҽ'ҽ''''ҽҽ''ҽ''ҽҽҽҽ'Gp ҽ, ҽ'ҽ''ؚ'ؚ'ҽ, ҽ'ҽ, ҽ''ҽҽ'ҽҽ'ؚ'ҽ''ҽҽҽҽ''ҽ, ҽ'''ؚ'ؚ'ؚ'ؚ'ҽ'ҽҽҽ'ؚҽ''ҽҽҽ, ҽ'ҽҽҽҽ, ҽ'ҽҽҽҽ''hҽҽҽҽ''hҽҽҽ, ҽ'ҽҽҽҽҽ b`DIFHJ&= ObjectivesI&]*G&]xA&]...~%] }%]-|%$@}/}/\/}/}/C%}/}/B!}/}/_-}/\}/C&}/}/['}/}/{#}/}/}/}/R#}/}/B)}/}/A*}/}/q$}/}/}/}/H*}/}/}/}/M$]}/}/}/j!}/}/A&}/}/E)}/}/g(}/}/}/}/^!}/}/T!}/}/`#@}/}/?}/}/|4}/}/e!}/}/}/}/g!}/}/n }/}/}/}/}/ j:t2\%Bm!B |w =R3Bk<3}3}hhR3Bk<hhhhhhhhhhhhR3Bk<hhhh,e e *}/}/z2@}/}/}/}/]$}/}/Z)@}/}/d }/}/O }/}/k-}/n9z0i%9:9:$G@2u!K>ؚ}L}L|||3}WSF}L}L}L}L3}}L'5M7<'5M7<'5M7< e DIFHp!t J]Destroy Vehicle Objectiveg! Q"]"!Destroy Objective to disable it.W]Destroy Vehicle ObjectiveX]Protect Vehicle Objectivee }e"Y}/}/I%}/}/m}/}/}/}/}/}/h'}/}/u*}/}/m }/_9l1m%@J}!;ܓW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽW=ҽ JY P7O7N7M7L7\;1S?}/}/U$@}/}/\4}/}/}/Y9U9T&A"QAʁ) uҽҽ uʁ)ҽ `&:AAJ! J! x  x  " j$SNuQ$Sn$u$w>\ "}/}/ B t#n} d t#t#t#at#Rw**v at#  G}/}/}/}/}/D;}/a9@2l%@@d%ܓW=W=W=W=W=W=W=W=W=W=W=W=W=W=W=W=W=W=ҽW=ҽW=W=W=W=W=W=W=W=W=ҽW=ҽW=W=W=W=W=W=W=W=W=ҽW=ҽW=W=W=W=W=W=W=W=3}W=W= JYS;T;U;;1S?}/}/}/u!}/s&}/}/}/}/}+^}/z+}/}/}/}/c&}/}/k%}/}/}/}/}/}/`9}/}/A/}/}/}/}/x%}/}/@}/_:}/}/}/}/}/A3@}/}/}/}/S&}/}/}/}/@}/k:}/}/}/N$}/}/g+]}/+}/}/@&}/}/@}/^2}/]!}/}/}/}/h$}/}/F(@}/}/j+}/}/E&}/}/F&}/}/H$}/Z}/J&}/}/h.}/}/G&}/}/r9}/}/@/}/}/Y+}/}/}/}/}/}/z%^}/N+}/}/I$}/}/g.}/}/W+}/}/@}/}/T&}/}/T,}/}/}/}/K#}/}/I+^}/^}/}/}/}/}/@}/}/P/}/}/ }/}/r :}/d&}/}/}/}/Q:}/_,}/}/e,}/}/V/}/}/}/}/}/}/j&}/}/t*}/}/}/}/q,}/}/W3=}/k*}/}/@ }/}/f*}/}/u&}/}/}/}/}/\9~1]$2v&Fݎ u b`DIFHf] Top Gun!f  Wrecker!f('Vehicle spawn blocking! 5 secs warningf('Vehicle spawn blocking! 4 secs warningf('Vehicle spawn blocking! 3 secs warningf('Vehicle spawn blocking! 2 secs warningf'&Vehicle spawn blocking! 1 sec warningfLeaving battle field!l!A"l!D$W S_ O*] >$w>\ "}/}/q"}/}/o!}/}/}/}/\*}/}/}/}/Y*}/}/[%}/}/}/YV9n6e$"&^ȵʁ)ʁ)ʁ)ʁ)hʁ)R3Bk<ʁ)ʁ)ʁ)3}\*F\*F\*F h\[$zEw$Ey$AR$zDgx+"u A$@@RT$HBMN$AO$@}/}/o$}/}/U*}/}/],}/}/Z c}/F }/}/J*}/}/}/}/}/}/X%}/'}/}/}/K$}/}/n#}/}/^8}/}/G@~k4}/E$}/}/u,I}/x }/}/@8}/}/|#}/}/Y'}/}/}/}/}/}/}/}/X'}/}/T$}/}/}/}/}/}/X"}/}/o)}/}/}/}/`'}/}/Y$}/}/e'}/}/n)}/}/m)}/}/@}/}/n4}/}/k)}/}/{,}/}/Z"}/}/^)}/}/h!}/}/}/}/m0}/}/g'}/}/}/}/q'}/}/g"}/}/X#@}/}/}/}/[)}/}/X)@}/}/}/}/y!}/}/}/}/Q)}/}/}/}/`$}/}/D%}/}/D }/}/}/}/}/}/}/v}/Rw/}/d6}/}/~$}/}/E(}/}/}/}/k"}/}/G(}/}/C(}/}/}/}/X @B&a5}/}/}/\6}/}/}/}/}/}/i$}/}/P(}/}/}/}/V(}/}/x}/'}/L(}/}/}/'}/R(}/}/T(}/}/k$}/}/k5}/}/}/'}/f }/}/J"}/}/a(}/}/b(}/}/s }/}/D"}/}/`(}/X}/](}/}/}/}/}/}/}/}/e c"}/b}/}/}/}/d-@}/}/j(}/}/G6}/}/U(}/}/s0}/}/I }/}/p(}/}/j$B0] G}/M(}/}/i5}/}/f!}/@0@}/}/K(}/}/r(@}/}/ }/}/}1}/}/D&}/}/j-}/}/}/}/l-}/}/}/}/T}/}/}/}/}$}/}/c6]"+gd9:9:$O!a_- dwO!*O!a*O!u+?+? G}/U }/}/}/}/B%}/}/|"}/}/}/}/}'}/}/Z0}/}/H)}/}/{'}/}/s/~}/K)}/}/}/d%}/M)}/}/S-}/}/}/}/M-}/}/z'}/}/n-}/}/x'}/}/}/}/u-@}/}/r'}/}/s'}/}/}/}/q!@}/}/u'}/}/@}/}/\)}/}/H%}/}/c.}/}/}/}/t}/}/O}/}/U }/}/}/}/m'}/}/n'}/}/@}/}/h)}/}/j'}/}/i)}/}/Z$}/}/f!}/}/}/}/}/}/A!}/}/}/}/}/}/q)}/}/}/}/X U}/W$}/}/I.}/}/K.}/}/T'}/}/]/}/}/V'}/}/{ }/}/P'}/}/Q"I}/x)}/}/T.}/}/|)}/}/m#I}/}/y"}/z}/}/C*}/}/}/}/B"}/y"}/H'}/}/G'}/}/o#}/}/i"}/}/{}/}/K*}/}/L*}/}/M*}/}/C'}/}/V }/}/v3}/}/P5}/}/Y,}/}/}/}/y}/}/ @!/pb Jw*qկ9?9?,2!}/a((a'' G }/U,}/}/I(}/}/}/}/}/}/z&}/}/}/[9c1n%2 [*B4F݅ҽҽҽҽҽҽҽҽҽzVGB b`DIFHq!]#"You have completed the Objective!q!completed the Objective!q#` _ O*] >$w>\ "}/}/_*}/}/e3@}/}/v#}/}/`*}/}/c*}/}/R }/}/~0@}/}/S,}/}/a*}/}/C"=}/b%}/}/}/}/R,}/}/w,}/}/i*}/}/V8}/}/Y/}/}/[=}/p&}/}/o,}/}/l&}/}/n,}/}/m*=}/}/}/y*}/}/k&}/}/K}/}/S1}/}/}/}/z*}/}/|*}/m9z9k% {*1><qYԉhȵhhSGhhhSG \ [Z,[&Q:HC`A`M}/P}/P $ff>l$Gl]TranslocatorFirep$>aaB: Bc:D}$@i:?F:D$@C$p}?F$>}/}/F,}/}/q#}/}/s#}/}/@+:}/b&:}/c}/}/D+:}/I:}/}/O/:}/}/R}/M/:\:Y1c%3G+op ~])(%k took out %o with a barrel explosion.]65%o was a little too close to the barrel she blew up.C ]54%o was a little too close to the barrel he blew up.B%p$w"s"$>}/}/F/}/}/s%^}/L+}/}/}/}/}/A}/K+}/}/Q,}/}/l}/}/[+}/}/}/}/X9S+^H-(:w*-Y+--(N&aS+T+U+N,'rN&*S+U+T+#-'w*--Y+N& G}/T+}/}/U+}/}/N,}/}/}/}/n}/}/N}/}/}/}/R+l!nJl!l! Y l! Y l! Y l! Yp#l! Y~l!Y6 G }/}/A}/Z+h,L Y  Y  Y  Yp# Y~Y6 G}/M&}/}/P&}/}/`+^}/^}/C,]}/^+}/}/y:}/}/}/}/b+}/}/k.@}/}/@}/v9}/r.}/}/h+F G}/m+}/}/B&}/}/t+}/}/X.}/}/]2}/}/@}/}/q:}/yf:~8i#q+5";Qyg{"R3Bk< "3$?.$B5$B}/}/l+}/ga:K9y"s+1og*}/R3Bk< "3$?.$B5$B}/}/^:}/y]:b%u+9yg{" $?b:C.$B5$B}/U:e%3v+mQG e `K~]+*%o was mowed down by %k's minigun turret.]#"%o turned the minigun on herself.C ]#"%o turned the minigun on himself.Y"V"r":Dt"$Du"$@?}/}/X:}/R:h%3x+>%G e `R~]0/%o was served an extra helping of %k's lasers.],+%o fried herself with her own laser blast.C ],+%o fried himself with his own laser blast.V}/}/}/}/a& }/}/i%^}/{+^}/|+^}/x9}/}/O$}/}/~+}/}/e+}/}/t9}/}/|%]}/B,}/}/D,}/}/}/k9Q2S%@G,= ܌3} JYG;H;I;;1Swn}/b9C$@H,z  JYK;L;M;N;O;P;Q;R;;1Sn}/}/J,}/}/K,}/}/L,}/}/g9}/}/}/}/q9}/}/}/}/Q+}/}/P,}/}/| }/}/g*}/}/F$}/}/|&}/}/}/}/T9}/}/tW,K 9?[.~wS!qկ9?9?,dS!q9?,dկ9?,d9?, w.S!*.S!-q?qqqD9?,dL> W,q G}/}/&M9s6f$"Z,:&^d%\*F }/}/}/}/}/}/[,}/}/F'}/}/`,}/}/a,}/}/b,}/}/c,}/}/g&}/}/}/}/f,}/}/g,}/}/h,}/}/E }/}/d,}/}/h"}/}/Y%l8O G}/}/a8k0L&m,+Z@SGhh3}hPPhPPW=hP w T$?r Pz~N3}/}/}/}/q*}/}/\8}/o*}/}/vX8[U1-F w6s, 6(Y'U%eP 9?% Y'P (vY'(U%99t,9?%(-GS'U%6S'v,ի@999PS'b$U%' G}/U%}/}/T8}/}/{)I}/S'}/}/f%}/}/O%}/}/w7}/}/k7y,q%cP%y, :6P%H*@(6P%P%@ G}/|,}/}/e)}/}/h ]&t%b#Q&y#^%C&D&E&\"M%H&]"}/,@}/}/@-@}/}/A-@}/}/C-@}/}/t'}/}/V7@}/}/d#}/}/}/}/a7T7j2V( G}/I-@}/}/F-S7y3( G}/L-@}/}/H-[4 G}/J-K5 G}/N-@}/}/}/}/O-@}/}/P-@}/}/R-@}/}/P }/}/@}/}/N)}/}/L)@}/}/T-@}/}/U-@}/}/V-@}/}/W-@}/}/q6}/}/J)}/}/A)}/}/e6[-T 952K(a d% [-A)9?,9PA) G}/}/}/]-}/}/}/\}/U6}/}/Q6}/}/L6}/}/I6}/}/h(}/}/}/}/}/}/@}/}/g-}/}/[}/}/N(}/}/x(}/}/m-}/}/o-}/}/B(}/}/i!}/}/n"}/}/p-}/}/q-}/}/r-}/}/T)@}/}/J5@}/}/Z#}/}/v-}/}/w-}/}/Cc)go0*f9wm'*m'a/!~7rm'`$q!i  y'c)cc)!G!q!D! G}/}/}/z4}/}/t }/}/r}/}/e#}/}/~-}/}/s4}/}/-}/}/^'}/}/B.}/}/ Iw&A,#* G}/C.}/}/b4}/}/L}/}/_a4a1#YV9:9:$-f  BV9?,dA,#* G}/G.}/}/^}/}/J.}/}/W'}/}/}/}/O.}/}/}/}/M'~}/l#}/}/@%}/}/~)}/}/k3}/}/V.}/}/}/}/o+}/}/V*}/}/[.@}/}/w }/}/\.}/}/].}/}/}/}/`.}/}/{ }/}/a.}/}/@}/}/f@}/}/N }/}/e.}/}/f.}/}/@}/}/F3}/}/b}/}/I&@}/}/M @}/}/j.@}/}/}/}/`2}/}/n+@}/}/}/}/q.y G}/i+j G}/}/}/D(}/}/H2}/}/n }/q }/u }/w%}/}/u%}/}/t%}/}/}/}/{.}/}/}/}/u( }/}/v(}/}/C/}/}/}/}/.}/}/D/}/}/}/}/Q}/}/i1}/}/B/}/}/S}/}/e%}/}/}/}/I/}/}/x#:}/ :}/}/}/_:}/R/@}/}/}/}/_1}/}/}/}/*:}/}/}/}/}/w*}/}/}/}/Z/}/}/[/}/}/}/}/m!}/^/}/}/w!}/}/b'}/}/r)U}/qu Y- -GH G}/k(}/}/b/}/}/c/}/}/`/U}/i/}/}/S#}/'}/}/}/"}/}/}/}/}/P}/k/}/}/}/}/^}/P#}/'}/n/^}/A#}/}/}/}/u/~}/[0}/}/~'~}/}/}/z/o p q }/'R}/}/}/x/R}/}/}/{/}/}/}/}//@}/}/t(@}/}/I!@}/}/fD0e"HQ9-o(-G-G'-M('i$%i$7_e"i$_ we"*e"%e"--M((re"*e"a/!-G(i$$--M(-o(-Gg-GJ$J$ G}/}/}/}/}/qE0bG H G}/a/G0u B H G}/ay(J B9:e 9:y( e y(?9:9:$V G}/sN0H=J H G}/I0L5*L*iu/* G}/K0{"J (w{"*w{"Q"*w{"Q"~'r{"Q"-m#{"Q"oJ {"Q"L G}/b`[EbwI *I a4wE!*E!ae $H G}/P0i!!":g*~'ois/* G}/}/}/D}/e79+- - -  -  }/ G}/wR08 H G}/L0}/}/W0O0O i! G}/y|/A 35MJ-{/ wg* -@)-@)'|/]g G}/S0a,p7wI *I a.wE!*E!a G }/{d(!0{7,%*&%d(H G }/n(y/w 0Xy/ G}/T0Y0r!'AG}/j$v/s-v/q!y G}/I)!62/I)!}//a0 v~'I)..10 G}/w/F)`V9:'9:$'|'9=ya9:'9:$F)9:|''9:'9:$F)&9:|''( G}/V0t/k% qt/-r/( G}/|'}/}/r/}/}/X0q/e+kA#.q//rA#*`A# A#0Az/A#A# #x/ G}/U0_0t!0G}/a!}/}/j$m/s--m/q!v G}/p0o/P1\(.P#K--G rP#* r\(* p%p7_rp_o/^(ppRp^(&:p7_0wp_ *Qrp_ *,p_ a/!D"p_:prD"*p%p^(wp_ *Qrp_ *,p_ a/!D"p_pLwD"*P#-b(%P#P#@'D" U\(D" -%D" b( G}/p/b0O9:9:$ D#.%wD#*p/D#D# ^$-n/D#D#Q G}/c0}/}/D#}/}/ [_$Aa!s wa!*Ora!*a!f _$a!'a!a!a! A_$'rh#*h#h#h#f _$*h# A_$' G}/i}/}/]0r0yJG}/j$j/s6-j/q!v G}/~ a w~ *~ a G}/h0W){-:19:9:$ w* 9:%9:%W)/r~ *~ ak/ W) w~ *~ ul/~ a*%~ w%~ w ,1w* 9:% 9:%G?! G }/ n0e0s \ Hi?wi*(i-i-i-!9:i#. miwi*wiii*r}*}i(sri*pw}*9i-#9:}9:i}i(r}*}}(i}}i((}-1}}}iii } G}/i0l0/C6w*w.*Z$. M f)h)i) f)6Z$h)6Z$i)6Z$ G}/f)}/}/g}/}/ q0k'C#9g>wg*g-(gg X! wX!*wX!k'wX!*X!%X!-'X!X! Iwk'*k'tr*--!9:%. m\#*o'HDg0wg*g-g-g-!9:g#. mg5r*-L"'ww\#*(g \# o'-L"'g--g-- 33>-L"'--L"'g"\-M9:9:gg"33?Yg"?9:9:gg"33?9:9:gg"333?-L"g">-L"gw\#*o'g \# gg G}/n(g0h/]<t7I!h/q(4I!?I!?q!t! G}/Z g/\[(.S#K--G rS#* r[(* o%o7_ro_g/Z(ooRoZ(&5o%+wo_ *Qro_ *,o_ a/!J"o_5orJ"*o7_&oZ(wo_ *Qro_ *,o_ a/!J"o_oOwJ"* S#-a(%S#S#@'J" U[(J" -%J" a( G}/ h#f/N Y\" Yw"*Br"f/" Ni/""   G}/o0d/WFf7&-k(8Wd/c/-b/-k(# G}/}/}/}/'}/f0h1vd G}/}/}/_C d%x8j 9Dף>Wf 9D??W9?j j 9D?W9?,f f 9D9?f 9?C ?WV 9D9?f L=9?j ] 9D9?f ?9?j N*9D9?f Q8?9?j -W$e#Wk W$WW9?f 9?T W-C 9?j 9?khfbW9?z)W9?5wC *_'C  Y$C  K_'Y$u 9D9?T 9?Y$b9?fWb&@?W9?f 9?u fW' 9?j 9?T fu W$WC WF>?9?C W9?_', b9?u wC *W C bV$WW @"V$WaTESTcP'u %u 9D9?T P'Su 9D9?u ?9?Y$b?P'W?>?9?C W9?, b9?u W$a9S9DC WV$WbW9?#k% NC %W kW `kb'k&b'kZ&%Zb'W99?V 9?T hfZ?9?fW$ fff?9?j z)9?,ZWx 33s?9?] V Z%ZkZmZWaZmcjc@$x U$Zm@$cZd`k`m`Wa`mcjc@$x U$Zm@$ci@$9?%-X$'WEWk &WaU$cjUcx WEWk ,WaU$cjUcx WEWk ,s)WZ% ZkZmZWaZmcj cx ZmZm9Dx c9?}ZmZp `k`m`Wa`mcj cx `m`m9Dx c9?}`m W9?K$9D?j  -W$K$9D>jW$WW&?W9?T ,s9D9?T ?9?h?jW. `Z%+ Zk! Z`W-9?V 9?hf9?Z9?sWaZm'Z  Z% Zk Z`WD9?V 9?hf9?Z9?s?j9?K$WaZm'Z5  -X$WEWk WZ% Zk Z`W-9?] 9?hf9?Z9?sWa9S9DZ'Z Wa0^/w!m)WW c9DWZ%+Zk!w.YZ*.YZH"B!9:.YZa#%A!.YZH".YZH"9?, W\9?] A!9?,b9?hf9?Z9?sw!?9?,bW4a BbBbcCCTB(B!9:.YZa#&| 9R.YZa#Wa| cjWq9?] A!9?,9?,bc?9?hf9?Z9?sw!?j?W a| 'Z Z%KZkAw.YZ*A9:.YZc#%A!.YZH".YZH"9?, W\9?] A!9?,b9?hf9?Z9?sw!?9?,bW4a BbBbCCA9:.YZc#&| 9R.YZc#Wa| cjWq9?] A!9?,9?,bc?9?hf9?Z9?sw!?j?W a| 'Z2Z%kZkaw.YZ*a9:.YZb#%A!.YZH".YZH"9?, W\9?] A!9?,b9?hf9?Z9?sw!?9?,bW4a BbBbCCa9:.YZb#&| 9R.YZb#Wa| cjWq9?] A!9?,9?,bc?9?hf9?Z9?sw!?j?W a| 'ZRWm) `%`kL#hfksW$W)9?f 9?T hfkWC 9?j 9?hW$w`*WW.9?V 9?,0b9?L#9?,bW4aBbBbCCL#hf`sWW+9?V 9?L#?j9?K$q-X$Ws)Wa`m'-X$WEWk W9?] 9?L#`-W a' Wa9S9D`'WOC %_/&`%W9?s9D9?T ?9?h9?K$W k ,-W$(W9?WK!9DWk ,GWK!9DWk &WaTestcjZ%#ZkJ'%Z-w.Z*w.Z*J'&W-9?V 9?hf9?Z9?sW9? ~!ppp(Z@ ) .Z] .Zz~!.Z^ .Z~!ppp(Z@ ) ~!Wa~!w)]/zw)9?] V ~!ppp(Z@ ) .Z] .ZW a~!'-W$Z-W=9?V 9?hf9?Z9?s9?J'jWaZo!'Zj`kW-9?V 9?hf9?Z9?sWa`o!'9:9:$ WV$WaTestcjs9D9?T ?9?h?jj%Wk T hfs`kN* G}/@}/}/x0@}/}/ F1v0kO@- rx*9?xx G}/L!!  G}/{0aW'wL!*L!aL!* G}/|0M%l aM%\/(M%%wM%*6M%&y'( G}/y0@}/}/}/}/}0A1mBEG }/N%e1)wN%*N%a/!Sl.N%i %.wi *ri i Ri s!'wi *i Ni .N%i i lq!d G}/}/}/j$Q/sP*-Q/q!y G}/@1E1{ In/a3 q&lq&@ %.w@ *r@ @ Rw@ *@ N@ q&@ @ T0'10@ %.iw@ *Rr@ @ s!(@ @ #( G}/q&}/}/[1z$e?u- rx*(fz$ |xz$Attack Objectivez$ \!x'z$ G}/Z1R%V R%l*Y/Z/[/l* *% P&R%$ L)$ U, |,R%$ M)$ ,R%$ S-$  G!}/D1K1dk G}/J1{b { q!m G}/}/}/I1Khn rL!*L!a  G}/H1M1Z ? G}/N"Kv N"%.wN"*srN"N"--s*'N"N"6-s*q!d q!\ G}/@}/}/N1}/}/L1Q1\ G}/Ku !wL!*L!aL!* G}/P1[ q!m G}/O1}/}/G"! RB?rG"*G"a ?wG"*G"@ G}/T1a''wG"*G"aG"* G}/U1W1{%R/a3 i&NMw.i&*.i& d v&,10 G}/i&}/}/X/}/}/ h&U"D%h& (V/%&h& AAL?&h&  G }/W/[ W/ *%pw* X- =& W- Q, V- u,pw* U- , T-  G }/ ]1X1O5<9-.miX/ G}/~*}/}/`1U/Y -bTwx*x%x'bx x _iU/ G}/\1}/}/^1}/}/a1S/%89?&xS/x-' G}/Q(S(!oe/a0 'S(a`S(R Q(S(xQ( Q(e%a10 G}/`&}/}/q1} O#*t} aP/(R/%s#`&9?,~*6} } } 9=,9=,9=,6} ~*} S}  s#`&>}  `&?s#?} &a s#s#CC G }/@}/}/n(C1N/]V7I!N/q(4I!I!q!r! G}/d1}/}/}/}/e1G/W`7&-v(8WG/B/-.-v(# G}/f1}/}/ RQ e7wQ *Jry *y .Q Q Take Energy Core to vehicleQ  R Q ry */a9 y 10ry *NO ENERGY CORE(wy *Q Protect Energy Core holderSy  Q  9?(Q R Q y Q Go pick up Energy CoreQ R Q y  G}/TJ/Y J/ G}/s1w!#E6&% 9=,$`$@6,% 9=,$`$@6&& 9=,$`$@6,& 9=,$`$@6&, 9=,$`$@6,, 9=,$`$@6&, 9=,$`$@6,, 9=,$`$@6&, 9=,$`$@6,, 9=,$`$@6&, 9=,$`$@6,, 9=,$`$@ G}/y h^ 1-b& Y  Y er* {]%]% w* n G}/m1Mo-&-b& d  G}/n1p1E x' G}/}/}/V&H+[ kDH+ %%V& /&F/&V& H+&V& G }/M~!lxf(uw *6w * @'n - a!t a * G}/x!-6&% $$$@6,% $$$@6&& $$$@6,& $$$@6&, $$$@6,, $$$@6&, $$$@6,, $$$@6&, $$$@6,, $$$@6&, $$$@6,, $$$@ G}/v1G"5% 6%& $`$9=,6&& $0$9=,6,& $0$9=,6&, $@$p$6,, $@$p$ G}/Op%b NA/9:cp%6p%%6p%%K/aI/ p% G}/L :19:9:$.% ,d G}/x1{$a!9Z{$9D9?,*9?, /9:{$u(%a a{$~. @ D{$u($ G}/~.x#u-aaa>a a}/G}/O |.A Q(MJ-{. -A+ w_*-A+'|.]_ G}/{1}.u _66%B}.66%66% G}/w06%% $$P$0 G}/Wkz.u C PWz.M7F%t%%Mt%7Ft%Fu t% G}/}/}/O2]+V jb]+M&@/C/D/_M&,&n+!}/]+y$M&,&n+$' G!}/|1y.\PNK7F%u%%Ku%7Fu%F \y.Ku% G}/C2 u:U   @?66%@ 66%HB 66%B 66%C 66% 66%66%66%66%66%66%66&A 66&HB ,%,% G}/@}/}/1x.P\NK7F%w%%Kw%7Fw%F Px.Kw% G}/E2X/g!6%% 9=,9=,$@6&% $9=,$ 6%,6%%6&,6&%6%&6%%6&&6&% G}/A2}/}/I2C"$6%% $9=,$@6&% $@9=,$ 6%,6%%6&,6&%6%&6%%6&&6&% G}/S w.H&cS H&.Z #rH&* H$%`H$,H$H&}%H$w.H$* G}/D2}/}/G2}/}/K2w6%% $$$`6&% $$P$06%,6%%6&,6&%6%&6%%6&&6&% G}/S v. $S .R -v#-v. G}/L T@9:9:$%-',-(u? G}/S u. $S .R -v#-u. G}/u0ekk e$e -c9De@?Xead$A(~$k"~$9?,]s.\ We#-D('6W e6\ 6W 6\ k"I!6\ qe-D('e9=,9=,9=,9=,e!6W 6W k"wX*X%e 6\ k"e 6\ k"e9=,9=,9=,9=,e6W 6W wX*X%e 6\ 6\ e 6\ 6\ I!?e -c9De@?Xee9=,9=,9=,9=,ead$A(~$eI6W 6\ A(?6W k"~$?ead$WeW -D(( G}/P2[#uKY#Y#?66%C[#66%66%6% C[#Y#6& «9?,[#Y#66&A[#66&66&666%.&D[#Y#666%.&666%.& G}/n.t.[ Tt.,&n. G }/w6%% $$P$06&%6%%6%&6%%6&&6%% G}/! -*9:9:$? G}/ p.S2q aXff> w*w*F&99 G}/T2}/}/U2}/}/V2}/}/}/}/R2[2g]J .r 9?,djj 9?99a@9?, !a a}/Gt}/o.tGo.j G}/}/}/q.X2jT,r.).Rjq!` G}/Z2b!j)Y66@]!99b!a^!A& 9?]! (rb!* j!^! L$6]!99b!a^!A& 9?]! (rb!* n ^! Tn j!j!n L$6@]!99b!a^!A& 9?]! (rb!* n ^! n j!j!n L$6]!99b!a^!A& 9?]! (lrb!* n ^! n j!j!n L$L$ G}/Y2}/}/8}/@}/}/@}/}/%@}/_2}/\2}/}/ }2m.v"g%-m. 7H(%@& %%^%7H(7@&@&%H(%,@& G }/W2f2`r G}/e2tl  G}/}/}/i+d2Fp q![! G}/c2j2i} m6% 9?99a?.Ry a}/G\}/i2tv@  G}/}/}/i+h2Fzb q!g G}/g2m2[! 4rh+9?, yoj 9?99ag  !a a}/Gt}/Ku h+ G}/p.l2y q!i G}/k2o2r*w.R*.R-v# G}/}/}/n2q2g "r@@9?, G}/}/}/p2s2V&Mr@ G}/}/}/r2l.Q -l.*r A  G}/a2}/}/w2M =' G}/}/}/v2y2yn$ G}/}/}/}/}/u|2M +h' G}/}/}/un!|#zn!(z#n!(A|n!UnrealGame.MutLowGrav(`|n!xGame.MutQuadJump(|n!xGame.MutInstagib(|n!xGame.MutZoomInstagib(n! G }/H.2u2ac G}/D.nwc G}/M2^W.rG)%H)9:X _)-B%^ -c9D^@?X^a0D l D a 6U!?S G)S H)-{''r%gr7XbI9:rXbS rXb-]9:XVS ^ -c9D^@?X^ -c9D^+?Xw"s^crXb-B)u-B%^aw"D 6Y 6Y D 6Y @^a0D f^rXb^"6U!l 9?,a ^aw"rXb_9:XVS ^X6~"6U!l D ?6~"a >Xx^~"ff>,,-{'^6U!l a ^ a9SS &^"6U!l 9?,a ^a@0a -{'(]9:XVS gr9:XVS ^ -c9D^+?Xr%r7Xb79:rXbS !rXb-vrXbR'9:rXbS vw"s^crXb-B) -B%^aw"D 6Y 6Y D 6Y vf^rXb^a0D ^"6U!l 9?,a ^aw".rXb_^X6~"6U!l 9?,D ?6~"a >Xx^~">j^"6U!l 9?,a ^a~/a rS a-B%^ -c9D^@?X^ad$D 6Y 6Y D ^a0D l D 6Y l 9?,6Y Y # G}/}/}/ wv%M$Xd ~v%bAllowTrans(7|v%TimeLimit(U~v%GoalScore( v% G(}/r}/}/ zq A$<] q -d+-d+q ]!}!q ]!Jq ]!lq ]!kq ]!Iq ]!hq ]!Hq ]!g G }/}/}/O&}/}/@3E%s1!E%aF%G%V)@G%E%>F%Z)q!iF%r(s'X){q!q!ppq!r(s'q!pq!s'F%X)E%apq!t(G%V)@G%E%>pZ)t( G}/ rW&d$B,r.T&*rT&*W&O&p9:9:$- .rO&*!O&T&9D9?W&g. W& G}/C#k!==============ShowSpawnAreas==============7?%j%%j%7?l"j%?稨PlayerSpawnManager:9Vl"bEnabled:9Tl"-dTag:9Wl"zl"-d#zw#*A$.#rA$*cc9:A$l"n 稨 9VA$Enabled:9TA$- ##j%I==============End...........============== G}/G%@}/}/G3]qQ$ rXG * ]X o]%]$t-])c XG c XG  {c j'Q!j'&c pc /9Sj']ac N s!@N ]>X]Xo]]ac N s!@N ]>X]Xo]]ac N s!@N ]>X]Xo]]ac N s!O N 9?,@XL s!9?,Xv!]?I%s!?9?, X]]$$$$],v!O ?I%L ?]&a O L (CSC&C0B]XgXG -c. v!N ?6W v!v!N ?6W 6]$],v!N ?I%s!?] ac (6U v!N ?9?,X6U I%O AXX?L AXX?]]9=,9=,9=,9=,](6U O 6U L ]2a O 9?,L 9?,BCXBXBwXG *]XgXG O BXX>L BXX>](6U O 6U L ]DaXG O 9?,L 9?,BBv-])]XgXG g)3|]b'b(XXXb(X9?&XXP]X9:g)%6]9C9<$9?,@XX6]$O XXff>L XXff>]46U O 9?, 6U L 9?, ]4a BO BL ?C?CBBX!p]h|U ?X!p]h|U ̌? |]XXx]U ? G}/nn!P@*-q' G}/}/}/K3P3Q!24]"%]"7Xb9:]"Xb9:XV!]"XbR]"Xb-l)]"l) G}/ S3d. <# [ d.e.f. G}/]"}/}/N3R3h5T"%T"7Xbz9:T"Xb9:XVT"Xb-q)T"Xbkp)T"q)9?p) G}/T"}/}/ Y3^.@ # [ ^.`.a. G}/Q3U3|r7XG _'R"%R"7Xb9:R"Xb9:XVR"Xb-R"Xb_'R"$( G}/R"}/}/T3[3O!9O"%O"7Xb|9:O"Xb9:XV!O"Xb-O"Xb_'O"( G}/]=}/ Z3N!P7 x( G}/ \3Y.# (%[ Y.[.\.]. G}/v{! 7 ( G}/O"}/}/ ^3W.H#I[ W.o+ G}/v }/}/f3f"g#p<Rrf"*rf"*7f"f"v %-wv *v Rv _(9:.O9:v wv *'v B f"'v v qf" G}/n`3j"^F  G}/}/}/_3b3}$_v  G}/}/}/a3X%e -J&-J& G}/c3C!c$j1C!C!oC!C!C!aAa1C!oC!C!C!aAa1 G}/}/}/l3h S#XGV8q"-q"- urh w&!h q"h w&q"]*8w.Yh *rVehicleDestroyed_Trophyq"h .Yh a#8w.h *#9:.Yh a#,.h d v&&h w&q"]* G}/wZ*S"/MZ*J-M w.*.- P!Z* G}/V3M"f :B>rT%XG K"M"9=,9=,$9=,rT%-K"M"$$$9=,T%-K"M"$$$$K"M"9=,9=,9=,9=,+T%_K"b'b(K"9?&XXb(M"9=,$$@9=,XXM"K" G}/h3})c<*-T.})}) G}/{$F%|kWw*-k. - =-X*$a*('S$$'h$-X* G}/@}/}/ n3R.@#PݝbEw@%*w.Y@%*.Y@%-_ ( R.@%U.V. G}/j3T#`-vmT#(-p WT#S!T#]w * [v!T#w* wR * w *R sH!R 0kT#x v9= G}/q3V#P E*W*V# .YV#-_ (QV#(V#a/!_.V# ~$W* G}/m3p3H! RrR * r *(.R O!'-J&-h. f9?% G}/}/}/r3x$B#2(rx$*r.Yx$* ~&.Yx$X~&-_ ( y$.y$hy$Ay$`)~&_# P x$ G}/XS*O ywy*v$.yW-S*yy-S*yyya!v$ry*y&wv$*$v$o v$B$wy*w.Yy*.Yy-_ 'w.y*.Yy_#9D.Yy_#.h.Ayy G}/B L!2fG %M#G  A -N#M#%J#9D9?M#9?H#9D9?M#9?J#,<f$9D9?M#9?J#9?H#,<J#%F p9SJ#: H#, F ppF 9SH#:'F pppF 09SH#:Jf$, F pF 9Sf$cF ppF 09Sf$I(G G k-N#I(9?%F p9S9DI(9?,d%F&E&j+9?66C"66C"?F&6C"m+9?66o 66o ?E&6o K&6C"9?B ??9?B G&6o 9?B ??9?B K&9?6C"F&j+9?&G&9?6o E&m+ff>B a#B B aF X.V*B $r*D'D' v9=D'-N#-N#\-N#F p-F B B 9=,$$9=,B B $9=,$9=,B K&G&V*9?,B aF ( G}/]\!Sl\!%w\!*{9:.O9:\!\!R\!` '\!` (\!\! G}/ w3lZ $ivo$] lo$\wl*bl-@',j@', l ]#@'rObjectiveCompleted_Trophy9Rl9So$ll.Ylc#w.l*.l d [*%@"w@"*w.@"*w@"l.@"d [*&l@"@"V3l-&9:l&9:lo$\wl*zrl*_!}/$9=,_l$9=,g!l l G}/R*}/}/ z3O*mt] \(!O*-'R*.X9:O*9:R*O'( G}/ J4W%Uv<*l#Q.V'bV'~)|)x)S.a<V'W% l#l#6W% ~)6W% |)6W% x)l#l#a b G}/}/}/ 3N.e s)&w*e N.9DO. G}/s3|3b<9: d9:$ rG *kG %UG 9?%G 9?&%G G k9?%(' G}/}/}/G\M!?\ r* R!R!A ?R!\\$\B9=\>{#\A \"\A \&a A A DD\7{#\\"\A \&a A A DD\7{#\A \"\\&a A A DD\0{#\\"\\&a A A DDI* B#\"A \\R#R!8 bE#}"M.r-YG#E\v\\a_ c!T!{j\#E#}"G#R#B#\66{?c!6{?T!\ a_ (\aa c!T!{j\#BE#}"G#R#B#\66{?c!6{?T!\ aa (\ap c!T!{j\#BE#}"G#R#B#\66{?c!6{?T!\ ap (\aw c!T!{j\#E#}"G#R#B#\66{?c!6{?T!\ aw (\Q$@A\9?@{j\ I*E#}"B#\66{?Q$6{?Q$\&a Q$Q$CCBB G}/}/}/A4~3\As( G}/}/}/C4@4[r.[ G}/}/}/E4B4G r( G}/Z!}/}/`D4lqri!*Z!%wZ!*9:.O9:Z!Z!RZ!- ri!*i!Z!Z!Z!*i! G}/nc"T!"n%%%%%&%&%&c"%wc"*c"%c"c"c" G}/o@!z M\_"ResetLevel- 'A-{.U%Ss@!w@!*F*@!r@!*@!-w.@!*.@!r%@![@!F*U/a0 G'G'a/!\ G'[10 G}/}/}/L4H4c T>%&.d$$|%&.d$$0%&%%?%&.d$$.d$ $n%&.d$ $%&.d$ $.d$ 9=, G}/Ey3bk(.%J %Y+ G}/}3wP!TrI r* |# R!R!y)?R!wR'\"y)wW'`F{ Aw9?@w$X'R!8 bz#y#L.}*9?&}*7q#%/a9 awa!a wa^ a%a-aY7q#q#ag na |#z#y#g W'g ng ?a/!Er.hawb'b(B9=a?Xb(w $@$$@XwB9=a`"jwa |#z#y#g X'R'w66`"?{ 6`"?{ w&a { { CCBB10T$%T$7q#aT$q#wa* wa!a wa^ a%a-aYg na |#z#y#g W'g ng ?a/!Er.hawb'b(B9=a?Xb(w $@$$@XDwB9=a`"jwa |#z#y#g X'R'w66`"?{ 6`"?{ w&a { { CCBBT$ G}/M4R$y -SR$c 9:R$,9:R$?9:R$9?& 9:R$?pair_of_round_winner G}/uH [ OH +wH *wH *H %H H w.H *.H  %w.YH *.YH c#$.YH b#$H H - (%&%9?&&9?& G}/Q4}s4X69:J g$*roundlimit4-q!U &_z($9=, G}/}/}/O4}/}/R4P4A!4( G}/U4F!Ki2F!wF!*v)F!wF!*F!-T'.F!wT'*T'~ F!} F!v) G}/}/}/S4}/}/T4L1 q!c G}/}/}/`4N4i 5G}/@}/}/X4}/}/K4!n5T}8!9? !!9? >9?mm!9?!!9??9?!E G}/Y4}/G}/}/}/[4x=1 G}/V4}/}/^4}/}/ 4]4^!B1%- H  a}/G}/_4}/}/}/}/dQ!S!oYpr^ *v*v*9?&/a9 ['on['- ^ ['o103w^ * w^ ^ %^ -Q!B^ 6Q!$3pQ!^ (X"U!Q!^ 6X"6X"?w *w r!* w*(w r!Q!6Q!$pQ! r!(X"W!Q!6X"6X"? G}/i4r#}/ar#pr#-(Wwr#*wr#*r#q!Zq!^! G}/@}/}/e4}/}/c4U"U!^r6d * ^'nB.k)6 d 6 d `'B^'e'Bk)^'-6d U"B9=9:$9:d U"6U"9C9<$9?,XU"$U",E.`'?C.e'?U"la6d `'e'6d 6d 6 d 6 d  G}/f4}/G}/m4h4xh/ G}/D.F.|Y"w*bF.( G}/}/}/Yh:C@wo *9:9:$o n G}/o4]'s$.N]'p<w]'*]'"stopsoundsy'O$ G}/}/}/v4d'L-PMd'!}/d'!}/d'-q!c G}/}/}/g4f#W! be#An~-f#6f#9C9<$9?,Xf#$f#,A.e#?-e#?f#&a e#e#B_CB$B G}/p4}/}/K'}/}/X,L@.K .K' #?wS!qկ9?9?,dK'S!n# qկ9?,d9?,K'n#e9?,q9?,xSqn#9?%q9?, n#eq9?, n#w.S!*.S!-q?qqqD9?,dL> @.q G}/}/}/ y4r4mp-' G}/q4N!pcN!@#i']B!a/!Sh!9?.B!.B!@N!B!f!@#i'B!a/!u-f+uN!B!-j)@#i'f!h!9?%pN!h!(f!n+?'(B! @#9?b$B! @#rN!B!-j)@#f!h!9?%pN!h!(f!n+?'h!9?%6f!9?,0{N!f!h!?N!( G}/}/}/}4x4G -' G}/}/}/i }/}/@#}/}/y-~4{-g,Sy'{- G}/K+3p-'J $i!L* G}/y-d4D!0G}/w4D!rAh?D!$p'pppg9S9Dx- v-<VfD!vD!D!ap'X#W#X#X#?W#W#?[$Bff>nP"Bff>nY)[$?X#u'P"?W#9?,aD!6Z#6Z#Y)u'6y!6Z#6y!6Z#u'W#P"?HD!-w-6y![$?6y!P"?[$P"D!/6y!X#6y!P"?D! ap'(Z#y! G}/z-}/}/a"C5h& Y  Y  Y  Y  Y  Y  Y  Y  Y a" G}/K5M# d  G}/l4E*fE-E*-d -d-E*-d7M'%/a9 'H'X%%X%7M'H'X%M'H'~!X%N10-P..O 9:F9:$ G}/}/}/I5E5\c),9:.d9:$ % G}/}/}/G5}/}/HH5A!^(( G}/\$}/}/b"[ n b"[ [ Y [ Y [ Y [ Y [ Y [ Y [ Y [ Y [ Y [ d  G }/a"Q5h Y  Y  Y  Y  Y  Y  Y  Y  Y a" G}/ gt-n$\$ t-T)u-w\$*9:9:$-b)|m"T)SpectatorOnly1J $-  -b)\$-i!G!*\$ G}/@5w ubmAw $p!^ s-q-p-p!\ w p!6n"w ?w 6p!?6n"w ?w 6p!?F#a!]$Cff>n^$Cff>naw 6n"6n"]$?^$?6F# 9D6p!6p!9?I@-r-F# F# w 66n"]$?6n"^$?w &aF#]$^$CCp" G}/ U5j"f%V 9:9:$ ewj"*j"a/!sj" wpj"j"j" ? G}/q}/}/b"b n b"b b Y b Y b Y b Y b Y b Y b Y b Y b Y  G }/}/}/R5}/}/}/}/ W5T5z$Q ' G }/}/}/ Z5V5H$Mw ( G}/}/}/P}/}/\5X5o J7 > G}/|w'xrB(>n-E(AB(G(xBB(w'w'66Q)E(?6Q)G(?w'&a E(G(CRCAxB G}/ ht#>i G}/S5}/}/]5}/}/^5}/}/` g5_5A G}/@}/}/[5o"pt!9?% N(?j-P(BN(V(BN(o"_t!-k-o"b'b(o"Xb(9?&X6o"$o"66x(P(?6x(V(?It!?k$B9?, t!9?, l$t!L>k$B9?,t!9?, l$Bk$B9?,t!9?, l$Co"&a P(V(k$l$BB G}/M }/}/ h5P!@$)Tr.P!* .P!- P!C&-h$M ?I#C& P! I#9?M L>I#9? M L>I#9?M L>I#9?M L>-h$M 9?,wC&P!wP!*]-h$M 9?,P!9?,M 9?&M ?M R!M C&-h$P!M  G}/}/}/}/}/e5D.$9:9:$.m!Fq!e G }/ j5f5t(- '  G}/O(}/}/ l5|!R!f%Qt!QO(V QwO(*am O(|!?4-m(wm *Fwm *'w.m *.m -$p( m  9? "p(- |!9?,1|!?w*!9:w*m G |!?m ^#|!?m --m(|!>|! G}/}/}/ r5W(F"[#d wW(*$^w.W(*.W(-$$ G}/Y6`5`G}/Xo5a!N7t"9:p"r9:p"t"*m$. _ m$ Bm$ B9:p"t"m$9:p"t" G}/m$}/}/}/}/n5n$b!]:Gn$%Dn$7t"[n$t"n$ G}/ w5O#d#P"5wO#*wO#*'[w* _$O#'w.O#*.O#-'( G}/}/}/zc!wt *t a G}/}/}/u5}/}/{5s5V G!M$w.*. Hw.*. * G}/C#}/}/~z5lrG * w *r$%r$7bQ#r$b9: O9:Q#Q#RQ#- rG *G Q#r$G  G}/Q#}/}/|5[g" Vr*--%. mW"'Vr*--w.*r.[*@%['t$[Tr[*[-T[ P#[j!'(kw.[*[-.[-!9:*--[Objective already disabled([pDisable Objective 9V e[- r.[*5w.X[*2[_#[.X[L[[Getting in vehicle[4l-~(-~('/a9 XC#k7}$}$C#10s % s 7}$C#s }$C#|(]([ C# r_(* ](`(_(C#`(](s s[_( w[*[[b[(w[*[pMove to vehicle entry trigger 9V[[j!' .X[|(9?, W[-w[*r.*(t!Qr[*s %s ,ws  *I [s  w[*s r[*W!wW!*|wW!*W!- W! | [I [W!|w[*W!W!(q$V nl [ wn*w[n wq$*anq$"a[q$vt!Bswn*[Support Key Vehiclew[*#[x"([S$[ Dr[`!nNn [ 9? n 9?,d([ B!n('s[ C!n' o r[* rn*[Attack Key Vehicle[ |n[ \!n'[ B!n(' [ C!n'R [Fight Key VehicleI [nl r[n(  r[n([ G}/ @6G \ $G  hwG *Qw.G *G -hG G  rG *G  wG *G -G G ~!wG G r**.9?& G}/y5~5h! WR-I&!-j.d*d*9?,-I&('( G}/}/}/v5}/}/ E6f-f#v HEwf-f-9?& G}/lB6Z#P( G}/}/}/\ `!z!<3`!ag(U(T(R(U(9?,@L(T(9?,`!`!$$$$`!,h(R(?j(L(?`!&a R(L((CSC&C0B`!d-`!,h(U(?j(T(?`! ag(( G}/5}/}/ H6e-N"n< $r.*\  e- G}/D6}/}/t$}/}/ K6i(c#ZOxw.e!*5i(+| .e!.e!w*!9:w.u!*w.u!x*.u!xt$.rt$**Ct$-.e!t$ri(*.-.* G}/E"}/}/` S6F6AX G}/ P6c-l I?w.e!*.e!E".wE"*E"-.e!E"rE"*rc-*E"-E"* G}/}/}/@~  -I&' G }/M6["v!gU=r* r * r* h% ["o["%["$s(b'b(?Xb(XK(9?% h A 9: d9:$K(9? j#z!["b. T 9DK(s(["?["+? G}/}/}/ T6b-a&>Rt!B;E'r*EEb-   G}/}/}/GU#I nr==============ShowSpawnAreas==============/a0 Ad"8稨PlayerSpawnManager:9Vd"bEnabled:9Td"-dTag:9Wd"7d"-dU#7wU#*|$.U#r|$*  9:|$d"n  9V|$U#U#10==============End...........============== G}/O6Di.$9:9:$.m!Fq!g G }/ [6a-r#5RF&(A,a--(' G}/@}/}/R6MF d  G}/V6h Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  G}/W6z F#x!x%x!9?, u!z z 9:9:$z z $z Xa z z z +?z +? G}/t6J6i[G}/X6|u!||$w(,D&|o|w(|aD&F(C(AF(|+?C(|+?x!9?&6|$~!x!9?,6|9C9?,x!9?&?~fx!9?,6|9C9?,?x!9?,9?,~6|9=,|>|F(?|C(?| aD&( G}/ ]6`-^ 2Vw*-9`--   u-  r* 't!Q{ H '!B{ H 9W G}/}/}/ ^6J(\#_J( J( 9?,%J(9?, G}/ n[  n* G}/}/X}/j6[T1d!*-(%-(-_ ( G}/J-g6[~ a!}>9:9:$>wa%*aa%owy*wy*yq!iwz*wz*zq!iq!i G}/O!f . 99] G}/b6a wO!*O!a G}/]#}/}/ (^-<1FT ^-]-a a G}/}/}/H-i6f6y #9:9:$-J!([' G}/}/}/h6D z G }/l6@(!>r@(*(w.@(*]#.@(r]#Y]#-(]#Y]#`!-(' G}/\-^#|!CdVr^# r^#r^#r^# (^# G}/c#C)9 EKH--_ 9?_#|".A%.lrA%*!|"-_ ( C)j|"9=|"@A% |" A% C) 9?. P |"H-_ ( G}/}/}/ k6_!IMYPw*r_! Pr_!r_!  ar_! V_!a/!u_!-B9:9:$r*r*_! z }'w.R*.R-v#}'9?, _!*A9D}'E)  <E) G}/@}/}/v6o6S d $ $~, %$, 0$@- ;$A- F$C- Q$G- \$I- g$L- r$ N- }$ O- $ P- $ R-  G}/}/}/(] #( wO!*O!w G}/\-r6Z-T JGK(K)a d% Z-J)9?,9PJ)K)w G}/E;a6ez a}/G}/K-x6Ks a!N >9:9:$>wa%*aa%owy*wy*yq!`wz*wz*zq!`q!` G}/}6Y-vu9:Y-9:9@-N G}/}/}/F-z6w6ji #9:9:$-J!'K' G}/}/}/F7y6Dd x G }/}/}/}/}/o|6[ ~ % G}/{6}/}/},L 8v&a?' G}/~6}/}/Th-o  G}/A7Q-e4w*w*P wP *xw.P *.P d _%%P P 5P wP *w.P *.P d _%&P P Q- G}/@7}/}/C7}/}/ Vx"T#M,dx"awx"*Jw.x"*.x" d _%,x"x" G}/` D7A^{9:9:$D  G}/E7O)A U4 KH-M- -N)-N)'O) ]L)O) ]M) G}/ | b ^( mKw*\Z%o$o$9?&  G}/R7xLa!B ?9:9:$\wy*wy*yq!gwz*wz*zq!g G}/TB ATB?COV J 3O(@|K1  @dd;@%@ @  @ 1 -@z@abIJ@@ -@ / E( G ] _@ u / G0 J_ bw z E8bd|y|w@ H(a@]y(zv J3O@|K1@  dd;@% @? @  1 -0@@z@a b(IJ@@ - / E@ G ]@ _H u /( G J_ b(w zEb@d |y| w@ Ha(]0yzv?J?3O|K1@@ ' dd;% @' @ ? 1@' -@za(b @@IJ - / E G ]@ _( u / G J_ bw zE?b@d|?y |w Ha]yzvJ3O@|?K@1' @ dd;% '@   1 -z?ab@''@IJ@@ - /? E G ] _ u / G? J@_? bw zEbd|y|w H?a]?yz(@@@vJ@@3?O(|K1?  @dd;?% @ @  1? -?zab@IJ@@ - /? E( G ] _ u / G J_ b?w z@E(@bd| y|w Ha?]y@z@v J(3O?@|K1  dd;@%@ ?  @ 1 -(@z@ab?I@J@@ - / E G ] _( u /0 G8 J_ b0@w z0E0bd @|y|(w@ H0a0@](@y0zvJ3O| K1@@  dd;% @ @  1@ -(@z a(b(@IJ - / E? G ]P@ _H u / G J_ b w? z@Eb@d|y|@w Ha ]0y@zv?J?3O?|K1@ ' dd@;% '@ @ ? 1 -za b@IJ@ - / E G ]0 _ u @ / G? J@_@ bw zEb@d|@y |w H?a]@yz@@vJ@3?O@|?K1  @dd;% @@' @  1?@ -?z?ab@'@IJ@@ - /? E G ]п _ u / G? J_ b?w zEbd|@y|w Ha]?yz @@vJ @@3?O(@|K1??  @dd;% @ @  1 -zab?@IJ@@ -@ / E(@ G ]ȿ _ u / G J_ bw z@E8bd|y|@w@ H a]?y@z@v ???e$%%("!#E&F O+*NMMLLKK--,  .+ N J( !,@IA/  ))J789:;<D0214365=?C BGH'>'e)#$$#$'''!! " ! ",,",=D&%ED=NGF )*$*)*$M'M$M'LL'LK KK J,J J,++,+&&  & - * *(M(*(MLMLIKILIKJKJ+J++?>>?H@ .- - ( ((III66787789:989:;C54//010/123210345432<;: >?BH  @AFE=EFG%%&=&O    + > '*O>L?@<>>3?>P?@<?>?>L?>3?&?> > &?L> >= >f? >f?=>?,>??(?>>,>>@@<=&?>>>&?>&??,>3?&?=@<3?>?,>?=f?,>f? ,>>!@<>"@<>#@<$,>=%=L?&,>L?',>L>(>L>),>*>=+>?,,>>->.&?/&?3?0?3?1&?L?2?L?3&?f?4?f?5&??6?3?7?L?8>L?9?f?:>f?;??<>?=@>f??>f?@>?A=?B>?C??D=L?E=f?F@?I>>J>>K>>L>>M>L>N@<?օ?? >a$ AV -$'  !  $ %   ",+% p!P%  p!#@#@00  0"   `""%I ( "P p!P ! "`!@p 0  @1&ω*ЭP,- %~P#Rp(i)) &!* P  +R(j 1" ` !*P!     )`!!]8U @!` @   ! N !  `  P p $%%!! P" " 0#    0 !`  `b.8@5kp0"$P! `)YɅP !E e )~Ѡ #!  ` 9P"a  0 ~eP%/"@ p"P*&P#=!   " # p"F # p"@ p@ p  !!"#   P   ,@ 3@p  P"   (!S" - V *za:J*#Ap'=%2PP   P# p0  0"-%5  Pp %"-@  "0% "%% " #p  !  A'+$ @ p    # " !p "@  $":j0    *0 @"p 0  `  p"10& ,_-E0*  &%5>&R(@ $Q(-/۱,E20 P ( g6 j) "  P$  5&p]P) " " `y*a4?@ !p# `!  # "   @"#  " P! # p!  ` @"`! !   !0%b)֡+i&p5@J0 "$# "/"F*$%6&  " !Y6*!0%cF$!0!e."p!0    nE&  $`*& p "  $P !#@# @`!  P P !=P'm *#  "# ! U(!!`   `  -%e(] ) @!E= D*** &>Qpm%  +b ,  J `!`##m0   -% 0 "pI2@!e0  PPp p!!@ 0"!L"`0p     `!  !@! @""#! "!p !!?P)&B4V|RKfq 0 ` p =Ip!P-M 0$Q`#4  @5` 9  zU@#F6 !`* #( P  "p # !P  ! "@Pp p!  !" 0! " F P+@ P4.``  P"p0 0 p  *` @ B -V40)R`(-P-5N*  0 ! ! ! "p" B@ !쑠+ $0P   "` 0  *  F(!B' p"@# !@ 0+3?!  # " ! ! ! " 3P0     0 !      "@$=`$#%2@&P(!` !p$=6%Rp(@!$E'3D*m*f +"( P o: N(! @  !`%  -p&9`'! #  `M("^14 P!$ ! "# p P#   "$90'# 0  @"`!0#p!    !%e)ɥ,E%),fZV.`&=p'!@% "(!="&"$  p" 2*# !?P.  Q  `     c6O TB@LB@PBAPBPBAPBTB@PBTB@LBTB@LB@PB ATBTB@TBPB@PBPB@HB ?xC@@ZC?CBCxC?xC`@?CCCvC}/BCC"CQCfb=HHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX ?-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP?--xxhh`wx7h7WPXpxpXx8hHGx8hxX8X8x!P@Ph@!X!@PHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCPE.X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX O-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP/z.υ-xxhh`wx7h7WPXpxpXw(hHGwhxXHXw!PPg@!X OHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP.X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX gz-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP.E-xxhh`wx7h7WPXpxpXvhHGvhxX`Xw"P@Qg@!X @OHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX ?-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP?--xxhh`wx7h7WPXpxpXw8hHGw8hxY8Y8w"P@Pg@!Y @PHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCPE-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX .X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼPgz-.xxhh`wx7h7WPXpxpXw`gHGwgxYYw!P@Og@!Y @QHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX /-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP/--xxhh`wx7h7WPXpxpXwHhXGw8hxYHY8v P@Ph@!Y!@PHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP'.X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX Gz-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP.E-xxhh`wx7h7WPXpxpXv0hhGvиhxXXvP@Qh@!X"@OHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX /-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP/--xxhh`wx7h7WPXpxpXwHhXGw8hxYHY8v P@Ph@!Y!@PHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCPE-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX .X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼPgz-.xxhh`wx7h7WPXpxpXw`gHGwgxYYw!P@Og@!Y @QHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCPυ-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX /z.X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼPO-E.xxhh`wx7h7WPXpxpXwHgHGwgxX(Xw@"POg@!Y PHHH?7w7w7weeeHkHkeHk87kkxwe0wexk0wHw?7kHkkexwe87eHwwg7|TxHeTp|wk`7SwwwwHwwg7wxp|xHkXpTeXTwe`7x|pkxWS{?7?7?7_7?7{87S87W87WX7W87oHo7ww7XhxxxHxhXxx7XpXwX7xX_7XXx7{?7_7?7{WSWw87wX7w87HwwXxHXxwxp_7_7{X7SX7_7xXX7_7_7{X7SX7g7xXXxx`7HoweHkhw'W7kke eP7HGwoeHek@wkhHow'W7kHeeehwk kP7/:.|P |PHGwokHke@weh?7?7S{{87S87OkeH?7?7_7_7WwWWw87W87wX7wX7OCP-X8!xXhhOekHg7xXX`7xx' _7_7wwWX7WX7oo77|h|TThT7T||7'ek 'ke ./ w9!Xxhpw XX ?-X7X w7 7 OCPh7 hh x8!x h' X9!hy!h@F!ǼP?--xxhh`wx7h7WPXpxpXx8hHGx8hxX8X8w"P@Pg@!Y@P???t S487547R77R6S5R6RK<<ZZK877HH0G0Q-::22-P11P1Q,P1PJ;;YYJ^+,^+D``DE]]O((AANBBNAONANXCCVVXI'I99'TM?==..?L//L.ML.LW@@UUW\\>__F>[[fTcfc9Gbb9eFdEe>dDaD>a|OOPtNxt0w/0#"&"wKMP$$&"#Ksv/u0s"0Nuuwvx|MLL_ ^ ^`_uw{IIJnHrn-q,- !%qEGJ!!%! Emp,o-m-Hooqpr{GFFoq8T  S7 V7S~T8~ zCCDhBlh*k) *  $ k?AD  $  ?gj)i*g *BiikjlzA@@Z  Y Y[Z y==>b<fb'e&'#e9;>#9ad&c'a'<ccedfy;::ce4RQ3U3Q}R4}ikt A``````A`ABAABB???A?B?B??``@@`>@@@>@>FFFGFFGGEEEFEGEGEEDDD>>>CCCUUvv^vy^^yKHu?K?HH]u?u{??{{x2Z22Z20X00X05VVKHHzz ;; [8[?3?[8?38Y!Y8?O1OY!O1!WO6E<WEBBw<<wB==B=Bw__4UN NU97>77> N >W<E<A>A@C=I=C:FFV\::\\tttj;979;j9j;v7x7vlk=<lkl<<=k<w<::8u88u:y88tl=ltt==lD;JGJ;RRnnZnqZZq96m-9-66Ym-ms--ssp"S""S" Q  Q %OO966rr++T(T/#/T(/#(RR(/M!MRM!PM&~3*T30~~0o**o0--0-0o[[$NLLN)'.''.L.T*3*/,/.1+7+1(44SX**XXlll}}}2)858)g42024g2g4q0m0qZih65ihi556phZZp5r533111k3n11i6i6o6ool[[i[yO{Oyy{f{fVfiVVix'$zex'x$z$UeekkkhLLJJHH'$$jjMMMKKKKKKIKv!Q|!vv|gggWWGJJGJQ!%""PTTTdddwuwwuud-+)+-d+d-g)i)gfe/.fef../e.h.,,*f**f,j**ef/fee//fqLsLqqs^s^R^aRRapr] pp ~rQ] ]c ~ cc~~`EECCAAbb FFFDDIIDIBInNt nn t_|_   |  _S||S@HH@ HN{ }}    z}zMP  PP\\\omoomma&$"$&a$a&b"^"bXcb('cbc''(abXXa'c' %%### \ % _~# #~c(c (`(  |``|] Y  YcY &#&b ""#223$%''4577 ),-9<=] __`cegghkm)+-oopsu9;=wwx{}~_]    geom*/0,-,-wu<AB>?>?}~"$)*46;<FHedts%&56EFLMSTZ[./>?AB`bHIhjOP"#prVW23xz '()+789;eftu'(78^_bc`ijghmnqroxyvw?E./>?\^_dfglnotvw?Y[\]^_defglmnotuvw !01CDJKQRXY>BF>GDEGABCD`FFAA>E?Cb ?>5?>>>A?|>?> ?>/?,>>d>;?|>>d>>;5?@<;?@<]?t>>>;?|>?>5?>>>A?|>?> ?>/?,> >d> ;?|> >d> >; 5?@< ;?@< ]?t> >> ;?|> ?> 5?> >> A?|>?> ?>/?,>>d>;?|>>d>>;5?@<;?@<]?t>>>;?|>?>5?>>>A?|>?> ?>/?,>>d>;?|>>d>>;5?@<;?@<]?t>>>;?|>?d> ?d>/?,>?d>5?>>d>A?|>?d> ?d>/?,>?d>5?>>d>A?|>?d> ?d>/?,>?d>5?> >d> A?|>!?d>! ?d>!/?,>"?d>"5?>#>d>#A?|>$>=$D?,>%>=%~?,>&>>&>;&;?@<&f?t>'>='D?,>(>=(~?,>)>>)>;);?@<)f?t>*>=*D?,>+>=+~?,>,>>,>;,;?@<,f?t>->=-D?,>.>=.~?,>/>>/>;/;?@0;0==0`=>1>;1>=1>$>2>>2>;2>=3>>3>=3>;4;4==4`=>5>;5>=5>$>6>>6>;6>=7>>7>=7>;8?=8J?@<9>;9D?,>:>d>:>=:;?@<:]?t>;?;;3?=;x?@<<>;<~?,>=>>=>==5?@<=f?t>>?=>J?@;?D?,>@>d>@>=@;?@<@]?t>A?;A3?=Ax?@;B~?,>C>>C>=C5?@D?=DJ?@;ED?,>F>d>F>=F;?@G?;G3?=Gx?@;H~?,>I>>I>=I5?@J?=JJ?@;KD?,>L>d>L>=L;?@M?;M3?=Mx?@;N~?,>O>>O>=O5?@P=;P==Q=Q=;Q`=>R=;R==S=S=;S`=>T>>T>=U>>U>=V;V==V`=>W>>W>>W>=W>;X>;X>=X>$>Y>>Y>;Y>=Z>>Z>=[;[==[`=>\>>\>>\>=\>;]>;]>=]>$>^>>^>;^>=_>>_>=`>|>`>|>`x?=a>>a?>aJ?,>b>>b?|>bJ?,>c>|>c?|>cJ?=d>|>d>>dx?=e>|>e?>eJ?=f>|>f>|>fx?=g>>g?>gJ?,>h>>h?|>hJ?,>i>|>i?|>iJ?=j>|>j>>jx?=k>|>k?>kJ?=l>|>l>|>lx?=m>>m?>mJ?,>n>>n?|>nJ?,>o>|>o?|>oJ?=p>|>p>>px?=q>|>q?>qJ?=r>|>r>|>rx?=s>>s?>sJ?,>t>>t?|>tJ?,>u>|>u?|>uJ?=v>|>v>>vx?=w>|>w?>wJ?=x?=x3?;xx?@$>|>=}>$>}>=~>>~>;===>@==`=$>=;=>`=$>=;===;=>===>>>>;===>@==`=$>=;=>`=$>=;===;=>===>>>>|>x?,>>>x?,>>>>|>x?,>>>x?,>>>>|>x?,>>>x?,>>>>|>x?,>>>x?,>=`=>>>>==`=>>>>=?;J?@<?;J?@<?;J?@<?;J?@<@==`=$>>$>>=@==`=$>>$>>=>;J?|>>;x?|>>;J?|>>;x?|>>;J?|>>;x?|>>;J?|>>;x?|>?>/?>?>/?>?>/?>?>/?>>d>A?,>>d>;?=>d>A?,>>d>;?=>d>A?,>>d>;?=>d>A?,>>d>;?=>>;?,>>>5?=>>;?,>>>5?=>>;?,>>>5?=>>;?,>>>5?=?d>/?>>>A?,>>>;?=?d>/?>>>A?,>>>;?=?d>/?>>>A?,>>>;?=?d>/?>>>A?,>>>;?=F?)?@=}? >>@=>>d>;?,>>d>5?=>d>;?,>>d>5?=>d>;?,>>d>5?=>d>;?,>>d>5?=@=;`=$>>$>>;@=;`=$>>$>>;@=;`=$>>$>>;@=;`=$>>$>>;>d>5?|>>d>5?|>>d>5?|>>d>5?|>===$>>=>$>=;=$>=====$>>=>$>=;=$>=====$>>=>$>=;=$>=====$>>=>$>=;=$>==s?}?z?}?d>>s?>?)?>>>v?}?n?>z?)?>>5?|>>>5?|>>>5?|>>>5?|>>=J?|>>=x?|>>=J?|>>=x?|>>=J?|>>=x?|>>=J?|>>=x?|>\?}?>;>$>>=>;>$> >= >; >$> >= >; >$> >=>;D?=>=D?=>;~?=>=~?=>;D?=>=D?=>;~?=>=~?=>;D?=>=D?=>;~?=>=~?=>;D?=>=D?=>;~?=>=~?=>>;?>>>;?> >> ;?>!>>!;?>">d>";?>#>d>#;?>$>d>$;?>%>d>%;?>&d>)?'\?)?(&?}?(?}?)<>*<}?+)?, >}?-v?>.W?>/F?}?0@=>1 >>2<}?3<>4)?5@=>6 >}?7 >)?8s?>9 >)?:<)?;<)?<W?)?=}?=>}?>W?}??t?)?@z?>A\?>By?)?C&?>C?>D&?)?D?)?E)?E>)?F@=)?GF?>Hd>}?I=}?J=}?Kn?}?Lm?)?Ms?}?Nr?)?O@=}?PP=)?Q@=}?RP=)?Ss?)?Tq?>Uv?>Vq?}?Wv?}?X=>Y=>Z?}?[?)?\>}?]>)?^?>_>>`>}?a>)?b>}?c>)?d>>e>>Q.@? >o Ab=yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3/-[)D; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6l21/Jk $o.inJko.Y 11Y 11rF bVrF bV2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"/2-ɕ=d!>35=IA#a`Ndɕ=!a`2i2pa3n!2n!2Un3o.3.25=.2];F4<;<; ط#m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.7'!1!V1W0X??yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_39/% jD; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6/Jk o. Jko.Y 11Y 11rF bVrF bVm2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"A/1${ɕ=d!fr35=h z#a`h}dɕ=!a`2r2f1#!3n!2n!2b.3p.}3.25=cI.2M;>$<+<;,'߷U%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.#91J#:r1("!g! ?!? l( 8yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3{Fa/=y T; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6:/Jk o.Jko.Y 11Y 11rF bVrF bV1qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"{n/1Bɕ=d!25=<ٱ+K"a`<%dɕ=!a`z1b1z2n!2n!2r2%q-b2.25==.2A;2<<; ` ô"m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.c%zR1w$z1(d'8$x?[9$ x?Ĉxyy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3/-[)D; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6l21/Jk o._Jko.Y 11Y 11rF bVrF bV2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"/2wɕ=d!B35=IAy#a`Ndɕ=!a` 2i2lq3n!2n!2U~3`.3.25=.2NmD:=$<;<; #m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}./!1 V1W8X$? x?yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3).L ymT; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6IÂ,Jk*Ԇo. Jko.Y 11Y 11rF bVrF bV?>3qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-".ͅ.2[ɕ=d!D 45=%a`dɕ=!a`CΡ3y!2,3n!2n!213a0@4.25=.29ed<֕k< ";),%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.K.0]!0/d'-x!Vw?时 ?(V$yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3/-K5T; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6m./Jk Lho.$iJko.Y 11Y 11rF bVrF bV 2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"/1ɕ=d!*r35=5K$a`dɕ=!a`2a1k2n!2n!2m2N,m3.25=.2i4<#bd<k<; g%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.F%~1w%Rq1pXW?/?!yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3{FQ/k=; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl67.Jko.dJko.Y 11Y 11rF bVrF bV皍1qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"zn/~1i);ɕ=d!~15=>q{k%a`>E~dɕ=!a`n1Rq1^1n!2n!21֐+ 2.25==}.2i;UvGd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3/-K5T; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6m./Jk Lho.$iJko.Y 11Y 11rF bVrF bV 2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"/1ɕ=d!*r35=5K$a`dɕ=!a`2a1k2n!2n!2m2N,m3.25=.2i4<#bd<k<; g%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.F%~1w%Rq1pXW?/?!yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3).L ymT; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6IÂ,Jk*Ԇo. Jko.Y 11Y 11rF bVrF bV?>3qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-".ͅ.2[ɕ=d!D 45=%a`dɕ=!a`CΡ3y!2,3n!2n!213a0@4.25=.29ed<֕k< ";),%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.K.0]!0/d'-x!Vw?时 ?(V$yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3 A/7 =T; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6-JkGo.Jko.Y 11Y 11rF bVrF bV`.N3qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-">/2ɕ=d!rb45=+$a`dɕ=!a`qA3m2㵡3n!2n!2E3#.nM4.25=.2*9I4<ܭK<;\%m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.̱1w M1@h$,?77 X?@ 8!yy .!jT,>Gd(v!!,G,sk(yy .!jT,>Gd(v!!,G,sk(1' 1MKس 1' 1MKس $^#۸T 1E"ۀQ#$G[ κ"$^#۸T 1E"ۀQ#$G[ κ" 2 2 *;N#ab*>-(5 ;!%;,*u>>NS"(c *;N#ab*>-(5 ;!%;,*u>>NS"(c ,9 ,9 o o i[ X O)2& i[ i[ X O)2& i[ _&SEA 5Q# _){?\5], GP)N0_&SEA 5Q# _){?\5], GP)N0,Q)^),Q)^),++,++i i mX&o iZ#96 X i i mX&o iZ#96 X >Qo ; ^!;>Qo ; ^!;& 6 & 6 WN&&WN&&& +& +v :/ v :/ \#/,\#/,"l6y*c6-v*"l6y*c6-v*D IG D IG / Hl-3 -I_3/ Hl-3 -I_3/-[)D; -=  -= ,-Q׍%f[#-(%,-Q׍%f[#-(%ys44ys44J/we]P-Yc6E I_Ҧl6J/we]P-Yc6E I_Ҧl6l21/Jk $o."*Jko.Y 11Y 11rF bVrF bV2qX*5g~5qX*5g~51VC|0L3m0Ts0t31VC|0L3m0Ts0t3PT;4PT;4~-"~-"/2ɕ=d!>35=IA#a`Ndɕ=!a`2i2pa3n!2n!2Un3p-3.25=.2@m95<+<; ط#m m 4s:54s:54b|:":4b|:":;}!}!2 2 }.}.7'!1!V1W0X%??!hYf BCCBCCBCCBCCBCCBCCBCCBCCBCCBCCBCC !CkC!C!C"CQC!CkC"CQC!CkC"CQC!CkC"CQC!C!C!CkCSY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:BA^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/SY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:A(B^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/SY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:AA(B^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/SY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:?^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/SY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:B?^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/}/!6 a!o?= G}/Uz>va!E ?9:9:$\wy*wy*yq!ewz*wz*zq!e G}/}/}/}/}/G-@}/}/U7@}/}/P)X7Y G}/}/}/W7Z7v G}/[7}/}/}/}/Y7]7Z! G }/}/ }/\7|( G }/^7!KP) G}/_7E-zD%E- G}/c7D /.m!j G}/`7D-A%tC-  % 0rt'*t' Iwd#*d#rd#*rd#*t'- wD%*d#D%w*b?D- B-@%9?&]!w*a -'a(((z'a z' aL>( G}/d7V.?<-J!-^*-^*-J!6-J!K<[ G}/rJ!fr-v#a"9?,d G}/B-}/}/}g7aP$ G}/l7}/}/b7]!H'*-x''@BR) G+C G}/h7j7{O6z'a-x'(@BR) G+C G}/}/}/i7U)@] x - -'/a8 tr'H%lt-x'ta/!X  6t 6H%1lta/!X z,t1lkwt9:t9:$ta/!w$Z"t H%g'?Z"Z"Z"g'l'?g'tr'r*r*t zD%tmA9Dl'U)t ի?ttZ"իl'\)Z"[)kw*w.t*.t%.t-[%U)r'[)\)H%10-( G}/m7}/}/r7}/}/a"o7h?z Y  Y  Y  Y  Y  Y  Y  Y  Y a" G}/s7M61 d  d  G}/N}/}/t7J%kw@*n'9?@mG 9?J% Dq'9?@nG 9?J%CJ%66d)n'?6d)q'?J%>a@n'q'9?@m9?@n G}/}/}/b"Z8K n"b"K K Y K Y K Y K Y K Y K Y K Y K Y K Y K d K d  G }/{7f'hf'|,of'9:E ,e) gF  f zf'{,e) ( G}/ f7wQ$ G}/vr&L%/b%.G& rb%*b%- xr&f*pp k r&f*e!r&.b% G}/P%}/}/F7{y1 G}/z,[;9?&P)-(a''' G}/y7k#qe+w.k#*.k#- k# 9?.k#w*w*zA9Dk# <#  G}/}7r i& uc' gF  fr x,or 9:E ,r ac'O%L%6V"O%?r 6V"r O%?!6V"L%?r 6V"r L%?r 66V"O%?6V"L%?r ac'( G}/z7Z'Y&+w.Z'*.Z'- .Z'pw*w*zA#  G}/r,Q%TvF sQ%I| 8$iQ%\'o)p U$hQ%\'o)p m$kQ%\'p  G}/|7Q'|!Z+w.Q'*.Q'-(.Q'pw*w*zA# ( G}/U8}/}/}/}/B8Y D G}/}/}/A8D8v v G}/E8}/}/}/}/C8G8A  G}/H8}/}/I8}/}/J8}/}/K8}/}/}/}/F8M8Z! : G }/}/ }/ L8O8Or G}/P8}/}/}/}/N8| G }/Q8S8q G}/}/}/v,}/}/}/}/j*}/}/w Y8p m6Zq*Gn&q,#rq**'n,^o*o,n&/Uo*n&'( G}/s,}/}/n&}/}/n*f" |j*i*w,w*f%p&6f%s&f%j*u&f%i*s&333? u&9?%a n*p&k*s&Q? u&9?%a n*p&k** G}/O'!W-m#-)<{)!}//a0 vQ"{);;10TO'9?%O'@ G}/[8L'X!%3L'F!'L'C L' G}/y//============================================================================= // Weapon_Sentinel //============================================================================= class Weapon_Sentinel extends Weapon config(user) HideDropDown CacheExempt; simulated function bool HasAmmo() { return true; } function byte BestMode() { return 0; } //============================================================================= // defaultproperties //============================================================================= }/}/}/\8D*o0B"wB"*G*B"wB"*B"-o#.B"wo#*o#F!'o#C o#B"G*iu,*wD**aO'(@*D* G]8x2u#6`8:qY *Y{*Y{*J${.?L${.?OSdQR: I"Y: sm,W]Sentinel weapon"$@@#@}/}/C//============================================================================= // WA_Sentinel //============================================================================= class WA_Sentinel extends xWeaponAttachment; var FX_SpaceFighter_3rdpMuzzle MuzFlash; var float MuzzleScale; var class MuzzleFlashClass; simulated function Destroyed() { if ( MuzFlash != None ) MuzFlash.Destroy(); super.Destroyed(); } simulated event ThirdPersonEffects() { local vector Start; if ( Level.NetMode != NM_DedicatedServer && Instigator != None && FlashCount > 0 ) { if ( FiringMode == 0 ) { // Muzzle Flash Start = GetFireStart(); if ( MuzFlash == None ) { // Spawn Team colored Muzzle Flash effect MuzFlash = Spawn(MuzzleFlashClass,,, Start, Instigator.Rotation); if ( MuzFlash != None ) { MuzFlash.SetScale( MuzzleScale ); MuzFlash.SetBase( Instigator ); if ( Instigator.GetTeamNum() == 0 ) // Red color version MuzFlash.SetRedColor(); } } else { // Revive dead particles... MuzFlash.Emitters[0].SpawnParticle( 3 ); } } // have pawn play firing anim if ( Instigator != None && FiringMode == 0 && FlashCount > 0 ) { Instigator.PlayFiring(1.0, '0'); } } super.ThirdPersonEffects(); } simulated function vector GetFireStart() { local vector X, Y, Z, MuzzleSpawnOffset; if ( Instigator != None && ASVehicle(Instigator) != None ) MuzzleSpawnOffset = ASVehicle(Instigator).VehicleProjSpawnOffset; GetAxes( Instigator.Rotation, X, Y, Z ); return Instigator.Location + X*MuzzleSpawnOffset.X + Y*MuzzleSpawnOffset.Y + Z*MuzzleSpawnOffset.Z; } //============================================================================= // defaultproperties //============================================================================= }/W8{!k 8k&9?{! Dj&9?{!C{!{!$9=,$${!${!46u*9?,k&6u*9?,j&{!Lap#Bk&Bj&9?p#m9?p#n G}/k //============================================================================= // Trigger_SetObjectiveStatus //============================================================================= class Trigger_SetObjectiveStatus extends Triggers; var(Action) name ObjectiveTag; var(Action) bool bActive; event Trigger( Actor Other, Pawn EventInstigator ) { local GameObjective GO; if ( Role < Role_Authority ) return; for ( GO=UnrealTeamInfo(Level.Game.GameReplicationInfo.Teams[0]).AI.Objectives; GO!=None; GO=GO.NextObjective ) if ( ObjectiveTag == GO.Tag ) GO.SetActive( bActive ); } }/_89L@*J  G}/d8f8OQ-m#-m# G}/g8}/}/}/}/e8[Y{-m#-) G}/b8j,e! 9J!h"-  r* H!Gi,d,Gw.H!* wH!w.H!*9:.H!%wh".H!&h"?h"a"j,.H!h"h".H! Gc8a0["@ j8|؂u3}Zs- =1'yؚؚؚؚ UVS}/}/`%N9x*n5,"M$x*`%x* G}/}/}/nY"9"Y">kw..*)w...*nr.*r..*.J9:9:$9:9:$W - O *K'Y" ף<5Y"=n-9:9:$Y" ף<l,Y"aY"( G }/P//============================================================================= // Trigger_ASTouchDamage //============================================================================= // Deals damage to actors touching the trigger //============================================================================= class Trigger_ASTouchDamage extends Triggers; var() int Damage; var() class DamageType; var() enum EPSM_AssaultTeam { EMT_Attackers, EMT_Defenders, EMT_All, } AssaultTeam; function bool IsRelevant( Pawn P ) { local byte DefendingTeam; if ( AssaultTeam == EMT_All ) return true; DefendingTeam = Level.Game.GetDefenderNum(); if ( AssaultTeam == EMT_Defenders && P.GetTeamNum() == DefendingTeam ) return true; if ( AssaultTeam != EMT_Defenders && P.GetTeamNum() == (1 - DefendingTeam) ) return true; return false; } function Touch( Actor Other ) { local Pawn P; P = Pawn(Other); if ( P == None || !IsRelevant(P) ) return; P.TakeDamage(Damage, P, P.Location, vect(0,0,0), DamageType); } }/m8WAAXUwI!( G}/k,^,O"F'^,6F'%a+F' G}/ i8~#z<? <w.* wC'*. iC' Gn8\0R r8؂uhh3}Zshh y"Z 1j }/}/Y%! Y%!}/a((a'' G }/s8w8g"G}/v8D6!.R-J!q!`3a!B @ G }/}/}/u8K y D% G}/t8{8e/8G}/z8D( q!e G }/}/}/y8K-a!E @ G}/x8}8`7G}/K5wa!N > G}/|88i?G}/K=a!}> G}/Y%! Y%!}/a((a'' G }/@9D9g"zG}/C9D6!.R-J!q!`3a!B @ G }/}/}/B9K g D% G}/A9F9e*G}/K(a!E @ G}/E9J9`7G}/I9D0! q!e G }/}/}/H9K5ea!N > G}/G9L9i?G}/K=a!}> G}/F //============================================================================= // PROJ_Sentinel_Laser_Red //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class PROJ_Sentinel_Laser_Red extends PROJ_Sentinel_Laser; simulated function SetupProjectile() { super.SetupProjectile(); if ( Laser != None ) Laser.SetRedColor(); } simulated function SpawnExplodeFX(vector HitLocation, vector HitNormal) { local FX_PlasmaImpact FX_Impact; if ( EffectIsRelevant(Location, false) ) { FX_Impact = Spawn(class'FX_PlasmaImpact',,, HitLocation + HitNormal * 2, rotator(HitNormal)); FX_Impact.SetRedColor(); } } }/O9f&R%~'w.*E .g&9?%-L&'g&9?%E [!~#E E [!f&a+~#[!E E ~#E E [!f&a+~#E  -L&(R-L&E E!~#[!E sM$9?%M$E M$E a $ (M$E f&_,`,a,b,c,g&e,f,g,h, G}/d9\,j r%PM- w*6 6 C,\, G}/B'Q*r 9!-Y,%9:Q*],6%9:Q*[, G}/q8R9H (=/G G}/}/}/P9V,X)-V,% &%  G}/}/}/S9A'T%U*@!S,\*Y*g*?A'A'U*Y*_*`*c*z&\*_*6B'`*6B'c*g*6B'a z&|&9Pz&U, 6|&a+|&A' a((B G}/Z*//============================================================================= // PROJ_Sentinel_Laser //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class PROJ_Sentinel_Laser extends Projectile; var FX_Laser_Blue Laser; var class LaserClass; // Human simulated function PostNetBeginPlay() { super.PostNetBeginPlay(); Velocity = Speed * Vector(Rotation); Acceleration = Velocity; SetupProjectile(); } simulated function Destroyed() { if ( Laser != None ) Laser.Destroy(); super.Destroyed(); } simulated function SetupProjectile() { // FX if ( Level.NetMode != NM_DedicatedServer ) { Laser = Spawn(LaserClass, Self,, Location, Rotation); if ( Laser != None ) { Laser.SetBase( Self ); Laser.SetScale( 0.67, 0.67 ); } } } simulated function Explode(vector HitLocation, vector HitNormal) { SpawnExplodeFX(HitLocation, HitNormal); PlaySound(Sound'WeaponSounds.BioRifle.BioRifleGoo2'); Destroy(); } simulated function SpawnExplodeFX(vector HitLocation, vector HitNormal) { if ( EffectIsRelevant(Location, false) ) { Spawn(class'FX_PlasmaImpact',,, HitLocation + HitNormal * 2, rotator(HitNormal)); } } //============== // Encroachment function bool EncroachingOn( actor Other ) { if ( Other == Instigator || Other == Owner || Other.Owner == Instigator || Other.Base == Instigator ) return false; super.EncroachingOn( Other ); } simulated function ProcessTouch (Actor Other, vector HitLocation) { local float AdjustedDamage; if ( Instigator != None ) { if (Other == Instigator) return; if (Other.Owner == Instigator || Other.Base == Instigator) return; } if (Other == Owner) return; if ( !Other.IsA('Projectile') || Other.bProjTarget ) { if ( Role == ROLE_Authority ) { if ( Instigator == None || Instigator.Controller == None ) Other.SetDelayedDamageInstigatorController( InstigatorController ); AdjustedDamage = Damage; if ( ASVehicle_Sentinel(Instigator) != None && ASVehicle_Sentinel(Instigator).bSpawnCampProtection ) AdjustedDamage *= 10; Other.TakeDamage(AdjustedDamage, Instigator, HitLocation, MomentumTransfer * Normal(Velocity), MyDamageType); } Explode(HitLocation, -Normal(Velocity)); } } //============================================================================= // defaultproperties //============================================================================= }/G//============================================================================= // ObjectiveProgressDisplay //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ObjectiveProgressDisplay extends Info config; var HUD_Assault ASHUD; var localized String HeaderText, OptionalObjectivePrefix, ObjTimesString, TextCutSuffix, SpaceSeparator, PrimaryObjectivePrefix; var float SlideScale; var vector BoxSize, BoxPivot; var() float SlideSpeed; simulated function ShowStatus( bool bShow ); simulated function UpdateSlideScale( float DeltaTime ); simulated function Initialize( HUD_Assault H ) { ASHUD = H; } auto state Hidden { simulated function ShowStatus( bool bShow ) { if ( bShow ) GotoState('SlideIn'); } simulated function PostRender( Canvas C, float DeltaTime, bool bDefender ) { DrawBigCurrentObjective( C, bDefender, false ); } } state Visible { simulated function ShowStatus( bool bShow ) { if ( !bShow ) GotoState('SlideOut'); } } state SlideIn { simulated function ShowStatus( bool bShow ) { if ( !bShow ) GotoState('SlideOut'); } simulated function UpdateSlideScale( float DeltaTime ) { SlideScale += DeltaTime * SlideSpeed; if ( SlideScale > 1.f ) { SlideScale = 1.f; GotoState('Visible'); } } simulated function vector DrawObjectives( Canvas C, vector BoxPivot, bool bDefender, bool bGetBoxSize ) { if ( bGetBoxSize ) return Global.DrawObjectives( C, BoxPivot, bDefender, bGetBoxSize ); return vect(0,0,0); } } state SlideOut { simulated function ShowStatus( bool bShow ) { if ( bShow ) GotoState('SlideIn'); } simulated function UpdateSlideScale( float DeltaTime ) { SlideScale -= DeltaTime * SlideSpeed; if ( SlideScale < 0.f ) { SlideScale = 0.f; GotoState('Hidden'); } } simulated function vector DrawObjectives( Canvas C, vector BoxPivot, bool bDefender, bool bGetBoxSize ) { if ( bGetBoxSize ) return Global.DrawObjectives( C, BoxPivot, bDefender, bGetBoxSize ); return vect(0,0,0); } } simulated function PostRender( Canvas C, float DeltaTime, bool bDefender ) { local float HeaderHeight; local float XL, YL; C.Style = ERenderStyle.STY_Alpha; C.Font = class'UT2MidGameFont'.static.GetMidGameFont( C.ClipX*0.75 * ASHUD.HUDScale ); C.StrLen( HeaderText, XL, YL); HeaderHeight = YL * 2; UpdateSlideScale( DeltaTime ); BoxSize = DrawObjectives( C, vect(0,0,0), bDefender, true ); //BoxSize = GetBoxSize( C, bDefender ); BoxPivot.X = C.ClipX - BoxSize.X; //BoxPivot.X = (C.ClipX - BoxSize.X) * 0.5; BoxPivot.Y = (BoxSize.Y+HeaderHeight) * SlideScale - BoxSize.Y; DrawBigCurrentObjective( C, bDefender, true ); // Draw Header Box C.SetDrawColor(255, 255, 255, 255); C.SetPos(BoxPivot.X, BoxPivot.Y - HeaderHeight); if ( ASHUD.PawnOwner != None && ASHUD.PawnOwner.GetTeamNum() == 0 ) C.DrawTileStretched(texture'InterfaceContent.Menu.ScoreBoxC', BoxSize.X, HeaderHeight); else C.DrawTileStretched(texture'InterfaceContent.Menu.ScoreBoxB', BoxSize.X, HeaderHeight); //C.DrawTileStretched(texture 'InterfaceContent.Menu.BorderBoxD', BoxSize.X, HeaderHeight); // Draw Objectives Box C.SetDrawColor(255, 255, 255, 255); C.SetPos(BoxPivot.X, BoxPivot.Y); if ( ASHUD.PawnOwner != None && ASHUD.PawnOwner.GetTeamNum() == 0 ) C.DrawTileStretched(texture'InterfaceContent.Menu.ScoreBoxC', BoxSize.X, BoxSize.Y); else C.DrawTileStretched(texture'InterfaceContent.Menu.ScoreBoxB', BoxSize.X, BoxSize.Y); // Draw Header Text if ( SlideScale == 1.f ) { C.Font = class'UT2MidGameFont'.static.GetMidGameFont( C.ClipX*0.75 * ASHUD.HUDScale ); C.DrawColor = C.MakeColor( 255, 255, 255, 255); C.StrLen( HeaderText, XL, YL); C.SetPos( BoxPivot.X + (BoxSize.X - XL)*0.5, BoxPivot.Y - (HeaderHeight + YL)*0.5 ); C.DrawText( HeaderText ); } // List Objectives DrawObjectives( C, BoxPivot, bDefender, false ); } /* if bGetBoxSize is true, function calculates the size needed for the objective list box Otherwise it draws the objective list... */ simulated function vector DrawObjectives( Canvas C, vector BoxPivot, bool bDefender, bool bGetBoxSize ) { local int i, priority, startpriority, endpriority; local bool bDrawObjectiveNumber; local float XL, YL, XUnit, YOffset; local vector ScreenPos, newBoxSize; local string entry; StartPriority = 0; EndPriority = ASHUD.ASGRI.MaxObjectivePriority; if ( !bGetBoxSize ) { C.Font = class'UT2MidGameFont'.static.GetMidGameFont( C.ClipX*0.75 * ASHUD.HUDScale ); C.StrLen("0", XL, YL); XUnit = XL; YOffset = BoxPivot.Y + YL*0.5; } for ( priority=StartPriority; priority<=EndPriority; priority++) { bDrawObjectiveNumber = true; // First pass, primary objectives for (i=0; i priority) || !ASHUD.OBJ[i].bOptionalObjective ) continue; // Only show non active optional objectives for current priority // this way we can still show optional objectives of different priority if ( !ASHUD.OBJ[i].IsActive() && ASHUD.OBJ[i].ObjectivePriority != priority ) continue; entry = CheckEntry( C, GetObjectiveDescription(ASHUD.OBJ[i], bDefender) ); if ( bGetBoxSize ) { C.StrLen( entry, XL, YL); newBoxSize.X = FMax( newBoxSize.X, XL ); newBoxSize.Y += YL; } else { SetObjectiveColor( C, ASHUD.OBJ[i] ); C.StrLen("0", XL, YL); C.SetPos( BoxPivot.X + XUnit*5, YOffset ); C.DrawText( entry ); if ( ASHUD.OBJ[i].IsCritical() ) { C.DrawColor = ASHUD.WhiteColor; ScreenPos.X = BoxPivot.X + XUnit*3 + XL*0.5; ScreenPos.Y = YOffset + YL*0.33; ASHUD.DrawCriticalObjectiveOverlay( C, ScreenPos, 0.3 ); } else { C.SetPos( BoxPivot.X + XUnit*4, YOffset ); C.DrawText( OptionalObjectivePrefix ); } YOffset += YL; } } } } if ( bGetBoxSize ) { // Check in case Header is larger than objectives info... C.Font = class'UT2MidGameFont'.static.GetMidGameFont( C.ClipX*0.75 * ASHUD.HUDScale ); C.StrLen( HeaderText, XL, YL); newBoxSize.X = FMax( newBoxSize.X, XL ); // Expand borders C.StrLen("0", XL, YL); XUnit = XL; newBoxSize.X += XUnit * 5; newBoxSize.Y += YL; return newBoxSize; } return vect(0,0,0); } /* makes sure entries are not too wide */ simulated function String CheckEntry( Canvas C, String Entry ) { local float XL, YL; local string left, right, newentry, previousentry; C.TextSize( entry, XL, YL); if ( XL < C.ClipX*0.33) return entry; // fit as much words as possible, and cut remaining... do { previousentry = newentry; if ( !Divide(Entry, SpaceSeparator, left, right) ) break; if ( newentry != "" ) newentry = newentry $ SpaceSeparator $ left; else newentry = newentry $ left; Entry = right; C.TextSize( newentry $ TextCutSuffix, XL, YL ); } until ( XL > C.ClipX*0.33 ) return (previousentry $ TextCutSuffix); } simulated function DrawBigCurrentObjective( Canvas C, bool bDefender, bool bCheckOverlap ) { local float XL, YL, XL2, YL2, XO, YO; local String CurrentObjectiveString; local vector ScreenPos; local byte bProgressPulsing; local int PrimaryObjectiveCount; if ( ASHUD.CurrentObjective == None ) return; C.Font = ASHUD.GetFontSizeIndex( C, 0 ); C.Style = ERenderStyle.STY_Alpha; if ( bDefender ) CurrentObjectiveString = ASHUD.CurrentObjective.Objective_Info_Defender; else CurrentObjectiveString = ASHUD.CurrentObjective.Objective_Info_Attacker; if ( CurrentObjectiveString != "" ) { PrimaryObjectiveCount = GetPrimaryObjectiveCount(); if ( PrimaryObjectiveCount > 1 ) CurrentObjectiveString = CurrentObjectiveString @ ObjTimesString $ PrimaryObjectiveCount; C.StrLen( CurrentObjectiveString, XL, YL ); if ( XL > C.ClipX*0.33 * ASHUD.HUDScale ) { C.Font = ASHUD.GetFontSizeIndex( C, -1 ); C.StrLen( CurrentObjectiveString, XL, YL ); if ( XL > C.ClipX*0.33 * ASHUD.HUDScale ) { C.Font = ASHUD.GetFontSizeIndex( C, -2 ); C.StrLen( CurrentObjectiveString, XL, YL ); if ( XL > C.ClipX*0.33 * ASHUD.HUDScale ) { C.Font = ASHUD.GetFontSizeIndex( C, -3 ); C.StrLen( CurrentObjectiveString, XL, YL ); } } } XL2 = XL + 64 * ASHUD.ResScaleX; YL2 = YL + 8 * ASHUD.ResScaleY; XO = C.ClipX * 0.5; YO = YL*0.5 + 10 * ASHUD.ResScaleY; // Draw only if not overlapping //if ( bCheckOverlap && XO + XL*0.5 > BoxPivot.X ) // return; // Draw background C.DrawColor = C.MakeColor(0, 0, 0, 150); C.SetPos( XO - XL2*0.5, YO - YL2*0.5 ); C.DrawTile(Texture'HudContent.Generic.HUD', XL2, YL2, 168, 211, 166, 44); // draw current objective text C.DrawColor = ASHUD.GetObjectiveColor( ASHUD.CurrentObjective ); if ( bCheckOverlap && XO + XL*0.5 > BoxPivot.X ) { XO -= (XO + XL*0.5 - BoxPivot.X); C.DrawColor.A = 128; } C.SetPos( XO - XL*0.5, YO - YL*0.5 ); C.DrawText( CurrentObjectiveString, false ); // Draw Objective Type Icon Background ScreenPos.X = XO - XL*0.5 - 20*ASHUD.ResScaleX; ScreenPos.Y = YO; XL2 = 27*ASHUD.ResScaleX*ASHUD.HUDScale*0.60; YL2 = 27*ASHUD.ResScaleY*ASHUD.HUDScale*0.60; C.DrawColor = C.MakeColor(255, 255, 255, 255); C.SetPos( ScreenPos.X - XL2, ScreenPos.Y - YL2); C.DrawTile(Texture'HudContent.Generic.HUD', XL2*2, YL2*2, 119, 258, 54, 54); // Draw Current Objective Type Icon if ( ASHUD.CurrentObjective.ObjectiveTypeIcon != None ) { C.DrawColor = ASHUD.GetObjectiveColor( ASHUD.CurrentObjective ); XL2 = 32*ASHUD.ResScaleX*ASHUD.HUDScale*0.4; YL2 = 32*ASHUD.ResScaleY*ASHUD.HUDScale*0.4; C.SetPos( ScreenPos.X - XL2, ScreenPos.Y - YL2); C.DrawTile(ASHUD.CurrentObjective.ObjectiveTypeIcon, XL2*2, YL2*2, 0, 0, 64, 64); } // Draw Shield overlay (defenders) if ( bDefender ) { C.DrawColor = ASHUD.GetObjectiveColor( ASHUD.CurrentObjective, bProgressPulsing ); if ( AnyPrimaryObjectivesCritical() ) C.DrawColor = ASHUD.GreenColor*ASHUD.fPulse + ASHUD.GoldColor*(1-ASHUD.fPulse); else C.DrawColor = ASHUD.GreenColor; if ( bProgressPulsing == 0 ) C.DrawColor.A = (127 + 64 * ASHUD.fPulse); else C.DrawColor.A = 127; XL2 = ASHUD.ResScaleX*ASHUD.HUDScale*0.45; YL2 = ASHUD.ResScaleY*ASHUD.HUDScale*0.45; C.SetPos(ScreenPos.X - XL2 * 32, ScreenPos.Y - YL2 * 32); C.DrawTile( Texture'AS_FX_TX.HUD.OBJ_Status', 64*XL2, 64*YL2, 191.0, 191.0, 64, 64); } // objective progress status ASHUD.DrawObjectiveStatusOverlay( C, GetGlobalObjectiveProgress(), AnyPrimaryObjectivesCritical(), ScreenPos, 1.0f ); ASHUD.DrawObjectiveStatusOverlay( C, GetGlobalObjectiveProgress(), AnyPrimaryObjectivesCritical(), ScreenPos, 1.1f ); // display critical icon for any critical primary objective if ( AnyPrimaryObjectivesCritical() ) { C.DrawColor = ASHUD.WhiteColor; ASHUD.DrawCriticalObjectiveOverlay( C, ScreenPos, 1.f ); } } } /* returns number of primary objectives currently relevant */ simulated function int GetPrimaryObjectiveCount() { local int i, Count; for (i=0; i TeamProjectileClasses[2]; function DoFireEffect() { local Vector ProjOffset; local Vector Start, X,Y,Z, HL, HN; if ( Instigator.IsA('ASVehicle') ) ProjOffset = ASVehicle(Instigator).VehicleProjSpawnOffset; ProjSpawnOffset = ProjOffset; Instigator.MakeNoise(1.0); Instigator.GetAxes(Instigator.Rotation, X, Y, Z); Start = MyGetFireStart(X, Y, Z); ASVehicle(Instigator).CalcWeaponFire( HL, HN ); SpawnProjectile(Start, Rotator(HL - Start)); } simulated function vector MyGetFireStart(vector X, vector Y, vector Z) { return Instigator.Location + X*ProjSpawnOffset.X + Y*ProjSpawnOffset.Y + Z*ProjSpawnOffset.Z; } function projectile SpawnProjectile(Vector Start, Rotator Dir) { local Projectile p; p = Weapon.Spawn(TeamProjectileClasses[Instigator.GetTeamNum()], Instigator, , Start, Dir); if ( p == None ) return None; p.Damage *= DamageAtten; return p; } simulated function bool AllowFire() { return true; } //============================================================================= // defaultproperties //============================================================================= }/U"//============================================================================= // DestroyVehicleObjective //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class DestroyVehicleObjective extends GameObjective; var ASVehicleFactory TargetFactory; var Vehicle TargetVehicle; replication { reliable if ( Role == Role_Authority ) TargetVehicle; } function PostBeginPlay() { local ASVehicleFactory ASVF; super.PostBeginPlay(); ForEach AllActors(class'ASVehicleFactory', ASVF) if ( ASVF.VehicleEvent == Tag ) { TargetFactory = ASVF; TargetVehicle = TargetFactory.Child; TargetFactory.MyDestroyVehicleObjective = Self; break; } } function VehicleSpawned( Vehicle NewTargetVehicle ) { NetUpdateTime = Level.TimeSeconds - 1; TargetVehicle = NewTargetVehicle; TargetVehicle.bNoFriendlyFire = true; } /* triggered by intro cinematic to auto complete objective */ function CompleteObjective( Pawn Instigator ) { if ( TargetVehicle != None && TargetVehicle.Health > 0 ) TargetVehicle.Died( TargetVehicle.Controller, class'Suicided', TargetVehicle.Location ); else DisableObjective( Instigator ); } function Trigger(Actor Other, Pawn Instigator) { if ( !bDisabled && UnrealMPGameInfo(Level.Game).CanDisableObjective( Self ) ) DisableObjective( Instigator ); } /* TellBotHowToDisable() tell bot what to do to disable me. return true if valid/useable instructions were given */ function bool TellBotHowToDisable(Bot B) { if ( bDisabled || TargetVehicle == None ) return false; if ( B.CanAttack( TargetVehicle ) ) { B.GoalString = "Attack Objective"; B.DoRangedAttackOn( TargetVehicle ); return true; } return super.TellBotHowToDisable( B ); } /* returns objective's progress status 1->0 (=disabled) */ simulated function float GetObjectiveProgress() { if ( bDisabled || TargetVehicle == None ) return 0; return (float(TargetVehicle.Health) / TargetVehicle.HealthMax); } }/9l9b  G}/h9E,w5K E,6D,6B,6 G}/N&}/}/[!]}/}%}/}/}/}/p9@,S'bg% (aM, @,~+Drg%**g% g% G}/}/}/E @:J#8' G}/g%}/}/X]//============================================================================= // DECO_ExplodingBarrel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class DECO_ExplodingBarrel extends Decoration; #exec OBJ LOAD FILE=..\StaticMeshes\CP_MechStaticPack1.usx var int Backup_Health; var VolumeTimer VT; var Controller DelayedDamageInstigatorController; var float RadiusDamage; var bool bCheckForStackedBarrels; function Landed(vector HitNormal); function HitWall (vector HitNormal, actor Wall); singular function PhysicsVolumeChange( PhysicsVolume NewVolume ); singular function BaseChange(); function PostBeginPlay() { super.PostBeginPlay(); Backup_Health = Health; } function SetDelayedDamageInstigatorController(Controller C) { DelayedDamageInstigatorController = C; } function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class damageType) { if ( !bDamageable || (Health<0) ) return; if ( damagetype == None ) DamageType = class'DamageType'; if ( InstigatedBy != None ) Instigator = InstigatedBy; else if ((instigatedBy == None || instigatedBy.Controller == None) && DamageType.default.bDelayedDamage && DelayedDamageInstigatorController != None) instigatedBy = DelayedDamageInstigatorController.Pawn; if ( Instigator != None ) MakeNoise(1.0); Health -= NDamage; FragMomentum = Momentum; if ( Health < 0 ) { NetUpdateTime = Level.TimeSeconds - 1; CheckNearbyBarrels(); if ( EffectWhenDestroyed != None ) Spawn( EffectWhenDestroyed, Owner,, Location ); bHidden = true; SetCollision(false, false, false); VT = Spawn(class'VolumeTimer', Self); VT.SetTimer(0.2, false); } } /* Barrels stacked on top, are set off instantly. Sides and below are set off with a slight delay */ function CheckNearbyBarrels() { bCheckForStackedBarrels = true; HurtRadius( 100, RadiusDamage, class'DamTypeExploBarrel', 256, Location ); } // delayed explosion for barrel chain reaction explosions function TimerPop( VolumeTimer T ) { VT.Destroy(); bCheckForStackedBarrels = false; HurtRadius( 100, RadiusDamage, class'DamTypeExploBarrel', 256, Location ); } /* HurtRadius() Hurt locally authoritative actors within the radius. */ simulated function HurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) { local actor Victims; local float damageScale, dist; local vector dir; if( bHurtEntry ) return; bHurtEntry = true; foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation ) { /* Set off top barrels instantly, side and below are set off with a delay*/ if ( bCheckForStackedBarrels && Victims.IsA('DECO_ExplodingBarrel') && Victims.Location.Z <= HitLocation.Z ) continue; /* limit damage radius to right next barrel, so we can set them of one after the other */ if ( Victims.IsA('DECO_ExplodingBarrel') && !IsNearbyBarrel(Victims) ) continue; // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag if( (Victims != self) && (Victims.Role == ROLE_Authority) && (!Victims.IsA('FluidSurfaceInfo')) ) { dir = Victims.Location - HitLocation; dist = FMax(1,VSize(dir)); dir = dir/dist; damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); if ( Instigator == None || Instigator.Controller == None ) Victims.SetDelayedDamageInstigatorController( DelayedDamageInstigatorController ); Victims.TakeDamage ( damageScale * DamageAmount, Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), DamageType ); if (Instigator != None && Vehicle(Victims) != None && Vehicle(Victims).Health > 0) Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation); } } bHurtEntry = false; } simulated final function bool IsNearbyBarrel(Actor A) { local vector Dir; Dir = Location - A.Location; if ( abs(Dir.Z) > CollisionHeight*2.67 ) return false; Dir.Z = 0; return ( VSize(Dir) <= CollisionRadius*2.25 ); } function Reset() { super.Reset(); NetUpdateTime = Level.TimeSeconds - 1; Health = Backup_Health; bHidden = false; SetCollision(true, true, true); } function Bump( actor Other ) { if ( Mover(Other) != None && Mover(Other).bResetting ) return; if ( VSize(Other.Velocity) > 500 ) { Instigator = Pawn(Other); if ( Instigator != None && Instigator.Controller != None ) SetDelayedDamageInstigatorController( Instigator.Controller ); TakeDamage( VSize(Other.Velocity)*0.03, Instigator, Location, vect(0,0,0), class'Crushed'); } } event EncroachedBy(Actor Other) { if ( Mover(Other) != None && Mover(Other).bResetting ) return; Instigator = Pawn(Other); if ( Instigator != None && Instigator.Controller != None ) SetDelayedDamageInstigatorController( Instigator.Controller ); TakeDamage( 1000, Instigator, Location, vect(0,0,0), class'Crushed'); } function bool EncroachingOn(Actor Other) { if ( Mover(Other) != None && Mover(Other).bResetting ) return false; Instigator = Pawn(Other); if ( Instigator != None && Instigator.Controller != None ) SetDelayedDamageInstigatorController( Instigator.Controller ); TakeDamage( 1000, Instigator, Location, vect(0,0,0), class'Crushed'); return false; } //============================================================================= // defaultproperties //============================================================================= }/u9{9_2' G}/}/}/}9_c' G}/}/y9~7X B&~9cZKe?4AfhhAfhhAfʁ)hhʁ)3}ʁ)ʁ)ʁ)ʁ)ʁ)ʁ)ʁ)ʁ)hʁ)ʁ)ʁ)ʁ)ʁ)}L}LhIShp,e3}IS x%$CQ%H,X$h"" Si$?#05$BVFA] B}/}/ l~%UsO$+P&bP&e+b+^+A,a<P&~% O$O$6~% e+6~% b+6~% ^+O$O$a b G}/}/}/w9b:Y!?Uwc%*v%}%!}/P$%sP$,IP$}%!}/(iiP$}%c%'P$#c% 9?@b$c% (' G}/D,class DECO_Convoy_BoxStraps extends Decoration; #exec MESH IMPORT MESH=Convoy_BoxStraps ANIVFILE=Models\BoxStraps_a.3d DATAFILE=Models\BoxStraps_d.3d #exec MESH ORIGIN MESH=Convoy_BoxStraps X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_BoxStraps STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_BoxStraps SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_BoxStraps X=1 Y=1 Z=1 #exec MESH IMPORT MESH=Convoy_LargeStrap ANIVFILE=Models\LargeStrap_a.3d DATAFILE=Models\LargeStrap_d.3d #exec MESH ORIGIN MESH=Convoy_LargeStrap X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_LargeStrap STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_LargeStrap SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_LargeStrap X=1 Y=1 Z=1 #exec MESH IMPORT MESH=Convoy_LrgRoundStrap ANIVFILE=Models\LrgRoundStrap_a.3d DATAFILE=Models\LrgRoundStrap_d.3d #exec MESH ORIGIN MESH=Convoy_LrgRoundStrap X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_LrgRoundStrap STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_LrgRoundStrap SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_LrgRoundStrap X=1 Y=1 Z=1 #exec MESH IMPORT MESH=Convoy_MediumStrap ANIVFILE=Models\MediumStrap_a.3d DATAFILE=Models\MediumStrap_d.3d #exec MESH ORIGIN MESH=Convoy_MediumStrap X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_MediumStrap STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_MediumStrap SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_MediumStrap X=1 Y=1 Z=1 #exec MESH IMPORT MESH=Convoy_MedRoundStrap ANIVFILE=Models\MedRoundStrap_a.3d DATAFILE=Models\MedRoundStrap_d.3d #exec MESH ORIGIN MESH=Convoy_MedRoundStrap X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_MedRoundStrap STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_MedRoundStrap SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_MedRoundStrap X=1 Y=1 Z=1 #exec MESH IMPORT MESH=Convoy_SmRoundStrap ANIVFILE=Models\SmRoundStrap_a.3d DATAFILE=Models\SmRoundStrap_d.3d #exec MESH ORIGIN MESH=Convoy_SmRoundStrap X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH LODPARAMS MESH=Convoy_SmRoundStrap STRENGTH=0.5 #exec MESH SEQUENCE MESH=Convoy_SmRoundStrap SEQ=Wind STARTFRAME=0 NUMFRAMES=9 #exec MESHMAP SCALE MESHMAP=Convoy_SmRoundStrap X=1 Y=1 Z=1 simulated function PostBeginPlay() { super.PostBeginPlay(); LoopAnim('Wind', 1.0, 0.1); } /* simulated function AnimEnd(int Channel) { PlayAnim('Wind', 1.0, 0.1); } */ //============================================================================= // defaultproperties //============================================================================= }/| sk+j| F| k+B&.k+CwB&*B&E!B& GB:Q7~"BD:G@?4 S1n3K7b Y#0rSXSeSB}/}/h%]&!_]&9h%!}/ h%!}/i%]&\/]&a0 i%h%[[10 G}/Mclass DECO_ConvoyFlag extends Decoration; #exec MESH IMPORT MESH=ConvoyFlag ANIVFILE=Models\Flag_a.3d DATAFILE=Models\Flag_d.3d #exec MESH ORIGIN MESH=ConvoyFlag X=0 Y=0 Z=0 PITCH=0 YAW=0 ROLL=0 #exec MESH SEQUENCE MESH=ConvoyFlag SEQ=Flag STARTFRAME=0 NUMFRAMES=10 #exec MESHMAP SCALE MESHMAP=ConvoyFlag X=1 Y=1 Z=1 //============================================================================= // defaultproperties //============================================================================= }/ E:C+C"@;wi%*aaC+ C+ a>('( GF:}"BH:x+?4 n3J7$ A#0XSeSB}/}/}/}/ G:G#0 a G}/ J:L:N#5' G}/}/}/ K:N:P$:V' G}/}/}/M:P:A?9Wh% G}/@}/}/O:m%aFvm%9D9?,*9?, /9:m%a&%a i%-am%z+ @}+ D|+{+m%a&$ G}/Eclass DamTypeSentinelLaser extends VehicleDamageType abstract; }/ Q:n%[U@4 n%%1n%, n%a&$n%  G}/W:y+M g Kr.| * 3-y+.| PH.| \ G}/Kclass DamTypeMinigunTurretBullet extends VehicleDamageType abstract; }/\&w+CC>\&!}//w+a9 RE+\&=E+D 10( G}/ Y:N!b M ' G}/E+}/}/i:{!]N M ( G}/V:[:Al9W\& G}/@}/}/Sclass DamTypeExploBarrel extends DamageType abstract; static function GetHitEffects(out class HitEffects[4], int VictimHealth) { HitEffects[0] = class'HitSmoke'; if( VictimHealth <= 0 ) HitEffects[1] = class'HitFlameBig'; else if ( FRand() < 0.8 ) HitEffects[1] = class'HitFlame'; } }/q //============================================================================= // ASVehicle_Sentinel_Floor_Swivel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel_Floor_Swivel extends ASTurret_Minigun_Swivel; //============================================================================= // defaultproperties //============================================================================= }/}/}/}/A}/[&J+!OJ+L[&!}//J+a0 AL+[&K7s%s%L+10 G}/i//============================================================================= // ASVehicle_Sentinel_Floor_Base //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel_Floor_Base extends ASTurret_Base; simulated event PostBeginPlay() { super.PostBeginPlay(); // Hack to instance correctly the skeletal collision boxes GetBoneCoords(''); SetCollision(false, false); SetCollision(true, true); } auto state Sleeping { simulated event AnimEnd( int Channel ) { if ( ASVehicle_Sentinel(Owner).bActive ) GotoState('Opening'); else PlayAnim('IdleClosed', 4, 0.0); } simulated function BeginState() { AnimEnd( 0 ); } } state Active { simulated function BeginState() { LoopAnim('IdleOpen', 4, 0.0); } } state Opening { simulated event AnimEnd( int Channel ) { GotoState('Active'); } simulated function BeginState() { PlayAnim('Open', 0.33, 0.0); } } state Closing { simulated function BeginState() { PlayAnim('Close', 0.33, 0.0); } } //============================================================================= // defaultproperties //============================================================================= }/p:}/}/`:d:C Ay%%<y%7s%y%s% f-I+y%( G}/e:}/}/y%}/}/{//============================================================================= // ASVehicle_Sentinel_Ceiling_Swivel //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASVehicle_Sentinel_Ceiling_Swivel extends ASTurret_Minigun_Swivel; simulated event PostBeginPlay() { super.PostBeginPlay(); // Hack to instance correctly the skeletal collision boxes GetBoneCoords(''); SetCollision(false, false); SetCollision(true, true); } auto state Sleeping { simulated event AnimEnd( int Channel ) { if ( ASVehicle_Sentinel(Owner).bActive ) GotoState('Opening'); else PlayAnim('IdleClosed', 4, 0.0); } simulated function BeginState() { AnimEnd( 0 ); } } state Active { simulated event AnimEnd( int Channel ) { GotoState('Active'); } simulated function BeginState() { PlayAnim('IdleOpen', 4, 0.0); } } state Opening { simulated function BeginState() { PlayAnim('Open', 0.33, 0.0); } } state Closing { simulated function BeginState() { PlayAnim('Close', 0.33, 0.0); } } //============================================================================= // defaultproperties //============================================================================= }/c:h:A(f(9W[&bEnabled9T-I+ G}/@}/}/A:r+V#S #Y!r+l+t+\\%d"- l+ ? ?9? G}/tAclass ASSentinelController extends SentinelController; var float StartSearchTime; var Rotator LastRotation; function AnimEnded(); function Awake(); function GoToSleep(); function rotator AdjustAim(FireProperties FiredAmmunition, vector projStart, int aimerror) { if ( (FRand() < 0.45) && (Enemy != None) && (Enemy.Controller != None) ) Enemy.Controller.ReceiveWarning(Pawn, -1, vector(Rotation)); return Rotation; } auto state Sleeping { event SeePlayer(Pawn SeenPlayer) { if ( IsTargetRelevant( SeenPlayer ) ) Awake(); } function Awake() { LastRotation = Rotation; if ( ASVehicle_Sentinel(Pawn).Awake() ) GotoState('Opening'); } function ScanRotation() { local actor HitActor; local vector HitLocation, HitNormal, Dir; local float BestDist, Dist; local rotator Pick; DesiredRotation.Yaw = Rotation.Yaw + 16384 + Rand(32768); Dir = vector(DesiredRotation); // check new pitch not a blocked direction HitActor = Trace(HitLocation,HitNormal,Pawn.Location + 2000 * Dir,Pawn.Location,false); if ( HitActor == None ) return; BestDist = vsize(HitLocation - Pawn.Location); Pick = DesiredRotation; DesiredRotation.Yaw += 32768; Dir = vector(DesiredRotation); // check new pitch not a blocked direction HitActor = Trace(HitLocation,HitNormal,Pawn.Location + 2000 * Dir,Pawn.Location,false); if ( HitActor == None ) return; Dist = vsize(HitLocation - Pawn.Location); if ( Dist > BestDist ) { BestDist = Dist; Pick = DesiredRotation; } DesiredRotation.Yaw += 16384; Dir = vector(DesiredRotation); // check new pitch not a blocked direction HitActor = Trace(HitLocation,HitNormal,Pawn.Location + 2000 * Dir,Pawn.Location,false); if ( HitActor == None ) return; Dist = vsize(HitLocation - Pawn.Location); if ( Dist > BestDist ) { BestDist = Dist; Pick = DesiredRotation; } DesiredRotation.Yaw += 32768; Dir = vector(DesiredRotation); // check new pitch not a blocked direction HitActor = Trace(HitLocation,HitNormal,Pawn.Location + 2000 * Dir,Pawn.Location,false); if ( HitActor == None ) return; Dist = vsize(HitLocation - Pawn.Location); if ( Dist > BestDist ) { BestDist = Dist; Pick = DesiredRotation; } DesiredRotation = Pick; } Begin: if ( IsSpawnCampProtecting() ) // spawn camp protection turrets should never sleep... { AcquisitionYawRate *= 100; Pawn.PeripheralVision = -1.0; // Full circle vision :) Awake(); } ScanRotation(); FocalPoint = Pawn.Location + 1000 * vector(DesiredRotation); Sleep(2 + 3*FRand()); Goto('Begin'); } state Opening { event SeePlayer(Pawn SeenPlayer); function AnimEnded() { GotoState('Searching'); } } state Closing { event SeePlayer(Pawn SeenPlayer); function AnimEnded() { GotoState('Sleeping'); } Begin: DesiredRotation = Rotation; DesiredRotation.Pitch = 0; FocalPoint = Pawn.Location + 1000 * vector(DesiredRotation); Sleep( 0.5 ); ASVehicle_Sentinel(Pawn).GoToSleep(); } state Searching { function BeginState() { super.BeginState(); StartSearchTime = Level.TimeSeconds; } function GoToSleep() { GotoState('Closing'); } Begin: if ( !IsSpawnCampProtecting() && (Level.TimeSeconds > StartSearchTime + 10) ) GoToSleep(); else { ScanRotation(); FocalPoint = Pawn.Location + 1000 * vector(DesiredRotation); Sleep( GetScanDelay() ); Goto('Begin'); } } function bool IsSpawnCampProtecting() { return ( ASVehicle_Sentinel(Pawn) != None && ASVehicle_Sentinel(Pawn).bSpawnCampProtection ); } function float GetScanDelay() { if ( IsSpawnCampProtecting() ) // more aggressive scanning if spawn protecting return 2; return ( 2 + 3*FRand() ); } function float GetWaitForTargetTime() { if ( IsSpawnCampProtecting() ) // more aggressive scanning if spawn protecting return 2; return super.GetWaitForTargetTime(); } function Possess(Pawn aPawn) { super.Possess( aPawn ); if ( IsSpawnCampProtecting() ) // kill on sight { Skill = 10; FocusLead = 0; } } }/}/A}/Q&P+!OP+LQ&!}//P+a0 A[+Q&K7z%z%[+10 G}/]%//============================================================================= // ASPlayerReplicationInfo //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASPlayerReplicationInfo extends xPlayerReplicationInfo; var byte DisabledObjectivesCount; var byte DisabledFinalObjective; var byte DestroyedVehicles; var float TrophiesXOffset; // for drawing tropheys on scoreboard var String PawnOverrideClass; var bool bAutoRespawn; // for reinforcements var bool bTeleportToSpawnArea; // Player can teleport to new spawn area var int TeleportTime; // countdown until valid replication { reliable if ( bNetDirty && Role == ROLE_Authority ) DisabledObjectivesCount, DisabledFinalObjective, bAutoRespawn, bTeleportToSpawnArea, TeleportTime, DestroyedVehicles; } function Timer() { local NavigationPoint NP; local Controller C; local GameObjective GO; super.Timer(); if ( bBot && bTeleportToSpawnArea && TeleportTime != Level.TimeSeconds ) { C = Controller(Owner); GO = ASGameInfo(Level.Game).GetCurrentObjective(); if ( GO == None || !CanBotTeleport( C ) ) { bTeleportToSpawnArea = false; return; } // Only Teleport if far from new Spawn Area NP = Level.Game.FindPlayerStart( C, C.GetTeamNum() ); // Check if worth respawning if ( VSize(GO.Location - C.Pawn.Location) > VSize(GO.Location - NP.Location) + 1024 ) ASGameInfo(Level.Game).TeleportPlayerToSpawn( C ); else { bTeleportToSpawnArea = false; } } } function bool CanBotTeleport( Controller C ) { local Vehicle V; if ( C.Pawn == None ) return false; // Don't exit if in a vehicle, except turrets if ( Vehicle(C.Pawn) != None ) { V = Vehicle(C.Pawn); if ( V.IndependentVehicle() && !V.bStationary ) return false; if ( !V.IndependentVehicle() && !V.GetVehicleBase().bStationary ) return false; } return true; } /* Reset() reset actor to initial state - used when restarting level without reloading. */ function Reset() { PawnOverrideClass = ""; HasFlag = None; bReadyToPlay = false; NumLives = 0; bOutOfLives = false; bTeleportToSpawnArea = false; } }/U4//============================================================================= // ASCriticalObjectiveVolume //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASCriticalObjectiveVolume extends Volume; var Info CheckTimer; var() class ConstraintPawnClass; function PostBeginPlay() { // skip associatedactor setup.. super(Brush).PostBeginPlay(); } function Destroyed() { if ( CheckTimer != None ) { CheckTimer.Destroy(); CheckTimer = None; } super.Destroyed(); } function bool IsCriticalPawn( Pawn P ) { if ( !ClassIsChildOf(P.Class, ConstraintPawnClass) ) return false; if ( P.Health > 0 && P.Controller != None && P.Controller.GetTeamNum() == 1 - Level.Game.GetDefenderNum() ) return true; return false; } auto state Safe { event Touch( Actor Other ) { local GameObjective GO; if ( Other != None && Other.IsA('Pawn') && IsCriticalPawn( Pawn(Other) ) ) { // Attackers have breached the 'Critical' objective volume (!!!) // Set Objectives to 'critical' for ( GO=TeamGame(Level.Game).Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( GO.MyBaseVolume == Self && GO.IsActive() ) { GO.SetCriticalStatus( true ); if ( GO.DefenseSquad != None ) GO.DefenseSquad.Team.AI.CriticalObjectiveWarning(GO, Pawn(Other)); } } GotoState('Critical'); } } } function bool IsStillCritical() { local Pawn P; local GameObjective GO; foreach TouchingActors(class'Pawn', P) if ( IsCriticalPawn( P ) ) { for ( GO=TeamGame(Level.Game).Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( GO.MyBaseVolume == Self && GO.IsActive() && (GO.DefenseSquad != None) ) GO.DefenseSquad.Team.AI.CriticalObjectiveWarning(GO, P); } return true; } // Turn active objectives to 'safe' for ( GO=TeamGame(Level.Game).Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( GO.MyBaseVolume == Self ) GO.SetCriticalStatus( false ); } return false; } state Critical { function TimerPop(VolumeTimer T) { if ( !IsStillCritical() ) GotoState('Safe'); } function BeginState() { if ( CheckTimer == None ) CheckTimer = Spawn(class'VolumeTimer', Self); } } /* Objective has been disabled... check if the volume should keep on monitoring breaching... ( several objectives might be sharing the same volume ) */ state ObjectiveDisabled { function BeginState() { local GameObjective GO; local bool bStillCritical; for ( GO=TeamGame(Level.Game).Teams[0].AI.Objectives; GO!=None; GO=GO.NextObjective ) { if ( GO.MyBaseVolume == Self && !GO.bDisabled ) bStillCritical = true; } // if there is at least another active objective... keep on monitoring! if ( bStillCritical ) { GotoState('Critical'); return; } GotoState('Disabled'); } } state Disabled { function BeginState() { if ( CheckTimer != None ) { CheckTimer.Destroy(); CheckTimer = None; } } } function Reset() { super.Reset(); GotoState('Safe'); } }/l:p+Ch{%%c{%7z%.p+"O 9:{%z%F9:${%( G}/c%}/}/{%}/n:R1m!27r:F׿e]3}B'yؚؚؚؚ3}B'yؚؚؚؚؚ\fF'yؚ3}B'yؚؚؚؚʁ)3}B'yؚؚؚؚؚؚ\fF'yؚhhhh,e3}Zs׿e] j}/}/o:t:A'q9WQ& G}/@}/}/v//============================================================================= // ASCinematic_SceneManager //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASCinematic_SceneManager extends Info placeable; var() name CameraTag; var() name EventSceneStarted; var() name EventSceneEnded; var ASCinematic_Camera Camera; function PostBeginPlay() { super.PostBeginPlay(); if ( CameraTag != '' ) ForEach AllActors(class'ASCinematic_Camera', Camera, CameraTag) break; } function Trigger( Actor Other, Pawn EventInstigator ) { PlayScene(); } function PlayScene() { Level.Game.SceneStarted( None, Self ); Camera.SetView( Self ); TriggerEvent(EventSceneStarted, Self, None); } event ShotEnded( ASCinematic_Camera Cam ) { if ( Cam != None && Cam.NextCamera != None && Cam.NextCamera != Camera ) // safety check, avoid loops { if ( Cam.NextCamera.bActive ) Cam.NextCamera.SetView( Self ); else ShotEnded( Cam.NextCamera ); // Skip if not active (use triggers to activate/deactivate cameras) } else SceneEnded(); } event SceneEnded() { Level.Game.SceneEnded( None, Self ); TriggerEvent(EventSceneEnded, Self, None); } }/o"//============================================================================= // ASCinematic_Camera //============================================================================= // Created by Laurent Delayen // 2003, Epic Games, Inc. All Rights Reserved //============================================================================= class ASCinematic_Camera extends Actor placeable; var() float ShotLength; // length of shot in seconds... var() name EventViewingCamera; // Event triggered when camera is active var() name NextCameraTag; var ASCinematic_Camera NextCamera; var() bool bInitiallyActive; var bool bActive; var ASCinematic_SceneManager ASCSM; function PostBeginPlay() { super.PostBeginPlay(); bActive = bInitiallyActive; if ( NextCameraTag != '' ) ForEach AllActors(class'ASCinematic_Camera', NextCamera, NextCameraTag) break; if ( ShotLength == 0 ) // safety check ShotLength = 2; } /* Specific version, when viewing an objective for end of round cam (and attackers didn't win)*/ function ViewFixedObjective( PlayerController PC, GameObjective GO ) { PC.ClientSetFixedCamera( true ); PC.ClientSetViewTarget( Self ); PC.SetViewTarget( Self ); } /* Scene Manager sets the view on this camera */ function SetView( ASCinematic_SceneManager SM ) { local Controller C, NextC; local PlayerController PC; C = Level.ControllerList; while ( C != None ) { NextC = C.NextController; if ( C.PlayerReplicationInfo != None && !C.PlayerReplicationInfo.bOnlySpectator ) { PC = PlayerController(C); if ( PC != None ) { PC.ClientSetFixedCamera( true ); PC.ClientSetViewTarget( Self ); PC.SetViewTarget( Self ); } } C = NextC; } TriggerEvent(EventViewingCamera, Self, None); if ( SM != None ) { SetTimer( ShotLength, false ); ASCSM = SM; } } function Timer() { ASCSM.ShotEnded( Self ); } function Trigger( Actor Other, Pawn EventInstigator ) { bActive = !bActive; } /* Reset() reset actor to initial state - used when restarting level without reloading. */ function Reset() { super.Reset(); bActive = bInitiallyActive; } }/_+c+Ck!c+wk!*w.k!*6c+ .k! _+k! T$`+k!k!( G}/@"//============================================================================= // ACTION_PlayExplosionSound //============================================================================= // Standardize explosion sounds... // Various explosion sounds are combined to create a unique and loud sound //============================================================================= // Created by Laurent Delayen // 2004, Epic Games, Inc. All Rights Reserved //============================================================================= class ACTION_PlayExplosionSound extends LatentScriptedAction; var(Action) name SoundEmitterActorTag; // source emitting the sound (none = self) var(Action) float SoundVolumeScale; // volume scale var(Action) float SoundRadiusScale; // radius scale var(Action) float SoundPitchScale; // pitch scale var Actor SoundEmitter; var Sound ExplosionSound[11]; var byte bPlayed[11]; event PostBeginPlay( ScriptedSequence SS ) { super.PostBeginPlay( SS ); if ( SoundEmitterActorTag == 'None' || SoundEmitterActorTag == '' ) SoundEmitter = SS; else ForEach SS.AllActors(class'Actor', SoundEmitter, SoundEmitterActorTag) break; } function bool InitActionFor(ScriptedController C) { if ( SoundEmitter != None ) { PlayUniqueRandomExplosion(); PlayUniqueRandomExplosion(); C.CurrentAction = self; C.SetTimer(0.33, false); return true; } return false; } event ActionCompleted() { PlayUniqueRandomExplosion(); } function bool CompleteWhenTriggered() { return true; } function bool CompleteWhenTimer() { return true; } function string GetActionString() { return ActionString @ SoundEmitterActorTag; } function PlayUniqueRandomExplosion() { local int Num; Num = Rand(42) % 11; if ( bPlayed[Num] > 0 ) { PlayUniqueRandomExplosion(); // try again if already played this sound... return; } SoundEmitter.PlaySound(ExplosionSound[Num],, 4.0*SoundVolumeScale,, 1600*SoundRadiusScale, SoundPitchScale); bPlayed[Num] = 1; } event Reset() { local int i; super.Reset(); for (i=0; i<11; i++) bPlayed[i] = 0; } }/k!}/x:S:E#20z: yC8Erʁ)**7z B T]%$?Y%$?W%$?Z Z Z Z Z Z Z Z Z Z Z }]Play explosion sound}/}/w:|:A4Radius:9U_+Intensity:9S`+ G}/@}/}/~//============================================================================= // ACTION_PlayerViewShake //============================================================================= // Shake player's view within radius. Against ViewShakes, it works client side //============================================================================= // Created by Laurent Delayen // 2004, Epic Games, Inc. All Rights Reserved //============================================================================= class ACTION_PlayerViewShake extends ScriptedAction; var(Action) float Radius; var(Action) int Intensity; function bool InitActionFor(ScriptedController C) { local Controller Ctrl; for ( Ctrl=C.Level.ControllerList; Ctrl!=None; Ctrl=Ctrl.NextController ) if ( (PlayerController(Ctrl) != None) && (VSize(C.Location - PlayerController(Ctrl).ViewTarget.Location) < Radius) ) Ctrl.DamageShake( Intensity ); return false; } function string GetActionString() { return ActionString @ "Radius:" @ Radius @ "Intensity:" @ Intensity; } }:{:A%20 ~:E).*3},e* uʁ),e,e B Tq$DV%"}]PlayerViewShake}/}/e//============================================================================= // ACTION_ASTeleportToSpawnArea //============================================================================= // Complete objectives //============================================================================= // Created by Laurent Delayen // 2004, Epic Games, Inc. All Rights Reserved //============================================================================= class ACTION_ASTeleportToSpawnArea extends ScriptedAction; var(Action) name PlayerSpawnManagerTag; var Array PSMs; event PostBeginPlay( ScriptedSequence SS ) { local PlayerSpawnManager PSM; super.PostBeginPlay( SS ); if ( PlayerSpawnManagerTag != 'None' ) { ForEach SS.AllActors(class'PlayerSpawnManager', PSM, PlayerSpawnManagerTag) PSMs[PSMs.Length] = PSM; } } function bool InitActionFor(ScriptedController C) { local int i; for (i=0; i PSMs; event PostBeginPlay( ScriptedSequence SS ) { local PlayerSpawnManager PSM; super.PostBeginPlay( SS ); if ( PlayerSpawnManagerTag != 'None' ) { ForEach SS.AllActors(class'PlayerSpawnManager', PSM, PlayerSpawnManagerTag) PSMs[PSMs.Length] = PSM; } } function bool InitActionFor(ScriptedController C) { local int i; for (i=0; i$>}/PZ$@$@}/QZ 8Z$$}/ Z$$}/Z$D$@E}/}/}/FiT(S)%SSY$*}/$?*}/C$>[$= "#6:H]Z 8Z$ $ }/ Z$$}/Z$H$H}/}/g,Y$?$@?}/Z 8Z$HC$HC}/ Z$4C$4C}/Z$B$B}/}/$pA Z$>$>}/QZ 8Z$$}/ Z$$}/Z$C$C}/}/}/ xi"iT(SSY$*}/$?*}/C$?[$= "6: ]Z 8Z$$}/ Z$$}/Z$$}/}/gZ 8Z$ȶ>$rH?}/ Z$$}/Z$$}/}/Z 8Z$?$?}/ Z$?$?}/Z$?$?}/}/$pBZ$?$?}/PZ$@$@}/}/(S)%SSMH"I"$?[:BY=$*}/$L>*}/$L?*@@@}/$?*@@@}/"Z 8Z$>$@?}/ Z$$}/Z$$}/}/,Y$$=}/$?$?}/Z 8Z$HB$pB}/ Z$B$B}/Z$B$B}/}/_"$@$@0 S"Z"Z$@$@}/_!Z 8Z$?$?}/ Z$?$?}/Z$?$?}/}/}/ (S;S[:uNZ 8Z$?$?}/ Z$?$?}/Z$?$?}/}/"tZ 8Z$$}/ Z$$}/Z$$}/}/'Z 8Z$$}/ Z$L>$?}/Z$$}/}/$ F0$Z$@$@}/QZ 8Z$$C}/ Z$$C}/Z$D$D}/}/}/(S;)%SSh4$+?"]"2KZ$$B}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$?}/$?$@}/Z 8Z$A$B}/ Z$B$B}/Z$B$B}/}/Q Yq qZ$D$D}/kZ$333?$?}/~ "lZ$@$@}/{Z$L>$L>}/}/q qZ$D$D}/kZ$?$?}/~ "lZ$@$@}/{Z$L>$L>}/}/HF Z$?$?}/$pA0S"Z"$Z$?$?}/}/(S;)%SSh"]"2KZ$B$C}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$?}/$?$@@}/Z 8Z$B$HC}/ Z$B$B}/Z$B$B}/}/Q YqqZ$D$D}/kZ$?$?}/~ "lZ$@$@}/{Z$?$?}/}/qqZ$D$D}/kZ$?$?}/~ "lZ$@$@}/{Z$?$?}/}/HF Z$?$?}/$A0 S"Z"$Z$@?$?}/PZ$@$@}/}/(S;)%SSMY=$*}/$>*}/$+?*}/$?*}/"]"'Z 8Z$=$=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$@}/$?$@}/Z 8Z$A$HB}/ Z$B$B}/Z$B$B}/}/$ A0S"Z"$Z$?$?}/}/Di(S;SM[:mNZ 8Z$?$?}/ Z$?$?}/Z$?$?}/}/B"Z$?$@}/C$?"]"tZ 8Z$$}/ Z$$}/Z$$?}/}/'Z 8Z$?$?}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$HB}/ Z$B$B}/Z$B$B}/}/$C0S"Z"$Z$@$@}/PZ$@$@}/QZ 8Z$z$zE}/ Z$z$zE}/Z$z$zE}/}/`"Z 8Z$fff?$fff?}/ Z$fff?$fff?}/Z$$}/}/}/(S;)%SSMY.$*}/$?*}/$?*}/"]"'Z 8Z$ #<$=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$?}/$?$@@}/Z 8Z$B$B}/ Z$B$B}/Z$B$B}/}/$C0 S"Z"$Z$?$@}/PZ$ff@$ff@}/}/(S;)%SSh6:B2KZ$B$C}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$?}/$?$@}/Z 8Z$HB$C}/ Z$B$B}/Z$B$B}/}/Q YqqZ$D$D}/kZ$?$?}/~ "lZ$@$@}/{Z$?$?}/}/qqZ$D$D}/kZ$?$@}/~ "lZ$@$@}/{Z$?$?}/}/HF Z$?$?}/$A0S"Z"$Z$?$?}/}/(S;)%SS[:uY.$*l}/$?*O}/$?*@}/J"$A4$? ",Y+$$?}/$?$?}/$?$?}/P"$AZ 8Z$C$C}/ Z$B$B}/Z$B$B}/}/$ F$Z$@$@}/w#"}/(S%SSY.$*@}/$?*@}/$?*}/ "'Z 8Z$=$=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$@$HB}/ Z$B$B}/Z$B$B}/}/$CZ$>$?}/QZ 8Z$B$C}/ Z$$C}/Z$$C}/}/}/(S%SSY.$*@}/$?*@}/$?*}/ "'Z 8Z$ #<$=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$A$HB}/ Z$B$B}/Z$B$B}/}/$AZ$+?$+?}/}/(S\%SSY.$*@}/$?*@}/$?*}/ 'Z 8Z$=$=}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$@$HB}/ Z$B$B}/Z$B$B}/}/$CZ$>$?}/QZ 8Z$B$C}/ Z$$C}/Z$$C}/}/}/(S;)%SSMY=$*}/$>*H}/$+?*H}/$?*}/"'Z 8Z$?$?}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y+$$@?}/$L>$?}/$?$?}/Z 8Z$C$C}/ Z$B$B}/Z$B$B}/}/$D$Z$?$?}/}/(S;S[:;2KZ$@B$B}/Z 8Z$$}/ Z$B$B}/Z$B$B}/}/$D$Z$@@$+?}/PZ$>$>}/XZ$H$H}/W}/(S;)%Sd SMYL$*}/$L>*-}/$>*(g}/$333?*(((}/$?*}/"]"'Z 8Z$$o:}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/,Y+$$?}/$>$ @}/$?$@}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$CS"Z"$Z$?$?}/PZ$>$>}/_!Z 8Z$o:$o:}/ Z$o:$o:}/Z$o:$o:}/}/}/(S;Sh"2KZ$@B$B}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$B$HC}/ Z$B$B}/Z$B$B}/}/H$A0S"Z"$Z$?$?}/PZ$ ?$ ?}/}/(S;)%SSh"Z 8Z$$?}/ Z$$}/Z$$}/}/,Y$$+?}/$?$@}/Z 8Z$C$C}/ Z$B$B}/Z$B$B}/}/$DS"Z"$Z$?$?}/}/(S;SM[:;NZ 8Z$?$?}/ Z$?$?}/Z$?$?}/}/Y=$*}/$>*}/$L?*}/$?*}/C$@?"<2KZ$B$B}/'Z 8Z$?$?}/ Z$$}/Z$$}/}/Z 8Z$$@}/ Z$$}/Z$$}/}/Z 8Z$@@$A}/ Z$B$B}/Z$B$B}/}/$C0S"Z"$Z$?$ @}/PZ$=$=}/XZ$H$}/W}/SY=$*}/$>*@}/$(?*@}/$?*}/4$(? "6:A^:'Z 8Z$ #<$<}/ Z$$}/Z$$}/}/Z 8Z$$?}/ Z$$}/Z$$}/}/Z 8Z$ A$A}/ Z$B$B}/Z$B$B}/}/$?$Z$@$@}/}/}/ACC/C`CLDe87?7?78787?7X7X7_7_7X7X7X7_7X7_77_7_7?7777778787?7?7?7X7_77G8'78؈7' @8  8 <{JW<08/<8 7( <(=?;:78CE28697143//}zwtqnkheb/0.-(+&\'X%*^ZUT~|}{zy#"_$R!)*P#$MKIGECA  :<852/,)>?&#    @? xMFZ^`llka`Uks_bs^lsl_NV^V`^VE`EU`ENUN^UO\nnuN\MuqEVqOnqnEidOd\OdM\gMdgiMiOMOZYMZOMOFOYFLGFZFGGDZYZDDLYFYLDdiGdDGLdLgdLDgDign\unNEuMquVNuqVMOql`kla_kUskbaksbU^sabjeaj_aeR_eb_RjbRBIX]PoQoeS]QRrjProorRTJP]TPAT]SA]JASPJS[KmtmJI[tApTKpmmpAchK[cKIc[IfchfIKhIXKWXIKKIBWKBCHBBXC@CXXW@H@WWBHc@hcC@HCcfHc@Hfh@f[mtJmAItpTtJptTKIp]oQeoRSQrjQerQjPSrJKJIHGIIHHH@?=@AEF<F;:A>@9<<8;>=>:7><695943:29:B1:9CDD0B/DBD678548362635053.2210-3,3+0*057875~}|{zyxwvutsrqponmlkjihgfedcba`_./.')-,]+&*')'*%^,[,Z#$&*&$$W*%*(Y\%V%XTSR~}}~}{|{}y{z|z{yzwxwzvwxw!v""v),-U-,Q)P ( '&%$ONM#"! LKJIHGFEDCBA@   =? ;  >     98  :76543210/.-,+*)('&<%$#"!       ???   ???>>>  >>>L @DBA@FEDPAEBBFFCGSNU__CGRHL@DRbaKOPIMS_[\yv=)VY]*.= > ?;>@  "#$OQ&!UW^#&%)]'.263678:19AL =$>>>>$>=$>=$>>$>=>=$>>> >$> =$> =$> >> >$>=$>=$>>$>=>=$>>>>$>=$>f?t>f?t>]?t>f?t>]?t>/?>5?>5?>;?>A?|> A?,>!A?|>"A?,>#A?|>$;?=%;?=&;?=';?=(;?@<)5?@<*f?t>+f?t>,]?t>-f?t>.]?t>//?>05?>15?>2;?>3A?|>4A?,>5A?|>6A?,>7A?|>8;?=9;?=:;?=;;?=<;?@<=5?@<>>=?>=@>?A=>B>>C>)?Dd??E>F^?>Ga?)?H>>I?>J=?K??Ld?>M?>N?O??PX>?Q?)?R>SX>>T=)?U>>V)?W>?X>)?Y^??ZW?)?[?)?\?)?]X>)?^>?_>>`>)?a>?b>)?c>)?di?)?e?f>>gi?>h>?ii??j)?kh?)?li??mi??n??o??pi?>q?>r?>si?>ti?)?u?)?v?>w?>x?d>y>>z>d>{>>|>d>}>d>~>>>d>>;>;>=>;>=?;?>?>?d>>>>d>>>>d>>d>>>>d>>;>;>=>;>=?;>=>;>=>;>;@=;=;@==>d>>>>>>>>d>>d>?d>>>>d>>>?d>?>>=>;>;>;>=>=@=;==?d>>>?d>>>>=?=>>>|>>> ?> ?d>>=>;>=>;>;@=;=;@==?=>;?;>;?=>=>=>;>;>;>=>=@=;==>=?=>|>>>>|>>;>=>=>=>;>;;@===@==;@=;=;=;>;=$>>$>=$>>;>=>=>=>;>;;@===@==;@=;=;=;>;=$>>$>=$>>|>?>>>?>>|>?|>>=>;>;>;>=>=>= >; >; >; >= >=3?=?;3?;?;3?=?=>>>|>>>>|>>>>|>>|>>>>|>>>>|>>> ?|>!>>"?>#>>$?|>%>|>&>>'>d>(>>)>d>*>>+>d>,>>->d>.>>/>d>0>>1>d>2>d>3>>4>d>5>>6>d>7>>8x?|>9~?,>:x?|>;~?,><x?@<=~?=>J?|>?~?,>@x?@B/?>C/?,>D/?>E/?>F5?>G;?>H5?>I5?>J;?>K;?>LA?|>MA?|>NA?,>O;?=P;?@d>S>>T>d>Ux?@Wf?t>Xx?|>Yf?t>Z~?,>[~?=\x?|>]~?=^~?,>_>|>`?>a>>b?>c>|>d?|>e?=f>;g?;h>;i?=j>=k>=l>;m>;n>;o>=p>=q>=r>;s>;t>;u>=v>=w3?=x?;y3?;z?;{3?=|?=}>>~>|>>>>|>>>>|>?|>>>?>>>?|>>|>>>>d>>>>d>>>>d>>>>d>>>>d>>>>d>>d>>>>>>>>d>>d>>d>>>>d>>>>d>>>?d>>>>d>>>?d>?>x?|>~?,>x?|>~?,>x?@<~?=J?|>~?,>x?@</?,>/?>/?,>/?>/?>5?>;?>5?>5?>;?>;?>A?|>A?|>A?,>;?=;?@<;?=>d>>>>d>x?@<x?=J?@<J?=D?=J?,>~?,>f?t>x?|>f?t>]?t>f?t>~?,>~?=x?|>~?,>x?@<~?==$>=>`=>>>>>`=$>>$>===$>>=>$>=$>`=>>>>>`=$>>$>>$>=====;>=>;>==;>;=$>=>`=>>>>>`=$>>$>===$>>=>$>=$>`=>>>>>`=$>>$>>$>=====;>=>;>==; >; x?,> ]?t> D?,> J?,>~?=x?=D?=J?@<J?=;?|>;?|>A?,>;?,>A?,>;?,>;?@<5?=5?=5?|>;?>5?|>;?= 5?@" ?d>#J?|>$]?t>%x?,>&D?,>'D?=(f?t>)J?=*J?,>+x?@<,x?=-J?@<.>;/>=0x?,>1]?t>2D?,>3J?,>4~?=5x?=6D?=7J?@<8J?=9;?|>:;?|>;A?,><;?,>=A?,>>;?,>?;?@<@5?=A5?=B5?|>C;?>D5?|>E;?=F5?@Hx?,>ID?,>J>;K>=`'@? >o ADe                                                              X*55xZ:q2 sw}U:= m|u6d#u1u] 6# z#1"d=/%(m1up*(9b1*\g? \h? J $ $39v-]<9> ?9?`$o$EwvwqV?)K=w ˇ8x7  @ {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55xx`EwvwyV?+=K"g%W"{! 4 |&!  !!{{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55x2>q2 swΥ>= m|u6 @"U'u] 6 ".Z+'C<~)},*u0*}p#*؉?*\g? \h? J ##8KL:8ہI?ؑ9?`$o$ iEwvwV? x {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55x}z:q2 swu:= m|u6l$vx1u] 6$y#w1d= n$3 2qP*3A2_*\g? \h? J P$ _$8Bޅ85~9?}Y?`$o$`Ewvwf?)[="w"Wti8&Lxt% {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55x2>q2 swΥ>= m|u6 @"U'u] 6 ".Z+'c x {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55x 7q2 sw7= m|u6x&:o?Ә8u] 6 %T[?/8r 44= %i2 vp*ޕ2*\g? \h? J $_$#9r a,9\>I?`$o$6EwvwV?42=˩7) /5 'Xh(L" @H 7p 5o {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                                                                               X*55xZ:q2 sw}U:= m|u6d#u1u] 6# z#1"d=/%0up*U0*\g? \h? J $ $#9v-],9D>I?`$o$EwvwqV?)K=G 78x7  {{tt0,0,0,x(0(i6 Ptt{{bbb?,b?,b?,xGG(0(6i6i6i6i6i6666m m m m m m Z6Z6Z6Z6Z6Z6ih ih ih ih ih ih 6-Yc60,b?,~6'''B'B'66666i6i6i6666666h h h h h h i6Ҧl6i6'''            ???               ???         ??????            ????????????                                                   eV6eV6eV6(3(3(3      ??????      ????????????            b.3b.3b.3b.3b.3b.3                               !                               hh6                      6hh                                                                 L ACCACCACCACCACCACCACCACCACCACCACC /C`C/C`C/C`C/C`C/C`C/C`C/C`C/C`C/C`C/C`C/C`C}/@BB?FB$Bw!0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}X ` _  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@~ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}XA ` g  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@~ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}PA ` g  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}P X W  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}` ` WA ~ 0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}` ` g  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@~ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}XA h o  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}` ` g  0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}` ` WA ~ 0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}` ` _A ~ 0000(((B(B B0B0B8B88}ȽȽ_@X@X@н}}}}}}'/B'700(0====}н}}_( }7/7==}=}}}/(===/(ؽ߽}= (B   B(B'B BX  '70н׽'  70//н׽ؽX((߽'B/'(@ /(@@(/B' =}(B B B8B88(B((/B(B=}}}==}X ` _  ???~@?W???xwwxv@Wv==<;;m<mjNhz{zkjkllz{zQNhQPhPh0I\]IL77MH4M\./H266238I5nJG5H]JH232/8I441KL.0Gn4+ED*UEu*Dt,F[ZtZT+[u&B}~|A%SB~s%Ar'}|CYXrXR&YsqV!pqbfe"de f"d_ _  g^bc^ed`e dVo! aa`cpgK1o ~5ci!H!GbcHefi!!ea_a_X_a_a\\__4__54_5P55P3P4334453P3P\3\3\aX_Xc!HG!ebHfHGHfib]bX]biX]Xcb]cic]]ifefdeGeddGfGh[I2[gI01h0^``W^78^8`^8`68677^^ ^^^ YZZZ Y  Y87Z8ZY8Y68Y676`W^W[I20IgI12I1ghgWhgWWg[[[hh110d002dd221SUSSUUTOOTwOOO,.,@,.,@(=(7(=(77$$&&$//4-4/4-A>F>4AC*CA>FC*9FC9#V##VuBEB#%%%#%33EBE3KIIvtvvtt"""MDB@BD|MBMD@@ONFEONOEEFN{{EE1CyCAyyAA0u~1C1~sA0AsxOFO/FF//qqw222xOxJ=;9;=mJp;pJ=99LK?>LKL>>?Kll>>-<j<:jj::,fo-<-od:,:diL?L+??++bbh...iLiY)T))]TQT]]jQmQjjmqm&(a*[&^a*a^yk^k!!~&a([(ar     ""  " QV|Q Q|VRR|    s| |sRoso} pp {{z$__'ZZxxx  P 'PP'%`%B')+567:(*34;<?DEFGUWXefgtuvJMHJMNLOcdcdrsrs0dns}UkizxRSV PQ \PQY[jiyx36po~!ml|{^IH0GG!]^lno!"!"    pqrs678././,-gdbB>>;?|>>d>;?|>>>;?,>>d>>d>>=?|>;?=;?,>D?=>>5?=>d>5?=>d>5?|>>>5?|>?d>?>/?,>/?> ?> 5?> ?d> 5?> >> ;?> >> A?|> >d> A?|>>>5?=>d>5?=>d>?>?d>5?>;?,>>>A?|>>d>A?|>>>>(?>}?>>;?|>>d>?d>?>/?,>/?>;?,>>d>>d>?d>5?>;?,>>>;?>>>5?|>>d>>d>5?|>;?,>>d>>>>>?>?=5?@<;?,>J?,>>;D?=>|>>|>>=3?;~?=>|>>>?;3?=x?@< >> >; ~?,>!>|>!>>!x?=";"=="`=>#>>#>>#>=#>;$>;$>=$>$>%>>%>;%>=&>>&>=';'=='`=>(>>(>>(>=(>;)>;)>=)>$>*>>*>;*>=+>>+>=,>|>,?>,?;,J?=->>->;-3?;-x?=-~?,>.?=.3?;.x?@|>0?|>0?;0J?=1>d>1;?|>2>d>2;?,>3>d>3>>3>>3>;3?|>35?@<3;?,>3J?,>4>d>4>>4>;45?@<4;?,>4D?,>5>d>5>;55?@<5;?=5D?,>6?=6J?@<7?;7J?@<8?>9=}?:?>;M?(?<=(?=$?>>?}??1?(?@`=$>@=;@==A=;A=>B==B=>C`=$>C=;C==D=;D=>E==E=>F>d>F>;F>=F5?@G>>G>=G5?@H>|>H>=H~?,>I>>I>|>Ix?,>J>|>J>|>Jx?=K>|>K>>Kx?=L>>Lx?,>M>N+?>O>}?P>(?Q=Q`=>R>>R>=S=S`=>T>>T>=U?=U3?;Ux?@X>$>X>=Y@==Y`=$>Z>$>Z>=[>;[x?|>\>=\x?|>]>|>]>|>]x?=^>d>^>;^>=^?|>^5?@<^;?=^D?=_>=_D?,>_J?|>`>;`J?|>a>d>a>;a5?@b>;bD?,>c>>c>>c>=c?>c5?@d>>d>|>dx?,>e>|>e?|>eJ?=f?;fJ?@jT?(?kM?}?l?}?m>;mD?=n>|>n?>nJ?=o?=oJ?@;p~?=q@=;q`=$>r>$>r>;s@=;s`=$>t>$>t>;u$?}?v*?}?w*?>xA?>yA?}?zA?(?{=={=$>|>=|>$>}=;}=$>~=====$>>=>$>=;=$>==L?}??(?(?>;>$>>=>;>$>>='?(?>=~?,>>;~?=>=~?=>>=>G?>J?(?>(??>M?}?+?}??}?+?(??(?>>>(??}?L?>L?(?>>>}?>}?>;x?|>>>>=5?@<x?|>>>>=5?@<f?t>>;J?|>>=J?|>>=J?|>>>?|>J?,>?> ?>/?,>?d> ?d>/?,>?d>/?>>d>;?>>d>A?,>>>A?,>>d>>=;?@<;?=]?t>>d>;?=>>;?=>>x?,>>>>;;?@<f?t>>d>>;5?@<;?=]?t>?> ?>/?,>?d> ?d>/?,>?d>/?>>d>;?>>d>A?,>>>A?,>>d>>=;?@<;?=]?t>>d>;?=>>;?=>=D?=>>>;;?@<f?t>|?}?|?(?|?>?>?(?M?>$,?? >o Aw!                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/Z+ #.q0,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!զ+M, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&  ;u> 31o' ̒C7nL7!^1!RQ1Mq0%:0=D=0vqW4R(}1m rq0%      i   =       $7  x c' N0DG??H                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/* `Ra0 ,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!n* N, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&`%` ;u> @1o޻̒C7nL7!^1!RQ1502>0=uu0ObƥqW4R(}1m rq0%      i   =       $7  x c'FNN0!??!                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/!* rA0 ,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!!* N, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&AUA ;u> R0o̒C7nL7!^1!RQ150B>q0=uu02VqW4R(}1m rq0%      i   =       $7  x c'Wp.0#??x#                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/^+ *q0P-Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!Ӣ+A_- o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&P_ ;u> 40oh̒C7nL7!^1!RQ1E/&.a0=35n/jnqW4R(}1m rq0%      i   =       $7  x c'O>0Զ??(                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/1, 5/׽-Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!>,A- o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&A ;u> N1o!̒C7nL7!^1!RQ1>Q/:0=}.ξZqW4R(}1m rq0%      i   =       $7  x c' Ɏ/)e??)lj                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/1, .0 ,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!>, N, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-& ;u> N1o7̒C7nL7!^1!RQ150:0=uu01qW4R(}1m rq0%      i   =       $7  x c'v N0 ?? T                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/") nA0 `,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!") Zo, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&AMQA^ ;u> R.1o[̒C7nL7!^1!RQ1E1BJ0=ve11fQqW4R(}1m rq0%      i   =       $7  x c'q.0!??" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/1, .0 ,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!>, N, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-& ;u> N1o7̒C7nL7!^1!RQ150:0=uu01qW4R(}1m rq0%      i   =       $7  x c'v N0 ?? T                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/1, 5/׽-Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!>,A- o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&A ;u> N1o!̒C7nL7!^1!RQ1>Q/:0=}.ξZqW4R(}1m rq0%      i   =       $7  x c' Ɏ/)e??)lj                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/1, )10,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!>,I, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&9 ;u> N1oC"̒C7nL7!^1!RQ1qq/:0=M/A9^qW4R(}1m rq0%      i   =       $7  x c'Ch/F??pI                   =Dª=      R=i[O ,9d\%>" i 2 i[ X O)2& i[ ʆi[ Ҧl6iZ#9{l'  Ҟ. ϴ3M6/Z+ #.q0,Z6Yʽ J,9o i iZ#96 X h'NZM lI_E u>0/!զ+M, o & 6 -Yc6ɰ-mX&,++& +,Q|GZ I0vLv9'RHk60"DX*5q!8=lS%^22,-Q׍%f[#-(%c=Rr6 7qX*5g~5} .1$f[#-&  ;u> 31o' ̒C7nL7!^1!RQ1Mq0%:0=D=0vqW4R(}1m rq0%      i   =       $7  x c' N0DG??H @BB@BB@BB@BB@BB@BB@BB@BB@BB@BB@BB ?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B?FB$B}/@BB?xBZL CV!CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/>?'CCW 0C C ( (//|(| <((|/<CC(|/| (| / |0|0| (7|0|7CC ? @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx@  C؃/|/7|0|7|C(Ѓ>808>(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/~?'CC?C  C ( (//|(| <((|/<CC(|/|| ( / |0|0| (7|0|7CC ?A @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx0 < C؃/|/7|0|7|C(Ѓ>808>(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/Ǿ?'CC  C ( (//|(| <((|/<CC(|/| ( / |0|0| (7|0|7CC G @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx  C؃/|/7|0|7|C(Ѓ>808A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/~?'CC  C ( (//|(| <((|/<CC(|/| ( / |0|0| (7|0|7CC GA @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx  C؃/|/7|0|7|C(Ѓ~@A0@(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/>?'CC' ( C ( (//|(| <((|/<CC(|/| (< / |0|0| (7|0|7CC ? @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx( < C؃/|/7|0|7|C(Ѓ@0@A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/~?'CC' ( C ( (//|(| <((|/<CC(|/| (< / |0|0| (7|0|7CC GA @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx0 < C؃/|/7|0|7|C(Ѓ~@A0@A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/Ǿ?'CC/ ( C ( (//|(| <((|/<CC(|/| ( / |0|0| (7|0|7CC G @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx8C < C؃/|/7|0|7|C(Ѓ>80@A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/~?'CC7 8C C ( (//|(| <((|/<CC(|/|< (| / |0|0| (7|0|7CC GA @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx@ | C؃/|/7|0|7|C(Ѓ~@A0@A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/>?'CC?C H C ( (//|(| <((|/<CC(|/|| ( / |0|0| (7|0|7CC ? @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx@  C؃/|/7|0|7|C(Ѓ@0@A~(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/~?'CC 0 C ( (//|(| <((|/<CC(|/| (< / |0|0| (7|0|7CC GA @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx( < C؃/|/7|0|7|C(Ѓ@0@(/(/CC/<'<(0|0|0< < < // <CC؃؃CCCCCC | | (<(<0<(<(< <||(<((/|Ѓ ''/'׃C0|7|/>?'CCC  C ( (//|(| <((|/<CC(|/|} ( / |0|0| (7|0|7CC ? @CC(<?(CC |'|CCC߃ |'|(|(0X_X=Cxx  C؃/|/7|0|7|C(Ѓ>808>(/(/CC/<'<(0|0|0< < < // <???x;ZY^]]\\[\\^[YZ::i;gnng>~i~~@AB??B??fe>BBfeA@hh~c|ocOPaMNoMPPOa "!!d|4NQRPRQ "!!bbmMM5maa5d10``k0k_/ 6  #2lj7$7 //l2_#1j6$4/-GyzxF,{LGzs,Fr.yxHVUr{UK-Vs(DuvtC'wJDvq'Cp)utETSpwSI(Tqx3!"C" C>>!>*'!'"!'&"& "&* *! 2@+*@+&'2&E2@2@DDEE223432224334344EDDED@+*&++'*+'2"CC >CC> !>BB???(%%%$$$((#=()=)%$#$G#AA#=A=FAFGG#####GAAAAFFFG)=$())(%)%#BB?BB??NN;N;;^^^^^^HJHFHJHFBDB?BDB??^^RRTT9R7799K4K972I2K42IG4E;E42G=C=GE;=CA;=A}PP}`}P<<<:<QSS8S5Q5S85313531:<:1\\~_~~Y_|_YY||7977.99..IyIVIy68&-66-080Os&-&ss{--{{0tvoxovmvktkvmkkiiiiggbegew zWz uRqRuu  wwnullnnjj  hh fc`:[b[:[TbMbTX[T[XKXKad d UPU     ``Z+ZY((__pNQLQNN"LaL""5aa55_]/}//101010|| zzz v  t ty11rrx   y1y, n,qq,  .-.-.-mmk kk  gppe  ej..ccij.jd567STU&&fghuvw*--/0["&dedeststeot~WLOPMPWZ^lj{yab#&*-kjzyqp!!nm}|"&.0NP'),- !$%&HJK+-efPRSTqorUVWXVX\]^>?@JKJKHId>>;?|>>d>;?|>>>;?,>>d>;?,>>>5?=>d>5?=>d>5?|>>>5?|>?d>?>/?,>/?> ?> 5?> ?d> 5?> >> ;?> >> A?|> >d> A?|>>>x?,>>d>>;>=?>5?@<;?=D?,>>>>>>=?|>?>5?@<J?,>>;3?=~?,>>>;?|>>d>;?|>>>5?=;?,>>d>;?,>>d>5?|>>>5?|>?d>?>/?,>/?>?>5?>?d>5?>>>;?>>>A?|>>d>A?|>>>>>>=5?@<~?,>>>5?= >d> 5?= ;?=!>d>!>>!>;!>=!?|>!?>!5?@"?;"J?@<#>;#D?,>$;$==$`=>%>>%>>%>=%>;&>;&>=&>$>'>>'>;'>=(>>(>=);)==)`=>*>>*>>*>=*>;+>;+>=+>$>,>>,>;,>=->>->=.>>.>|>.>=.x?,>.x?|>/?;/3?=/x?@<0?=03?;0x?@<1>|>1>|>1x?=2>|>2>|>2>;2x?=3>|>3?|>3J?=4>|>4?>4?=4J?=5?=5J?@<6>=6x?|>6~?,>7?>8}?9,>>:'?;=><=}?= >'?>}??p?>@p?}?A=>B`=$>B=;B==C=;C=>D==D=>E`=$>E=;E==F=;F=>G==G=>H=H`=>I>>I>=J=J`=>K>>K>=L>>L?>LJ?,>M>;M3?;M~?=M~?,>N>;Nx?|>O>>O>=O5?@P>>Px?,>Q>>Q?|>QJ?,>R@==R`=$>S>$>S>=T@==T`=$>U>$>U>=V?>W>}?X?}?Y>>Z>'?[$>}?\=}?]='?^>|>^>>^x?=_>;_x?|>`?;`3?=`x?@;aD?=b>=b3?;b~?=c?;cJ?@}?g?>h,>'?i>;iD?=j>|>j?>jJ?=k>|>k?|>kJ?=l>>l>|>lx?,>m>n>;n~?=o@=;o`=$>p>$>p>;q@=;q`=$>r>$>r>;s==s=$>t>=t>$>u=;u=$>v==w==w=$>x>=x>$>y=;y=$>z=={?={3?;{x?@<|,>}?},>>~,>'?$>}?$>>$>'?>}?'?}?'?>o?'?>?'?>;>$>>=>;>$>>==>@>'?$>>>=D?=>;~?=>=~?=>=x?|>'??}??}?='?='??'??'?=}?=>=}?=>>>>=5?@<x?|>>;J?|>>=J?|>>d>>;5?@<;?=]?t>>>>=5?@<f?t>>>?|>J?,>>|>>>x?=>;J?|>?> ?>/?,>?d> ?d>/?,>?d>/?>>d>;?>>d>A?,>>>A?,>>d>>=;?@<;?=]?t>>d>;?=>>;?=>>>;;?@<f?t>>;D?,>>=J?|>>d>>;5?@<;?=]?t>?> ?>/?,>?d> ?d>/?,>?d>/?>>d>;?>>d>A?,>>>A?,>>d>>=;?@<;?=]?t>>d>;?=>>;?=?=J?@<>=D?=>>>;;?@<f?t>ZL?? >o AV!              .^%l            hZ   q'g2o i 2 i[ X O)2& i[ źP$>!oBC A/A.<0 | id B?1 O9qO&(\5؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, ͟d !oBC A/A.<0" oiB?1 O9q;(*"3"؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, K$.t?1 ~ _UUV=gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-q?+m8q +Pb8DH'%l:&$N1!d($NA1j.E^A/qX*5g~5 !16z\)W!oBC A/A.<09TXA^'}7Z?1 O9qc+ %ۃ6؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, 38D9?1 ~ _ji=gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-g&SP'68&S'8 w&Q:~0ƭ:*q0JV֞/V*/qX*5g~5t16z\)W!oBC A/A.<0 wv.:7z&?1 O9qw0 | +Y؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, (I?1 ~ _޸9gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-t&{= 8o{& t8Tg*'0k'50Rx /R /qX*5g~5 dy!16z\)W!oBC A/A.<04Wr*nV?1 O9qV0\6!؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM,  ɕ?1 ~ _ɼ8gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-~A,] -=8ۂN,ER 28-@,7%>1%I11'~/'q/qX*5g~5i$16z\)W!oBC A/A.<0 PGz9^,lf6?1 O9q̧,$e ؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, x9?1 ~ _:gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-|k*{2=8|*C B8-@,7%n1%I11"~/'q/qX*5g~5i$16z\)W!oBC A/A.<09TXA^Ր7Z?1 O9q'Se؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, 3t9?1 ~ _ji=gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-ʯ$SP:8&S'8Hw)U',1K)F1%$/' /qX*5g~50 16z\)W!oBC A/A.<0 PGz9^,lf6?1 O9qۧf*2E6!؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, x9?1 ~ _:gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-|k*{2=8|*C B8;W.">2W"a1$/aa/qX*5g~5#'16z\)W// 7F/*/.]<<M !qWQ'4Re'1        Fo  }N }Noj      /1)  |%36l '{               .^%l            hZ   q'g2o i 2 i[ X O)2& i[ źP$>!oBC A/A.<04Wr*nV?1 O9q2l 8_7؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM,  ɕ?1 ~ _ɼ8gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-~A,] -=8ۂN,ER 28h 2c!فn2!}a2PW/X-/qX*5g~5fTj016z\)W!oBC A/A.<04Wj.:~F?1 O9qw3*س$؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, CeI?1 ~ _޸9gE.,-Q׍%f[#-(%J/we]P-Yc6E I_Ҧl6n-*xL = 8s*C 8kg3?&حN1÷&QA1$Vq.$$YqE.qX*5g~5^h116z\)W!oBC A/A.<0 | id B?1 O9qCv1'0$[:؝b7,9o i iZ#96 X  o & 6 :9% !]F4R<~KM, ͟d W9@6;6999XXJ8=J06;676;670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=J 55OD6{670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=JD5{5_6670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=J06;676;670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=JX66D5{570078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9P6;6999XXJ8=J@6;6G6;670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9`6;6999XXJ8=J0D5{56670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9P6;6999XXJ8=J@6;6G6;670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=JX66D5{570078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=JHD6{6'5570078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:07770999999:::::?:::99999999999::99: :: !!IE!@:!G:!GI0z!: :   QQ'V QQQVQI@IX V(WV>W9@6;6999XXJ8=J06;676;670078:::999999999:9:9:9:9999:9:::999:?:9:::999:::::0:7:::::7009:::999:::99999::::999::9:::999:::999:::999:::99:999:::999::9:::99999999:9:9:9::::::7::::7:0:::::::::::::::0:8:7:?:8::9::9999999999999999999997099999999999:::::::99:9:9::::9999999:::9:9:999999999999:???J__vh]^naOQOavhdi^dQmx\PxP\]mzzshshtiSnRaRa[[ufYZb`JLJ`ufcgZcLlwXKwKXYlyysfsftgUbT`T`DEUTBETWTTDBDCWCDrkkpprFGSR>GRVRRF>F?V?FqjjooqTUSRMPKLJOIBH8C9>@<;23DF-:9}zw5486730ts.;-*+)(&$#%!$qonkheUbV^[\X`ZPO~}TSMK  HFDB@>   <5730-*'$!9:  : JOu\\^]uc^[gh[O\[\gNmMm`PLNMMmPP`L`NL\u^\]g^c[^h]^[hcO[MPllyMlwcwlPLMyOcwPLwywLculyluuOywyOrshhgrdrgg]dsd]]hsFRmmNFRQ``mRQFNN`QtJXZXYbtZeWfJWXXWeaHG_aKHIGaGK_KIH_ItXZYXebZWfZYWZfJbWKGkxkGvkbkvKGIxbJvIKvvxItbkkxtJtxxvJsrfefrrdeYeddsYfYsTDHHaTSTaa_SDS__HDCSVjqDTjDSjTSojqoSDqSVDBVSDDSCBDCA@CCVA?AVVB?@?BBC@j?qjA?@Ajo@j?@oq?oQEUpiFiRFiQRnQinpQpFQFU>QUFQFEF>E<;EUE;;=U>U==<>E><=ip;i=;<i<ni<=n=pnSTSLNRQPKOLNLOJQQHIKOKIIOJOMJJNQRRQA@8ABFG7G65B?A4==3<?>?;2?=1:0:/.;-:;C,;:DEE+C*ECE998988~}|{zyxwvut423132745354261016/:.s:r:q)-('/,/+-*&%)*($'$&'%'#"#%"!(!(  # po::nmlkjihgfedcb:TSRQa`UTSTU_Q]Q\ZUZZ[UUWY^VXONM}~~}~{|{~z{|{zzSQRPRQLK JIH     GFE D  CBA@?>=<  ; 8:69  43 5210/.-,+*)('&%$#"! 7        999  999U =?B?>=GMFFDD>BJXO\HNHW[YY]];AJON<@=?ddZ^bcJO}z 8VY8 969;JL _T#$$%):21235,:BHKJNLU =$>>>>$>=$>=$>>$>=>=$>>> >$> =$> f?t> f?t> ]?t>f?t>]?t>/?>5?>5?>;?>A?|>A?,>A?|>A?,>A?|>;?=;?=;?=;?=;?@<5?@<=$> >>!>$>"=$>#=$>$>$>%=>&=$>'>>(>$>)=$>*/?>+5?>,5?>-;?>.A?|>/A?,>0A?|>1A?,>2A?|>3;?=4;?=5;?=6;?=7;?@<85?@<9>=:>=;>-?<>}?=>>>>>??>@?}?A?-?B!?>C!?}?D>>E>}?F>>G>>H\>>I>?J>>K>-?La?}?Ma?>N*?>OZ?>Pa?-?Q>}?R>-?S>}?T>-?Ud>-?V(?-?W\>}?X\>>Y>Z\>-?[%?}?\%?>]>>^%?-?_\>}?`*?}?a\>-?b>}?cZ?}?d\>>e}?f-?g>}?h>-?i>-?j?-?kt?-?l>-?m*?-?n>}?o?}?p>>q?>r\>}?s\>-?t>-?uY?-?vt?}?w>}?xt?>y>>z?>{?>|?d>}>>~>d>>>>d>>d>>>>d>>;>;>=>;>=?;?>?>?d>>>>d>>>>d>>d>>>>d>>;>;>=>;>=?;>=>;>=>;>;@=;=;@==?=>;?;>;?=>=>=>;>;>;>=>=>=>;>=>;>;@=;=;@==>=>;>;>;>=>=@=;==?d>>>>=?=@=;==?d>>>>=?=>|>>>>|>>>>|>>> ?> ?d>x?@<J?@<x?= ?> ?d>~?,>~?=~?,>x?,>>;>=>=>=>;>;;@===@==;@=;=;=;>;=$>>$>=$>>|>?>>>?>>|>?|>>=>;>;>;>=>=>=>;>;>;>=>=3?=?;3?;?;3?=?=>>>|>>>>|>>>>|> >|> >> >|> >> >|>>>?|>>>?>>>?|>>|>>>>d>>>>d>>>>d>>>>d>>>>d>>> >d>!>d>">>#>>$>>%>d>&>d>'>d>(>>)>d>*>>+>d>,>>-?d>.>>/>d>0>>1?d>2?>3x?|>4~?,>5x?|>6~?,>7x?@<8~?=9J?|>:~?,>;x?@<</?,>=/?>>/?,>?/?>@/?>A5?>B;?>C5?>D5?>E;?>F;?>GA?|>HA?|>IA?,>J;?=K;?@d>N>>O>d>Px?@V~?,>Wf?t>Xx?|>Yf?t>Z]?t>[f?t>\~?,>]~?=^x?|>_~?,>`x?@;c>=d>=e>=f>;g>;h;i@==j=k@==l;m@=;n=;o=;p>;q=$>r>$>s=$>t>|>u?>v>>w?>x>|>y?|>z?={>;|?;}>;~?=>=>=>;>;>;>=>=>=>;>;>;>=>=3?=?;3?;?;3?=?=>>>|>>>>|>>>>|>?|>>>?>>>?|>>|>>>>d>>>>d>>>>d>>>>d>>>>d>>>>d>>d>>>>>>>>d>>d>>d>>>>d>>>>d>>>?d>>>>d>>>?d>?>x?|>f?t>x?|>~?,>J?=J?,>f?t>]?t>f?t>]?t>J?|>]?t>~?=x?@</?,>/?>/?,>/?>/?>5?>;?>5?>5?>;?>;?>A?|>A?|>A?,>;?=;?@<;?=>d>>>>d>x?@<~?,>f?t>x?|>f?t>~?,>~?=x?|>~?=~?,>=$>=>`=>>>>>`=$>>$>===$>>=>$>=$>`=>>>>>`=$>>$>>$>=====;>=>;>==;>;x?,>]?t>D?,>J?,>~?=x?=D?= J?@< J?= ;?|> ;?|> A?,>;?,>A?,>;?,>;?@<5?=5?=5?|>;?>5?|>;?=5?@<J?|>x?,>D?,>>;>==$>=> `=>!>>">>#`=$>$>$>%==&=$>'>=(>$>)=$>*`=>+>>,>>-`=$>.>$>/>$>0==1==2=;3>=4>;5>=6=;7>;8D?,>9D?=:;?|>;;?|><A?,>=;?,>>A?,>?;?,>@;?@D;?>E5?|>F;?=G5?@I]?t>Jx?,>KD?,>LD?=Mf?t>NJ?=OJ?,>Px?@;T>=@? >o Agf                                                         X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#A+4 E@Er+EZo+ѹp+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"^0^^0() =) =P$_$N0!A0 P"= = qE??1A1k  D Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#eO+4 Mn+v@++_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"n0~a0() =) =P$_$;/;"/ P"= = qE??.1E!1 ) & Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#u_+4 }0x]Q*f+OP+x^++_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"V00() =) =P$_$s^/s:Q/ P"= = qE?? ^1 JQ1  Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#A+4 EPEr+E^o+ѹp+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"`0`^0() =) =P$_$N0!A0 P"= = qE??1A1g  H Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#8>*4 !+j!y/+O5!1*+. +_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"1A1() =) =P$_$^0mQ0 P"= = qE??0=0((!` ! Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#E*4 EMz?+Eb*ѱ0+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"`0`f0() =) =P$_$N0!A0 P"= = qE??N1IA1w7x@!! Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#*4 qxq*v+}*x++_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"F~0q0() =) =P$_$s^/s:Q/ P"= = qE?? 1 ^1WX $$ Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#E*4 EMz?+Eb*ѱ0+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"`0`f0() =) =P$_$N0!A0 P"= = qE??N1IA1w7x@!! Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#8>*4 !+j!y/+O5!1*+. +_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"1A1() =) =P$_$^0mQ0 P"= = qE??0=0((!` ! Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#]*4 t Ru_+t2?Z*P+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"*1*F1() =) =P$_$n0=a0 P"= = qE??0=0$/$l Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                                                                                       X*55sXzR6@ hW?@gX]6r|X?n- T'5nn" E#A+4 E@Er+EZo+ѹp+_  "/" I ;2`< =6 2Ҝ3 =Y6wcW5g20"o"^0^^0() =) =P$_$N0!A0 P"= = qE??1A1k  D Ptt{{bbb?,b?,b?,xGG(0(6_{{tt0,0,0,x(0(i6i6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih 66666i6i6i6h h h h h h 6-Yc6b?,~6i6Ҧl6*0,i6''''''B'B'O_o''  '!            ???         ??????            ????????????            b.3b.3b.3b.3b.3b.3                              _ !                        ???   Y6Y6Y6g(3g(3g(3      ??????      ????????????            !3!3!3!3!3!3                                                            hh6                                                6hh                              U FAFCCFAFCCFAFCCFAFCCFAFCCFAFCCFAFCCFAFCCFAFCCFAFCCFAFCC ?1CC?1CC?1CC?1CC?1CC?1CC?1CC?1CC?1CC?1CC?1CC}/ABACB COee(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=(///(=====<<<<<<======<= =<< ! /'./>.@0  !>.?=!((=)(( ) .8=!0}!B!<~.<< A. /((/0===<<<<<<<=<=<=<7====7=0=7=<<===<<<===<<<<==<===<<=<=<<<===<<<==<=<=<<=<<=<<<<<<<===<=<=<=<=/((=<<<==<===<<<===<<<===<<<===<<=<<<==<===<<<<<<<<===============0=0=7=7=0==7==<<<<<<<<<<<<<<<<<<<<<<<<<<<=<<<=<<=<<<===/(=========0=7=<<<<<<<<<<<<=<<==<<<<<<<<<<<=======<=<=???~L@PA\@PeiHj@j=eH;=HKHHK<L;K<KbII``b@iAffHWVX\WVYWcXYWEYGcEY5R[]ZRZdgM]MN7d6BB6J454658J65a87__aOghONhU[TZTZSU^TSTGQF^FQMLONKI1H/FDCA)>*<?97456832-0+,*/~}(')%#&$! $$|yvspzyxwjflhcbtsrpqonmm` ^[Y  WUSQOHJFC@=:7LM41.+(%"   0 ~G;K?@O@[O@=[=>[=?>?O><dhhe?dGei=@i<hih=aH<Hd<HGd_GH_aGa<G<KJGK<G<;<J;9:;K;::8KJK889J;J98Ha:H8:9H9_H98_8a_hdeh?=eGie@?ei@G<iWVOO[WUW[[>UVU>>OVbXVVWbCbWWUCXCUUVXFDXXbFBFbbCBDBCCXDA4IM\Q\ZQ\LZLYZLMYMQY3cffNMcANgL\g3fgfL`636c36Ac^A6^`A`3A3I2AI3A34324174I4775I2I551242156`7657161^615^5`^fcNfMLNAgN\MNg\A3gTRQQZTSTZZYSRSYYQR]PRRT]E]TTSEPESSRPFBPP]FDF]]EDBDEEPBLKKNLMKMLJ0I00.H-,JGJFHE+*DEC)B?AB@B('>@=<C&C%:;9>$;000688343354745,.210+/,.,/*11()+/+))/*/-**}~~}~{|{~z{|{&z''z.1221#$%"!% ## "" #" !  "$%$"~}|{zyxwvutsrqponmywxwwuxvxuutvvttklihegjdfsba`rqsqrqopoqmonpnomnklknjklkjjc_^   ]\[ZYXW   V U  TSR Q PONKMIL  GF HEDCBA@?>=<;:987654J3210/.-,+*)('&%$#"!     / //  ///O 115598=1B<:2;;LM>ERRUUCQQ>LE1958C3<@MA?=mw}jszy Kdgk# /ILN]_celk## &(+*.,6$(?)*.0O =$>>>>$>=$>=$>>$>=>=$>>> >$> =$> f?|> f?|> ]?|>f?|>]?|>/?>5?>5?>;?>A?|>A?,>A?|>A?,>A?|>;?=;?=;?=;?=;?@<5?@<f?|> f?|>!]?|>"f?|>#]?|>$=$>%>>&>$>'=$>(=$>)>$>*=>+=$>,>>->$>.=$>/>=0>=1>?}?28?>3Y?>48?}?5>?>6C?-?7;?-?8>?}?9>?>:;?-?;8?><Y?}?=[?>>$?>?[?}?@[?-?AY?}?B>C\>>D}?E\>}?F-?GY?>HD?-?I1?-?J8?}?K1?-?L[?}?M[?>N~?-?O$?}?P\>>Q$?>R>>S>}?T>-?U>>V>}?W>-?X\>}?Y$?}?Z$?-?[$?-?\[?-?]\>-?^C?}?_D?>`C?>aD?}?b\>-?cY?-?dY?-?e?-?f~?>g~?}?h?}?i?>j?>k?>l?d>m>>n>d>o>>p>d>q>d>r>>s>d>t>;u>;v>=w>;x>=y?;z?>{?>|?d>}>>~>d>>>>d>>d>>>>d>>d>>>>>>>>d>>d>?d>>>>d>>>?d>?>>d>>>>>>>>d>>d>?d>>>>d>>>?d>?>?d>>>?d>>>>;>=>=>=>;>;;@===@==;@=;=====;=;>=>;>=>;>;@=;=;@==?=>;?;>;?=>=>=>;>;>;>=>=>=>;>;>;>=>=>=>;@=;==>=?=>>>|>>>>|>>>>|>>|>>>>|>>>>|>>>;?=5?=;?@<5?@<;?@<;?=5?>;?>;?|>5?>;?>;?|>;?=;?,>;?=;?,>;?@<5?=5?>5?|>;?>5?|>;?=5?@<>;>=>;>=>;>=>=>=>;>;;@===@==;@=;=;=;>;=$>>$> =$> >|> ?> >> ?>>|>?|>>=>;>;>;>=>=>=>;>;>;>=>=3?=?;3?;?; 3?=!?=">>#>|>$>>%>|>&>>'>|>(>|>)>>*>|>+>>,>|>->>.?|>/>>0?>1>>2?|>3>|>4>>5>d>6>>7>d>8>>9>d>:>>;>d><>>=>d>>>>?>d>@>d>A>>B>d>C>>D>d>E>>Fx?|>G~?,>Hx?|>I~?,>Jx?@M~?,>Nx?@P/?>Q/?,>R/?>S/?>T5?>U;?>V5?>W5?>X;?>Y;?>ZA?|>[A?|>\A?,>];?=^;?@<_;?=`>d>a>>b>d>cx?@ef?|>fx?|>gf?|>h~?,>i~?=jx?|>k~?=l~?,>m>|>n?>o>>p?>q>|>r?|>s?=t>;u?;v>;w?=x>=y>=z>;{>;|>;}>=~>=>=>;>;>;>=>=3?=?;3?;?;3?=?=?|>>>?>>>?|>>|>>>>d>>>>d>>>>d>>>>d>>>>d>>>>d>>d>>>>d>>>>d>>>x?|>~?,>x?|>~?,>x?@<~?=J?|>~?,>x?@</?,>/?>/?,>/?>/?>5?>/?>5?>;?>A?|>;?>A?|>A?,>A?|>A?,>A?|>A?|>A?,>A?,>;?=A?,>;?=>d>>>>d>x?@<~?,>f?|>x?|>f?|>~?,>~?=x?|>~?=~?,>>=>;>;@=;@===;@=;===;=;>;=$>>$>=$>=$>=>`=>>>>>`=$>>$>===$>>=>$>=$>`=>>>>>`=$>>$>>$>=====;>=>;>==;>;x?,>]?|>D?,>J?,>~?=x?=D?=J?@<J?=;?|>;?|>A?,>;?,>A?,>;?,>;?@<5?=5?= 5?|> ;?> 5?|> ;?= 5?@< ?> ?d>J?|>]?|>x?,>D?,>D?=f?|>J?=J?,>x?@<x?=J?@<>;>=x?,>]?|>D?,> J?,>!~?="x?=#D?=$J?@<%J?=& ?>' ?d>(J?|>)]?|>*x?,>+D?,>,D?=-f?|>.J?=/J?,>0x?@<1x?=2J?@<3>;4>=5>;6?;7>=8?=9=$>:=>;`=><>>=>>>`=$>?>$>@==A=$>B>=C>$>D=$>E`=>F>>G>>H`=$>I>$>J>$>K>=L>;M>=N>;Ċ?? >o Aee                                               X*553~>8^ 9)#޳wu] 6m|= &9c4w2ԥߧ"{%0~ e3z?L"$ \h? J Tx7Z7b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= # #Oxo#7x Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>5^ 9)#޳wu] 6m|= ^6i2ԥw o"$0~ e3z?8!$ \h? J *X9  b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= "" ˸'W ,G#Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>i(3^ 9)#޳wu] 6m|= z7'5K/ԥH "($0~ e3z? w$ \h? J ղ8<ʔ, b2_,0)+2  a6`< 26))Z ,Yo, P"t=~Eqw{= "!/ $i+C8*+Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>8^ 9)#޳wu] 6m|= 78yH74ԥӗ !{H%0~ e3z? T%$ \h? J VX7Z7b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= # #Oxs## dFtt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>&<^ 9)#޳wu] 6m|= bG>JG0ԥۇ#w&0~ e3z? $ \h? J x'x50`b2_,0)+2  a6`< 26))Z ,Yo, 0#t=~Eqw{=#"1o&@'v(Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>8^ 9)#޳wu] 6m|= :K$0ԥO#{H%0~ e3z?8W$ \h? J VX7Z7b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= # _"Oxs#g W&Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>i(3^ 9)#޳wu] 6m|= z7'5K/ԥH "($0~ e3z? w$ \h? J ղ8<ʔ, b2_,0)+2  a6`< 26))Z ,Yo, P"t=~Eqw{= "!/ $i+C8*+Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>8^ 9)#޳wu] 6m|= 78yH74ԥӗ !{H%0~ e3z? T%$ \h? J VX7Z7b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= # #Oxs## dFtt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>&<^ 9)#޳wu] 6m|= bG>JG0ԥۇ#w&0~ e3z? $ \h? J x'x50`b2_,0)+2  a6`< 26))Z ,Yo, 0#t=~Eqw{=#"1o&@'v(Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>:^ 9)#޳wu] 6m|= '<_d72ԥŻg"o%0~ e3z?Pg"$ \h? J jgH6@$ @b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{=P#_#'Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h                                                 X*553~>8^ 9)#޳wu] 6m|= &9c4w2ԥߧ"{%0~ e3z?L"$ \h? J Tx7Z7b2_,0)+2  a6`< 26))Z ,Yo, "t=~Eqw{= # #Oxo#7x Ftt{{bbb?,b?,b?,xGG(0(6{{tt0,0,0,Zb Zb Zb Zb Zb Zb 666666m m m m m m Z6Z6Z6Z6Z6Z6b?,0,             D "hi6i6i6i6i6666i6i6i6i6i6i6ih ih ih ih ih ih h h h h h h 666-Yc6~6      ''''''             [  |         S&S/'            ???         ??????            ????????????                                                   `96`96`96g(3g(3g(3      ??????????????????                                                        888888c66c66c66c667???                      hh6                                                             'c66c66                  h  O ABACABACABACABACABACABACABACABACABACABACABAC B CB CB CB CB CB CB CB CB CB CB C E E Ee Ca Cx CT C\ C\ CS Cq Cu C` ` C CF Cc Cs q{ CY Cd CC Ct EW Cv Ca Ce Cx cZ CK q\ Cs Cb qS s Cj dJ Cr s `P qm q^ CP cO CI Cw \D qe Cw Ew d c `] qf qo cq sS Cf Cp \@ qq sf EB C] ` `l Cl qq) Ew CL CZ Cn sj Cr+ C^ Cm qF) ` qz q^ Cb CA qz C] CM wu ` C^, vh CU Co w_ wX Ct C_ sR qr qR Cv wb CB qZ Cq Ed Ec CN tN s EV cp E`/ qe C_ ty c cp \! s CO `d CW d cY w^ q_ qt& qJ vh Ed si Ev wP vj qz Ee Ezf ]t qg qs s} cQ Cn CJ sE/ wZ qi vu s C~ qM qz) CU E~~ C\. Cd Cu sh C\, qj vf vk ]A CO, Ea c Cd \K CO Co vA nB* C^ qP lU( Cw t[ EX CE* C_( qm E\ qq C`, \a tg CR' s> EN \[ tw Ei `X" cl" qO Cj s. qF' td* bG* qT EW* qz- CX qE tK lr` vA n~ \E sC Ej nv c qM wc Eb tD" CO vu \O E[ EX yN/ c[ EBB sr, Ez qL sN. db E$a EE~ a, \M _ tI vL wi qi yh sQ sb y csY CLy cH q3 bn& sV bW qs EE. Cl vS vS/ CS- qu vs, EM+ CM vQ vP F. co) s{- tk tl E.m Ep tU sw( \T Ch- vQ- \h \L nE, to \` CN Ed \ vK cD- \e \V Cb \! ET' sk' E8Z) C~ p) c vL ql, vh C E{ s5 \A E^ bX qB b} bUA, qQ v| tV C_, qp Ey tA+ qk. co vq* CZ qf \D lC \f c cn) q[* qi ck `m sD \[ c Q s>K. | @ qH \[{ co tO qg! P a. ti' q[* Pe* ql w" CG- tN \U \H tj ti& w_ E8Y* EV nd- Ci \9 ET+ \D qAW \C qu CE `l qk da cj cm tU sc. \g# tf* \S# E}' Ct.  c \g" Ew' wS wt ws \[ \Z vM# nu, \X \} CS, tu wB hU* qe+ h} h~ tF- tT Cv CI ta U_* sp( \X \E \V \{ \_ W \A \A tv s} tGr q` tf dRE c`Q `Ro- c \| ]c Cz qr* \F% tb q[ \i tA* \t l{ wsF ]'[! wsZ \f c[n Cl( CLx tV q|* C#F q[o \k \h C#R \e \p \rb q| CLZ Ey, qW( \! wj tr CG \a q_ \'V& \RK wsk \^ \b sB, \T \'Q \S \YA \R qU. qq( qb( qj t~ c@ tC+ tD+ qH+ sF sE s@ tG \Ye CC qf s> cI+ UU qC \6` \[ cR \M \y \h \Y` \Y! \G qB \S" \Y \m` \e \! \c$ \|# tm \F# Ei \L Ed j \n \h \a E]- Eq. \A! sey qG \[ qe \e|! bY vp lQ% cE$ q~* s{* \Y \v \A \Z! \L \| \q tz sn \h \! CX t\ nOY( c6 \R% \9 \! \o \^} qM, CM qX/ CK) \^C qW clq \^x \^w Co. tB+ \9 \f dF) qo sq vs qq \^k vQ- EU \E CV tL( \f \n \o sR \{! Ec+ sr Eb+ \N! a+ \I ti \C \~# S+ qU) EEg R+ \[ qO* U\ qe& \w tc tA C_ tV qh& qA. \o t` tr \n \@ \b Cn s \j E~f+ \f CT CQ R* tn tt tY qx I* CG Pj- H* K* F* D* \U \a CL- CC EM CG qG' CK qb/ qk, N L CP qd/ \! EU tR( qN- qR) sAP sAQ \[ Er' Eyt' Ed' q@* qJ* tq" \@$ qb. \t tL) Cu sl. Ct  E+ \N"  `. EBd tM) qN) \H# \# \@ \ \F \Z q_% \m qa% tI- Ck s[) nK- ~' \J \v" \@# qv% \M$ \A \D \n$ \m \D \N \H \V sd! sU \]9 \K \E \@ c^ \A$ \! by \u \e \j \A \Y ]U \A ]^! \j \a \O \f% \H$ \z$ \m \t# \[ Er q0o tm, \d$ sp tD  ^' i` sq \r# id  V+ \a& \\ \^ \f# \N \s \C# \A \} \w \R! \F" b \d# \c# \l )k- )c* )X* \\# tg, Pe- f- tn, bh, { bt, })V, })g- })i- })v( })t- bV- bP/ l- bX, bA) K G Q F v@) qq, CJ CL CY \P$ P} P~ })Y, \N# EY+ \C \G# i+ qJ}, O m- s[ q^ qn- qY qQ* qc qb qs- to tQ tS tT t\ ta) \K, sI, s^. _) ql( sl] sl^ vd bK vf vv q sd( qa vY \O cC, tX$ \e< \eI qep- leg seR se[ \G tH- tQ, cr \D cP- cp \\ \x tj' \O \k lj l6j vv \6e sG qM sM lN \'q l^/ vT( s@+ qV( wS tT tx( \rO \G \ru \rH \U" s`* \T# E@ D su" s}* C#T* C#s) C#M/ C#O C#g) tW \sA \Y9 yg tYt* tY\ tYf, \O E.v ql qU+ qY) ty v, E.~ E.@ E.^* qp o~+ o \O \~ \C \c \b \A \f" \V# \Y! tA|$ sA sA sn. bz wj th t[ C} C_ C` tM" tg+ t] \_ \E \N }i. }j. \xK \xA \x| \xS I. \xD \xR \xQ \xY \x9 \[9 ED) q]^- \xr \xb \xP \xO \Mf \xN \ f \ S \xG q@m' q@z( Eg \xE \x_ \I \Y \v \| \y \ qNT, bR, \r bN \L% \I \| \J# q|. cz. \d% qz sA qE sN s}( sP vM sN|) \U \O# cO \j) bk( b_. sg \L \B# \s$ \g \y \J nx* \F cw* cd. bM se( tK$ tH) `R tOG+ i, \}$ \j" \B \[ vp, tO. vj+ \^j \^l so+ tw \^Z# \z \@ \A ]. \L \Y& \|! \q \} Es Eq r }t \ \P `e. EG/ W)X+ t` td sT hs Ue w# hJ sA hC h| hP* hL* wn E~ @ hx w` tS tu w{ sH sG wJ wE OI) OJ) OF OE) OC) wC EB) E{( ~( CY- EH' \Y B D vo vp ~xs' xu' vt vv qw|' qw{' `^ qz' qy' CX) Ch OPG ' EV* I' qx'G | L}/=rvH&Lz 8bFc}hWeRRw}/}/zGRW'gHw,RG}/}/wW}/yRgKv}/ QF}/}/}/ZVRfRUvRyFWa U}/}/wFvhF xV }/}/:e f }/}/ RK }/}/}/R[ }/}/wj Nz cI RzX Rh }/tw RF }/}/}/}/R|U }/dd R}u RD c T }/^ b ,Sp |x k@O }/R^ Rn w~ }/ZN `^ Asn }/b~ \M }/}/R] }/R{n \~ }/}/RM }/I ] Zl 'y~ }/[L S\ Pm KP} }/,QM s i\ ^ E }/_zV |N e }/Ms [SC }/,kS }/ENc g r RXA }/RwP }/}/}/F_ Rn e~ CN }/}/l^ ~Wn }/RE }/}/}/}/}/}/_UT }/}/wRc Rs }/SB R P Rw^ \m _| }/tK R[ Qk }/]ez E_ xn }/}/}/x~ vNN R_ }/yn y} zRL {[ EUk }/V@ }/RP }/@` up w S O }/Zz^ }/kl (R{ }/YJ }/}/HY }/}/bh ww LG }/dBW }/vf Nv cF }/}/}/}/'jV }/}/Sf d w }/v]I }/*W }/}/d h }/}/Wx }/pH }/M V ,cd }/ws TAC }/L D RS (*b rs }/}/}/,bB JQ N` }/x o j~ {wN cp] }/}/}/}/Zwl T| yK gm s[ wN k^ un }/}/dA} }/qM }/}/Ed\ hl }/Ar{ RJ }/f]Y Ug }/Vx }/}/gH dW }/S g }/} Xv [N }/}/]] }/}/[n }/}/}/}/}/}/P~ R@N R^ rn u} }/ekM }/'j\ kk {{ rwJ BZ ki }/x }/'eH \PX ]h wdv }/LF OW ah Zw }/VH whX wgg KQv }/}/nF cU w$c kG }/}/}/}/}/tW ew$f }/}/}/}/}/}/}/Y] {Rl }/}/R| CL [\ }/ul 'G| }/}/ ]L 'r[ Jj 'Hy P H O W ]f }/}/Rmu }/NSD }/iT g d }/]r }/iA DQ }/E` Zo ^~ ,IM ]\ }/Fj K x iG }/NW eh Tx kI }/h]X ^df }/,Jt ,]C k]R '*` }/^Dp }/,n }/Zj ~M *K }/}/}/;RZ Rj rz uJ LRY Li }/L x LQG rNV QRf LSv }/}/}/VeD 5eR }/Gc Yr }/FB uQ Wa }/[yp D@ DO dX^ }/}/}/}/RSn }/}/ } }/}/CM }/}/}/cz\ jk }/aO{ azJ BY Jh }/}/}/`w RQF }/}/}/gLU gke [zu }/[@D nT }/Ld Z^t l`D }/bT }/v c }/}/dwt }/}/d@C }/}/}/R\S t b Qq }/}/}/'fA vO }/}/}/Q@^ }/}/}/}/}/}/}/Wo }/X mN P_ Kn z} RM i ^ }/m } e M ERW u g }/q w }/lG o V ^`e ;wu }/}/{E zU R d h s ^XB }/mQ |` }/Qo | uN }/h^ }/ym T@| }/}/}/}/}/rK <HZ }/Nb ts O_A mP Rva mp R@ | P Du_ uo }/t~ }/}/A[M dy] k}m }/y |6| }/[r YB AQ }/t` do }/}/] }/}/&DM }/}/}/}/_\ nl }/}/}/}/{| }/ML D[ }/}/}/zj }/My wK }/}/}/wP[ yi Jx VH }/wQW Kqf vv }/LE weU }/}/7Rd }/wjs tC uR Kfa x\q 7jM |$^ }/}/'v FB FRH wX }/KXg iu xE }/}/_W }/}/Ei { }/iK M[ }/Xj  y RI q Y ~j Wy QH W !Hf }/~t HC kgGQ }/"FX }/Nf }/}/n[v }/ZF }/}/jX nh ex }/}/GIH }/}/0iQ 2~a v p }/}/}/}/}/kq  PP [a pq }/hA gO }/X e^ iC sS }/}/}/}/}/sb }/}/5q r wC }/}/H Q M` 'Hip tY I ~i 5]g 'fv 5l \ 5Ql Rm} sM o\ sk qy }/dUH }/Tm] Q m AC | U  L N M ] }/ll g{ 4J 4 Y Xi Sx NI WY 4h lx RG V W zif }/Fv pF 7kU O d W s RB '!ZQ vk }/ j_y }/yX 8ig }/}/ @cw }/^Z fnj }/]y }/iI }/^ Y uVi }/}/}/cx EPG 'mW }/Me Ou rE QT Nd @s rQB r`R w@b Nq q @ SQ wAa {@p ] }/}/N  ^ n f~ RM }/}/{A\ kk Q{ dJ jZ nj '[z qOI }/}/iX zh nw mF }/}/sV }/vf }/}/[w }/}/}/\ F Z U @c Rq }/}/}/}/'h@ }/rJN R] Ik 'gz u H }/}/^QW }/}/^Pg Viw }/v uG n| _`K }/}/}/}/}/dk }/}/}/}/}/}/}/Rx{ [I bX ag }/}/}/}/}/jx }/]H }/}/}/]W bf }/}/vu ZsD }/}/}/diU }/}/be }/}/}/}/}/}/_Vt }/nC }/Nm R na jp Rx@ ` QP cTa eq ZA }/` AuR nG }/D_W }/}/}/}/}/}/pv nE }/MU nd Ums }/u` 9`p EYP }/}/}/}/{ i g jt  ^ }/}/}/}/}/}/Cj }/}/}/}/}/'a z D F HR }/Sb Tp 'i~ L L R\ rk }/}/}/}/}/'kz }/}/wRH }/AX 'Cg }/mu nD LS Hc Gs ltC fu R ~ G 'oW | e ku hnD RT a#c tF 'pT }/V$b C WF }/n ] }/}/}/al `} m N P ] ^n f ~ }/}/}/sM \\ }/}/}/}/}/}/}/}/Mk Muz J H }/}/}/}/Q H `W }/}/}/}/J fw K ] J n Wn K hN ov }/LaE LbU I e }/Nt N eC "X h "q q "yB }/}/O kQ { | >K }/}/AyZ }/Aji Aey AZI yZ ji ky y }/>kD k~S kb >Rq }/}/y A hnP }/j` }/}/}/kp kn~ (uN R^ nyo }/y~ njN }/ne^ wn m~ uM n\ W_k KRJ Rh dZ Kd~ EN _^ Gm Kv} }/y M zX {h Hx }/}/wfH uW nZg Ri Lx vD }/7X S 7q \ 7N m 7Qw ykH yRW 7l g }/}/Fkv RE }/`U zc }/}r }/}/}/}/CA }/lQ }/}/T` np j sO }/,m_ }/ CNn gP j| }/}/}/5X f }/}/xq S@ tO ZR H ^ tf *ju zl E 4rU zQd zJu k E j V cg ;Sv }/}/^F }/` V rg 3U v EQE y U Ev` 3W p n }/}/*N z ] }/}/}/{ m v ~ }/3r N }/s_ 3p n }/}/w ~ ^vO }/}/}/Qi_ r`o }/}/r[ rZO qJ_ VMn VN~ }/}/}/XrO }/\ ^ q j X { w uD dwy dI dRY Ng i }/}/}/}/Nvx Nh G Ni V Nj e Np t yC }/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/}/oR US` e~s L0q oa E 'o }/}/uV $Osf }/}/oY 5li rU !=e ub acr {I U 5Os^ }/a2Q CEC }/}/97H pC KIB }/ A ?K rJ uY *Omi CQ V }/}/og 7UCu ux }/7OKH }/LyS }/}//^L etj o^ on US| }/l7O VLF Z gWR k[_i }/}/}/kHyH kLAA keeB }/}/}/0og }/}/}/kUSu kb7H ha kH9` \aY y(z 5ob k7q :rh :uw kO^G k!ae bSF ?oU Tc "Bqr Uc "Axs }/Dok "`^z "9@X "!7X [VO }/}/Loe Lcs x^C Noa D~o ~xm o,e uQ iba ToC `{R }/}/}/}/}/}/}/}/i M }/}/}/}/}/}/}5\ KgQ jV2x huj nE,y m94e lmYlng_f%vno[|$iuZMue^ujn!_~u[]uym[A%|aHax hi|jQ|Z`|rrw SBb%U|$zS#^jUAyVk Rd^D%vR#[Q#~l %amF} >Vr%T}/P#yZ\yma| O%LxqN%AkfStG%CE$h_$L^#p]IS}/a\nJlZv@CFHj<DNoRoab(p}/g#XX#{jc^yAJQOqo`eoOv/~}/omY-}BojdKYtdx}XX )U}/Wu~}/osGaA}/}/}/S^bR@NBP}/}/}/}/}/}/oR fva IwW}/oN}/B @^\`%nBz}/| j@|Z%aL| ~ @HfYHnao pN zkHSVk G0e}/}/HLU}/}/}/}/}/}/}/}/}/}/}/{_a}/}/n@j<^OSmo|}>K foIoxfFFZ%aNLoZM &hf\NT*!;jKoewotIQC}/ G KT*Kt_*9/SoB[dP*|$twSXmknytH}/*f%W Z| eM j] [m y}*A%Ljqms @ZsrE*b%U*|$z}/*S$^yB*D%P*R$u*Q$Yn}}/*Y%Lmq*r%A*P$f}/ ZJ y[ aj*O%z"x_*N%o&kT&Sb}/*G%q*E$V*_$z*^#^t3A.otyhB.]jy){adZsoE*nT4oc/vs6oi cAw oMxBMEoR8oaghq}/O}9IfK9 Rq9uJ+A9 RR9y)b9 ur9 RB9* cR9Pa9 Sr9D wA9 ^P9 R_97 Ko9 Q~9NkM9 ]']9| Sl9 R{9o*J9v[9 d)k9 Mz9d ~,I9 QX9 Lg9 Rv9j SE9g'U9 Qe97 P,t9 dC97 I/S9KQ/b9`r9 B/B9@.R9K d)b9KR/q97 w+A9Q(P9L+`9J(q9 NB9Q d)Q9 y.`9' Q(o9\'97 S.Q9 X`9 ro9A w97 v+N97 D,]9 C/l9j H,{9 XK9D%Z9dRj9 nz9 RK9{ ][9g(j97 `'{9 wJ9N RY97 t+i9P+x9 RG9 _V97 ^)e9c xt9- ID9 qU9 Rc97 j&s97 XA9 RQ9@ R`9\*p9 R@9\+P9)s_9KT/o9U~9f!D%O9)S9nd97 Rt9 HD9d SU9# Re9g$u9x-D9 SS9 Q/b9Rr9{ RB9. +R9Ra9 wq9p#@9 wO9 c^9 jn9 u~9 RN9$ t^9 sm9 Q}9AL9})[97 dj9S*z97 J'J9]X9 bh9Z,w9 d)F9 \%~U9 g*S9 `+b9N `q9 A/A9tP9 Sc9b r&r9i%gA9 Ih97 E-w9b'F9@ C'T9nc9"Rs9j {+C9m% R97 r(Q9 X`9 Ro9T&x~9Rv9O%F9 v*V9 nf9'nu9^)E9j&U9nd90 v*t9 RD9. ^T9 Rc9M ws9 ]C:@ hQ:M'`: ]q:&n: ]O:' R^: en:T%~:# dN:-r]: ck: Rz:i$J: ]Y:kh:wx: uG:\+hBW:Z+nHY: wa: ip: n@: uP:. s`:)to:w@:O SO: J/^: im:Jf)~:N dM:b R]:f(m: j,}:kM:^"]:i(k:~.|:2kJ: y(Y: Rg:~hv:Z,^: k)m: R}: X(M: d]:1 +m:7 Q|: NL: M[:{ R-j:! w{: P.J:N VZ: Xj: Ky:d XH: {)V:}-e:7 Q.t: C: U'R:r Z(a: nq:y wA: `Q:0 n`: Rp: P: RP:@ S`:@ Qo: _+~:@ dL: q\:. Wk: n{: uJ:f&Z:g&j:l&{:m&M:o&_: [q:1 Q-A:1 RO:o$_:\c/n:X}:B'L: u]: xl:U|:4 ],K:kZ:r$i:](z:$ kK:c d,Z:` kh:]*w:m H:kW:'m)f: X(u: P.E:h$U: dd:Q#ot:NS(c: Pq:7 ^(B: DQ:4xb:gwr:dhB:RQ:dg`:Xjo: ]:XXM:dd]:7 W.m: {.|:A-K:h#Z:xk:]{: _I: s&X: G,g: ]w:7 q+E:7 V.T:7 _/e:7 p+t:7 [.C:+ bR:@ ga:M kp:N g@:N hO:$ S^:V/n:Dj(: sN:N+^:KJ&n:o,}: [L:P'[:d h*j: ]y:Ks$G:b Nk:b >z:n VH:q ]X: q*f:v&u:{ c&D:y ]T:&]b: np:']: kM:W'\: kj: zz:F SJ:w b*Z: Dh:ey: SI: RW: @#g: ww: K/F:m+U:~zd: Rt: y(D: QS: jb: Jr: RA:XQ: S`:= No:A u: QO:: c^: Rm:G N}:XM: w\:2 Ql:C%|: kL:D ]\:g!hj: aGR:r-Y:q-i:'d x:AF:p%KU: nl`:n L: k\:k*k:l%b {:'h)]:{,m:uN}:_'M:@-\: ]l:dPz:dQI:b*X:]f:Xnt:u `)D:nT:XPc:f's:| ]C: ]Q: (_: ]n:Xh|:]L:f'Z:]j:j#x:`(I:kX: ]h: i*w: nG:kW:d H,f: h(v: o'E: n'T: W+c: R-r:o(C:n(R: ^+a:Hp:~ J: XN: r.^:sm:e'|:XMK:X[-[: [k:ON{: q!K: yY:deh:O-w:R-G:e'W:c'f:e,t:}+D:AS:c Sa:s.p:'D:d|,M:dk\:'R(k:Nty:NGH:Y C*W:V Nh:"fw:"eE:hdT:d)d:b-s:J%C:t(S:D Nc: Rs:h+C:r.R:G)a:]${o: @#j: T-z:waJ:UZ'[:{ak:UY'|:u-L: J([:e$uk: s*`:URo:`&:k$O: N,`:L.o:0V'~: XM:D f.\:tl:7 D.z:4 z+I:kY:h.i:kz:o%J:7 q&Y: uh: Mx:2 qG: kW:kf: su: FD: `S:2 Xb: up:# n: eO:- k_:' ,n:7 c)}:' QL:m+[:7 C.k: gz:/ v)H:' PY: Rh: Xx:m+G:7 vW: w.g:. W-u: T)E:y uT: Pc:. br:@ D'A: tP: L^: N*m: Z|:@ U-M:J'\:[ Rj:~k/z:U/H:~yY: D/j: my: w,H:u.V:2q f: Rv: QF:[ ,U: Sd: O/r:[ QA: QP:[ P_:z%m: r&~: SL; [\; Mj; m*x;b ,G;j c&V;b Qf;uK+u; LE;a f.T; Sc; Qr;b PA;l SP;;f.`;eo;0 l)~;0 kM; k];{ Q+m; l)|;{ cK;{ b\;0 u*k; u*z;WI;VX; Qi; vy; UH; IW; Sf; Jv;2 K/E;p*T;j h*d;K]$s; DW;j Sf;K|%v;K~%D; cS;KA&d;s.s;h K/B; k&Q;b d`; l*p;J; nN;j*]; _l;t){; ]pJ;5b&z;\ nI; O/X; @g;j(x; jG; NW; H/g; F/v;p.E; nT; p&d;@&t;%C;b&R; n`;~@'q;[ d@;~x%P;W/_;M lm; ])|; SK;) dZ; d+i;@ F,x; @/G; ZU; eg; O/v;l+E;x.S;w%c;P'r;M Q)C;y v)Q; ib; \r;+ @; SP;+ `;+ p;7 O'@;' b,O; y+];7 e/k;l+|; kJ; y+Y; v.h;q$v;7 T.E;XV;Xf; Yv;7 Y.F; U; ^e;7 X.t;L'C; R; wb; r;\B;N'Q;Ya;x)q;w)@;v)N;D W,_; Yn;Y~;YN; d^;J.n;H.};G.M;B.];7 s(m; w|;-L;Pi\; zl; ]/{; !lJ;Ukv; SF; J-U; [+d;Uvr; RB;n%rQ;UQC; M-S;z,b;Uq;U A;jQ;N_&a;Up;h'@;N%O; d_;U['o;K}; M;];L/m;G J|;H%K;u&[;Kk;h_{;_-K;G%[;M ~)k;hy;"dI;l'Y;Z `h;+kx;h G;hW;k%ug;hK\;a(l;c m{;'L)K;'d*Y;'b&g;'k#v;RD;'l#U;d'c;'r)s;c%TB;q JV;ye;e,t;rf/E;iS;rwc;Xs;3vC;e,R;Xh+c;^hq; jY; ni; w-y;isI;OL,X;zTg; X-v;nCD;iG;hyW;~ NP;`;qp;V%;n#M; \;Rl; |(};K;u([;ej;mV)z;mF#I; p'l;R{;AK; q'Z; l!i; c-x;RF;yi#DW;+[;gy"Dk;k*o;yb%F;e%JE;RO;h%`;,_;Zm;W%~;Y%M;]%\;uck;y{;udK;w[;pk;m#{;p J;pZ;hLj;S%Ay;C$}z;ijw;inG;iw-W;idg; [w; dH;sX;Xg;X w;LG;UXW;dfg;Uv&v;SX'F; hT;K fd;PX'J;&f$uX;x M;O|,];J!k;0S'|;N\/L;Nk+[;N@,j;NE'y;NO+H;)nW;NS)f;NFu;NED;NP)S;)jb;)Rr;gO$B;gQ'f;L&yt;sm;L|;m$L;`-Z;[[j;2 NE;2 vU;K'e;2 ft;D; kT;: Xd;~q%lt; i`< kp<A' @<[&`<Z"o<R"~<F$M< e\<s%l< c({< RJ<j&Y<x$<y&N<`#t<[#C<K#f<}#I< |(X<M&f<N&u<\$D< AS<y%c<{%q<K&@<O&O<R&^<S&m<U&|< iK< j[<\ jk< T I{< nD< jS< hc< @t< NE< NU< Se< Z+u< SF< +U<\d<hs<NB<b qQ<b x&`<ko<j~<[ qM<{#\<N vk<N Q{<N O'K<N XZ<M |+j<M ty<@ QH<@ O'X<@ Xg<gpw<D#g<= v)v<U,G<k"X<1 qi<1 x<4 hG<1 W<' qf<' u< w@D<' D<* uS<X(c<als<P._<X(o<P.< O< _< a*n< }~<I%L< y[< rk< w{< O/K< Z-Z< Zj< \){< QK< mZ<n+i< rx< \-H< yX< \)i<n+y< C-H< c-W<{$e< .t< iC< C-R< c-a< wo<m(<Y$N<V$]<U$l< [({< u+J< fY< ~-h<my#w<mj#Z<mO)}< tL< J[<ym j<m x<`(F< nT< nd<| nt<y |(D<y nR<z qc<Zq<h O/B<~ `Q<u Ka<h Q/o<~ [<~ ZO<gg/^<q `m<h R}<TM*M<'v#\<k mm<'i)|<'s#L<'_  Z<e tg<'U u<c u)C<C ]+R<c J`<` F+o<'f*~<] mL<Y w&[<Z Ji<[ mx<G `G<G [W<G Zg<jv<7 Z.F<7 m.U<7 a-d<M.s<ku 9B<2 O/{<2 Q/J<2 RZ<I$j<1 ty<0 f.I</ tY<1 x,g<' ]+w<- r E<- TV< ]+e<*Us< f.A<*`(Q< u`< O/p<[/~< RM<Z/]< ]+l<2X z<2ZF< tX<2yg< |(v< nD< uU<KI&d<KG&s<K}%Bv<J St^!Tv>^a@J>^{[J>V R-e>[ uv> U"WF>_ [ M]> uONj>c Zx>uY jH>c [r>c `B>uIR>u!j[>c QE> O#wT>q oK>n(5 ]MY>q Zf>j ov>5 WLD>q [P> eS`>Y ,s>}w!q_>'hCP>'M'E 'O>o ov> [ XD>'~!y\>}x!XU>G"Rm>'b U>L LT>ak`>x#RK>'A _]>uc|>w@_>W|u ^_>h o}> V jL>|\]v>d uOS> ob>|P]p>d X[M> Zh>d C"Yx>S jQ> [{> `K>d wU[>S :p>d L aj>S y:K>KkF E>uTK> [ 4_>wWS> !Cj> mqlm> a'Y> \(j> uz> oI>mgXX> t2p> Z*b>q. j?q> jLp> e)|> K(M> i*T> ob> op> n*A? v"oQ?m`2@? t$r? ~-V?i+ F)e?miN? t$M? ~-q?i+ F)@?m[!Vi? K3?p. y)r?mr?[? oZ?mg Ah? oi?mV&7w? on?mQ E|? tA? M &P? ov? y(D? ol? o{?M 'I? op?|#A~?H.a%?D.w$d?KW@H? oH? M$|V? oR? A$ib?i(K? o[?KsZj? d$oD?k!Xs? oK?KqtZ?n!-N?]({?KQ!pJ?  ;z? ou?KhuD? oy? @ ;H?K|~C? oA?KO!iP?K%y? N!)I? #>r?{!)p? oY? H#8h? o`?g#Po?j"%? Rd?}$%s? RX?X%.g?c$`U? ou?S#\C?S"W_?Kf]v?KcAS@F%tT@ oH@ @#hV@`w~@P Bu@H!dw@ o[@B#ni@O SW@L!uj@S]_@ Z k|@ og@ miv@ Ur_@ oQ@ e A`@bba@ oC@M!{Q@ oL@\&Z@ o@@[1N@ o@G &M@ os@lsC@T!Fv@z w|@ os@c mB@bEo@P!|t@y Op@[ W@ }gV@ o}@ K@ A!'[@ KbB@ udA v)sA L)DA Z*mAi 2|A onA m|AnPLA m\A omA x#{A e)^A n*oA ^!NA tMA* o\AS!KjA? }kuA) o`A) mnAU!|~A) mzA? x$KA|K3EKY% !7xK g2oKADMaKBynKAK)|K e2eKEK3WK `2JKGD)|KHyeKGK4sK i2gKKK3YK Y4R LKR%F^Kj [dKr LKH -KKQoxKX@GK oGKT]VK Y4f*sLKY4TYLGOmNY4@|N_ Y4B|N Y4X~N Y4O VN^Y4VeNo#P{O}Y4J'KOXoUOd Y4P-eO Y4ZuOdoOOw xB^O"_'`OeoGOioUO fkeOR+^UPOY4NeO Y4vsOooiP Y4xPuY4a"wPb(XP wS@P oSPB-cP`rPpoCP SiRP e{PJ#'KPuorP~Y4d]CP _'gQzoNQ_&\Q|oBQX uPQ UrEQwowQY!uEQY4P,zQ| jSJQ~"J]Q!ggQY4YNQ CVgQ}"}}QozQ G#(HQ N#'pQoWQ P$'eQoLQA0ZQoJQaXQ Y4QWQ [JhQM \rQ Y4WNQCUeQ N!)zQocQ{!)rQA0[QoKQ Y4_YQ Y4} xQouRs f'CR!ZSR Y4umR+bRCSrRRERoVR Y4GeRADlRopRV#Q~RmY4@BORz f'OR!Z_RY4i%ySY4a4bSCoCSArSoASm!D PSA0TSoDSY4BRSY4{"TSCWOTY4L"fTorTE#{ATAP|ToLTY4JZTA%QdTY4quTO"pfTY4VT$YUUY4bnUoPUgS_UU%KrU PL}U RMIU s+NVUMEdU j/@iU @(_iU A(lHU B(rtU C(F fU D(vlU E([bU F(H}Ud G([EUd H(^`Ud I(Y~UNhWUO|UP`{URs[VSiNVT]wV}P(RTV}&LfV|&hr]{&|Za~&DVd&tZl