Áƒ*žEø@¼x6>m .zg¥×gO§»ÍÞ }þM¼øNoneClientMessageColor SmartCTFLogSpecialEvent GetString SmartCTF_4CCoreEngine DrawStatTypeSystemReceiveLocalizedMessageClientPlaySound GetStatsSmartCTFBonusesBroadcastLocalizedMessageBotpackSmartCTFMessagesBroadcastMessage InternalTime GetBigFont ClearStats MessagesGetStatsByPRI GetSmallFontPostBeginPlayResetFlagCarriers GetTimeStamp RefreshPRITwoDigitString IsInZoneCarriedStringSmartCTFSoundsInitStatBoardDynamicPos DitchZerosClientReceive GetStatNrTimerUSizeVSizeGetSmallestFontMipZeroPaletteUBitsUClampVClampVBits SwapOrderedCompressStatBoardAddRedFlagCarrierAddBlueFlagCarrierSmartCTFShowScoresSmartCTFScoreBoard ShowScores ResetSpreesOvertimeControl GetHugeFontCalcSmartCTFEndStatsSpawnNormalScoreBoard MaxColor RedTeamColorBlueTeamColorGray ShowStats DrawMOTD PreBeginPlay RemoteRole PostRenderUT_ShieldBelt FontSize SortScores GetColor GetOffset ToggleStatsbCenterGetBroadcastStringClientJoinServerShowIndicatorTournamentPlayerSetEndCamsTiedCTFGameDrawLeaderBoardGiveCoverSealBonusWhiteDrawGameStatsInitStatBoardConstPosRewardBlueFlagCarriersRewardRedFlagCarriersRecountNumbers GreenFlagGetMeterLengthDrawContactInfo GetTimeStrUDamage SpreeSound bIsSpecial PlayerPawn bIsUnique bFadeMessageConsoleCommandbHiddenHandleEndGameTournamentGameStarted FirstSpawnGibbedDrawServerStats DecapitatedYPosbAlwaysRelevantValidateSmartCTFMutatorLocalizedMessage DrawHeader DrawTitle DrawColor DrawFootersEndGame ModifyPlayer AddMutatorMutateGiveTo GameEnded bEnabled SpectatorMessagingSpectatorshotbPlayLeadSoundMutatedDefaultWeapon AddStringHandlePickupQuerybPlaySavedSoundbPlayAssistSound SectionNamebShowCoverRewardConsoleMsgbShowSealRewardConsoleMsgbShowAssistConsoleMsg EradicatedbShowSpawnKillerGlobalMsg SavedMsgType SealMsgTypeCoverSpreeMsgTypeLongRangeStringUberLongRangeStringbAfterGodLikeMsg GetMultiSkinSpawnLamerString GetFontSize LifetimeSpawnKillTimeNWSpawnKillTimeArenaDropSpawnNotificationbSpawnkillDetectionbNewCapAssistScoring ActorClassbSmartCTFServerInfoEnhancedMultiKillBroadcast bFixFlagBugMinimalCapBonusSpawnKillPenaltyCloseSaveReturnBonusEnemyBaseReturnBonusMidReturnBonusBaseReturnBonus SealBonus CoverBonus AssistBonus CapBonusOvertimeEnabledStringOvertimeDisabledString EnabledColorDisabledColor LogoTextVersionSpawnLamerColor CoveredMsgYouCoveredMsgCoverSpreeMsgYouCoverSpreeMsgUltraCoverMsgYouUltraCoverMsg bDrawLogobPlay30SecSoundbStatsDrawFacesbShowFCLocationDroppedMessageSmartCTFSpreeMsgSmartCTFSpawnNotifyPRISmartCTFServerInfoSmartCTFServerActorSealMsgSmartCTFPlayerReplicationInfoSmartCTFMessageSmartCTFGameReplicationInfoSmartCTFFlagCheckerInventory!SmartCTFEnhancedMultiKillMessage!SmartCTFEnhancedDeathMessagePlusSmartCTFEndStatsSmartCTFCoolMsgSmartCTFBindsSmartCTFAudioMsg YouSealMsg SavedMsgGameTieMessageMegaKillStringUTMenu YellowFlag PureCTFHUD YouSavedMsgTopPlayersText BestNameText BestFPHText bOverTimeBestRecordSetText SpawnKillMsg RenderInfoPtsTextCTFFlag HealthPackUT_invisibilitySepTextRedeemerDeath MoreTextPawn HeaderTextbIsConsoleMessage DarkGrayRedHeaderColorBlueHeaderColor StatsColorYellow FooterColorCTFGame HeaderColorUserTinyInfoColorHeaderTinyInfoColorTournamentWeapon CalcEndStats spreenoteTick bHeldItem DestroyedSpawned MapNameText HeaderBlue LabelListBot TextBlue InfoWhiteBestSomethingUTPure AliasNames FragsTextRegisterMessageMutatorClientGameEndedRegisterHUDMutator PreventDeath!MutatorBroadcastLocalizedMessage bHUDMutatorNextHUDMutator ZoneNameSizeY bAllowPickup ReceiverSuperShockRifle ImpactHammerUWindowIconsRowBest TotalHeight PlayersTextSizeX NameText GameTypeTextWhatMOTDBotText PlayerStatsClipX VoiceType TimeMessage TeamColorTeams PlayerZone TalkTexture ShieldBeltSender TeamInfo MaxTeamsSize Palette7NumBotsRemainingBotsGRIHoursMinutes Palette5IconSelectionSkinsBelt_fxnewblueDeaths PlayerID bInitializedGameEndedCommentsDeathMatchPlus MOTDLine3CTF AdminName TeamGamePlus ElapsedTimeRemainingTime TimeSoundInvCurrentNetSpeedStartY LocationName ChallengeHUD FaceNameSkin PlayerOwnerServerInfoClassStrClipY ChildMessageVictimXL CaptureSoundYL Palette1 NextMutator FlagBaseTeamScoreBoard LocalLogUnrealCTFScoreboard BaseMutatorTournamentPickup bBehindView Palette3 WeaponScale HUDScale ScoreTimeScoreBoardType bGameEnded PawnListNetModeGameStatsTextGamesHostedTextServerStatsText UnknownText EMailText AdminTextContactInfoTextServerInfoTextMonsterKillStringUltraKillStringDoubleKillStringTripleKillStringMultiKillString CountDown bTournamentTournamentGameReplicationInfoBotReplicationInfo LastKillTimeServerInfoCTF ServerInfoRedFlagMultiKillMessageTournamentScoreBoardKillingSpreeMessageMinutebHome FontInfo EndStatsDeathMessagePlusCTFReplicationInfoFlagsCapturedTextLocalMessagePlusVictimMessage CTFMessageHour MultiLevelHolder TotalGames TotalFlagsBestRecordDate FlagList RealOrders Announcer doublekill monsterkill multikill ultrakillbRequireReadyEndTimeOrdered bTimeDownMyFontsTGRIXL2YL2(All) BlueFlag DayOfWeek RedSkin2 BlueSkin2bHideAllWeapons PickupTimeX1I_TeamBI_TeamRFlag Ammocount LEDFont2bReadytotal SpawnTimecapturecd30sec lostlead megakill nicecatch takenlead triplekillassistTempStrDay TrophyCTFUTExtraKeyBindingsMonthcresFBYeargg TimeSecondsOptionalObject RelatedPRI_1OwnerLoc nextPawnmyHUDScoringHUDTypeGamebAdminPRI StartTimePlayerLocationbWaitingPlayer bIsSpectatorbIsABot PacketLoss TickRateHasFlagScore PlayerName PRIArrayNormalScoreBoardClassbServerInfoSetServerSideDefaultHUDType MOTDLine4 MOTDLine2 MOTDLine1 AdminEmail NumPlayers CapturesAssistsGrabsCoversSeals FlagKillsFrags HeadShots ShieldBeltsAmps FragSpree CoverSpree SealSpreeSpawnKillSpreebHadFirstSpawnbViewingStatsIndicatorStartShowIndicatorVisibilitySecondsItemmeterpoweredshade SCTFGame RedAstIndex BlueAstIndexTRCountMFCs RedAssistersBlueAssistersRedFlagCarrierBlueFlagCarrierRedFlagCarrierTimeBlueFlagCarrierTime RedFCIndex BlueFCIndexRedAssistTimesBlueAssistTimes FlagStandsbForcedEndGamebTournamentGameStartedbTooCloseForSavesbClientJoinPlayer LogoCounter DrawLogoIdpTGRIpPRI Velocity bReadyToPlay MutateString HitLocationLastUpdateTimeNFlagKillBonusKillerP GrabBonus RelatedPRI_2 ViewTarget bShowScoresResultDelta SkinNameOtherbEnhancedMultiKill TotalTimeMapNamePingGetPlayerNetworkAddressDeathMessageClass MaxPlayers ServerName SmallFont CoverMsgTypeSetPos DrawPattern DrawIconbShowLongRangeMsg DrawRect FovAngle Location bNoSmooth bIsPlayerbPlayCaptureSound ScoreBoard LocalMessageStyleTeambEnableOvertimeControlbRememberOvertimeSetting MenuTick bRunning OtherStats DamageTypeF VictimPRI KillerPRI bPreventbVictimTeamHasFlag bWarmupSkippn TimeAwake KillerStats VictimStatstempAAsterFctXCbNotPlayedLeadAssisterStatsBonusYLabeljPerc LeadSound FirstPawnReceiverStatsipnPRI PawnStats ScriptText SoundsString MsgsString CMsgsString SenderStatsbTiedBR TopScore TopFragsTopCaps TopCovers TopFlagkills TopHeadshotsPerHourGnrDummyY ReturnValue OwnerStats MultiStrDynamicLoadObjectMinTimeScaleMutatorWeapon LevelInfo GameInfo ZoneInfoHUD DecorationPlayerReplicationInfoStatLogReplicationInfoGameReplicationInfo locationid SpawnNotify Inventory ViewportCanvas facelessNormalScoreBoard TryCountFontLevelActorPlayer LastSortTimeMaxMeterWidthColorChangeSpeed RowColStateCountSoundTextureMessageTitleConsoleRoleClassStatsTextWidth StatHeight MeterHeight NameHeight ColumnHeightStatBlockHeight RedStartX BlueStartX ColumnWidth StatWidthStatsHorSpacingShadingSpacingXHeaderShadingSpacingYColumnShadingSpacingYStatLineHeightStatBlockSpacing StatIndent StatFontCapFont FooterFontGameEndedFontPlayerNameFont FragsFont TinyInfoFont PtsFont22 PtsFont20 PtsFont18 PtsFont16 PtsFont14 PtsFont12MaxCaps MaxAssists MaxGrabs MaxCovers MaxSeals MaxFlagKills MaxFrags MaxDeathsTotShieldBeltsTotAmpsPackageSwitch BlockLen LineHeight TextBufferAvgPingAvgPLTotSBTotAmpEffRedYBlueYNilDummyXBuffer LabelDrawn Rendered TempColor PlayerStats2ObjectLeftSpacingPercentMidSpacingPercentRightSpacingPercent FunctionRowsCols NewStatFont LineSpacing BlockSpacingVectorEndYStructCol ColorChangeNameY1TextStrTimeStr UnrealShareMon StrPropertybSorted PlayerStats1StructPropertyClassProperty NameProperty bFontUpdated HeaderHeight CatHeight TextHeightSmallTextHeight VSpacingBorderSpacing SideSpacingObjectPropertyFloatProperty BoolPropertyWhoWhereWhen IntProperty RecordDate MostPoints MostFrags MostCapsMostFlagKills MostCoversMostHeadShots ByteProperty ChatSoundël y }Þš:Ï:$š:Ï:$ÿÿÿÿÿÿÿÿÿÿŒm¢‡ëYQ²Z‡œÔXˆ> £Yˆ> £YÚOXˆ> £Yˆ> £Y‡œÔXˆ> £Yˆ> £YÚOXˆ> £Y†Ž”ˆ> £Y J€ƒën ~ $š:Ï:$š:Ï:$ÿÿÿÿÿÿÿÿÿÿ> ÀÙëYQ²ZŒm¢‡Œm¢‡Œm¢‡‡œÔX‰žtÈŒm¢‡ BÕt iCI š:Ï:$ÿÿÿÿÿÿÿÿÿÿ™*Õ{ÇùëhkÓ~x j…KK€ˆ n ‰9€ƒA{h €ƒ…1@7@VÃm p ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ xp¬ÛÃ=íˆ> £Yˆ> £Yˆ> £Y…{#U¿…{#U¿…{#U¿…{#U¿…{#U¿…{#U¿ m]covered the flagcarrier!n]You covered the flagcarrier!o]is on a cover spree!p]You are on a cover spree!q]got a multi cover!r]You got a multi cover!|]is sealing off the base!G]You are sealing off the base!H] Saved ByN] Close save!!T]is a spawnkilling lamer!E"^Ó`ÓaÓp*Àj$DCJÓR…H]€ƒ\›H…€‰xv€ƒf€ƒo€ˆO€ƒtFšYv€ƒz€ƒfˆp€ƒ:FA@W[V€ƒ@ €@M€ƒj@€‰Opw@&Úo‰tšn@@s ‰C ‰A@J@^@%G€‰B@D€ƒMSsCHL@xi.4 n\ hE€ƒ[®C @Q‰b @DFdˆF @DFg @DFy…l€‰E@La @DFl @DF^T@_ @DFS €‡@|€ƒÃu R DÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿpIî¸)Ã=í K]Long Range Kill!L]Über Long Range Kill!O] Spawnkill...f]! Sudden Death Overtime = Enabledg]"!Sudden Death Overtime = DISABLEDh*€ÿÀi*ÿÀ€l*ÿ@E"^Ó`ÓaÓp*ÿààj$DCJÓE@ˆt @ C€‰W€•Q@fU…i|€¿Zw€^ h@m°] sd …Be@m€ˆFT…~VL‰d€‡w‰WRh@^g_Ya®U X ` U Ea]€‰k@hM~@cq@k@{•c}‰zO@7bP¢jl @R¢S {`~ ¤ÚJGD-xˆˆ€ˆZ€‰Ãx h FÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿK|í¸‡Ã=íˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Y _SQ"dE|@t@7M@ RE@SRW‰gZ€•`@UWPHpv@€aGL€¤µ€ƒMr‰qvBeB…Du[ yctbÊsx®uo «A®DC®G€C…B€d…J@M@@Tr@}€…n;€X ¤à2B {\T ZYX a@Sz_@c@n€ˆmÅq N Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2f{AXÅZ@¨kˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Y J= MEGA KILL!W€ƒhšlm`S€•`€wEZNZ P›{O[ Q q@N@@M¿GPQÊ€‰/J RO…NXK@ bWFQV@ZP…]@e@\@Bs@{®z<@²reH €i@l@k@o@n€zy€q@`@e@crsp®|@u®w®…}®z®I@¢y Tÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿt }¿~æT¢=$:e†Ž”†Ž”> ÀÙ> ÀÙ> ÀÙ> ÀÙ> ÀÙ> ÀÙ> ÀÙ†Ž”­-¤%n†Ž”­-¤%n†Ž”­-¤%n†Ž”­-¤%n†Ž”­-¤%n†Ž”†Ž”­-¤%n†Ž”‰žtȉžtȉžtȈ> £Y‰žtȆŽ”> ÀÙ> ÀÙ> ÀÙ¤°²‘¿!> ÀÙ¤à5Iœ´> ÀÙˆ> £Y•'n 6ˆ> £Y‰žtÈ> ÀÙ‰žtÈ> ÀÙ¤Áz`Ì=ƒxáˆ> £Yˆ> £Yˆ> £Y°²‘¿!> ÀÙš;¬º(š;¬º(…{#U¿š;¬º(…{#U¿š;¬º(…{#U¿š;¬º(…{#U¿…{#U¿š;¬º(…{#U¿…{#U¿š;¬º(…{#U¿ÅG©™Àš;¬º(…{#U¿š;¬º(…{#U¿éÿF×zš;¬º(…{#U¿š;¬º(…{#U¿ì1Úȃxƒx…{#U¿ƒxƒxƒx²ÃflUƒxƒx°²‘¿!ƒx°²‘¿!°²‘¿!ƒxƒx°²‘¿!ƒx°²‘¿!ƒx°²‘¿!ƒxƒxƒxƒxƒxƒxƒxƒx…{#U¿ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx¢=$:e> ÀÙ> ÀÙ> ÀÙŒm¢‡…{#U¿Œm¢‡…{#U¿Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡†Ž”…{#U¿…{#U¿™*†Ž”…{#U¿™*…{#U¿™*…{#U¿™*†Ž”†Ž”«©€'™*Œm¢‡†Ž”…{#U¿Œm¢‡™*†Ž”…{#U¿™*Œm¢‡™*…{#U¿™*†Ž”†Ž”«©€'™*Œm¢‡†Ž”…{#U¿Œm¢‡™*†Ž”…{#U¿™*Œm¢‡™*…{#U¿™*†Ž”†Ž”«©€'™*Œm¢‡†Ž”…{#U¿Œm¢‡™*†Ž”…{#U¿™*Œm¢‡™*…{#U¿™*†Ž”†Ž”«©€'™*Œm¢‡†Ž”…{#U¿Œm¢‡™*†Ž”…{#U¿™*Œm¢‡™*…{#U¿™*†Ž”†Ž”«©€'™*Œm¢‡†Ž”…{#U¿Œm¢‡™*†Ž”…{#U¿™*Œm¢‡™*…{#U¿™*†Ž”†Ž”«©€'™*™*†Ž”†Ž”‰žtȉžtȉžtÈ…{#U¿‰žtÈ…{#U¿‰žtÈ«©€'•'n 6«©€'†Ž”†Ž”‰žtȈ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Y‰žtȉžtÈ«©€'†Ž”«©€'©ôªª‘†Ž”«©€'©ôªª‘†Ž”­-¤%n¢=$:eˆ> £Y…{#U¿> ÀÙŒm¢‡> ÀÙŒm¢‡ˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Y…{#U¿†Ž”ˆ> £Yˆ> £Y…{#U¿†Ž”«©€'ˆ> £Y…{#U¿†Ž”ˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Yˆ> £Y†Ž”­-¤%nˆ> £Yˆ> £Yˆ> £Yˆ> £Y…{#U¿†Ž”ˆ> £Yˆ> £Y…{#U¿†Ž”ˆ> £Yˆ> £Y…{#U¿†Ž”ˆ> £Yˆ> £Yˆ> £Yˆ> £Y> ÀÙ> ÀÙ> ÀÙŒm¢‡…{#U¿Œm¢‡Œm¢‡> ÀÙ> ÀÙŒm¢‡…{#U¿…{#U¿Œm¢‡…{#U¿Œm¢‡ˆ> £YŒm¢‡Œm¢‡†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿Œm¢‡Œm¢‡Œm¢‡…{#U¿Œm¢‡ˆ> £YŒm¢‡Œm¢‡†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿Œm¢‡Œm¢‡‡œÔX‡œÔX†Ž”­-¤%n…{#U¿›j\º¥†Ž”†Ž”> ÀÙŒm¢‡†Ž”«©€'©ôªª‘†Ž”«©€'©ôªª‘†Ž”«©€'©ôªª‘†Ž”«©€'©ôªª‘†Ž”‰žtȉžtȉžtÈ…{#U¿ˆ> £Y‰žtÈ…{#U¿ˆ> £Y‰žtȈ> £Y›j\º¥›j\º¥…{#U¿›j\º¥†Ž”†Ž”›j\º¥›j\º¥†Ž”›j\º¥›j\º¥›j\º¥†Ž”›j\º¥…{#U¿> ÀÙŒm¢‡†Ž”‰žtȉžtȉžtȉžtÈ›j\º¥›j\º¥Ê3e Ð…{#U¿†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿›j\º¥†Ž”Ž©Ù«Èréæå›j\º¥›j\º¥…{#U¿…{#U¿ˆ> £Y¤xp¬Û¤xp¬Û…{#U¿…{#U¿ˆ> £Y›j\º¥…{#U¿†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿›j\º¥›j\º¥…{#U¿†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿›j\º¥…{#U¿†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿›j\º¥›j\º¥›j\º¥> ÀÙŒm¢‡‰žtÈ…{#U¿ˆ> £Yˆ> £Y†Ž”Ž©Ù«†Ž”Ž©Ù«³& ‰žtÈ…{#U¿‰žtÈ…{#U¿ˆ> £Y‰žtÈ…{#U¿> ÀÙŒm¢‡‰žtÈ…{#U¿ˆ> £Yˆ> £Y†Ž”Ž©Ù«†Ž”Ž©Ù«³& ‰žtÈ…{#U¿‰žtÈ…{#U¿ˆ> £Y‰žtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtÈ…{#U¿…{#U¿…{#U¿éÿF×z…{#U¿…{#U¿ì1ÚÈ> ÀÙ¿¯Ð“œŒm¢‡¿¯Ð“œŒm¢‡Œm¢‡¿¯Ð“œ¿¯Ð“œ¿¯Ð“œ¿¯Ð“œ¿¯Ð“œŒm¢‡‰žtȉžtÈ…{#U¿…{#U¿> ÀÙŒm¢‡Œm¢‡Œm¢‡‰žtȉžtÈ…{#U¿…{#U¿> ÀÙ…{#U¿…{#U¿Œm¢‡Œm¢‡Œm¢‡†Ž”Œm¢‡Œm¢‡Œm¢‡†Ž”Ž©Ù«…{#U¿¤f{AXŒm¢‡Œm¢‡Œm¢‡†Ž”†Ž”­-¤%n…{#U¿Œm¢‡…{#U¿…{#U¿…{#U¿…{#U¿‰žtÈ…{#U¿‰žtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtÈ…{#U¿‰žtȉžtÈ…{#U¿‰žtÈ…{#U¿‰žtȉžtÈ…{#U¿Œm¢‡Œm¢‡…{#U¿†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿…{#U¿…{#U¿Œm¢‡‰žtȤxp¬Û¤xp¬ÛŒm¢‡‰žtȤxp¬Û¤xp¬Û‰žtȤxp¬Û¤xp¬Û…{#U¿…{#U¿…{#U¿…{#U¿‰žtÈ…{#U¿…{#U¿…{#U¿‰žtÈ…{#U¿Œm¢‡Œm¢‡…{#U¿Œm¢‡‰žtȤxp¬Û¤xp¬Û†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿…{#U¿…{#U¿Œm¢‡Œm¢‡†Ž”‰žtȉžtȉžtÈŒm¢‡‰žtȉžtȉžtȉžtȉžtȉžtȉžtȉžtȆŽ”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿…{#U¿Œm¢‡†Ž”Œm¢‡†Ž”Ž©Ù«¢=$:e‰žtÈ…{#U¿Œm¢‡†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿…{#U¿Œm¢‡‰žtÈ…{#U¿Œm¢‡†Ž”Ž©Ù«†Ž”Ž©Ù«³& …{#U¿…{#U¿Œm¢‡†Ž”Ž©Ù«‰žtȈ> £Y…{#U¿†Ž”Ž©Ù«³& ˆ> £Y†Ž”Ž©Ù«³& ˆ> £YãR@G¢†Ž”Ž©Ù«³& ˆ> £Y†Ž”Ž©Ù«³& ‰žtȉžtȉžtȉžtȉžtȆŽ”Ž©Ù«³& †Ž”Ž©Ù«³& ‰žtȉžtÈ…{#U¿‰žtÈ…{#U¿¿¯Ð“œ> ÀÙŒm¢‡Œm¢‡Œm¢‡†Ž”†Ž”Ž©Ù«¢=$:e}¿~æT¢=$:e†Ž”> ÀÙ> ÀÙ†Ž”Ž©Ù«†Ž”Ž©Ù«> ÀÙ> ÀÙ> ÀÙ> ÀÙ†Ž”Ž©Ù«Ê3e ÐÊ3e ÐÊ3e Ð> ÀÙ†Ž”> ÀÙ†Ž”Ž©Ù«†Ž”Ž©Ù«> ÀÙ†Ž”Ž©Ù«¤°²‘¿!†Ž”Ž©Ù«¢=$:e¢=$:e¢=$:e> ÀÙ¢=$:e> ÀÙ†Ž”Ž©Ù«¤à5Iœ´> ÀÙ†Ž”Ž©Ù«¤à5Iœ´> ÀÙ> ÀÙ†Ž”Ž©Ù«> ÀÙ†Ž”Ž©Ù«> ÀÙk-4CI]The game ended in a tie!j] SmartCTF 4C<*ÿ=*€ÿR*ÿÿÿ>*€€€xÓe"d"c"b"a$?`$@_$€@^$A]"\"[ÓZvÓYÓWÓVÓS$€?R$`@MÓuÓsÓJIHGÓEÓDÓCÓAÓ@Ó|ÓtÓRÓkÓBX@l[[®yA®*s +.&"'","-")* ;* ÿ"c· Œ¢ø^ØiëiûiI@ rkJ@S@ T@ F €…S@ I €‡@7] €LqU |€‰V~_f€K[j€V€rs€zo@b@b@e@k®*Õg f zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2[i Ü~>Õôð@ƒxƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx> ÀÙ™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*™*ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒxš;¬º(ƒxƒxš;¬º(ƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒx•'n 6•'n 6…{#U¿ƒxƒx•'n 6ƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒx•'n 6ƒxƒx•'n 6ƒx•'n 6ƒxƒx•'n 6ƒx•'n 6ƒxƒx•'n 6ƒx•'n 6ƒxƒx•'n 6ƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx•'n 6ƒx•'n 6ƒx•'n 6ƒxƒx•'n 6ƒx•'n 6ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxƒxƒxƒx†Ž”ƒx²ÃflUƒxƒxƒx²ÃflUƒxƒxƒx²ÃflUƒxƒxƒx²ÃflUƒxƒxƒxƒx†Ž”ˆ> £Y r]Wheres* —÷v*€ÿw*ÿÿÿO],+SmartCTF Record Holders [Numbers per Hour]P]WhoQ]WhatS]Whenïk j 4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2Fkj2,âïJEBm…{#U¿…{#U¿…{#U¿> ÀÙŒm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡…{#U¿…{#U¿š;¬º(š;¬º(…{#U¿š;¬º(…{#U¿š;¬º(…{#U¿…{#U¿…{#U¿…{#U¿> ÀÙ> ÀÙŒm¢‡Œm¢‡Œm¢‡Œm¢‡…{#U¿…{#U¿ˆ> £Y†Ž”ˆ> £Y†Ž”ˆ> £Y†Ž”ˆ> £Y†Ž”ˆ> £Y†Ž”ˆ> £Y†Ž”š;¬º(ƒxƒxš;¬º(ƒxƒxƒxƒxƒxš;¬º(ƒxƒxƒxƒxƒxš;¬º(ƒxƒxƒxƒxƒxƒx†Ž”š;¬º(> ÀÙ> ÀÙƒxˆ> £Y•'n 6ˆ> £Y•'n 6ˆ> £Y•'n 6ˆ> £Y•'n 6ˆ> £Y•'n 6ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx²ÃflUƒxƒxƒxš;¬º(©ôªª‘š;¬º(©ôªª‘š;¬º(©ôªª‘š;¬º(©ôªª‘²ÃflUƒx²ÃflUƒx²ÃflUƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx†Ž”†Ž”ƒx> ÀÙ…{#U¿…{#U¿ƒx…{#U¿ƒxƒxƒx…{#U¿ƒxƒxƒxƒxƒxƒxƒxƒx…{#U¿ƒxƒxƒxƒxƒxƒxƒxƒx…{#U¿ƒxƒxƒxƒxš;¬º(…{#U¿©ôªª‘ƒxƒxƒxš;¬º(…{#U¿©ôªª‘ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒx†Ž”…{#U¿…{#U¿> ÀÙ…{#U¿…{#U¿Œm¢‡Œm¢‡š;¬º(…{#U¿©ôªª‘š;¬º(…{#U¿©ôªª‘š;¬º(…{#U¿©ôªª‘ƒxƒxƒxƒx…{#U¿ƒxƒx…{#U¿ƒxƒxƒx…{#U¿ƒxƒxƒxƒxƒxš;¬º(…{#U¿©ôªª‘…{#U¿…{#U¿…{#U¿…{#U¿ƒxƒxƒxƒx> ÀÙ…{#U¿ƒx…{#U¿ƒxƒxƒxƒxƒxƒxƒxƒx…{#U¿ƒx…{#U¿…{#U¿ƒxƒxƒxƒx…{#U¿ƒx…{#U¿ƒxƒxƒxƒxŒm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡ƒx†Ž”…{#U¿…{#U¿Œm¢‡…{#U¿Œm¢‡Œm¢‡…{#U¿ƒxƒxƒx…{#U¿ƒx…{#U¿…{#U¿ƒxƒxÂ#fInƒx…{#U¿…{#U¿…{#U¿ƒxƒx…{#U¿…{#U¿…{#U¿…{#U¿ƒx…{#U¿ƒxƒx…{#U¿ÅG©™Àƒx…{#U¿ÅG©™Àƒx…{#U¿ƒxƒxƒxƒxƒx…{#U¿ƒxƒx…{#U¿ƒxƒxŒm¢‡ƒxƒxŒm¢‡ƒxŒm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡…{#U¿Œm¢‡Œm¢‡Œm¢‡Œm¢‡Œm¢‡…{#U¿Œm¢‡Œm¢‡…{#U¿…{#U¿ƒxŒm¢‡ƒxŒm¢‡ƒxŒm¢‡ƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxƒxŒm¢‡ƒxƒxƒxƒxƒxƒx†Ž”Œm¢‡Œm¢‡ÚOXˆ> £YŒm¢‡ÚOXŒm¢‡> ÀÙ> ÀÙ> ÀÙkj2,â> ÀÙ> ÀÙˆ> £Yˆ> £Y V]Pts{]FragsZ] / \] More...^]b`[ SmartCTF 4C | {PiN}Kev | {DnF2}SiNiSTeR | March 2005 | http://www.dnfclan.com/~sin/SmartCTF ]R*ÿÿÿ>*€€€`* d*ÿÿ<*ÿ=*€ÿa*@b* @c*ÿÿÿe*ÿÿÿg*ÿÿi*€€€j*ÀÀÀu…lo€@×o V @ÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿ2 qTœa-×Xu6艞tȉžtÈ…{#U¿›j\º¥‰žtȉžtÈ…{#U¿ w]10had the flag but disconnected. Flag is dropped!oÓcÓÃ_ T yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ r½ƒ!°ÃŒ”mó‡œÔX‡œÔX‡œÔX‡œÔX‡œÔX‡œÔX‰žtÈ X…jFv…swxy€•b €{€ü\ Qxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2}¿Yõüv`+…{#U¿…{#U¿¤žÒxxœ mÝThis is just TOO EASY for]•Æ]•ÆN@@@@A@B@C@D@E@F@~G@I@LMNxHQRYO@W XVQYJ B € @q €^€^@Tbcd@e@f@g@h@j…k…nopA@j@^@t@u@]@P€M €àx…y…J G €C €aX€g€@@€A€'€$€uÊr SBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2FŒæ„Ê^¦Mˆ> £YžÒxxœžÒxxœà5Iœ´žÒxxœà5Iœ´žÒxxœãR@G¢åIò&/žÒxxœ†Ž”žÒxxœžÒxxœžÒxxœžÒxxœžÒxxœžÒxxœžÒxxœ†Ž”žÒxxœˆ> £Yˆ> £Y°²‘¿!žÒxxœ†Ž”ˆ> £YžÒxxœ rK€Y€0h€f[€\O…åYïkfwZ*8šY,p¨YÑZ´!fšY,¨Z´, žß  @Ð"##½Crc"Ÿw.ž"ß*.ž"ßmÌocyU.ž"ßmðocyUæ-Ò.ž"ÑÆ ~ocyUÙ‚wcy wy*‘‚°¯.ž"‹§.ž"ö?, ›o&¥.ž"ø.ž"# f.ž"øc¦.ž"ø%.ž"ö.ž"‹§î.ž"ø%@w.°"ß*.°"ßû.ž"‹§»œry"Ÿ.ž" ù%cÒ"ocyU»Ò"ocyU  äXO%ï\éO䨛:‹Ä:$¨›<%¥chš<,ÿ<%\›:Ï:$a(ea€?'¨”—c,<¡<,‘—<,ÿ<,ÿ¨¨šc,<<,M„š:‹Ä:$ š:Ï:$)—:‰@,|Jbget IpDrv.TcpNetDriver NetServerMaxTickRate@$Yó-[-M-[-M‰ó-X-]-X-]¹ó-U-\-U-\M‚-z.­‹“-â6‚‚‚.­‹“-Ç —.­‹“Ö%T„š.­‹“Ã.­‹“Äš:‹Ä:$ ˜.­‹“Í%-O'O‹Ô6wO*‚‚Oa/!_Oa/!y.ˆO-æ-O(6OOÛÂM-O-z'e UV€ÂYWnÁãžœ›:‹Ä:$ír*/a0 6610Dr* í‚-wS*°Sã içp¨Notified HUD (clientside,WSÙ) to use SmartCTF ServerInfo.!-L -Æ~œw`*=-s-s'L`œ‚{`ÇÓ -r-r'`"bmutate SmartCTF ForceStats ZIL¨ÀàØ(„r.ˆI*I-¾ -UIUppRunning SmartCTF [. Type 'Mutate SmartCTF' in the console for info.­<&aÍÌL='Ö-T, Á@Ò ñ Î] CPlÕñ‚r`*` ÊÚB.°`ß@.š`Çt`ŸdBÈA-[9%A–9, Är9@€·*A ‚9@€·-Í!9@€·-Î77‚‚‚w9@€·Â*0š:9@€·˜:t˜.›9@€·¯t¯,9@€·Âa/!Xw9@€·ú*|9@€·úÍggw9@€·ç*|9@€·çÐœz||Nameless Area ±$­ ±$Ùš:t˜% —mí —n ¨d( œ aÐ|PE^B-ØOD ½ä²««BÜBÛ œ¯ œ«?BÿOD¯ ½«?,@BÿOD¯ ½«?,€Bÿ ?”¯¯ œP?,®?““O,, ¬¯?, E?, aÑ|•š: ±:$ —o© —o 8”¯¯¯¯ œP?,?, ?,?““O,, š:t˜% ¼ í€?4 ¼ Ú€?A¥9›¿›<% ±$Å—<&6á —=“,ÿ<6î —=“,ÿ<6Ø —=“,ÿ<ê ±$ —o #”¯¯ œ?,€?,€A ¼ u €? ¨d œ aÐpPE /”¯¯ œP?,®®€A?,?,€ aÑp ±$ïwÜ*Ü C   ]€@€@_N"7Òe]UN6zê]&0]€]“}]& ]zê]&.]€]“}]&] ,`~9Ûuª ~R$Ü–:R,@: $R`r:*ܵ„r~*;±.…:£¬.…~£¬~:î„ru*—:4u4u:'„rb*—:\b\b:`„ra*—:XaXa:™„rE*—:UEUE:Ò„rD*—:@D@D:‹R+.…~£,¬¯‹§?»?%‚±¬¬,?6-(i(±¯‹§?»?,6-(iD¬¬,6F(i´6J(i‹Ð.«‹“ G6B(iG.…u£,¬¯‹§?»?p‚±¬?u4,?6-(l(±¯‹§?»?,6-(lD¬?u4,6F(l´6J(l‹Ð.«‹“ G6B(lG.…b£,¬¯‹§?»?»‚±¬?b\,?6-(_(±¯‹§?»?,6-(_D¬?b\,6F(_´6J(_‹Ð.«‹“ G6B(_G.…a£,¬¯‹§?»?‚±¬?aX,?6-(g(±¯‹§?»?,6-(gD¬?aX,6F(g´6J(g‹Ð.«‹“ G6B(gG.…E£,¬¯‹§?»?Q‚±¬?EU,?6-(b(±¯‹§?»?,6-(bD¬?EU,6F(b´6J(b‹Ð.«‹“ G6B(bG.…D£,¬¯‹§?»?œ ‚±¬?D@,?6-(a(±¯‹§?»?,6-(aD¬?D@,6F(a´6J(a‹Ð.«‹“ G6B(aGb f?O±˽Ó@.«‹“?‹Ô®w?*—‚?-¾>„ro*1±?Ÿ¬oŸ¬o???Û-@ÔÓ]@ß®‹§@@?‹Ô¼w?*r.ˆ?•wr*r-Ï'\rrorÛ*prÛor  î 'r}?q!w??Û@l9 iab©c€n6Tº¾A·C úAô(6œAô86œ[ô6œa6ó¥r[{[}Âr[z[}ßr[}[wür[x[u[ Ó6¨[6aÐPlayerMOT«¬ðB€D6½_$dfš™™=eš™>mš™™=F«f6œL«¬¯¯¯€?fem?,6œQ®®FL«e6œx«¬ A€D6œf®¬¯BO?,«¬€@€D6œL«¬ A€D6œR«¬ @€D6œH®BR!6 Åidd‚«¹ç[´%.«‹“ÜÈ&.«‹“ÜÈ-i'·„-b6‚‚-S -t.­‹“-â-b(·-iO'È-i9ãwù*ùd( ×pLP€–L,Á,  €ëj5u߉™GZ|€5,SmartCTFK Ÿ¯ „|5, , ShowStats|5, ,Statsj  wj*jIWó|5, , ForceStatsj  ðwj*j?W¶„„„|5, ,Rules|5, ,Points|5, ,Score|5, ,BonusÊ-^ _¨¨SmartCTF Score Settings: - Cap/Assist:S’,Apts divided over all FC's by time& S¨¨¨¨SmartCTF Score Settings: - Cap:S’,Apts, Assist:Shpts. p¨¨¨¨- Cover (Kills while defending FC) Bonus :Slpts each. AndSlmore pts each if FC caps. S¨¨¨¨- Seal Bonus:Skpts each, andSkmore pts each if FC caps. °- Seals (Kills while sealing off base) are defined by: 1) Your FC is on your team's side of map. 2) Your flag is not taken. 3) You kill someone on your side of the map. 訨¨¨¨¨¨¨¨- Flagkills:S’,ipts. Flag Returns in base are worth"jpts, in mid"kpts, enemy base"opts, VERY close to capping"qpts. *- Additional features: See Readme!W½|5, ,ForceEndU‚ Ÿ-×›:‹Ä:$ CYou need to be logged in as admin to force the game to end.º¨ Ÿ´forced the game to end.-b'.«‹“rforcedW‹|5, , ClearStatsc‚ Ÿ-×›:‹Ä:$ HYou need to be logged in as admin to be able to clear the stats.ˆ Stats cleared.W HppSmartCTF by {PiN}Kev_HH. SmartCTF [ by {DnF2}SiNiSTeR. Q- To toggle stats, bind a key or type in console: 'Mutate SmartCTF Stats' 6- Type 'Mutate CTFInfo' for SmartCTF settings. G- Type 'Mutate SmartCTF Rules' for new point system definition. 8- Type 'Mutate SmartCTF ForceEnd' to end a game.W-S ?- Type 'Mutate OverTime ' for Overtime Control.5j|€5,CTFInfo0˜-J0¨0Capture¶-S0¨0AssistÓ-K0¨0Savedï-T0¨0Lead -M0¨030SecLeft+ z00All offI z€0& 00&| š:e&¨Covers§ š:e,¨CoversÉ š:e,¨Coversù š:k&¨Coversprees) š:k,¨CoverspreesP š:k,¨Coverspreesz š:T&¨Seals¤ š:T,¨SealsÅ š:T,¨Sealsï š:h&¨Saved š:h,¨Saved: š:h,¨SavedU zAll offs z€& &7ž -V7¨7AssistBonusÀ -E7¨7SealRewardã -I7¨7CoverReward -~7¨7LongRangeKill# z77All offA z€7& 77& ¨- Sounds:0 ¨- Msgs: ¨- Private Msgs:7 ¨- bFixFlagBug:T-| D¨p¨- bEnhancedMultiKill:T-I, Broadcast Level:RJ #¨- bShowFCLocation:T-M´ -` V¨¨p¨- bSpawnKillDetection: True, Global Msg:T-X, Penalty:Septsá  $- bSpawnKillDetection: False B¨¨- Overtime Control:T-S( Type 'Mutate OverTime' ) 2- Scores: ( Type 'Mutate SmartCTF Rules' )55|€5,OverTimeø.­‹“-â HNot in Tournament Mode: Default Sudden Death Overtime behaviour.5­-S OOvertime Control is not enabled: Default UT Sudden Death functionality. FAdmins can use: admin set SmartCTF bEnableOvertimeControl True5f|€5, OverTime OnK‚ Ÿ-×›:‹Ä:$ AYou need to be logged in as admin to change this setting.c-t'b p,5 |€5, OverTime Off‚ Ÿ-×›:‹Ä:$ AYou need to be logged in as admin to change this setting.-t(b p,5‚„ Ÿ-ך:‹Ä:$ %Usage: Mutate OverTime On|OffÃ-t *Sudden Death Overtime is DISABLED.ÿ 3Sudden Death Overtime is ENABLED (default). -¨Remember 'Disabled' Setting:T-Oë5  mÐ9˜+$% *& * eg!Þ+H<šW%W,&š\%\,=´k?%kfff?T´l?%l€?y‚šW, š\,r$r$M¯¬¯LH?\«R?“\&Þrg*Cô(gœéCgg¨CgaÐFlagKls: 00_z`D¯¯M_Rb«zk{?ú&D«bš™™>P«blJ«?Wbþ—%%ÆË&%ÆËC¯«?%%ÆË®®OJPP:C¯«?&%ÆË®®OJPP ØgGzdG %b &Ób ,,Ùb :,Ôb H,pb V,Õb ÿÿÖb  oI6¾á–ŸY$–:Y,@Z $YLrZ*“›:.…Z£˜IZM%ZS%‹Y w3  ¥Y±¯‹§?o?F, WT0oD‹§DTQN±$%–, ³r’*&’ár*ƒJ’¯;š:’˜%DFQzK]DQNzL—z? š::’˜i%-Þ(¨[±$ûš:’˜%—M—NaÐfAN±$ ”¯?x¯?f-è D®L«x?,®N«f?,±$ ”¯?x¯?f-š:’˜%2À Ê®L«x?,®N«f?,€?h2À Ç®L«x?,®N«f?,€?±$'”¯?x®®?Nf-è D®L«x?,®C«L?,±$—z#”?¯?¬¯?, N?,gš:’˜%¼ ä?€¼ ã?¨C<aÐSD:’˜%ÆÈJ/±$,”®?H¯?¬¯/N?,2aÑSD:’˜%ÆȨ[ ”¯®?LA?aÑf¨[aÐpebsK'”¯¯®?LAs?aÑpeb—Y¨aaÐTESTK/D”®®®?HJ«?,R®?¬¯N«/?,?,Zú&D¬‹§?,<Y%W%S%R%~%ß–~, r~’*ßÕš:~’˜:’˜\&~’tr\*Õ¡Y~’ê¡W:~’å¡S\^¡R\`¥~÷†›:’˜%ÆË%Y‘Y:’˜%ÆËW‘W:’˜%ÆË›šB%S%ºSûD«¬?S?B?,d%,dÏšD%R%îRûD«¬?R?D?,d%,dppppPING:SY PL:SW%aÑK”®®®?HJ«?,R®®?¬¯N«/?,?,/pTM:SZº ›S%pp¨SB:SS%ä ›R%pp¨AM:SR%aÑ-Þ'¡D®®NfL:’˜i$¨AaÐTestK/ ‚›::’˜i,8±®®®?OJP¯½«/?,—zaÐcz/X š:’˜&4”¯®?Lz¯½«/?,‡ &”?¯½«/?,`aѨ¨¨[S“:’˜%ÆË::’˜ac]:’˜i$22›::’˜i,{ r’Â*-Þ(—w±$”??ø ‚&-Xw’Ï*¼’Ï? ¼ a ?”??—\¼ ù€?±$-Þ'”®?H?¨[à ’-×—w2š’¯F¯—[2—zj—aÑ’´!aÐ’´zs—R¨aaÐTESTs/?”®®®?HzR®?¬¯O«/?,?,[›@%ppHS:S@’›^%p¨SB:S^É›`%p¨AM:S`çz€& &aÑZú&‘D¯®‹§?F»?’»,<v´®?4’É?%W·W«¬?4®?4’É?,dF”®®®?HzR®®?¬¯O«/?,?,/,aÑppppTM:SZ EFF:SûDW%,d%”?®?H’-ïaÑBOTš:’˜:F˜ ”?®®?H/!aÑ€W.Â’É,–—YpPI:S’êj—},pP:S’ê“—},S’êaÑ ”?®®?H/ppPL:R’å%(—},ppL:R’å%W—},pL:R’å…—},pR’å%aÑ­w’Â*—w”??’Âa/!X¼ â€?­]’Âa/!L¼ Û€?­”š:’˜%¼ í€?­¼ Ú€?¨[—j#aÐSD’¬z/ ”¯®?Lz?aÑSD’¬¨[#aÐpS4bsN'”¯¯®?Lzs?aÑpS4b¡DO¨C–š:r& &&Caps: \p &,Assists: Cq &,Grabs: ]v ,&Covers: Xu—D% ,,Seals: \D\ ,,Deaths: D’Ér ,,FlagKls: Us &&Caps: \p &,Covers: Xu ,&Grabs: ]vt—D% ,,Seals: \D± ,,Deaths: D’Ér ,&Assists: Cq ,,FlagKls: Us¡D®JP[š:’˜%QfN‹:’˜a¥“nq qHQœëfT$d–:T,@2 $TLr2*dK.…2£[.‰K£Z›:K˜Hú‚w2*—2S%¸K¬?2Sk|‚-Ew.ˆ[*.ˆ[uppppYou killed S2S people sealing off the base. You get S2Sk bonus pts!úw‹“ª*‹“ªFseal_bonusSK¯S2SS2SkZ‚w2*—2M%¸K¬?2MlÛ‚-Iw.ˆ[*.ˆ[qppppYou killed S2M people covering your FC. You get S2Ml bonus pts!Zw‹“ª*‹“ªGcover_bonusSK¯S2MS2Ml‹T €ætP@ôrf : rl Ô6Pa/!f.›d‡]Pa/!W.›P‡æPdlLHd¼r*æPdlLHd‚.­‹“-â -zæPdlLHdL ¹%¶rd.‰£=“:$:¸“š:&2: ¯‹§:mÁ1: ¯‹§:mw : ýww*¥w\Ó-Tr´¯:.«‹“ÜÈ?&“&:.«‹“ÜÈV$Ú´:.«‹“ÜÈ“&:.«‹“ÜÈV$^‹ÔÓw^*¼‚w.ˆ^*^-¾l‚š:V&!š:^Ÿ˜:.ˆ^  K,¼¼‚š:V,$š:^Ÿ˜“&:.ˆ^  K,^^Ûî/‚-Jw.ˆ: */‚-T š:V&.ˆ:  K%cš:¸%U‚-T š:V&V‚-T š:V&$Q:¸% *& *6,: d,ard.‰£=“:$:¸3š:&2: ¯‹§:ma1: ¯‹§:m: Õ,Òrdñ=“:$:¸:m‹§: ñ: ˜,•rdñ=“:$:¸:m‹§: ñ¸¬?qw : •ww*¥w]: œ& ¡, 7 ,Q‹ÔwQ*ð„Q-¾Qa/!zQQÛº4 rdQ šL&0 ‚-t<°áØ ¶“&:¸{ ¶?„¸¬qôw‹“ª*‹“ª;flag_return_closesaveS¯R¸- “&:¸.È‹“Ôà-áš‚š:h&w.ˆ£*.ˆ£  ’,,@åÆš:h,  ,ååš:h, ,- ‚-Kw.ˆ£*.ˆ£  K, Þ =“:$:¸¸¬oÛ w‹“ª*‹“ª;flag_return_enemybaseS¯R¸  ¸¸¬k~ w‹“ª*‹“ª5flag_return_midS¯R¸ ¸¬j w‹“ª*‹“ª6flag_return_baseS¯R¸6:¸=“:$:¸: ÿÿæPdlLHd v…n€@uqß#n¨´`?%m1m«¬q`?,dnûDm%,došn,d¨¨(Solocap,SDqsec.)¦¨¨p¨(CarriedSn% of the time:SDqsec.) y^ÄAl¨S›:^&@$V$S–:V, :VD*:Vs‹V¦›:^%{$V$¦–:V, :VC*:Vt‹Vo z…|!M&u6á!—Yr6î!—Yr6Ø!—Yr!±$!¨!ó!aÐScoreboard:fh!%”¯¯!œf?,€A!aÑScoreboard:!'”¯!œf®€Ah! aÑDefault!,”¯!œf®€A«?,h! aÑSmartCTFÝY-k!1”¯¯!œf?,®€A«?,h!,”¯¯!œf?,®€Ah!¼ þ€?!±$s±¯‹§YG?,Yr$ s Z ('RÌ¡ED®H«®MR?“A&¡GD«b?“B&Z—xZ”?E?GZaÑ@ZaÐSgX~Z ”¯®?E_X?GZ aÑSgY—g%aD«<_À?g —a,ÿa,ÿ6áZ—=“:6áxa6ØZ—=“:6ØxaWYgZ3”®®?E_R®?G¬¯z{?,Zè w ?W{ {DU“¯d¦Zh$$=–:$, ¸Y:$t‹$$$œ–:$, _‚w:$C*w:$C& t :$Cºwt*¥tC-^Ý´Y?%__«¬:$tY?’,AZúD_&¸:$CŸ¬?Zðw.ˆ:$C*»-V.ˆ:$CO¨ppYou get SZ bonus pts for the Assist!:$tYð‚-S-D.ˆ:$C  K&\w‹“ª*‹“ª4Flag_assistS:$CŸ¯S%’’r:$C& q-^š´Y?%_¿_«¬:$tY?’,AZúD_v¸& Ÿ¬?“Z,n‚-Vw.ˆ& *.ˆ& J¨ppYou get SZ pts for the Capture!:$tY’¸& Ÿ¬?A‹$E$ B CV_N\¦Nh'$=–:', ¸L:'s‹''$œ–:', _‚w:'D*w:'D% v :'Dºwv*¥vC-^Ý´L?%~~«¬:'sL?’,ANúD~&¸:'DŸ¬?Nðw.ˆ:'D*»-V.ˆ:'DO¨ppYou get SN bonus pts for the Assist!:'sLð‚-S-C.ˆ:'D  K&\w‹“ª*‹“ª4Flag_assistS:'DŸ¯S%’’r:'D% q-^š´L?%~¿~«¬:'sL?’,ANúD~v¸% Ÿ¬?“N,n‚-Vw.ˆ% *.ˆ% J¨ppYou get SN pts for the Capture!:'sL’¸% Ÿ¬?A‹'E$ ÿ}m5i¼M„r&* rY*:w>*> 5mK*-Ä( mY-k3mš†r>*3mš> 5mº—:Yr%Mm ä~%Pö »r>*¥h:/w>*a(¹¹—h,çGiven up. Using the default CTF ScoreBoard instead.!°r>*>a ï*ç¨Spawned asV>!a( @ :3ø´ r&*/a0 &10Ew&*Y&  *³‚w&*r&B*çUnable to identify original ScoreBoard type. Retrying in 1 second.! 7‚w&*r&Bð>a ï*çCannot use itself. Using the default CTF ScoreBoard instead.! ²‚w&*w&B*>a&B*ç¨Determined and spawned original scoreboard asV>! A c2CYë_„„rc*c-¾8‚cŸ-ÍcŸ-Î t™:{, {$j$¾–:j, ´rc:jC¸:jt] ‹j|:{Cc:{t]‹{ à>@~à*.ˆ£%.š*ÇF*Ÿoœÿÿÿ{.®ÑLadderFonts.UTLadder22 ®z.®ÑLadderFonts.UTLadder20 ®}.®ÑLadderFonts.UTLadder18 ®x.®ÑLadderFonts.UTLadder16 ®w.®ÑLadderFonts.UTLadder14 ®u.®ÑLadderFonts.UTLadder12 ®:|r>*a€?' F J1-aWë_„„rJ*J-¾8‚JŸ-ÍJŸ-Î t™:@, @$f$¾–:f, ´rJ:fD¸:fsZ ‹f|:@DJ:@sZ‹@ €@K€lgK,v<%šg,¨had ang:¨had ag  x3qD¨Ui3-ý'3¨A3—P3aÐTestVV3 ”¯3½V]¨¨¨Playing‹Ðon%òð—&|%]p¨¨](TR:S&|)3aÑ]ׄ-é—*Çí%-é'e˜*Çí%apè00:00Ôq‘*Çí,<ED­?*Çí?,<apppèq:EzE*ÇÙq‘E,<‘q,<E“Eq,<q“q,<apppppÐ:q:E3%”¯3½«?,V3&aѨ¨¨Current Time:[|a3aÐbV{3±$3—[3%”¯3½«?,V3aÑb3-ý( L N»U¨4wNú*KNúÍjhwNç*KNçÐj(š:}%›~ëKREDÿÿÿÿ¦›~ëKBLUEÿÿÿÿ }€€@êD I#2ÊàÒImzyxm -%Þ J&I  ç 'Þ h,I  ï 'Þ †,I  è 'Þ ¤,I  ð 'Þ Â,I  é 'Þ ÿÿI  ê 'Þ !K ]ßO U?RA}  UK‚|a/!D w}*¥}^|‚|a/!\ w}*¥}`)‚‚-` w}*µ}c?%)„„„„|a/!k|a/!D|a/!\|a/!X|a/!Y}cßU|| €ÒI wGJ dóG‚™w& ˜w,6îd=:$0“,wdy—w,6Ød=ù,0“w,,ÿdd  ÝP 8&é'ë-jÝ8w1-j-jCr8*-j8Ÿ©„„r*8-¾&‚-Í-Î-j{  8îw{*{g%{i%8„r* r81‚-I —:J%{W%-jŸž„„r*-¾&‚-Í-Î-j  âš:˜:˜-j w*¥4¥gû‚-I —:J%{W%ΰ¯‹§U?,¥WË™’W&:J‹“3¨´ fKWÞW%U‹§-S‚.­‹“-â -zÓ -SwÂ*fw*¥U¸¬?iÓ Ó ‚‚rÂ*w:˜ *+w:˜ ŸÂ*\„„„„°áØ8 ¶:˜  ¶?9°áØ ¶:˜  ¶?_‚°áØ8 ¶:˜  ¶?"8b:˜ _‚°áØ8 ¶:˜  ¶?"b:˜ _‚°áØ8 ¶:˜  ¶?"8b:˜ «w*¥X¥M¸¬?l8w‹“ª*‹“ª?flag_coverS¯S¯R˜\w*ÿšM,§‚š:k&w.ˆ*% ’,,@üØš:k, ,üüš:k, ,\»šM,c‚š:k&w.ˆ*% ’,,@¸”š:k, ,¸¸š:k, ,\ ‚š:e&w.ˆ*$ ’%,@\9š:e, %\\š:e, %Ó wç*-^'›r:˜ *-^(í‚w:˜ *+r:˜ ŸÂ*-^(Ó -^Ó ‚˜3:˜ Ÿ˜v w*¥\¥S¸¬?k] ‚‚›:T% w*šS, ‚š:T&w.ˆ*$ ’&,@] : š:T, &] ] š:T, &Ó w‹“ª*‹“ª>flag_sealS¯S¯R˜ ‚‚-u w**„šg,šg,#q‹Ô wq*x qa/!Nq% }“‘g,&qqÛ+  ‚-~w.ž* ‚‚‚‚‚ÿ!{ ÿ!i ÿ!g ÿ![r.ëÜ* ÿ!F ±áØ ¶8 ¶?‘ ±áØ ¶8 ¶?  p,°  p& w‹“ª*‹“ª3longrangekillS¯S¯G ‚þ!i w*¥@â‚‚-` ÿ!g w{*}¯‹§{cÑw‹“û} Õβ}s p,¹¬?ew*¥iŠw‹“ª*‹“ª5spawnkillS¯S¯Se΂‚-X w*—i, , ââ°}t p,¹¬?e1w*¥ižw‹“ª*‹“ª5spawnkillS¯S¯Seâ‚‚-X w*—i, , -j R e %97-S*-t p,7 p, ×E Knwì[?z%Ó K¨AKaÐ%ÓDGK—\K±$K4”®¯¬Kœ?,¬D?,?,®G?,KaÑ%ÓK—QK±$K*”¯¬Kœ?,¬D?,GKaÑ%Ó S Ifõ!ki‚‚w‹“ª*w.ˆI*I-¾G=.ˆIŸ¯‹“ª$IPRG.ˆIä‹“ª;playerNetSpeedRGS.ˆIÑé‹“ª-playerFovRGU.ˆIÉ‹“ª-playerVoiceTypeRGIËiIa/!NÔrIÌ*INIB@õBVIÌ@None‹“ªplayerSkinRGB‹“ªplayerFaceRG@ ðW usØ ‚‚-|u-¾:‚uŸ-ÍuŸ-ÎCa quwC*C vuM  u´rM* äM-HM-H'fuMc‹§ðu }€Q V [Ž3^dQS*‹ö;–JQ, Qp0Q*‹õ f&=Jan: y,=Feb: Œ,=Mar: Ÿ,=Apr: ²,=May: Å,=Jun: Ø,=Jul: ë,=Aug: þ, =Sep: , =Oct: $, =Nov: 7, =Dec: ÿÿ*‹Ï h%wSundayö }&wMondayö ”,wTuesdayö ­,wWednesdayö Å,wThursdayö Û,wFridayö ó,wSaturdayö ÿÿpp¨p¨¨¨wS*‹ï=S*‹è,S*‹î:Q =€@X T l¹Õ¡}‹“ûtw}*]‚w}r}ðð-R't}}ùË-p稨InstanceWÙnot loaded because bEnabled in .ini = False.!,r.«‹“*稨InstanceWÙnot loaded because gamestyle is not CTF.!~-R稨InstanceWÙnot loaded because it is already running.!-L'-L ÖY H“¢‹“a rb‹“|-[-M-T-M-X-]-U-\¡-O-t'Ç-I‹“Å F/a0 ÊHó:Hç{H102°áØ%{ ¶&{ ¶«À??„-t'~a Öpš:‹Ä:$a€?'稨SmartCTF[loaded successfully.! Ó\ xAg‚ÓB‹“ä‹“ä kç¨Original Scoreboard determined asVB!o-r°‹“÷ã ix‹“ûfwx*Oxa/!yxA-'çNotified UTPure HUD to use SmartCTF ServerInfo.!fxxùÕ2‚-(ÿ‹“÷Ù!M-(çp¨HUD is not the UTPure HUD butW‹“÷Ù, so SmartCTF ServerInfo will be set clientside.!l-S‹“÷€-' U vY¶¤bF šP%%_‘v`P>—_``D_ ^ …ØqUÙ BØ‹“a @laa _€` …ÚZ PFÇ*d $;$¼–:;P>r:;%€·*¼‰‚:;%€·-Í":;%€·-β:’:;%€·‹‹;;ï–:;P:;’*‹;Ç;$–:;P-x'$ò–:“P&V„r:’*r’:&’*ò¨°:’¬’:&’¬/=’:&-x(èè´:’¬’:&’¬y&:’c&’:&’è‚wy* wc*x–y4c4/=’:&-x(èèšy4c4è±:’É’:&’É/=’:&-x(‹þ-x‹;÷ d€Éb  ë  c d …e …g _ l/Öi?y:l’:l’:n’:n’y €@Òa I#É¿ÒIlkj C%I  ò '½ `&I  ö '½ ~,I  ô '½ œ,I  õ '½ º,I  ó '½ ÿÿ !m f aW k—p%q%v%u%D%s%e%r%B%D%T$•–:T, pr:T’*•©‚:T’-Í:T’-΋a=:T’¯.&:T’Ow.*—.\pp.\I—.Cqq.Cu—.]vv.]¡—.Xuu.XÍ—.\DD.\ù—.Uss.U%—.4ee.4¡B.^¡D.`‹±:T’É?rrD:T’É‹TN åip H "¯«¬ì@D^«?,_  i D ‰m ‰`ˆ_€€@@ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿÿÿ ÿ  ÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿ"ÿ%ÿ*ÿ$ÿ.ÿ+ÿ$ÿ1ÿ5ÿ:ÿ3ÿ#ÿ%ÿ#"ÿ+$ÿ'&ÿ4"ÿ<"ÿ6*ÿ!ÿ!"ÿ""ÿ&&ÿ$$ÿ)*ÿ--ÿ**ÿ)&ÿ1,ÿ12ÿ45ÿ::ÿ=>ÿ:<ÿ78ÿÿ$$#ÿ*)%ÿ,-+ÿ%*&ÿ4*#ÿ7*$ÿ'6(ÿ74*ÿ!34ÿ!69ÿ!;<ÿ*95ÿ442ÿ;:5ÿ9;8ÿ/1ÿC#ÿL$ÿC*ÿK+ÿS%ÿZ(ÿL1ÿX5ÿg(ÿw+ÿf:ÿv9ÿG7&ÿV:&ÿD1)ÿU)ÿ+B+ÿ'C<ÿ9E:ÿ:I1ÿxHÿrHÿYC)ÿED9ÿYU7ÿNJ2ÿgH*ÿxV2ÿlS2ÿok;ÿTe<ÿ>@ÿA>ÿ!>AÿCDÿKLÿHGÿNQÿZUÿSTÿSTÿ[\ÿXZÿ SLÿ!CDÿ!JKÿ(HFÿ8GEÿ&WWÿ5WVÿ,RLÿcZÿ-f[ÿ^bÿc^ÿ$^aÿkgÿbdÿhiÿslÿmrÿzvÿuxÿsgÿ%hiÿ*uvÿ7yuÿ-nmÿGIEÿHVHÿIWVÿWZXÿUUIÿQjUÿegYÿnrJÿZbbÿ[kjÿ[vvÿKrhÿfigÿwzwÿmvoÿc]Sÿ‰0ÿŽ6!ÿ†SÿŠZ)ÿ’f6ÿ¦o6ÿœcÿvKÿªyEÿ¡}`ÿ…zÿ6…xÿsˆRÿF†{ÿT‹qÿpŽrÿn¨xÿR’dÿ‘ŽPÿ²‹Nÿ°¬Zÿ‰Œwÿ²¶lÿ”£pÿÊTÿÑ«eÿÃÆmÿ}‚ÿ ‹{ÿ$|„ÿ6}ƒÿ]ÿŠ†ÿ…‰ÿ–‰ÿ‹’ÿ—•ÿ—šÿ$„Šÿ$Œ”ÿ&“›ÿ6—šÿ5Š‹ÿ©—ÿ ±—ÿ.µ˜ÿ›¢ÿ)›¤ÿ4¥ÿ ¬¤ÿ-£¬ÿ8¥¨ÿ3¯¯ÿLˆƒÿZ††ÿL“ŠÿV˜‹ÿy……ÿl‹ÿT«•ÿf§™ÿs®ŒÿI´­ÿw´¯ÿUÁ¹ÿuŸÿi™ÿxÈÅÿLºÃÿˆŠ‰ÿŒ““ÿ•˜—ÿ‘”ŠÿŒ¬’ÿ«¬˜ÿŒ§§ÿ—¤¤ÿ‡·¶ÿ’¶´ÿ©«ªÿ²¸±ÿ››ÿ‹Æ˜ÿ‘Í­ÿ°Ó²ÿ³ÕªÿÇȯÿÉäºÿÐç»ÿ½Áÿ‘ÕÍÿ¬ÓÈÿµáÑÿÅÇÇÿÜÝÝÿÑÔÒÿÐçÆÿÝäãÿèóäÿàáÔÿÖ¿Ÿÿ*t +.&"€'"€,"€-"€)*6OI;*èóäÿ"=‘b†¢ø^^M@€”××ÖÖÖÓÒÒÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÒÒÖÖÖÖÖ×ÚÚÚ×××××Ö××××××ÖÖÒÒÐÐÐÐÐЕ••””””””””””””••••••••••••••••ºººººÑÑÑÑÑÑÑÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕööõõõõÞÞÞèèÚÚÚèèèèèèèèèèèèèèèÞÞÞÞÞÞõ÷÷÷÷õõõõõõõõõõõõõÞÜÚÚÚææææææææììììììììææææææææææææææææææééééééééééééééôôôôööööööööööööööööÕŽàXÄÈÈÇƽ»¥‚‚‚‚‚‚‚¥¿ÆÆÆÆÏÙÏÙÛÙÏÏÌÇÇÇÇÆÆÆÆƽ¥mmmltttiihffffhffissstttjttjjloooqpp€€€‡ŠŠŠˆˆˆˆˆˆ‰‰¦¦¨¨¨ÐÒÒÒÒÓÓÓÓÓÓÓÓÓöÕšàwÇÆÆƽ»„‚‚‚¿ÌÆÆ¿ÌÙÏÏÛÛÙÏÌÇÆÆÆÆÆÆÆÆƽ‚zmnjttisf33333ffhisiittjjjllonnqq}€€€‡‡ŠŠˆˆˆˆˆˆˆˆˆ‰¦‰¨¨¨ÐÒÒÒÓÓÓÓÓÓÓÓÓöÕšÔu1.‚ÆÆƽ¥¥¥ÆÆÆÆ¿ÌÌÌÙÛÛÛÙÇÆÆÆÆÆÆÆÆƽ¥¥mmnjisf32223h3hfisittjlllnnnqq}}}‡‡‡ŠŠˆˆˆˆˆˆˆˆˆˆ‰‰‰¨¨¨ÐÒÒÒÓÓÓÓÓÓ×ÓöÕ‘à ÒŠ! 5„ÆÆ»¥‚‚½¿¿¿ÆÆ¿ÆÏÛÛÜÛÏÆÆÆÆÆÆÆÆƽ½½¥zmmrtkif@112A333isitjjllnnnqq}}}‡ŠŠˆˆˆˆˆˆˆˆˆˆˆˆ‰‰‰‰¨¨ÐÐÒÓÓÓÓÓ×××öØ™ãyÖ¦! /}¥¥¥„¥¥¥¿Æ¿ÆÏÛÜÞÜÛÌÆÆÇÇÆÆƽ½··‚zmrnljjiA@122A3fitjlllnnnqqq}}}}‡‡ŠŠ‰‰‰‰‰‰‰‰ˆˆˆˆŠ‰‰‰¨¨¨ÐÐÒÓÓÓ××××öì°â {y )k‚‚‚»ÆÆÌÏÛÜÞÞÛÏÇÆÇÆ·€^TTTTSUCBAXstttkfffifsitlonnnnqmm}}}}‡‡ŠŠ‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰¨¨ÐÐÒÓÓÓ××××öæäå !  '5rzz‚„½ÆÌÏÛÜÞÛÏÏ·pX8HP›››››PKG$;89Ahfiikiistooonnqqzz}‚†‡ŠŠ‰Š‰‰‰‰‰‰‰¦¦¦‰‰‰‰‰‰‰‰‰¨¨ÐÐÒÓÓÓ×××÷æØåI    '5rm‚‚‚¥¿ÆÌÌÏÏÀ†BHORRœœœ››POLHG$%;;9>>;;;88888BAikkiADTTVU< ‰6    '5rz‚„„„}k/ $N[[[[[[VHOOPPPPOLLLLLLKKKKKHHHHHHHHHHLLLOK$;v–¨¨–––––‰‰‰–xvYE‹©ÓÓ×öì×÷e ‰¦*  G$ /ggkkkkg50* B€†2NR[[[QNNM !;<%GIUUDD^YD;#<>><;DŒëÔ×õ«")ÙÖ/   GG *†ÉÇƽyaQ$ IMMIJN$!y–¨¨–YGGHLOKHHG#ãš×õÝZ¨ÙÖX  $$HH$NQQNMNQQS>Y{·xUGHLOR¡¡ ¡PPOOKHBg?=989Xo{ˆÇÈÖÓÓÓÓ©UHKLHGHG##;%<>â—×õȬAÙÙÙ{  GH$HHLK $NQ\[[[[[[RPP_Š_POOKKG$QLLOOPP››PPK7/23io†††††{y88CEv©SIG$;YëÕÖõÈÖ xÙÙÈÇ· KOHIMQ[\NI  I$$ %Dª×ت”ŒD;>^D<>Œ–ÐÒÐöÕÖõÇÈ«8 ÖÙÈÈȽ.HPOGI$$$MRROLHGIJJI$ II$ $#YŒŒŒŒŒŒ‘™ªª«ØØØØØØØØØØØØØØØØ×Ööæ×õÈÈÈÖ`¨ÙÈÈÈǽ¥/ H¡[KHG#II$$INQQRQ[QLOLHGGGG$$$JNQI##C;Dx{{Š¦¨¨©©¬©©©«ØíííííííííííØØØØØØØØØØÝ÷é×õÈÇÇȧXÙÈÈÈÈǽ‚. $\¡OOLKHHNNNNMMJI$GLQ[R››PPPOLKHHGGGNQVHHHKHHG$$GHHHHGG$D;=‡{x¦ÄÈÙÖÖÖÝÝÝÝÝíííííííííîîîîííííØØØØÝÝÜ÷é×õÈÇÇÈ«ZÒÈÈÈÈÇ¥¥‚) Q›PPOLKVJMNQ\\N IMVP›œœ›››PPLKHHN[MHHKLOPPOOLLLKHKKHI>>;uÁÄÄÖÖÖÝÖ«ªš___‘«îîîîîîîîîîîîîîîîîîîîüéÖõÈÇÇÈÈ’ yÇÇÇƽ‚‚rJL›››PPLKHGN[\ ##GOP›PPP››POL\Q$GGHVLOOOOOOLHGGGHG$;#BYE>>TQOLT‘’’cLG^ªíîîîïïïïïîîííäääääúçÖõÈÇÇÇÇ«> À½½½¥zzzm1#P››PPOLKV[[\JI$ GOPLLOOPPR¡¡NGG$GGGHHHKKKKHHGG$$GLOVS`_S$S‘ªªª™‘š__š‘‘‘šê˜ÒÞÆÇÇÇÇÝe‡½½½¥‚zzrg!$# L›››PPOL\[N$$$I\\I  HGGHHKL¡[HKG$$G$$$$$$$$IUS^`_`S<$S_’ª°²²°ª™‘`SUâ‘ÒÞ¥¥¥¥·§"'½½½¥‚zrg1F$$ O››››P[[NHGN GGHQ[NHLVG$$$$$$$$$$#<Œ–©ÓÓ×ØØØØØ«ª_$$III$$$USSU%ã‘Òè‚‚‚mm¬Z…¥¥„‚m51117II# GPœœ›[NQ[[J J\[M$GHH>DvvDCU]c`)wˆxŒª«Øíîîîí䲪§§°åðððòòòòòòò÷ýë•æmmrkggk§>†zzzmrk511* MM O¡[QVKH$$ GNQ###‰ÎÅ{C#;>DD>CxŹ Ic¤]% 66)xyÒÜîîïïïïòòòòòòóóûûûûûûûûýë“ì00000000Y’"'}k32111111HIMN# $MR¡¡\QM#  M^ÅÍÏÏÍËÅxE;;DD>>9  T`; *0)XÓX‰Üîïïïïòòòòòòóûûûûûûûûûýë“ì000FF0000§`w5?1111155&GHMNJ #$Q¡ž\QM EÅÍÍÍÍÍÍËÎÎÅ{C#cM  (@uAy3¨ÕÕØØäääðòóûûûûûûûûûûýë“ì010FF0000Œ’ 1@/1111555+ VINQ #J\¡[RR\Q# ;ŠÃÊÍÍʹ¹ÅÅŠCCvx‰¹: Ÿ]NM  BX* iÐ×äíðòóûûûûûûûûûûýë“á011FF000?@§Sy,,F015221 KGMQJ #\OPPPR[Q## 8X‡Š{vYx¹‰YE¹ÎÏÏÏÏFž]\³³ŸM/‰Ú–ÕÚ䪌vBŒ«ðóóóûûûûûûûýë“á00?0000000edAF,,,F12fgHHIQN #MHPPP[NI{ÄËÎÎÎÏÏx#ab[®´³ M ouxBŒÕîïïïïîððððóóûûûûûûûýë“ì1000000000B§>6u-,,,02gi)GK#NQ$$ LPP[VLU<;vv<!988;##;v‰¹ÅÄËÍÎÎÎTMŸ£ ££ ŸQ 56  Bªãëðòòòòóóóûûûûûýë“ì10,,F000010’_u-,,,F2gk0 $VMNIG HOOQLLDDYxˆxU$#CEx‰¹ÅÅÄÊÊËÍÍΖT]QMMTTb- *Y–ªªãääðòóóóóóóûûûýë“á00F,,,F000FY§;)A-,,,14f2 V$MMHG GLOI$UvYxŠxyC79vvvˆÃÊÄÄÄÊÊËËËËÍÄcŸII I ŒBíïîääðòòòóóóóóóóóýë“á,0,,,,,FF,,-§`y+,,,223fVJMOGH HQN <#988!9C99>vˆÃÊÊÊÊÊÊÊËËËËËËÍ–b%#³Ÿ ST *:Œ¬ªäòòòóóóóóóóýë“á,,,,,,,,,,++Œd"01-,,124fVIMPL GN! !vŠ¹ÂÃÊÊÊÊÊÊÊÊÃÊÊÊÊÊÍÊ NM³ !T  =™íððòòòòóóóóóýë“á,,,,,,,,,+++,§`u-,,?223*$LG $JPO $BBxww‡ˆˆˆ‡wA7##;Cvx–E99C–v‡ÅÐÅ–`£´®]! B7Y:䪙Œäðòòòòóóóóýë“á+++++++,,,+++edX,-,1223+GPK #JPO 8ys ?‡Â¸‡yB9888!CÑ•BXŠxYCCC˜ X%Ÿabc 7‹D&(íäïòòí«ªðòòòóóûûýë“á)+++++--++++.=§>6X++024fFG›L JLKO  CBxwu?::?u~ˆ¸¸¹u 7v*9C(8‹ŽŽE™Ž< ]#!:77D87yy Ø™Yïïïððí«òòòóûûûýë“á+++.+++++++-++’_ u+-,54f5G›O VHOO QI +yx–{y77Xuw~~~‡ˆy:vC v^Ž7^——ŽC—7U ]%% :9E‹DED7.«:Œïïïïðîðòòûûûûýë“á+++)).+++++-++Z’;)A+-1432G›O NPH N[NjƒÎÞÞÞÛÄA7 :Ahu?BCE7BŽ˜v8YC9:—“;]%II C979CED—8 YXB–=äïïòòïòûûûûûýë“á)++)))..+++-+..’`u,,0522GœO \IKPJQ;qƒ¸ÛÞÞÞÞ‡ŠÁÁˆ?BBCv˜– 7:9C‹™™!    ^E7 79˜‘9E Exy–,=©äïòòòûûûûûýë“á..+))))).++.+.*`d"?0,1112GœO#N$QQ$$h}…ÂÂÎÞÞÞÙÂÁÁÁÁ‡+79?Œ:(v‹“v 8™°‹ECÕጋ“9 B•Ž^8E77vyÓ–vªØïòòòûòòòüë“á+.))))))).))))(:§`u,015@HœOI¡IGQ\I$M B}ƒ¦‰¹ÎÛßÃÁÁÁ¸ŠxB 7BBv‹‹*8™°D^DŽvÚìã°°°åã”C Œ‹8 97:?ØîÕíö÷÷÷÷÷ööüê“á.)))))))))))))((edX1F111HœLM#Q[$NJ$MM 77;DEÙΈxyvÑ–YC 9YE8 CD9^ CE ™‘B°ååå˜CC 77‹^9  –ööö÷ö÷öööîîûé“á..+*)))+)))++)**=§S6u,011KœKKM#QJ$$#  ,oÅÎÖÐvDv{ˆyxv‹^ECE9 U9:9‹ ‘Ž°˜E79D99‹“‹ ‹ 7:! 8EC9C‹:–öööööîÜÜÜÜ÷æ“á..)**))++)))))))'’d u-,00LœGPGG 8l…ÃÙÛÛÙ¹ŠxxAB‹Y‹9  I_‘“š‹ñ—ã™EŒ“——— ˜— ‹ EDU 9DCCC7 ÚööõîÜÛÛÙÙ÷Ú“á).)****)+)))))..(Z¢>.A,/0OœGKLLG  7t¶ÃÏÙÏÏÄÁˆA 97!;]! ™Œšãåñññ嘋EÔ˜™™‘å™°˜º`S! —˜^/ôõõÜÜÛÙÙÙÙöדá).+(***)+))))))-)*§_u/52PP$OGK$G 5q}ƒ¶ÂÃÍÎÍÂBU£#!9—‘‘°åëññå˜^E“×Õ˜˜°ãåñëã™^7SU YÚÜÜÛÙÙÎÎÎöדá())((**)+))))))-+(e’"@fggPOGLHGG$ ?ljto}¶ÂÊʈ!Ha®C‘ëÕ—˜ãåëñå˜DC•ÚæÔ˜ÔÔãåñë—ë—8Ÿ°õÛÙÙÎÎÎÎöדá(*(((((*.+)))))+0gX­`wrkPHKKHGG$ 79slq}}…X™_GGGaa 8C‹Y“—˜àãååã™DC•ÜÚÕ™˜˜Ôãåñ“àŽ‹  b££¢ÕÙÎÎÎÎÎõדá(('((''),---+..+gkk§’tmkLHKOGKHFAAilq}}|>$JMG T! 8‹Ñº™˜˜Ôàà˜—EC•ÞÚÕ˜™™˜Ôãå^>8 ]®£³£¢ôÎÎÎÎÎöדá(('''()F101gg2500gk{­SgGGG$KGGL :?ijlnq||}бbGMM  ºÚ×Õ˜˜™˜™™—ŽC9ÑÕÕ˜™™™™˜˜ŽC77  ž Ÿ³®£²ÓÎÎÎÎõדá('''+052222rmmmmrkkm²d wgG7;GGGKG 7 :13hhiitl}}{¤³³M  CŒ–Œ‹‹E97 78C7:vŽ““—“Ž^7 !aŸŸ££³£’ÒÎÎÎõדá((()13fikg3m‚„‚mkm–­>:8G/riGK$!.1432?F2fffhijˆ×’Ÿ®®aI  >Z97 8C9:  778 !SaŸ Ÿ³³®¤ÙËËõ×”ì1112gikrmkn‚„»¼¼¶…z}­aKmmD#;?23334533fffffsÑï¤IbŸŸ]<  !S8 Då™  : >]žb££ŸŸåõÙõ×”ækkgkkjmzzm„¶»¾¾¼¶……†¢LHkgG>@g3320,14333fAuæñ´]JTaS!   9ãþö•) 7CE %]cŸžc]b´ï÷רÚmmmmm‚„»¶¶»»¾¾ÀÀ¼¶………§_TG 9Xif3,*+@443333Xäÿ´³] #< –Y79 9E‹Ž™åþ÷ôÕ9  F <% U]]S<]³´þæÒÜ„‚‚¥¾ÀÀÉÉÀÉÉÉÉɾ¶¶¶¶…’Q$ Bskg2**F5444444A©²³³®]  lÙŒ7998D>8‹‹Ž™˜ãëøèÕ—Ž—E 8‹:C7ôj %% Ua£´ÿåÒÞ»»¾¾ÀÀÉÉÉÊÉÉÉÉÉɾ¼¼¼¼„§SO *-43334444@‘®®³®ŸMD88  ‹ÓÍ͸,  !>>D!b£ŸbŸb< *12224fstoq71}‡Z !;U<USSS%7 :{ÍÍÍÍÍÍÍÍÍÍÍÍÍÁF !ãšÒÞ»»»½½½¿¿¿¿¿¿¿ÀÀÀÀÀÀÀÉÊÃÂÁ±_>>8  bbbb]! &F2225524fjnqn:i 7 !SSUSUSSSS]T XÊÍÍÍÍÍÍÍÍÊÊÊÊÊÊÀ àŽÒÞ¥»»»½¿¿¿¿¿¿À¿¿ÀÀÀÀÀÀÀ¾¼¸¸¸B; ST< .,1@22222512A23jlqn7j}‡> :%SSTa\TSST]]TT: {ÍÍÍÍÍÍÊÊÊÊÊÃÃÃÃÊÊÀFàŽÒÞ¥¥¥»»»½¿¿ÀÀ¾»»»¾ÀÀÀÀÀ¾¾ÁˆX :13332442222552244ijjn3:qqe 7!SST]]S< 6XÊÍÍÍÊÊÊÃÃÃÂÂÂÁÁÁÁÁÁÂÂÂÂõÓÐè„¥¥¥¥¥¥¥¥»»»»¼¼¼¶¶¶¼¼¾¾ÂÒe   )ƒ¶…nj3342242224443333fhhs7?jjttB>Z8 USSUST7  ===:==::==    :0ijjlqqq€ƒ…ÅÄÄÄÅôÑÐè‚‚‚‚‚†nk…ƒƒƒƒƒƒƒƒƒƒƒƒƒƒ…………¶¶¶²¯%w¸¶¶¶¸……ƒƒ€||qlf33A3334@111­"ZW=W=.  =3jjjjnqnq}}qqqqq€ˆÅÅÅÄôÑÐè‚‚‚‚††q0-ƒÃƒƒƒƒƒƒƒƒƒƒƒƒƒƒ………………©µd6¹………ƒƒ€€€€€€||qjsA3424334@1?X¢ 7  : ikjjjnqlnqqnnlllop~ŠÅÄõÕÐè‚‚‚‚††}0*)ƒÊƒƒƒƒƒƒƒƒƒƒ…………ˆ±¯{ƒƒƒƒ€||||||||poihAA@@@@A2@??ŒdD=   .ikjjjlnnnnlnnljkf33iˆÅôÕÐè‚‚‚††g*()…¼Ã€€ƒƒƒƒƒƒ…ªµ]-ˆƒƒƒ€€pppppppppoihAA1??@@@@@1§_ "!8E   :/hiijjjnqqljlnljiif3hioéÑÐ膆†††n)(*)…¸‡€€€€€€ƒƒƒƒŠ±­Šƒƒ€|qoooooooootsA@?01@@@115­ 8"     0AfiiijlnnnlnnlljkiiiiiæºÐ膆††},(((jl͹¸€€€€€€€€€€€€€€ª¯>A‡‡€|pooooooooootsA@?0?111@@B­  !====   012fikjjlnnllnljjkiiifiì”Ð膆†}1('(+j€ÁËÄ€€€€~€€€€€€€€€€€€€Š±d‰€€ppoolllloooothA@??111@@@A’A?):! W==.=  C  :.+-F23iiiikjjiijjjkifffiì”Ñèg('')+,wËo߀€€€pp€€€€€€€€€ppppppp²­ypppooolllllllot3@@@@@@@2A3hitjj:"==..(*)-1@3iiffh33fkkiiiiiiì”Ñèzj)''&)-F3ˆsÏ…€€€~~€€€€€€€€pppppppp–±_6ŠppoooolllllltsA@@@AA3hhssttw{x‹vyyuXB= " E'())+,054333343ffiiijljæ•Ñè}n+&&&.+ppjtÁË€€€€p~~~~€ppppooooooow±­{pppoooolllttthA@@@Ahsstttlo§­­šDCCC9C“C  !8™Ž ('*)+-,01@42@@45143ijnnæ•Ñèn-(*+0ƒ|¹߀€€ppp~~€pppoooljjlllo§¯S-‡pooooolttttsAAAAA3ssstjlo|§¯­^^CC9C9E7  C879C?'()++,0144@@110015fjlnæ•Ñè56'')-2ÍÍÏËÁ€€€~pp€~ppoolttttsttlx±¢Šppooltttttti3AA2Ahssstlp€€©¢_; 8>Z99  9898 :YB))-,,014445@11?0Fhjoq溺æ666&')+,¼ÄÎÉχ€€ppppppoottssssssttl­¯%X~ooltttttttsshAAAAAhslo€€‡‡^D8 C99  7CC978 *u---+-F@2443451F@slp€éººá666&'()-oƒ‡É€it¸ƒpppoottshAAAAhsstxµd{lttssssstsssh3A@@@Aslpp€€{¢š^C88799C=:9^C9v u))++F0@233f3423itop麔á6&))))0ÉÉÉ2.)iÁÙ€ppoltshA@@?@Ahsst²­utssssssssshhhhAAAAhstoopp–µ¢9799C W 9‹C997 *)).++,,?53issiiififæ•“á&'++,vÒÁ¶f*-fˆß¸ppolssA@?00?@hhhs¯_6whhhhhhhhAA@@@@@@AA3stloow>8 899 W 9‹C9 7:7)))+++++F2fstti2511씓á&&&&&BÔëüüùüü÷Ä1+ƒËÁppoltsA@0FF?AhAAAX¯¢yAAAAAAA@@????0??@™áAhtlÑì’šEC97 898W. D^98 6**)))++)+FF00F-))+,á““á''&'(êùøç“€‡@Ò÷üu.1jÂËppoltsA@?0?@AhA?0?’¯>,u??????0FF,,,+,F?ëë?2hsëø¯’D98 C87 W=: ^E8   :,(*)))))))+)))((''((á““á(''((âBù–…ÃˈÙü“),o~¸€ooltsA?00?@AA?F,,B¯dyFFF,,,,++)***)+,úì00@húçd>  C8  W=: E98 C *'*))))))))*((''&&'(᎓á*(((*))ùv2p¸Áöüv)-0‡Šp|ˆpthA?FFF0@A0,-+,§­"@?+++))+)(&&&&&'?ùÔ,,0XüÔ`97 887==‹‹8 77 &'())))+)))*((&&&&'(᎓á))))))-Ôù,,,xêüì2.)-,io2…¸shA@@@?@@?,++.+Z¯_u)*(&&'(&66ù),0“ü•­šD977 7:=‹C8  X('(***)+))*((('&&'((á““á))))..vìø˜çùúáo@—øùø—,çÔisAA@@@vÔ,Eçùùç?±å çê“Cçùùç766“áêëùB(+FÔü•ññâ7˜˜ ê—: Y7‹C88(&&(()))+))*((''&&'((á““á)))).ùùùùùë™?0‡ÔùÔŒÔùxçë|+AìüB00ëê?ú猎ù˜åþøùçÔE(úâ‹Žù˜6áùá˜ëù'+Fáüüê˜ùà9ù8 ‹ù7 : 9E9 7 6&&(*))++))*((''''((*á““á)))).)ùâ)''(,uüÔ)ëÔ˜ø5o”üüF˜ú?âç&Bçø,êýú7X áâ :çø*˜ù‹êê&+Fëø‹ëëEçâ êâ  9šEE 6''(*)+++))**(((((*))á““á+....+Eù)(*ü)66ë˜ùEvúÔëÔ‹ù—&ú˜êú˜,'úú­%))ú™êú˜( øâ  úâ'+Fúጭøâ9‹ùC‹ù‹   DšYE 7(A())).++++)))))))))))á““á))..))ŽùB'&vù—(‹ù9&úâúâ,áêúç&ù˜™7&ŽŽùà¯dXù™— ‹ù˜66™ù˜&*+BùÔv­åùE ââêê=WW. 9 ‹‘^97 F++++,,,,,+++++++++++á““á*)).))Ôú&6666êúààú˜ áùá&+“ùë:6êø˜àøùâù­­?êø™Ôøù“êúÔøúù+,Fùáçúù—877Eúù‹ W=.š^E7 Ahh@000???0F,,,,F,FF,á““á(*)**(Ôç66 66*áêç‹ Eà &*â:&*àêêÔYYëE^¯`vàêê˜967áê™Bëv,,,vëáøå§D:787ëêW.>C99BsstoltsfAAA@@111@@2@0ì““á((((''&66 6&((6 66&&&&&&(++,,++,­¢X&6666 6+,,+)*+,F¯šE 7Cù‹WW. 7 ?utowp€€‡~otis3AAA44@1ì“Žá''(&&6 66&'(&6 +1)&&'*++,00F,,e­SX&&&&&6 6*+++,+++FY§Œ? àëZW.  6-5oop~€‡‡‡Š‡‡~oshh344@1씎á&&&&66  666&'66 .-(*)+'*)+,0?@00?B¯du,++++*'&&(+++F00FF1A2BeWBù“ eW Xwp~‡‡‡‡‡Š‡‡‡‡‡~tsif444씎á6  666&6 6+&-,,*++F?@@@@@2§­",u@??F,,+)+,,,F?@AAhhAY­Wâø ’W  9~‡‡ŠŠŠ‡‡‡‡‡‡‡‡‡oisif33씎à6 66&-&)+F),,0123kfhsŒ¯_{shAA@?0FF00F0?@AhhhAY§WÔŽ §Zv‡ŠŠŠŠŠŠŠŠ‡‡‡‡‡‡‡otssis씎à6666 666 6&&'0-'&F66F0-hiijqƒƒpoo²¢ uwtsshAA??????@@@AhhAŒeW: §e{ŠŠŠŠŠŠŠŠŠŠ‡‡‡‡‡‡‡~ottt攎à666 6& 6(&*)13,*5)(&53,jjn…¼¼¸ƒ–¯S ŠoltttshA@@@AAhhhhhhuZW=  ’d -ŠŠŠŠŠŠŠŠŠŠŠŠŠ‡‡‡‡‡‡‡‡~~攎ààààààààààààààááááàááááàááááìììáæáìáàáìáììæèôôôôôòåàÔéææææææææççìììççççççëåââãàààààààååãààààààÔàààààìééééééééééééééééééééééééé•ŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ““““ŽŽ““ŽŽ““““”””•””•“ŽŽ““””•º•ÑÑÓ䲑‹“Ñ••••••••••••••••••™°™“ŽŽŽŽŽŽ™‘“ŽŽŽŽŽ”ºººººººººººººººººººººººººººº€€n]@@ÕÜÜÚ×××××××××××ÚÝÝôîôÜÜÜÜÜÜ×××ÕÕÕÔÔÔÔÔÕÕÕÕÕÕÕÕÕÕÕ×××ææææéééééééæ™XÉƽ„‚»ÆÆÏÏÛÏÇÆÆÆƽzrtif333fsitjjlnq|€‡Šˆˆˆˆ‰¦¨ÐÒÓÓÓÓÓé™uBm¿½„‚ÆÆÆÆÙÛÏÆÆÆÆÆ»mji4533fitjlnq}}‡Šˆˆˆˆˆ‰‰¨ÐÒÓÓÓ×éàŠ7km„„¿ÆÙÞÜÌÆƶ{{tikts33fijlnnm}}‡Š‰‰‰‰‰ˆˆ‰‰¨ÐÓÓ××éä  -gm‚¥ÆÏÛʇ=$O›œPLJ<9BBBBh3srqqyŒxxŠ¹¦¨¹‰‰‰‰¨ÒÓÓ×ôô:i1  -grmmmrrg.=BN[\QGHKGGGG$$$$$GHEx‹‹ŒŒxvEDDŒ–çÜ–Öy  I#$YŠ·‹HVQ[NHG:8!8Bw¨Ò–Y$HGK$#;˜ÜÖ{Ù GGKGJNNMVHEIGG\NGKLOOH:,2iiB 8CZ<$;D^^™«ØØØ««««×ÓéÜÈÈD/ÏÈÌ‚\LH$IJGIIN[RPOKHGGNG$$$G;Xx‰ÄÒÓ××ØííííîíÚØØØÝöÜÌÌ©ÃÌÌ„rNPPOVJQ\ $HP›PPOK\JHLOOLLHHI){–ØíîîéäåðòòòòòúÔgkgyZ6zmk10JI žRPOVM JJ#%>xÅßÛ:TŸ]/ˆÓîîïïðòòòòóûûú˜0111elk311*HM $Q[[NT‰Îˆv>>Ex Ma6){¨îïïòòòóûûûûú˜0FF0ZD'1115,GMIJž[QŠÍÍÄĉvYBSM ?AXŒ©äîóûûûûûú˜00F00eA,F52GIN NPR\%!uxxxx¹ÎψT\³Ÿi–•Ø᪪îòûûûûú˜0FF00Œ"--,1gGN$ ORQM>x>!;Cx¦ÄËͨTabba66xªåðòóóûûú˜F,,FF?e@,04+GGV HQ>Eu9!8E{ÃÊÊÊËËËdT%Y•ªéòóóóóú˜,,,,,+e,-F2,HOG # 9BusA=uw{ˆ‰{Š¹ÂÄY%£b=Y”ªïòòóóú˜+++--+B`6F,21OLK F ?Awwwwy9vYXY‹ŽC8I9‹˜çã—:>>8 –Ã5 !S å×»½½¿ÆÉÉɾ¾¾¨’ƒ}n34x¤£žcI%'2}|8:8^79 8C‹‹C9CC ¸Í͈5;Sbå×»½½½¿ÀÀÉÉÊÃÀ«lƒ}l™Ÿ£bSU#! .kqF+?B    77=ÄÍÍÍÍo !a Ÿc!  ,2fjl@y& S===,C‹—9'¦ˆ¶ËÎÙÎÎÎÁ¸×ׂ‚‚ƒƒƒƒƒƒ…………¶¶¶¯ ˆÃÃÂÁ¸¸…€olfh322Œ>=,./=889  =flqƒÁ¶ÁÄÄ…×ׂ‚†qƒƒƒƒƒƒƒƒ……¶«_2¶Á¸…ƒƒ€qj333@1Œ:W== .fjnq}}||ˆÄÄ×ׂ‚†n+Á…ƒƒƒƒƒ……ˆ¯ˆƒƒ€||||lh2242?š : &ijlnnnljjoÅÚ׆†-*¶ˆ€€€ƒƒ²>iƒ|oooojh@0@@1e "76 &&-fijnnlljifkÕ׆†5'5…Å€€€€€€€€€Š¢ ‡|ooloolh?01@@&7 ==6 -0fkkljjjiffÔ×k'(-‡¹€p€€€€pppp°tpoolllt2@@43stwCA@F &*-13333iiikÔ×l&(5|ˆÅ€p~~ppolll•špooljtsA@hstl–­‹C9E  8‹ ?()-02@515inÕÕ&6&)€ÎÊ€€pppotsstt²woltttiAAhsl€Š_8 99 &&89 9?--F22510ipÕÔ6')1¼¶3€ˆpoth@@hs§^/tsssshhA@hop{­9 89.&D97 ,)-F5fffijÕ˜&Y˜ìèÐ-€Äpls@00AAu­uAAAA@??@“sl–`79,&E9())++142FF˜˜'&“àá…‰öBfÁpls@0?A?F§810FF,-+.Fë1hë’877... D7 ))))))*'&'˜˜**)và4¨ø?-ooƒs@00@,+Zd 0)(*&?ç-Xêš9 7.,&^7&()))*(&&'˜˜))?çëêâxÔçç••2Ô@“áâàëÔìCáâàCâçÔ)ŽøåàÔ7à &:^  &()+)('&&(˜˜)).áŽ'&Bê&—™Ô•øê—˜àŒú’—™à‹ê—“*˜Ôšë™˜^  ‹7 )(*.+))***)˜˜).)ç*6*ëâëàøY™à—àê­ÔÔŽ˜ë“øv-áÔë—áç= 7 '1,FFF-----˜˜(((6 6E“: E &Y&Ž“BŒd>)ŽCŒ?+™°97˜^=)  7 AtooosA5@21˜™&&6  6&&6 ,(('),0FW¢1**&)+,,?ŒB)çZ(lp€‡‡‡~tf45Ô™6 666'&)+-023A§ 5A@F-,,0@hAe”Ž  e&:‡ŠŠ‡‡‡‡€tifÔ™66 66 &'1*-,1kq…ƒ–c6wtsA@?@AhhŒ=’&6uŠŠŠŠŠ‡‡‡‡poÔ—™™™™™™™˜˜™˜™˜˜ÔÔÔ˜˜˜ÔÕ××å™ÕÕÕÕÕÔÔÔÔÔâÔ™™™™°™™™—™™ÔÕÕÕÕÕÕÕÕÕÕÕÕÕ@@~a@ºÙĦ¦ÅÅÄÏÛÛÙÙΉ–––––¨ÐÐÑÓ×××ØŽtz»ÆÛÈÆ·ji2fjlq}‡ˆˆˆ‰¨ÒÓÚ”. )5rzz‚ˆt9NRLG;;;9BEDE{{{–Ø×t~JMyUQVHG":sxvUG$>‹E“ÙXΆHJ$GHMMN##>D”تºÓ×Ù¦~ÌrQOHMJNPOKNHKHG<{¨ºª«îîíÚôη=»m7ORQN$H\G$G$;#Y”™`U`_’˜–kYrrFIGQIJY¹ÓDc {Øîïðòóò0Y,31 JGQCĉvv!% yÕéòûûûF0DF0,GJLR<98Y{ÄÄ]Ÿ@Œºéóûû,,Y*,1$H$CX:XˆÁÅÄDa vªòóòŒ++,>F5KG:xutyCv‹^;%887ŒéïóûŒ)))Y)1LJJ$oÒĈ?BE^Y“Y9E:ïòïŒ*))=90KHlΊF:!‹°˜—ŽD 8*ôÝÚ‹'.-/Z5HH@qˆS%:•à™º˜ã‹#¤ÖÖ5kz†Š!=;?13–šT9 7Œ7C !Ÿ¢ÚÄ¥ÀÀ¾¶S512Œ®# )B CD—ç‹"B4U¯Ë½¿ÉÀé2oŽ¢a#g1h7:887w͸)<¢Ë½¿¿ÀÉÃ^,*a] (5ikw UU% ¸ÍÍÃi‹Ä¥»»¼¾Š  j3224i3@!S<% fÍÊÃÂÂÖÅ„„„¶¶Á …Áj223iABY9> ˆÃÁÁÁÁÒÅ‚†ƒ……¶ŠY|Ãøl3ifv:./:^ p…ÂÎÄÂÒÅ‚ƒƒƒƒ¶©vÂÁ…o32Y::=  6&kq…ƒÅÒņ1¶ƒ…e€ppi@@Z  ilnltЦg-¸€€€€|•2plls@@u?=Ffiii–.ˆ¸ppojx`plthAt{_97C:+,513–‹YÑ~ˆos1he/hh2@u~` &C),42‹=˜ŠÔlph01Z>,+(+”™` .&C &*)*&‹Œ+á“•™™™“™Ôâà—™‹Ô㎎ C &))((‹‹*‹6‹“‹YŽŽ“˜E““™?™˜E. 9 5i300‹  6()0A`0-),@Z“=6~‡‡~iŽ^^‹‹‹‹Ðª–”Œ^š‹EEÐÐÐШº Žb@–¶…¶ÍÙÍ{yx{Š¹¨Ó×:72gYDNG<9YvYx”ÅÁ8VHJVG$#vŽ«Ø؈ngKQJYv>º§ãåvB1;JMyŠvI.ªðûE?,;$CXy{v% BéûB)=7',XB“““˜“—“—9& ,,BY:9BBxŒvvE::‰‰Þb@xo‰xEy{ºˆ;VGIDºäB9$>xDWð@B#x:Ž8ªÀŠB=0>t{…ƒ‡l= j¹y~u4v )XE‹ŽŽ9ByýbwZEºB>v•¶u9~yvBAcYwX cy@ÿ€ÿ€ÿ€€ÿ€ÿ€€ÿ€€ÿÀÀÀÿÀÜÀÿ¦Êðÿ@ ÿ` ÿ€ ÿ  ÿÀ ÿà ÿ@ÿ @ÿ@@ÿ`@ÿ€@ÿ @ÿÀ@ÿà@ÿ`ÿ `ÿ@`ÿ``ÿ€`ÿ `ÿÀ`ÿà`ÿ€ÿ €ÿ@€ÿ`€ÿ€€ÿ €ÿÀ€ÿà€ÿ ÿ  ÿ@ ÿ` ÿ€ ÿ  ÿÀ ÿà ÿÀÿ Àÿ@Àÿ`Àÿ€Àÿ ÀÿÀÀÿàÀÿàÿ àÿ@àÿ`àÿ€àÿ àÿÀàÿààÿ@ÿ @ÿ@@ÿ`@ÿ€@ÿ @ÿÀ@ÿà@ÿ @ÿ @ÿ@ @ÿ` @ÿ€ @ÿ  @ÿÀ @ÿà @ÿ@@ÿ @@ÿ@@@ÿ`@@ÿ€@@ÿ @@ÿÀ@@ÿà@@ÿ`@ÿ `@ÿ@`@ÿ``@ÿ€`@ÿ `@ÿÀ`@ÿà`@ÿ€@ÿ €@ÿ@€@ÿ`€@ÿ€€@ÿ €@ÿÀ€@ÿà€@ÿ @ÿ  @ÿ@ @ÿ` @ÿ€ @ÿ  @ÿÀ @ÿà @ÿÀ@ÿ À@ÿ@À@ÿ`À@ÿ€À@ÿ À@ÿÀÀ@ÿàÀ@ÿà@ÿ à@ÿ@à@ÿ`à@ÿ€à@ÿ à@ÿÀà@ÿàà@ÿ€ÿ €ÿ@€ÿ`€ÿ€€ÿ €ÿÀ€ÿà€ÿ €ÿ €ÿ@ €ÿ` €ÿ€ €ÿ  €ÿÀ €ÿà €ÿ@€ÿ @€ÿ@@€ÿ`@€ÿ€@€ÿ @€ÿÀ@€ÿà@€ÿ`€ÿ `€ÿ@`€ÿ``€ÿ€`€ÿ `€ÿÀ`€ÿà`€ÿ€€ÿ €€ÿ@€€ÿ`€€ÿ€€€ÿ €€ÿÀ€€ÿà€€ÿ €ÿ  €ÿ@ €ÿ` €ÿ€ €ÿ  €ÿÀ €ÿà €ÿÀ€ÿ À€ÿ@À€ÿ`À€ÿ€À€ÿ À€ÿÀÀ€ÿàÀ€ÿà€ÿ à€ÿ@à€ÿ`à€ÿ€à€ÿ à€ÿÀà€ÿàà€ÿÀÿ Àÿ@Àÿ`Àÿ€Àÿ ÀÿÀÀÿàÀÿ Àÿ Àÿ@ Àÿ` Àÿ€ Àÿ  ÀÿÀ Àÿà Àÿ@Àÿ @Àÿ@@Àÿ`@Àÿ€@Àÿ @ÀÿÀ@Àÿà@Àÿ`Àÿ `Àÿ@`Àÿ``Àÿ€`Àÿ `ÀÿÀ`Àÿà`Àÿ€Àÿ €Àÿ@€Àÿ`€Àÿ€€Àÿ €ÀÿÀ€Àÿà€Àÿ Àÿ  Àÿ@ Àÿ` Àÿ€ Àÿ  ÀÿÀ Àÿà ÀÿÀÀÿ ÀÀÿ@ÀÀÿ`ÀÀÿ€ÀÀÿ ÀÀÿÿûðÿ  ¤ÿ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*v +.&"'","-")*ÿÿÿ"烢ø^zgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgÿÿÿÿgÿr z [Y\%C%]%X%\%U%4%@%^%`%g%M%S%i%cUW% { H?JÿÁ r£* H.ˆ££3rH* ¦‚wHò*Hòa/!4H2Problem loading the SmartCTF ScoreBoard...¿-k'H-Ä'  | GI4å r£* G.ˆ££3rG* ¦‚wGò*Gòa/!4G2Problem loading the SmartCTF ScoreBoard...ã-k-kG‹§r=,ÿG-Ä'  ä} %(Qr£*a(a Ö\!Öa?'  RV~X%*–X,@XQ*¥XX%/a0 R{w–X,@twR£*¥XQRz{10 D _JKH_%F–_,@'r_Q*F_Q¥_ áž( r*/a0 10á Ý@ #UŒÃ'±¯‹§B?-^(M-^#¨º8#œ#aÐTestOy#¨º#œ#aÐTestO#¨º#œ#aÐTestO1#¨º#œ#aÐTestOW«š™™?1«1š™™?W«WÍÌŒ?n«yÍÌL?MnV®®®®®«À?y«?,M«?,«1?,«W?,«n?,F¯¬#½?,¬V?, ¬#œ?, -^'B‹§n.ˆ£Ço#Z#n@#nS#nh#nP#n €Ék [}E[ &i ,h ',f 2,e =,g ÿÿ  H \$Dû:\Q ÞA (o> F(±$(”¯ M (6è D®¯(œ«?, «?,MV(±$6á(—$ 6î(—$ 6Ø(—$ (”¯ M (BÀ ÷®¯(œ«?, «?,M«À?y€?(±$(¨º8(œ(—A(-ý'(”® «€>y( aÑÀ'(-ý(¸ ®«À?yM p€üE ZZz Þ—A¨ºœaÐTEMPZY”   aÑø'—`¨ºœaÐTEMPQX” ®  aÑÿ'” ®® 1 aÑþ'#” ®® «?,1 aÑý'—U#”® «Q?,® aÑ]ò'*”® «Q?,®® 1M{]ÞaÑ]Þ'_ aÑñ'/”® «Q?,®® «?,1Ê{]ÎaÑ]Î'Ü aÑñ' L L9öl rL**p%h–p,@4rpQ*h^rpQ£LpQ¥p* v€K …M …O N )uNa/!]*P.‰NŸ>rP**v%™–v,@ervQ*™rvQ£PvQ¥vE* Q ÁG @ƒê¸ —A ¨º œ aÐTEMPWV ”« ?,  aÑ÷' —U ¨º œ aÐTEMPXR aÐvÙXR ”« ?,®  aÑvÙ' aÐvôXR #”« ?,®® 1 aÑvô' aÐvêXR (”« ?,®® «?,1 aÑvê' aÐvçXR (”« ?,®® «?,1 aÑvç'¸ ®®«?,1n äP %!à Ö|¢ a?' €@ÒC UG5HU &ó ,ó ',d 2,c =,b ÿÿó  €‡ÑmUnrm£*m`‚m£a/!_m£a/!umˆ.‰m£-¾ma mm  ÄN +S¨às+—A+¨º+œ+aÐTEMPSO+”  + aÑñ'+—`+¨º+œ+aÐTEMPH~+” ® + aÑò'+” ®® 1+ aÑó'+—U+”« ?,® +aÑSmart Capture The Flag'N% –N, ‚wNp€·*Np€·-ï¥d¥N³+#”« ?,®® 1+/aÑp¨ppSpã [Sdô]' âTypò£›.‰£-¾y.›.‰£ŸÂ›wy*y TÕ?.‰£ ݨ.‰£Ÿ´Tâ X …Y …€\åJ] H }"¯«¬ì@D{«?,|  hclass SmartCTFSpreeMsg expands KillingSpreeMessage; static function string GetString( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { if( RelatedPRI_1 != None ) { if( Switch == 5 ) return default.SpreeNote[Switch] @ RelatedPRI_1.PlayerName $ "!"; if( Switch == 6 ) return RelatedPRI_1.PlayerName @ class'TournamentPlayer'.default.SpreeNote[3]; } return ""; } |€ÃU )hÍÓ/)—A)¨º)œ)aÐTEMPyx)”« ?, ) aÑð')—`)¨º)œ)aÐTEMPws)”« ?,® ) aÑí')#”« ?,®® 1) aÑÈ')—Uj.šz)”« è@® )aÑSjì')%”« è@®® 1)aÑSjü'¸ ®®«?,1n Gclass SmartCTFSpawnNotifyPRI expands SpawnNotify; simulated event Actor SpawnNotification( Actor A ) { if( A.Owner == None ) return A; if( !A.Owner.IsA( 'PlayerPawn' ) && !A.Owner.IsA( 'Bot' ) ) return A; if( !Pawn( A.Owner ).bIsPlayer ) return A; // Spawn SmartCTF PRI for this pawn on the server Spawn( class'SmartCTFPlayerReplicationInfo', A ); return A; } @ÿÿÿÿÿÿÿÿÿ ÿ ÿ ÿ ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*` +.&"@'"@,"@-"@)*;* ÿ"v­¢ø^Š‘@@                                                  @@š•@                         ª–@           ú–@    — ,—<—€É[ tm rF*t /%¨F´J I&¨F´C d,¨F´E ,¨F´G Ÿ,p¨AF´! º, ¨F´ È’%,@I Ö’&,@B å’,,@D ô’,,@F ’,,@@ ÿÿ  e …z Þ^ PôºJ—Ah¬¯®W?,?,@¨ºœ”® «?,Dh  aÑÎ'—U±$-Þ(”  ¼ íh”  -Þ'±$¨º(œ—`”«  @®  aÑÌ'”« p@®  aÑÍ'”« ¸@®  aÑ`'”« ð@®  aÑË'—Uw*~Hw*h%H–h,h D%HGreatest Point 'Hoe¨S6-(ipoints/hE6F(iA6J(in6B(i Ð&HBiggest DM'ere¨S6-(lfrags/hE6F(lA6J(ln6B(l ^,HBest Flagcappere¨S6-(_caps/hE6F(_A6J(_n6B(_ î,HBest Flagkillere¨S6-(bflagk./hE6F(bA6J(bn6B(b y,HMost Covere¨S6-(gcovers/hE6F(gA6J(gn6B(g ,HHardcore Snipere¨S6-(aHS/hE6F(aA6J(an6B(a ÿÿzee--4zEE--JzAA--`znn--ƒ—}A,Ap€A,..¦—}E,Ep€E,..—`)” ®® «?’h&W aÑH'—U0”«  @®® «?’h&W aÑe'0”« p@®® «?’h&W aÑE'0”« ¸@®® «?’h&W aÑA'0”« ð@®® «?’h&W aÑn'¥hŸ B¥class SmartCTFServerInfo expands ServerInfoCTF; var SmartCTFGameReplicationInfo SCTFGame; var PlayerPawn PlayerOwner; var string MapNameText; var bool bFontUpdated; var float LastUpdateTime; var float HeaderHeight, CatHeight, TextHeight, SmallTextHeight, VSpacing, BorderSpacing, TotalHeight; var float StartY, Y, SideSpacing; var Color HeaderBlue, TextBlue, InfoWhite; function PostBeginPlay() { if( SCTFGame == None ) { ForEach AllActors( class'SmartCTFGameReplicationInfo', SCTFGame ) break; } super.PostBeginPlay(); } function RenderInfo( Canvas C ) { local float XL; local GameReplicationInfo GRI; if( Level.TimeSeconds - LastUpdateTime > 0.5 ) bFontUpdated = False; if( !bFontUpdated ) { C.Font = MyFonts.GetHugeFont( C.ClipX ); C.StrLen( "Test", XL, HeaderHeight ); C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( "Test", XL, CatHeight ); C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "Test", XL, TextHeight ); C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "Test", XL, SmallTextHeight ); CatHeight = CatHeight * 1.2; TextHeight = TextHeight * 1.2; SmallTextHeight = SmallTextHeight * 1.1; VSpacing = HeaderHeight * 0.8; BorderSpacing = VSpacing; TotalHeight = 1.5 * HeaderHeight + 2 * BorderSpacing + CatHeight * 3 + TextHeight * 6 + SmallTextHeight * 7 + VSpacing * 3; StartY = C.ClipY / 2 - TotalHeight / 2; SideSpacing = C.ClipX / 10; bFontUpdated = True; LastUpdateTime = Level.TimeSeconds; } GRI = PlayerPawn(Owner).GameReplicationInfo; DrawTitle( C ); DrawContactInfo( C, GRI ); DrawMOTD( C, GRI ); DrawGameStats( C, GRI ); DrawServerStats( C, GRI ); DrawLeaderBoard( C, GRI ); } function DrawTitle( Canvas C ) { Y = StartY; C.Style = ERenderStyle.STY_Modulated; C.SetPos( SideSpacing - BorderSpacing, Y ); C.DrawRect( texture'shade', C.ClipX - 2 * SideSpacing + 2 * BorderSpacing , TotalHeight ); C.Style = ERenderStyle.STY_Translucent; C.DrawColor.R = 32; C.DrawColor.G = 32; C.DrawColor.B = 32; C.SetPos( SideSpacing - BorderSpacing, Y ); C.DrawPattern( texture'newblue', C.ClipX - 2 * SideSpacing + 2 * BorderSpacing , 1.5 * HeaderHeight, 1.0 ); C.Style = ERenderStyle.STY_Normal; C.Font = MyFonts.GetHugeFont( C.ClipX ); C.DrawColor = HeaderBlue; C.bCenter = True; C.SetPos( 0, Y + 0.25 * HeaderHeight ); C.DrawText( ServerInfoText, True ); C.bCenter = False; Y += 1.5 * HeaderHeight + BorderSpacing; } function DrawContactInfo( Canvas C, GameReplicationInfo GRI ) { local float XL, YL, XL2, YL2; C.DrawColor = HeaderBlue; C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( "TEMP", XL, YL ); C.SetPos( SideSpacing, Y ); C.DrawText( ContactInfoText, True); C.DrawColor = TextBlue; C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "TEMP", XL2, YL2 ); C.SetPos( SideSpacing, Y + CatHeight ); C.DrawText( NameText, True); C.SetPos( SideSpacing, Y + CatHeight + TextHeight ); C.DrawText( AdminText, True); C.SetPos( SideSpacing, Y + CatHeight + 2 * TextHeight); C.DrawText( EMailText, True); C.DrawColor = InfoWhite; C.SetPos( SideSpacing + XL2 * 2, Y + CatHeight ); C.DrawText( GRI.ServerName, True); C.SetPos( SideSpacing + XL2 * 2, Y + CatHeight + TextHeight ); if( GRI.AdminName != "" ) C.DrawText( GRI.AdminName, True ); else C.DrawText( UnknownText, True ); C.SetPos( SideSpacing + XL2 * 2, Y + CatHeight + 2 * TextHeight ); if( GRI.AdminEmail != "" ) C.DrawText( GRI.AdminEmail, True ); else C.DrawText( UnknownText, True ); } function DrawMOTD( Canvas C, GameReplicationInfo GRI ) { local float XL, YL, XL2, YL2; C.DrawColor = HeaderBlue; C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( "TEMP", XL, YL ); C.SetPos( SideSpacing * 6, Y ); C.DrawText( MOTD, True ); C.DrawColor = InfoWhite; C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "TEMP", XL2, YL2 ); C.StrLen( GRI.MOTDLine1, XL2, YL2 ); C.SetPos( SideSpacing * 6, Y + CatHeight ); C.DrawText( GRI.MOTDLine1, True ); C.StrLen( GRI.MOTDLine2, XL2, YL2 ); C.SetPos( SideSpacing * 6, Y + CatHeight + TextHeight ); C.DrawText( GRI.MOTDLine2, True ); C.StrLen( GRI.MOTDLine3, XL2, YL2 ); C.SetPos( SideSpacing * 6, Y + CatHeight + 2 * TextHeight ); C.DrawText( GRI.MOTDLine3, True ); C.StrLen( GRI.MOTDLine4, XL2, YL2 ); C.SetPos( SideSpacing * 6, Y + CatHeight + 3 * TextHeight ); C.DrawText( GRI.MOTDLine4, True ); Y += CatHeight + 4 * TextHeight + VSpacing; } function DrawGameStats( Canvas C, GameReplicationInfo GRI ) { local float XL, YL, XL2, YL2; local int i, NumBots; C.DrawColor = HeaderBlue; C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( "TEMP", XL, YL ); C.SetPos( SideSpacing, Y ); C.DrawText( GameStatsText, True ); C.DrawColor = TextBlue; C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "TEMP", XL2, YL2 ); C.SetPos( SideSpacing, Y + CatHeight ); C.DrawText( GameTypeText, True ); C.SetPos( SideSpacing, Y + CatHeight + TextHeight ); C.DrawText( PlayersText, True ); C.DrawColor = InfoWhite; C.SetPos( SideSpacing * 2, Y + CatHeight ); C.DrawText( "Smart Capture The Flag", True); // GRI.GameName for( i = 0; i < 32; i++ ) { if( ( GRI.PRIArray[i] != None ) && ( GRI.PRIArray[i].bIsABot ) ) NumBots++; } C.SetPos( SideSpacing * 2, Y + CatHeight + TextHeight ); C.DrawText( GRI.NumPlayers $ " [" $ NumBots @ BotText $ "]", True ); } function DrawServerStats( canvas C, GameReplicationInfo GRI ) { local float XL, YL, XL2, YL2; local TournamentGameReplicationInfo TGRI; C.DrawColor = HeaderBlue; C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( "TEMP", XL, YL ); C.SetPos( SideSpacing * 6, Y ); C.DrawText( ServerStatsText, True ); C.DrawColor = TextBlue; C.Font = MyFonts.GetSmallFont( C.ClipX ); C.StrLen( "TEMP", XL2, YL2 ); C.SetPos( SideSpacing * 6, Y + CatHeight ); C.DrawText( GamesHostedText, True); C.SetPos( SideSpacing * 6, Y + CatHeight + TextHeight ); C.DrawText( FlagsCapturedText, True); C.DrawColor = InfoWhite; TGRI = TournamentGameReplicationInfo( GRI ); C.SetPos( SideSpacing * 7.25, Y + CatHeight ); C.DrawText( TGRI.TotalGames, True ); C.SetPos( SideSpacing * 7.25, Y + CatHeight + TextHeight ); C.DrawText( TGRI.TotalFlags, True ); Y += CatHeight + 2 * TextHeight + VSpacing; } function DrawLeaderBoard( Canvas C, GameReplicationInfo GRI ) { local float YL; local int i; local SmartCTFEndStats EndStats; local string Title, What, Who, Where, When; C.DrawColor = HeaderBlue; YL = ( CatHeight + SmallTextHeight - 4 ) / 64; C.Font = MyFonts.GetBigFont( C.ClipX ); C.SetPos( SideSpacing + 68 * YL, Y ); C.DrawText( TopPlayersText, True ); C.DrawColor = InfoWhite; C.Style = ERenderStyle.STY_Translucent; C.bNoSmooth = False; C.SetPos( SideSpacing, Y ); C.DrawIcon( texture'UTMenu.TrophyCTF', YL ); C.SetPos( SideSpacing, Y ); C.bNoSmooth = True; C.Style = ERenderStyle.STY_Normal; C.Font = MyFonts.GetSmallestFont( C.ClipX ); C.DrawColor = TextBlue; C.SetPos( SideSpacing * 2.5, Y + CatHeight ); C.DrawText( BestFPHText, True ); C.SetPos( SideSpacing * 3.75, Y + CatHeight ); C.DrawText( BestNameText, True ); C.SetPos( SideSpacing * 5.75, Y + CatHeight ); C.DrawText( MapNameText, True ); C.SetPos( SideSpacing * 7.5, Y + CatHeight ); C.DrawText( BestRecordSetText, True ); C.DrawColor = InfoWhite; if( SCTFGame != None ) EndStats = SCTFGame.EndStats; if( EndStats != None ) { for( i = 0; i < 6; i++ ) { switch( i ) { case 0: Title = "Greatest Point 'Ho"; What = EndStats.MostPoints.Count @ "points/h"; Who = EndStats.MostPoints.PlayerName; Where = EndStats.MostPoints.MapName; When = EndStats.MostPoints.RecordDate; break; case 1: Title = "Biggest DM'er"; What = EndStats.MostFrags.Count @ "frags/h"; Who = EndStats.MostFrags.PlayerName; Where = EndStats.MostFrags.MapName; When = EndStats.MostFrags.RecordDate; break; case 2: Title = "Best Flagcapper"; What = EndStats.MostCaps.Count @ "caps/h"; Who = EndStats.MostCaps.PlayerName; Where = EndStats.MostCaps.MapName; When = EndStats.MostCaps.RecordDate; break; case 3: Title = "Best Flagkiller"; What = EndStats.MostFlagkills.Count @ "flagk./h"; Who = EndStats.MostFlagkills.PlayerName; Where = EndStats.MostFlagkills.MapName; When = EndStats.MostFlagkills.RecordDate; break; case 4: Title = "Most Cover"; What = EndStats.MostCovers.Count @ "covers/h"; Who = EndStats.MostCovers.PlayerName; Where = EndStats.MostCovers.MapName; When = EndStats.MostCovers.RecordDate; break; case 5: Title = "Hardcore Sniper"; What = EndStats.MostHeadShots.Count @ "HS/h"; Who = EndStats.MostHeadShots.PlayerName; Where = EndStats.MostHeadShots.MapName; When = EndStats.MostHeadShots.RecordDate; break; } if( What == "" ) What = "--"; if( Who == "" ) Who = "--"; if( Where == "" ) Where = "--"; if( When == "" ) When = "--"; if( Len( Where ) > 20 ) Where = Left( Where, 20 ) $ ".."; if( Len( Who ) > 25 ) Who = Left( Who, 25 ) $ ".."; C.DrawColor = TextBlue; C.SetPos( SideSpacing, Y + CatHeight + ( ( i + 1 ) * SmallTextHeight ) ); C.DrawText( Title, True ); C.DrawColor = InfoWhite; C.SetPos( SideSpacing * 2.5, Y + CatHeight + ( ( i + 1 ) * SmallTextHeight ) ); C.DrawText( What, True ); C.SetPos( SideSpacing * 3.75, Y + CatHeight + ( ( i + 1 ) * SmallTextHeight ) ); C.DrawText( Who, True ); C.SetPos( SideSpacing * 5.75, Y + CatHeight + ( ( i + 1 ) * SmallTextHeight ) ); C.DrawText( Where, True ); C.SetPos( SideSpacing * 7.5, Y + CatHeight + ( ( i + 1 ) * SmallTextHeight ) ); C.DrawText( When, True ); } } } h€•dclass SmartCTFServerActor expands Actor; function PostBeginPlay() { if( CTFGame( Level.Game ) != None ) { Log( "ServerActor, Spawning and adding Mutator...", 'SmartCTF' ); Level.Game.BaseMutator.AddMutator( Level.Game.Spawn( class'SmartCTF' ) ); } Destroy(); } ‡i { {ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿj ðÿ臜ÔX†Ž”†Ž”Ž©Ù«¢=$:e†Ž”Ž©Ù« cÓ_¾class SmartCTFScoreBoard extends UnrealCTFScoreBoard; #exec texture IMPORT NAME=faceless File=Textures\faceless.pcx GROUP=SmartCTF var ScoreBoard NormalScoreBoard; var SmartCTFGameReplicationInfo SCTFGame; var SmartCTFPlayerReplicationInfo OwnerStats; var int TryCount; var PlayerPawn PlayerOwner; var string PtsText, FragsText, SepText, MoreText, HeaderText; var int LastSortTime, MaxMeterWidth; var byte ColorChangeSpeed, RowColState; var Color White, Gray, DarkGray, Yellow, RedTeamColor, BlueTeamColor, RedHeaderColor, BlueHeaderColor, StatsColor, FooterColor, HeaderColor, TinyInfoColor, HeaderTinyInfoColor; var float StatsTextWidth, StatHeight, MeterHeight, NameHeight, ColumnHeight, StatBlockHeight; var float RedStartX, BlueStartX, ColumnWidth, StatWidth, StatsHorSpacing, ShadingSpacingX, HeaderShadingSpacingY, ColumnShadingSpacingY; var float StartY, StatLineHeight, StatBlockSpacing, StatIndent; var TournamentGameReplicationInfo pTGRI; var PlayerReplicationInfo pPRI; var Font StatFont, CapFont, FooterFont, GameEndedFont, PlayerNameFont, FragsFont, TinyInfoFont; var Font PtsFont22, PtsFont20, PtsFont18, PtsFont16, PtsFont14, PtsFont12; var int MaxCaps, MaxAssists, MaxGrabs, MaxCovers, MaxSeals, MaxFlagKills, MaxFrags, MaxDeaths; var int TotShieldBelts, TotAmps; function PostBeginPlay() { super.PostBeginPlay(); PlayerOwner = PlayerPawn( Owner ); pTGRI = TournamentGameReplicationInfo( PlayerOwner.GameReplicationInfo ); pPRI = PlayerOwner.PlayerReplicationInfo; LastSortTime = -100; // Preload PtsFont22 = Font( DynamicLoadObject( "LadderFonts.UTLadder22", class'Font' ) ); PtsFont20 = Font( DynamicLoadObject( "LadderFonts.UTLadder20", class'Font' ) ); PtsFont18 = Font( DynamicLoadObject( "LadderFonts.UTLadder18", class'Font' ) ); PtsFont16 = Font( DynamicLoadObject( "LadderFonts.UTLadder16", class'Font' ) ); PtsFont14 = Font( DynamicLoadObject( "LadderFonts.UTLadder14", class'Font' ) ); PtsFont12 = Font( DynamicLoadObject( "LadderFonts.UTLadder12", class'Font' ) ); SpawnNormalScoreBoard(); if( NormalScoreBoard == None ) SetTimer( 1.0 , True ); } // Try to spawn a local instance of the original scoreboard class if it doesn't exist already. function SpawnNormalScoreBoard() { if( SCTFGame == None ) { ForEach AllActors( class'SmartCTFGameReplicationInfo', SCTFGame ) break; } if( SCTFGame != None ) OwnerStats = SCTFGame.GetStats( PlayerOwner ); if( SCTFGame != None && SCTFGame.NormalScoreBoardClass == None ) { Log( "Unable to identify original ScoreBoard type. Retrying in 1 second." , 'SmartCTF' ); return; } if( SCTFGame != None && SCTFGame.NormalScoreBoardClass == self.Class ) { NormalScoreBoard = Spawn( class'UnrealCTFScoreBoard', PlayerOwner ); Log( "Cannot use itself. Using the default CTF ScoreBoard instead." , 'SmartCTF' ); return; } if( SCTFGame != None && SCTFGame.NormalScoreBoardClass != None ) { NormalScoreBoard = Spawn( SCTFGame.NormalScoreBoardClass, PlayerOwner ); Log( "Determined and spawned original scoreboard as" @ NormalScoreBoard, 'SmartCTF' ); } } // In the case of the 'normal scoreboard' not being replicated properly, try every second to see if it has. function Timer() { if( NormalScoreBoard == None ) { TryCount++; SpawnNormalScoreBoard(); } if( NormalScoreBoard != None ) { SetTimer( 0.0, False ); } else if( TryCount > 3 ) { Log( "Given up. Using the default CTF ScoreBoard instead." , 'SmartCTF' ); if( NormalScoreBoard == None ) { NormalScoreBoard = Spawn( class'UnrealCTFScoreBoard', PlayerOwner ); Log( "Spawned as" @ NormalScoreBoard, 'SmartCTF' ); } SetTimer( 0.0, False ); } } function ShowScores( Canvas C ) { if( SCTFGame == None || OwnerStats == None ) { if( NormalScoreBoard != None ) NormalScoreBoard.ShowScores( C ); else PlayerOwner.bShowScores = False; return; } if( OwnerStats.bViewingStats ) { SmartCTFShowScores( C ); } else { if( NormalScoreBoard == None ) SmartCTFShowScores( C ); else NormalScoreBoard.ShowScores( C ); } if( OwnerStats.IndicatorVisibility > 0 ) ShowIndicator( C ); } function ShowIndicator( Canvas C ) { local float BlockLen, LineHeight; C.DrawColor.R = OwnerStats.IndicatorVisibility; C.DrawColor.G = OwnerStats.IndicatorVisibility; C.DrawColor.B = OwnerStats.IndicatorVisibility; C.Style = ERenderStyle.STY_Translucent; C.Font = C.SmallFont; C.StrLen( "Scoreboard:", BlockLen, LineHeight ); C.SetPos( C.ClipX - BlockLen - 16, 16 ); C.DrawText( "Scoreboard:" ); C.SetPos( C.ClipX - BlockLen, 16 + LineHeight ); C.DrawText( "Default" ); C.SetPos( C.ClipX - BlockLen, 16 + 2 * LineHeight ); C.DrawText( "SmartCTF" ); if( OwnerStats.bViewingStats ) C.SetPos( C.ClipX - BlockLen - 16, 16 + 2 * LineHeight ); else C.SetPos( C.ClipX - BlockLen - 16, 16 + LineHeight ); C.DrawIcon( texture'UWindow.MenuTick', 1 ); C.Style = ERenderStyle.STY_Normal; if( Level.TimeSeconds - OwnerStats.IndicatorStartShow > 2 ) OwnerStats.IndicatorVisibility = 0; } function SmartCTFShowScores( Canvas C ) { local int ID, i, j, Time, AvgPing, AvgPL, TotSB, TotAmp; local float Eff; local int RedY, BlueY, X, Y; local float Nil, DummyX, DummyY, SizeX, SizeY, Buffer, Size; local byte LabelDrawn[2], Rendered[2]; local Color TeamColor, TempColor; local string TempStr; local SmartCTFPlayerReplicationInfo PlayerStats, PlayerStats2; if( Level.TimeSeconds - LastSortTime > 0.5 ) { SortScores( 32 ); RecountNumbers(); InitStatBoardConstPos( C ); CompressStatBoard( C ); LastSortTime = Level.TimeSeconds; } Y = int( StartY ); RedY = Y; BlueY = Y; C.Style = ERenderStyle.STY_Normal; // FOR EACH PLAYER DRAW INFO for( i = 0; i < 32; i++ ) { if( Ordered[i] == None ) break; PlayerStats = SCTFGame.GetStatsByPRI( Ordered[i] ); if( PlayerStats == None ) continue; // Get the ID of the ith player ID = Ordered[i].PlayerID; // set the pos depending on Team if( Ordered[i].Team == 0 ) { X = RedStartX; Y = RedY; TeamColor = RedTeamColor; } else { X = BlueStartX; Y = BlueY; TeamColor = BlueTeamColor; } C.DrawColor = TeamColor; if( LabelDrawn[Ordered[i].Team] == 0 ) { // DRAW THE Team SCORES with the cool Flag icons (masked because of black borders) C.bNoSmooth = False; C.Font = PlayerNameFont; C.Style = ERenderStyle.STY_Translucent; if( Ordered[i].Team == 0 ) C.DrawColor = RedHeaderColor; else C.DrawColor = BlueHeaderColor; C.StrLen( PtsText, SizeX, SizeY ); C.Style = ERenderStyle.STY_Modulated; C.SetPos( X - ShadingSpacingX, Y - HeaderShadingSpacingY ); C.DrawRect( texture'shade', ColumnWidth + ( ShadingSpacingX * 2 ) , SizeY + ( HeaderShadingSpacingY * 2 ) ); C.Style = ERenderStyle.STY_Translucent; C.SetPos( X - ShadingSpacingX, Y - HeaderShadingSpacingY ); if( Ordered[i].Team == 0 ) C.DrawPattern( texture'redskin2', ColumnWidth + ( ShadingSpacingX * 2 ) , SizeY + ( HeaderShadingSpacingY * 2 ) , 1 ); else C.DrawPattern( texture'blueskin2', ColumnWidth + ( ShadingSpacingX * 2 ) , SizeY + ( HeaderShadingSpacingY * 2 ) , 1 ); C.Style = ERenderStyle.STY_Modulated; C.SetPos( X - ShadingSpacingX, Y + SizeY + HeaderShadingSpacingY ); C.DrawRect( texture'shade', ColumnWidth + ( ShadingSpacingX * 2 ) , ColumnHeight + ( ColumnShadingSpacingY * 2 ) ); C.Style = ERenderStyle.STY_Translucent; C.DrawColor = TeamColor; C.SetPos( X, Y - ( ( 32 - SizeY ) / 2 ) ); // Y - 4 if( Ordered[i].Team == 0 ) C.DrawIcon( texture'I_TeamR', 0.5 ); else C.DrawIcon( texture'I_TeamB', 0.5 ); C.Font = CapFont; C.StrLen( int( pTGRI.Teams[Ordered[i].Team].Score ), DummyX, DummyY ); C.Style = ERenderStyle.STY_Normal; C.SetPos( X + StatIndent, Y - ( ( DummyY - SizeY ) / 2 ) ); C.DrawText( int( pTGRI.Teams[Ordered[i].Team].Score ) ); //Draw the Frags/Pts text C.Font = PlayerNameFont; C.SetPos( X + ColumnWidth - SizeX, Y ); C.DrawText( PtsText ); C.Font = FragsFont; C.StrLen( FragsText $ SepText, Buffer, Nil ); C.SetPos( X + ColumnWidth - SizeX - Buffer, Y ); C.DrawText( FragsText $ SepText ); C.DrawColor = HeaderTinyInfoColor; C.Font = TinyInfoFont; C.StrLen( "TEST", Nil, DummyY ); C.SetPos( X + StatIndent + DummyX + 2 * StatsHorSpacing, Y + ( SizeY - DummyY * 2 ) / 2 ); Time = Max( 1, Level.TimeSeconds / 60 ); AvgPing = 0; AvgPL = 0; TotSB = 0; TotAmp = 0; for( j = 0; j < 32; j++ ) { if( Ordered[j] == None ) break; if( Ordered[j].Team == Ordered[i].Team ) { PlayerStats2 = SCTFGame.GetStatsByPRI( Ordered[j] ); if( PlayerStats2 == None ) continue; AvgPing += Ordered[j].Ping; AvgPL += Ordered[j].PacketLoss; TotSB += PlayerStats2.ShieldBelts; TotAmp += PlayerStats2.Amps; } } if( pTGRI.Teams[Ordered[i].Team].Size != 0 ) { AvgPing = AvgPing / pTGRI.Teams[Ordered[i].Team].Size; AvgPL = AvgPL / pTGRI.Teams[Ordered[i].Team].Size; } if( TotShieldBelts == 0 ) TotSB = 0; else TotSB = Clamp( float( TotSB ) / float( TotShieldBelts ) * 100, 0, 100 ); if( TotAmps == 0 ) TotAmp = 0; else TotAmp = Clamp( float( TotAmp ) / float( TotAmps ) * 100, 0, 100 ); TempStr = "PING:" $ AvgPing $ " PL:" $ AvgPL $ "%"; C.DrawText( TempStr ); C.SetPos( X + StatIndent + DummyX + 2 * StatsHorSpacing, Y + ( SizeY - DummyY * 2 ) / 2 + DummyY ); TempStr = "TM:" $ Time; if( TotSB != 0 ) TempStr = TempStr @ "SB:" $ TotSB $ "%"; if( TotAmp != 0 ) TempStr = TempStr @ "AM:" $ TotAmp $ "%"; C.DrawText( TempStr ); C.bNoSmooth = True; Y += SizeY + HeaderShadingSpacingY + ColumnShadingSpacingY; LabelDrawn[Ordered[i].Team] = 1; } C.Font = FooterFont; C.StrLen( "Test", Nil, DummyY ); if( LabelDrawn[Ordered[i].Team] != 2 && ( Y + NameHeight + StatBlockHeight + StatBlockSpacing > C.ClipY - DummyY * 5 ) ) { C.DrawColor = TeamColor; C.StrLen( MoreText , Size, DummyY ); if( Ordered[i].Team == 1 ) C.SetPos( X + ColumnWidth - Size, C.ClipY - DummyY * 5 ); else C.SetPos( X, C.ClipY - DummyY * 5 ); C.DrawText( "[" @ pTGRI.Teams[Ordered[i].Team].Size - Rendered[Ordered[i].Team] @ MoreText @ "]" ); LabelDrawn[Ordered[i].Team] = 2; // "More" label also drawn } else if( LabelDrawn[Ordered[i].Team] != 2 ) { // Draw the face if( Ordered[i].HasFlag == None ) { C.bNoSmooth = False; C.DrawColor = White; C.Style = ERenderStyle.STY_Translucent; C.SetPos( X, Y ); if( SCTFGame.bStatsDrawFaces && Ordered[i].TalkTexture != None ) C.DrawIcon( Ordered[i].TalkTexture, 0.5 ); else C.DrawIcon( texture'faceless', 0.5 ); C.SetPos( X, Y ); C.DrawColor = DarkGray; C.DrawIcon( texture'IconSelection', 1 ); C.Style = ERenderStyle.STY_Normal; C.bNoSmooth = True; } // Draw the player name C.SetPos( X + StatIndent, Y ); C.Font = PlayerNameFont; if( Ordered[i].bAdmin ) C.DrawColor = White; else if( Ordered[i].PlayerID == pPRI.PlayerID ) C.DrawColor = Yellow; else C.DrawColor = TeamColor; TempColor = C.DrawColor; C.DrawText( Ordered[i].PlayerName ); C.StrLen( Ordered[i].PlayerName, Size, Buffer ); C.DrawColor = TinyInfoColor; C.Font = TinyInfoFont; C.StrLen( "TEST", Buffer, DummyY ); // Draw Time, Eff, HS, SB, Amp C.SetPos( X + StatIndent + Size + StatsHorSpacing, Y + ( NameHeight - DummyY * 2 ) / 2 ); TempStr = ""; if( PlayerStats.HeadShots != 0 ) TempStr = TempStr $ "HS:" $ PlayerStats.HeadShots; if( PlayerStats.ShieldBelts != 0 ) TempStr = TempStr @ "SB:" $ PlayerStats.ShieldBelts; if( PlayerStats.Amps != 0 ) TempStr = TempStr @ "AM:" $ PlayerStats.Amps; if( Left( TempStr, 1 ) == " " ) TempStr = Mid( TempStr, 1 ); C.DrawText( TempStr ); Time = Max( 1, ( Level.TimeSeconds + pPRI.StartTime - Ordered[i].StartTime ) / 60 ); if( PlayerStats.Frags + Ordered[i].Deaths == 0 ) Eff = 0; else Eff = ( PlayerStats.Frags / ( PlayerStats.Frags + Ordered[i].Deaths ) ) * 100; C.SetPos( X + StatIndent + Size + StatsHorSpacing, Y + ( NameHeight - DummyY * 2 ) / 2 + DummyY ); C.DrawText( "TM:" $ Time $ " EFF:" $ Clamp( int( Eff ), 0, 100 ) $ "%" ); // Draw Bot or Ping/PL C.SetPos( X, Y + StatIndent ); if( Ordered[i].bIsABot ) { C.DrawText( "BOT" ); if( Ordered[i].Team == pPRI.Team ) { C.SetPos( X, Y + StatIndent + DummyY ); C.DrawText( Left( string( BotReplicationInfo( Ordered[i] ).RealOrders ) , 3 ) ); } } else { C.DrawColor = HeaderTinyInfoColor; TempStr = "PI:" $ Ordered[i].Ping; if( Len( TempStr ) > 5 ) TempStr = "P:" $ Ordered[i].Ping; if( Len( TempStr ) > 5 ) TempStr = string( Ordered[i].Ping ); C.DrawText( TempStr ); C.SetPos( X, Y + StatIndent + DummyY ); TempStr = "PL:" $ Ordered[i].PacketLoss $ "%"; if( Len( TempStr ) > 5 ) TempStr = "L:" $ Ordered[i].PacketLoss $ "%"; if( Len( TempStr ) > 5 ) TempStr = "L:" $ Ordered[i].PacketLoss; if( Len( TempStr ) > 5 ) TempStr = Ordered[i].PacketLoss $ "%"; C.DrawText( TempStr ); } // Draw the Flag if he has Flag if( Ordered[i].HasFlag != None ) { C.DrawColor = White; C.SetPos( X, Y ); if( Ordered[i].HasFlag.IsA( 'GreenFlag' ) ) C.DrawIcon( texture'GreenFlag', 1 ); else if( Ordered[i].HasFlag.IsA( 'YellowFlag' ) ) C.DrawIcon( texture'YellowFlag', 1 ); else if( Ordered[i].Team == 0 ) C.DrawIcon( texture'BlueFlag', 1 ); else C.DrawIcon( texture'RedFlag', 1 ); } // End if he has Flag C.Font = PlayerNameFont; C.DrawColor = TempColor; // Draw Frag/Score C.StrLen( int( Ordered[i].Score ), Size, DummyY ); C.SetPos( X + ColumnWidth - Size, Y ); C.DrawText( int( Ordered[i].Score ) ); C.Font = FragsFont; C.StrLen( PlayerStats.Frags $ SepText, Buffer, SizeY ); C.SetPos( X + ColumnWidth - Size - Buffer, Y ); C.DrawText( PlayerStats.Frags $ SepText ); Y += NameHeight; // Set the Font for the stat drawing C.Font = StatFont; if( RowColState == 1 ) { DrawStatType( C, X, Y, 1, 1, "Caps: ", PlayerStats.Captures, MaxCaps ); DrawStatType( C, X, Y, 1, 2, "Assists: ", PlayerStats.Assists, MaxAssists ); DrawStatType( C, X, Y, 1, 3, "Grabs: ", PlayerStats.Grabs, MaxGrabs ); DrawStatType( C, X, Y, 2, 1, "Covers: ", PlayerStats.Covers, MaxCovers ); if( MaxSeals > 0 ) DrawStatType( C, X, Y, 2, 2, "Seals: ", PlayerStats.Seals, MaxSeals ); else DrawStatType( C, X, Y, 2, 2, "Deaths: ", Ordered[i].Deaths, MaxDeaths ); DrawStatType( C, X, Y, 2, 3, "FlagKls: ", PlayerStats.FlagKills, MaxFlagKills ); } else { DrawStatType( C, X, Y, 1, 1, "Caps: ", PlayerStats.Captures, MaxCaps ); DrawStatType( C, X, Y, 1, 2, "Covers: ", PlayerStats.Covers, MaxCovers ); DrawStatType( C, X, Y, 2, 1, "Grabs: ", PlayerStats.Grabs, MaxGrabs ); if( MaxSeals > 0 ) DrawStatType( C, X, Y, 2, 2, "Seals: ", PlayerStats.Seals, MaxSeals ); else DrawStatType( C, X, Y, 2, 2, "Deaths: ", Ordered[i].Deaths, MaxDeaths ); DrawStatType( C, X, Y, 3, 1, "Assists: ", PlayerStats.Assists, MaxAssists ); DrawStatType( C, X, Y, 3, 2, "FlagKls: ", PlayerStats.FlagKills, MaxFlagKills ); } Y += StatBlockHeight + StatBlockSpacing; } // Alter the RedY or BlueY and do next player if( Ordered[i].Team == 0 ) RedY = Y; else BlueY = Y; Rendered[Ordered[i].Team]++; } //End of PRI for loop DrawHeader( C ); DrawFooters( C ); } function InitStatBoardConstPos( Canvas C ) { local float Nil, LeftSpacingPercent, MidSpacingPercent, RightSpacingPercent; CapFont = Font'LEDFont2'; //Font( DynamicLoadObject( "UWindowFonts.UTFont40", class'Font' ) ); FooterFont = MyFonts.GetSmallestFont( C.ClipX ); GameEndedFont = MyFonts.GetHugeFont( C.ClipX ); PlayerNameFont = MyFonts.GetBigFont( C.ClipX ); TinyInfoFont = C.SmallFont; if( PlayerNameFont == PtsFont22 ) FragsFont = PtsFont18; else if( PlayerNameFont == PtsFont20 ) FragsFont = PtsFont18; else if( PlayerNameFont == PtsFont18 ) FragsFont = PtsFont14; else if( PlayerNameFont == PtsFont16 ) FragsFont = PtsFont12; else FragsFont = font'SmallFont'; C.Font = PlayerNameFont; C.StrLen( "Player", Nil, NameHeight ); StartY = ( 120.0 / 1024.0 ) * C.ClipY; ColorChangeSpeed = 100; // Influences how 'fast' the color changes from white to green. Higher = faster. LeftSpacingPercent = 0.075; MidSpacingPercent = 0.15; RightSpacingPercent = 0.075; RedStartX = LeftSpacingPercent * C.ClipX; ColumnWidth = ( ( 1 - LeftSpacingPercent - MidSpacingPercent - RightSpacingPercent ) / 2 * C.ClipX ); BlueStartX = RedStartX + ColumnWidth + ( MidSpacingPercent * C.ClipX ); ShadingSpacingX = ( 10.0 / 1024.0 ) * C.ClipX; HeaderShadingSpacingY = ( 32 - NameHeight ) / 2 + ( ( 4.0 / 1024.0 ) * C.ClipX ); ColumnShadingSpacingY = ( 10.0 / 1024.0 ) * C.ClipX; StatsHorSpacing = ( 5.0 / 1024.0 ) * C.ClipX; StatIndent = ( 32 + StatsHorSpacing ); // For face + flag icons InitStatBoardDynamicPos( C ); } function InitStatBoardDynamicPos( Canvas C , optional int Rows , optional int Cols , optional Font NewStatFont , optional float LineSpacing , optional float BlockSpacing ) { if( Rows == 0 ) Rows = 3; if( Cols == 0 ) Cols = 2; if( LineSpacing == 0 ) LineSpacing = 0.9; if( BlockSpacing == 0 ) BlockSpacing = 1; if( Rows == 2 && Cols == 3 ) RowColState = 1; else RowColState = 0; StatWidth = ( ( ColumnWidth - StatIndent ) / Cols ) - ( StatsHorSpacing * ( Cols - 1 ) ); if( NewStatFont == None ) StatFont = MyFonts.GetSmallestFont( C.ClipX ); else StatFont = NewStatFont; C.Font = StatFont; C.StrLen( "FlagKls: 00", StatsTextWidth, StatHeight ); MaxMeterWidth = StatWidth - StatsTextWidth - StatsHorSpacing; StatLineHeight = StatHeight * LineSpacing; MeterHeight = Max( 1, StatLineHeight * 0.3 ); StatBlockSpacing = StatLineHeight * BlockSpacing; StatBlockHeight = Rows * StatLineHeight; if( pTGRI.Teams[0].Size > pTGRI.Teams[1].Size ) ColumnHeight = pTGRI.Teams[0].Size * ( NameHeight + StatBlockHeight + StatBlockSpacing ) - StatBlockSpacing; else ColumnHeight = pTGRI.Teams[1].Size * ( NameHeight + StatBlockHeight + StatBlockSpacing ) - StatBlockSpacing; } function CompressStatBoard( Canvas C , optional int Level ) { local float EndY, Nil, DummyY; C.Font = FooterFont; C.StrLen( "Test", Nil, DummyY ); EndY = StartY + ColumnHeight + ( ColumnShadingSpacingY * 2 ) + NameHeight + HeaderShadingSpacingY; if( EndY > C.ClipY - DummyY * 5 ) { if( Level == 0 ) { InitStatBoardDynamicPos( C, , , , 0.8 ); } else if( Level == 1 ) { InitStatBoardDynamicPos( C, 2, 3 ); } else if( Level == 2 ) { InitStatBoardDynamicPos( C, 2, 3, Font( DynamicLoadObject( "UWindowFonts.Tahoma10", class'Font' ) ) , 1.0 , 1.0 ); } else { // We did all the compression we can do. Draw 'More' labels later. // First find the columnheight for the amount of players that fit on it. ColumnHeight = int( ( C.ClipY - ( EndY - ColumnHeight ) - DummyY * 5 + StatBlockSpacing ) / ( NameHeight + StatBlockHeight + StatBlockSpacing ) ) * ( NameHeight + StatBlockHeight + StatBlockSpacing ) - StatBlockSpacing; return; } // Did some compression, see if we need more. CompressStatBoard( C , Level + 1 ); } // No compression at all or no more compression needed. return; } /* * Draw a specific stat * X, Y = Upper left corner of stats ( row,col: 1,1) */ function DrawStatType( Canvas C, int X, int Y, int Row, int Col, string Label, int Count, int Total ) { local float Size, DummyY; local int ColorChange, M; X += StatIndent + ( ( StatWidth + StatsHorSpacing ) * ( Col - 1 ) ); Y += ( StatLineHeight * ( Row - 1 ) ); C.DrawColor = StatsColor; C.SetPos( X, Y ); C.DrawText( Label ); C.StrLen( Count, Size, DummyY ); C.SetPos( X + StatsTextWidth - Size, Y ); C.DrawText( Count ); //text if( Count > 0 ) { ColorChange = ColorChangeSpeed * loge( Count ); if( ColorChange > 255 ) ColorChange = 255; C.DrawColor.R = StatsColor.R - ColorChange; C.DrawColor.B = StatsColor.B - ColorChange; } M = GetMeterLength( Count, Total ); C.SetPos( X + StatsTextWidth + StatsHorSpacing, Y + ( ( StatHeight - MeterHeight ) / 2 ) ); C.DrawRect( texture'meter', M, MeterHeight ); //meter } function DrawFooters( Canvas C ) { local float DummyX, DummyY, Nil, X1, Y1; local string TextStr; local string TimeStr; local int Hours, Minutes, Seconds; C.bCenter = True; C.Font = FooterFont; // Display server info in bottom center C.DrawColor = FooterColor; C.StrLen( "Test", DummyX, DummyY ); C.SetPos( 0, C.ClipY - DummyY ); TextStr = "Playing" @ Level.Title @ "on" @ pTGRI.ServerName; if( SCTFGame.TickRate > 0 ) TextStr = TextStr @ "(TR:" @ SCTFGame.TickRate $ ")"; C.DrawText( TextStr ); // Draw Time if( bTimeDown || ( PlayerOwner.GameReplicationInfo.RemainingTime > 0 ) ) { bTimeDown = True; if( PlayerOwner.GameReplicationInfo.RemainingTime <= 0 ) { TimeStr = RemainingTime $ "00:00"; } else { Minutes = PlayerOwner.GameReplicationInfo.RemainingTime / 60; Seconds = PlayerOwner.GameReplicationInfo.RemainingTime % 60; TimeStr = RemainingTime $ TwoDigitString( Minutes ) $ ":" $ TwoDigitString( Seconds ); } } else { Seconds = PlayerOwner.GameReplicationInfo.ElapsedTime; Minutes = Seconds / 60; Hours = Minutes / 60; Seconds = Seconds - ( Minutes * 60 ); Minutes = Minutes - ( Hours * 60 ); TimeStr = ElapsedTime $ TwoDigitString( Hours ) $ ":" $ TwoDigitString( Minutes ) $ ":" $ TwoDigitString( Seconds ); } C.SetPos( 0, C.ClipY - 2 * DummyY ); C.DrawText( "Current Time:" @ GetTimeStr() @ "|" @ TimeStr ); // Draw Author C.StrLen( HeaderText, DummyX, Nil ); C.Style = ERenderStyle.STY_Normal; C.DrawColor = Yellow; C.SetPos( 0, C.ClipY - 4 * DummyY ); C.DrawText( HeaderText ); C.bCenter = False; } function DrawHeader( Canvas C ) { local float DummyX, DummyY; if( pTGRI.GameEndedComments == "" ) return; C.Font = GameEndedFont; C.StrLen( pTGRI.GameEndedComments, DummyX, DummyY ); C.DrawColor = DarkGray; C.Style = ERenderStyle.STY_Translucent; C.SetPos( C.ClipX / 2 - DummyX / 2 + 2, DummyY + 2 ); C.DrawText( pTGRI.GameEndedComments ); C.DrawColor = HeaderColor; C.Style = ERenderStyle.STY_Normal; C.SetPos( C.ClipX / 2 - DummyX / 2, DummyY ); C.DrawText( pTGRI.GameEndedComments ); } /* * Returns time and date in a string. */ function string GetTimeStr() { local string Mon, Day, Min; Min = string( PlayerOwner.Level.Minute ); if( int( Min ) < 10 ) Min = "0" $ Min; switch( PlayerOwner.Level.month ) { case 1: Mon = "Jan"; break; case 2: Mon = "Feb"; break; case 3: Mon = "Mar"; break; case 4: Mon = "Apr"; break; case 5: Mon = "May"; break; case 6: Mon = "Jun"; break; case 7: Mon = "Jul"; break; case 8: Mon = "Aug"; break; case 9: Mon = "Sep"; break; case 10: Mon = "Oct"; break; case 11: Mon = "Nov"; break; case 12: Mon = "Dec"; break; } switch( PlayerOwner.Level.dayOfWeek ) { case 0: Day = "Sunday"; break; case 1: Day = "Monday"; break; case 2: Day = "Tuesday"; break; case 3: Day = "Wednesday"; break; case 4: Day = "Thursday"; break; case 5: Day = "Friday"; break; case 6: Day = "Saturday"; break; } return Day @ PlayerOwner.Level.Day @ Mon @ PlayerOwner.Level.Year $ "," @ PlayerOwner.Level.Hour $ ":" $ Min; } /* * Length of a meter drawing for a given number A out of B total. */ function int GetMeterLength( int A, int B ) { local int Result; if( B == 0 ) return 0; Result = ( A * MaxMeterWidth ) / B; if( Result > MaxMeterWidth ) return MaxMeterWidth; else return Result; } /* * Sort PlayerReplicationInfo's on score. */ function SortScores( int N ) { local byte i, j; local bool bSorted; local SmartCTFPlayerReplicationInfo PlayerStats1, PlayerStats2; // Copy PRI array except for spectators. j = 0; for( i = 0; i < N; i++ ) { if( pTGRI.priArray[i] == None ) break; if( pTGRI.priArray[i].bIsSpectator && !pTGRI.priArray[i].bWaitingPlayer ) continue; Ordered[j] = pTGRI.priArray[i]; j++; } // Clear the remaining entries. for( i = j; i < N; i++ ) { Ordered[i] = None; } for( i = 0; i < N; i++) { bSorted = True; for( j = 0; j < N - 1; j++) { if( Ordered[j] == None || Ordered[j+1] == None ) break; if( Ordered[j].Score < Ordered[j+1].Score ) { SwapOrdered( j, j + 1 ); bSorted = False; } else if( Ordered[j].Score == Ordered[j+1].Score ) { PlayerStats1 = SCTFGame.GetStatsByPRI( Ordered[j] ); PlayerStats2 = SCTFGame.GetStatsByPRI( Ordered[j+1] ); if( PlayerStats1 != None && PlayerStats2 != None ) { if( PlayerStats1.Frags < PlayerStats2.Frags ) { SwapOrdered( j, j + 1 ); bSorted = False; } else if( PlayerStats1.Frags == PlayerStats2.Frags ) { if( Ordered[j].Deaths > Ordered[j+1].Deaths ) { SwapOrdered( j, j + 1 ); bSorted = False; } } } } } if( bSorted ) break; } } /* * Used for sorting. */ function SwapOrdered( byte A, byte B ) { local PlayerReplicationInfo Temp; Temp = Ordered[A]; Ordered[A] = Ordered[B]; Ordered[B] = Temp; } /* * Recalculate the totals for displaying meters on the scoreboards. * This way it doesn't get calculated every tick. */ function RecountNumbers() { local byte ID, i; local SmartCTFPlayerReplicationInfo PlayerStats; MaxCaps = 0; MaxAssists = 0; MaxGrabs = 0; MaxCovers = 0; MaxSeals = 0; MaxFlagKills = 0; MaxFrags = 0; MaxDeaths = 0; TotShieldBelts = 0; TotAmps = 0; for( i = 0; i < 32; i++ ) { if( Ordered[i] == None ) break; if( Ordered[i].bIsSpectator && !Ordered[i].bWaitingPlayer ) continue; ID = Ordered[i].PlayerID; PlayerStats = SCTFGame.GetStatsByPRI( Ordered[i] ); if( PlayerStats != None ) { if( PlayerStats.Captures > MaxCaps ) MaxCaps = PlayerStats.Captures; if( PlayerStats.Assists > MaxAssists ) MaxAssists = PlayerStats.Assists; if( PlayerStats.Grabs > MaxGrabs ) MaxGrabs = PlayerStats.Grabs; if( PlayerStats.Covers > MaxCovers ) MaxCovers = PlayerStats.Covers; if( PlayerStats.Seals > MaxSeals ) MaxSeals = PlayerStats.Seals; if( PlayerStats.FlagKills > MaxFlagKills ) MaxFlagKills = PlayerStats.FlagKills; if( PlayerStats.Frags > MaxFrags ) MaxFrags = PlayerStats.Frags; TotShieldBelts += PlayerStats.ShieldBelts; TotAmps += PlayerStats.Amps; } if( Ordered[i].Deaths > MaxDeaths ) MaxDeaths = Ordered[i].Deaths; } } H"class SmartCTFPlayerReplicationInfo expands ReplicationInfo; // Replicated var int Captures, Assists, Grabs, Covers, Seals, FlagKills; var int Frags, HeadShots, ShieldBelts, Amps; // Server side var float LastKillTime; var int MultiLevel; var int FragSpree, CoverSpree, SealSpree, SpawnKillSpree; var float SpawnTime; var bool bHadFirstSpawn; // Client side var bool bViewingStats; var float IndicatorStartShow; var byte IndicatorVisibility; replication { // Stats reliable if( Role == ROLE_Authority ) Captures, Assists, Grabs, Covers, Seals, FlagKills, Frags, HeadShots, ShieldBelts, Amps; // Toggle stats functions reliable if( Role == ROLE_Authority ) ToggleStats, ShowStats; } function PostBeginPlay() { super.PostBeginPlay(); SetTimer( 0.5, True ); } function Timer() { if( Owner == None ) { SetTimer( 0.0, False ); Destroy(); } } // Called on the server, executed on the client simulated function ToggleStats() { local PlayerPawn P; if( Owner == None ) return; P = PlayerPawn( Owner.Owner ); if( P == None ) return; if( P.Scoring != None && !P.Scoring.IsA( 'SmartCTFScoreBoard' ) ) { P.ClientMessage( "Problem loading the SmartCTF ScoreBoard..." ); } else { bViewingStats = !bViewingStats; IndicatorStartShow = Level.TimeSeconds; IndicatorVisibility = 255; P.bShowScores = True; } } // Called on the client simulated function ShowStats() { local PlayerPawn P; if( Owner == None ) return; P = PlayerPawn( Owner.Owner ); if( P == None ) return; if( P.Scoring != None && !P.Scoring.IsA( 'SmartCTFScoreBoard' ) ) { P.ClientMessage( "Problem loading the SmartCTF ScoreBoard..." ); } else { bViewingStats = True; P.bShowScores = True; } } function ClearStats() { Captures = 0; Assists = 0; Grabs = 0; Covers = 0; Seals = 0; FlagKills = 0; Frags = 0; HeadShots = 0; ShieldBelts = 0; Amps = 0; FragSpree = 0; CoverSpree = 0; SealSpree = 0; SpawnKillSpree = 0; SpawnTime = 0; LastKillTime = 0; MultiLevel = 0; } h // Above all other messages. class SmartCTFMessage extends LocalMessagePlus; var string CoveredMsg, YouCoveredMsg; var string CoverSpreeMsg, YouCoverSpreeMsg; var string UltraCoverMsg, YouUltraCoverMsg; var string SealMsg, YouSealMsg; var string SavedMsg, YouSavedMsg; var string SpawnKillMsg; static function float GetOffset( int Switch, float YL, float ClipY ) { return ( default.YPos / 768.0 ) * ClipY - 3 * YL; } static function string GetString( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { if (RelatedPRI_1 == None) return ""; switch( Switch ) { case 0: // Cover FC return RelatedPRI_1.PlayerName @ default.CoveredMsg; case 1: // Seal base return RelatedPRI_1.PlayerName @ default.SealMsg; case 4: // Ultra cover return RelatedPRI_1.PlayerName @ default.UltraCoverMsg; case 5: // Cover spree return RelatedPRI_1.PlayerName @ default.CoverSpreeMsg; case 7: // Saved by ... return default.SavedMsg @ RelatedPRI_1.PlayerName $ "!"; case 10: // Spawnkilling return RelatedPRI_1.PlayerName @ default.SpawnKillMsg; case 0 + 64: return default.YouCoveredMsg; case 1 + 64: return default.YouSealMsg; case 4 + 64: return default.YouUltraCoverMsg; case 5 + 64: return default.YouCoverSpreeMsg; case 7 + 64: return default.YouSavedMsg; } return ""; } static simulated function ClientReceive( PlayerPawn P, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { super.ClientReceive( P, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); switch( Switch ) { case 5: // Cover spree - guitarsound for player, spreesound for all if( RelatedPRI_1 == P.PlayerReplicationInfo ) P.ClientPlaySound( sound'CaptureSound', , true ); else P.PlaySound( sound'SpreeSound', , 4.0 ); break; } } P$// This class gets spawned in the mutator, serverside. // Because of its Role, it will also get copied to clients. // The replicated variables are accessible there. class SmartCTFGameReplicationInfo expands ReplicationInfo; var int TickRate; var bool bShowFCLocation, bStatsDrawFaces, bPlay30SecSound, bDrawLogo; var class NormalScoreBoardClass; var SmartCTFEndStats EndStats; var SmartCTFPlayerReplicationInfo PRIArray[64]; var bool bInitialized, bServerInfoSetServerSide; var class DefaultHUDType; replication { // Settings reliable if( Role == ROLE_Authority ) bShowFCLocation, bPlay30SecSound, bStatsDrawFaces, bDrawLogo; reliable if( Role == ROLE_Authority ) bInitialized, TickRate, NormalScoreBoardClass, EndStats, bServerInfoSetServerSide, DefaultHUDType; } simulated function PostBeginPlay() { //default.NormalScoreBoardClass = Level.Game.ScoreBoardType; SetTimer( 0.5, True ); } simulated function Timer() { RefreshPRI(); } simulated function SmartCTFPlayerReplicationInfo GetStats( Actor P ) { local int i; local PlayerReplicationInfo PRI; if( !P.IsA( 'Pawn' ) ) return None; PRI = Pawn( P ).PlayerReplicationInfo; if( PRI == None ) return None; for( i = 0; i < 64; i++ ) { if( PRIArray[i] == None ) break; if( PRIArray[i].Owner == PRI ) return PRIArray[i]; } return None; } simulated function SmartCTFPlayerReplicationInfo GetStatsByPRI( PlayerReplicationInfo PRI ) { local int i; if( PRI == None ) return None; for( i = 0; i < 64; i++ ) { if( PRIArray[i] == None ) break; if( PRIArray[i].Owner == PRI ) return PRIArray[i]; } return None; } simulated function SmartCTFPlayerReplicationInfo GetStatNr( byte i ) { return PRIArray[i]; } simulated function ClearStats() { local int i; for( i = 0; i < 64; i++ ) { if( PRIArray[i] == None ) break; PRIArray[i].ClearStats(); } } simulated function RefreshPRI() { local SmartCTFPlayerReplicationInfo PRI; local int i; for( i = 0; i < 64; i++ ) PRIArray[i] = None; i = 0; ForEach AllActors( class'SmartCTFPlayerReplicationInfo', PRI ) { if( i < 64 ) { if( PRI.Owner != None ) PRIArray[i++] = PRI; } else break; } } qclass SmartCTFFlagCheckerInventory expands TournamentPickup; // This inventory item gets added to every player by default. // Now, each time this inventory item gets destroyed it means either the player left the game or died. // If he simply died, then the original code already made sure the flag is dropped, before we get here, // and nothing special happens. // When we're here, we will check if he was actually carrying the flag. If he still has a flag, it means // the player left the server and we drop the flag manually. // All this happens before the code that would send the flag home. // Quite ingenious if I may say so :p (c) {DnF2}SiNiSTeR imo xD var string DroppedMessage; function Destroyed() { local CTFFlag flag; if( Pawn( Owner ).bIsPlayer ) { flag = CTFFlag( Pawn( Owner ).PlayerReplicationInfo.HasFlag ); if( flag != None ) { flag.Drop( 0.5 * Pawn( Owner ).Velocity ); BroadcastMessage( Pawn( Owner ).PlayerReplicationInfo.PlayerName @ DroppedMessage ); } } super.Destroyed(); } Òc d#3À{Òdnluvn v,\rldŸd  î 'sda Æ €@y ÿÿ !g,//============================================================================= // SmartCTFEnhancedMultiKillMessage. // - v1.0 29-Feb-2004 by {DnF2}SiNiSTeR - //============================================================================= class SmartCTFEnhancedMultiKillMessage extends MultiKillMessage; // Extended Multikills adds 2 more to the list :] // These Announcer sounds already were included in the orginal game, just not used. // It also doesn't stop after 9 times ;p #exec OBJ LOAD FILE=..\Sounds\Announcer.uax var(Messages) localized string MegaKillString; static function int GetFontSize( int Switch ) { if( Switch < 3 ) return default.FontSize; else return 2; } static function string GetString( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { switch( Switch ) { case 0: return ""; break; case 1: return default.DoubleKillString; break; case 2: return default.TripleKillString; break; case 3: return default.MultiKillString; break; case 4: return default.MegaKillString; break; case 5: return default.UltraKillString; break; default: return default.MonsterKillString; break; } } static function string GetBroadcastString( int MultiLevel ) { if( MultiLevel == 5 ) return "had an" @ static.GetString( MultiLevel ); else return "had a" @ static.GetString( MultiLevel ); } static simulated function ClientReceive( PlayerPawn P, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { super( LocalMessagePlus ).ClientReceive( P, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); switch( Switch ) { case 0: break; case 1: P.ClientPlaySound( sound'Announcer.DoubleKill', , true ); break; case 2: P.ClientPlaySound( sound'Announcer.TripleKill', , true ); break; case 3: P.ClientPlaySound( sound'Announcer.MultiKill', , true ); break; case 4: P.ClientPlaySound( sound'Announcer.MegaKill', , true ); break; case 5: P.ClientPlaySound( sound'Announcer.UltraKill', , true ); break; default: P.ClientPlaySound( sound'Announcer.MonsterKill', , true ); break; } } static function color GetColor( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2 ) { local Color cres; cres = Default.DrawColor; if( Switch >= 1 && Switch <= 5 ) { cres.G = 48 * ( 5 - Switch ); return cres; } else if( Switch > 5 ) { cres.B = Min( 48 * ( Switch - 5 ), 255 ); return cres; } else { return cres; } } _%class SmartCTFEnhancedDeathMessagePlus extends DeathMessagePlus; static function ClientReceive( PlayerPawn P, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { local string MultiStr; if( RelatedPRI_1 == P.PlayerReplicationInfo ) { // Interdict and send the child message instead. if( TournamentPlayer( P ).myHUD != None ) { //if( class'DeathMessagePlus'.default.ChildMessage == class'KillerMessagePlus' ) class'KillerMessagePlus'.default.YouKilled = "You" @ TournamentGameInfo( P.Level.Game ).default.deathmessage[Rand(32)]; TournamentPlayer( P ).myHUD.LocalizedMessage( default.ChildMessage, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); TournamentPlayer( P ).myHUD.LocalizedMessage( default.Class, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); } if( default.bIsConsoleMessage ) { TournamentPlayer( P ).Player.Console.AddString( static.GetString( Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ) ); } if( ( RelatedPRI_1 != RelatedPRI_2 ) && ( RelatedPRI_2 != None ) ) { if( ( TournamentPlayer( P ).Level.TimeSeconds - TournamentPlayer( P ).LastKillTime < 3 ) && ( Switch != 1 ) ) { TournamentPlayer( P ).MultiLevel++; TournamentPlayer( P ).ReceiveLocalizedMessage( class'SmartCTFEnhancedMultiKillMessage', TournamentPlayer( P ).MultiLevel , RelatedPRI_1 ); } else { TournamentPlayer( P ).MultiLevel = 0; } TournamentPlayer( P ).LastKillTime = TournamentPlayer( P ).Level.TimeSeconds; } else { TournamentPlayer( P ).MultiLevel = 0; } if( ChallengeHUD( P.MyHUD ) != None ) ChallengeHUD( P.MyHUD ).ScoreTime = TournamentPlayer( P ).Level.TimeSeconds; } else if( RelatedPRI_2 == P.PlayerReplicationInfo ) { //class'VictimMessage'.default.YouWereKilledBy = "You were" @ TournamentGameInfo( P.Level.Game ).default.deathmessage[Rand(32)] @ "by"; TournamentPlayer( P ).ReceiveLocalizedMessage( class'VictimMessage', 0, RelatedPRI_1 ); super( LocalMessagePlus ).ClientReceive( P, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); } else { super( LocalMessagePlus ).ClientReceive( P, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); } } ko0þ·LŽo¨AoaÐTestEus®®®®TC«L?,OfŠ±s¯o½«u?,¡š|%!o ÍÌL?w¾š|&!o,,w š|,!o,,.®ÑUWindowFonts.Tahoma10 ®€?€?wC¯«?D¬®¯¯o½¯sC«u?,P®®OJP®®OJPP 0o’|&  V class SmartCTFEndStats expands EndStats config( user ); replication { reliable if( Role == ROLE_Authority ) MostPoints, MostFrags, MostCaps, MostFlagKills, MostCovers, MostHeadShots; } struct BestSomething { var int Count; var string PlayerName; var string MapName; var string RecordDate; }; var globalconfig BestSomething MostPoints; var globalconfig BestSomething MostFrags; var globalconfig BestSomething MostCaps; var globalconfig BestSomething MostFlagKills; var globalconfig BestSomething MostCovers; var globalconfig BestSomething MostHeadShots; Dclass SmartCTFCoolMsg expands LocalMessagePlus; var(Messages) string LongRangeString; var(Messages) string UberLongRangeString; var(Messages) string SpawnLamerString; var(Messages) string OvertimeEnabledString; var(Messages) string OvertimeDisabledString; var Color EnabledColor, DisabledColor, SpawnLamerColor; static function float GetOffset(int Switch, float YL, float ClipY ) { return ( default.YPos / 768.0 ) * ClipY - 2 * YL; } static function string GetString( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { switch( Switch ) { case 1: return default.LongRangeString; case 2: return default.UberLongRangeString; case 3: return default.OvertimeEnabledString; case 4: return default.OvertimeDisabledString; case 5: return default.SpawnLamerString; } return ""; } static function Color GetColor( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2 ) { switch( Switch ) { case 1: return default.DrawColor; case 2: return default.DrawColor; case 3: return default.EnabledColor; case 4: return default.DisabledColor; case 5: return default.SpawnLamerColor; } return default.DrawColor; } 4class SmartCTFBinds expands UTExtraKeyBindings; õv Eÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿw ¤g:öõ’…iŽK B] SmartCTFt] Toggle Statsz]mutate smartctf showstatsf// This is a fix to be able to get certain sounds to play. Certain sounds like Assist and Capture only // work on the client. By simply sending this message instead of ClientPlaySound on the server we don't need // to include the sounds in the pack. class SmartCTFAudioMsg expands LocalMessagePlus; static function string GetString( optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { return ""; } static simulated function ClientReceive( PlayerPawn P, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { super.ClientReceive( P, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); switch( Switch ) { case 0: P.ClientPlaySound( sound'Announcer.capture', , true ); break; case 1: P.ClientPlaySound( sound'Announcer.assist', , true ); break; case 2: P.ClientPlaySound( sound'Announcer.nicecatch', , true ); break; case 3: P.ClientPlaySound( sound'Announcer.takenlead', , true ); break; case 4: P.ClientPlaySound( sound'Announcer.lostlead', , true ); break; } } iÆ// SmartCTF 4 by {PiN}Kev. Released January 2004. // SmartCTF 4A Tweaked by {DnF2}SiNiSTeR. Released December 2004. // SmartCTF 4B/4C Uber Massively tweaked by {DnF2}SiNiSTeR. Released March 2005. // // This mod changes the point system and adds features to ultimately promote Teamwork in CTF. // This is a CTF Mod only. It will not load in any other gametype. // // Contact Info: Private Message me, {PiN}Hai-Ping, on http://forums.prounreal.com // {DnF2}SiNiSTeR @ #DutchNet [QuakeNet IRC] // // CHANGELOG: See Readme class SmartCTF expands Mutator config( SmartCTF_4C ); #exec texture IMPORT NAME=meter FILE=Textures\meter.pcx GROUP=SmartCTF #exec texture IMPORT NAME=powered File=Textures\powered.pcx GROUP=SmartCTF #exec texture IMPORT NAME=shade File=Textures\shade.pcx GROUP=SmartCTF /* Server Vars */ var SmartCTFGameReplicationInfo SCTFGame; var byte RedAstIndex, BlueAstIndex; var byte TRCount; var string Version, GameTieMessage; var Pawn FCs[2], RedAssisters[32], BlueAssisters[32]; var Pawn RedFlagCarrier[32], BlueFlagCarrier[32]; var float RedFlagCarrierTime[32], BlueFlagCarrierTime[32]; var byte RedFCIndex, BlueFCIndex; var float RedAssistTimes[32], BlueAssistTimes[32], PickupTime[2]; var FlagBase FlagStands[2]; var bool bForcedEndGame, bTournamentGameStarted, bTooCloseForSaves; /* Client Vars */ var bool bClientJoinPlayer, bGameEnded; var int LogoCounter, DrawLogo; var string LogoText; var PlayerPawn PlayerOwner; var FontInfo MyFonts; var TournamentGameReplicationInfo pTGRI; var PlayerReplicationInfo pPRI; var ChallengeHUD MyHUD; var Color RedTeamColor, BlueTeamColor, White, Gray; /* Server Vars Configurable */ var() config bool bEnabled; var(SmartCTFBonuses) config int CapBonus, AssistBonus, FlagKillBonus, CoverBonus, SealBonus, GrabBonus; var(SmartCTFBonuses) config float BaseReturnBonus, MidReturnBonus, EnemyBaseReturnBonus, CloseSaveReturnBonus; var(SmartCTFBonuses) config int SpawnKillPenalty, MinimalCapBonus; var() config bool bFixFlagBug; var() config bool bEnhancedMultiKill; var() config byte EnhancedMultiKillBroadcast; var() config bool bShowFCLocation; var() config bool bSmartCTFServerInfo; var() config bool bNewCapAssistScoring; var() config bool bSpawnkillDetection; var() config float SpawnKillTimeArena; var() config float SpawnKillTimeNW; var() config bool bAfterGodLikeMsg; var() config bool bStatsDrawFaces; var() config bool bDrawLogo; var(SmartCTFMessages) config byte CoverMsgType; var(SmartCTFMessages) config byte CoverSpreeMsgType; var(SmartCTFMessages) config byte SealMsgType; var(SmartCTFMessages) config byte SavedMsgType; var(SmartCTFMessages) config bool bShowLongRangeMsg; var(SmartCTFMessages) config bool bShowSpawnKillerGlobalMsg; var(SmartCTFMessages) config bool bShowAssistConsoleMsg; var(SmartCTFMessages) config bool bShowSealRewardConsoleMsg; var(SmartCTFMessages) config bool bShowCoverRewardConsoleMsg; var(SmartCTFSounds) config bool bPlayCaptureSound; var(SmartCTFSounds) config bool bPlayAssistSound; var(SmartCTFSounds) config bool bPlaySavedSound; var(SmartCTFSounds) config bool bPlayLeadSound; var(SmartCTFSounds) config bool bPlay30SecSound; var(OvertimeControl) config bool bEnableOvertimeControl; var(OvertimeControl) config bool bOvertime; var(OvertimeControl) config bool bRememberOvertimeSetting; /* * Check if we should spawn a SmartCTF instance. * This check doesn't seem to work properly in PostBeginPlay, hence here. */ event Spawned() { super.Spawned(); SCTFGame = Level.Game.Spawn( class'SmartCTFGameReplicationInfo' ); if( !ValidateSmartCTFMutator() ) { SCTFGame.Destroy(); Destroy(); } } /* * Get the original Scoreboard and store for SmartCTFScoreboard reference. */ function PreBeginPlay() { local Mutator M; super.PreBeginPlay(); SCTFGame.NormalScoreBoardClass = Level.Game.ScoreBoardType; Level.Game.ScoreBoardType = class'SmartCTFScoreBoard'; //Level.Game.default.ScoreBoardType = class'SmartCTFScoreBoard'; // The above line was fatal in version 4B :E Log( "Original Scoreboard determined as" @ SCTFGame.NormalScoreBoardClass, 'SmartCTF' ); // Change F2 Server Info screen, compatible with UTPure if( bSmartCTFServerInfo ) { class( Level.Game.HUDType ).default.ServerInfoClass = class'SmartCTFServerInfo'; for( M = Level.Game.BaseMutator; M != None; M = M.NextMutator ) { if( M.IsA( 'UTPure' ) ) // Let UTPure rehandle the scoreboard { M.PreBeginPlay(); SCTFGame.bServerInfoSetServerSide = True; // No need for the old fashioned way - it can be set server side. Log( "Notified UTPure HUD to use SmartCTF ServerInfo.", 'SmartCTF' ); break; } } if( SCTFGame.bServerInfoSetServerSide && Level.Game.HUDType.Name != 'PureCTFHUD' ) { // In this scenario another mod intervered and we still have to do it the old fashion way. SCTFGame.bServerInfoSetServerSide = False; Log( "HUD is not the UTPure HUD but" @ Level.Game.HUDType.Name $ ", so SmartCTF ServerInfo will be set clientside.", 'SmartCTF' ); } if( !SCTFGame.bServerInfoSetServerSide ) SCTFGame.DefaultHUDType = Level.Game.HUDType; // And in the old fashion way, the client will have to know the current HUD type. } else { SCTFGame.bServerInfoSetServerSide = True; // We didn't change anything, but neither do we want clientside intervention. } } /* * Startup and initialize. */ function PostBeginPlay() { local FlagBase fb; Level.Game.Spawn( class'SmartCTFSpawnNotifyPRI' ); SaveConfig(); // Create the .ini if its not already there. Level.Game.RegisterMessageMutator( self ); // Since we have problem replicating config variables... SCTFGame.bShowFCLocation = bShowFCLocation; SCTFGame.bPlay30SecSound = bPlay30SecSound; SCTFGame.bStatsDrawFaces = bStatsDrawFaces; SCTFGame.bDrawLogo = bDrawLogo; if( !bRememberOvertimeSetting ) bOvertime = True; // Works serverside! if( bEnhancedMultiKill ) Level.Game.DeathMessageClass = class'SmartCTFEnhancedDeathMessagePlus'; // Get the Flag bases ForEach AllActors( class'FlagBase', fb ) FlagStands[ fb.Team ] = fb; if( VSize( FlagStands[0].Location - FlagStands[1].Location ) < 1.5 * 900 ) bTooCloseForSaves = True; SCTFGame.EndStats = Spawn( class'SmartCTFEndStats', self ); super.PostBeginPlay(); if( Level.NetMode == NM_DedicatedServer ) SetTimer( 1.0 , True); Log( "SmartCTF" @ Version @ "loaded successfully.", 'SmartCTF' ); } /* * Returns True or False whether to keep this SmartCTF mutator instance, and sets bInitialized accordingly. */ function bool ValidateSmartCTFMutator() { local Mutator M; local bool bRunning; M = Level.Game.BaseMutator; while( M != None ) { if( M != Self && M.Class == Self.Class ) { bRunning = True; break; } M = M.NextMutator; } if( !bEnabled ) Log( "Instance" @ Name @ "not loaded because bEnabled in .ini = False.", 'SmartCTF' ); else if( CTFGame( Level.Game ) == None ) Log( "Instance" @ Name @ "not loaded because gamestyle is not CTF.", 'SmartCTF' ); else if( bRunning ) Log( "Instance" @ Name @ "not loaded because it is already running.", 'SmartCTF' ); else SCTFGame.bInitialized = True; return SCTFGame.bInitialized; } /* * For the flag bug each player gets a FlagChecker inventory on spawn. */ function ModifyPlayer( Pawn Other ) { local Inventory Inv; local SmartCTFPlayerReplicationInfo OtherStats; if( bFixFlagBug && Other.bIsPlayer && !( Other.PlayerReplicationInfo.bIsSpectator && !Other.PlayerReplicationInfo.bWaitingPlayer ) ) { Inv = Spawn( class'SmartCTFFlagCheckerInventory' , Other ); if( Inv != None ) Inv.GiveTo( Other ); } OtherStats = SCTFGame.GetStats( Other ); if( OtherStats == None ) return; if( !OtherStats.bHadFirstSpawn ) { OtherStats.bHadFirstSpawn = True; FirstSpawn( Other ); } OtherStats.SpawnTime = Level.TimeSeconds; super.ModifyPlayer( Other ); } /* * Gets called when a new player or bot joins the game, that is when they first spawn. */ function FirstSpawn( Pawn Other ) { local byte ID; local string SkinName, FaceName; // Additional logging, useful for player tracking if( Level.Game.LocalLog != None && PlayerPawn( Other ) != None && Other.bIsPlayer ) { ID = PlayerPawn( Other ).PlayerReplicationInfo.PlayerID; Level.Game.LocalLog.LogSpecialEvent( "IP", ID, PlayerPawn( Other ).GetPlayerNetworkAddress() ); Level.Game.LocalLog.LogSpecialEvent( "player", "NetSpeed", ID, PlayerPawn( Other ).Player.CurrentNetSpeed ); Level.Game.LocalLog.LogSpecialEvent( "player", "Fov", ID, PlayerPawn( Other ).FovAngle ); Level.Game.LocalLog.LogSpecialEvent( "player", "VoiceType", ID, Other.VoiceType ); if( Other.IsA( 'TournamentPlayer' ) ) { if( Other.Skin == None ) { Other.static.GetMultiSkin( Other, SkinName, FaceName ); } else { SkinName = string( Other.Skin ); FaceName = "None"; } Level.Game.LocalLog.LogSpecialEvent( "player", "Skin", ID, SkinName ); Level.Game.LocalLog.LogSpecialEvent( "player", "Face", ID, FaceName ); } } } /* * Gets called once when the Countdown before a Tournament game starts. */ function TournamentGameStarted() { // Fix warmup mode bug + Overtime functionality ClearStats(); if( bEnableOvertimeControl ) { if( !bOvertime ) BroadcastLocalizedMessage( class'SmartCTFCoolMsg', 4 ); else BroadcastLocalizedMessage( class'SmartCTFCoolMsg', 3 ); } } /* * Check for covers and seals, and adjust scores. */ function bool PreventDeath( Pawn Victim, Pawn Killer, name DamageType, vector HitLocation ) { local PlayerReplicationInfo VictimPRI, KillerPRI; local bool bPrevent, bVictimTeamHasFlag, bWarmupSkip; local Pawn pn; local float TimeAwake; local SmartCTFPlayerReplicationInfo KillerStats, VictimStats; bPrevent = super.PreventDeath( Victim, Killer, DamageType, HitLocation ); if( bPrevent ) return bPrevent; // Player didn't die, so return. // If there is no victim, return. if( Victim == None ) return bPrevent; VictimPRI = Victim.PlayerReplicationInfo; if( VictimPRI == None || !Victim.bIsPlayer || ( VictimPRI.bIsSpectator && !VictimPRI.bWaitingPlayer ) ) return bPrevent; VictimStats = SCTFGame.GetStats( Victim ); if( VictimStats != None ) { VictimStats.FragSpree = 0; // Reset FragSpree for Victim VictimStats.SpawnKillSpree = 0; } // If there is no killer / suicide, return. if( Killer == None || Killer == Victim ) { if( bEnhancedMultiKill && EnhancedMultiKillBroadcast > 0 ) VictimStats.MultiLevel = 0; return bPrevent; } KillerPRI = Killer.PlayerReplicationInfo; if( KillerPRI == None || !Killer.bIsPlayer || ( KillerPRI.bIsSpectator && !KillerPRI.bWaitingPlayer ) ) return bPrevent; KillerStats = SCTFGame.GetStats( Killer ); // Same Team! We don't count those stats like that in SmartCTF. if( VictimPRI.Team == KillerPRI.Team ) return bPrevent; // Increase Frags and FragSpree for Killer (Play "Too Easy" at 30) if( KillerStats != None ) { KillerStats.Frags++; KillerStats.FragSpree++; } if( bEnhancedMultiKill && EnhancedMultiKillBroadcast > 0 ) { VictimStats.MultiLevel = 0; if( Level.TimeSeconds - KillerStats.LastKillTime < 3 ) { KillerStats.MultiLevel++; if( KillerStats.MultiLevel + 1 >= EnhancedMultiKillBroadcast ) Level.Game.BroadcastMessage( KillerPRI.PlayerName @ class'SmartCTFEnhancedMultiKillMessage'.static.GetBroadcastString( KillerStats.MultiLevel ) ); } else { KillerStats.MultiLevel = 0; } KillerStats.LastKillTime = Level.TimeSeconds; } bWarmupSkip = DeathMatchPlus( Level.Game ).bTournament && !bTournamentGameStarted; if( !bWarmupSkip ) { // For Flag Kill, inc player's FlagKills and total if( VictimPRI.HasFlag != None ) { if( KillerStats != None ) KillerStats.FlagKills++; KillerPRI.Score += FlagKillBonus; // Already logged by UTStats serveractor. Dont want to do it twice. //if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_kill", KillerPRI.PlayerID, VictimPRI.PlayerID, VictimPRI.Team ); } // If Killer has Flag, no cover or seal for him else if( KillerPRI.HasFlag == None && FCs[KillerPRI.Team] != None && FCs[KillerPRI.Team].PlayerReplicationInfo.HasFlag != None ) { // COVER FRAG / SEAL BASE // If Killer's Team has had an FC // If the FC has Flag Right now // Defend kill // org: If victim can see the FC or is within 600 unreal units (approx 40 feet) and has a line of sight to fc. //if( Victim.canSee( FCs[KillerPRI.Team] ) || ( Victim.lineOfSightTo( FCs[KillerPRI.Team] ) && Distance( Victim.Location, FCs[KillerPRI.Team].Location ) < 600 ) ) // new: victim within 512 uu of FC // or killer within 512 uu of FC // or victim can see FC and was Victim within 1536 uu of FC // or killer can see FC and Victim victim within 1024 uu of FC // or victim has direct line to FC and was Victim within 768 uu if( ( VSize( Victim.Location - FCs[KillerPRI.Team].Location ) < 512 ) || ( VSize( Killer.Location - FCs[KillerPRI.Team].Location ) < 512 ) || ( VSize( Victim.Location - FCs[KillerPRI.Team].Location ) < 1536 && Victim.canSee( FCs[KillerPRI.Team] ) ) || ( VSize( Victim.Location - FCs[KillerPRI.Team].Location ) < 1024 && Killer.canSee( FCs[KillerPRI.Team] ) ) || ( VSize( Victim.Location - FCs[KillerPRI.Team].Location ) < 768 && Victim.lineOfSightTo( FCs[KillerPRI.Team] ) ) ) { // Killer DEFENDED THE Flag CARRIER if( KillerStats != None ) { KillerStats.Covers++; KillerStats.CoverSpree++; // Increment Cover spree } KillerPRI.Score += CoverBonus; // Reward points // Log cover if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_cover", KillerPRI.PlayerID, VictimPRI.PlayerID, KillerPRI.Team ); // Cover sprees if( KillerStats != None ) { if( KillerStats.CoverSpree == 3 ) // Cover x 3 { if( CoverSpreeMsgType == 1 && PlayerPawn( Killer ) != None ) Killer.ClientMessage( class'SmartCTFMessage'.static.GetString( 4 + 64, KillerPRI, VictimPRI ) ); else if( CoverSpreeMsgType == 2 ) BroadcastMessage( class'SmartCTFMessage'.static.GetString( 4, KillerPRI, VictimPRI ) ); else if( CoverSpreeMsgType == 3 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 4, KillerPRI, VictimPRI ); } else if( KillerStats.CoverSpree == 4 ) // Cover x 4 { if( CoverSpreeMsgType == 1 && PlayerPawn( Killer ) != None ) Killer.ClientMessage( class'SmartCTFMessage'.static.GetString( 5 + 64, KillerPRI, VictimPRI ) ); else if( CoverSpreeMsgType == 2 ) BroadcastMessage( class'SmartCTFMessage'.static.GetString( 5, KillerPRI, VictimPRI ) ); else if( CoverSpreeMsgType == 3 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 5, KillerPRI, VictimPRI ); } else // // Covered FC { if( CoverMsgType == 1 && PlayerPawn( Killer ) != None ) Killer.ClientMessage( class'SmartCTFMessage'.static.GetString( 0 + 64, KillerPRI, VictimPRI ) ); else if( CoverMsgType == 2 ) BroadcastMessage( class'SmartCTFMessage'.static.GetString( 0, KillerPRI, VictimPRI ) ); else if( CoverMsgType == 3 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 0, KillerPRI, VictimPRI ); } } } // Seal kill // If the map has player zones if( VictimPRI.PlayerZone != None ) { bVictimTeamHasFlag = True; if( FCs[VictimPRI.Team] == None ) bVictimTeamHasFlag = False; if( FCs[VictimPRI.Team] != None && FCs[VictimPRI.Team].PlayerReplicationInfo.HasFlag == None ) bVictimTeamHasFlag = False; // If Victim's FC has not been set / If Victim's FC doesn't have our Flag if( !bVictimTeamHasFlag ) { // If Killer is Red & he and his FC's Location has Red if( IsInZone( VictimPRI, KillerPRI.Team ) && IsInZone( FCs[KillerPRI.Team].PlayerReplicationInfo, KillerPRI.Team ) ) { // Killer SEALED THE BASE if( KillerStats != None ) { KillerStats.Seals++; KillerStats.SealSpree++; } KillerPRI.Score += SealBonus; if( SealMsgType != 0 && KillerStats != None && KillerStats.SealSpree == 2 ) // Sealing base { if( SealMsgType == 1 && PlayerPawn( Killer ) != None ) Killer.ClientMessage( class'SmartCTFMessage'.static.GetString( 1 + 64, KillerPRI, VictimPRI ) ); else if( SealMsgType == 2 ) BroadcastMessage( class'SmartCTFMessage'.static.GetString( 1, KillerPRI, VictimPRI ) ); else if( SealMsgType == 3 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 1, KillerPRI, VictimPRI ); } // Log seal if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_seal", KillerPRI.PlayerID, VictimPRI.PlayerID, KillerPRI.Team ); // Log to ngLog; } } } } } if( bAfterGodLikeMsg && KillerStats != None && ( KillerStats.FragSpree == 30 || KillerStats.FragSpree == 35 ) ) { for( pn = Level.PawnList; pn != None; pn = pn.NextPawn ) { if( pn.IsA( 'TournamentPlayer' ) ) pn.ReceiveLocalizedMessage( class'SmartCTFSpreeMsg', KillerStats.FragSpree / 5 - 1, KillerPRI ); } } // Uber / Long Range kill if not sniper, HeadShot, trans, deemer, instarifle, or vengeance relic. if( bShowLongRangeMsg && TournamentPlayer( Killer ) != None ) { if( DamageType != 'shot' && DamageType != 'decapitated' && DamageType != 'Gibbed' && DamageType != 'RedeemerDeath' && SuperShockRifle( Killer.Weapon ) == None && DamageType != 'Eradicated' ) { if( VSize( Killer.Location - Victim.Location ) > 1536 ) { if( VSize( Killer.Location - Victim.Location ) > 3072 ) { Killer.ReceiveLocalizedMessage( class'SmartCTFCoolMsg', 2, KillerPRI, VictimPRI ); } else { Killer.ReceiveLocalizedMessage( class'SmartCTFCoolMsg', 1, KillerPRI, VictimPRI ); } // Log special kill. if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "longrangekill", KillerPRI.PlayerID, VictimPRI.PlayerID ); } } } // HeadShot tracking if( DamageType == 'decapitated' && KillerStats != None ) KillerStats.HeadShots++; // Spawnkill detection if( bSpawnkillDetection && DamageType != 'Gibbed' && VictimStats != None ) // No telefrags { TimeAwake = Level.TimeSeconds - VictimStats.SpawnTime; if( Level.Game.BaseMutator.MutatedDefaultWeapon() != class'Botpack.ImpactHammer' ) { // Arena mutator used, spawnkilling must be extreme to count if( TimeAwake <= SpawnKillTimeArena ) { Killer.ReceiveLocalizedMessage( class'SmartCTFCoolMsg', 5, KillerPRI, VictimPRI ); KillerPRI.Score -= SpawnKillPenalty; if( KillerStats != None ) KillerStats.SpawnKillSpree++; if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "spawnkill", KillerPRI.PlayerID, VictimPRI.PlayerID, SpawnKillPenalty ); if( bShowSpawnKillerGlobalMsg && KillerStats != None && KillerStats.SpawnKillSpree > 2 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 10, KillerPRI, VictimPRI ); } } else // No arena mutator { if( TimeAwake < SpawnKillTimeNW ) { Killer.ReceiveLocalizedMessage( class'SmartCTFCoolMsg', 5, KillerPRI, VictimPRI ); KillerPRI.Score -= SpawnKillPenalty; if( KillerStats != None ) KillerStats.SpawnKillSpree++; if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "spawnkill", KillerPRI.PlayerID, VictimPRI.PlayerID, SpawnKillPenalty ); if( bShowSpawnKillerGlobalMsg && KillerStats != None && KillerStats.SpawnKillSpree > 2 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 10, KillerPRI, VictimPRI ); } } } return bPrevent; } /* * ShieldBelt + Damage Amp tracking, spawnkill detection. */ function bool HandlePickupQuery( Pawn Other, Inventory Item, out byte bAllowPickup ) { local SmartCTFPlayerReplicationInfo OtherStats; OtherStats = SCTFGame.GetStats( Other ); if( Item.IsA( 'UT_ShieldBelt' ) && OtherStats != None ) OtherStats.ShieldBelts++; if( Item.IsA( 'UDamage' ) && OtherStats != None ) OtherStats.Amps++; // For spawnkill detection if( bSpawnkillDetection && OtherStats != None && OtherStats.SpawnTime != 0 ) { if( Item.IsA( 'TournamentWeapon' ) || Item.IsA( 'UT_ShieldBelt' ) || Item.IsA( 'UDamage' ) || Item.IsA( 'HealthPack' ) || Item.IsA( 'UT_Invisibility' ) ) { // This player has picked up a certain item making a kill on him no longer be qualified as a spawnkill. OtherStats.SpawnTime = 0; } } return super.HandlePickupQuery( Other, Item, bAllowPickup ); } /* * Proper check if a player is in a location with 'red' or 'blue' in the name. */ function bool IsInZone( PlayerReplicationInfo PRI, byte Team ) { local string Loc; if( PRI.PlayerLocation != None ) Loc = PRI.PlayerLocation.LocationName; else if( PRI.PlayerZone != None ) Loc = PRI.PlayerZone.ZoneName; else return False; if( Team == 0 ) return ( Instr( Caps( Loc ), "RED" ) != -1 ); else return ( Instr( Caps( Loc ), "BLUE" ) != -1 ); } /* * Add a player to the Red FC/assister list. */ function AddRedFlagCarrier( Pawn Aster, float Fct ) { local byte i; if( Aster == None || !Aster.bIsPlayer || ( Aster.PlayerReplicationInfo.bIsSpectator && !Aster.PlayerReplicationInfo.bWaitingPlayer ) ) return; if( RedFCIndex >= 32 ) RedFCIndex = 0; // Check if already in list for( i = 0; i < 32; i++ ) { if( Aster == RedFlagCarrier[i] ) { RedFlagCarrierTime[i] += Fct; return; } } RedFlagCarrier[RedFCIndex] = Aster; RedFlagCarrierTime[RedFCIndex] = Fct; RedFCIndex++; } function AddBlueFlagCarrier( Pawn Aster, float Fct ) { local byte i; if( Aster == None || !Aster.bIsPlayer || ( Aster.PlayerReplicationInfo.bIsSpectator && !Aster.PlayerReplicationInfo.bWaitingPlayer ) ) return; if( BlueFCIndex >= 32 ) BlueFCIndex = 0; for( i = 0; i < 32; i++ ) { if( Aster == BlueFlagCarrier[i] ) { BlueFlagCarrierTime[i] += Fct; return; } } BlueFlagCarrier[BlueFCIndex] = Aster; BlueFlagCarrierTime[BlueFCIndex] = Fct; BlueFCIndex++; } /* * Walk through Red assisters/FC and reward them with points because of a cap. */ function RewardRedFlagCarriers( bool bNotPlayedLead ) { local byte j; local SmartCTFPlayerReplicationInfo AssisterStats; local int Bonus; local float TotalTime, f; Bonus = AssistBonus; // Calculate the total flag carrying time for( j = 0; j < 32; j++ ) TotalTime += RedFlagCarrierTime[j]; for( j = 0; j < 32; j++ ) { // If flagcarrier was not the capper if( RedFlagCarrier[j] != None && RedFlagCarrier[j] != FCs[0] ) { AssisterStats = SCTFGame.GetStats( RedFlagCarrier[j] ); if( AssisterStats != None ) AssisterStats.Assists++; if( bNewCapAssistScoring ) { if( TotalTime == 0 ) f = 0; else f = ( RedFlagCarrierTime[j] / TotalTime ) * ( 7 + CapBonus ); // proportionally score Bonus = Max( f, 1 ); } RedFlagCarrier[j].PlayerReplicationInfo.Score += Bonus; if( PlayerPawn( RedFlagCarrier[j] ) != None ) { if( bShowAssistConsoleMsg ) PlayerPawn( RedFlagCarrier[j] ).ClientMessage( "You get " $ Bonus $ " bonus pts for the Assist!" @ CarriedString( RedFlagCarrierTime[j], TotalTime ) ); if( bPlayAssistSound && bNotPlayedLead ) PlayerPawn( RedFlagCarrier[j] ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 1 ); } if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "Flag_assist", RedFlagCarrier[j].PlayerReplicationInfo.PlayerID, 0 ); } // Award capper propertionally too. Behave like assist else if( RedFlagCarrier[j] == FCs[0] ) { if( bNewCapAssistScoring ) { if( TotalTime == 0 ) f = 0; else f = ( RedFlagCarrierTime[j] / TotalTime ) * ( 7 + CapBonus ); Bonus = Max( f, MinimalCapBonus ); FCs[0].PlayerReplicationInfo.Score += Bonus - 7; // 7 already awarded by UT if( bShowAssistConsoleMsg && PlayerPawn( FCs[0] ) != None ) PlayerPawn( FCs[0] ).ClientMessage( "You get " $ Bonus $ " pts for the Capture!" @ CarriedString( RedFlagCarrierTime[j], TotalTime ) ); } else FCs[0].PlayerReplicationInfo.Score += CapBonus; } } ResetFlagCarriers( 0 ); } function RewardBlueFlagCarriers( bool bNotPlayedLead ) { local byte j; local SmartCTFPlayerReplicationInfo AssisterStats; local int Bonus; local float TotalTime, f; Bonus = AssistBonus; for( j = 0; j < 32; j++ ) TotalTime += BlueFlagCarrierTime[j]; for( j = 0; j < 32; j++ ) { if( BlueFlagCarrier[j] != None && BlueFlagCarrier[j] != FCs[1] ) { AssisterStats = SCTFGame.GetStats( BlueFlagCarrier[j] ); if( AssisterStats != None ) AssisterStats.Assists++; if( bNewCapAssistScoring ) { if( TotalTime == 0 ) f = 0; else f = ( BlueFlagCarrierTime[j] / TotalTime ) * ( 7 + CapBonus ); Bonus = Max( f, 1 ); } BlueFlagCarrier[j].PlayerReplicationInfo.Score += Bonus; if( PlayerPawn( BlueFlagCarrier[j] ) != None ) { if( bShowAssistConsoleMsg ) PlayerPawn( BlueFlagCarrier[j] ).ClientMessage( "You get " $ Bonus $ " bonus pts for the Assist!" @ CarriedString( BlueFlagCarrierTime[j], TotalTime ) ); if( bPlayAssistSound && bNotPlayedLead ) PlayerPawn( BlueFlagCarrier[j] ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 1 ); } if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "Flag_assist", BlueFlagCarrier[j].PlayerReplicationInfo.PlayerID, 0 ); } else if( BlueFlagCarrier[j] == FCs[1] ) { if( bNewCapAssistScoring ) { if( TotalTime == 0 ) f = 0; else f = ( BlueFlagCarrierTime[j] / TotalTime ) * ( 7 + CapBonus ); Bonus = Max( f, MinimalCapBonus ); FCs[1].PlayerReplicationInfo.Score += Bonus - 7; if( bShowAssistConsoleMsg && PlayerPawn( FCs[1] ) != None ) PlayerPawn( FCs[1] ).ClientMessage( "You get " $ Bonus $ " pts for the Capture!" @ CarriedString( BlueFlagCarrierTime[j], TotalTime ) ); } else FCs[1].PlayerReplicationInfo.Score += CapBonus; } } ResetFlagCarriers( 1 ); } /* * Clear assisters list of Team, because of flag return. Team = 2: clear both teams. */ function ResetFlagCarriers( byte Team ) { local byte i; if( Team != 1 ) { RedFCIndex = 0; for( i = 0; i < 32; i++ ) { RedFlagCarrier[i] = None; RedFlagCarrierTime[i] = 0; } } if( Team != 0 ) { BlueFCIndex = 0; for( i = 0; i < 32; i++ ) { BlueFlagCarrier[i] = None; BlueFlagCarrierTime[i] = 0; } } } function string CarriedString( float Time, float TotalTime ) { local int Perc; local float f; //if( !bNewCapAssistScoring ) return ""; if( TotalTime == 0 ) f = 0; else f = ( Time / TotalTime ) * 100; Perc = Clamp( f, 0, 100 ); if( Perc == 100 ) return "(Solocap," @ int( Time ) @ "sec.)"; else return "(Carried" @ Perc $ "% of the time:" @ int( Time ) @ "sec.)"; } /* * Intercept CTF messages to set FC states and adjust scores. */ function bool MutatorBroadcastLocalizedMessage( Actor Sender, Pawn Receiver, out class Message, out optional int Switch, out optional PlayerReplicationInfo RelatedPRI_1, out optional PlayerReplicationInfo RelatedPRI_2, out optional Object OptionalObject ) { local CTFFlag Flag; local byte i, LeadSound; local Pawn pn, FirstPawn; local SmartCTFPlayerReplicationInfo ReceiverStats; // This function gets called each time someone receives a message. Thus for a broadcast, we need to make sure code only // gets executed once. We can do that by comparing Receiver with f.e. the FC if applicable, or with the first Pawn // in the PawnList (FirstPawn, see below). if( Message == class'CTFMessage' ) { if( Sender.IsA( 'CTFGame' ) ) Flag = CTFFlag( OptionalObject ); else if( Sender.IsA( 'CTFFlag' ) ) Flag = CTFFlag( Sender ); else return super.MutatorBroadcastLocalizedMessage( Sender, Receiver, Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); if( Flag == None ) return super.MutatorBroadcastLocalizedMessage( Sender, Receiver, Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); // Warmup if( DeathMatchPlus( Level.Game ).bTournament && !bTournamentGameStarted ) return super.MutatorBroadcastLocalizedMessage( Sender, Receiver, Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); switch( Switch ) { // CAPTURE // Sender: CTFGame, PRI: Scorer.PlayerReplicationInfo, OptObj: TheFlag case 0: if( Receiver == Pawn( RelatedPRI_1.Owner ) ) { //Flag = CTFFlag( OptionalObject ); i = 1 - Flag.Team; if( i == 1 ) AddBlueFlagCarrier( FCs[i], Level.TimeSeconds - PickupTime[i] ); else AddRedFlagCarrier( FCs[i], Level.TimeSeconds - PickupTime[i] ); // Increment Caps for the player and the total ReceiverStats = SCTFGame.GetStats( FCs[i] ); if( ReceiverStats != None ) ReceiverStats.Captures++; if( bPlayLeadSound ) { if( ( CTFGame( Level.Game ).Teams[i].Score - 1 ) == CTFGame( Level.Game ).Teams[1 - i].Score ) LeadSound = 1; if( CTFGame( Level.Game ).Teams[i].Score == CTFGame( Level.Game ).Teams[1 - i].Score ) LeadSound = 2; for( pn = Level.PawnList; pn != None; pn = pn.NextPawn ) { if( PlayerPawn( pn ) != None && pn.bIsPlayer ) { if( LeadSound == 1 && pn.PlayerReplicationInfo.Team == i ) PlayerPawn( pn ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 3 ); else if( LeadSound == 2 && pn.PlayerReplicationInfo.Team == ( 1 - i ) ) PlayerPawn( pn ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 4 ); } } } // Don't play Capture sound if "Got The Lead" sound has played if( bPlayCaptureSound && PlayerPawn( FCs[i] ) != None ) { if( !( bPlayLeadSound && ( LeadSound == 1 ) ) ) PlayerPawn( FCs[i] ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 0 ); } // Reward points To FC and Assisters and increment Assists count and total if( Flag.Team == 0 ) RewardBlueFlagCarriers( !( bPlayLeadSound && ( LeadSound == 1 ) ) ); else RewardRedFlagCarriers( !( bPlayLeadSound && ( LeadSound == 1 ) ) ); ResetFlagCarriers( 2 ); GiveCoverSealBonus( Flag.Team ); // Reward pts to Covers And Sealers // Reset FCs And Assister num n index And reset sprees FCs[0] = None; FCs[1] = None; ResetSprees( 2 ); // Means reset all since no Team is equal to 2. } break; // DROP // Sender: CTFFlag, PRI: Holder.PlayerReplicationInfo, OptObj: CTFGame(Level.Game).Teams[Team] case 2: if( Receiver == Pawn( RelatedPRI_1.Owner ) ) { i = 1 - Flag.Team; if( i == 1 ) AddBlueFlagCarrier( FCs[i], Level.TimeSeconds - PickupTime[i] ); else AddRedFlagCarrier( FCs[i], Level.TimeSeconds - PickupTime[i] ); } break; // PICKUP (after the FC dropped it) // Sender: CTFFlag, PRI: Holder.PlayerReplicationInfo, OptObj: CTFGame(Level.Game).Teams[Team] case 4: if( Receiver == Flag.Holder ) { i = 1 - Flag.Team; PickupTime[i] = Level.TimeSeconds; FCs[i] = Flag.Holder; } break; // GRAB // Sender: CTFFlag, PRI: Holder.PlayerReplicationInfo, OptObj: CTFGame(Level.Game).Teams[Team] case 6: if( Receiver == Flag.Holder ) { i = 1 - Flag.Team; PickupTime[i] = Level.TimeSeconds; FCs[i] = Flag.Holder; // Set the FC RelatedPRI_1.Score += GrabBonus; // Increment FC's Grabs and total Grabs ReceiverStats = SCTFGame.GetStats( FCs[i] ); if( ReceiverStats != None ) ReceiverStats.Grabs++; } break; // RETURN case 1: case 3: case 5: // Get a pawn that receives messages, thus triggers this function ( as Receiver ) for( FirstPawn = Level.PawnList; FirstPawn != None; FirstPawn = FirstPawn.NextPawn ) { if( FirstPawn.bIsPlayer || FirstPawn.IsA( 'MessagingSpectator' ) ) break; } if( Receiver == FirstPawn ) // Just get the first one. { // Switch == 1: it's returned by player, sent by CTFGame. // Sender: CTFGame, PRI: Scorer.PlayerReplicationInfo, ObtObj: TheFlag if( Switch == 1 ) { // 8 pts for a close save (with msg), Half a pt for base returns, 2 pts for Mid, 4 pts for enemy base if( !bTooCloseForSaves && VSize( Flag.Location - FlagStands[1 - Flag.Team].Location ) < 900 ) { // CLOSE SAVE RelatedPRI_1.Score += CloseSaveReturnBonus; if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_return_closesave", RelatedPRI_1.PlayerID, Flag.Team ); // Only a msg if not a Flag standoff - other flag is home if( CTFReplicationInfo( Level.Game.GameReplicationInfo ).FlagList[1 - Flag.Team].bHome ) { if( SavedMsgType == 1 && PlayerPawn( RelatedPRI_1.Owner ) != None ) PlayerPawn( RelatedPRI_1.Owner ).ClientMessage( class'SmartCTFMessage'.static.GetString( 7 + 64, RelatedPRI_1 ) ); else if( SavedMsgType == 2 ) BroadcastMessage( class'SmartCTFMessage'.static.GetString( 7, RelatedPRI_1 ) ); else if( SavedMsgType == 3 ) BroadcastLocalizedMessage( class'SmartCTFMessage', 7, RelatedPRI_1 ); if( bPlaySavedSound && PlayerPawn( RelatedPRI_1.Owner ) != None ) PlayerPawn( RelatedPRI_1.Owner ).ReceiveLocalizedMessage( class'SmartCTFAudioMsg', 2 ); } } else if( IsInZone( RelatedPRI_1, 1 - Flag.Team ) ) { RelatedPRI_1.Score += EnemyBaseReturnBonus; // If in enemy base if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_return_enemybase", RelatedPRI_1.PlayerID, Flag.Team ); } else if( !IsInZone( RelatedPRI_1, Flag.Team ) ) // Not in enemy base and not on own side = mid { RelatedPRI_1.Score += MidReturnBonus; // If in Mid if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_return_mid", RelatedPRI_1.PlayerID, Flag.Team ); } else { RelatedPRI_1.Score += BaseReturnBonus; if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "flag_return_base", RelatedPRI_1.PlayerID, Flag.Team ); } } // end if switch == 1 ResetSprees( Flag.Team ); // Reset cover sprees and seal sprees of Other Team ResetFlagCarriers( 1 - Flag.Team ); // Reset assist list } break; } // end switch } // end if msg is CTF msg. return super.MutatorBroadcastLocalizedMessage( Sender, Receiver, Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject ); } /* * Gives all players of Team that covered their FC extra bonus points after the cap. */ function GiveCoverSealBonus( int Team ) { local PlayerReplicationInfo pnPRI; local byte i; local SmartCTFPlayerReplicationInfo PawnStats; local Pawn pn; SCTFGame.RefreshPRI(); for( i = 0; i < 64; i++ ) { PawnStats = SCTFGame.GetStatNr( i ); if( PawnStats == None ) break; pnPRI = PlayerReplicationInfo( PawnStats.Owner ); pn = Pawn( pnPRI.Owner ); if( pnPRI.Team != Team ) { if( PawnStats != None && PawnStats.SealSpree > 0 ) { pnPRI.Score += PawnStats.SealSpree * SealBonus; if( bShowSealRewardConsoleMsg && PlayerPawn( pn ) != None ) PlayerPawn( pn ).ClientMessage("You killed " $ PawnStats.SealSpree $ " people sealing off the base. You get " $ PawnStats.SealSpree * SealBonus $ " bonus pts!" ); if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "seal_bonus", pnPRI.PlayerID, PawnStats.SealSpree, PawnStats.SealSpree * SealBonus ); } if( PawnStats != None && PawnStats.CoverSpree > 0 ) { pnPRI.Score += PawnStats.CoverSpree * CoverBonus; if( bShowCoverRewardConsoleMsg && PlayerPawn( pn ) != None ) PlayerPawn( pn ).ClientMessage("You killed " $ PawnStats.CoverSpree $ " people covering your FC. You get " $ PawnStats.CoverSpree * CoverBonus $ " bonus pts!" ); if( Level.Game.LocalLog != None ) Level.Game.LocalLog.LogSpecialEvent( "cover_bonus", pnPRI.PlayerID, PawnStats.CoverSpree, PawnStats.CoverSpree * CoverBonus ); } } } } /* * Reset cover and seal sprees of Team cause of flag return. */ function ResetSprees( int Team ) { local byte i; local SmartCTFPlayerReplicationInfo PawnStats; SCTFGame.RefreshPRI(); for( i = 0; i < 64; i++ ) { PawnStats = SCTFGame.GetStatNr( i ); if( PawnStats == None ) break; if( PlayerReplicationInfo( PawnStats.Owner ).Team != Team ) { PawnStats.CoverSpree = 0; PawnStats.SealSpree = 0; } } } /* * Clear stats. */ function ClearStats() { SCTFGame.ClearStats(); ResetFlagCarriers( 2 ); FCs[0] = None; FCs[1] = None; } /* * Give info on 'mutate smartctf' commands. */ function Mutate( string MutateString, PlayerPawn Sender ) { local int ID; local string SoundsString, MsgsString, CMsgsString; local SmartCTFPlayerReplicationInfo SenderStats; if( Left( MutateString, 8 ) ~= "SmartCTF" ) { ID = Sender.PlayerReplicationInfo.PlayerID; if( Mid( MutateString, 9, 9 ) ~= "ShowStats" || Mid( MutateString, 9, 5 ) ~= "Stats" ) { SenderStats = SCTFGame.GetStats( Sender ); if( SenderStats != None ) SenderStats.ToggleStats(); } else if( Mid( MutateString, 9, 10 ) ~= "ForceStats" ) { SenderStats = SCTFGame.GetStats( Sender ); if( SenderStats != None ) SenderStats.ShowStats(); } else if( Mid( MutateString, 9, 5 ) ~= "Rules" || Mid( MutateString, 9, 6 ) ~= "Points" || Mid( MutateString, 9, 5 ) ~= "Score" || Mid( MutateString, 9, 5 ) ~= "Bonus" ) { if( bNewCapAssistScoring ) Sender.ClientMessage( "SmartCTF Score Settings: - Cap/Assist:" @ 7 + CapBonus @ "pts divided over all FC's by time" ); else Sender.ClientMessage( "SmartCTF Score Settings: - Cap:" @ 7 + CapBonus @ "pts, Assist:" @ AssistBonus @ "pts." ); Sender.ClientMessage( "- Cover (Kills while defending FC) Bonus :" @ CoverBonus @ "pts each. And" @ CoverBonus @ "more pts each if FC caps." ); Sender.ClientMessage( "- Seal Bonus:" @ SealBonus @ "pts each, and" @ SealBonus @ "more pts each if FC caps." ); Sender.ClientMessage( "- Seals (Kills while sealing off base) are defined by: 1) Your FC is on your team's side of map. 2) Your flag is not taken. 3) You kill someone on your side of the map." ); Sender.ClientMessage( "- Flagkills:" @ 5 + FlagKillBonus @ "pts. Flag Returns in base are worth" @ DitchZeros( BaseReturnBonus ) @ "pts, in mid" @ DitchZeros( MidReturnBonus ) @ "pts, enemy base" @ DitchZeros( EnemyBaseReturnBonus ) @ "pts, VERY close to capping" @ DitchZeros( CloseSaveReturnBonus ) @ "pts." ); Sender.ClientMessage( "- Additional features: See Readme!" ); } else if( Mid( MutateString, 9, 8 ) ~= "ForceEnd" ) { if( !Sender.PlayerReplicationInfo.bAdmin && Level.NetMode != NM_StandAlone ) { Sender.ClientMessage( "You need to be logged in as admin to force the game to end." ); } else { BroadcastMessage( Sender.PlayerReplicationInfo.PlayerName @ "forced the game to end." ); bForcedEndGame = True; CTFGame( Level.Game ).EndGame( "forced" ); } } else if( Mid( MutateString, 9, 10 ) ~= "ClearStats" ) { if( !Sender.PlayerReplicationInfo.bAdmin && Level.NetMode != NM_StandAlone ) { Sender.ClientMessage( "You need to be logged in as admin to be able to clear the stats." ); } else { ClearStats(); Sender.ClientMessage( "Stats cleared." ); } } else { Sender.ClientMessage( "SmartCTF by {PiN}Kev_HH. SmartCTF " $ Version $ " by {DnF2}SiNiSTeR." ); Sender.ClientMessage( "- To toggle stats, bind a key or type in console: 'Mutate SmartCTF Stats'" ); Sender.ClientMessage( "- Type 'Mutate CTFInfo' for SmartCTF settings." ); Sender.ClientMessage( "- Type 'Mutate SmartCTF Rules' for new point system definition." ); Sender.ClientMessage( "- Type 'Mutate SmartCTF ForceEnd' to end a game." ); if( bEnableOvertimeControl ) Sender.ClientMessage( "- Type 'Mutate OverTime ' for Overtime Control." ); } } else if( Left( MutateString, 7 ) ~= "CTFInfo" ) { SoundsString = ""; if( bPlayCaptureSound ) SoundsString = SoundsString @ "Capture"; if( bPlayAssistSound ) SoundsString = SoundsString @ "Assist"; if( bPlaySavedSound ) SoundsString = SoundsString @ "Saved"; if( bPlayLeadSound ) SoundsString = SoundsString @ "Lead"; if( bPlay30SecSound ) SoundsString = SoundsString @ "30SecLeft"; if( SoundsString == "" ) SoundsString = "All off"; if( Left( SoundsString, 1 ) == " " ) SoundsString = Mid( SoundsString, 1 ); MsgsString = ""; if( CoverMsgType == 1 ) MsgsString = MsgsString @ "Covers"; if( CoverMsgType == 2 ) MsgsString = MsgsString @ "Covers"; if( CoverMsgType == 3 ) MsgsString = MsgsString @ "Covers"; if( CoverSpreeMsgType == 1 ) MsgsString = MsgsString @ "Coversprees"; if( CoverSpreeMsgType == 2 ) MsgsString = MsgsString @ "Coversprees"; if( CoverSpreeMsgType == 3 ) MsgsString = MsgsString @ "Coversprees"; if( SealMsgType == 1 ) MsgsString = MsgsString @ "Seals"; if( SealMsgType == 2 ) MsgsString = MsgsString @ "Seals"; if( SealMsgType == 3 ) MsgsString = MsgsString @ "Seals"; if( SavedMsgType == 1 ) MsgsString = MsgsString @ "Saved"; if( SavedMsgType == 2 ) MsgsString = MsgsString @ "Saved"; if( SavedMsgType == 3 ) MsgsString = MsgsString @ "Saved"; if( MsgsString == "" ) MsgsString = "All off"; if( Left( MsgsString, 1 ) == " " ) MsgsString = Mid( MsgsString, 1 ); CMsgsString = ""; if( bShowAssistConsoleMsg ) CMsgsString = CMsgsString @ "AssistBonus"; if( bShowSealRewardConsoleMsg ) CMsgsString = CMsgsString @ "SealReward"; if( bShowCoverRewardConsoleMsg ) CMsgsString = CMsgsString @ "CoverReward"; if( bShowLongRangeMsg ) CMsgsString = CMsgsString @ "LongRangeKill"; if( CMsgsString == "" ) CMsgsString = "All off"; if( Left( CMsgsString, 1 ) == " " ) CMsgsString = Mid( CMsgsString, 1 ); Sender.ClientMessage( "- Sounds:" @ SoundsString ); Sender.ClientMessage( "- Msgs:" @ MsgsString ); Sender.ClientMessage( "- Private Msgs:" @ CMsgsString ); Sender.ClientMessage( "- bFixFlagBug:" @ bFixFlagBug ); Sender.ClientMessage( "- bEnhancedMultiKill:" @ bEnhancedMultiKill $ ", Broadcast Level:" @ EnhancedMultiKillBroadcast ); Sender.ClientMessage( "- bShowFCLocation:" @ bShowFCLocation ); if( bSpawnKillDetection ) Sender.ClientMessage( "- bSpawnKillDetection: True, Global Msg:" @ bShowSpawnKillerGlobalMsg $ ", Penalty:" @ SpawnKillPenalty @ "pts" ); else Sender.ClientMessage( "- bSpawnKillDetection: False" ); Sender.ClientMessage( "- Overtime Control:" @ bEnableOvertimeControl @ "( Type 'Mutate OverTime' )" ); Sender.ClientMessage( "- Scores: ( Type 'Mutate SmartCTF Rules' )"); } else if( Left( MutateString, 8 ) ~= "OverTime" ) { if( !DeathMatchPlus( Level.Game ).bTournament ) { Sender.ClientMessage( "Not in Tournament Mode: Default Sudden Death Overtime behaviour." ); } else if( !bEnableOvertimeControl ) { Sender.ClientMessage( "Overtime Control is not enabled: Default UT Sudden Death functionality." ); Sender.ClientMessage( "Admins can use: admin set SmartCTF bEnableOvertimeControl True" ); } else { if( Left( MutateString, 11 ) ~= "OverTime On" ) { if( !Sender.PlayerReplicationInfo.bAdmin && Level.NetMode != NM_StandAlone ) { Sender.ClientMessage( "You need to be logged in as admin to change this setting." ); } else { bOvertime = True; SaveConfig(); BroadcastLocalizedMessage( class'SmartCTFCoolMsg', 3 ); } } else if( Left( MutateString, 12 ) ~= "OverTime Off" ) { if( !Sender.PlayerReplicationInfo.bAdmin && Level.NetMode != NM_StandAlone ) { Sender.ClientMessage( "You need to be logged in as admin to change this setting." ); } else { bOvertime = False; SaveConfig(); BroadcastLocalizedMessage( class'SmartCTFCoolMsg', 4 ); } } else { if( Sender.PlayerReplicationInfo.bAdmin || Level.NetMode == NM_StandAlone ) Sender.ClientMessage( "Usage: Mutate OverTime On|Off" ); if( !bOvertime ) Sender.ClientMessage( "Sudden Death Overtime is DISABLED." ); else Sender.ClientMessage( "Sudden Death Overtime is ENABLED (default)." ); Sender.ClientMessage( "Remember 'Disabled' Setting:" @ bRememberOvertimeSetting ); } } } super.Mutate( MutateString, Sender ); } /* * To stop on a tie if needed. */ function bool HandleEndGame() { local TeamInfo Best; local byte i, MaxTeams; local bool bTied; if( CTFGame( Level.Game ).Teams[0].Score == CTFGame( Level.Game ).Teams[1].Score ) bTied = True; if( bForcedEndGame || ( bEnableOvertimeControl && !bOvertime && DeathMatchPlus( Level.Game ).bTournament ) ) { bForcedEndGame = False; if( bTied ) { SetEndCamsTiedCTFGame(); //ShowEndGameStats(); return True; } } if( !bTied ) { CalcSmartCTFEndStats(); //ShowEndGameStats(); } if( NextMutator != None ) return NextMutator.HandleEndGame(); return False; } /*function ShowEndGameStats() { local Pawn pn; local SmartCTFPlayerReplicationInfo PlayerStats; for( pn = Level.PawnList ; pn != None ; pn = pn.NextPawn ) { if( PlayerPawn( pn ) != None && pn.bIsPlayer ) { PlayerStats = SCTFGame.GetStats( pn ); if( PlayerStats != None ) PlayerStats.ShowStats(); } } }*/ /* * Position end cameras for a tied game. */ function SetEndCamsTiedCTFGame() { local Pawn pn, Best; local PlayerPawn Player; local CTFGame gg; gg = CTFGame( Level.Game ); // Find Individual Winner for( pn = Level.PawnList ; pn != None ; pn = pn.NextPawn ) { if( pn.bIsPlayer && ( ( Best == None ) || ( pn.PlayerReplicationInfo.Score > Best.PlayerReplicationInfo.Score ) ) ) Best = pn; } gg.GameReplicationInfo.GameEndedComments = GameTieMessage; gg.EndTime = Level.TimeSeconds + 3.0; for( pn = Level.PawnList ; pn != None ; pn = pn.NextPawn ) { Player = PlayerPawn( pn ); if( Player != None ) { Player.bBehindView = True; if( Player == Best ) Player.ViewTarget = None; else Player.ViewTarget = Best; Player.ClientPlaySound( sound'CaptureSound', , true ); Player.ClientGameEnded(); } pn.GotoState( 'GameEnded' ); } gg.CalcEndStats(); CalcSmartCTFEndStats(); } function CalcSmartCTFEndStats() { local SmartCTFPlayerReplicationInfo TopScore, TopFrags, TopCaps, TopCovers, TopFlagkills, TopHeadshots; local string BestRecordDate; local int ID; local float PerHour; local SmartCTFPlayerReplicationInfo PawnStats; local PlayerReplicationInfo PRI; local byte i; local SmartCTFEndStats EndStats; EndStats = SCTFGame.EndStats; SCTFGame.RefreshPRI(); for( i = 0; i < 64; i++ ) { PawnStats = SCTFGame.GetStatNr( i ); if( PawnStats == None ) break; if( TopScore == None || PlayerReplicationInfo( PawnStats.Owner ).Score > PlayerReplicationInfo( TopScore.Owner ).Score ) TopScore = PawnStats; if( TopFrags == None || PawnStats.Frags > TopFrags.Frags ) TopFrags = PawnStats; if( TopCaps == None || PawnStats.Captures > TopCaps.Captures ) TopCaps = PawnStats; if( TopCovers == None || PawnStats.Covers > TopCovers.Covers ) TopCovers = PawnStats; if( TopFlagkills == None || PawnStats.FlagKills > TopFlagkills.FlagKills ) TopFlagkills = PawnStats; if( TopHeadshots == None || PawnStats.HeadShots > TopHeadshots.HeadShots ) TopHeadshots = PawnStats; } PRI = PlayerReplicationInfo( TopScore.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( PRI.Score / PerHour > EndStats.MostPoints.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostPoints.Count = PRI.Score / PerHour; EndStats.MostPoints.PlayerName = PRI.PlayerName; EndStats.MostPoints.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostPoints.RecordDate = BestRecordDate; } PRI = PlayerReplicationInfo( TopFrags.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( TopFrags.Frags / PerHour > EndStats.MostFrags.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostFrags.Count = TopFrags.Frags / PerHour; EndStats.MostFrags.PlayerName = PRI.PlayerName; EndStats.MostFrags.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostFrags.RecordDate = BestRecordDate; } PRI = PlayerReplicationInfo( TopCaps.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( TopCaps.Captures / PerHour > EndStats.MostCaps.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostCaps.Count = TopCaps.Captures / PerHour; EndStats.MostCaps.PlayerName = PRI.PlayerName; EndStats.MostCaps.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostCaps.RecordDate = BestRecordDate; } PRI = PlayerReplicationInfo( TopCovers.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( TopCovers.Covers / PerHour > EndStats.MostCovers.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostCovers.Count = TopCovers.Covers / PerHour; EndStats.MostCovers.PlayerName = PRI.PlayerName; EndStats.MostCovers.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostCovers.RecordDate = BestRecordDate; } PRI = PlayerReplicationInfo( TopFlagkills.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( TopFlagkills.FlagKills / PerHour > EndStats.MostFlagKills.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostFlagKills.Count = TopFlagkills.FlagKills / PerHour; EndStats.MostFlagKills.PlayerName = PRI.PlayerName; EndStats.MostFlagKills.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostFlagKills.RecordDate = BestRecordDate; } PRI = PlayerReplicationInfo( TopHeadshots.Owner ); PerHour = ( Level.TimeSeconds - PRI.StartTime ) / 3600; if( TopHeadshots.HeadShots / PerHour > EndStats.MostHeadShots.Count && Level.TimeSeconds - PRI.StartTime > 300 ) { EndStats.MostHeadShots.Count = TopHeadshots.HeadShots / PerHour; EndStats.MostHeadShots.PlayerName = PRI.PlayerName; EndStats.MostHeadShots.MapName = Level.Title; CTFGame( Level.Game ).GetTimeStamp( BestRecordDate ); EndStats.MostHeadShots.RecordDate = BestRecordDate; } EndStats.SaveConfig(); } /* * Convert a float to a readable string. */ function string DitchZeros( float nr ) { local string str; str = string( nr ); while( Right( str, 1 ) == "0" ) { str = Left( str , Len( str ) - 1 ); } if( Right( str, 1 ) == "." ) str = Left( str , Len( str ) - 1 ); return str; } //---------------------------------------------------------------------------------------------------------------- //------------------------------------------------ CLIENT FUNCTIONS ---------------------------------------------- //---------------------------------------------------------------------------------------------------------------- /* * Render the HUD that is startup logo and FC location. * ONLY gets executed on clients. */ simulated event PostRender( Canvas C ) { local int i, Y; local float DummyY, Size; local string TempStr; // Get stuff relating to PlayerOwner, if not gotten. Also spawn Font info. if( PlayerOwner == None ) { PlayerOwner = C.Viewport.Actor; MyHUD = ChallengeHUD( PlayerOwner.MyHUD ); pTGRI = TournamentGameReplicationInfo( PlayerOwner.GameReplicationInfo ); pPRI = PlayerOwner.PlayerReplicationInfo; MyFonts = MyHUD.MyFonts; } // Draw the FC Location if( SCTFGame.bShowFCLocation ) { for( i = 0; i < 32; i++ ) { if( pTGRI.PRIArray[i] == None ) break; if( pTGRI.PRIArray[i].bIsSpectator && !pTGRI.PRIArray[i].bWaitingPlayer ) continue; if( pTGRI.PRIArray[i].HasFlag != None && pTGRI.PRIArray[i].Team == pPRI.Team && pTGRI.PRIArray[i].PlayerID != pPRI.PlayerID && !pTGRI.PRIArray[i].HasFlag.IsA( 'GreenFlag' ) ) { if( pTGRI.PRIArray[i].PlayerLocation != None ) TempStr = pTGRI.PRIArray[i].PlayerLocation.LocationName; else if( pTGRI.PRIArray[i].PlayerZone != None ) TempStr = pTGRI.PRIArray[i].PlayerZone.ZoneName; if( TempStr == "" ) { TempStr = "Nameless Area"; C.Style = ERenderStyle.STY_Translucent; } else { C.Style = ERenderStyle.STY_Normal; } if( pPRI.Team == 0 ) C.DrawColor = RedTeamColor; else C.DrawColor = BlueTeamColor; C.Font = MyFonts.GetSmallestFont( C.ClipX ); C.StrLen( TempStr, Size, DummyY ); if( MyHUD.bHideAllWeapons ) Y = C.ClipY; else if( MyHUD.HudScale * MyHUD.WeaponScale * C.ClipX <= C.ClipX - 256 * MyHUD.Scale) Y = C.ClipY - 64 * MyHUD.Scale; else Y = C.ClipY - 128 * MyHUD.Scale; C.SetPos( C.ClipX - Size - 6, Y - 4 - 32 + ( 32 - DummyY ) / 2 ); C.DrawText( TempStr ); if( C.Style == ERenderStyle.STY_Translucent ) C.DrawColor = Gray; else C.DrawColor = White; C.SetPos( C.ClipX - Size - 6 - 32 - 4, Y - 4 - 32 ); if( pPRI.Team == 0 ) C.DrawIcon( texture'blueflag', 1.0 ); else C.DrawIcon( texture'redflag', 1.0 ); break; } } } // Draw "Powered by.." logo when player joins if( DrawLogo != 0 ) { C.Style = ERenderStyle.STY_Translucent; if( DrawLogo > 1 ) { C.DrawColor.R = 255 - DrawLogo; C.DrawColor.G = 255 - DrawLogo; C.DrawColor.B = 255 - DrawLogo; } else // 1 { C.Style = ERenderStyle.STY_Translucent; C.DrawColor = White; } C.SetPos( C.ClipX - 128 - 16, 16 ); C.DrawIcon( texture'powered', 1 ); C.Font = MyFonts.GetBigFont( C.ClipX ); C.StrLen( LogoText , Size, DummyY ); C.SetPos( C.ClipX - Size - 16, 16 + 8 + 128 ); C.DrawText( LogoText ); } C.Style = ERenderStyle.STY_Normal; if( NextHUDMutator != None ) NextHUDMutator.PostRender( C ); } /* * Executed on the client when that player joins the server. */ simulated function ClientJoinServer( Pawn Other ) { if( PlayerPawn( Other ) == None || !Other.bIsPlayer ) return; if( !SCTFGame.bDrawLogo ) { Other.ClientMessage( "Running SmartCTF " $ Version $ ". Type 'Mutate SmartCTF' in the console for info." ); } else { DrawLogo = 1; SetTimer( 0.05 , True); } // Since this gets called in the HUD it needs to be changed clientside. if( SCTFGame.bPlay30SecSound ) class'TimeMessage'.default.TimeSound[5] = sound'Announcer.CD30Sec'; } /* * Clientside settings that need to be set for the first time, checking for welcome message and * end of game screen. */ simulated function Tick( float delta ) { local int i; local SmartCTFPlayerReplicationInfo OwnerStats; // Execute on client if( Level.NetMode != NM_DedicatedServer ) { if( SCTFGame == None ) { ForEach AllActors( class'SmartCTFGameReplicationInfo', SCTFGame ) break; if( SCTFGame == None ) return; if( !SCTFGame.bServerInfoSetServerSide && SCTFGame.DefaultHUDType != None ) // client side required { class( SCTFGame.DefaultHUDType ).default.ServerInfoClass = class'SmartCTFServerInfo'; Log( "Notified HUD (clientside," @ SCTFGame.DefaultHUDType.Name $ ") to use SmartCTF ServerInfo.", 'SmartCTF' ); } } if( !SCTFGame.bInitialized ) return; if( !bHUDMutator ) RegisterHUDMutator(); if( PlayerOwner != None ) { if( !bClientJoinPlayer ) { bClientJoinPlayer = True; ClientJoinServer( PlayerOwner ); } // If Game is over, bring up F3. if( PlayerOwner.GameReplicationInfo.GameEndedComments != "" && !bGameEnded ) { bGameEnded = True; //OwnerStats = SCTFGame.GetStatsByPRI( pPRI ); //if( OwnerStats != None ) OwnerStats.ShowStats(); PlayerOwner.ConsoleCommand( "mutate SmartCTF ForceStats" ); } } } } /* * For showing the Logo a Timer is used instead of Ticks so its equal for each tickrate. * On the server it keeps track of some replicated data and whether a Tournament game is starting. */ simulated function Timer() { local bool bReady; local Pawn pn; super.Timer(); // Clients - 0.05 second timer. Stops after logo is displayed. if( Level.NetMode != NM_DedicatedServer ) { if( DrawLogo != 0 ) { LogoCounter++; if( DrawLogo == 255 ) { DrawLogo = 0; if( Role != ROLE_Authority ) SetTimer( 0.0, False ); // client timer off else SetTimer( 1.0, True ); // standalone game? keep timer running for bit below. } else if( LogoCounter > 60 ) { DrawLogo += 8; if( DrawLogo > 255 ) DrawLogo = 255; } else if( LogoCounter == 60 ) { DrawLogo = 5; } } } // Server - 1 second timer. infinite. if( Level.NetMode == NM_DedicatedServer || Role == ROLE_Authority ) { if( ++TRCount > 2 ) { SCTFGame.TickRate = int( ConsoleCommand( "get IpDrv.TcpNetDriver NetServerMaxTickRate" ) ); TRCount = 0; } // Update config vars to client / manual replication :E // Allows for runtime changing of settings. if( SCTFGame.bShowFCLocation != bShowFCLocation ) SCTFGame.bShowFCLocation = bShowFCLocation; if( SCTFGame.bStatsDrawFaces != bStatsDrawFaces ) SCTFGame.bStatsDrawFaces = bStatsDrawFaces; if( SCTFGame.bDrawLogo != bDrawLogo ) SCTFGame.bDrawLogo = bDrawLogo; if( !bTournamentGameStarted && DeathMatchPlus( Level.Game ).bTournament ) { if( DeathMatchPlus( Level.Game ).bRequireReady && DeathMatchPlus( Level.Game ).CountDown > 0 && ( DeathMatchPlus( Level.Game ).NumPlayers == DeathMatchPlus( Level.Game ).MaxPlayers || Level.NetMode == NM_Standalone ) && DeathMatchPlus( Level.Game ).RemainingBots <= 0 ) { bReady = True; for( pn = Level.PawnList; pn != None; pn = pn.NextPawn ) { if( pn.IsA( 'PlayerPawn' ) && !pn.IsA( 'Spectator' ) && !PlayerPawn( pn ).bReadyToPlay ) { bReady = False; break; } } } if( bReady ) { bTournamentGameStarted = True; TournamentGameStarted(); } } } } €@ÖKˆw.«‹“*çServerActor, Spawning and adding Mutator...!‹“û t‹“a }a r r I ÿÿÿÿv r I ÿÿÿÿn I ÿÿÿÿi I ÿÿÿÿ| I ÿÿÿÿ_I ÿÿÿÿ]I þÿÿÿh h ùÿÿÿ{ I þÿÿÿi I þÿÿÿn I ÿÿÿÿj I üÿÿÿpI þÿÿÿE I þÿÿÿI h ñÿÿÿKh úÿÿÿ{I ýÿÿÿ]I ÿÿÿÿq I þÿÿÿZ ] ýÿÿÿpv ûÿÿÿjI þÿÿÿj I üÿÿÿiI üÿÿÿWi ýÿÿÿVQ ðÿÿÿI üÿÿÿNh ÷ÿÿÿn I üÿÿÿmI þÿÿÿv I ÿÿÿÿg h ùÿÿÿuI þÿÿÿI r X I þÿÿÿ] i úÿÿÿrh ýÿÿÿz I Ûÿÿÿ_h òÿÿÿMI üÿÿÿfi ûÿÿÿFI üÿÿÿqI ÿÿÿÿz n ûÿÿÿnI üÿÿÿ}v ýÿÿÿiI üÿÿÿtI ÿÿÿÿo Z ûÿÿÿGI ÿÿÿÿh] ùÿÿÿch ëÿÿÿHv åÿÿÿjI þÿÿÿv h àÿÿÿMn ûÿÿÿ~I ýÿÿÿ_i ýÿÿÿCj ÷ÿÿÿeI ÿÿÿÿt r ¿ÿÿÿQr Dh ûÿÿÿEI üÿÿÿyv úÿÿÿYI üÿÿÿoh æÿÿÿZh øÿÿÿq i ×ÿÿÿFi ûÿÿÿmI üÿÿÿKn ×ÿÿÿar üÿÿÿJj ûÿÿÿAj ûÿÿÿ@v ùÿÿÿH Z úÿÿÿF I ðÿÿÿc I Ëÿÿÿ#Z ëÿÿÿph úÿÿÿXI üÿÿÿlI ùÿÿÿj ûÿÿÿ|v ãÿÿÿT _ ðÿÿÿT I ÿÿÿÿgh ÷ÿÿÿwh £ÿÿÿZI üÿÿÿuj ýÿÿÿdh øÿÿÿxI ÿÿÿÿl v ãÿÿÿU j ÓÿÿÿhI ÿÿÿÿ} I ùÿÿÿ%v ûÿÿÿCI Þÿÿÿ@h ûÿÿÿ[I ýÿÿÿaI ÿÿÿÿr n ûÿÿÿVI ÿÿÿÿp I ÿÿÿÿk n ëÿÿÿwv ãÿÿÿ] I üÿÿÿN^ ðÿÿÿI h åÿÿÿ~h øÿÿÿy] Ëÿÿÿph ñÿÿÿMI ÿÿÿÿD I ÿÿÿÿ*^ òÿÿÿzn âÿÿÿ}h ÞÿÿÿJh ûÿÿÿh òÿÿÿOI üÿÿÿqj ýÿÿÿJI þÿÿÿ^ i Ðÿÿÿf I ýÿÿÿ^I üÿÿÿXI üÿÿÿjI ÿÿÿÿs j øÿÿÿNI ÿÿÿÿm C uÿÿÿ]r KI üÿÿÿwI ËÿÿÿI üÿÿÿvr üÿÿÿw h ùÿÿÿZ —ÿÿÿ|Z ëÿÿÿOh ûÿÿÿ\Z ”ÿÿÿCh øÿÿÿ} I ½ÿÿÿGI ÞÿÿÿAh òÿÿÿq I üÿÿÿur üÿÿÿjI üÿÿÿPI ùÿÿÿqZ ëÿÿÿND ´ÿÿÿnh øÿÿÿMh ÞÿÿÿBI ÞÿÿÿZ ëÿÿÿtI ÞÿÿÿI ñÿÿÿI àÿÿÿI Áÿÿÿp^ ÐÿÿÿA^ òÿÿÿVI ½ÿÿÿHr üÿÿÿsZ ëÿÿÿLZ ñÿÿÿwj ñÿÿÿLZ ëÿÿÿrI Þÿÿÿui ËÿÿÿjD ´ÿÿÿRC ZÿÿÿGj ûÿÿÿBI ÞÿÿÿsZ àÿÿÿ]Z ëÿÿÿZh ýÿÿÿ[Z ëÿÿÿMI yÿÿÿli âÿÿÿkD Hÿÿÿlr Fÿÿÿ]D Eÿÿÿir Ûÿÿÿkr ÛÿÿÿJI àÿÿÿZI üÿÿÿLD @ÿÿÿmI Cÿÿÿ5r >ÿÿÿJI àÿÿÿ@r II «ÿÿÿhI «ÿÿÿSI Þÿÿÿdj ÞÿÿÿAj ÓÿÿÿIh ÐÿÿÿM_ ~ÿÿÿCh ýÿÿÿu Z ÷ÿÿÿW^ ËÿÿÿDn ÓÿÿÿdI ÞÿÿÿCn úÿÿÿSI vÿÿÿ#I }ÿÿÿUj Ëÿÿÿ_z ÿÿÿÿ[I üÿÿÿ{I üÿÿÿHn ÓÿÿÿgI ñÿÿÿnj ÐÿÿÿVn ëÿÿÿvI ñÿÿÿFi ÐÿÿÿSi ÐÿÿÿTI àÿÿÿUI àÿÿÿoi ÓÿÿÿJh xÿÿÿBj åÿÿÿsr üÿÿÿ\n ëÿÿÿPI øÿÿÿWI „ÿÿÿj øÿÿÿCv ¶ÿÿÿjn úÿÿÿpn ÿÿÿzI »ÿÿÿ#I üÿÿÿGn æÿÿÿZ àÿÿÿ[n úÿÿÿ|n úÿÿÿjZ àÿÿÿ\Z àÿÿÿZZ àÿÿÿQZ àÿÿÿNZ àÿÿÿTn úÿÿÿmn úÿÿÿrZ àÿÿÿSZ àÿÿÿ`I üÿÿÿzz ÿÿÿ]i ÐÿÿÿUn æÿÿÿ@Z àÿÿÿ^Z àÿÿÿ_Z àÿÿÿPZ àÿÿÿan ½ÿÿÿEI ùÿÿÿnn òÿÿÿPn òÿÿÿY^ òÿÿÿXh ÿÿÿG D jÿÿÿUZ «ÿÿÿxi ÷ÿÿÿbD jÿÿÿTZ àÿÿÿSZ àÿÿÿQZ àÿÿÿPZ àÿÿÿOj ÷ÿÿÿQZ ñÿÿÿvZ „ÿÿÿmh ÿÿÿxZ »ÿÿÿdZ »ÿÿÿfZ »ÿÿÿcZ »ÿÿÿbI »ÿÿÿPI »ÿÿÿZ »ÿÿÿeh ÿÿÿ| D ´ÿÿÿLh ÷ÿÿÿh ] ùÿÿÿBI «ÿÿÿPZ âÿÿÿmQ ðÿÿÿO I ÿÿÿÿu D ´ÿÿÿXD ´ÿÿÿYD ´ÿÿÿZI ÿÿÿÿG I þÿÿÿQ C ÀÿÿÿEC ÀÿÿÿGC ÀÿÿÿHC ÀÿÿÿFI þÿÿÿr r yÿÿÿjD ÔþÿÿkI þÿÿÿ_ C ÀÿÿÿgC ÀÿÿÿdC ÀÿÿÿbC ÀÿÿÿaC ÀÿÿÿcC ÀÿÿÿeC ÀÿÿÿfC Àÿÿÿhë}cfÄŠ.@ IÈëfWÈÕCi}Ê.K  fÌŠ}hsÌŠOsAÍ.D  OÍŠ)^\ÍŒ©D  jÍŠ}mvÍŠ@  DÎŒ©g  QÎ. ^ΊOyjΊ¦@ xΊOr FÏŒ©b  SÏ–.i _ÏŠu kÏ–)P  xÏ¡1K DÐÃ~~RЊ}PØŠ¦u^ØŠ‡@ lØŠ.UzØŠ1[ HÙŠ1tUÙŠOIcÙ¡_F qÙŠŽ@ ÙŠ7@ MÚŠJ[ÚŠ@ iÚ¡9F wÚŠ«@EÛŠ«hSÛ¡;F aÛŠ…@  oÛŠž@ |ÛŠ«@JÜŠ•@ XÜŒ\  fÜÆB  rÜŠjU ÜŒ._  LÝ–)O  YÝŒ©c  eÝŠ/M rÝŠE@ @ÞWNÞ–)D ]ÞŠ%@ iÞ–)Q  wÞŠOE DßK  QߊM  ^ß¡_K  kß}~ xß–UY  EàŠ«x RàŠ w`àŠ}@nà–¦l  |à–Æo  IáŠ}qUáŠ}pcá–¦k  qá–ÆG ~á–A K⌫Z  XâŠRRdâ–ÆU râŠQ@ ⌫R  Mã\ ZãŒ.D g㌫M  t㌫Y  AäŠHN䌫T  \ä] iä¡jK  väVCå¡5K  Q匩d  ^åTk劫a zåŠ8@ H披_ VæQdæ–B sæŠ1wæ¦r MçŠ}@^ç¦u lç¦s }çŠtNèŠ1F\è–¦R j茫V  wè¦t Dé¦K  Ué¦p aé™Ot ré¡}Jé¦q Mꊔ|^ê–¦m  lꊳ@ xêÃDhFëEg nïŠ } {ïŒ}r IðŒ}s VðŠSRcðŠŽeqð–Uj ðŒ«U  LñŠLYñŒ.a gñŠOz tñŠLdAòŠLo Oò.F  \òîOp iòXvò}e EóŠ}xRóR`ó«l  oóEc |óŠ£tHô¡RVô–¦F  dôŠIJqôŒ«O  ôŠ/L LõŒ;T ZõŒ©f  gõ;C  tõŠw AöŠ1^NöŠ1I \ö.z  jö.y  wö¡}ID÷¦©w R÷¡1H _÷} m÷~K  z÷Œ9T Fø9C  SøŠ«` `øUnøS}øYLùŒ9q [ùZgùŠY vùŠX DúŠ?}Rú¦Nn `ú¡}\múŒ7t  {ú[ Hû¡}HUû^ cûŠ)R  pû}b }û}c JüŒ}W WüŠe düs  qüˆK  ~üŠOwJý¡b XýŒ.@  eý™}R rýŠW ýŒK  MþŠ1J  ZþŠYl gþŒ©a  tþ¦.Y@ÿ¡}uNÿ–i \ÿŠWlhÿŒ;q vÿ™JB€¡}tQ€¦©s_€þIm€Œ«N  €Š[ LŠZ ZæxhŠ{J {ŠzJ H‚ŠhJU‚ŠA}c‚ÃFTq‚1s  E…ŠSo Q…•K  ^…D  k…Œa x…–Ud  E†ŒŽP Q†™}k ]†™}| j†Šsw†™}E E‡.x  R‡ŒŽO _‡.w  l‡Š-M  y‡Š/w Fˆ+K  SˆŠ‡e`ˆ™}W nˆK  {ˆ¦©vG‰8S  U‰Œ«X  b‰Œ` o‰Š1s|‰}] JŠ¡AK  WŠ8B  dŠŒ7u  qŠ¡.A }Š¡?K  K‹™` X‹þ1E e‹Š<@  t‹Œ©e  AŒŠ LNŒ«h  \Œ«i  iŒ«o  vŒ«m  CŠ}AP«k  ^«j  kNs  x™_[  EŽŠ_\ RŽ™}z `ŽŠ}xmŽ³{  |ŽŠ«d IŠV WŠ©heŠ q sŠ«] @«p  NŠ«[ [«q  i8 uŠ«AB‘8D  P‘Š1L]‘™}S k‘¡}Zx‘–Fv F’Œ«W  R’™}v _’ŠF}l’ŒF z’_G G“Œ‡O S“¡K  `“þKm“¡/K  ~“™sK”ŒE_  Z”+J  g”™ut”¡-K C•.e  Q•™v^•Š.D  m•–EV  z•™Ou G–Œ«J  T–«  a––EW  n––«Z {–Š_D  H—Š°JU—Œ%G  c—ÅAap—Š+@ QšŒ¦H _š™&S  lšŠžN xšŒ+M  E›Œ+N  R›Œ4q ^›4G  j›«~  w›Š•eDœŒ4e  Rœ¡«A _œŒ³P  mœŠ9B zœŒ³_  HŠ;B T¦«Rb¦«cpŠ–[ ~Œ«K  KžŒ«L  XžDežŒOx tžŠu@ŸEf PŸ–R~ ]ŸŒ.O iŸ–RQ vŸŠSyC ŒQ  Q Œ_  ^ Œ«P  k ŒQ_  x ŠXoD¡ŠR R¡Œ.  _¡Œ.~  k¡™ox¡Œ«S  G¢.}  T¢™^ `¢ŠŒ} m¢.|  z¢Š~}G£™}A U£Œ«{ b£Œk o£Œ©M |£Œ.{  I¤™}G V¤s  c¤Štp¤–}k ~¤™}s K¥™}u X¥™©`  e¥ZO r¥™}V ~¥Š«a K¦™}y Y¦}} f¦Š}Mr¦«n  @§Œ%F  M§D} Z§}d g§}H t§Œ}a A¨Œ}` N¨¡f|[¨Is  i¨¡fT v¨Œ}_ D©–}j Q©Œ}^ ^©™}W k©™}| x©™}{ EªŠ«g Rª}\ `ªŠ«f mªŠ«e {ªŠf{ I«Š«c V«Š«b d«™}[ r«¢tx«™}` s¤hs  @¥¡}kM¥Š«^ [¥Œ©F i¥Š«\ v¥õ¼gAD¦™}D E¨Œ©{ R¨Œa ^¨™_ k¨™}C x¨™}f E©™}@ R©Šˆ}_©™}t m©ŠŒJz©™}l HªZT  TªŒ«Q  aª™Wn nª™Ov zª™tG«ŠLRV«ŒE  d«8l q«Œ8a }«¦«jJ¬ŒA~ X¬¦«de¬¦«`s¬Œ?~ A­¡5jN­¡«@ \­Œ4T j­¡.B w­–«^ E®–«\ R®•c _®–«{ k®–«V x®Š+L E¯«y  S¯Õzn!_¯¦.C  MÑï4{;ZÑŠ°tUŒ%H  c°s  o¦}R|–&J JŽ×@XVŽÃy^n‘ŒžP L”£s  Y”Š°Lf”Š°s t”ŒžO A•ŒžH N•ŒžF [•Šžeh•Œ›C v•Œ›H C–üxlP–Œ•P |˜–T I™–N U™–H b™–G o™–| |™–r Iš–q Vš–p cš–o pšŒ•O }š–n J›–m W›¦«<d›¦«=r›¦«a@œ¦«bNœŒ•H \œ¦«eiœ¦«gwœ¦«iEŒ•F S–±w `’s  lŒŽH yŒŽF FžŒ‡P SžŒ‡H _žŒ‡F lžƒs  yž¡„K FŸ–}I TŸŒkC `ŸŒkH mŸ–©r zŸ¡jG ¦pl U ¦pib ¦php –pg ~ –pf K¡–pO X¡–pL e¡–pK r¡Šhs ¡ŠhLL¢ŠhtZ¢¦}<h¢¦}=v¢¦}>D£™}x R£}K _£™}Y l£Œ}S y£Œ}R F¤™}M S¤Z| `¤¦OEm¤ŠIs |¤ŠILI¥ŠItW¥ŒE~  e¥¡LEr¥¡Fj@¦Œ8_  N¦8_ [¦–8E  h¦8R  u¦8K B§™;A  O§™9A  [§Œ³~  g§ÊBSt§,s  G­/j T­-j a­. n­) z­'s  F®Œ%~  S®Œ^  `®Šsm®ŠL{®‘å½mI¯–b  v°‘Ð#\B±‘ä}%Z ^¸Ša  xÂK  EÃŒP RÑÂ}ni_Ñ}LPHÉ‘Î}C{XÌ–`  Sà–`  `à‘}"jlà Vâ‘}9rbâ‘}OZTü¡&`n¡&K |Š&LJ‚™&`  X‚‘«TKe‚‘Å}dFpŠ‘×&P3v'`  iŽ‘ë}uT>uŽ‘}6IÍ‘«!FÍ‘Ø&rEÕ‘}6MwÖ‘«3}DDÙ‘}Qb Až™1`  c¨‘æ}@bo¨Š,tQÈ–4`  _È‘}mlÈ‘}_YËŠ,LxÍ‘«M]FΑ« acÕ‘}U| DÛŠ,s@æ‘}V| Næ‘ÿ«5bJñ‘ä«%uló‘«:~aö‘}2M_ü‘à«vlÿ‘}1Mb„–,`  o‡™F`  {‡‘&KLHˆ‘«qQ T‰‘}ee“™L`  J––D`  W–‘ê&#Dc–ŒEX g™ŒEU  t™‘ß}XAš™O`  Yž‘Ò&GBež‘Ý}O,g ‘}eCv̑׫nCyÍ‘}fZ|Ñ‘ð}sbVÙ™W`  xÜ‘«[OEÝ–U`  Tå‘}l{`å‘Ö}V[ë‘Ó}AQqð‘«YPBùŠNtRú‘Ø}qJ`úZ`  jûŠNLwû‘Ú«FeEü¦N` j„‘ÉË x„as  X…Šate…ŠaLs…ŠasA†‘«/BO†–a`  Q‡‘ÒË#j]‡Œ}w GŠ‘«WgTŠ‘åpH9{‘Œ}v t’Š}oA“Š}nO“Š©@]“ks  k“Œk`  x“¡}jD”ö¼hCR”ö¼RCU¤õ¼fRØX´ö¼ICjŒ õ¼ezmœ ¡}igž ‘xuž ‘?xm  ‘IQe£ ‘ä%1v¦ ‘Ö*g§ ‘{Q¨ ‘RLª ‘á©:^« ‘Ý©UvX¬ Š„`  N´ ‘ÉpU[´ ‘$&pµ ‘Þ©ooV¶ Šˆ` E¼ ‘ü©Z}S¼ ‘nPÄ ŠŒ` ~Å ŠƒtLÆ ŠƒLZÆ ‘ QhÆ ŠƒsyÈ ‘Á©@iGÉ ‘ä% pÐ ‘Ö&PÑ –ƒ`  vÑ ‘ÒpGWBÒ Š”`  YÓ ‘ѲUNfÓ ‘Ä©SBtÕ ‘â±pFvÜ Š’t|Þ Š’LJß ¦’`  Xß ¦«>eß ‘åH9sß ¹½N 4slà ›s  _è ‘Ã©hDlè ¹²N 4Rpî ö¼bCBõ õ¼w AXE… Œ›`  FÝ ‘ÉoRÝ Š£LAá Š£sOá ‘Þ©P^]á ¹©N 4N¥{ø Š¦eIž¹ªN 4oWž‡{SF£¹«N 4k¾Y¥¹N 4S"Dä¹N 4s W†¹N 4[$J§¹±N 4|eË‘Ò#waܹ&N 4r,XÞ¹N 4j%J‹‘«0Ft°¹N 4a zµ¹pN 4O[¿¹·N 4>jÔõEZhÕ¹ËN 4qBع}N 4uÆsë–£`  h²‘ÖªIt²ë}´