*EX @Cpcv4JuKJ)OX None addLabel hasRight splitRegionVCore Nexgen108Color Register addButtonSystemtrim GetValue SetValueFormatdivideRegionH splitRegionH SetMaxLength addCheckBox addEditBoxlogAdminActionUWindowConsoleCommand InternalTime stringHashnscLog skipRegionSetTextReplaceMessageNotifyaddContentPanel fixStrLensetRPCI addPanel boolHash setContentshowMsgsignalConfigUpdateEnginedivideRegionVsplitAddTextUBitsUClampVClampPaletteVBitsUSizeVSizeMipZerogetconfigChangedClosebMasked bInvisiblelfillpanelIdentifier addNewLine addComponent MaxColor playerEventprintlngetControllerCreatedSetNumericOnly addListBox setValues AddMessageMutatesetAppend setDisabled getPropertyplayerSelectedaddRightDefinitoncreateWindowRootRegiongameInfoChanged showPopup fixByteRangeget_paAccountTypeCreateControl selectRegion TeamColorfixStr notifyEventdecodeCaptionaddAccountTypeencodegetClientByNumClear addProperty setNexgenHUDsignalGameInfoUpdateColors TeamGamePlus bindCommand addRegionset_paAccountType PreBeginPlay broadcastMsg wrapLength PostRendergetUserAccountTitleclientInitialized saveSettings removePlayerRemovecreatePanelRootRegion SetTextColorgetAccountTypeTitleLocalizedMessageupdatePlayerInfoaddPlayerToList getClient getPanelrenderMessageBoxBotpack GetStringUWindowSmallButtonSortPaintSetTeam FirstPage Initialize NextPageaddHistoryMsgupdatePreviewGetSelectedIndexDrawTypingPromptCriticalEvent CountShown MD5String ReconnectNexgenPanelContainergetCurrentRights GameEndedsetEncryptionParamsaccountSelectedclientCommandaccountTypeSelectedloadAccountTypesgetUserAccountIndexUser daysInMonth sendMessage baseColors!doTournamentModeReadySignalCheck isSpectatorloadMutatorList playerJoined renderAlert GetTeamNamebanPeriodSelectedgetCurrentDate playerLeftplayerNameChangedgetSelectedAccountNum updateBan formatGUID gameStartedhandleMsgCommandplayerTeamChanged SavedMessageaddPropertyLabelsetPlayerTeamremoveMessageColorTag PanelHeightisMutedreconnectText ChangeNameSetFontAddItem selectPanelannouncePlayerAttrChangemoveSelectedPlayerTogetLogTypeTagcalcStaticChecksum addPlayer RemoteRolecalcDynamicChecksumEvent startGamemakeKeygetClientByIDloadGameTypeListcanEditAccount PlayerPawn virtualTimer checkConfigloadUserAccounts BalanceTeamsMutatorTeamMessage!MutatorBroadcastLocalizedMessage PreventDeathMutatorBroadcastMessage ModifyPlayer isLeapYear addChatMsgMutatorTakeDamagegetPlayerColorsetNexgenMessageHUD ModifyLogin checkLoginsplit2loadMatchSettingsgetBanPeriodType addListCombo ScoreKillGetLookAndFeelTextureTeamSaySetSelectedIndexloadBootControlSettings isBlockedNotifyBeforeLevelChangeKeyDownupdateBootControlseparatePlayers sendPasswordtoggleMatchMode banPlayer PasswordTextCorrodedMessage GetPlayer readDateserializeDateisValidClientID daysInYearSpectatorText bAlwaysTick execCommandTimerNexgenControllerNexgenMainFrameupdateChecksumupdateStaticChecksumupdateDynamicChecksums setFlagTexaddEditControlgetWrapPositionresetEncryptionConfigcanUseAccountType getBanIndexselectionHasAccount isExpiredBan removeBanhudReplacementSelectedloadHUDReplacementListUWindowCheckboxreceivePasswordaddUserAccountgetMutatorIndexweaponSelectedloadIgnoredWeaponList setGameInfo ListClass ServerTravel getIDList getIPListreconnectPlayer isFirstGameSetup pauseGamegetCurrentBanPeriodbanPeriodTypeSelected banSelectedmoveAccountType loadBanListloadAccountTypeInfoSayaddDynamicTextAreaGetServerPortFellunblockPlayer fixIntRange canGetSlot addImageBoxdisconnectClientsetupControlPanelremoveClientHandlerclientCreatedEndGame BlockPlayercheckPreventDamage getItemByIDgetBackgroundColorsendMsggetDisplayTextgetPlayerJoinEventArgsgetBanPeriodDescriptiongetDisplayFontBurnedupdateLoginOption showPanelshowGameReadyToLaunchMessageswitchPreferredPlayergetSmallestTeaminitializeConsoleWindowgetLargestTeamgetLocalizedDateStrclearReadySignalsgetBoolgetDaterenderMessagegetPanelWidth renderPanel isValidLevelignoreWeaponFire firePressedgetClientStategetServerState clientLoginrenderTypingPromtgetShortDayNameaddMsgNexgenControllerPawn getMonthNamegetPlayerNameIndicesaddColorizedMessagegetShortMonthNameCopyToClipboard windowHeight windowWidth clearDatagetDelocalizedDateStr firstTicksetAccountInfo hasRightsdoCompatibilityCheck forceEndGameinitializePopupWindowinitPreferredSwitchersDrawCrossHairgameSpeedChangedinitializeControlPanel parseDatecompareSwitchDesirabilitygetCompactDateStrbShowCountryFlagaddControllerupdateCountryCodescheckConfigUpdateplayerRespawnedgetDisplayColorclearLogBufferaddLogBufferEntry shouldLogPlayReceivedMessagegetPlayerByID respawnedmodifyLoginRejectcheckResidentConfigClientInitialize InputNumberaddRaisedButton RestartGameaddPluginClientConfigPanelProcessKeyEvent!initialConfigReplicationCompletemodifyClientState AdminLoginClientPlaySound ChangeHudChangeCrosshairmodifyServerStatesetPlayerDataisReadyToInitialize isBanned hasUniqueKeyRestartPlayergiveJoinOverrideCodeisValidJoinOverrideCode newClient SuicidedregisterPluginsetServerSettingssetReplacementHUDClasssendPM receivePM initGameInfo Spectator NetPriority ShowWindowupdateAccountType addSubPanel SetRange loadKeyBinds DrawItemcontainsCommandremoveKeybindInsert addKeybindupdatePlayerTitlesdeleteAccountTypeComparedeleteAccount FocusWindow applyConfig CloseUWindow loadBanInfo preloadMap SetEditableupdateAccountselectRandomBootMap addAccount doNexgenBootcheckLogSettingstoggleTeamSwitchregisterServersendPlayerToURLLaunchUWindowtoggleGlobalTeamSwitchaddLogPostNetBeginPlayendLogtoggleGlobalTeamBalance PreRendertoggleLockedTeamsupdateMapPrefixDoubleClickItem beginLogflush deleteBan closeFile openFileNexgenLogin setLevelInfosetupTeamButtonsaddBangetEncryptionParamscheckMatchSettingsloadFavouritessetActiveMutatorList getGameIndex checkBanListserverSelected getAllRightscheckAccountSystemSettingsreceiveMessageupdateMatchSettingscheckBootControlSettingstogglePlayerMuteupdateBanPeriodssetPlayerNamecleanExpiredBans kickPlayercheckExtraServerSettingsshowAdminMessagePawntoggleGlobalMute ItemHeightupdatePlayerListinstallVersion108installVersion107installVersion106 updateConfiginstalltoggleGlobalNameChangesetServerSettingsExt1setServerSettingsExt2 parseBoolpostInitialize SetFrame rebootServerdelIgnoredWeaponsaveIgnoredWeapondelHUDReplacementClass getFlagTexcopyTogetLoginParameterscheckLoginParametersparseCommandStrsaveHUDReplacementClassNexgenHUDWrappertoggleGlobalTournamentModeTick visitServersetLogSettings computeDate DestroyedexecSwitchTeamexecJoinAsSpec SetDamageisValidIPAddressDeathMatchPlusexecJoinAsPlayer isValidKeyexecBalanceTeamsexecStartGameexecPauseGamegetMessageColorUMenu autoFormatcheckEncryptiongetLevelFileNamevalidateFileName getDayName urlEncodecheckGlobalServerSettings getNextLinerfillcountryFlagsPkginternalVersion versionCodeversion DecToHexIIHHGGFF ROTATE_LEFTMD5Move MD5Final MD5Update MD5TransformMD5InitMD5_CTXpNum msgLabelTextsendButtonTextcloseButtonText slotMessagereplyButtonText messageText senderText noReasonTextIpDrv HTTPError periodText reasonText loginText UBrowserHTTPReceivedDataBrowse buttonSpace buttonHeightbuttonPanelHeightbuttonPanelBorderSizeeditControlLabelVOffseteditControlHeightautoCloseControlPanelhasCloseButtonrightNotDefined rightDenied rightGranted BeginPlayPostBeginPlaySpawnNotificationGWAVi PackageNameLogEventString ChangeTeamFbAlwaysRelevantbNetTemporary GetItemName GetIntOptionDisplayMessagesClientGameEndedPBT_Transparent PBT_Beveled PBT_Default LayoutRegionitemIDselectedAccountColor accountColor selectColorSetProgressTimeRegisterDamageMutator getFloatgetIntgetByteSetProgressMessageAttributeEntrySShot ActorClass GetLocalURLClearProgressMessages ipToCountrypluginVersion pluginAuthor pluginNameUMenuRaisedButtonTriggerctrlIDaddPluginConfigPanel bIsSpecial ButtonWidthbIsConsoleMessage csnormalcsdeadcsmuted csprotectedcsidlecslogin ssnormalssmatch sspausedssended ssstaringssready sswaiting ssoffline PanelInfo MessageInfo StartMatch blankColor signalEventGetStaticHugeFontGetStaticSmallestFontBot BorderSizeHRegisterHUDMutatorRegisterMessageMutator BeforePaint HideWindowGetDesiredDimensionsGotoTab HideConsoleSetEditTextColorSetSelectedItem noplayrightChallengeCTFHUD serverfull invalidpassbanned duplicateid illegalloginNSCbUseExternalConfig SetHistory GetValue2CreateRootWindowAddPageUWindowEditControl NexgenUtilNexgenTeamBalancerNexgenSimplePlayerListBoxNexgenSimpleListItemNexgenSimpleListBoxNexgenServerFullDialogNexgenScrollPanelContainerNexgenResidentConfigDialogNexgenRCPUserAccountsNexgenRCPServerSettingsNexgenRCPServerInfo NexgenRCPReplacementHUDSettingsNexgenRCPPrivateMsgNexgenRCPModerateNexgenRCPMiscNexgenSettingsNexgenRCPMatchSetNexgenRCPMatchControlNexgenRCPLogSettings BaseColor NexgenRCPIgnoredWeaponsSettingsNexgenRCPHomeNexgenRCPGameInfoNexgenRCPClientConfigNexgenRCPBootControl LabelHeightNexgenRCPBanControlNexgenRCPAccountTypesNexgenRCPAboutNexgenPrivateMsgDialogNexgenPopupFrameNexgenPlayerDataNexgenPlayerListNexgenPlayerACListItemNexgenPlayerListBoxNexgenPlayerACListBoxNexgenPasswordDialogNexgenNullMessageNexgenNoPlayRightDialogNexgenMainPanelBarMD5HashNexgenAccountUpdatedDialogNexgenPopupDialog NexgenActorNexgenAdminLoginDialogNexgenBannedDialog NexgenClientNexgenClientControllerNexgenClientCoreNexgenClientLoginHandlerNexgenCommandHandler NexgenConfigNexgenConfigCheckerNexgenConfigExtNexgenConfigSysNexgenContentPanelNexgenMainPanelNexgenCorePlugin NexgenPluginNexgenCPKeyBind NexgenPanelNexgenDummyComponentNexgenEditBoxNexgenEditControlNexgenGameInfoNexgenHTTPClient NexgenHUDNexgenTextFile NexgenHUDxASNexgenHUDxCTF NexgenHUDxDMNexgenHUDxDOMNexgenHUDxTDMNexgenIdleKickedDialogNexgenIDUsedDialogNexgenIllegalLoginDialogNexgenImageControlNexgenJustBannedDialog NexgenLangNexgenLogEntryNexgenLogFile ParentWindowAlign bCanEdit bDisabled NotifyWindow serverID bStretchGeneralConfig ServerConfig WhiteTexturebBlink MaxLength NexgenCCRootWin TeamButton LeftOverACbBottombBold LabelTextItems GameTypeList Smallest bHideFaces bHideHUD bHideFragsbHideTeamInfo bHideAmmo bHideStatusbHideAllWeapons Static_A00 LadrStaticmyFlag ControllerTGRIMyFontsbPlayersBalanceTeamsWinEndTime bStartMatch bNetReadyserverControllercontrol separatorstaticChecksumdynamicChecksumsdynamicChecksumModifiers updateCountsCT_GlobalServerSettingsCT_AccountTypesCT_UserAccounts CT_BanListCT_BootControlCT_MatchSettingsCT_ExtraServerSettingsCT_ExclWeaponListCT_HUDReplacementListCT_LogSettings bInstalledlastInstalledVersion serverKey isNexgenBootisAdminRebootencryptionKey codeSchemeconfigEncryptionKeyconfigCodeSchemeglobalServerPasswordglobalAdminPassword enableUplink playerSlots vipSlots adminSlotsspectatorSlots MOTDLineautoUpdateBansremoveExpiredBans waitTimeautoReconnectTime maxIdleTimemaxIdleTimeCPspawnProtectionTimeteamKillDamageProtectionTimeteamKillPushProtectionTimebroadcastTeamKillAttemptsallowTeamSwitchallowTeamBalanceallowNameChangeautoDisableMatchTimespawnProtectExcludeWeaponsrestoreScoreOnTeamSwitchenableNexgenStartControlbroadcastAdminActionsautoRegisterServer logEventslogSystemMessageslogChatMessageslogPrivateMessageslogAdminActions logToConsole logToFilelogPathlogFileExtensionlogFileNameFormatlogFileTimeStampFormatenableBootControlrestartOnLastGame bootGameTypebootMapPrefix bootMutatorsbootMutatorIndices bootOptions bootCommandslastServerURLmatchModeActivatedmatchesToPlay currentMatchserverPasswordspectatorsNeedPasswordmuteSpectatorsDuringMatchenableMatchBootControlmatchAutoLockTeamsmatchAutoPausematchAutoSeparatetagsToSeparateuseNexgenMessageHUDreplacementClassHUDReplacementClass atTypeName atRightsatTitle atPassword paPlayerID paPlayerNamepaAccountTypepaCustomRightspaCustomTitle rightsDefgiveRightToRoot bannedName bannedIPs bannedIDs banReason banPeriodmaxBanIPAddressesmaxBanClientIDs BP_Forever BP_Matches BP_UntilDateserverInfoPanelClassgameInfoPanelClassmatchControlPanelClass gameTypeInfo mutatorInfoactiveGameTypeactiveMutatorIndicesIW_Fire IW_AltFireFirstChildWindow configTypeNextSiblingWindowTextY OwnerWindowbWindowVisible bTopCentric WindowTitleWindowIsVisible remainingactiveGameTypeClassgameTypeClass GetParent gameInfoStr DrawUpBevelmutatorInfoStr ClipTextcb bValidCharDrawStretchedTextureDrawClippedTexture CreateWindownewReplacementRuleSetAcceptsFocus BringToFrontSetSize typeNamerightsGetPlayerOwnerrightID bNotForRootUWindowListBoxItem bConfigOkcCheckUWindowListBox playerIP bNameMatch bIPMatch bIDMatchbIgnoreRDoubleClickcurrIPcurrIDipCountidCountbIgnoreMDoubleClick bExpiredbanPeriodTypebanPeriodArgs UWindowBasecurrBan bBanDeleted bAlwaysOnTop entryNumUWindowWindowUWindowButton accountNumUWindowDialogControl accountTypeUWindowRootWindow clientIDUWindowClientWindow accountName customRights customTitleUWindowComboControlbForRootAdminUWindowFramedWindow banPeriodStrargsUWindowListControl currClass UWindowListUWindowControlFrameUWindowDialogClientWindowcsUWindowDynamicTextAreaUWindowPageControlPagecknbUWindowPageControlcilbUWindowPageWindowbRequireReadyUWindowEditBox updateCount bTeamsLockedbNoTeamSwitchbNoTeamBalance gameStatematchAdminCount bMuteAllbNoNameChangerebootCountDownbTournamentMode numReadynumRequiredReady GS_Waiting GS_Ready GS_Starting GS_Playing GS_EndedIT_GlobalRightsIT_GameSettingsbIsOpenUWindowVScrollbar tempFileNameBestRecordDateWindowConsolebBuffer BestFPHslngtimeStampFormatdefaultLogFileExtensiontempLogFileExtension logFilePath logFileName tempLogFilelogFile TextColor logEntrylogLinebIgnoreLDoubleClick BestPlayerslogType serverHost TotalFlags TotalDeaths bSpecialModebBootSeqFailedbServerReloadedbIsNexgenBootbIsAdminRebootsConf clientList cmdHandlergInfplugins teamBalancerplayerDataList loginHandler logBuffer httpClientnextPlayerNumjoinOverrideCodesoverrideCodeLeaseTimesmaxOverrideCodeLeaseTimejoinOverrideCodeOptionbUTPureEnabledlastTimeDilationbServerTravelDetectedvirtualTimerCounterbFirstTickPassedlastPlayerLeftTimegameStartTime gameEndTimelogTag TotalFrags timerFreqserverPauserNamemaxBootAttempts CMD_PrefixCMD_SwitchTeamCMD_BalanceTeams CMD_Play CMD_SpectateCMD_StartGame CMD_ExitCMD_Disconnect CMD_Open CMD_OpenVote CMD_PauserebootCommandsuicideDamageTypefallDamageTypeburnDamageTypecorrodeDamageType LT_System LT_Event LT_MessageLT_Say LT_TeamSayLT_PrivateMsgLT_AdminActionRT_IllegalLoginParameters TotalGamesRT_DuplicateID NumTeams RT_BannedChallengeDominationHUDRT_InvalidPasswordLocalMessagePlusRT_ServerFull FontInfoRT_NoPlayRightTournamentGameReplicationInfosecondsPerMinutewildcardTokenbUseTeamColor bTournament randomMapbootURL attempts bMapLoaded CountDown shortMapNamebFirst mapCountrandomMapIndexOpacitylvlSummaryObjectStr HUDScale StatusScale WeaponScale hudClassNamehudReplaceClassNamesrcHudClassName tokenIndexUWindowLookAndFeelpluginkclientHandler overrideCodeC_WhitebValid bInvalidC_Black Receiver bRejectedallowSpecReconnect rejectTypepopupWindowClass popupArgsFrame currClientPadding banIndexbBannedNextMessageMutatorhasVIPSlotAccesshasAdminSlotAccess vipCount adminCountvipAdminCountspecialSlotsUsedFavoriteHUDColorpDatNextHUDMutatorCrosshairColor ZoneNameWidthClipX EditBoxWidth bAllowChangebWasForcedChangedLine bAllowSwitchbPreventDamage bResetPlayerAction StatLogFinal bAltFirebFire AssaultHUDMsgTypenewLogHistory TypedStrstr1str2str3str4 bNoBroadcastbSendToAdminsOnlyAmount Checksum SelectedItem PlayerZone TalkTextureSender bIsCommand bCheckedValue2 PlayerIDGameEndedCommentsbSend senderPRIbIsSpecMessagebIsNexgenCommandbIsLegacyCommand MOTDLine3 AdminName infoTypeRemainingTimeattributeNameNewItemPZoneChallengeTeamHUD argumentsPName instigatedByCriticalStringGFXgrad32grad64 playerIcon playerIcon2 serverIcon serverIcon2 offlineIcon offlineIcon2 waitIcon waitIcon2 specIcon specIcon2 shieldIcon shieldIcon2 idleIcon idleIcon2 mutedIcon mutedIcon2 matchIcon matchIcon2lastSetupTime baseFont ChallengeHUD baseHUDColorStartYbaseFontHeight MessagescolEditBoxtextCol solidIcon chatMessages chatMsgCount msgCountfaceImg msgBoxWidthmsgBoxLineHeight msgBoxHeightminPanelWidthbFlashMessages lastResX lastResY lastTeamlastLevelTimeSecondsbShowPlayerLocation iconSizechatMessageLifeTimemessageLifeTimemessageBlinkTimemessageBlinkRatepanelBlinkRateblinkColorDampconnectionAlertDelay secPerMinutematchInfoSwitchTime hDefBarSizealertAnimTimealertAnimDistalertBorderSize newLineTokenC_REDC_BLUEC_GREEN C_YELLOWC_PINKC_CYANC_METAL C_ORANGE SS_Offline bCanDrag SS_WaitingButton SS_ReadybAcceptsFocus SS_Starting PlayerNum SS_Ended WinHeight SS_Paused MutatorName SS_Match FirstMap SS_NormalRestartButton CS_Login MutatorListCS_Idle StartButton CS_ProtectedPages CS_Muted bInitializedCS_Dead WeaponClass CS_Normal LabelWidthbadConnectionTimetimeRemainingStartX LocationName HUDMutatorcxcy animIndex hBarSize textWidth maxTextWidth textHeight lineCountpri1pri2 playerColor messageColorbIsSpecSayMsgspecPRITeamNumfirstPlayerNamesecondPlayerName firstIndex secondIndexfirstPlayerColorsecondPlayerColor msgPart1 msgPart2 msgPart3 msgColor tempIndextempPlayerColorSourceindex1index2tmpPRI nameIndex tmpIndex PlayerOwnercol1text1col2text2col3text3col4text4col5StrKeyNum bUpdateBaseClipY serverState clientStateYPos msgOffsetXPos msgIndex msgWidth msgHeight blinkFactorblinkIntensity bPollingpInf stateInfo stateTypeConsoleWindow protectTimebComplexStringseparatorWidthVictim iconHeightNextDamageMutator colorNum timer_tick nextClientgcscloginHandlerChecksum bNetLogin bNetWaitloginComplete ipAddress bHasAccount loginOptionsloginTimerFreq waitTimeOutcountry bSpectator bFirePressedbadConnectionSincebBadConnectionDetectedbMutedteamSwitchOverrideTimenameChangeOverrideTimelastRespawnTimelastSwitchTimespawnProtectionTimeXtkDmgProtectionTimeXtkDmgProtectionTimetkPushProtectionTimeXtkPushProtectionTimebScreenShotTakenbReconnecting originalHUDnewHUDbEncryptionParamsSet idleTime idleTimeCPidleTimeRemainingbUsingNexgenMessageHUDscoreBeforeTeamSwitchbIsReadyToPlay clientCtrlnscHUD popupWindownextDynamicUpdateCountnextDynamicChecksumbWaitingForNewConfiggameInfoUpdateSSTR_ClientKeySSTR_ClientIDSSTR_ServerPasswordSSTR_OverrideClassSSTR_UseNexgenHUDSSTR_FlashMessagesSSTR_ShowPlayerLocationSSTR_PlayPMSoundSSTR_AutoSSNormalGameSSTR_AutoSSMatchSSTR_RunCount R_MayPlay R_VIPAccessR_AdminAccess R_NeedsNoPW R_CanBeIdle R_MatchAdmin R_ModerateR_BanOperatorR_AccountManagerR_ServerAdmin R_MatchSetR_BanAccountsR_HiddenAdminRCN_ReconnectOnlyRCN_ReconnectAsPlayerRCN_ReconnectAsSpecreconnectCommanddisconnectCommand exitCommand startCommandspectatorClassPE_PlayerJoinedPE_PlayerLeftPE_AttributeChanged PA_ClientID PA_IPAddressPA_Name PA_TitlePA_Team PA_CountrymaxIdleRadiusidleCountDelayidleTimeWarningmaxOverrideTimecancelSpawnProtectDelaynormalModeTimerFreqautoScreenShotDelayautoSSMinGameTimewelcomeMsgCountmaxClientCtrlInitWaitTimebClientControllersReadylastIdleTimeRemainingTextbIgnore bIgnoreFirebIgnoreAltFirecurrWeaponClassexcludedModesPortal Palette1 runCountValuebEnableKey cleanMsg NextMutator BaseMutator Palette3 rightsStr bHasRights MapPrefixAdminPasswordwWidthwHeightwTopwLeftpos bGameEnded popupClassdistNextSwitchCountdown optionNameNextURL PawnListcontrollerClasscreatorEngineVersion controllerIDNetMode Screenshot updateNumSummaryPauserIdealPlayerCountSecondMinuteUMenuFramedWindow panelClass containerHour DayOfWeekDayUMenuLabelControlbCanModifyHUDStatePanelMonthYear TimeSecondsOptionalObjectblockedPlayers bBlockAllopenURLCommand restartURL rebootDelay RelatedPRI_1 bBlockedbBeepOwnershortServerNameMOTD1MOTD2MOTD3MOTD4 specSlotsbEnableUplink Password bWindowed targetCtrl senderTitle nextPawn senderIDbForcedpmPanel FilenameaccountTypeNumReason newTitle TimerRateuserAccountsChangedremovedAccountTypemyHUD oldPosition newPositionmovedAccountTypeTargetremovedAccountremovedAccountTitle InstigatorHUDTypebAlreadyHasAccount accountTitleBasebGameIsPausedRegionGameNextbSpecPRIfURLContextUMenuMapListFrameCWPlayerLocationbValidPassword bRootAdminbFound deletedBanbWaitingPlayeripListidList bIsSpectator bLoadLastMap mutators extraOptions indexStrHasFlag teamTagsScore targetPlayer pwToSendpwReceivedMsgOldName PlayerName teamTag0 teamTag1 teamTag2 teamTag3 PRIArray MOTDLine4 MOTDLine2 MOTDLine1 AdminEmailbanPeriodDescbHasExistingBanEntry NumPlayersCommandbBadConnectionAlert bTeamGame GameClassSecondsItem currIndexMignorePrimaryFireignoreAltFireweaponConfigStrL OldLocationoriginalClassreplacementConfigStr bSelectedaPawnopenMapVoteCommand MutateStringbInvalidCommand failMessagebTyping bAllowedDamage numSpecs HitLocationIndex Momentum actualDamageN SpawnClassKillerP RelatedPRI_2MsgURL bNetOwner NewValuemaxLenHitLocintVar lowerBound upperBound EventTypebyteVar CHSpectator WinWidthTransA3OldTeam bShowScoresOptionWinTop PA_MutedPA_NoTeamSwitchResult bCancelledipInfoDelta oldClientdateFormatStrdefaultLogFileNameFormatdefaultLogFileTimeStampFormatlongDateTimeFormatstartingControllerMsgnoDedicatedServerMsgcompatibilityModeMsgautoInstallMsgautoUpdateMsginvalidConfigMsgattrServerIDMsgnexgenBootMsgnexgenMapLoadFailMsgnexgenBootFailMsgexecCommandMsgbootLevelSwitchMsgnexgenActiveMsglogFileCreateFailedlogFileCreatedloadingPluginMsginitFailedMsg regFailedMsgnoHUDReplacementClassMsgloginRequestMsgattrClientIPMsgattrClientIDMsgattrPasswordMsgillegalLoginParametersMsgduplicateIDMsg bannedMsginvalidPassMsgserverCapacityMsgnoPlayRightMsgloginAcceptedMsgloginRejectedMsg logFileTitlelogFileEngineVersionlogFileNexgenVersionlogFileServerIDlogFileServerNamelogFileServerPortlogFileGameClasslogFileLevelNamelogFileLevelTitle logFileStart logFileClosegameStartedMsg gameEndedMsgplayerJoinMsgplayerLeaveMsgplayerNameChangeMsgplayerLeaveLogMsgteamSwitchFailMsgteamsLockedMsgnameChangeFailMsgnameChangeDisabledinvalidCommandMsgcommandFailedMsginternalErrorMsgteamSwitchFailedMsgspecTeamSwitchMsgteamSwitchDisabledMsgplayerTeamSwitchDisabledMsginvalidTeamMsg sameTeamMsgnoSpecsAllowedMsgnoMoreSpecSlotsMsgnoPlayingRightsMsgnoMorePlayerSlotsMsgteamBalanceFailedMsgnotATeamGameMsgteamBalanceDisabledMsgteamsAlreadyBalancedMsg balanceMsg launchMsgplayerReadyMsg forcedEndMsgrootAdminTitle specTitledeathPreventedMsgmutedReminderMsgaccountTypeNameStrteamKillAttemptMsghttpClientErrorMsgcontrollerSystemLogTag eventLogTagmessageLogTagchatMessageLogTagteamSayMessageLogTagprivateMessageLogTagadminActionLogTagallowedToPlayRightDescvipSlotAccessRightDescadminSlotAccessRightDescneedsNoPWRightDesccanBeIdleRightDescmatchAdminRightDescmatchSetRightDescmoderatorRightDescbanOpRightDescaccountMngrRightDescserverAdminRightDesccanBanAccountsRightDeschiddenAdminRightDesclaunchGameMsgadminLaunchGameMsgtournamentLaunchGameMsgserverCrashedClientMsgbootFailedClientMsgserverAdminRebootClientMsg welcomeMsgsettingsSavedMsgreceivedPMMsgreceivedPWMsgpasswordSendMsgnoBanAccountRightMsgadminTeamSwitchMsgadminPauseGameMsgadminResumeGameMsgadminRestartGameMsgadminStopGameMsg adminPlayerTeamSwitchDisableMsgadminPlayerTeamSwitchEnableMsgadminReconnectAsPlayerMsgadminReconnectAsSpecMsgadminSendToURLMsgadminDisableTeamSwitchMsgadminEnableTeamSwitchMsgadminDisableTeamBalanceMsgadminEnableTeamBalanceMsgadminLockTeamsMsgadminUnlockTeamsMsgadminAddBanMsgadminDeleteBanMsgadminEnableMatchModeMsgadminDisableMatchModeMsgadminMutePlayerMsgadminUnmutePlayerMsgadminSetNameMsgadminKickPlayerMsgadminBanPlayerMsgadminMuteAllMsgadminUnmuteAllMsgadminEnableNameChangeMsgadminDisableNameChangeMsgadminRebootServerMsgadminEnableTournamentModeMsgadminDisableTournamentModeMsgadminAddAccountTypeadminUpdateAccountTypeadminRemoveAccountTypeadminMoveAccountTypeadminRemoveAccountadminUpdateAccountadminAddAccountadminUpdateBanMsgadminUpdateBootControladminSeparateByTagadminUpdateMatchSettingsadminUpdateIgnoredWeaponListadminUpdateHUDReplacementList adminUpdateGlobalServerSettingsadminUpdateMiscNexgenSettingsadminUpdateLogServerSettingsinvalidPasswordMsgadminLoginMsgautoReconnectAlertreconnectingAlert rebootAlert idleAlert waitingStatewaitingStateUnknownTime readyStatereadySignalWaitStatestartingState onlineState offlineStateofflineStateRCN endedState pausedState loginState idleState mutedStateprotectedState deadState matchState clientTabTxt homeTabTxtsettingsTabTxtprivateMessageTabTxt gameTabTxtplayersTabTxtmoderatorTabTxtmatchControlTabTxtmatchSetupTabTxt serverTabTxt infoTabTxtbanControlTabTxtaccountsTabTxtaccountTypesTabTxtbasicSettingsTabTxtnexgenSettingsTabTxt bootTabTxtpluginsTabTxt aboutTabTxt welcomeTxtrightsOverviewTxtrightNotDefinedTxtteamBalanceTxt redTeamTxt blueTeamTxt greenTeamTxt goldTeamTxtplayTxt spectateTxt reconnectTxtdisconnectTxtexitTxt mapVoteTxt startTxt loginTxtserverNameTxtshortServerNameTxt MOTDLineTxt adminNameTxtadminEmailTxtserverPasswordTxtadminPasswordTxtplayerSlotsTxt vipSlotsTxtadminSlotsTxt specSlotsTxt advertiseTxt resetTxtsaveTxt keyBindsTxtbalanceBindTxtswitchRedBindTxtswitchBlueBindTxtswitchGreenBindTxtswitchGoldBindTxtsuicideBindTxtopenMapVoteBindTxtopenCPBindTxtpauseGameBindTxtUISettingsTxtenableMsgHUDTxtmsgFlashEffectTxtshowPlayerLocationTxt pmSoundTxtmiscSettingsTxtautoSSNormalGameTxtautoSSMatchTxtplayerListTxtblockedListTxtblockToggleTxtblockAllPMsTxt messageTxtsendNormalPMTxtsendWindowedPMTxt historyTxt blockMsg unblockMsg sendMsgTxtreceivedMsgTxtaccountNameTxtaccountTitleTxt passwordTxtaddAccountTypeTxtdelAccountTypeTxt moveUpTxt moveDownTxt userNameTxtaccountTypeTxt userTitleTxt onlineTxt offlineTxt updateTxtaddTxt deleteTxtcustomAccountTxtswitchToTeamTxt sendToURLTxtreconnectAsPlayerTxtreconnectAsSpecTxtdisableTeamSwitchTxt pauseGameTxt endGameTxtrestartGameTxtallowTeamSwitchTxtallowTeamBalanceTxt lockTeamsTxttournamentModeTxtplayerNameTxt banReasonTxt banPeriodTxtbanForeverTxtbanMatchesTxt banDaysTxtbanUntilDateTxtipAddressesTxt clientIDsTxt addBanTxt updateBanTxt delBanTxt removeTxtenableBootCtrlTxtrestartOnLastGameTxtinclMutatorsTxtexclMutatorsTxtbootCmdLineTxt gameTypeTxt mapPrefixTxtextraCmdLineOptTxtpreSwitchCommandsTxt rebootTxtadministratorTxtcontactAddrTxtmsgOfTheDayTxt serverIDTxtstatisticsTxttotalGamesTxttotalFragsTxttotalDeathsTxttotalFlagsTxtbestPlayersTxtFPHTxt recordSetTxt timeLimitTxtscoreLimitTxtteamScoreLimitTxt gameSpeedTxtteamSwitchEnabledTxtteamBalanceEnabledTxtteamsLockedTxtnameChangeAllowedTxt mutatorsTxt levelTxtfileTxt titleTxt authorTxtidealPlayerCountTxtmatchSettingsTxtmatchNumOfGamesTxtmatchCurrGameNumTxtmatchSpecNoPassTxtmatchMuteSpecsTxtmatchBootControlTxtmatchAutoLockTeamsTxtmatchAutoPauseTxtmatchSeparateByTagTxtmatchAutoTagSeparateTxtmatchDoSeparateTxtstartMatchTxt stopMatchTxtsendPasswordTxtallPlayersTxt clientIDTxt ipAddressTxtmuteToggleTxtsetPlayerNameTxtkickPlayerTxt banPlayerTxt muteAllTxtallowNameChangeTxtshowAdminMessageTxtcopyTxtnexgenMiscSettingsPanelTitleautoUpdateBansTxtautoDelExpiredBansTxtannounceTeamKillsTxtrestoreScoreOnTeamSwitchTxtenableNexgenStartControlTxtbroadcastAdminActionsTxtenableNexgenMessageHUDTxtdefaultAllowTeamSwitchTxtdefaultAllowTeamBalanceTxtdefaultAllowNameChangeTxtautoRegisterServerTxtgameWaitTimeTxtgameStartDelayTxtautoReconnectTimeTxtmaxIdleTimeTxtmaxIdleTimeCPTxtspawnProtectTimeTxtteamKillDmgProtectTxtteamKillPushProtectTxtautoDisableMatchTimeTxtignoredWeaponsTxtweaponClassTxtignorePrimaryFireTxtignoreAltFireTxthudReplaceClassesTxtoriginalHUDClassTxtreplacementHUDClassTxtaddNewItemTxtlogSettingsPanelTitlelogToConsoleTxt logToFileTxt logEventsTxtlogFilePathTxtlogFileExtensionTxtlogFileNameFormatTxtlogTimeStampFormatTxtlogMessagesTxtlogChatMessagesTxtlogPrivateMessagesTxtlogAdminActionsTxt TimeStampOther DeltaTimedateStr bSaveDefaultMapName PanelWidth strValueNewName PlayerCount PlayerListTempPlayerName nextLogEntryMinutes attributesGetPlayerNetworkAddressGRINewTeamGoalTeamScore TimeLimit maxTeamCount teamSizeminPlayersPerTeam targetTeampreferredSwitchersprefSwitchTeamOffsetsswitchedCountbHighDetailModelargestMaxSpectators FragLimit nextOffset tempClientbSortedbStopCountDown preferredPickupsclient1client2 TimeDilation lastChecksavedMessagessavedMsgCountbHandleByParentmsgStrcanvcons GameSpeed bWasTyping noCountry Palette7 LeftMessageoffsetXflagTexbackgroundColorEnteredMessage MaxPlayers MutatorClass Lifetime ServerName ShortNameIcon FileFlush Palette11 Palette39 CloseLog Palette19OpenLog mainPaneldialog dialogClass Palette23regions regionCount currRegionEPanelBackType Palette27Dec Palette31 panelBGType parentCPminRegionSize AL_CenterAL_LeftAL_Top AL_Right AL_BottomdefaultComponentDistdefaultButtonHeightdefaultLabelHeightdefaultEditBoxHeightdefaultCheckBoxHeightdefaultRaisedButtonHeightdefaultlistComboHeight SmallFontSetPosHealthAdmin Location bIsPlayer bPercent splitPointregion1heightregion2height region1top region2top LocalMessage region1width region2width region1left region2leftGetNextIntDesctotalRegionHeight regionHeight carryOver currHeightcurrTop Palette35totalRegionWidth regionWidth currWidth currLeftTypeStyle GameNameTeam DrawColor checkBox Palette43 raisedButton Palette45 imageBoxSizebgType contentPanelbQuickKeyEnable listCombo MaxTeams DamageType listBoxClasslistBoxbLeaveOnscreenPanel bShowConsole playerItemtempA bindButtonD selectedBindbindSeparatorgetKeyNameCommandgetKeyBindCommandsetKeyBindCommandX keyActionC commands PropValue actionStr PropNameZ panelNameY identifier newPanel parentPanel subPanelsW barHeight scrollBarpanels numPanelsclientAreaDesiredHeightnextPanelOffsetpanelDistanceborderDistancedefaultPanelHeightbNeedScrollBardesiredPanelHeightlogonumAccountTypesrpciaccountTypeListaddAccountTypeButtondeleteAccountTypeButton moveUpButtonmoveDownButtonaccountNameInpaccountTitleInpaccountPasswordInprightEnableInp resetButton saveButton rightDefLabelRootaccountRightsKeyNamejWrapPosbanList addBanButtonupdateBanButtondeleteBanButtonplayerNameInp banReasonInp banPeriodInpmatchCountInpdateInp addIPButton delIPButton addIDButton delIDButton ipAddressInp clientIDInp ScriptTextnumBansSBbanArgsR Selected ReturnValueLenselectedIndexinclMutatorListexclMutatorList rebootButton mapPrefixInpextraOptionsInp commandsInpenableBootControlInprestartOnLastGameInp previewBoxDynamicLoadObjectoldItem mutatorIndex TotalPlayersbootCmd GameTypeenableNexgenHUDInpuseMsgFlashEffectInpshowPlayerLocationInpplayPMSoundInpautoSSNormalGameInpautoSSMatchInptimeLimitLabelfragLimitLabelteamScoreLimitLabelgameSpeedLabelenableTeamSwitchInpenableTeamBalanceInpteamsLockedInpallowNameChangeInp fileLabel titleLabel authorLabel playersLabelFavoriteCountMutator levelFileteamBalanceButtonplaySpecButtonreconnectButtondisconnectButton exitButtonmapVoteButton loginButtonserverTitleLabel MainWindow CloseButton PageControl rightPanelWeaponignoredWeaponListweapSaveButtonweapRemButtonignorePrimaryFireInpignoreAltFireInpweaponClassInp LevelInfo GameInfologToConsoleInp logEventsInplogMessagesInplogChatMessagesInplogPrivateMessagesInplogAdminActionsInp logToFileInplogFilePathInplogFileExtensionInplogFileNameFormatInplogTimeStampFormatInp ZoneInfoHUD teamButtons pauseButton endButtonsendToURLButtonreconnectAsPlayerButtonreconnectAsSpecButtondisableTeamSwitchButtonurlInpallowTeamSwitchInpallowTeamBalanceInp lockTeamsInptournamentModeInpfavouritesListdefaultButtonColorPlayerReplicationInfoStatLog favsCountfavStr serverIP StatLogFilestartStopButtontagInp numGamesInp currGameInp passwordInpspecNeedNoPWInp muteSpecsInp autoLockInp autoPauseInpautoSeperateInpseparateButtonsendPasswordButtonInfoautoUpdateBansInpautoDelExpiredBansInpbroadcastAdminActionsInpannounceTeamKillsInpenableNexgenMessageHUDInpenableNexgenStartControlInprestoreScoreOnTeamSwitchInpdefaultAllowTeamSwitchInpdefaultAllowTeamBalanceInpdefaultAllowNameChangeInpautoRegisterServerInpgameWaitTimeInpgameStartDelayInpautoReconnectTimeInpmaxIdleTimeInpmaxIdleTimeCPInpspawnProtectTimeInpteamKillDmgProtectInpteamKillPushProtectInpautoDisableMatchTimeInpipAddressLabelclientIDLabelcopyIPAddressButtoncopyClientIDButtonmuteToggleButtonsetNameButton kickButton banButtonshowMsgButtonnumMatchesInp numDaysInp messageInpbanForeverInpbanMatchesInp banDaysInp muteAllInpReplicationInfoblockedPlayerListblockToggleButtonsendNormalButtonsendWindowedButtonmsgInp blockAllInpGameReplicationInfo LevelSummaryselectedPlayer locationidhudReplacementListhudReplSaveButtonhudReplRemButtonoriginalHUDClassInpreplacementHUDClassInp SpawnNotify ViewportCanvasserverNameInpshortServerNameInpMOTDInp adminNameInpadminEmailInpserverPasswordInpadminPasswordInpplayerSlotsInp vipSlotsInpadminSlotsInp specSlotsInp doUplinkInp accountList updateButton deleteButtoninvalidAccountTypecustomAccountTypedefaultAccountTypeFont accountItem ServerActorsLevelActorbItemSelectedBitmap rightStrbClientIsServerAdminPlayerClientbDoneWindowminWrapRetain wrapChars bSuccessnextButtonPosPart FavoritesCode ServerPortUBrowserHTTPClientUBrowserFavoritesFactcw newButtonList fontTypewrapLentextStrlineStr newLinePoswrapStrCount maxCharsHeightAuthor DescriptionOptionspasswordInputImage reasonLabel periodLabel DefaultValueData NewValue2periodspectatorButton allowSpecs msgLabel senderLabel replyButton LookAndFeel bByParentEditBoxTextColorfirstLineWrapLenlineNum lineEntry slotLabel WndClass sendButtonPageVAlignHAlign borderDistseparatorDistcomponentDisteditCtrlHeight sayCommandbDownpTitle pIPAddress pClientID pCountrypTeam bFlagTexSet specTeamSoundTextureTitleConsolepTitleApTitleBpNameApNameB displayTextFontsbufferCmddigestHexbRightbMovingBufblock ClientHeight inputLenpartlentmpbuf ClientWidthbitspadLenstrbits ClientAreasrc srcindex bufindex EditControlTailHead TextAreabUnique TextAlignRole clientKeyStaticbLoginParametersValidbSelectOnFocus bAllSelected NotifyOwner CaretOffset keyChars keyFormatnexgenCommand assignment escapeTokenillegalFileNameCharsClassoldStrnewStr subStrIndexstrLeft formattedStrParentPackage minLengthfillStrOutputInputcmdStrcmdName argCountcclc recStartrecEndbRecStrConstpropStrformattedValueSwitchpropDefaultValuesaved StartTime daysToCountdaysRemaining TextBufferObjectEnum FunctioncurrentSectionsectioncharStateVector formatIndex keyIndexStructName UnrealShare StrPropertyStructProperty rawGUIDStrClassProperty NamePropertyhashObjectPropertyFloatPropertylvl BoolProperty IntProperty bInvalidMap BytePropertynsbMaxOutputLengthReachedCh indexCRLFindexCRindexLFtext5QGx>l U3::$::$w9U[T>{:>&{V*s3T>*s3*s3{V;B*s3*s3{V;B.e> Y 3B> Y 3B}"#}"#.e> Y{#U> Y}"#{.e*s3T>*s3T>{{{*s3T>T>T>T>T>> Y> Y> Y> Y> Y*s*s*s/T2/T2*s3Z6Z6Z6Z6/T2/T2/T2/T2o .'l.'l.'l*s*s/T2o /T2o /T2o *s*s3T>Z6Z6/T2o /T2o /T2o Z6Z6Z6Z6Z6> YR@G/T2/T2/T2/T2 3B.e{V.e{V 3B> YR@G> YR@GI&/> Y> Y5I> Y5I.e> Y5I5I5Ia ,O> Y5I> YMT>MMM{V> Y{#U> Y> Y.eo ${{> Y> Y> Y> YX' 3B 3B> Y> Y> Y> Y> Y> Y{{> Y> Y*s> Y.e> Y{#U> Y{{> Y 3B{T>{{> YMM> Y.e> Y{#U.e& es}$@{Fz8q 7 ::$nYQZ=$:e 3B 3B 3B 3B 3B 3B 3Bq3A"q3A".e{V.e{V 3B 3B 3B 3B'n 6'n 6'n 6'n 6'n 6'n 6'n 6'n 6 3BUު.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V.e{V 3B 3BԝX& jFm7hJ .e=$:e{V9999999{{999H,{V{VH,=$:e'n 6{Vttttt'n 6-%nԝX 3B99999{99{9999H, 3Bv v H,=$:eԝXttttEl{#UH,=$:eԝXtԝX{#U{#U{#U9{{99999{Vttt{#UH,=$:eԝX99{Vttt{#UH,=$:eH,b{V{V{{{H,{V{{{H,{9{V{999{V9{V{{{{{{{99{{{{{{{H,999˔> Y{#U99˔> Y{#U9ˋ{{{{{99˔> Y9ˋ 3BH,999999ˉ 3B9ˉ 3B 3B999ˉ 3B 3B999999EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1{V{V{V{V{V{V{Vb{{{{{{{-%n-%n{{{{{}99˔> Y{#U99˔> Y{#U9˔> Y9999˔> Y{#U9˔> Y9˔> Y99{VH,=$:e99{V'n 6ttt{#Ut{#U99{Vt{#Ut{#UtH,=$:e999˔> Y{#U99˔> Y{#U9999{{V{{V9{V99˔> Y{#U9H,99{V999{{V999˔> Y{#UH,9˔> Y{#U{V99˔> Y99{V9S^S99{H,{V99{V{V9{{{9ˋ{{{{9H,{{9{V9{V9{V{{99ˋ}"#99˔> Y{#U999˔> Y{#U99{{9999{H,{V999˔> Y{{{-%n{{{{9H,H,=$:e999999˔> Y9S^S9S^SS^S9S^S99999999999999999{V999ˉ 3B99{V{V9{V{V9{V{V 3B9{V{Vo ${V{V{V999{V9{V999{VH,H,9{V{V99{V9ˋ{H,=$:e99999999ˉ 3BH,{V{V{{{{{}"#{{{{{-%n'n 6'n 6'n 6'n 6'n 6'n 6'n 6'n 6 3B 3B{V{V 3B{V{V{V{V{V{V{V 3B{V{V 3B{V{V{V{V{V 3B-%n-%nW]8&iy ee*pDG;L ]{VU[ډ 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B& kFj*u 4L4L4Ll5ezZԌzZl5e_4_4_44L4L4LL ¦L ¦|.Xڌ|.Xڌ|.X[[[[᱘᱘᱘7XÐ7X ?Bv@aG  3BxWUު.e.e.e.e.e.e.e.e{V 3B 3B y$q=?x"lw"[h] Nexgen108v]CountryFlags2D!  PAXBB  EyEy&. EyE EyE v"GFf8~ 3( ::${YQZ& %[A`-C  yJ~ EyE EyE EyE EyExxxxxxxxxxo  EyE C$PA JCJB^ ^y&.^^^^^^^^^^^^^^^^^^ 3B F" TIG|6n ::$::$mOLST>99ˉ 3B.e{V.e.e.e.e.e.e.e.e.e.e.e.e.e.e9.e{V.e{V.e99˔> Y99.e{.e{-%n.e{.e{.e.e{.e{.e{.e.e.e-%n.e{.e.e{.e{.e{V.e{V99.e 3B 3B.e.e.e.e 3B 3B.e.e.e.e{V99.e.e.e.e.e.e.e.e.e.e{V99.e 3B.e.e.e 3B.e.e.e.e.e.e.e{V99.e.e.e.e.e.e.e.e.e.e{V99.e{V.e{99.e.e.e.e.e.e.e.e.e.e.e.e9.e{V.e{V99.e.e.e.e.e.e.e.e.e.e.e.e.e.e99.e{.e{.e.e{.e{.e{V.e{V99.e{.e{.e.e{.e{.e{V.e{V99ˋtt> Y> Y> Yt9999.e9999.e{V.e.e 3B 3B.e{V99˔> Y.e{V9.e99.e.e.e9.e99.e9.e9.e.e.e.e.e99.e9999.e{V99˔> Y.e{V9ˉ 3B99.e99.e{V99.e999.e{V9.e{V999.e.e.e.e.e{.e{.e{.e.e{.e.e.e{.e.e.e.e{V.e{V99.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e9.e{V.e{V9M99M999M99{V9{V99.e.e.e9OLS.e99OLS99.e{V99ˋ.e99.e}"#9.e9˔> Y{#U99.e{V99.e.e9 3B9.e.e.e.e.e 3B9 3B9.e.e.e.e.e.e.e.e.e9.e{V.e{V99ˉ 3B.e.e.e.e.e.e.e.e.e.e.e{V99ˉ 3B.e.e.e.e.e.e.e.e.e.e.e{V99.e.e.e.e.e.e.e.e{V.e.e.e.e.e.e.e.e99.e.e{V.e99.e.e{V9.e9˔> Y99˔> Y.e.e.e9.e{V99.e{.e{.e.e{.e{.e{V.e{V99.e{.e{.e.e{.e{.e{V.e{V99.e{.e{.e.e{.e{.e{V.e{V 3B.e999.e{V9.e99999.e99.e{V9.e{V9.e99999.e{V9.e{V9.e99ˋ'n 6}"#99.e{V9.e{V99ˋ.e{V99.e{.e{.e.e{V99.e{.e{9.e{V.e{V99ˉ 3B.e.e 3B.e.e.e.e99˔> Y.e.e.e.e.e.e.e.e.e.e{V99.e.e 3B.e.e 3B.e.e99˔> Y.e 3B.e.e.e.e.e.e.e.e.e{V99.e.e.e.e99˔> Y.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e{V99.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e{V99.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e{V.e9.e99.e{V.e.e99.e9999.e 3B.e.e 3B.e.e.e.e.e.e{V99.e.e.e.e.e{V.e{V.e 3B.e.e 3B.e.e.e.e.e.e{V9˵M99˔> Y9*s3⥉i'ri'r9ˏ{#U99{V9{V{#U999.e.e.e.e{.e{999999999OLS99˔> Y99.e99.e99.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e'n 6'n 6'n 6'n 6'n 6'n 6'n 6'n 6.e.e9.e{V.e{V9*s39{V9*s39{V99*s39{V9*s39{V99*s39{V9999*s39{V9999*s39{V9999*s39{V9*s39{V99*s39{V9999*s39{V999*s39{V999*s39{V9*s39{V9*s39{V9*s39{V9*s39*s39*s39*s39*s39{V9*s39{V& K = ClientCore{!vCH1z 34L'; 롉 3B9^ 3B9^ 3B9^^ 3B9^'; ^^ 3B9^ 3B9^ 3B9^ 3B9^ 3B9^ 3B9 HFc-} [[tT9 CU K/U K/U K/Ԍ o@@f2 WjHGCG-` '; 롙'; ^y&.'; ^^^^^^^^^^K4^^^^o ~xx^xx Q *y*ȖR*RRRȖRdddRC$PATCNB_ )1ז^)1ז)1ז)1ז)1ז `D{-i2*s0 3Bl B$ DA$C@ @\+C@`w*j @zAv ;^De2v  3;B> YR@G/T2o .'l.'l.'l> YR@G/T2 8]mainx r r3LwED@@ f:>&=$:e{#U{#U{#U{#U{#Uxxxxxxxxxxxxxxxxxxxxxx99{V999{V9{V9999999{V9{V999{9{V9˔> Y9{V99999T>9T>9˔> Y99999{V9{V9{V9{9{9{99{V9{V9{V9{9{9{9{9{V9{V9{9{9{V9{9{9{V9{V9{9{9{9{V9{V99˔> Y'n 6999{V9{V9˔> Y'n 69{V9{V999T>9T>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxZ!Z!xxxxZ!Z!9˔> YR@GI&/9˔> YR@GI&/9˔> YR@GI&/xxx9˔> Y{#Ux> Y!flUxxx9˔> Y{#U9˔> Y{#U9˔> Y{#U9˔> Y{#U9˔> Y{#Uxx9˔> Y{#Ux9˔> Y{#U{#U{#U'n 6'n 6'n 6{#U{#U{#U{#U'n 6'n 6'n 6{#U{#U{#U{#U{#U{#U{#U{#U{#U{#U{#U{#U 3B 3B{#U{#U9˔> Y'n 6'n 6'n 6{#U'n 6{#U'n 6{#U'n 6{#U{#U'n 6'n 6{#U{#U{#U{#U{#U{#U{#U{#U{#U{#U{#UFz{#U{#U1{#U{#U{#U{#Uxx> Y!flUxxxxxxxxxxxxxxxxxxxxx9ˍxxxxxxxxxxxxxxxx=$:e99999{99{V9{V9{V9{9{9{V9{V99999{V9{V9˵M99˵M9& a *R*RRRRR^*ZZ^ZZ^ZZ^Z^^2^2^^ 2^ soC{)F2;B7`?{?{?{?{7`?{?{?{?{7`?{?{?{?{7`?{?{?{?{7`?{;B7`?{7`?{;B?{;B7`?{;B7`?{;B?{ 'BAR-A <`k'; ^ q @@(@@q@`R@DC@h Cn~> YR@G/T2o .'l.'l.'l> YR@G/T2᱘᱘tt᱘᱘᱘᱘᱘7XÔ> YR@G/T2o .'l.'l.'l ^e"Pf $AW $A\$A[$@@Z$@Y$AX$AN $@BW$@\0Qo6QP4wE *E QP oDd:M EP]1U[EP]1& Z | @FCN.x H,U[.e.e.e{V.e{V.e.e.e{V.e{V.e.e{V.e{V.e.e.e& N Tn)oRHIb ZMGz=m  ::$T>U[& s}$?m[wTNh(m=o=?;Q a\s ;-{%WClose-z%^.w^*V ^wV *V a/!iV 4V V  'UCO-a ['; ^)1ז)1זo o  x*w*ȖdRS)C @U @@p@j  @@rc @@l @@5-`8*./"0"+","1*"l"CkQ`9o]j<X<a @G}{i @@j# J uK zY@y4ErO@K~bP h@tg@efD@eC Xu|OIuu#c b#a#`#^#uYu_#c   i&EV@@w @Z]e6]_4r]W :_,4 MX@UMCm9]  S^SU[ډ 3B 3B 3B 3B& sHU p#\~ &N\{#[ l#k#j#h#\Y\i#\[   a @@Vy}Iyx#` g#f#e#c#yYyd#`   CCC.\ 2 Z60 3BCnCnCnCnCnʼn 3Bl B$CA$HCHs{Isp#r \#[#Z#X#sYsY#r   d!N Y B @bkuBy @aXT @@W @@$I'h @@AV)g_4h&yI  @@O G"u @@cG@Q6Tg~  @N@e @@gO @@pn'A}A @I-sl~)PEn @\@iTj Io7RDf UުxW rSC@\ E@@K"@\ @ytx} @@L @@EHCrq03, W f g dQr @~@jp4X @U  ]RxnR^)f @@fdE|Pp @_D }KM @E|BgRHmU aC@@ @@FZl@rN}s @x+RV Dxw @Y*uIpp@\@h z @u)rSfh~ @Q)Yd  L*BB @m(.ZM@g n B{u fU{D`W_  PMi @l"jY }g@N @tw @|Sz@qcC @Z @@{ @W 'kH5W5s5H J@Ms@@kg3v \x@E @N zw@@l @B@c< @]@J@@D@Ledv g @ s@p@[L XjhS C[zWA @P$@e^^ w@Ft#N@Uvwg@`BBB;K Zi'r9{V9{V{#U<`k<`k<`k<`kt9999{9{9^99999{V9{V^tOLS^tt9ˋ9ˋzZOLS|.Xڐ7X<`k<`kOLS^9{V9{V^<`k<`k<`kOLS^9{V9{V^<`k<`k<`ky&.<`k<`k<`ky&.<`k<`k<`kOLS^9{V9{V^<`k<`k<`kOLS^9{V9{V^<`k9OLS 3B99<`k<`k99ˉOLS4L4L4L4L9{V4L4L9{V4L4L4L4L9{V4L9{V4L4L9{V4L4L4L4L4L9{V4L9{V4L4L9{V4L<`k<`k7XÌ|.Xڐ7XÐ7XÐ7X99ˑtt 8= privatemsgo"y&V[@x G [@i Ix+R"@@V'@ :uY*h :] @u)@!:` @Q)Y!:h$o m(g GS~@bjR @@H @@S q!:[@E9@PfW@@pN_l @@ TxM  @@I@d  @@_mF2@\zG ! i @4 u]  @Q^g[ V^ U @e~}V@`@y b@mca\"EI {  @ Ri{?FGs@o:`@v&m&v @m _T_ @UW@hju0&!!!El!ElEl!!!!!!!!!!!!!!!!!!!> YR@GI&/I&/!!I&/:>&!a ,Oa ,O!!!u&O]@tM{ @@_v @@/@Fgce MGx J@bz!Pc\)_ZIk@u@]YN Q [T @Ud @z<@@c@} W h yF@cTg @wLl  @]"p  @@p+FG[Do 8o $䇘xW 3B9ˉ 3B99ˉ 3BUު99˵M99˵M9ˉ 3BUު9˵M99˵M99˵MUު 3BUު9˵M99˵M99˵M9M99ˉ 3B9ˉ 3B9 q  @R @v@s@M@~E@M^ y } ZoV@CF @X`@sG @t @@@s @|N y@LY @z@~O= ^@t  @] @_ @m [ @sT`abcd}@Ln @@y[ i @@m@XSI @s @Qj!Q!x a _:A+U Q K wjL^aKkNk P`+@E lV mwuoE f _e\KL d*@hs0L8 E1@V*@nK@[VG@M@h @@X@z;[Vu ^B@eD@jW LT OQR]z5@U} y o@i @r@E@AA|gu4@j J`P@c  Wa@V'{@YpyG x{q@qo A@k YDpFHNJKt@eO@Q^9TUVWAYM _]H@^`abdAhD@f#Dnp^rg@wt xb|YI@T@A@}CVGTIKY@eLH T@wPGSB @\@XBb {%@J@y%Mv%UF e f LnkKwmG@@e%;;P @J @_ @j  @k@UBa z~>B?#A DH%|] o C;kAd3E #I;B;B 3B;B;BI;B KoE@kKS@@U@D$@A$@XHx;!xJ x, J   [H [ ]Dj]d@{ cD}7N Vb{ [.e{V.e{V{V{V{V{V{V{V{V{VN'{V{V 3B.e{V{V.e{V{V{V{V{V{V 3B{V{Vv?{V{V{V{V.eEP]1.eEP]1EP]1{VEP]1EP]1EP]1EP]1EP]1EP]1EP]1EP]1.e 3B.e 3B 3B.e 3B.e 3B.e.e{V{V.e{V{V& n t h!@i!@Zq S|!@@"@I E xFU3r Vq3A"U[ 3B& |F@SDGj5p @v U[9ˉOLSOLS.e.e{.e{.e.e{99.e{.e{999.e{V99˔> Y.e.e.e{V99˔> Y{V99.e{{V.e{{V.e.e{V99˔> Y{V99{V9.e{V.e{{V99.e99.e{V.e9{V999{V.e{{V9{V.e{{V}"#{V9˔> Y{#U{V{V{V9{V{V.e{V.e{V.e.e.e.e.e99.e99.e9.e=$:e99{V9{V.e& x@N"@{Y} @|@@@sI F@D"X_@  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~hHYF~,w ^N'H,.e99.e99.e999999S^S999S^S99S^S999ˉ 3B99ˉ 3B99ˉ 3B99ˉ 3B99ˉ 3B9ˉ 3B99.e99999.e99999ˉ 3B9S^S9.e{9999S^S99S^S9.e9ˎԝX9999.e999.e.e.e& H ]Nexgen core controllerG ] ZeropointF ]1.08 build 1115eI d(@ SF@{ IFm-| T9 CU K/xxx l!EF\7 W]8釅m.e 3B.e{V 3B 3B.eTO& AFoC#@@^g!@k!UE`NER!fN!@z U#@@qn@W#u @r b c {O" u` x^ @ @T M ~BH @H@yDJC$#@pjX}#WvhWv|#X~#=#W&X^X,@hW  ZtR@U,ND @hLBQA %6dL,,?M%6dLD ,D ,&6dL&6dLD ,P,@A D PHP%6NLA Ph6oL6NLkPk,?D HPkk%,@h6oLkk,@A %$k%HPk6NLA D k  OT@RXO@G,fMU@[@gr,\@`@c`Y_ iJo +tsrV+@u@qsU+mynh@x@F8@ }U[999˔> Y{#U9˔> Y{#U9.e999ˋ}"#.e999999ˎԝX& EA`M DR@H~*y*@S Lv @P*@x MN@Q @a@y[v@{srCa@Qb%TkJm`@wqR@ FC@bj>Z @~@b>h4@{@D@e@@mv utO@jI>r@N@PkTTXqe@Z) Q @^@V P Y)kce@@V6@}%Qz NopqGxU)@vt@ar@<Y kK ~S~}vd ]FX[ K&@l<W~ iY&@LNR@f  O^&@SU@Vl r X\Q@@drfliA@`g@`jklG}@I8uopQ@m@d@qy@P@f|a@ta@XA `  F@J@[;@\@PJK@LMNQ|N@I(U} @~[m:L Wg:e@]^aC@_eZ'@hb r pmikl'@l~qv@{f@ye@lx'@t@w@~'@r@@['@\:@@ziG\@@HRK@@@u@R_;@WF@Z  [@]@wO@o@`@ @@\q@k@wU8@mnC@q@s@p@@v_t@B@Sz{@@C@E@@F@GKa@S"LMW@R)]&I@U@_@x(@@H@C{(@@_D\Z@e e@O7@b@a@(WP @D)j|mnoK@s[@@s@u@@v@T)@~(@y@x@v @|@CY uXDEF@H@I@eQ=Z6@lw ORSTZd@z%h=__@x=t@@@D@`hS y @>Vnl pm@Os%lq%lxFEbC@@` @^ @|@{@m%x@_H@b ^@u>QK@L@iNl@r3Ti3~UWW3o@V3@\Q3n P3@^@L3@@X@h%iD3@j gE@n@cqA\%~O2@V%@^@U%] {@2Z|@x}1@s?<s. ?,?, vY@t@M*@C@Z FR%RV @Qli*PNo M%L%YCi/[F c^ab@%Y/g`e^xL/ls$vC/@B/@M @tc$oF v.a$RKe CD.@@ABREt-|Ty+Ou@QBPF-l@Q-UXZf'oYn^{s,]@bB@W@cR$^C1l %^&^,^,^C$P$,@V%,xjV&, VV,,p $V,,νV,,|V,, *ƇGV,,F0V,,FV,,ؘiV, , DV, ,[V, ,\V, ,"kV, , qV,,CyV,,!IX&,b%X,, @@X, ,QZ^&X%,ǶX,,]/X, , SDX,,X,,X, ,!X,, 7X,, X,,ZEX, ,X,, X,,ogX, ,L*H,,B9H,, qH, ,"amH,, 8H&,D꾤H,, KH,,`KH, ,pH, ,~(H%, 'H,,0H,,H, ,9H, , H,,|H,,eV[%,D")[,, *C[,,#[,,9[, ,Y[e[,,  [, ,}[&,][,,O~o[,, ,[,,C[, ,N[,,~S[, , 5:[,,*[, ,ӆ%^&^,^,^  S@I,@m@Vmno@zLr@sI$TXs %^%^D$^T=s U,^&T=:=s U,,^,T=:=s U,,^,T=:=s U,,s ^,  ~#GJ fE@{R @\A B C @~@CF @G _ YCAz#[C@O N DC}@cC`W X Y @l#|\ @] g#vb#t@d `*di j k @@ln o p @\#rs @t [pz'fn%^nW#,op0123456789ABCDEFp,&opp,no  X@mpw@M8A { [D& i@| A!o{B!C!D!@rF!G!H!@@ghL!@M!R#@eeJ#d@T!X!@j@uZ![!\!@H#v_!`!a!@F#@f_e!@f!Q@E#@\MF@U@n!{r!s!t!@t7v!x!OO~!@Ml@~ B"@U(E"@O(p@BG@zCRGf?k 2H"&Cnť᱘᱘᱘ V]98Failed to login: you are banned/kicked from the server.]gThe server has refused to let you join the game because you have been banned or kicked, meaning you are probably not welcome for the time being. Please go play somewhere else, there are enough of other servers and games out there.R] Reason:Q] Period:N]e"O65-|'*./" 0" +" ," 1*";*"5@ =U}q>r˲ o8`tmxuejeD4 F,-Pnled;.:Oz2#&XĔHIW[Z'0Ԟ3M+Y9K~^Yb/)^]JwA $_\%A _QE i" {SGp*VRyC 욚1@C(0?<70g505|LA7hvT=fޫ!6BѦߤh06kascN7  z'@M"@[G~ 65-|'*./" 0" +" ," 1*;*"@q>r˲o8`tmxuejeD4F,-Pnled;.:Oz2#&XĔHIX[Z'0Ԟ2M9~^b^]w_[_Qi{SqRzC욚1>C0><70g505|LA7hvT=fޫ"6CѦߤh06l`rdN7 V'SQ"@HT"U"V"W"X"Y"Z"["@O^"_"`"a"b"D<@e"f"g"h"i"Z<@cUG@LGHG@rFs p"&,&imFt q"$BE& hFr"s"t"u"v"@`Fx"y"z"{"TFt1y 8}"Y>n9˔> Y 3B9˔> Y9˔> Y9˔> Y9˔> Ysss֨)ssssss9˔> Y9˔> Ys9{V9{V9{V9{V9{V9{V9{V9{V9{V9{Vsssssss `]mutate nsc balanceteams`mutate nsc setteam 0`mutate nsc setteam 1`mutate nsc setteam 2`mutate nsc setteam 3` suicide`"!mutate nsc openvote,mutate hz010`87mutate nsc openrcp,mutate asc#get#window,mutate hz0090`mutate nsc pauseDF@~E"zEEmE@Z@[@[E @c!@a@^!@c@S!@FE@BE@M#@N#@O#@P#@wD@O!@@S YDuAe 2V#*gM~tt> YMtU K/> Y7XÐ7XÑttt᱘᱘ I]CloseH]SendG]Say:QDX#Y#Z#[#~Cc ]#=u& M O S^#_#`#a#c#d#e#f#h#i#j#k#mCm#n#u#o#gn#o#m#  hCq#r#Rx#s#g bs#r#q#  V v#{#w#ew#V v#V   ^Cy#YL kL z#L y#  W|#}#@v@E$@IV@uB$ULI%Z%ZA$IB$:ZV:Z&V,:Z,V,:Z,V,IZ,  s @}Bh3Z F$Г 3B 3B 8]aboutwBU4Y WG$R99ˉOLS7X yJ EyE7XOLS yJ EyEttt7XOLSttt7XOLS yJ EyE7XOLS yJ EyE7XOLS yJ EyE9|.X yJ7XÐ7XÐ7XÐ7XÐ7X yJ7X EyE7X EyE7X EyE EyE7XÐ7X yJ yJ EyE9t9t9t9999|.Xڌ|.X yJK4 yJ99 yJK4 EyE9 EyE4L4L4L4L4L4L4L4L9{V4L9{V4L9{V4L4L4L4L4L4L4L94L9{V9{V|.X4L94L9{V4L9{V4L4L9{V4L9{V4L9{V4L9{Vttt yJ7XÐ7XÐ7XÐ7XÐ7XÐ7X 8] accounttypes` @QH$AES,m&7m,@SpS%mul6d` ,Q%6d` ,,?Q,8K,8QK,xQQ` SKRm%m,RpR:mlmQ` R,uH$6o` ,m%Cm,@m6N` $m  uBI5X zK$#7XÉ 3BtOLS 3Bt7XÉ 3BtOLS yJ EyE 3Bt7XOLS yJ EyE7X yJ yJt yJ EyE7X yJ yJt yJ EyE7XÉ 3Bt 3B yJK4 EyE7X yJK497X yJy&. yJ7XÐ7X yJK497XÉ 3Bt 3B yJK4 EyE7X yJK497X yJy&. yJ7XÐ7X yJK49)|.X yJ EyE EyE EyE EyE EyE yJ EyE EyE EyE EyE EyE9|.X[[9|.X9{V[[99ˉOLS[[9|.X[[9|.Xڑt9t999|.X9[[[[[[[[9[[[[[[[[9{V[[[[[[[[ yJK4 yJ9 yJK4 EyE7X yJK497X yJK4 yJ9 yJK4 EyE7X yJK497X yJ7XÐ7XÐ7XÐ7X yJ EyE yJK4 yJ99 yJK4 EyE9 EyE7X94L4L4L4L4L4L9{V4L9{V4L4L4L4L4L4L4L4L4L4L4L4L4L9{V4L4L4L4L4L9{V4L9{V4L9{V4L4L4L4L4L4L4L4L4L4L4L4L4L4L4L4L4L4L4L9{V4L4L4L9{V4L4L4L9{V4L9{V4L9{V4L9{V4L4L9{V4L9{V4L9{Vtttt[[[[[[ yJ yJ yJ7XÐ7XÐ7XÐ7XÐ7XÐ7XÐ7XÌ|.Xڌ|.Xڐ7XÐ7X[[9{V 8= bancontrolrBG6V uL$9OLS yJ yJy&. yJ yJ yJy&. yJ yJ yJK4 EyE yJ EyE EyE yJ EyE yJ yJy&. yJ EyE yJy&. yJ yJ yJ yJK4 EyE yJ EyE EyE yJ EyE yJ yJy&. yJ EyE yJy&. yJ yJ EyE EyE EyE EyE EyEOLS|.Xڌ|.Xں_4 3B[[ 3B[[ 3B[[9ˉOLS_4 3B9 3B[[_4 3B9 yJ EyE EyE 3B9 EyE EyE 3B[[ 3B[[zZzZ99_4 yJ EyE EyE yJK4 EyE EyE EyE EyE EyE yJK4 yJ yJ yJy&. yJ9 3B yJ yJK4 EyE EyE EyE EyE EyE yJK4[[9[[9[[9|.X9|.X999 3B9 yJK4 EyE EyE yJK499 3B9 3B_49{V9{V9{V9{V9{V4L4L4L4L4L4L4L9{V4L4L9{V4L4L4L4L4L4L4L4L9{V4L4L4L4L4L4L4L4L4L9{V4L4L9{V4L4L9{V4L4L9{V4L[[[[[[7X yJ yJ_4[[[[7XzZ yJ 8] bootcontroloBR6U kM$`jO9˵M9ˌ|.X9˵M9|.X999˵M9ˌ|.X9˵M9:>&|.X9˵M9ˌ|.X9˵M9:>&|.X9˵M9ˌ|.X9˵M9˵M9ˌ|.X9˵M9˵M9ˌ|.X9˵M4L4L9{V4L4L9{V4L9{V4L9{V4L9{V4L4L9{V4L4L9{V4L9{V|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.X9˵M9ˌ|.X9˵M9ˌ|.X9˵M9ˌ|.X9˵M9ˌ|.X9˵M9ˌ|.X9˵M9 8Mclientsettingsg$pCmBu6T FN$u@:9{99'; 99 3B9 3B yJK4 EyE᱘᱘9˔> Yv?᱘9˔> Yv?᱘9˔> Yv?9˔> Y᱘;(᱘;(᱘;(᱘9{|.X9{|.X9{|.X9{|.X9{9˔> Y'n 64L4L4L4L9{V4L9{V4L9{V4L9{V4L9{V4L9{V4L9{V4L9{V4L4L4L4L4L4L4L4L9{V9{V4L9˔> Y4L4L9˔> Y4L4L4L4L9{V4L9{V4L9{V4L9{V4L4L4L4L9{V|.Xڌ|.Xڌ|.Xڌ|.X 8] gameinfojBQ7S BO$i9᱘9)7X9˔> Y9˔> Y9˔> Y9˔> Y9˔> Y99˔> Y9˔> YM9˔> YM9˔> YM9˔> Y9˔> YM9˔> Y999˔> Y'n 69˔> Y'n 67XÐ7XÐ7X9{7XÐ7X4L94L4L4L4L9{V9{V994L9{V4L94L994L4L9᱘9{V9{V᱘᱘999᱘4L᱘9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9ː7X9{V7X9{V9{9{7X R*RRdRa*``*`_*@@@8] startpage@fBi7R RQ$Js97XOLS yJ EyE7XOLS yJ EyE 3B[[|.Xڌ|.X9ˉOLS yJ7XÐ7X EyE|.Xڌ|.X[[|.Xڌ|.X[[ EyE|.Xڌ|.X[[ 3B9 EyE|.X9|.X9[[ yJ yJK499 3B9 yJK4 EyE EyE9 yJK4 EyE9{V EyE9{V9{V9{V9{V9{V9{V[[ 8]ignoredweaponsettingsg$B`BB D$Ah%6dB %&6dB %%6oB #Eg&6oB ,6oB ܺ,6oB vT2  cB@^BA8P VT$2^sOLS|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڑtttt9)7XÌ|.X9|.X9|.X9|.X9|.X9|.X9|.X9t9t9t9t99ˉOLS9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{Vtttt 8]nexgenlogsettingsg$ C\Bn8O iU$?t_4h{h{ 3B 3B 3B 3B_4_4)7XOLSOLSOLSOLS'; ^OLS'; ^OLS'; ^OLS'; ^OLS'; ^OLS'; ^OLS'; ^OLS'; ^ 3Bt)|.XOLSOLSOLSOLS9ˉOLS99'; 9'; 9˔> Y'n 67XÐ7XÐ7XÐ7XÐ7XÐ7XÐ7X^^9{7XÐ7XÐ7XÐ7XÐ7X^7X^7X^9{9{|.X9{|.X9{|.X9{|.X9{4L4L4L4L9{V9{V9{V4L9{V4L9{V4L9{V4L9{V4L4L4L4L4L4L4L9{V4L9{V4L9{V4L4L9{V4L9{V4L9{V4L9{Vt'; 롌|.Xڌ|.Xڌ|.Xڌ|.Xں_4|.X9˔> Y'n 6|.X9˔> Y'n 6 R*RRdR8] matchcontrol[BV$VBZ9N JX$A^99ˉOLS)7X9))7X99'; 9OLS 3BtOLSttt|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.XOLS'; ^ 3Bt 3BtOLS7X'; 롑t9t9t99|.X9|.X9|.X9|.X9|.X9|.X9t997X9{V7X9{V7X4L4L4L4L4L9{V4L4L4L4L9{V4L9{V4L9{V4L9{V4L9{V4L4L4L9{V4L4L9{V4L4L9{V4L4L4L4L4L4L4L4L4L4L9{V4L4L4L4L4L4L4L4L9{V4Lt4L9{V4L4L4L9{V4L4L4L4L4L4L4L4L9{V4L4L9{V9{Vttttt'; ^^9{V^7X9˔> Y'n 67XÐ7XÐ7XÐ7X'; 롐7XÑttt|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڑt 8= matchsetupTB@LB|9M [Z$OyOLS|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.XOLSttttttttt9ˉOLS9)7XÌ|.X9|.X9|.X9|.X9|.X9|.X9|.X9|.X9|.X9|.X9|.X9t9t9t9t9t9t9t9t9t99{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{V9{Vtttttttttttttttttt 8]miscnexgensettingsg$fCCBe:L B[$ls9{99'; 9˨)7XOLS'; ^OLS'; ^ 3BtOLS'; ^ 3BtOLS 3Bt'; 롔> Y^'; 롔> Y^|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.XOLSOLS|.X9 3B[[|.X9 3B[[9OLS'; ^ 3Bt9ˉOLS[[|.X[[|.X'; 롐7XÐ7XÐ7XÐ7X99ː7XÐ7XÑt᱘᱘t^᱘^᱘^|.X9{|.X9{4L4L4L4L9{V4L4L9{V4L4L4L9{V4L4L9{V4L4L4L4L9{V4L4L9{V4L4L4L4L4L4L4L4L9{V4L4L9{V4L4L9{V4L4L4L4L4L4L9{V4L4L9{V4L4L9{V4L4L4L9{V4L9{V4L4L9{V4Ltt[[[[[[[[t'; 롐7XÐ7XÐ7XÐ7XÐ7XÌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.Xڌ|.X[[[[ 8] moderate@BW;J F\$:v97XOLS yJ EyE7XOLS yJ EyE 3B[[ 3B[[9ˉOLS yJ7XÐ7X EyE[[[[[[[[ EyE[[[[9 EyE[[[[ yJ yJK499 yJK4 EyE9 EyE9 yJK4 EyE9{V EyE9{V9{V9{V9{V9{V[[[[ 8]replacementhudsettingsg$B~A];I i]$E 3B9˔> Y4L'n 64L4L4L4L9{V4L9{V4L9{V4L4L4L4L9{V4L'n 64L'n 64L'n 64L'n 64L'n 64L'n 64L 3B94L4L9{V4L4L4L4L9{V4L9{V4L9{V4L9{V4L;(4L;(4L;(4L;(4L4L9{V4L4L4L4L9{V4L;(4L;(4L;(4L4L4L9{V4L;(4L;(4L;(4L9{V4L;(4L;(4L;( 8= serverinfo|Ay;H p^$htttttttttttttt|.XOLS)7X9ˉOLS9t9t9t9t9t99t99t9t9t9t9t9t9t9t9|.X99{V9{V4L4L4L4L4L4L4L4L9{V4L9{V4L9{V9{V4L9{V9{V4L9{V9{V4L9{V9{V4L4L4L4L4L4L4L4L4L4L4L9{V4L9{V4L9{V4L9{V4L9{V4L4L4L4L4L4L9{V4L9{V4L9{V4L9{V4L4L4L4L4Ltttttttttttttttttt 8MserversettingstAW=G z_$޶9ˉOLS99[)1ז9)1ז)1ז)1ז)1ז9)1ז)1ז)1ז9)1ז[K49999˺_49997XÐ7XÐ7XÐ7XÐ7XÐ7X[[[[9999|.Xڌ|.X9ˌ|.X9999999[[7XÐ7XÐ7X[[9_49[[[)1ז_4[[_4[[)1ז yJ[[)1ז yJ yJ EyE9|.X yJ yJy&. yJ[[y&.[7XOLS7XÉ 3B[[_4 3B[[OLS7X[)1ז 3B[[_4 3B[[OLS9[K49)1ז)1ז)1ז yJ yJ)1ז[ yJ EyE9[)1ז yJK4 EyE)1ז EyE9)1ז9)1ז yJK4[ EyE yJ[[9 yJK4 yJ99[9 yJK4 EyE EyE99 yJK4螺_4_49{V99_494L4L4L4L4L4L4L4L9{V4L9{V4L9{V4L4L4L4L4L4L4L94L9{V9{V4L94L9{V4L9{V4L9{V9{V9{V[[[[_4[ yJ7XÐ7Xú_4 8] useraccounts`$b$e$@i$@@f$@g$@j$@k$@@UA@l$@m$@@o$@IA@q$@r$@w$@@u$@x$@@A%Ts@@{$@@}$@~$@$@g@`@@P@@@D%@E%@F%@G%@P@J%@K%@@N%@@P%@Q%@@S%@T%@i?@]%@X%@Y%@Z%@[%@@o@_%@`%@a%@qph@f%@g%@@?@qIl%h>VY Ip%s@M@`@\u%c=@s x%aWT=@i V=b@M=B&@C&@D&@E&@K=@\D=@G&@fR@Q&M&N&O&P&j<R&K@T&@U&V&W&X&f<[&@@                !$ (+++,%!%!1!2!3! 5# 6%=&>&:2:0""!''(.2:32+97-444>><>>>F.L/D8 A:B<X- ^/ Q6 Q5 V1 W6V: Y7Y8Z8 Y? U?a/c4 c<f?h0r!I@SB^A OI&GC4JE2QD'SG%PL;PM?XP&UP:aBeAeB dCbHaMkBiG jOkK hQmP jQqG tK xJ rRyU}TlX1o[6vW y^*p]9zaxk0SYbQXdhaEqqMaehy|z^[[\bm ah`qq u { | dldhg"r/p>}3v?tC 9 4S^A]CHl|\&@{@O_&@`&@@b&@c&@O @e&@f&@G<Jg&b@v@j&g@k&@q&@j;@r&@h;@Q@@   -6( 6$3! $#!! ""$%#!%$"%%%'('(%")(")(%,)$+))./-0.)0/;30+30,51-74/210315630542952986=:5<<3==:Z$|! M=;ECK ]@4@>9J>:fjzn*d j><|(3z@x3WBD:EA=GD?DEEDBKIFBMGDHGKJHBMIFOLGKKMOQMOQPQB^RQGQPMURMXUORRQUPPWUPZVQYYS^[R^ZT_\WZZX\YY^^ZB@cEClIG`NGlIHlIDyNLpNIzcUPa^Yg_[e_\zEFba[f`Yea\kd\``bgcegfdjf`jhckignhammfeczoopnlxslcrmlqrlvqjuvlztlvvrxwzzzu{||72<<979;9;:;72596994=988@=D6C1B;U5MGVQb`~|{~~goprCBZSebzz':6<F!D&O{u|t|  18!.)5  ++..,-~f}~¼ƾn&b@u&@@      #%&)*!!/##/%%4((7))9)):**<--=22?..@33D22G33H88M99S::R::T<;U<;V==Q==U<=X>>X@?[AAPAAY@@Z@@\BA]BA^CC\BB^DD\DD_FF]FF_LL\CC`DC`DD`FEbFF`FFbFFdHGeHGfIIbHHeHHfJIdJIgJJeJJfLLfJIhJJiKJjLKjLLiLLjOOkMLlNMnOOlNNnPOoPOpQQkQPnRRmRRnVVlQPqQPrRQrSRpRRrSRtTSuTSvTTrWVpTTtUTwVUuVVtWWvVTxWVxXWtXVzYW|ZZsYXv]\s^^uYYxZY{ZZzYX|ZX}[Y[[|[Z\[|_^z\\|\\~^^``uccygg{\Z][\\]\^\^^_^^]_^_b`^`_``aabba`a`ccedddeeffb`cacbdbeceeffedfdgegfhgihkknmhhkjjjkkllllgfhfigihjjkikjkolkljljoomknlompnpntt~~qpqqssrpusttuuvvwwxwyxtyzzxx|z~~~~}{z&d;w&{&@k @     )'!*#-#,&/&2&3,5,4* 4,!4,#=2%@3'D4%C7*A:.D:-G>.M7)I>/X?0MC3SC-TE3TH4[F1fN6qT=uZ?_TAcUBdXEj[Ayb@bFfFmGmJlJnLnQqNwKtKuNrLuNxSqPvRwRvT{R{T|Q}TsMtKwNvL{N}T}T}PNPVSagTVXYXURUZ\\]_QSY[TVX]YY_eacacibeacfkhlmhmmkmoimpo_‘bŒ`ǔeÜnŘmȕcϜjϞmpsřrƞqʜrўlПqsväqġsĥqťtǡxǩsŨvɠsȡvΡr͢vˣyʥyʮyˬ|ͭyέ}ϲzҢr֣q֥uҥxЩ|Ҭש}ԯئwܩvڨxв}Ӵ~|ӭҬ׭ܯұԷչٺڻؼۼݻ߻᱀ഇṆ赂빆칆辏쾎œÏ’ƑƗ̚ƒɑɓ˙’ƔÑēƗɛ͙ə͚̜ɚҚљўԛ՜֞נԤءܣԢ٠٧ݢۡV;|&P;N;A'@PI;D'OD;J'@h P@P'ng@y@Q'R'@S'D@ U'@^:@@  !$(& )"-#3&2)7+5+9,=1"""%%%)%!*(&)))**-.-+---1,'7,!4/+20.;1'81*?4)=4.11122443366678::6;999;;*CA?LA5NEx[6}\8AABDCBEEECCLHFEHHHIJLNLKMMMOPRQGDXOCTNR\QGZTOQQPPPTUUUWWYXV__XSYYYZZ\\[[\\\]]a_`c`]\m_Rw_Gfa^pg^{gSaaabbfeeeffjhgejhgnhcihhhinoljllljkpkmrqqqvtsvvvuvywx}yxuzyzyy~}yxz|}}h>jNhEkJrFzWzz`yG~LRs]TbipŸpʥ}ϳؽӻa'@\'@]'^'@M:@`'@L:@c'@I:d'@G@f'@D:C:@W'h'@k'@9m'@n'@r'@p'@y9@p9@u'@o9w'uy'@{'@i9@z@@        "&! $ ) * &##, 3# 1& 2$6%9$9(:-?,=)'$ +&!0*$>4$421:60897998@'F( L* B-D+L,D1 E1 O8 E2G2L3U7 P8 Y0]: P0R5R:Q8W9T9];]9^>F6!J3 O;#K:*N>.@80C>8Y?#]?)`> j>c;e?g?"]A_A^G@@26b|YOOOMMRϺTd2,e25^RNQONLLKGGH4$8/26mLGILLIE &.*120JEEGIF &$,=E &F @        '3 $2!**!",?/$,)&'9.9 +0<0)&%*G'-R-3\66@07\-4f19i29v5D3@?L>S?M;;CyK=JLCVK]@P"EZ$YL S_26b|YOOOMMRϺTd2, e25^RNQONLLKGGH4$<8/26mLGILLIE &.!9*120JEEGIF &- (!$,=E &F   J(@M(L(K9@N(P(8Q(W(@  """"#####%%%&&&'''((()))***+++,,,---...000111222333444776777787888999::9:::;=<===Pd?BBBCCBCCCCDCDDCDEDFFFGGFHHGHHHIJHJJIJLKKLLNPOPPOPPPQQQRRRSSSUUSUUUVVVWWWYYYZZXZ[[[[Z\\\]_^^^^^_^___aaabbbcccbdcddceedeeeeefffeiihiiijjijjjkkjkkklllmmlmmmmmnnnnoooylkppov~opppqqqrrrssstttuutuuuvvuwwu{{{{{||||}}}~~}~~~Fcmw1/{R~Hxw¾{8V(x8X(Y(@[(@5-L*./"@0"@+"@,"@1*"Fĥ@@¿}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuussssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd@@\(@p8@Su `(} @log(@e(f( y!z\@l(n(u!co(p(q(r(s(t(u(v(@B@|(f AN E)@A)B)C)F)@G)@H)@J)K)L)M)O)P)R)]!cS)@t@w@@W)@B @d@c@e5Y@\4HQM4J4@b)@hf)@n3@W@g)@N@i)@j)MLK3@J3F3|V ' l@o)z2Xe r)hE!ct)v)d\ @y)@b*)z)T)$z\ s{xw\ *`w.\ *.\ Tz)y)\ \ } X @|)@})]A*~)<!X s{}wX *ew.X *.X <~)})|)X X } G jC*@*L'uG s{swG *[w.G *.G  L@*G G } A hE*B*3iuA s{swA *[w.A *.A  3B*A A } g2K2V$ I*tm{ s{-u  w{ *.{ i|jt-u 'a/!F-u .; mt-u s m { '{ { }-u  D*I2h H2D2[! G*B2b[# K*}!f{aP~a,%]a~a,va~a,&[]aJs{-^ wJ*{.;Jw{*|{j]-^'JJ}p-^v {!}|ZvJs} }|wJ*v .J{Zv jZv v #v  H*~1\& A@s.C s{-@  wC *L.C wL*t|Lj@-@ 'La/!FL.;L s@-@ wL*-@ C C }-@ L* A~@j1b1_1@Y1S*@ZK1lT*W*@X*@\*@l ckZ*']*@c*\@z ^*@_*']y0TU  q f*@g*@o*@h*n*OysVW 4$OQT <$T Oi*h* k*l*Dm*Wq+)wE *E Wm*l*k* q*@^0p LS0lO0t*Wu*w*}*@E0z*@{*@+@~/J@F+@R :x/B+C+@K+@r/G+H+@e/dQ+R+]/Q/@qyj.X+Y+Z+Wuf@]+@^+@_+@Cc+@d+@a+8f+@j+k+n-h+@j-o+m+^-u+@v+w+D cs+nT-N-E-@A-E y,v,D,B,]z#B,-j!J E,c_k,ppp[cX] cQ l,o,b]S&( KF,H,PG@L,! "Failed to create log file: %1"M,' "Nexgen Server Controller is active."N, "Restarting server on %1"O, "EXEC %1"P,9 "Nexgen boot sequence failed, resuming to normal mode."W,+ "Warning, attempt to load %1 has failed!"a,R,A~ S,Q,C\c@ L>@ /a0 :uRQwu*R10wu*C%CsuF6D C\6C C\6B C\6A C\Ces% FT,pCru*,s, VsstV&fVsV&\V\V3ss&6D V\p6C V\o6B V\n6A V\muponm X,C "Server crash/reboot detected, executing Nexgen boot sequence..."Y, "ServerID = %1"Z,7 "Configuration file has been automatically repaired."[,2 "Updating Nexgen configuration to version %1..."\,5 "First time run, executing default installation..."],8 "%1 has been detected, entering compatibility mode..."c,, "Failed, your server should be dedicated."5-_,*./"0"+","1*"758q@ 00#000000' !)00000000+" !'00000-'00." %,00000 000&$+000000000(")000000(00+"!'000000, 0/#&,000000$&$+000000&-000* @HHHQQQbbbnnnzzz|~~OG "Loading %1 %2..."t,Io`-rI-F-rIwGJtsfI-LsLIvwGJtCL!GJ JGC*WU^]. d3^JG^GVXG,F,?& K,-H,GJL. TrL*L ^,GV?KX?&LK,GW. Gb. GV?KX_.  d,( "Starting Nexgen Server Controller..."e, "%l, %F %j, %Y, %H:%i:%s"f, "[%d/%m/%Y %H:%i:%s]"i, "nsc_%Y_%m_%d_%H_%i_%s"`,* "Failed to initialize %1, destroying..."g,( "Failed to register %1, destroying..." "dd/mm/yyyy hh:mm"g-| A nL:w| *| a/!AF.| w} *1r} *} a/!{DZvURONrF*D$ppF: D$VH,wH%*-H%)A| } ZURONL-(Hw*)A| } ZURON' b,m,cM w* $  h,% "No replacement class found for %1"p,n, "Login request for %1"k,@@x,|> L-yE!B4-y|{EJC{E|* q, "IP = %1"C,A,W:A,qI, u}f'5}ru*\3u t} w,{,re. F z,@,j`E .^wE *BE e@,E kE .E  u, "ClientID = %1"J*B-_\'3J(n__name_/ |,+_Y@ .Uw@ *9@ e+@ @ .@ * }, "Password = %1"@ H*H-db$4J)nddteamSdj ,~+\U Y| .Uw| *9|| E~+| | .| * @-- "Illegal login parameters (possible hack)."| VC-\o[#ecw*f\r. Ufk*\ p f G*P-Q[!L J?`wL *L !<QC L plL L AQD#EQnameQ/QDEmutedTQ-{QD$EnoTeamSwitchTQ-y q@}+j,ID TICr@-~ XIU }wC*k-~@fCU }|Iasc#get#window|Ihz0090@fCOPENRCP}-T 'G-~ -T #,w%*%DI@Gw*DI@ E,J-|+b>+.)|+-l&(<%( D- "Client ID already in use."C,L-W]1C;W-2.)W-l}+8jAJ W-F`WxU Fj1F-FU ,RRU % U ,U , &[qFidF\ &[qFipF^ ([qFnameF/ )[qFtitleF{ [qFteamSU  +[qF countryF~ q D,{+_n{+Q M-" "Kicked/banned from the server."@XC?Y. S-6X$6X$6X$XPOy+s+?& 6X=,6X=,6X=, 6X$6X$6X$X%(XP?,O. S> S- "Invalid password."F*_-z+h%xnJ?vwn*V`nz+&<nC npjVnnA ` 24.0X- 16.0V- "Server is full."h-t+C?10.wA*At+u+v+w+ U-r+\?T Yy . Uwy *9y (r+y y . y * y  D*e-pVQ`pjJ?wj*nwjpj&<pC jpjQjjA%u - pD2pnameJ-A {u{up/p jup-{pD mmutedp-ypDmnoTeamSwitch \-a-cT w* $  ?yw. T-'?,o  b-MG,5.T-L-M--M ]-q)s-q+Xrq+ S  Ln y}o-L6n $6n $6n $n  n p+m+ M.HC7 l=rH:|V}TrH:|V}(wH*Ha/!AV.H-x wV*Ha/!|0|V}V&pV:-x  rHl-_a.HV}V&-x nrHwn*nh-G-i:4,nnFnnGrHlq-_'n<$-Unable to send message, you are muted.(-x  rHlV$mm-x  wl*1rl*la/!{JrV*V$mppV: V$M,wM%*-aM% CHlV-NT-a(Mmw* CHlV-NT' i-d-A0. o-n+c!c,&$w1*1cn+o+ k-l-f-l+ 6Il+h+?-}}$ |-i+e*.*w1*1ei+j+k+( Y- 12.0p- 4.0u Hy wu *;-IHu G?D?u @E?D?u @HGEu  v-QTQ pQJ?^wQ* -jGzQ~ o znQ^zo &!o  !BAD INPUTQ~ none !DISABLED-j' GG{o |o ,noneQ~ noneGQ~ o ,J+nQQ countryQ~ QQAn-jz* u-Gz-g?wz*T Fx-o)~-w-|&Jg ]$Jf N$Je U$/a0 F!E {zF{10a?@'' g+?pNexgen Server Controller vU _, 3@A?,?,8.3-'-' }-y-pl'' i.b+[5%+)w1*1[b+c+d+ - "noTeamSwitch"@. "muted"z 2.0q- 4.0e+? OpNexgen Server Controller vU _,-'-' B.SM8 0~S.%Spp S .S~CS f.C~@A?,?,f}%Bfi Af_@fhCf#`+_+^+]+f DZ- "No playing rights."E. "Login accepted."F. "Login denied. Reason: %1"G. "NEXGEN LOG FILE"I.@H. "engine-version: %1"J.O.L@2pwL*La/!{ rLRg !M g !R-Da.Le RrLwR*RhrLR-D'R<$-Unable to send message, you are muted.(BrL* wR*rR*e $wL* rLRwR*g !MP$g !RP$P$ppR: e PPN,wN%*-KN%%@LR}e g -F-K(Nw*%@LR}e g -' S.L.anQ( P.kMM-M? AKk,wk%*k" Q.TV+a>T,wT%*T%HT_wr*r^r* R.UH%,XF "The game has ended after %1 sec.SDXC?$-G`-G-y-G-G(]$U,wU%*U%HUb T.V`m"CThe game has started.$-G-y-G-G']$V,wV%*V%`V s.V O U.X fX, p-G-^X X$IWaiting for ready signals, press [Fire] to send your ready signal!n0-G:d %X X FX O$@Please wait, an administrator is going to start the game.nX 5$&Press [Fire] to start the game. r.X|"jP$x%xx%:4%-_4$V ?wV *fV V V Ax%:4,v-G:R% r?*#@?,<:R-G(b%$-y-G(:o%o:o%-D'bdebug gpfNX,wX%*X%|X l 4.0V. 4.0W. 0X. 1Y. 1Z. 2[. 2\. 4.0]. 16.0^. 12.0_. 16.0`. 13.0a. 18.0b. 16.0c. ","d.[+aLwo@ ,@6W@ +[+6Z@ +Z+6N@ +Y+6T@ +X+@ u K. "nexgen-version: %1"f. "server-id : %1"g. "server-name : %1"^/Eo -F E-Z-F Ww1*1$oEK ABH G zE-CG CEvK ABH CC!AB k.e.KeZ"a@@@@@@A@@ A l.lvZ"a@@@@@@@@@@ m.W+Q "W+ h. "server-port : %1"n.& " p.ZQ k-V+B-yP ?D6T"+BZBhP ?D6T"+ZB-yP 6T"+ZP Z[P ?D?m@@w6T"+[?m@o6Z"+uo[?mta6W"+o6N"+[a6W"+u6N"+w"t x.agOa?wa*T{a/a\aaj:abaaaA -:4,4$H^xxAMsss| y.|AL o. "game-class : %1"@P u.@J/x\s1zxF ?wF *orF *[F F F A<-r{x?%-r'V-~E-~' {.w.TJ .z.3wH q.\)k-U+B-qK ?D6N"+B\BhK ?D6N"+\B-qK 6N"+\K \]K ?D?u@@o6N"+]?u@v6W"+mv]?ulav6Z"+]6T"+am6Z"+o6T"+"l |.H/~.PF t. "level-name : %1"K sA/D/E/F/T/G/BD( }.H ! 2Qw6T"+?H &ky?Dw?H hwy?H ?H _6Z"+`%B`H E y^h^?&^^?E E ?fa6W"+_6N"+E `%ef__E ?k`|"e U/@as  p-M 's 0!r [!redDNSCSETTEAMS%@ b!b !blueDNSCSETTEAMS&@ !g !greenDNSCSETTEAMS,@ !y !yellow !goldDNSCSETTEAMS,@ !t !team B!teamsDNSCBALANCETEAMS@ I!p n!playDNSCPLAY@ u!s !specDNSCSPECTATE@ !l !startDNSCSTART@ !quit !exitDNSCEXIT@ !leave 0!byeDNSCDISCONNECT@ 7!o _!openDNSCOPENRCP@ f!v !voteDNSCOPENVOTE@ -M (N %-M  N ,wN %*-M N %a@pN -M  wK/M/N/O/` @/ "level-title : %1"P/X/S/GzA _/T+x{s` ?]-z w` *F|` \T+-z'Z` ` A o-z` q* I/B '\9Q@6N"+?B &cA?D@?B `@A?B ?B b6W"+c%BcB  Aa`a?&aa?  ?_ab6Z"+ 6T"+c%^_bb ?cc|"^ `/W/Dg= @@Z/@[/Z d/P `-M !BH-M Ew1*1P O ^CO P * j/S+YYsZ ?]-{ wZ *FZ C S+-{'ZZ Z A o-{Z q* g/\/JZ; a/@V/O+:%C>dy 6W"+G6N"+Gdn:\&y 6W"+:\,y 6W"+6N"+dy ?D6W"+6N"+d@#ex 6Z"+H6T"+HeS:[&x 6Z"+:[,x 6Z"+6T"+ex ?D6Z"+6T"+e@"O+y x GH f/P+L+)w1*1LP+Q+R+ d k/N+kV!w1*1 kN+ _0b/DK.9 y W0M+r7sd ?]-B wd *Frd M+-B'Zd d A o-Bd q* o/L+j!w1*1 jL+ h/l/c/I+gJSf.: H+AG+$f I+ff u/J+ax!w1*1 aJ+ R/ "Log started at %1"p/ "Log closed at %1"fq/ "The game has started."n/E+7Nhv .: @A $v E+L-C+v k&v B+v  v/S fK w1*1--1--1--1--1--1--1--1111111D-Q D-D-(1-'1 fS D--Q A tS   {/D+`9!w1*1 `D+  s/$ "The game has ended after %1 sec."v w/ "(+%2) %1"t/*RJ?%KJ0K6N"+g.: JA~*$gKg  *g 1B|!1BAA+BR %hR ,B*!R ;R %R , B o ]#R o m/y/ "(-%2) %1"gK-T % Z:T (]  jT S?wS*S53T :T (] :T (SSSA6~,w~%*~% 3T ~ |/z/|*!wWht .: PA $t {*t |*`-z*t k&t  /v*] ^adW?_wW*WLv*dWWA }/+ "%1 has changed his/her name to %2."C0 "%1 has left the server."t D0# "Failed to switch team, %1."A0H0b8Z'V.:  A $V V@0G0x*TNt^Vh.L : L u*t*$$hu x*h-I-w*h F0 "the teams are locked"M0Z Crx*,w, `wwt`&f`w`&d`d`3ww&6l `dZ 6k `dY 6j `dX 6i `dW xZ Y X W  T0v\jh L>h /a0 :xRQwx*R10wx*v%vwxF6l vd6k vd6j vd6i vdvew% hL I0J0s*caQr .: r Ws*r lr E r  N0r j0R0A~ Q0V0OxdTq .: A $q q q Q(q  q p0r*^"IL  Ly*}*@+F+r*$LK+ U0Y0N,hT.: o .P BBo mo -(T Oo o  TP0K0# "Failed to change name, %1."X0p*AkeS.: N.Pp*BBS ONN [0! "name change has been disabled"SZ1Z0A=6' ]0. "Invalid Nexgen command or parameters."`0b0a0' "Failed to execute command, %1."d0 "internal error"e0# "Failed to switch team, %1."f0 "spectators can't switch team"B0g n1 a| [m `*^*\?zw\*\&<g C g acm \\A) c0@o0}o`-\ }-F-\ }a v{^ ] f}-|] |}va v{^ C|!v{ g0- "team switching is disabled on this server"k0+ "you are not allowed to change from team"l0 "team doesn't exist"m0 "you are already on %1"x0e > L-b t!B4-b e d tJCd te * M1idi  id*f*g*o* fi$p ?wp *p $iq*p p AU i0n0( "this server doesn't allow spectators"v0w0@@xf f'5f rx*\3x tf  z0@@b*a*qg^Ha*rHe_*HQ Hz nameHX Hz titleHw  Hz ipHE Hz idHA  Hz  countryHqI Hz teamH t0! "all spectator slots are taken"|01 "you do not have playing rights on this server"}0 "all player slots are taken"H~0% "Failed to balance teams, %1."{0[*peX[* _Z*]wX*[ Hknamen{[XQ[[ Hktitle{[XX[[ Hk country{[XA [Xm[ Hkteam]{[XqI[X @11 "this command is only available for team games"B1 "team balancing is disabled"C1" "the teams are already balanced"XD1# "%1 has balanced the teams."F1! "%1 has started the game."A1U*@sjF .:U*F WT*F E F F #F  G1 "%1 is READY!"I1' "The game has been forced to an end."F r0O1Myl  lV*W*X*\* fl$-N-c*MMM-Bq ?wq *-Nq -_ q $l]*q q A L1X1XU wq*qaq* [1q Cr{*,z, lzztl&flzl&olol3zz&6E!loq 6D!lop 6C!loo 6B!lon {q p o n  A "|"Q1 "keyname"R1 "keybinding"S1 "set input"rT1V#$lA Keybinds'$',, ,  Balance teams Switch to red Switch to blue Switch to green Switch to yellow Suicide Open map vote Open control panel Pause gameV%V, VAbVA$VA-(VA-'VA-'VA-'VAVVAVB h0y IE 0d%The game has been forced to an end.pwp*p-pq!Hpqppc-'-'Ba/!e.@@/a0 y !Yy J *10 U1mBS m%m,nkeynameSm{nKkeybindingnV %V , DKV PV AnV m a1R*YgZa EZ\"R*Z["S*ZZ"ZY"ZX"ZW"ZV"ZU"ZT"rq*qZe\ qQw\ D*\ \ D&\ DZ u1N1@"0' i1s\i@!L>@!/a0 :{RQw{*R10w{*s%sz{F6E!so6D!so6C!so6B!sosez% W1RDuRRNP*{N -Vp~N,dp%UNNUNpNNp},-V~RU%-V U]1g1Q*ZQ* $-G 1$-t F$-J [$-J p$-s $-P ' @`1D\1q/DqG-:G,wq*qa/!I Z .q-R vZ vA-(-R(-RvA-(Z A-'vZ Z A-'vZ -R'---RvA-(-R( ^1c1 @p1O*p{ZO* !$ [ EVENT ] ;$ [MESSAGE] U$ [ SAY ] o$ [TEAMSAY] $ [ PMSAY ] $ [ ADMIN ]  [NSC-SYS] n*d1N*WrkeynameSN*-R {rEvAvPGrvPvA-(vAr-R( M2e1A~ k1rf1h1EE;e~keybindingEMM*1{MM~M,{M%sMMsMMMMM},M~~s.M%~p~M~M}s.z~M}||~p~M~M}|>set inputE~ l1J1 "Root Admin"q1WbZQ Tr*-Y :Q %pQ W!x r*-t  rr*YWQ wr*r\WQ  s1vF:P-_3:4&:]%3:4,x%4$.-(.` `NN:4&:]%4$x:] y1r13"r*(  m1DG)%h keybindingD[~t,%wt~t,fwtz  h h wh pph |wset inputDh  v1n1C K,' w1H( J*`N' o1 "Spectator"L2y[ Fyj:yv@(X@( yn?%v@'X@ry*RA!PyB A!c A!^;vv@ya ?%SyI?%<A!P A!c A!^ rL**X@yI?%$ry*RA!PyB A!c A!^ x1, "The server has prevented you from dying."z1@C |1{1/ "Unable to send message, you are muted."s 1 "Account type %1"A2* "%1 had a team kill attempt against %2."C2 "HTTP client error: %1"JF*G2V E2 "[NSC-SYS]"X2\Bts r\ws * y!u[s [y~;~s ,d;qs s 9$*The server has prevented you from dying.'>x,wx%*4x%B\[yz'xNr*(rB\[yz W2|o`-s |-F-s |x mqu t f|-rt r|vx mqu Cr!mq J2 "[ EVENT ]"{ @P2@Q2@N2 "[MESSAGE]"S2 "[ SAY ]"R2T2 "[TEAMSAY]"Z2} > L-z i!B4-z } | iJC| i} * a2q G9^rD Lw^* A!u[^iAq _s;_q %;sq^^9$*The server has prevented you from dying.LwD i"- wi*(ia/!{ia/!e 3:D :i^I<X L;_q %^a <~L-j d(%1 had a team kill attempt against %2.iD  i~,w~%*~%$Gq D ipqA~Lw*$Gq D ipqA V2 "[ PMSAY ]"{~ f'5~ r{*\3{ t~  V1 Pj hnH{,w{%*{%P A!{lw*P A! Y2 "[ ADMIN ]"U2\2 "Allowed to play on server."^2 "VIP slot access."_2 "Admin slot access."l2@bWF-u&@`@?5@@x?&@@x@`@?@`-b':-CC+team switching is disabled on this servert-GCthe teams are locked@-yC)you are not allowed to change from team-b'\-b@j:@@cYB,wB%*B% b@B@z=@j^@!Failed to switch team, %1.C  22Ab2?mes. ?,?, V#?,?,A c2V(4 d2x)4<d.wd*Qd-f wQ*-fwQQQ-QQK-f.N-x) `2 "Password immune."y2]2^3 h2@i2@j2@m2M\&+OM]M?M]-i'-e'-Akname change has been disabled-i'-iEM/M/M4D,wD%*D%\ME-eD-e({EMd)%1 has changed his/her name to %2.EM/ M)MjM/^M!Failed to change name, %1.k n2U[zBWUUDCQUUFd @F,wF%*F% [UF\d(-%2) %1U/U{6 %1 has left the server.U/-G-] w?*:4,:d %U-Fserver{:d %4-_-^:4&lSUa E3h hCG,wG%*G% hh G'-C:4,-_h Y$JThe server was restarted by an administrator and has been reloaded!'h C$4The server has crashed and has been reloaded!-Yh c$TThe Nexgen boot sequence has failed, please contact the server administrator!:4&fh  k2g  4.0p2 6.0q2 288.0Ar2?#Xg . ?,?,@. ?,@A?,@-'H@@j@ s2w)j >* h?, j H8j j @-f'g hj -f@#Aj @ A@A@g @w)v)t) f2 "Can be idle."u2 "Game supervisor."[2J!H 9kJ!get Engine.GameEngine ServerActors-{~J!.UTPURESA"%-{M 6%1 has been detected, entering compatibility mode...UTPure o2q)x2K}' t2s)l _ s)r) v2 "Setup matches."|2 "Moderate."j*{22yo @3A3K*~2es:rI* W NN|W ]jeIW ]W ]a/!FI.;W ] seW I }2 "Ban operator."IM3~V~A??~>~-Fa/!_-G-[>-g K,$K.4~~/K_%-g'1:~K~ z=K;Kz~j:~~c~-^ ':4,~-F~n<}~~Fd K%^K,wK%*K% V~Kd(+%2) %1~/~{ ~-_-^:4&S I*B3p)!{` (`_^-] n Nn ]a/!F!|.;n ]j_-]'V.;n ]!p)lm^n *N, R le*R ?%R CV.g 4l@jg ?,@R N]V{mVjmVV#HR N%H@jR @NV C3 "Manage accounts."Z3I!Cr*,~, r~~tr&fr~r&urur3~~&6]!ruI!6\!ruH!6[!ruG!6Z!ruF!I!H!G!F! Jc#/a0 JwJ*10grJ*CRITICAL EXCEPTION, Nexgen controller not detected.a ~J-Ba JLJ4 JLoading %1 %2...n)aX|UJvJXJ@ J&Failed to register %1, destroying...VaJZJB J(Failed to initialize %1, destroying...VaJlJMJq a@VS3kDVHv-_.-:4%4$`JrkwJ*J]L,wL%*L% VJL'L,wL%*L% DkLFw* Dk H3 "Server administrator."A. 2.0];O3 0.70X3KW7S&r?K?KAT ?-Z wT *rT AK-Z'T AKAT T A1 E*G3Ym -o  Q NE|Q ]jY-o 'Q ]a/!F-o .;Q ] mY-o @Q ]Q -o  ^3|Nn6F!:|:[|['DB:|:\|\'D( Q c3nU".Wnnana C*T3m)3$<L%:LNL] 3m)L a3`\pY!L>Y!/a0 :RQw*R10w*`%`~F6]!`u6\!`u6[!`u6Z!`u`e~% R3 2A*Y3l)L#&<M%:MNM] Ll)M m3}RU2B}V}V'@>}W}W'@( )\3k)<8G*FN%DNNN]<k)j)i)N ]3N4`3A~ N3 "Ban registered players."l3smq~f-r wq*O|qR"s\-r'cqqQ" -rqa SqR"s\qQ"~~qsDq {)_3h)TI,AW%?WNW]Th)g)W b3 "Hidden admin."e3( "Press [Fire] to start the game."qr#K',T j3,Nexgen Server Controller'$versionU _,buildS U# $Copyright 2006-2008 Zeropoint productions $d.scheerens@gmail.com $Development'$Daan "Defrost" Scheerens $Credits and thanks to'$Mickal "ATHoS" DEHEZ $Matthew "MSuLL" Sullivan $David "The_Dave" Schwartzstein $Zohar "SuB" Zada $*TNT*CryptKeeper $[BOSS]Snipes $ 6-k3*./"0"+","1*iy;*"غ-D@VdfwȽpnbZpÿnKNbnZXPXXSSXZXSKNKIDDDKXSSSSKICAA""A"A"AAAQY\[EEE"RRRRUQWW[W\))****BBBDDV[[enunuwww|~|~ddofpppp}}~}~~~}}pwpppfoîx~xwwwuGFFFFFFDFDDDDBBBBBBB***)*)DLKKKKKGKGGGGGEDDFSKJHe­ׅܹ{؎uy󬀣zyeyTXczzUcUQQQGEUQGGEB\\EGD"QURUVBW[[[eBFLV[gxKѾߎþЮߧڧ~ߎuwuwZeneeewLVVVRVTLLRLGgLgvxvWg[UKD[NJ5.fzÎǫ|unSYyyxUcUQQGQEQQGGEA\\EG"BRUTUWAW[eggDELR[euDìwЬо~~йѐuufw|Teee[[uLVVTRTLLLRLFWRexg|vxU\WRKCbJ.++wأɰǨ⺩ynXUyczT\SQQGQAUGGGEA\\EGQTUUWWBU\eguBDLR[guGì~ЏߥϏڅϹ{~ufuu|Leee[[eKVTTLTLLLLLFWL[vgxxvuQx\VLI*N.+ 嬰ΫǯۯyXXXyYnzzYITQQKE"AGKGEAA\\\IARUUTD"D[geT))LRVefDg|оw~Ў؏o~o徧Ⴥ~{~{wKnefdKFZZWVVDFTLLKKLKKB*KK[|gKTxxugKK\[TKC(H+#װɴۨnNDSNybyySYKDID"GECAI"DKE\[)DBAKFA"VRKLKBBFFNK.),JNZd{zw~{~}}ϊ}ϊ~}~~ஹᮏڎp~~~~DFZVKVVDKPFKL.BFKDDKD*DKD)TLK|eTuXFTYKIKC+! ⯫պPNIHrynbXX[SKDC"EDDDA)DCIICL"CC*,"JHKLKNDY)DD.# '44}d}oϊ}}ooޫ}~ndn{{~XVJKNLPLDHINKKK*.DD.)FIFFDFLn[ZTKFXVLKID., Ư믗PNP,bbbXXNSNIHC)DCCCCD)IHIC.! DJKN.Z).F( #334P3'M^s_qdP_}omϤZ~tmZtLoorKPFJKJKMDFJFJHK,.DD).FD5D5DZXLNLSJLKPIH).( ӞƴկėOJM.N_PPPMNIHC,))H)))!C!D.  ,HFJ.P(,D+ &'&3mts&''''3#4Mh}sP_}PoiPP}mtttmPpNZmZ9K.JHJHF.HHFHDJ!...)(F..*.DNLNKKJHKNHFD(- ŵʖ쳳ŚҴėՙM9H59PNNNHMHHC(().)(!)(.,$HHJ,P!,.+ &&&0trPi&0'0''31'1kPsOis}sOdPOt_ttstsZ_osNOPJPPZ9H,HH5HH-.5...H!,,,).,,,,,NJIJJF.NHJH,(( ִĖ՝֞řėiaššęk_55+5PNMJ5HJH.!!(),!(!!C(  .(((N!+,$  %&&OJPO�''11114li}_is9ssssiMOPMimtPiOmmmPqPOmMMMJJPN.,,(-5.5)!(...((!(,,,+(,HJF.(.5JD,(, 읖ֱ웙⛞ů띙_kikՠ떕kP]M55H]P9HNPJ5)! !!,!)(!,!  (.J5.!!((    qtt;'0# #&#&&ii}ssMoiiPP9JMmP}imttPP_mmssNJPMPPJM..5H+.(,5H!!.!+.,(!,,!((!HF5,.,NHHD.,., 얞䞳ĕ䝝֞ijį_엛_ii֙ęՕO]NJMH5PJHONNH$  !(C()!!!J    HD.JJ+,$  &'s4'1#&0'#'1'4_08hPOPi_PPO9o_mssoJqmmsqMMNOPdH5.5HH(....5H!(.,-H.,+,!,..JI,JNHJH.(K,,$ ힳ쳳䞖❛k՛ճPs톙ik_k뙝ԝ]OMJOH7MMqNM;&  !(,((!!!D$ ...JM+(( %&0r}0'#0'0'111<81'0#8iMPsPPOP9}PqsqsJqmmqimMNMNPm55D5.J(-....J!,,,,.,+)+!.(.JJ,NHJHHD(J.,( ųijl䝛kӗʝPqq흗k_햙ĝkkOOOMN9JM_M713&  !.("!!H(    +..HJ(+)$  %&0tts#&'01''11hJOP0'0'00';iMO_PPOO9sPsoqqMdmqmmMJMNONmH.5.5F,....J!.,,,,+,+,(!,).JF.NMHHH.,J5,+ ų䳳kձaț_iqq񝗗ęi_9P]M]JMNJ6444&  (,((!!.) $,.H9(((( % 0siN9&&''1'4'4lii_OM<1'0'#0&0&'5OPPOO5d_qosmqmJ_smmiMJJNMNPH.5.55!(....,!!,-,+)+)(!(+.FM(PHHHH,,H5.+  ҙ쳳͖͝_䁈PsONqq_kkęP^_^OMMMM_r^44;   !,((,,( ..5!(!! #&0PP<'0&'111#114sssO410&&0#&&#&<9OOOJ9PitiOmoPimMPmP_ZJ9NONJ_+(...,((..!+.!(((((!+)!(.J,H,HHH.5J.J5+$ ųŴֱ끖sq_m_qaikaki__MOMM_kk6;1&   !!!!C,) !,(5+!(  &0&mP}q8''1 &&000'_s'10&000&##%0isPJJ9JiPsPmttiPPmmsJJPP_JMHMJNPH(!-,.5..(,,,.,((((,,)(!..NJHHHHMNNMHM33  lij񗁈sqsq񗖈sN_tkkkiO_]qkqa44  !)(!,,,  (J5(!($  &0&tPJMNq301'0'''1;s4000&0&&4osPMMJ9___sostMmm_qoOmPPJNNJMPN.M!....H!+..,-.!((+.(+()-(XHIJJJHiP__]MM3   ų䳳䳖qsqis웗ti_웕k^q^_q]kq7%0   (+(,),  H(-((!  #&0&HPt0''0'1141^Oi'0'&0000&&OioPJM99dPioqqMd_m_mPPPPJJPHPON.J!.....)-,,,,(((.)((.(+NHJJMMJbŝ>1 ű󛖳lkOOPOP__񗗁i흆iaiakkklkkak>;>^i_MP_k_1  !),)  5(-  &&MPs0'0&'1'1#14h_O1000%0&0#OM95555-_$8simmtMPiPPsNPPPH55J5D9(+!!(!((!!!!!!!((.,.5HJMk__^N;7&  ŝlkikMPOPPPi񗖁is헖a_aiakkklkk?;;:a_MM]__4 !)((+--  q-&0''1114lsOJJP;000&0%'OO5555..i9#&Ji_mJNiPP_JJONH5HJ5.J(.!(((-!(!!!!((!..HJJMqk__^^]60  ӳ󳳚li__9hPPOP_s`>>:?]M^qiOM5 !!, -!.-   & O}M90&&&0'1141isO#00000%&%5OM55.55.O#%##'MP_OMP_MNPJJ5HJ55.J.(++$.!(!(!!!(!!(+!5,9HPkkk__kƝ?1 Ş󴞝liMOMsOPPPsʗՁk^OO^_kkla``?`>;??]k__aN5.J   !)()+!5+ &&OPt4&'&&'1'1#16is}}<##0&0#&&&#JMM555..9'####-PiPOJNNNMN5J5D.5M(,+)+.((,+((!!!(!((!!+(!,HJHPkb__]7&  llkOMOMP___˖▖P_]MM]ikkk````?^?`>;;kq_PM.NJ+  (!(! $!--  %%qZOJMt}&0&0'#%&1_s}4&0&&%8J9O.55.5-##&9POMMJMMF5J5.5.J,,,+,5(((().((!((!!++!,!,HJJkqq_]M6&  󞝝l䖁____O_iks՗՗얕O^M9MMai?;:;`P]NH,J.5    !!!!5-   &&m9PoiNi&&&'%&010#1^ssi&&%#&%&MMOO55..9&JJJJJJHJ5.5.J5,,,,.,(,)+(.(((()(,+!!,!.JMMqka_];;?1 ų읖i_OOOik՝욙lks__hqƖjj^??>;>?kOH.+!!(  !   $HO5..+  (5JJJ99#### ##%&&<sis^'%&&&0#0&#OJMJOMOPM &.HH55.-,.-,.+!H55J5H,....D!(.,,,5.,,!,,(,..M]_q]OMM] Ğs_iŠĠ띕k_q흝`^`>>^;;_.)(!! ,  $MMJM..    .9FJJM+ ###%%&Oss}'0'0'000&%&%9P_PPimii0 ..+.5D.J((,.(!$.HNJJJ,HJJH,N.,HHJ.HD()H,H(,+,MPa]MM;_$ Şlsl̝q얝Ԝj```?;6'5(H.(!)   .MPMH-   .9HJ9J# ##%&&isiss_00&0000&%&&#P_PPOmiP9#&   $59J+(-9...(.((.PNHHJNP..FJHNN,HHJH..JNHH,(!(O]Jk_MMa5& 鳝lҖř̘j^j;640&M.,)(. !    PPPMH.     +55H9J%#%0_siP<'1&0000&%&&'_PiPOoi_&#% 59HHN(J5..5+(((.Pm5JNNNPHHJJNJXJHNJDHKJNJ.(HJJPM_kJa53$̝͖qⳝj`443&.,,((!)$ !   MPOMJ.   +.J9J.'POOi'00&000&%&&%9_PiOPms8#&# $HHH5J-....H+!+(.PZ.NNNNNZ.NKMJX.MJJ.HJNHJIJHMP]kaaJ+3 ՞`k볠?;40& .,()!,,  !+   5MOPJH     +++-,+  '_O9_O0&&&%&%%#%&&PPiPOPiM%%%  #-HH5HM-...5+5+!9NP,NNNNMZ+KMKPN5HJI,NNJIJJJHJ__PM5+ŝj;ik❙j>;: 0 $,(,,!  !!,   +H_PJ5  -HONP-% &%&&&&0OO?666&1141#009sim_P'#&%  -.9HH5J(..,$ $(-.MN,HNNNNZ(NJPJX(.JJ(PJIHJJJHM_^_]5.$ҳ?;6iƝՒ`>74&%  +)((( .)   $.k_P+# # -MNPO-##%#&&&0&iis4441144110%'smidiO%&&& #.,(55J5.+($  +!.NNZ5,KNJH.,NJNJH).)5DHHHD(.HM7MOM.( ųš̓j>;6:ŝę>64&&& # !.)  ,!!C,    ,MJ5.   JOPOP'&&0&&}^'11&412'11'0_Pismi_'&%#  .9MN,.9.HH5  !(NPSmN.JJFPbH.HDJN(NNHD.).S.,5Okq_]5+-ŝšŠj`?;664^⛛ij]0&& & H)+)!+  ,.D  5__H,-4(-9.4$$'JOONP### %&&0&4O84440%44111%9qiqi8&%&#%# #JJJJP.5HH5 (P_NNXZ,PNNNb(HJHF_NHJHH(SM,5M,___PJ. ҝl鞗֝Ğ֝j`j>>>6644;ŗq0 #   .,)+(.  +..$ $-5H,Mi_JHN_.OPHP55M59Odim9-8''##&0&8_44644064441%tims%&& %  -JJJJP(H5.#   ONNNPJHNNMNX(HHHNPNJJMJ,PN.JM7___].+𱖈ih❚қ͖`?`?>;>6:64:kPtqq9#  ++)(),   .C+..HIH,,,.HN__JMHJ.HMJ_5HMJJ-...._mimmi;309_9OM<4444410%&%&8si3%#% % -JOJMJ(H5    #HNNX.HNN_JX!HINJNNNNNM5bNMMJ-P___.(յҵŴhӚkl??``?>>>;6666:kaNmbPb  (,(.$ !.),)HHH,H5HHHN__NMHM.MMHP55MJ.5JMMJPimmisOs}s&64444&0000#htsO%%&% 5.JJ9MJ,($   5NP..H_KHN(.JJJHJPb_NJb_MJ55__aM,+ ҴŵʵsՈ՚s֝``jj???>6:868OPqJ_NMM.    ((( !((HJ...,.IJIHJNP_NM._.MNJP5HPJ,JJMJJ5osi}Oi&6464400000&mi'#&#&#%-JJ55H.JM-    +ODMNJ.JC.H5555JO___J55NMaJ5+!+ҵŵŵ䁁Ӗiӗ_՝j??>:`6'3__tHPMNJ    .)!!(  !(!IHHDH,)HJJJJKM___DJP.MNMMH-.+9JJMMONJiosPtsil;0&1000&8sO]%##%& &&$JJOH5.HH-    5.JJPN)-.DJHX,MPkėqHOPa^M7M5+ ȵŵݖklsՈ̘j`?`>40&3ZP9NNJN.%   .(!!+ .,HD5HDMHHIJJN,9J_MJNP.HPMM(-9.HJJMMN55559is}ssi;4000&_sssiO0#%& &#& HJOJ(JHJ.   N.NHPHI5)HH.HN.NaՙMabaO]]M+( ӞҞҳ◖՗k՝jj>:1&& 4PbMHPMJM+  (!!!!($(!+HDHDHHMJDJJKN,NJi_JJP.H_JM.J955JJMMO.NOPPOOik81's};## %%%% MJPJ9JJ5#   HJHHOHHJN,..C5N.Pk]_MMMN].($ ų֛⚈ț?:40% #5PiJJPMJJ  !!!!((++HD5DHHIPJ,,X.HMJq_M.b.J_HP.M5JJ.Omi.9OOPOih__sOi&##&# %&#+NM(-MHH$  JJ,MDHJHM!,..DH.O_MJ7H^J-+$+ ҳ⚁֝llk֝`;:61&&5PM5HN5H+   !!-!.D.DHHDP.,.,HIJNk_NHH9HOMP5J9JJ-..-JOPP_iOOJOiiMMMsisi_s8% ##&%%-55,5(JJ$   ,5HM,(5DH,,!),.,MMkM7J.57M]53++& Ş֝ųŞ]i՞j>6110& %#JPiHJHHJ   (!!!($,!HDHJX-HJJH,JNq_N5N9JPMP5M9J.9JMNJOOP_s^issssiiii0#%#%#%%#H.MJM.+-    5J.DJ(5)..D,(,.H__͝PJ5..MJ9754733 ҳ̳֞;<ݚ靖`>:4&&&%%%#MNs5MJF+  !!((!!.(!DMKNHHJIJJJHPq5JNJJ_JOHMM55MMMOOMOdssOlsssPss8## %&%&-.MHMHH   !J.,H,M(,,(H!,.MMՠM7H5]5_JJM;];7: ҝj>::_kśkk440%% %##$MmJJM9H# 5!!!!!!,(!(!(.MIJJNN,J^NJNNMJ_PP.95HJMNONPPJPOissssssiP_P' %$+5MMHH-    -,,5,.D(( .!)5J]PkkJ593M_J7J]^a>̓j>:6;llhkq<& %##&NOHMHH5  (+.!!!!!+-).(HHHHMJJJN.HP_qNJPJMiPP9MMJ.O_OPPMMi__ssssoiO_9#%%% O59JJH.    (,5).,. .H.J_ab9M55]7559]a`=/ j>;:6;hs_OMlP4#%+5MHJ5H$+.((,.!DHHIJNXXPXHNPikPNPNPqN_JPMOJPsmqiJ_s_kOssqsmMdPM9##-PM.OMJ#    (.).((  +(.JPk͝O7J75--.5=6/ `::::8^ihMO^m9PiO&-MJ.J5,-!!($-$+!!,(DHHJN.H,H.JNPqqbbJPMi_rM_PPPMOMJPiissl_P_siP_Ossis_isismPOMOO9' N_J5((    +!,(( (.9_͙k^MM5+((+35]aj=/잠j`;6:6:64Ph9M;MsPsP&#&#&%#MHMJJ.J.,+.+.!,(!!(!(!!+!!,HHIN.MPNNNNPbqrPPbNkPiJOMNMM_ONOPPiisl_iPkOii_OPssidisi_iPiMJMJMO_OPM__.M.   ++(!J((   -.MOPM,+!!(5JM^k=ɱŞ霓jj?;6>>;14_sPisM59O5% #  J5-.,!NJJJNJ5q5D.H(ND.5..(,H.+5!!,.H.(JJHHJ.JPP_JPOJiMPPtl_i_OMOOOOM9O9.---.59.-JOJOM5### (JM,,.,H(!9__MHH+NJJM_akkj>/ ɱšճųŒjj``>>8:::10'OkPi9599O.#  #   3!M-5JJPJJN+sH.D..J..,HJ(()M,5((!!),DH_JNMNNJP_X__NsPiqPhiMOPOP^O5JM--,.5-55-.5-M5  (.9)(5,5, 5]kPkNHH.),HHMOaaa?6 ۴š՞ųj^????>>:::410&%Ji_OM9JMO-  #+O(555!MNJNJN,bM55.5JD.HH5HC,H.5J!,).D.IJP_NXNNPqiqrbmtss__M___OPOO55---9+...-95.-+ !.5+,5)5)  3MkʕaMrJM..,,HHMN_ka^6 ՞Şh;>??>;:::810&##8JOO59MO#   #..-+(9(-,JJPH.H5JOD,,J..J,JN5H5MHN((,JDHJJNbqbb_brrrȱȼҼsiP__s_PMM9J-,5..+.-9.9-5JH#   !.5(,H,5(   Ma̙kM7MM..,(+.HM_akkj?% ȵġ𞞠Ğk:>>;::::610&%#8_JJ^95JO&  #..-,J.(9.JH5HMNMJJM..JJ.D.JMMPIH_JP,..NJNNSPbrbrqtӲʼȪ}sqi_^s_OJMJ--9+.+-5.9+(.M.9    -5((H,5, (H5]^M_H5,,(HHHJM_= ݲȴŴŚ^?>:>;>;41&&#&$^JJO99MO#  -O9-9.-9H.95NJHPNHMHJ_NMHMHHNNP_PH_PbPINbbbybƪɼӴӼisPO9_OMJ.9J9+(..MJ55NOPN_-$.J,(,D5(  ++]_kkaJJH.,JHHMO_j=/ ɵɴҵҳl?;>>>:410&%#&#OJ9OJJMM# '5J999..-J-J5OJHNOJJMJqJJNNMJJ__bNbrkSXby˫ƻʺɼӱsi_9POJ9J9.55M+PH5JJNNbPP. 5J,,.(H+  (+5M_k̙OMMJ5.HHMNk?62  ޵ұ?>?;>:610&###%%&9OJ^J9O^+O59999M..M-,OJOJPJNJNH__MPNPNPrXbryƻȪsmiOJP_O.95.J9M+MOJJmbPPNi. HM.,.,,   !!-]kř__PMJ5JMMj=/  伵Şl?;>>;:40&%#% 9OJ^JJO--99O5-5M.M-.5.5_HMJNONJMNsNPbbrPXqrκdzk^?:2022216>`jݱs_PN5955.5J9J9,.!-JmPSNN+ ..J,5,,  !.]ka_PHJM_k=  l>?j:810&%#% 4OJ_99_9.9J95-95.M-,55MMPJMNMJP_PXsbbƣƇƝ`@2=/// 6⵴tiPON_9.-5MJ9.+J5JO.bPNNP555J.5H,. !!5]_MP]Oabkikj?/  Ȟj?:61'0%%##4iJOJMiO559MMP5595-,JmNPMJJrmb_rۯ˰Ơ==222222////////// 2似_OiO9.-9JM5.9HJ5NJHbb_HMMNJ,.H.   -_iqP_k_k^:%  Ӽұj>640&%%%&#8Oi9Js999JM5P99^..MZOqP_Nqmmsư˰ꢟ@@@=@=@@@@=222/2/22/2/  6ӽȵPOOm_P.559M,,.HJ5JJPJJ.H,ONMJHJ,(   !,9MkʖkaqkP_P_akk`:% ۶ɳ̢硜ȝҪ^611&&%%19MO_JOOO99OHM99J^.J_PPsqPmtꢟ@=22/// 2lɵqO_N..M99-9(!OJ.JPqHJPJHPMHJ.+   ,+-J_̓_ai__i_j^/  ת̟űյ<1'00%#10&%4MJOiiP5PM9JOM.J9M^J_mqqsqꢢ@=2  ?ȴss_s_5J5M..9,+MHHJqJNPPN5PNPHH      !!!(!+H>`jaOk_aqakŢ=  ɪšjŝh00&&%&#.OMMOO9O5.OO95O..MM9_PmsbȻ͢@=2 >ұsk1&&&&##8OOMMJOOMOO5OM99_-.M_isbst롑2/ 2@=2 %26:?h<;6:21& ^m_OMM9.59.5.5++9(,_PPPNHHH,((H,    4>`]O_ab_@:/ ȯҠjjj```?^??^>`ȴs1&%0#'iOOO9JMO_9OP9_9JJiOO_iqtԑ2%; / ;lȵqOP_99-.59.5,-P.JMJXiPJ5H..,,..)  (- &:``_kbkaۖꡑ=0  kҜ`>????66>>><>^j?>;:6'6Ossh#%MiOOO_O9iOOOJJhMOM9iMO_iqʽ̑2  4ռʴ_Mq_O.5,55,,+OHH9HNOHNJH,J..,.5("! ()!( &:jj`kkȖaa;6 ɪȴj>::::?^j?>;:44144:ssssh<}<_iOO_MMi__MMMi9_MOO_sȰ՘= l%ֵŝimOON9.5-5.,M!MMHP_HNMHHHHJKH5!(!!( .,++   4?`?qkk^]& j?::;>>^>:>8641%%&#%8}OMhPiOi_O_MMMJ9_OO_OiOiim͑/ aί յӳқibi__5.5+95,.],..!(..PMHFJ.(!+.!,(,+!!!(!(  &6?j`??;kq͕͖M950 Ӫ훗kœ?::>;``>4:6411%&&&&%1;ss_i_OsiOi_OOiOOMJ_OOiPi@ư&ȵұňii_q_OJO..-..M-5+5HMH5NNHJH),JH(,.!!!,,".04:>;:;]]ȕƕk_OM7+ }l֙h;?`?>;61841&&&&&&%&01OsiiPhsiiPhO_OOMmsPPiͼ@ ^ǻưջǴ?˯ƱȱŵʳʛŴŪs_riiJO9H9(._5H,59M.JN,P_N(.M.)(((,)(,!,,!!!()$  0014]J_kՕˆP]M5+ d훚šk^>:8161''&%&%&%#0&&&'PPiiOOisiPhPhOiOOi_Piiż= ŰĩͰ˕kʺůĪűҝŵűұsi__kiiMOMM9,+^.,55.M.HM..SHHJ5.,)((()(((!+!(,+(   +-M]MʖkkOOJ5&Tkl;6000400&0#%#%#%0%&&0is9MOhiP_hiPOihPOsii_sst=  ˺ƺůư;ƺƯŚŞiOOk___kNMM95-+P..9H9M(,+!,PJHNN.,!+(,,+(((  --..Oakq_J53 ZҞ_^4'#%#%# #4Jssslsisiʵ= ˺ĨįƯǰ ʯěk_lksi_qq_PJqJM]JMNMP,_PNJM),.7,+(,+5 -9.+5]OMO^___OM59-+ wlisii8##&%##OOss2 4ɴqũưůėiillh_tsPbMJP__iH_rPXJ.,HOH..((+!   -J5,HM9MM9__^__^J9.+#uν󲝨ĞOiss__O&# #-9Mis2 6˯bůęikkhh__qPkibOb_biJPXqbHH5].!!(((!-    +95,JJ5.5JOJP_^__M953e񯝛jŞkq___PiiPO4& &O99Ps= 6͵kqģņ_llklslkkhiqqsPiqqaNrqbrbbNiN.(,.)!((!!(!(    $H.(9H(+,,.JOJ^_k^_^OM5-&e񯛗Ş_OMPPPPO9ss;###OOJ9O}= :ʯkqqģįĩěl_kkllll_sPqbqrrrqrrNMS_JH+,+(+!+!((!!    -9J.MOJJ5D5H5XO9_^;^kM]M73 e񯛕jԙiO9JOMJ.miiPO' 8PMJ9M}i@ 0ɵƛPk_qk^illlllik_rrq_N__NINHH,!+,!(!!   995MOJNH,JJ.H9J_5:;;>aia_M;8& [jj^iOPO595-JPPPiiO-#MMOO9MPP_isӳƛqii_kr_kh_aklllliklir_PrXPPNM((.5+.  7J5__JMM5H5.,HHJ5406:;>lk^^]80 W`;6&-+_iPPPJPPPP9o<%8OMJ9MOsss= ʪa_iaqk^lklklhlqkiưybrrb_CNNNM(!(+!.,,(,$&;bMaqPa_bMONJJ59+ 10;>>>kkh> W񳛗^``:4&-O_P9NPOH.PPPM'OOOO95isssist Ũ_i_kkhlkkklkl_ƴrNJXPM,,,5-((((5,7O_kis_i_M5% #&00:>;;lkl=  V|h:>`j>61$5M9--.PMMMPO.MO99MOsssissqȱ@ ȯś__a__k^lkhlkhlkqİưǻǰbSPqqJHDJ,(!((((,535_kqk?61 & &11>:?>^kȕj=/  Vq?>?`^j?;40% 4PsP9MMMM5O_OOP9Mssiʼ2 ųkikk__kalkaʯƳƺۯPNPP5,.)!!!+((.PNMP__ęšj?600&&041>>>;`ȕ?6/ V퉆_O446:?``j?>:4'& ##8.9MMJ.J99MJ9OsssPs}֟=0śqkklalllaůƺ˰۴= krXbN,.)(!((!(!--H]MP_`>4&&1&146>;>?klꡑ=0  V_M013446;::410&%  ##4M.5J95559O_iiis@// >մėkkkkkkklhŰŜ@@2 ƩqPJDH,,-!(!!-..JJMO_`:1&&011::?>>aʕl=  Vq400&003&4110&%  # $9M59555..2  յ͙kkalkllkŴ颡@22 6bXMJHH,,-(M5H-++JHJOk`;1&%414;>>>>?ʕjj% V_M4& &0&% # %&  9J-9M55..Oois՚:  2śllƳꢟ@/ κrbPMJH(,-(J5-+(!5HJPa??:'& 444:;>>>>kkka`? Vś_iPJ3+% %   HMM-.999-Md_m_s^  ?ʞ̴= rbMHHM-.9(-,(!5HJO?j̒>610&441:;??askkah6&&%&46:>klkkkia^>> [qPNMHMJ+    +.-5.5-99-5iiPPmmil  /ěĚĞ2 P_M,.-(+((!+-HHJHMa?j瓓`;41%&&014^aakkkkah>> {kPNMJ.HJ...(  -.-(+(.4+9MOPiimqss^///ijĠ̝/6ɩq_P9,()+(.-()JM5_iq;??jjj^?61&0004;9skklkka^? [ʖqPMMIH.5.....,  3+((+(+((5-9iii_ss; 22/ Šĝġ̡̙̠̠Š;ƨNJ5,,+.-(((+MqOO__];;`?`?`>:41&33MiMkkʕkȖʖl`j%V_PJJ5.JH......,(!$   -P__((((+(+5mPiqt4 /==/ /ġ̡̡̡̡̡̞ > 6ƇmPMHJ55.((.99PiJMPiP::>;;>>;643;_bis^ҁkՖ͖=  Vՙ_OJ5.H5D.,...,,.,,$   J5H5O9-((++.PO_sst׼ /=@2 =̡̡ ;k ۰r_PN5..5.9..5_POJOP;4:::;>8?kj^>/  KQRTYDHN     -JJ.5JH_NNNPNJHMobNHJNMPJH+,.HMPlʳ2@`:222ƲPNMOMMO..99JO9O__kO____^P_klh``j```??>la]6&  GKQLFDK,   +-5JJMP_PHHmZPPPHJJNJJH+.5JMPrƝ;Ư 2@ 2 @ 6@2 l⼺sq_PMJOM595JO_MOikO_iqh^^>`???^````^?;:h^;1  GEB"FD$    #$-J5ib_PNP.5H.HJH,.5JNsql6ͼ6 =@=2 2@@Dz_P_POJ_59OM9M_O_^^?j=::>`?>>>jj`?`j??:6>?`?;;:?`>??`j```j^??:6;_<4  QRUUT**    ##JJPP_NPNNt5_qbiP.NN_t=/κ/=@2 @2 /@/ =k⼺m_ZOmMPM_kk>?``;>>`????j?j``k`>?>848aM1  QQRURQ"     MNHNNPPPbb,PP_bPOP_q2ۺtkijŝ /@=/  / @2@/㴼mm_PPaa?```;?``>j`j`?j``?>?>641_;3 QQRRRD     KMJ(NNNNPqHP_bmMHP_s2ɺ2=/ /=22/  碢=2 /@Ƕsslkk횝klj`?j>j`??`j`??j`?;;>>840M<1  KQQQQ"H    $JJD.HJNXXHHJNZPHO_PbȠ2 κqqij 222  `=// 6=ۺȗO_l훚j`````???j`???jj>;;>:;:40<5'  KQQQB.   +J.HJNHN,,JJJS5JJNPqɟ/ ɨiijĴ 22/  =/ `/aӯmiq񛕖`??j??``>`?^;;>;>>>;64<;&  G""QD+   $,HJJKJ,.JNJNP5XJMSmbӟ2k⨳ͳj /// ==2/  2כll`?jj```jj^?`j`?:?;>??`>>;^M0 GKQGAEFDC,),(  .,5IJJN,.MKJNZ5PJNNbqӟ/?ίƯ /22/    2 /=@2  ר񝝳󝝖`jj``jj`?>`?<6>;?k՞i<&%  GQGQGCDD.,),()()   .,DHJJJS.IJJNPHNJNPbr26ȺƳʴ /22/    /@꟔@22 =Ӳ잛𞝝j```j`?`?^?`h]̝k<0% GGQGQE)C)),()()(( H,5DHNK...JKMX.NJNPbr2ʺƯį/ /2@=/  2@@=// /ӯ♝񚛝j?``j```llŝl]0& GGGQGA)!)((((!)!!(C!.,$ (,D.H((,H,HJ,HHN.NNXr/ƯƯ2/2=@/  /222 @ ׼ӛ𛝝j```kllis֞l<4 EGGGEEDD.H(,,.,!!((!C.C,(!!.D5.D(5D5D.).HJNHNJbt2Ǩ=/=@2 2/ //  /^Ӽl쳞𳖖𛝝񝗗_^4  (.H55.H.!,..C.H,D.H.H,HIJNHJNbr2۰ƺ@@/    񡔟@4Ӽ֝䝝󖝝󗚝󛛈_Ŝ^6%  ,5..55N.MMJMMJ5HHD.N(HHJNIHNbr=kܺƯ򑔟@2   /  2222@@/ ӵݞ֝󳖛񳖛񞝚kh6% EDED)),)(!!!)),,D(),..CJ.HHMMPHNP__PMbrr=6򟡢=/  = /    /2/ ȼձ➞Ş쳳엗ss鞚`8 AAAA"   (!(((,C.!,,,D.(,.HJNNNbq˝@=/ /// l  ӵ֞֝l՚kklkslshOO_O̜h:%  AAAA"   +5,,(.5.,,,(D+DJH,JNXr@2/  2 /// : ױՖ֚lh:6::;:6&4&%%&1046?j>^6% AAAA   (H(.5H5H.!.HHHMHMJNbr̠@2 2/ 22/ %  ȵ՝❝Ӛh:::::641%%%&141;?袜``6% DAAA     !(!((((+,,5H5JNbj@a`@@=/ 22 /22// / ȼ❝֛՛l;:6:::41&&%0146>`@`:%  ,!(...-5..5HHMJMJN_?@ %j22@2/ =@ /2=2 6 ӵ֚֞֞l:::::64100%&114>`j`:/ EEGE,    (,((,+,,,(,,,.H5H5HNby==//==/ 2 /=@//   ҵ֝֝Ӛh:666:640&#%&116>`ꡜ`6/ EAEA!!!!!),),C(.IPb:2/ 2@ꢟ@2/ 2 /@@2/ 6 ų֛֝Ֆkh66666610%%#&146;jj:0 EAEA)  !((!!("(!,HC+DJSb6224/2@@22/ 22=@2/  ֝՝֗lk:6666611&&%%%11:>`韑j;/ QQQQC    !(!DHNby6/@   2 2@@2/  ŞŞ֞֝h::46:4400%%%&06?ꢜj?6%  "v\\\A!!!)!HNXr2/=k  22=@2/ ` Ҟ֛֞h:::::6410&%&%04>j`4/ "vv\QC    !!!(,.Prr2/= / 6 2@=2/  ՞ȝl>>:>>:>66414%114>``6% "UQQDY !!!-..+-.H]Jbk62kj  22=@2/  촛k>>:;;;;6441'%%16:`顜`2% "\UIJH5!.H5H.,+5!.!(..(++.($,-+(+!++5HH_r:/@/  2 2@@2/ ^ Ş֚֝llՖkklihOO< == 6/ / 22=@2/   Śśⳝݖ䝱_鞓^1 AvvcNCMH5NNPNNPN(NNNJJ!,(!(!,,.,H(!!!!!((.!,Nbra /@@ =//22/ 2 2@=2/  ̳ŝֳݝ䱝i֡<1& EIznSNIHKJKNNP,NPNNN+H()(((.!!!!,!!()5(,NZr =@/򜔑@2/ 62=@2/ /  Şś䝯ձ쳳kҡ͞<1/ AvvUQ[XSNNMNPPKNN!KJKMI!.()().!!!!!.((()5!,Nb 2=2 ꟔=/ 2 2@=2/ j  4ⳳҞijӛųŝk>1& AEACAvYXSNKHJHKNNI.HKNJ)H!! (!!((!(.H95.Pr  /=2;>@@=/ 22=@2/   ^ųk䝞❞>`jա?2% AASXSNHIJKH.).NI,N!HJH,,,!(,-,+!!.,N& 22/ j͒22==2/ 2/2@@2/  lŝ՛֛h>?``j̘lŞh>1 Avvv\\LSNNKNNNS(NKNJJ(   35HH!(()(.5MMJqbb> /22 0 /2@@/ ///=@@2/  ̞䝯֛k?`jj眔j`?`:1466;`Ŝl?0 Bv\c\RITHH.+  #   #HHJJ(+(,.(5HJ5bPq۝ /2/ / //// 2=2/  ҡ񳝝➙`?jԘ?>:01146>`Ԙ^1/  Bvgc\DU      ..HH(..5H5!.D,PXm/// `?  @2/ ˴ >󞝛❈>?`;6&0016;`^1%  DUQGBKN     JM(,.-(.,.H+5.P /2/ 62  `矑2/ ƴʺ 󝞛䗖;?`;60%04;`Ř?1 DRSx|DK+     $,HHF!.JMP_Mist: //     ꟟ꢑ2 Ƽ/ ŝ͈l>?`>:11&02;`;0 Dgg\\DU-     HHHHHM(MMOON(,Pb/ 6  @2 6 2ҝĝ❛k>`ꠓ`?:0&&&1;`k;& ETUUgD[5   #  #  HMJOPM(5.H5M5Jk    =@/ ۯ= ̙䗗]?`硘j?;10&&&6:`jlh;&  ELR[vFYJ  ## ## OJMHHH.JOM_..Pbt     2 ɯȺ=/ ŝ񛗈;?`ꢘ`>6100&16:?`?`>h]4#  EFEEEDD)      5HHHM5JMJ5HJ5)JNPmt6 / // @/ Ư?/0̖qkihhaŒ?>1&%&&04466194&  EQW\gQeX #  #### $-.HH(HMPONJ+5H5HM,.Pbt ` /2/ 2/ ƺ=/j;640&&&004141O5'  EWW\xF[Z+# #   # 3$(+,(!HHJMP-PMJJJJ!5HHHM,5i /2=// >=/ ˯ƺ:  ۴ę衘?:44000%&&%&3J4$  Ggg\xIeY5  # # '49JP,PH...(-PP_MJ!JJJJMJ!HHJMPM5imt602@@2 =/ ƺ2 jƵŝk<610&&&%%49-$  GxFndJ# '39M5NZbZ_d.PH9MJ5+5JJMJ!5JMMMN9NOOP++_stݯ/2=@2 /@@2/ ˯ͺĝikĝ͞_P^M8'#95-#  GGGKILIZb599H.PPDmHHdmbHMOMJ.,,((.J!.- 5N-5O55JM.M9Jmq2@@2   /=2  ȯ۴ 6˰Ġġ^?^įkqM_P55M.55$# "RLQXHX..!,JJK.HJN-5OJJOH.JKHMHqH.& &&JPP_PbMsPObMHO__ql%@@2   //@2 ͺƯ˴ĝ^O_ai:646>k̝tsm_OJ53#  "unnRB)KJCJJJJ(.J__NM(HJHHNPHNM-5  &&_5PPbiPNZiO5JO_o 򑑔=/  /2==2 ʺ6;44446?왈qi_P5M3  "WWUVLDH.JJJJP.5OJJMNJHF9NP.-& #%&& &4MbiPPm_mMH5JOZi}h4蔑=/       ʩͯĞ̝ęks_kki6410116>jĞ񛕆miP9M3  )eW[WV)FJKJONMK(JNJKM!JHJ.- &# && P_ZsP_dmMHJ9OPms k@2/    ʯ^6ƴŝa___6400016;`̠ﳯm_99-  *vwggVKNNJJKMJNHJMJN,(-#&##&&%&+is_ZJMPmO55.MPmstj2  > ΰƴܻ2Ưĝkakk<4100116:?jj`kk񝛝qO993#  )KD[xZVXNNJ,JMKM(,J.-$  %& #%3JMPPPmqPPN.9OJO_m&2  ˰̩6ĝęa_k_a6644404::>`j``?>;j񝗖iiP93#  *gRG)FeXNNM.HNMNNJ ## & &%% PMbmmmMN9JMPMPm/6/  / ǯƯƴΰ Ɨįękiai^66::6:64:>?`jjj`??>???`뙛񕛕i<4   *|xxuDnZPNJJNMJ- # #& &00# #5JmimqtPOH9MOMOshj  ? ˯ʩkaƕʠ̡̡??``jki]7&%  *x|xKdbXPNH5$ #&&& &# # mMmmqiNP9JMOsOs`?>:1  ƯƯ]㯣ʖi__:446666;4::>;>;>>>;:``^`?j^`kO;&  B||eF,(!,J# # %& &&# #%&MMoiqosOP9JO_i^s  6 ƺưƣ⣗_Ŗka_O;114464646:6::6:::::>```>jjj`h;' B||KZZXN.O$  %##& &39_mPMmqm_PO5OM_PiOi^ 2: ưįǺܗPNk̝_O_]N756446464166464444::>j`?^`jkĖ?6 Bx|ndPNJ.5### ##'9OZPPqsoP__m}_5MhP^msii k%%ʰƩĩbqbqb_ę^PMOPPMM7866:664664668:::>`j`^?ja?4/ Bu\[De{ZZPNJ- ### #%&#-OqoOPmqmstPsssi_OOMPiik 4:l˰ƨƨbq_X_qkřkM]P^__O^ia]>;6:666;:::;;>`j```󝛖k?6% BC{mXPNMN' # ##-OMmmqmtMPmqo_t_siOO9_iisOl >>0ʰP__N_bk̡̡?;`^jj`kŘ^6 DeKdmPNMP5 # #-J_oMmmmqqqPiP3'ti_59M;>60&00:?a__O]M쁖^6 F~|fNdPPJJJJJJ5JMJ-----.JPmiP9'%&&&#&&0&0%&0&&'_sOiOOOOOisssi_ss% ʺůʳ:tqPrP__b9a͕ġĠ`>;4:400&6>j]_OOMM__헗l]6/ F~||wwN....JJ9JJJ5.5-.-.-.O_PO4&# &%&&%#&&00#%&%&;OOMOOsi_isOOűȵ1 ʯǺŴijkrXPk_PNMPbMƙēa>;40664406?j`>;79M9i_]_Ę`6 F|wwwZKPPMH-J9J9J599-.-..-P_5#&%&&&%&&&00&0&00'%001sOPPOsissl? 6˺ưʰƺŴŴĴ?%ƩtXNPr_NO_q˕Ւ?;14&77464:?j`>:666M_____aį`6& FfwfZPVNNJJ.9JJ9559H-.-.-.9& %%&&0#&&&0&1&0&00'%'>;666616;^_aiaĝl^6/ IVLLKVNMJH95...-5555.-..+#%&&&&&#&&0000&0&0014sM_iOsMsi   `Ͱưƺ˴2>ȯqXN_MXH__N_b͖ĕk50&360404776014Ř`6 {VPbmqPMmPPPOJ'# #%#####'OOiiiisissO_m& /˻ƵŴƵҵ/ ƯbPNO.!+MMH]a_MMH$&0336 4666&366;:667^9kqakkah;4 ڃ¶t_Ptt9%## #####&<_POOOiiis_Ȱ]  ?ȴ@/ƴbrb5J.!(M^O]ak]M.N_,3444&06640041:666414__a^kkaa_^^;1  Љtq_mOP###%%%%%####&'OiPssPi6'iȼ  ۵ʼ2 2ۼȴb_J(.M,!(^M_k̜]HMNN_.5314033146474101040HMaʝ?1 ߏPP_o8#%&####%4iOssssOO1'08sssa /ʺ韑2 ǰtrqNq,!.M5H5ak렙j>757PNONq]446444447640& 317MM9˕qk_kJ^O]]7& ߬tOmts0&##%%##%#&OsssPss8&00&&;isq4 2˵ԟ@2ȭPPqNM(!.MM5Pka͙`?`>6&.bNNN__b_M6764467643&&&JM]9_aiPP5M9977%  ڷt_Pi_t<&####%%%%##&08isssM_sss<%0000&hiOsqi˻ۙ 1顔=/ ?ȰqiPP_.M!5MaJaƖkk``;>>4&H___bM__]6667>761&&H5HM-_OMP],55754;0 ­ioqssst4%%#%%&%&%%-OOPssssOMsss8&#00&0%0kOttiqiPttƼa  2蟔@/ 6ۺӼƯtb_PbPNM.M.59a͖j`?;:44&&J_iq7;;>??;4& 3N.H5.MOJJH-5..437  î׮m}i_0&0&&00004ilssiOsOi_O1&&0&&&%0kmit_smqsqiskPiMO_NqƩƫ˺^  2Ԣ@2/ %ɶƲrmPqHNN9H-_OiՙŘ̒`?;:400% 3M͕k_^^?j`?60&.J,(+95MH,(-53$6 ׹_t<10&0046:hsssiOs}0#%%&&%00%&1%&Oliiqmt_s_q5mPOP_ik :̟@2/ 2ӰZNm_iPH9MMšj?;:0 %014:ařk˕j^77JH,5H.+J-,!37  ~mPPm41144:^sissh&0%&%&1&%&&&0%0itPimssm_sPi_5PJMPqHbt0 2`ҡ̟@=2  hȼqmiN_Zi_MP++Pa?>?6& &6:>j͙ʖj;NJHH.55,(,.(!+36 描iŝh66:^s<&&0&%%&1%0&%&&&&<OPss_s_Pi_OHJJ9_OMq_ibb1 /226@``j`@@@=2;ȼӼȲmq_MZPMPiPM-.`;6:6&06?`˕ĝaPJHH....(,!(+-&7 ᥫsiҝ<ӼȼӼtqsq_MJPJPNi_5OOM_?61&&6;>?`͕aN5,(,-(((! 7 ᦹ}՞śil'&&%&%%#1PssP_OMsmmi_PO_OPP.+559HJ9._,_OJHPJNNibXrqλܯ<0  /4`ӵӼsqbiPPJiJMNP_M5O_k^;1 %6;?jʕkPH,H(!((.,(3ڃqŞֳ^%'0&&%%#%#3PsiimqM&%9iq_O_N_PPM,,9-M.M.M.HP.5JJJHMNON_rrΰȼțӵss_PPOOP_JbPqM99k_Ġ՘ki40 &:?`jj`akʖkM,MH!(+(,+!3 иsҞԳh'&&%&%%8Oqmid_d&%#9_JPPPMPJJ,9(5.55+O(M5,.M.5,MHHHNXyǻ˰ȺӵiPMP_PMPP_H..-._Ma;;?`?j`kk_].$ %3?^``j```>;^]Naka_PMJ,J.!(+(++!!4 ڦtűҞ^40%%#&%% #%9O_PsP_P4#%#8ZMOPMJPJJ..5+5.+9.55((.,.((95,HHbbNrbbɰƼɺƴȼ˱ƼӼȵtlsssOJNOO_PJPNN.8H]4114:;::7]OM_M-(% 06??^?>:7:66MMMJ_]OH5,.H,!(++-,(4ᥤmԳҞh:60&%%&%%%%# &MO_O_PPP8##'J9OJJMJM.-+(9(5-!.-(!,!,!+,,(..MNJrNyyűsimskPJPPM_MMPNM.(M&&0&&11003H9J](($(0 &067??;:6434647H5H9H5+!(,5!(.-5-(!3®揮sҞŚj:0&&%&%%%#&OP_OPOON955H9H5O!-(++!9-(((-(+!MJ(.bHJbbrbrsimPss_qOJMMMOPMPN-  %%$(+(](+.5611667?;6410040&5,,((,+.((+,55795,!3 sqiiiss䞝֚?:40&%0%%%& #9oiPiosmM##&%## 55JJ_HOH55(5+(]),!(.+(++(,+MC.NXbrNbbrrttstsslslii_issi_PPOO_OiOOM9HHPM_ONO$   !(]M9^_j;>667>>46314:4&H,,(!H.H.5,Mkk_^5+,(!3}ssss𱝛?;640&&%%&&#  &5MPiiPmi'% & &MOP9M,9,59O.!!(9(!-(!!5+!H,,NPXbJbbqbrPrrmqtiiq_sqsissks_ssiOsiii_POPPiOJO9H9PJM_NM-     !+9kaĕ`>646>>4444:775.,(H,HHJO._aqM-(!3ϧss󝛛k6600&&%-5.9PiPd_i&0##%&%## -N_JMH55+9.P!!!+5(((!((!(),H.JJ_PPPb_bq_Pbqq_qiPPiiP_isimsksissholii_sim__dMiiOOMM9HOPOM9PJ+    (-Mař`6444;666:>^MMH.((C,.MN]O.+!!4ϊsim񞝛s:40&&%%85599iP__m'&& %%0#M5_J_.HJ+9.,+J!+!+!-!!$(!!!)5.HMHNMNPNHM_NPP_PiP_PMOM_POPPi_iOhOOlsii^ssiiiski_ilsii_i__MO9OO99M9&OM.!+$   5];4114>:76;]MP^M,!H..Ha]kaH+!3حsh800%&%#999M5Oiimi8&#%%& #-NJMMM#.+9(-(!!+!$!(+!!(.,5HHJHJNHJO_MMNOO_MPMJ9MOMOOO_POOkPPhsiisOiksiOslsi_iqi_OPiJOMMM5'-OO+$5    4_ŕa;0311;::;kNMM5,..HMNa_7,!3᮸sllsh'0&0%%#%#1M9O99MOisq<0%&&0%%%% &JMP5M+ -(.-(((!(!,(.+.+H..95HJOJJJMMOMMM59MM9M_PiMOOiOPhiii9siOsitsOP_iJO9M4M9.(-$  &^M7&&03>;_]_]HPM.,HJ]aH+!4Ϯ׸sssss՛k440&1108sO^OOOM_i401111400%% ##9JPJ_M#  9.!!((+((!(5,5HJ(J5MH.OM_NMN5MOJOM959MM-.599POhOOi^OOO:>>?>>;;>01%-+.5+9!  +-,J,.5.((!5HH(!!+!-++.,-$,J5.-59---5MiiJP__i_PsslPl_s9i_hOJ^OMM99O4   $OO_PP_J  %06?kO9M+,7 +.JMMMM]bM59Ma_Ė_MH5M537 p~oiOOssաĞœjj?>60+5(9+9(    $,,9).(,!,(!!! (-(+.+.($!(--9+5$,M5OOP_Pi_POOk_ilh9OM<9OOOOMM9-   '_iPP_O5   %&0:^qaM_M9,+,7,-5-OMMM;aMJ7aę_O..3&7 pϮ}sOs록բ`;44H.M!+-    +,...((,(++$! ,((.-$+.+($+-7+-$+MOMOPPPi_Miik_PlslsO }ss_s՚lųŖM^.M+(     5,,J.+  ($+(--(+-+'+$+9M<99JMM]Oi_hiiMkii ӲӲl󝁚ksʳȞůjj`jj??k_OOM55&%&1114&  5(,H(.$    '$4-'  9;<88 #'#####  3333&$&$$ 3$$-+$(++599.--+(5!!(!+5H5NHO_a^;4 յ󝝚l񛗵ųͳ󝗙j??ahM_kP94016:>?>60 -,)+JHH    # &&'3  8888'  &#  433'  + $$-+.$!+--M95.--+7(!(!(.JJJ,HONPPP_aP;& 욚l𛝪󵳴ų󚗗󝗗`>>ak_M^99744:?jjj?:0&,-,.,+,   # &  4'411       # $(+++-M955-5.5$(,((,(,,.5JMJM5-3  ųĞlʳ󞝝󝛗k^^ak_M_]M:6>`j?:&35(,H+(.      %&%&%    +$+($-5MOMMM997,,(,.,)(,...M,,.(ŝҞ񚗛󝝨흕얕__aOO]::`j>4HJ(H,,,(             +-+(--7_aaaa_9_+(.,,,(,C.H.,,+$ 읗ȝ񝝝lki?7O.(H.!.  $$(+++5]kĕaP],5,,)((,,,C!-(! ҝšĞ󝗝ų񝖯񝖗kkii^_]6:^j?O].(HH((   +($+5MaaO.H.,(!)()(.!!(Şŝʳų񛙖kikq_O^466?ja_M.+9,(!  ($$++5;a^M.,,()(,()()$+ʳijʳ񛙖l_Oa<67;>`硘a_J..5,(( $$($+-MaO5MJHH!()+()!,,(ҞŞŞų󵝝񛙖ka_]k466:>`ԙk]J.7).( #+$(+9_]JJ..C5!)))(,,($šŞĝқŝ񙗖k_^O_O;;:>jkM95,.((    (+-]a_9HH5,,D((!((),(! ҳŝĞ횗kaOJM,M!   #(++-+5]_kĕa5.H..,(,DHHC(,((ŞŞĞĝŝŗ󝗝񙁗kki_M]_OM`^kMMH+,,     $(--..M^_^OM-^(5.,,)+,,,.!,($ ŞŞŝ󝝙ksakkkk_]PMMMk^akO55(@/읞ﯙkkaqP_qbiaPi̙kM5,! =2ŞĝĞkk흗q_MqNMqJOP_iiPJ+-(   3+-+-....J-J9HH5MHHH.)-)/ŞŝŞ읗iai얆iPMM_JJiHJMMPiqPaMJJ+!!q_;3   % 4^ǻܻq;/񗚖ikiPOOMJJ_N55HJOPNMJH55!- q_]M0   %% 6]kǰǻǽ_72ҝĞkkaiitPNO.HN_....HP..J.,55!bPM7&   %% 4]qq]4/ͳĞҝijlia_aaqPMOJHHJ-.H..H,,J.,..5!NMM4&   %& %8]^iyrrPJ42떕kka_kqO_NMMHHN5D5.D5.,...,D9)! JJ]-$    &%0 &8]_it{rr{rrtbNP7&/ŞijĞki_kOMJMHH5_...D.J,,.,,,J.)!JJH4$    %&&0 07P^bqstbbbbZmbbbXPX_M5 /ҴųŠĞękkaikqqkPMJJHHHJN,D...H,,,,,)O)( ..-.            &30   49^O_ibqqqrtrtyttrttPXPNPXPNSkNNNJH-$/k_^PaO^__NJ.H.HHNH.,.DJD+),,CH5,C-+++          # &-'&$&37MOMOP_rq_Z_bmtrqtmb_ZrNMJIHPSMJIPHJH-+ 2ȴġĠka_OOaO9JaNMH5H.DM,,..,H((,.(,.5!!((!($        %%  #& $'3&&$ $34999MOMPPMP_PPbNMNMZPZ_P_JH.H..,H..DM.,+$/弸ġššĠkaaP61>0&&&6                ##  #  s84&%%%%/0=====2=====2=>===%0 &              @ = @  = = =  = = =  = @ @  = = = = @  = = >_<$ /2/////2///2/    /2//2//2/2////2 /2/2/2 /  2/2/2/ /2/2/2///22//2// /2/2/22//2/22/2/2//_M4%          iM8&     s_<4&                @   # ) 5%2 =")%7&&'#,8(2;789ES "K &R)G,T1M3Y +d-`5d;s!-A)6F%9X3=I2>Q$aE\B^KdHhLpTjTlYr[uJkMpSmRsStUyUyZuYv[zZ|\|anhvezr|q~e}`^]_]niyu~ebedklmmabeejjjjkluuyurtt{|}||glqu}q3mSm-F'q?wq*wqmq-F-E qmB-F qmC-E -F Q-E S-F Rp qqA-E mmB-F mmC-E -F p SRQ:K:n:r-E O%Q:rRSp O:K:nn-F O%Q:nSRp O:K:rp :K w3t?/,(}tRttR'*(  f3B "Please wait, an administrator is going to start the game."o3K "Waiting for ready signals, press [Fire] to send your ready signal!"t3y oz  0ry /y ^y \ %-j '^ y ^y \%$e) Tf)a -P t -P Y[3 60{3OpuDv-Y'y ?z-Y wy *cwy O|y \O\-Y(y y A-Y Is3 4B4x V%+0}x ],x ]-I'-I-Ix d , -I-Ix ^ ,d-I-Ix ] ,d-I rSK#+ K@C,B, 'KK BK BKA 'K,K,K ',,K 6CK' Account name'K( Account title'K# Password'z K| K} KK ,,K ,,K ',,Ko%o,\o ez\oq KX$ >  Privilege %1 (not defined).So&oq -'oq K.$\~\ ,&on K Savep K Resetg.A KK,XK* Add account type} K- Delete account type| K! Move upz K# Move downz ,| ,} , gX} | z p n ML v3 20y3 0.5A4SK*f.Z 'HSl S Password3 Login request for %1S/, IP = %1S^; ClientID = %1 _S\;{Z# Password = %1Z~ WS-o'l!w g+Illegal login parameters (possible hack).kNexgenIllegalLoginDialog5-opS-o'l!v gClient ID already in use.kNexgenIDUsedDialog-ooSJK-o'l!u g Kicked/banned from the server.kNexgenBannedDialog%\J&\K -o-G{{%{ZU{SSD&S-F-f-o'l!t gInvalid password.-LS-F-fkNexgenPasswordDialog%\T-L-oSS-o'l!s gServer is full.kNexgenServerFullDialog%\RK&\Rn,\RrU-oS-FSSA-o'l!q gNo playing rights.kNexgenNoPlayRightDialogmS-o i,wi%*-oi%KSlgk\i`-oi%4i,wi%*i%^Slgk\ir{kS)Mk%\&\,\,\US. Login denied. Reason: %1g,S-_ nMNSIMNLogin accepted.VS x3f MsgZg*f , "{f  =v. g F v>f  =v(f f (Sf  Dz3 64|3J L&zJ  = z # J  =| # J  i} ;  #UJ  WGJ  qc %c ,^c  eAz^c q -(~E^~^,c q -GEc  p36 "The server has crashed and has been reloaded!"O4d)rv`]-u h,ShN %h|pA-u'Zh-uhN h|d)dNXOCShN  R4P o c'-D-DNP |$$d-D-D%NP `$P |}P {,P {-D'@%@,-D-D@P _,@-D ~3 32C4 "\\n"3K L`lrg*} -'| -'z -'p -'n -'(K . g} -K (&| -K (,z -K (&K (&Sp -(n -(^wg*L. g( JE4c)1~pc),pb),% @4V "The Nexgen boot sequence has failed, please contact the server administrator!"w2W!b nj?Fwj*jTW!X!jjA y,wy%*y%TW!X!yF G4L4Gy M %M ,^ M  eM q - {^ zL L ^ ~^ ,L ppL ,^ ~^ ,M L  L @wc5zo`-L!z-F-L!zQ!efN!M!fz-hM!hzvQ!efN!Ch!ef X4a)s\-w -F b ,b N a)bb |pA-w'j-F'b N b |b -w DK4t]$Dtz :rtg :z,Lrtp p - :z,L. g(0rtn n - :z, w~*~V=. g(z  G|  }  rtXX- :z, w~*~9Wz  G|  }   rt} } - :z, w~*~#I=. g(rt| | - :z, w~*~$J=. g((rtz z - :z, w~*~$J=. g(' D4 0a4_ s#"B,{B_ b-J-JB_ b, -J-JB_ l,-J-JB_ h,-J-JB_ T,-J-JB_ , B-J P4T4 :M-C?r~*~.> lw~*A' hS4`)3P 0,*:`) &ML H4L "The server was restarted by an administrator and has been reloaded!"Q4 1Z4`JX r`* CoxNXOCj-GsC` _,w_%*_%J`Ax_jw*J`Ax V4A "Welcome to Nexgen, type !open to open the control panel."^4_)thDSQa _)QFO QRQ Q!Q QC (QG~Q] V~ a,wa%*a% XQa W4 2yY4& "New settings have been saved."c4^)vMPPYP-y b,Frb%*-y'b%^)Mb-y C[4 3l4pv`t, {tp=-C-Ctp=,-C-Ctpq,-C-Ctpi,}tpW,tpW-C'tt%Wt,{tpa-C-Ctpa, -C-Ctpc, -C-Ctpb,-C-Ctp},Mp Ot%(z  tp}-C'tp}Player*t-C ~d4b4xH~V[-d A,{A]c~A]=Xc%|A]cQ||~ ||*~A]c&Z ~ GwZ *1rZ a  aZ -d'NAXA{-dUZ 7 #No replacement class found for %1~-d e4{iCa 4$x:j Aa/!_B=.-C-l -g-p -A-q d&a/!e-^.--_S k4M=set Engine.GameInfo GamePasswordUZ set Engine.GameInfo AdminPasswordUb sI [M :K:n:r:X-i set IpServer.UdpServerUplink DoUplink True9set IpServer.UdpServerUplink DoUplink False%_&_,_,_ `4 4y{rY #0VK C,B, ' f  B,& B  , , & Player name' * Ban/kick reason'X  [   Qf Q B,f "& ?  : i B , B, % Ban period'   , ,%e #$ Forever&e '$ 'x' matches,e ($ Until 'date' H E  Qf Q ?, : i ,, `C, ' `C, ' `BR. A  `BU. A  ,  ,  ' IP addresses' ',,e  % Client IDs' ',,| K  AddF  RemoveL  AddG  Remove].A   ,U  ( Create new banP  $ Update banO  $ Remove bane,|, X , [ ,H,H@'E,]RUKFLGU P O g%g,gegK%e-'HF-'G-'E*  dd/mm/yyyy hh:mm f4 5w4AP:y@~A.0@%` A@;` A` p` .LevelSummary{` 'w{* t4m y;0}m I,@-y'm I-y-ym H,-y-ym l,-y-ym i,-y i4{ K]Z]*{ ,"{{  bG. ] F G>{  bG({ { (v{ U -v,I j4 6n4 7Vm4I9r]*P -'O -'}P -(O -(O. ]( q4e O X # e  b[ # e  T -Ne  jJO%O,Oe-O:jO=:j &HG(H  JEG'E :j ,HG'H EG(E#  kJHG'H EG'E RZR*Me  l{MO~M,O%w MMw MOMMO},i. R F i>w IK-RC ,F-'UZU*Me  h1{MO~M,O%w MMw MOMMO},i. U F i>w L-UC ,G-' o4 8D5q-V-VNqj $$<-V-VNq]$$-V-VNqA$$<-V-VRqp%'-V-VRqt%'-V-VNq}$$<-V-VNq~$$-V-VNqX $$<-V-VNqR$$xw%w,-V-Vwqv,@ww%w,-V-Vwq],w-V x @B@K5v4S4Bb%hB-x '{B-x  {Bh-x (|B}H&pH- rBHBbB&!H%xHBb%hB-x '{B-x  {Bh zE-x (|B}H&pH- rBuxEBuBbB&E s4 9Mr4H0&kH+G &e-E,G ,e- z4|4 A)C?rY *Y .> lwY *A' h{4])3Xh,'%:]) ,K ]4 "[PM] %3 %1: %2"}4@5Gf=.> &e-pMH  ,e-pU DE  @4B5B|"1_. Rw_*|{_>\zh h _>|h pph ,_>_. _h  _@x4 'ssoffline'V5zs_ Hzzs-M'zs[NEXGEN] Another UT Server-M-Mzs,-M-MzI , -M-Mz[,@-M-MzM ,@-M-M%z_,-M-M&z_,-M-M,z_,-M-M,z_,-M-MNzK$$ -M-MNzn$$-M-MNzr$$-M-MNzX$$:zK:zn:zr%-M'zK$-M A5F5A34c. Uwc*|{c>\zk k c>|k ppk ,c>c. ck  c@C5 'sswaiting'QDE5zB8Dzg rzU  :g,U -c   X  {c Y ;mc BA  [  GrzP  :g,P -c   X  {c Y X^=. ](c BA  [  GrzO  :g,O -Y #f=. ](rz] :g,IrzR :g,F-rR*wR*e" . R>rzU :g,G-rU*wU*|" . U>rzK :g,K-e   e  de o. R F o>e K-RC ,rzF :g,F-RkR*F-'K-RC ,rzL :g,L-e   |  be o. U F o>e L-UC ,+rzG :g,G-UkU*G-'L-UC ,:g,za/!xu u % C,rzCeu CCYu %C%C,Ce-Cu CH mM5J5U/+r-s$-] -GQzn(@n(mI rm*(G-l r,l S={l -lPl =-l= )Warning, attempt to load %1 has failed!l rT-l(mi{m (mPm  EXEC %1PNP{Np> Nhopppppl ?game=I?mutator=Rl- Restarting server on %1l  @o(' N5L5D) zb# O5nca &Starting Nexgen Server Controller...::$*Failed, your server should be dedicated.a H-z(a p"a q"--}3First time run, executing default installation...I^  jR 0Updating Nexgen configuration to version %1...U _,H}5Configuration file has been automatically repaired.-]-C^D-]-C'-_-DD8-t$-] -GAServer crash/reboot detected, executing Nexgen boot sequence...-BU?-B-C'b 7Nexgen boot sequence failed, resuming to normal mode.-Y'-C-D(N; ServerID = %1 _O !-t ra bXM{-_.-(-{.&-Z -{x@a va/!_a }i {n%n,nN nZa Nlkx~ o -Fha WhXa? A' P5 "*"Q5 60R5 'noplayright'S5 'serverfull'T5 'invalidpass'X5 'banned'G5 'ssready'\5cn@ $-Qcw%}ck, -QcpcZ c.Xget Engine.GameInfo GamePasswordcb c/Xget Engine.GameInfo AdminPasswordc{P%P, PcWP-Q SY5 'duplicateid'Z5 'illegallogin']5 6U5 'ssstaring'd} -Snd sd d yd vd sd od Vd-Sdb-S _5 5rh7#*KA,',A, 'A,A,7DC 'W$ Enable Nexgen boot control'X$ Restart game on last map'R RebootB$',,k SaveV Reset7BD?,@'r7"77,7 A7 A7( Mutators used'X.7 A 7, Mutators not used'N.7 A 7 Qr7Q7 C,r7"77 A73 Server boot command line'q7N7 Qr7Q7 ,,7 B7 B7 A7 A7$ Game type'S7O7% Map prefix'T77: !Additional command line options'j77= $Pre switch server console commands'p7T,j,p,VXNSTjRyUTq-'X-' `5 4b5 3^5C yC , "{C  F -(C  F\)Y (YYeSleSC C  g5 2i5U!> L-R!d!B4-R!U!T!dJCT!dU!* d5@a5F UF ,"{F  M -(F  MZ)cZ. N F Z>cZ(F F Nx l5 1~4& "Match password received: '%1'"V!f'5V!r*\3 tV! v5[)jF*0.[)> lF' f5tTV(t r IS Stt. Xwt*t(%U . N F U >t>U (t(t. tbXZX*ewN*N-(N*s WF{s (sastJatN \tU . X F U >t>U (t(tkNxT  Hj  lp  iW- -tX- -s m5 0n5 'CorrodedMessage'p5 'Burned'br5 'Fell'k5Mt_S@V_% -(_ F[^P . XwP *P (% 6(P ( M\^zQ Q \Q pppQ , \P . P oMp  T -*.unrv{[MppM ?game=[{Q MppM ?mutator=Q MppM   j qZq )M t5 'Suicided'o5@x5 "debug gpf"[5 'ssended'U6ei % 9-_S:949&9-G:9d %eeF9-^-b' -b9-^e-Fe-ue-u'9JdL%1 is READY!e/ e9S 9v9VdL%1 has started the game.e/ e' u5 'sspaused'A6 "PAUSE"q5`b%`S@w`% -(` FY)e (ededT  d Th5$ "The password has been send."w5 'ssmatch'|5 'ssnormal'y55 0[(C?rh*h.> lwh*A' ~5J XH*;u. Xwu*u(%\zJ J Su(J pppJ , Su(u. uhXW-X-S@J   T   j   p  B6 "OPENVOTE"D6 "OPENRCP"D@6whM0CDwx :rwV :x,Tkrwk :x, wh*XrwR :x, wh*hPrwX :x,wN*N-(N*``rwN :x,`wX*X-(X*rwX :x, wX*n. N F n>. X>n(. X(@wN*N-(Nnn-'XkX*NxrwN :x, wN*n. X F n>. N>n(. N(wX*X-(Xnn-'NkN*rwS :x&brwT :x&Arwj :x& E6 "DISCONNECT"F6 "EXIT"I6 "START"hC6X)3^<'%:X) ,T {5X "You are not allowed to kick or ban players that have an account on this server."J6 "SPECTATE"K6 "PLAY"L6 "BALANCETEAMS"M6 "SETTEAM"N6 "NSC"P6 5rJ x#"lDC,@ }"B,xx Ax+ User interface'$x,J x5$ Enable Nexgen message HUDI x9$ Enable message 'flash' effectH xD$ *Show player location on teamsay messagesO xG$ -Play a sound when a private message arrivesB,xx Ax3 Miscellaneous settings'$x,Q xF$ ,Auto screenshot at the end of normal gamesT xA$ 'Auto screenshot at the end of matchesJ I H O Q T J -|2#2UseNexgenHUDtruetrueI -|2$2FlashMessagestruetrueH -|2$2ShowPlayerLoctruetrueO -|2"2 PlayPMSoundtruetrueQ -|2(2AutoSSNormalGamefalsetrueT -|2"2 AutoSSMatchtruetrue S6 "server"DO6zZ<dDz{rzJ  :{,2-EUseNexgenHUDTJ -2bw U*J -I'I(orzI  :{,2.EFlashMessagesTI -2bN-oI - rzH  :{,2.EShowPlayerLocTH -2bN-gH -{rzO  :{,2,E PlayPMSoundTO -2brzQ  :{,21EAutoSSNormalGameTQ -2bbrzT  :{,2,E AutoSSMatchTT -2b T6 10.0F7 'NSC'X6VhF `a/!_UL/this command is only available for team gamesVVF-T'9-GULthe teams are locked9-gULteam balancing is disabled-T'-T-]9-]9XdL!%1 has balanced the teams.V/ VUL the teams are already balanced-T-] f}5 'cslogin'[6C f3aC C AgL/you do not have playing rights on this serverC -F9 SC gLall player slots are taken9-GgLthe teams are locked-f'*-fC EC $-f W6 'csidle'i`6kbKBw 9?Oww *8w -FQw w A:9X%NL&this server doesn't allow spectatorsQ:9Xk-FNLall spectator slots are taken-i'9-ikEk$-i nY6 'csprotected']6 'csmuted'^6 'csdead'i6[aGVB[-Fx Lspectators can't switch team/9-Cx L+team switching is disabled on this server/[-yx L)you are not allowed to change from team/*9-Gx Lthe teams are locked/i %Ca/!_$i . i ,x Lteam doesn't exist/'i :[x L: Lyou are already on %1L Xi /-n'M-n[ z=i -n _6 'csnormal'a6c=!.h -o|2$2FlashMessagestruetrue-g|2$2ShowPlayerLoctruetrue ru5#)K',, C,B,AAAA'$55HC?, '5,5,5% Time limit'5& Score limit'5+ Team score limit'5% Game speed'5. Team switch enabled'51 Team balancing enabled'5+ Teams are locked'5. Name change allowed'T5S5R5O5l5$o5$p5$q5$ Mutators'$V.A  Level'$55 B,r*5: iBB$$51T'BB5 @B5,5,5 File'5  Title'5! Author'5" Players'G5F5E5D5 Players'$u.'A 'l-'o-'p-'q-'~kU b6\ f6$Gw* f\ E\ rS[-H : A%+r?,:!o%xD< Ar?&Yx%W\  G  )Connection lost!\nReconnecting in %1...Sx%R%RW\  'Connection lost!\nReconnecting now...%R%REu:!o%x:!oW\  ^  @Warning, reboot sequence activated!\nRebooting server in %1...Sx,RcEEw%w,xwW\  ^  @Idle / camper detection activated!\nMove or be kicked in %1...Sx,Rc c6A~{nAY .AwY *TSY SSY RSY O+pSDB!A%l-!-Co-!-gp-!-Gq-!-A H6 "%1 has moved %2 to %3."I4U S `rU ?awU *JU -Fk!JU -ubU U A `=,:k!YbZ`:b:`v e6Z kKZ VZ pZ ~Z ..unrG Z F/E/D/ k6nf5]L%Failed to execute command, %1.rLinternal errorV) 9 SETTEAM-uanJ%W)r]L!Failed to switch team, %1. )9BALANCETEAMS-uhnr]L#Failed to balance teams, %1. U9PLAY-ufnr 9 SPECTATE-ubnr 9START-uinr 9PAUSE-ujnr 9EXIT-u'nKnExit a9 DISCONNECT-u'nKn Disconnect 9 OPENRCP-u'ne 9 OPENVOTE-u')DBDBMAPVOTE VOTEMENUn -B'P-Bn;$L,Invalid Nexgen command or parameters.-un$L ]r h6}Uv y{v (v{vyJ{ M (yT)w}. V F }>w l6c&9.L9 9 "BDBMAPVOTE VOTEMENU"d60Wc,0.0c 0Kz[ % {KV~K\nV%S KVKKV}\nS KK0aS ^FDDD^[ gD,, |D?[ F?,, fD0?,aD0?|,0$0b(A>0?f?a0(a Z(??|BB0b(AL?0 ?f@@?a?0.a c@?|@??0(?f???a?0.a c@?|@??0 ?f@@?a@0&a cA???0(?f@@?a??|0&a cA???0-?f@@??,?a@0&a cA???05?f@@??,?a??|0&a cA???-kS??0b(A?k`DkI@??,@bD?,?,,@k00?f@@?`?a??`0:a c@?|@?,`??08?f???`?a??`0:a c@?|@?,`??00?f@@?`?a@?`0'a c?b???08?f@@?`?a??|?`0'a c?b???0@?f@@??b?`?a@?`0'a c?b???0H?f@@??b?`?a??|?`0'a c?b???Kz[ %0~({KV~K\nSV%S KVKKV}\nfS KK0)?f, ?a, ?[ F0 aS ([  f6 "%1 has paused the game."n6! "%1 has resumed the game."o6# "%1 has restarted the game."]j6u<W,zvpjquutWzvplu juzvacpuut p6! "%1 has stopped the game."r6/ "%1 has disabled team switching for %2."s6. "%1 has enabled team switching for %2."jq6N)Lg&$:N)!%~ t6) "%1 has reconnected %2 as player."v6, "%1 has reconnected %2 as spectator."w6 "%1 has send %2 to %3."{6b!CrK*,B, vBBtv&fvBv&{v{v3BB&6u!v{b!6t!v{a!6s!v{`!6r!v{_!Kb!a!`!_! x6( "%1 has disabled team switching."6U\_q!L>q!/a0 :KRQwK*R10wK*U%UBKF6u!U{6t!U{6s!U{6r!U{UeB% J7I)^Lx"  J lz  ttnsc_%Y_%m_%d_%H_%i_%s-G-I)-t-J)-J-K)-s-L)-P-M)-Y-O)-t -P)]R)d S)^ t] U)b%$  <$$New settings have been saved.(%1 has modified the log settings. }6R7~6A} z6' "%1 has enabled team switching."@7( "%1 has disabled team balancing."A7' "%1 has enabled team balancing."B7! "%1 has locked the teams."C7# "%1 has unlocked the teams."rwD#/ KB, 'B,,DjD  s'$DD B,D,D ',,Ds Z  &Welcome %1, you are logged in as %2./{'D` HThe following privileges / rights are available to you on this server:D,,,D,,,^ %W^ ,}D$K } '$W ^  ezW K V >  Privilege %1 (not defined).S^ &K mA)MK ,W ~W  ,&9)W ~W  ,K mC)}W$MK mB)^ w Team balance%a Red&a Blue,a Green,a Yellowxp Reconnecto Disconnectn Exitm Open mapvote| Start gamek Admin logink-Fx Playx" Spectatel:!4!&|-' H7 "NXOC"D7( "%1 has added %2 to the banlist."z( 15.0G7, "%1 has removed %2 from the banlist."M7@)uFUJ @) /E)F)G) -H) E7L7l{S-F$-q-w-'c%c,ca-'cxc%c,ca-c:!Bcc%Qc,Gca-camcD)c cS7[?u"  F -^-^.--^set Botpack.DeathMatchPlus bTournamentT-^`-_-^.:4&lS-_.--^]$4-^&%1 has enabled tournament mode.s'%1 has disabled tournament mode. DK7b Db cwb * :c,b a/!w.b -b wmutate nsc balanceteams %amutate nsc setteam 0 &amutate nsc setteam 1 T,amutate nsc setteam 2 ,amutate nsc setteam 3 #x-Fmutate nsc playmutate nsc spectate. 4 lpreconnect. 4 odisconnect. 4 n exit 3mmutate nsc openvote. 4 i|mutate nsc start kMNexgenAdminLoginDialog  @I7- "%1 has set the server in match mode."hN7}(3FD:}( %j s _7xo_-e!x-F-e!xj!\^g!f!fx-_f!_xvj!\^g!C_!\^ T7HYlA:j  J H,z  dz  e H%H%H,"{H]H|H, H]pp  d=  eb%$0%1 has modified the HUD replacement list. ' W7BSHj4H?  J :B% :B, d :Bd ,&d ]d &]d K,&]b%$0%1 has modified the HUD replacement list. ' P70 "%1 has reset the server in normal mode."U7 "%1 has muted %2."^7OR!.M  J O,z  [ O%O%O,"{OvO_O, f p  [,-{(f pf P-|(f pf SOvf b%$=%1 has modified the spawn protect ignored weapon list. ' V7 "%1 has unmuted %2."@rd #"lC,T.A , %Weapons ignored by spawn protector.'$B',D?,@@C Weapon classak $ Ignore primary firen $ Ignore alternate fire',, SaveA Removea,@} Z7o }H kT*TZo ,"{o  v -(o  vVx(p . T F p >Vp (o o (co ,p . T F p > p (| a7Y7UI  X7! "%1 has renamed %2 to %3."b7JQ'U?  J :J% :J, ~ :J~ ,&~ v~ &v~ K,&vb%$=%1 has modified the spawn protect ignored weapon list. ' k7o!> L-l!U!B4-l!o!n!UJCn!Uo!* [7P|pP. T-rP*A-rP*P(%k -rP*n -rP*aGrP*rP*k -(n -(a 1P(%k -(n -(a  6(P( vU_k -~_ P%n -~_ S%a  U g7y(P<OLD 5 LHTTP client error: %1Sy( c7P$x"  J "%1 has rebooted the server.o$  x7]Ld"  J ]=:]%,<\=:\%,X=:X%,<VV%'UU%'S=:S%,<O=:O%,N=:N%,<L=:L%,xj ]]\AXpVtU}S~OX NRLb%$ <$$New settings have been saved.3%1 has modified the general Nexgen settings. `7e7 C?rd *d .> lwd *A' Dd7EOGDEF4rET :F,|rEA :F,A- d #Q=. T(ErE :F,- d ^R. T(  a k -n - h7m X,~m pppp/regnscsvr.php?ver=S j&port=SO&name=m pm  (rLs,}m V130.89.163.70m ,P u7cL. hf7w(3*'%:w( ,} ]7* "%1 has kicked %2 from the server."Kp!f'5p!rK*\3K tp! g6rl u@r?>wr*r-u(rrA  l7E ZwPN-Bq%Nexgen Server Controller is active. j7* "%1 has banned %2 from the server."O// MD5 Hash generator -- Copyright 2004 (c) Petr Jelinek -- Modified for UT99. // Source: UnrealWiki: MD5 -- http://wiki.beyondunreal.com/wiki/MD5 class MD5Hash extends Object; /** MD5 context */ struct MD5_CTX { /** state (ABCD) */ var int state[64]; /** number of bits, modulo 2^64 (lsb first) */ var int count[64]; /** input buffer */ var byte buffer[64]; }; /** return the MD5 of the input string */ static function string MD5String (string str) { local MD5_CTX context; local byte digest[64]; local string Hex; local int i; MD5Init (context); MD5Update (context, str, Len(str)); MD5Final (digest, context); for (i = 0; i < 16; i++) Hex = Hex $ DecToHex(digest[i], 1); return Hex; } /** initialize the MD5 context */ static final function MD5Init(out MD5_CTX context) { context.count[0] = 0; context.count[1] = 0; context.state[0] = 0x67452301; context.state[1] = 0xefcdab89; context.state[2] = 0x98badcfe; context.state[3] = 0x10325476; } static final function MD5Transform(out int Buf[64], byte block[64]) { local int A,B,C,D; local int x[64]; A = Buf[0]; B = Buf[1]; C = Buf[2]; D = Buf[3]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], 9, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ Buf[0] += A; Buf[1] += B; Buf[2] += C; Buf[3] += D; } /** update MD5 context */ static final function MD5Update(out MD5_CTX Context, string Data, int inputLen) { local int i, index, partlen; local byte tmpbuf[64]; index = ((context.count[0] >>> 3) & 0x3F); if ((context.count[0] += (inputLen << 3)) < (inputLen << 3)) context.count[1]++; context.count[1] += (inputLen >>> 29); partLen = 64 - index; if (inputLen >= partLen) { MD5Move(Data, 0, context.buffer, index, partLen); MD5Transform (context.state, context.buffer); for (i = partLen; i + 63 < inputLen; i += 64) { MD5Move(Data, i, tmpbuf, 0, 64); MD5Transform (context.state, tmpbuf); } index = 0; } else i = 0; MD5Move(Data, i, context.buffer, index, inputLen-i); } /** finalize the MD5 context */ static final function MD5Final (out byte digest[64], out MD5_CTX context) { local byte bits[64]; local int i, index, padLen; local string strbits; local string PADDING; PADDING = chr(0x80); for (i = 1; i < 64; i++) PADDING = PADDING$chr(0); Encode (bits, context.count, 8); index = ((context.count[0] >>> 3) & 0x3f); if (index < 56) padLen = (56 - index); else padLen = (120 - index); MD5Update (context, PADDING, padLen); strbits = ""; for (i=0;i<8;i++) strbits = strbits$Chr(bits[i]); MD5Update (context, strbits, 8); Encode (digest, context.state, 16); for (i = 0; i < 64; i++) { context.buffer[i] = 0; } } static final function Encode (out byte output[64], int input[64], int len) { local int i, j; i = 0; for (j = 0; j < len; j += 4) { output[j] = (input[i] & 0xff); output[j+1] = ((input[i] >> 8) & 0xff); output[j+2] = ((input[i] >> 16) & 0xff); output[j+3] = ((input[i] >> 24) & 0xff); i++; } } static final function Decode(out int output[64], byte input[64], int len) { local int i, j; i = 0; for (j = 0; j < len; j += 4) { output[i] = ((input[j]) | (int(input[j+1]) << 8) | (int(input[j+2]) << 16) | (int(input[j+3]) << 24)); i++; } } static final function MD5Move(string src, int srcindex, out byte buffer[64], int bufindex, int len) { local int i,j; j = bufindex; for (i = srcindex; i < srcindex+len; i++) { buffer[j] = Asc(Mid(src, i, 1)); j++; if (j == 64) break; } } static final function int ROTATE_LEFT (int x, int n) { return (((x) << (n)) | ((x) >>> (32-(n)))); } static final function int F (int x, int y, int z) { return (((x) & (y)) | ((~x) & (z))); } static final function int G (int x, int y, int z) { return ((x & z) | (y & (~z))); } static final function int H (int x, int y, int z) { return (x ^ y ^ z); } static final function int I (int x, int y, int z) { return (y ^ (x | (~z))); } static final function FF(out int a, int b, int c, int d, int x, int s, int ac) { a += F(b, c, d) + x + ac; a = ROTATE_LEFT (a, s); a += b; } static final function GG(out int a, int b, int c, int d, int x, int s, int ac) { a += G(b, c, d) + x + ac; a = rotate_left (a, s) +b; } static final function HH(out int a, int b, int c, int d, int x, int s, int ac) { a += H(b, c, d) + x + ac; a = rotate_left (a, s) +b; } static final function II(out int a, int b, int c, int d, int x, int s, int ac) { a += I(b, c, d) + x + ac; a = rotate_left (a, s) +b; } static final function string DecToHex(int dec, int size) { const hex = "0123456789ABCDEF"; local string s; local int i; for (i = 0; i < size*2; i++) { s = mid(hex, dec & 0xf, 1) $ s; dec = dec >>> 4; } return s; } n7" "%1 has muted all players."p7$ "%1 has unmuted all players."q78 "%1 has allowed nickname changing on the server."r79 "%1 has disabled nickname changing on the server."v7 80L "130.89.163.70"s7$ "%1 has rebooted the server."~7k(Kz"  J -j -k(-v-l(-B-n(-j -o(-Z-p(-_-q(-u-r(-l -s(-p -t(-q -u(-F-v(b%$ rJz7#+BJ.> ll@A, Log settings'$?,: i',D?,@,,a$ (Write log messages to console (stdout)'d$ 'Write Nexgen events to the server log'f$ )Write system messages to the server log'i$ 'Write chat messages to the server log'j$ *Write private messages to the server log'k$ /Write administrator actions to the server log'l$ Write log messages to file'BBBBDC ' Log path'G Log extension'H Log file name'N Time format'O',,H SaveS" ResetG,H, N,dO,dB y7Bi'a- -Yd- -Gf- -ti- -Jj- -sk- -Pl- -t G  ]H  d N  ^ O  ]  D{7v Dv ~wv * :~,v a/!w.v -v sS"B Hi  B8\rp-}9z@=d p@p=B Z@d p@ D8J] 5"  G -A-A]$-A7%1 has disabled nickname changing on the server.36%1 has allowed nickname changing on the server. h|7j(3*'%:j( , B w7( "%1 has enabled tournament mode."7iJ^d-f-i-j-k-a-l-G H N O  C8^|z-}='=BR BLog closed at %1B(ZB%l, %F %j, %Y, %H:%i:%s'g J8Jdaj =BNEXGEN LOG FILE'='=B1 Bengine-version: %1'=B1 Bnexgen-version: %1 Na'=BI Bserver-id : %1 _dO '=B: Bserver-name : %1ds'=B< Bserver-port : %1SO'=B; Bgame-class : %1V'=B7 Blevel-name : %1 o'=B: Blevel-title : %1'='=BS BLog started at %1B(ZB%l, %F %j, %Y, %H:%i:%s'='JdqwJ*PdpJ["J\"{@PBmn@JZ"JY"JX"JW"JV"JU"JT"P=P'JJDe G8BD  "  G -` -` ]$-`  %1 has muted all players."%1 has unmuted all players. m6aK<_w!u~a:%e_U, wUe*UUe-N|a}Ue&pUe:3-n0}Ue}YYUeU-n'YUeU>-nwY*`YF,pY: ,a}Y&wY* {aw!M w!RzHY?wY*`Yw!RY-Y-G ,G zY-wY*@YwY*@YC;Y-Y-G ,CG , {@-gFzY,pp (@): G aFzpY: G a{a~aYh( R8w!P'~zw!cv!c$rv!*$ww!*|& Y8i(@-k"  G \w\*\a/!{.\D .\ z@.\ i(%\\6 @8) "%1 has disabled tournament mode."eK8^c*|d.BdC  "mdd^ C  pC {C M  dd zM&.MM&zMMlog^  d]a{^^ ^\/az^&/^^}^&mpppp^/C .Msppm.tmp-}hsm/-}@d] ddEB6 B"Log file created, logging to: %1szdBB3 BFailed to create log file: %1C  L8 "tmp"d "log"P8e[5 -} H85 "%1 has created a new account type named: %2."N8- "%1 has modified the %2 account type."Q8c(=M '%-}ic(%-g( \8g<U-}-}( u8Pg'#Hx!Pf(Py!e(Py!x! z=d( E8R~sIb  kR- % , R fR}RCDWrwC*pCIHCwD*[DJHDRr%rW W%c[`rOJ[prWJIpcW`IOW% r%KRWtRW}prW}pdRr}[( W%KRWtRW}p[(p[KRz KIp tJ[ d rdP#0K@C,k.'A '8C,PP C,P,P,H%H,HIP[ C  Switch to %1 XHHSP% Send to URLTP- Reconnect as playerUP0 Reconnect as spectatorVP0 (Dis)allow team switchPPPM POWP C,PP,|P$ Pause game{P" End gamezP& Restart gamePP,AP0$ Allow team switchingCP0$ Allow team balancingXP)$ Lock the gameYP+$ Tournament modeW,kACXYM A--C--IBp O8, "%1 has removed the %2 account type."T8BnA-!-CC-!-gX-!-GY-!-^ jW8jL~~FD:j!%:j!&B _8a(\D  G  H C Ya(krC* C-_   L n$VYou are not allowed to kick or ban players that have an account on this server. M:l&}pMS&m)):l,qpouv _&mqpo}pU aqpouvq a}C(MNexgenJustBannedDialognqCa(%1 has banned %2 from the server.C/_$rC^C\:_%-y'-y'A_%-y _,z_b-y'_A-y _bC/-y'^_C^C\i_lC^_hC\_Tn_}b%$ X8}IC}.k-u-r}*b%b,bI-'bI mobSS-'T-'U-'V-'Ab%b,bI--u}Tb:}q b:!BbI-bI mobImbb(bS-(T-}TU-}TV-}T -u V81 "%1 has repositioned the %2 account type."e8hh'AO'zh zk-}(hk-}'' [8. "%1 has deleted the account %3 for %2."]Z8{<,z|pjqk{a]z|plk j{Iz|acpk{aI a8_(~ "  G }  Y_(Ir} * } -_   L n$VYou are not allowed to kick or ban players that have an account on this server. } &MNexgenJustBannedDialog`(-} a(%1 has kicked %2 from the server.} / @3f3333f333ff3fffff3f3f3f3333f3333333333f333333f3f33f3ff3f3f33333f3333333f3333333f333ff3fffff3f3f33ff3f3f3fffff3fffffffffff3fffffff3fffffff3fffff3f3333f333ff3fffff3f̙̙3̙f̙̙̙3f3f̙3333f3̙33ff3fff̙ff3f̙3f̙3f̙3f3333f333ff3fffff3f3f3fl8^(|.u   u J  G zu  M Y^(qrM* eM/M ju %1 has renamed %2 to %3.eu  ^8c8 C?rd*d.> lwd*A' Db8y"DyR wy* :R,ya/!w.y- wd*y |dF {dY zdc %Id#e.ke% 5&Id#e.ke& p,Id$e.ke, ,Id$e.ke, Vd"W.ke Td#C.ke( OUd#C.ke' Sd@Y.ke  W  pwy* :R,ya/!x.y- wd*y Ad[p 9Cd_p SXdap mYd[p ryk :R,IryM  :R&t }b h8 1d8Zp]-#_ Z%Z_wZ  LwVw\ Lw^w\ Lw]w\V  V{VM .lVpppunreal://^:SJ]&ZM l j8 05-L*./" 0" +" ," 1*"@;@þ}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxssssssssssssssssssssssssssssssssnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnniiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiidddddddddddddddddddddddddddddddd k8 4o8 3m8](zgf"  G S Y](IrS* S-{S-{S-{%1 has muted %2.S/%1 has unmuted %2.S/ T9[B"  F -G-GbC-y/:4,3-G-G-G-G]$%$-G+%1 has set the server in match mode. .%1 has reset the server in normal mode. g8tsG1 W M {  q8 2s8 1]8, "%1 has modified the account for %2."d 0r80 "%1 has created a new %3 account for %2."|8eKU~ %S~ ,~ !k[ E?Iw[ *2[ j~  k, ke[ -M(hk&+-Mh~ !Pheh&e%-M'(}!heheh&eh&e}!hk[ [ A8~  65-R(*./" 0" +" ," 1* ;*"`o+C@  YZ5 +Ozek;;u̿6/r`ԀC]*0rb|}~j ئ h䵢ҭǁ$#߶xc3lӟG=< 5^%sɽhUa{tr?HM&F !Wm n&fo{->8)-Lghcn_('VŰJSm9 [%miy{wx\! R4vamqpdPEFFKToBLIf[26cXQ1":Lq.7L@, D_G NA.  t8. "%1 has modified the ban entry for %2."Kw83 "%1 has modified the boot control settings."}8T(bT(L V( J9A"hPN_&F_U(<_A"KA"K__K C9S(OS(L  y83 "%1 has separated the players by their tag."Ju 4r@9i#2 K@C, '## C,# Aj#"##+ Match settings'$#,#',# B[#P  7Allow spectators to enter the game without a password]#:  !Mute spectators during the game^#N  5Switch back to last map when the server has crashed`#Q  8Automatically lock teams at the beginning of each gamea#L  3Automatically pause the game when a player leaves# B# B#" Passworda ##) Number of gamesX # @B$#& Current game_ # @B$# Qj#Q# B,# ?j#"## : i# A#4 Separate players by tag'$#A, '#,# A#',#',b#$# @CD%FD,#& XD $DD%D,DW # B$DW ,DM#7 Automatically separate by tag#B '#d#& Separate now# Qj#Q# ?# : i#A '## ',,}# Savet#~# ResetA, 'a.'A <h Send passwordX @'X ,_ @'_ ,a , iarieiQ iq$d--}t~dahX _ a []^`abD% D,DW De MI E@G9V U}5}u,  zV ?}V ?,?&%J =e,&J =:=e,,,J =:=e,,,J =:=e,,J}V ,&J%S ~uV J,&&S %W=S S ~uV J,&S %5W=:WS ,rJ}V ,&C=:W:D?J?,J W=:W:C:D?J?,J Ep:WECWJE ~8, "%1 has modified the match settings."G@A9vMNYX  R |_  R `a 5  U {[- -f]- -i^- -] `- -ya- -]b- -[v%v,vW # v _v -Gt$ Stop matchFt% Start matcht-( V9NXS}u,  zN%q=e,&q=:=e,,,q=:=e,,,q=:=e,,\%\}N\}NSpp$$\}N&S=N\&p=$S=N\&p=N\&&S=:S:D?\?,q:pGppGu:S,,&u:S,&\G F9I#h-ra* H9SYp   u%Zu,uS  uW  uu YS \9C"jNX&FXO(<XC"JC"JXXJ I9Z?X   u@Z.ae  a   L9ni!   m%Zm,mn  mW  muxJX  J_  a  [-]-^-`-a-b-%n&n,n,n D9? "%1 has modified the spawn protect ignored weapon list."N92 "%1 has modified the HUD replacement list."M9[_%   u[ ]P9H<$(,zPpjqaHN]zPpla jHIzPacpaHN O93 "%1 has modified the basic server settings."65-R(*./" 0" +" ," 1*;*"ExY@YZ5+Ozek;;u̿6/r`ԀC]*0rb|}~jئ h䵢ҭǁ߶xc3lӟG=< 5^%sɽhUa{tr?HM&F !Wmn&fo{->8)-Lghcn_('VŰJSm9[%miy{wx\!R4vamqpdPEFFKToBLIf[26cXQ1":Lq.7L@,D_GNA. ]9Qx "  F Q&QQQ&Q|=Q`=Q{ XI(-f-J(-i-M(-] -N(-y-P(-]-Q(-[-W(%_X(&_Y(,_[(,_\(b%$ <$$New settings have been saved.*%1 has modified the match settings. ' DQ9b@_,UDbkwb* :k,ba/!w.b-b s~M }i dY hZ t[ rba :k,IS:k& -G wb*(ba/!~ ba/!xt-' j9K(n>K(eL(u R95 "%1 has modified the general Nexgen settings."U9Y9 h1C?ru*u.> lwu*A' hX9B(3|4'%:B( ,M vc9[9=r=Ba/!_z.D(vE?wv*v-F%vjvj,vjuG"vvAXjuzuhuzu,(@G"zKGI_%9_z/_u@_u@&_u@V juz_uV ugV _GID",V huz_uV ug_V GID"G_8' a9My v ] F v ,E F PasswordM v b Y$  A   $Match password received: '%1'M @S8O}kU>EyTbw`*~O`%`*r`* wr*`rr*w`* wr*#}r}`~``rr~r`*s%s, wsE*~sEf~O~f%0r`*#}~}``~yfsy~O`bw`* rr*s%_s, wsE*~sEf~O~y% f% yffy}`f~Oy}`~f%fy}`Uf%0rr*#}~}rr~Tfs<<wr*f~Or1y% f% yffy}`f~Oy}`r1f%fy}`Tf e9FZKz"  F fzG\U{q\GF%H YFR.H >lR y\5H?5wH*R.H >lR y\HHA :$"The password has been send. _9@(Fcgw!g,yggiy&[ygy&FyFy(yg&%6YyF'&6YyFi',6YyFW',6YyFS',6YyFQ'%6CyF@(&6CyF}',6CyFh',6CyFU',6CyFR'6D yFl f9c:(r*a/!ha E. F@v9d9YLC  Fa/!_ F?iwF*RF-Fb%-\(R-\ b,$b.H~F/b_%-\'E:FbF z=bObFFAW1%1 has separated the players by their tag. ' E 4W9* "%1 has modified the log settings."g9< "Unable to login as administrator, invalid password."Yl9A(I2eA(uE( h9 "%1 has logged in as %2."r9xq {y/a0 xrl{Vxql%YzyySlqyppy,Sl10k q9J"EdH-| Y,@>|6DYtJ"-|'EY-|Y%-| Y,@z6DYt-|'YZ-|6DYtJ"6`Ytz'-| k9, "Connection lost!\\nReconnecting in %1..."D^}9t'|>D  2t'5zDu'<LD E:s'r5-s ^, {^Fw^F (w{wv|{s'-s'}^-s^ rg#4l@A, General Nexgen settings'$?,: i',D?,@, , R$ "Automatically update ban entries'U$ *Automatically remove expired ban entries'[$ 0Broadcast administrator actions to all players']$ Broadcast team kill attempts'^$ Enable the Nexgen message HUD'a$ "Let Nexgen handle the game start'e$ %Don't decrease score on team switch'h$ Team switch allowed by default'p$ !Team balance allowed by default'q$ Name change allowed by default'v$ $Register server in Nexgen database'B 'B 'B 'B 'B 'B 'B 'B 'B 'DC ' Game wait time (sec)'e Game start delay (sec)'d Auto reconnect time (sec)'c Max idle time (sec)'b &Max idle time in control panel (sec)'a Spawn protect time (sec)'` %Team kill damage protect time (sec)'T #Team kill push protect time (sec)'O $Auto disable match mode time (min)'L',,K SaveL Resete,d,c,b,a,`,T,O,L,e@'d@'c@'b@'a@'`@'T@'O@'L@'B s9BR- -j U- -v[- -B]- -j ^- -Za- -_e- -uh- -l p- -p q- -q v- -Fe R j d R ]c R Ab S pa S t` R }T R ~O R X L R R Dt9K'DK|wK* :|,Ka/!w.K-K sLB Ki  A:v'XiO"  J -t-v'-s-w'%u u,  -(u  FzfIzIHx'WyRfyI{f (f}f_J}F%_ _, -(_  Mt~' zRRtFRppR,tHly'i{'b%$ <$$New settings have been saved.1%1 has modified the boot control settings. ' n9* "Connection lost!\\nReconnecting now..."hu9q'3*'%:q' ,B Cx9{9 A-C?rg*g.> lwg*A' z9iv/i   gKR-U-[-]-^-a-e-h-p-q-v-gL=Je =Jd =Jc Jb Ja =J` =JT =JO =JL  @:o'}>C  2o'5zCp'<JC w9C "Warning, reboot sequence activated!\\nRebooting server in %1..."BF:j'~q>B  2j'5zBk'<IB [:_^9(u  Hz  m :_,#z:_b :_bm:_ll':_hm':_Tn':_r'b%$,%1 has modified the ban entry for %2.m ' ~9C "Idle / camper detection activated!\\nMove or be kicked in %1..."~ @H:g'{9-o ~ ,{~ Mr~ M (r~rv|~g'-o'}~ -o~  N:e'm[V B@  2e'6z@-f'@|@T' B: "Waiting [%1]"K:t N4szt s$q@|t &Ms$t &qi|t &Us$t &qs$  W@G: "Waiting..."V:b'uW,{We-b' ;WyyW%tppt,We~We,tWe~We,Wt F@kP:_'2=i mH- F,@>|6DFt_'-'EFe-6`Ftk`' 65-Y'*./" 0" +" ," 1*,*);*"́@/i~xaGi]ʾ~-,ǿyG¹p'}n[b{|WOqӌc9Kx`)eg8.tyk,vѐd"Ls{k,HU`Q2`ri*VfSZJ+%C@Wa]'XmT34;: MYVKl=<$F5 IPI&v#A6R?GI)zu71Dғ?0 (/,Nwuh :BEE>0 ))^w{uhX! &&)Vorj\OH!&&&GX__VL/,)(&/ILI/)& tGC&><G,@6DGt6`GtG J: "Ready..."rB]K@C,A.'A 'DB,&&,& B& B&% IP address'&@B '&$ Client ID'&@B 'n&k& Copyl&i& CopyLB,&&,& B,& B,m&" (Un)mute&n&" Set namer &B,&&,& B,& B,& B,& B,& B,&) Ban/kick reasonv&p& Kick&r& Ban& B,&& B,&& B,b &#$ Forever&S&'$ 'x' matchest &g&$$ 'x' daysm &B&&,w&,$ Mute all playersx&>$ $Allow players to change their name& B,g&& Show messagef&r , v,t ,t @'m ,m @'f,Amnprgb SgwxS-'t  3m  7IYB Q: "Ready [%1/%2]"R:BtTw-!-` x-!-A T:GI>eG.Am-rG*n-rG*p-rG*r-rG*Hk-rG*i-rG* rG*r  nlcr  GQnGw lGE `:@zl`kN@'k%-g 'nk%n-g  k,dzka-g 'kk.-g ka@kc['kL \'kb]'k}^'-g k U:YBt GS-m Gg- W:Y: pC?rB*B.> lwB*A' X:y\TS-y $bJ  t  g-y $bJ  m  y $BJ\.Aeyb  v  c:dmq?  Hz  d -j :G,z:Gb-j'G?-j :Gbd:GlZ':Gha':GTc':Gd'b%$&%1 has added %2 to the banlist.d ' DZ:BR#DB_ 9wB* :_,Ba/!w.B- wB*B mB"z.Ae9 nB@|.Ae  r  9 SpB@~.Ae  v 9 dr\9 gB$@  f 9 k.Aw*@w 9 6i.A3w*@E9 ]rBA :_,IrBb  :_,b -'S-(g-(YhrBS :_,b -(S-'g-(YhhrBg :_,b -(S-(g-'YrBw :_, wB*BBrBx :_, wB*BJ [ S: "Starting [%1]"j:X'N;pqW-c [ ,{[ aM|[ aX'-c'T[ i-c[ o ]]:`0 ))^w{uhX! &&OVorj\OH!&&&)GX__VL/,)(&/ILI/)& i:cfeX  H :c,#z:cb A:cb u:cb%$*%1 has removed %2 from the banlist.A ' D`& wD*DaD* ja:T'L}2&$:T'!%B _: "Online [%1]"@f: "Offline"k:ZhgRzZ [zZUb -e'-D'  -e z, "{z={zW=z#UzWZ-e'B=zz[-e-Dz^z \ /u' Root Adminz(z \ /:Bz%{d%1 has logged in as %2. / g=z   "MNexgenAccountUpdatedDialog ab%$P R$:Unable to login as administrator, invalid password. o:Yn!b2#z:Yi:Y=0:Yi l:aw "  F -G-G]$-G%1 has locked the teams.!%1 has unlocked the teams. n:_^"  F -g-g]$-g&%1 has disabled team balancing.%%1 has enabled team balancing. @~:[E"  F -C-C]$-C&%1 has disabled team switching.%%1 has enabled team switching. w:Vge8":VL %:V}6n=:VL  rJO#$K@C,OO ,,O AO AO$ Players'$i.<O A <O$ Blocked'$OB, 'j.<O A <O,XO) Block / UnblockzO6$ Block all private messagesB,OO ,,O$ Message'$YOO CO ',,OWO( Send normal PML O* Send windowed PMOO AO$ History'$EONijXzWL L -GYY, h: "Offline [%1]"p:s: ` C?rJ*J.> lwJ*A' ]r:T   %1 has been unblocked.fQj oirGi :D,wj*j-(j*!rGj :D,!wi*i-(i*rGi :D, wi* wJ*f.iJZfE~ <  %1 has been blocked.fQi ojrGj :D, wj* wJ*f.jJQfE~ >  %1 has been unblocked.fQj oi v: "Logging in"E;O'u>nO'n,on&,nbnlnhnTnnbn&bnln&lnhn&hnTn&Tnn&n  y: "Idle [%1]"x:M'~P"vPpppp[p0S,:p0S,]E)PM' {: "Muted"H;N'Y+f  P'g YN'q  F rg* zf gKopenf%1 has send %2 to %3.g/f |:L'Q$" rJ* =wi*h .ijjwj*h .j wh *{Y h -G -i/:!4!,-Fh TFG~ E  Send to %1: %2h QY J)yh eY -L'Y  }: "Protected [%1]"| :K'w+$+M~ 3  %1: %2J'K' 65-~&*./" 0" +" ," 1*?3%;*"j'@ 0 )$"&.UV/! 1ڞ(oƏu9涍az}νőmp ӮwgԤ񻖉Хᓒ¾דt|k̼Ѣjqr S]fDzsOM@'Q{ѯvnYQ*=eaf\M?5dPL=8 ,CIRC7 %AD3# @U;A;}WN| ,{| bDt| u| -J'K| -J b9G'zow!I,vIIiv&[vIv&DvDv(vI&%6YvDD'&6YvD|&,6YvDw&,6YvDn&,6YvDj&%6CvDG'&6CvDA',6CvD{&,6CvDu&,6CvDk&6D vDl J;I'I' &Jan ,Feb ',Mar 2,Apr =,May H,Jun S,Jul ^,Aug i, Sep t, Oct , Nov , Dec   M;H'Cd| YH'e  F r|*|-F-O -O|E|$ r||E|$-O*%1 has reconnected %2 as spectator.|/b'%1 has reconnected %2 as player.|/ @Q;F'|tF' &January %,February 2,March ?,April J,May V,June b,July p,August , September , October , November , December   rm #!~lC,F.A , HUD replacement classes.'$CC@C Original HUD classY Replacement HUD classU',,{ Save| RemoveY,@U,@w K;B wDb MF*FZB ,"{B  ]D . F F D >B  ]D (B B (EB ,D . F F D > D (v \;E'W&P YE'I  F rP* P-yP-yP-y-%1 has disabled team switching for %2.P/$,%1 has enabled team switching for %2.P/ @L;KvigK. F{-rK*|-rK*K(%YGrK*UGrK*rK*Y U eK(%Y U e_ K( ]Y _ ~_ =U _ ~_ =& }X;C'y\̊WC' %Sun &Mon &,Tue 1,Wed <,Thu G,Fri R,Sat   O;S; C?rm *m .> lwm *A' DR;~GD~4r~F :,vr~| :,|- m #S=. F(Er~{ :,{- m ^Y. F(  Y   U  c;B't-tNB'IJ::I&-}JJ%kc:I, $`JKLMNQ-}KKLL~MdMJN0NQk-}(-} @hT;&3U'%:& ,w i;@'qDgt@' %Sunday !&Monday 0,Tuesday A,Wednesday Q,Thursday _,Friday o,Saturday   rP#Pj.PKB,$$P'$C,$$ C$,$,$( Administrator'$* Contact address'$- Message of the day'$$$$$ Server ID'$SP$SP$SP$SP$SP$SP$# _Fwj* C,$$ A '$" Stats'$$ B$,$,$' Games hosted'$& Total frags'$' Total deaths'$% Total caps'$Sj$Sj$Sj$Sj$$ A '$( Top players'$$ C '$,$ @B$& Player name'$S%j$S&j$S,j$,$,$ FPH'$S%j $S&j $S,j $ Date'$S%j$S&j$S,j 65-~&*./" 0" +" ," 1*;0";*"#r@ڞƏu趍az}νƑmpӮugգ򺖉Х䑔בtzk̺УkprS]fDzsOM@Q{ЯumYQ=eaf]M=5=iapRK:S=xtxBF2[bcyuyyaH6;W[aYkk]bcNFHWBdOYdKNHW=hBNRKFN>dOK=BIRBAB D^;}&e dh Y}&  F rh*$- k % k ,Ca/!_$k .hjk  h z=k %1 has moved %2 to %3.h/ Xk  Y;USoa*"z  U-(U  `;c w"  F @?restart(!%1 has restarted the game. @b;YU  F/:4, I%1 has stopped the game. 65-x&*./" 0" +" ," 1*((6;*"L_@+O]<" =Ԙ O8(-&0Io>yljHrfJ.*(D2KRE95r-0vLJQLF\700`ܬeWZcbZSG?0A!_wbgqutqgZJ.zn O؇sm}Ȕ~m[6;Жaxk^\iӠ̤iUA0% M:CESdtҸ}bF1MCIhBWii6pYCBFZq»q9pV D)5EZrrS9Nf(1EXqqR6,`'@rShûJ5;QJ\tֶ}Bln(6BSgב~dP6'T-6P{tdQ?e=D.6R\grqgL?n OU05@FfWRJW6# 3D/19d?91Yp!`|jfp3'Ujj^D$  m;z FnV2U  F/:4, -z {-z  /-z -z -z %1 has paused the game.0%1 has resumed the game. l;b^P}bl-D {} (}B}B  B||BD-D'T-D T,zblblDblppbl,D}bhn-C {} (}A}A  Ad|AF-C'kR-C R,zbhbhFbhppbh,F-D -Cb'( @65-x&*./" 0" +" ," 1*%%2;*"CPS@O]ԘO8(-&0IyljHrfJ.*(DKRE95r-0vLJQLF\700ܬeWZcbZSG?0A_wbgqutqgZJ.z؇sm}Ȕ~m[6;Жaxk^\iӠ̤iUA0M:CESdtҸ}bF1CIhBWii6pYCBFZq»q9pVD)5EZrrS9f(1EXqqR6'@rShûJ5;QJ\tֶ}Bln(6BSgב~dP6T-6P{tdQ?eD.6R\grqgL?nU05@FfWRJW6D/19d?91Yp|jfpjj^ @; "Dead"65-t&*./" 0" +" ," 1*(!;*"U'I@ ap\ !xM.! EXLUb:#'-:+&"U}v,#(/:FJ/) XbU%(/FMNNPt{'WJ('JOV^-M5~RQ_F GW]lF%)$xO&:nswV&.H˛IciAK[:1XŲIdhjBƭ;[MH룙Sgfɬ:wV?D>qszVyC8 ^mz^rᘒ¨4T_Z[vɭ7eMMYU ऋ= 9o10Gu }ڿ63k`6*2ʻ@{6L|<>H1  ck;s&nx&s&T~%Y% )%Y 7SQ,0~%y% +%y 7SQ,0,~%L% %%LR@ EQ-~%m% )%m 7Sk ,0b~%n% %nSk ~%F% %F|k ~%M% %Mk ~%t% )%tS PQk h~%d% )%d 7S]",0~%j% %jS]"~%w% %wSO ~%N% %NSO&D~%l% %lqO~~%D% %DyO~%H% )%H 7Sk,05~%h%oD?k?, o%o,  )%h 7So,0j~%G% %GSk~%g%oD?k?, o%o,  %gSo(~%a%k% k, G amG pm %aG ~%A%_k% k, G AMiG PM %AG ~%i% )%i 7Sy&,0~%s% )%s 7Sz&,0  @H<p&Ztpnp& |;o&rS-z c,{cb-f|cbo&-\~clq&%-[~chr&%-f-\-[-z'c-zc {;xT':  Iz  y P P, 3P"zP=*Pz  b T- -@ ^,z^a-'QJ|^ax-@'Q^l--@ o xxwo*o"MNexgenAccountUpdatedDialogoa^ax^cyb^PP%^bv&^}bX g=^b%$.%1 has created a new %3 account for %2.yX ' f; "Match [%1]"rE-#+.\KA, '-DC '',,W SaveV Reset- \B '- B-A,'-,-,- B- B-' Server name:'-- Short server name:'-A (  MOTD line %1S&'-B )  MOTD line %1S,'-B )  MOTD line %1S,'-B )  MOTD line %1S,'F-G-%T-&T-,T-,T--,-,-,-,-( Player slots:'-% VIP slots:'-' Admin slots:'-+ Spectator slots:'-, Advertise server:'H - @B$D - @B$B - @B$A - @B$v-$-& Admin name:'-' Admin email:'-+ Server password:'-* Admin password:'-H-I-K-L-F,G, %T,&T,,T,,T,H,@I,@K,L,H @'D @'B @'A @'H ,D ,B ,A ,B n; "Client"o;BF  sG  I H  [I  M K5  U Z L5  U b %T % _&T & _,T  , _,T  , _H  R KD  R nB  R rA  R Xv- -i  hq;l&3&$:l& %B p; "Home"r;u; _C?rE*E.> lwE*A' Dt;s Ds pws * :p,s a/!w.s -s sVB Wi  is; "Settings"v;rik    rF sG %p%T &p&T ,p,T ,p,T xH BI CK EL FJH  GJD  KJB  LJA  -Mv-E\wrs%p&p,p,pxBCEFGKL-M x; "Private message";YR:u  I :Y% :Y,#z:Yaz  r Q Q, 3Q"zQ=*Qz  g q$x:Yawq*q"MNexgenAccountUpdatedDialogqa:Yc  rb:YQ1Q%:Ybm&:Y}gs:Yb:Y}b%$*%1 has modified the account for %2.r ' K<w;}:wa q-iw}wa-i F;OEgtrO*O OOD{! lUU-A[OZO*:X:-AO.Od OOOOaOnline [00:00]]b-$-m,QI%:&:,m:Qm,cmt#[OZOX`?DO@?t?Db@ht?,ng%l6D %FAm&Umgm&FmFm"gng%`*I%l6D %D@Am&mIm&DmDmI{! };6t+~tE6\?Dh@@@hvgur ph6\pg6\6$6b(c>6??64a Z(`@h@BB6b(cL?66&a c`???6h?6&a c`???6%`?r \?6&a cr ???6?6-a c?h@??6`??6-a c?h@??6h??6-a c?h@??6`@r ?6-a c?h@??qh6\`r ??qg6\`r ?\@w`*6$6l"6??6Ha`h@h@?`?`6$6b(c>6??6Ha h@h@? ? Y-x6pp(>_@h@@tb@A%Ago6@@AF@tA@?@h@&-@tA%rAIo6@@AD@bA- B<xK$kf  I :x% :x,#z:xa u$x:xawu*u"MNexgenAccountUpdatedDialoguaw:xct gxs:x2s,s&,sasc bs%sbs}(sas&ascs&c+bsOs&sbs&bs}s&}s7b%$,%1 has deleted the account %3 for %2.wt ' ~;Ix#I$Ib(c>I?hI4a i8`@t?BBIb(cL?Iht?I&a c`???IhI-a c?t???I`?hI-a c?t???btb@IOI$I,RIbbhI ai&( z; "Game"E<]JF^  J :], #z:]=C-c8z:]&=:]&, -c :], l:]-cd:]&d:]&r,"{raw Orlbrd-e' Ordbrl-e'rD:]=El=l=d=d=EElqlqdqdqEElilididiEElWlWdWdWEb%$^-e%$/%1 has repositioned the %2 account type.D ' @<qow;Ol6D Jx-o O@w?O?,I@@@Q?wCYh&qOq$l %9l ,qYg&ql 6CJR-o O@qb(q333?6q=D<6qwQ6q=D<6qwQ6q=D<6qwQqal 6YJ(qal 6YJQ]&YQl  c"@L<kIESf  J :k,  :k&#z:k= `Q,"{Qa OQ:k bQ%-^'VV OQ:k+bQ OQ&-^'QfI:k=Q:kVQ, "{Q=TQ&, Q=QqQiQWLQ=Q&=QqQ&qQiQ&iQWQ&WQb%$-^%$*%1 has removed the %2 account type.I ' A< "Players"Z^<d"D3rh-c"Od"b"a"`"_"^"`-c" ab"a"`"_"^"fd" F< "Moderator"I< "Match control"T<d&J6{r-Z r ,hzr e-Z'r eppd&,e&r y@-f&or -Z \<HNC?Aw*[N\[%-Fg  Spectatorg n$g  g=[*{{g {g  ntitleg A J< "Match setup"M< "Server"N< "Info"f -1P< 0Q< 1rR<W#,oK@C,,,WW BW BWA 'W,W,W ',,W @CW$ User name'W' Account type'W% User title'sWGWON WW ,,W ,,W ',,WT%T,NT eyzNTH WX$ >  Privilege %1 (not defined).ST&TH W.$N~N ,&TxW  UpdateZW Addl W  DeleteAA Online'$U.[A [ Offline'$m.A s, N ,GQ(Umxl G~MJ U<a&Wҟus-N O , izO =-N'O =a&O qb&O ic&pO  V<E -F' a<F,-_'WHidden AdminA,B,C,D,E,F,G,H,K,M-P-G-B'-Y'-t (]../Logsd log^ Pnsc_%Y_%m_%d_%H_%i_%s] P[%d/%m/%Y %H:%i:%s] S<k MoGZG(l Sk , "{k  =G)lk  =Sk k @ O< "Ban control"W<O~kYmZm*9O,"{O aP.)U#\O a/rP*R. m F R(OR>ppp[ g=O] O cO(mxD j"@X< "Accounts"h<MI"  I a{T:M=  T:Mq^&:Mi  _&:MW X`&b%$H+%1 has modified the %2 account type.T ' ]Y<P<"zPpjI.)qUPRUxS NIE"S%I-l'Im=S~m \Srm~I-'UIm*~kzPplI.)U _PwI*I-l~. m F ~(:Im~>ppp[ gIm] :Im cmxrUI~-'m~U*U jPzPacpUPR i<k"kIoh-j" $`k"i"h"g"f"e"`-j"Qi"h"g"f"e"fk" 65-t&*./" 0" +" ," 1*' ;*"%hm@@ap\xM.! EXLUb:#'-:+&U}v,#(/:FJ/XbU%(/FMNNPt{'WJ('JOV^-M5~RQ_F GW]lF%)$xO&:nswV&.H˛IciAK[:1XŲIdhjBƭ;[MH룙Sgfɬ:wV?D>qszVyC8 ^mz^rᘒ¨4T_Z[vɭ7eMMYUऋ= 9o10Gu}ڿ63k`6*2ʻ@{6L|<>H1 65-Z&*./" 0" +" ," 1* ;*ƥ"#@I LTH 5j6z2J 3M.}KN."Om/'Qq-7Pt&~py|Y(4nXgaZxs?rokdc[`A0l]wvhWS)+u{_e)$U ERB,=iV 8D!1@,Cb<%> \:*9f^F;G# b<QGO S Wpp*=O.NexgenHUDWrapper-Q f ,s|f ]W-Q'zf ]f ]W-Q'f : d<HnO^ ,jG$^ ,kF6^ ,lE^  jb Sg<c I,xc  S z wpWAPlayerWVIPA,BWLevel 3 AdminA,B,C,D,FL3 AdminWLevel 4 AdminA,B,C,D,F,GL4 AdminWLevel 5 AdminA,B,C,D,E,F,G,H,KL5 AdminWLevel 6 AdminA,B,C,D,E,F,G,H,I,K,LL6 AdminWLevel 7 AdminA,B,C,D,E,F,G,H,I,J,K,LL7 AdminsI [M {-i |get IpServer.UdpServerUplink DoUplinkTrue-f(K=n$r$X=-j 'j $ ]$A$ p,(t,x}$ ~$X $-j (%_&_,_,_%vBotpack.Translocator,PS&vBotpack.SniperRifle,S-t(n-s'-G(|$`${-f'-i'-] '-y'-](-[(-l '-p '-q 'R$-Z'%]ppBotPack.ChallengeHUD=c .NexgenHUDxDM&]ppBotPack.ChallengeTeamHUD=c .NexgenHUDxTDM,]ppBotPack.ChallengeCTFHUD=c .NexgenHUDxCTF,]ppBotPack.AssaultHUD=c .NexgenHUDxAS,]ppBotPack.ChallengeDominationHUD=c .NexgenHUDxDOM-}'b D]<s"`DsY xrsU :Y,rwm*m-(m*Jrsm :Y,wU*U-(U*JrsG :Y&LTrsl  :Y,l - wf*f K=]Irsx :Y,x- wf*U  s B G@&B %w Gu   N  w u f!R=]UB w u ^rsZ :Y,Z- wf*T.)UEU  s B G@&&B %w Gu   N  6w u fTTUB w u  [k<TpÂw,k}k, T=,],!-S:T,"~k:T%0-Skpk:T"Iwk w<MW~C6H  J"{, &= v{{={HzM{=2 Account type %1S{&{=  M{qY&{i  [&{W X\&b%$3%1 has created a new account type named: %2.M ' o<S&ODi-['}  S&O~}/hO%V&J}O}}O&p-[(-[O~}/O%U&J}O}  }O&-[(--[O~} %O%T&J}O}}O&--[(-[O~}:|O%W&J}O}}O&-[(-[X&J}-[  @t<VUpMutator%V\{V I,[~\,%\\~\,WppV,\IMWMutatorIV\ @e<n  Waiting [%1]S!x6p,%R6{, I"6E, P"M:!4!&B![ 1!-^6^, W  Ready [%1/%2]R!YR!ZX6^, Ready...6p,, R-6f,'6{, I"6E, P"Mv:!4!,B!Z 6^, ?  Starting [%1]S!x6p,,R-6f,'6{, I"6E, P"M :!4!,B!Y 6^, Ended6p,,R6{, H(6E, F(M{B!X 6^, Paused6p,,R-6f,'6{, D(6E, C(M  -GB!W JRJ%?J,?,?&WJ,<XD?J?,<Cppp0SW,:p0SX,CppR `/R |6^, )  Match [%1]C6p,,R6{, `<6E, q<MB!V JJ%WJ,<XD?J?,<Cppp0SW,:p0SX,Cppp0S,:p0S,6^, *  Online [%1]C6p,,R6{, H(6E, F({@-6f, Y ,wY @I*Y @I-BY @I8lB6^,6p,6{,6E,{Y _-6f,;{, 65-Z&*./" 0" +" ," 1* ;*ƥ"|,-@ILTHjzM}NmQqPt~py|YnXgaZxsrokdc[`l]wvhWSu{_eUERiVb\f^FG m<s<]ea0:wU*Y:.)Um~swm*Y. m(~YY YF=G y!{TournamentGameInfo%G F {G  E, HG z  F F HXppppG ,H,F EFXTournamentGameInfoEG F % r<v[PM] %3 %1: %2RGR&R u<mJI7Q ]-[ s-mQ %sG-mx--m -[ zQ l --m -[ zQ Z--m-[ B-[ -ms# Q  cG&S OQ &-[ -ms" .)UQGS&s G S ,@`\ @Q J=I&y"34A  G h-b e  YI&6-G-i/:4, -Fe -F  F  G \ -_ \ {2we *`.e >l`Vz \ f-b  G\Dpppp / -> e /: f$ x<zz#>I Oz%yz by Oz qJyJ p<@=u]6{@ v86E@ S9~-^ e!U 6^@ Logging in6p@,R:w%e!T qSw6^@ (  Idle [%1]q6p@,R6{@ a;6E@ e;-6f@'l:v %:{ %:i%e!S K=:v :{ :i6^@ .  Protected [%1]RK6:{ %6p@, RI6p@,R6{@ C;6E@ Z;-{!-` e!R 6^@ Muted6p@%R6{@ g;6E@ _<_%e!Q 6^@ Dead6p@%Re!P 6^@{-F6p@,R6{@ O:6E@ b:6p@,Rj@-6f@z ,wz @I*z @I-Bz @I8ge6^@6p@6{@6E@jz -6f@;j@ y@@`}<H&A~pH&,pG&,% [< "Account types"N=W a ^zW \ foreverQ|W &M\ forW &matches|W &U\ untilkW &\ forever\  A=iL#Dx-]JiG@W ]-F&W %-\syib i%-\b W  }b  n$b  n=i&1iZ-'x-'-\Z-'x-zW -]qiZ--]qix-'N  b N Gi% i] fi%D-\] W  bc] % q] i& qE%vE,I E ezI EH -'lEH -i%0-]#I ~I ,EH -] I ~I ,E G=iNStnO  U Dzt%Dt, t] &t!IwkZ Xget Engine.GameInfo GamePasswordb Xget Engine.GameInfo AdminPasswordJAPAllowed to play on server.JBPVIP slot access.JCPAdmin slot access.JDPPassword immune.JEPCan be idle.JFPGame supervisor.JGP Moderate.JKPSetup matches.JHPBan operator.JIPManage accounts.JJPServer administrator.JLPBan registered players.JMPHidden admin.'yUP R{P  (P iP t{it%zWWStWppW,St#O C O O ~O /&nO gVt%-Z t, {tF (tFaP u|ga-Z'i=t|t-G:`:|`$-G(-v}{-C(b H=c7LkB(r*a/!ha P.-I%' I=[l'i,[$*:[, j[[ L=kgMq P=`w& "  J Kz``s][%[%oW%W%T%T%m %m %[, [, W,W,T,T,m ,m ,[WT%[,s`I J%_I&_H,_,_|[xM vZ  Xub  XsK=[n=Wr=TX=m -i -lb`JIH|xvset Engine.GameInfo GamePassworduset Engine.GameInfo AdminPasswords[WTm $-lset IpServer.UdpServerUplink DoUplink TrueXset IpServer.UdpServerUplink DoUplink False%$ <$$New settings have been saved.1%1 has modified the basic server settings. @S=mj e.:mx:mStm Z=A& \+  A&B&C&D&E&  E=Lq;N?L%0&GL& q n%Y=V .8-!  Client ;client .8,!  Home O$ client d M$ .87!  Private message i client .8)!  Game ;gamew  f* .8<!  Info  f game  G .8/!  Moderator [$ game  Fw  e* .8E!  Match control  e game  K .81!  Match setup X$ game .8-!  Server ;serverw  g* .8>!  Info  g serverF  H .83!  Ban control K$ server  I .80!  Accounts _$ server  J .85!  Account types G$ server .8?!  Settings ;serversettingsserver .8<!  Basic ^$ server,serversettings .8L!  Nexgen Inexgensettingsserver,serversettings .84! Z$ server,serversettings,nexgensettings .84! T$ server,serversettings,nexgensettings .84! Q$ server,serversettings,nexgensettings .84! \$ server,serversettings,nexgensettings .8C!  Boot control L$ server,serversettings .8$!  About F$ O=zDLNQ2z.)Uwz*^ NzE^%z-l'zm=^zX g=^z-l(zm$zX n$z.)zUx \=@&"Hc-@&&%  hR=P3mRU]0:P &~MJ[:P ,~J @U=X= OXC?rf*f.> lwf*A' _=%QuSQ-M b, G|bU %-M'bU Nb [=~%XNX<~% %red &blue ),green 7,yellow   ]=1 "Write administrator actions to the server log"e=|%^ }|%  b=, "Write private messages to the server log"~<fpNi?Db>DODa6^fnk%n]nr6{f*n@iAHnH@@inA@@in l=YZXcUY a-U d, WzdU -U'dU Y^d h 0.60`= " -,."f=) "Write chat messages to the server log"b@n=d=qfZ$P%5P,@PeP@VUP%}P, @PFPOP%P,@PMP@O @Vg@Vf@:i@y@Ve@ g=+ "Write system messages to the server log"i= "Time format"j= "Log file name"k= "Log extension"v= "Log path"p=w%U? LC-c b, 9|bU w%-c'@b-c a= "\\n"q=[tC:[x[ $sI [M Z {:K:n:r"-i %,_ $%7, = %l, q>%, is%, W $%,a%H,c%w,L O%,b~%,} $%,b%S,l%%,hZ%,T%, }$"-t"-sIHWli Y$"-f"-G:|:`"-i"-] "-y"-]"-[%V,_( $:Ap:}:~:X "-j "-j "-v"-Z:j :]"-l "-p "-q :Rt"-u"-_"-B"-F $%,v $%,] $ "-G"-t"-J"-s"-P"-Y"-t ]d ^ ]   ^s= 10r= "S"J> "P"t= ","w= "?restart"Nt%| ?`S ?`*S u%Uv%gaS hcs cU@?,T.P ghS UT t%aS \T G>) "Write Nexgen events to the server log"U  "open"g}=y=n* ' @{=@H>|=T u=jmlknjp@kOajO.P lnpO l=A>B>C>@~=qd]hkLqjMkaK.P hLjkK s%Kk&hMj@kMqk.P hLjk D>P> "Write log messages to file"X>F>la hL> 2M> 1V> 0K>E>r%)#$I%IZtklsw@kFamr%{mz~m\nz%[mm[mzmmz}\n{[{o[I{%B[[2B[{&[[{&m.P tlwFm Bm kq%mp%lF[sl R>* "Write log messages to console (stdout)"N>S> "Log settings"e> ""Q>T>@Y> 6U>]>W>g k> 8@Z>@[>`>\><  O>|o&@,}|PzP&l~ -,.|P&%?P??P-P&PP c>^>Lq Pn%a>3eO _>o%9C/o%a g> "Replacement HUD class"d>}nYg3N~y%}ka }{R {a x%z.P }a R ~z zk&}{a }R @k{R @k}a ~.P }a R ~R , s> "Original HUD class"o>hN  }l> 9m> 8n> 7p> 6r>i>|B'  |> 5f>@y=8@m%l%Is Qcs Ts ?,Uc@IQTUQ l]0-a  t> "HUD replacement classes."v> "Ignore alternate fire"iz> "Ignore primary fire"Y }>w>fO r *(1 M q(Y %Y , Y  (] %,Y  (S t=Y (Y 8' q>j%4q;q.wq*wq-p ww*-pwwww-wwK-p.N-j% > "Weapon class"^=hq>U-6fhN ?l?,I@@@x?N CT?Db>Me%Tw6{h*AoJoN hJAN h?DoA@g$gl"gMN g+a6{hJJAAw6Eh*g$gMN g+a6EhJJAAMTJN hob@g$g6ph-6fhgb(g333?6g=D<6gN x6g=D<6gN x6g=D<6gN xgMN gOga6^h( A? 4F?] `] %M] ,Cw] I*] Ia] I*] ::$yw * a *w!*!a!*wN*NaN*w * a * y>i%MK?|i%true G?' "Weapons ignored by spawn protector."L? 3C?@D?@E?@@P?bTtr-w.*.8TbXpo,woI*oITbX- H?& "Auto disable match mode time (min)"I?% "Team kill push protect time (sec)"N?' "Team kill damage protect time (sec)"c "Reconnect"ZJ?A?!WZAk)h%A&$9A)g%A%$cf%,@ W? 2NK?d;N RNdiPrdc :i,Reconnect4 O? "Spawn protect time (sec)"Q?( "Max idle time in control panel (sec)"Y?d%d^p.;.8spluginclientsettingsrp*p.;.8<! Settings Ipluginclientsettingsclientp !d% R? "Max idle time (sec)"S? "Auto reconnect time (sec)"T? "Game start delay (sec)"U? "Game wait time (sec)"\?& "Register server in Nexgen database"ZjA ?"KZA k)b%A &$9A )a%A %$9A gnA `%Bj_%,@g,  e? 1NV?lD Nlnrlj :n,4c  g a.h> l{c wa*a hc Z?c%L Jq.;.8spluginsettingsrq*q.;.8D! Plugins Ipluginsettingsserver,serversettingsq !c% [?mj8K]Rjm(dNamem' ]?_&|;ppget  S .NexgenConfigExt bInstalledT'I|;ppget  S .NexgenConfigSys bInstalledT'MNexgenResidentConfigDialog ^?" "Name change allowed by default"k?^%z`a/!_-o.-.-(`Rx j:^%a/!_.--o _?# "Team balance allowed by default"`?" "Team switch allowed by default"a?! "Enable the Nexgen message HUD"b?2 "Broadcast administrator actions to all players"c?$ "Let Nexgen handle the game start"g?' "Don't decrease score on team switch"Z`|?"Z|k)\%|&$9|)[%|%$9|`d|Z%@Brd|Y%@B L@ 0@d?u#< M#zu` X%7` ur V% h? "Broadcast team kill attempts"l?, "Automatically remove expired ban entries"j?@@s?W%I# IW%]%-I ' m?$ "Automatically update ban entries"n? "General Nexgen settings"v? "Copy"w "Reconnect"Zo?B?!WZBk)U%B&$9B)T%B%$wS%,@ Np?y;R RNy{Pryw :{,Reconnect4 t?q?h--{!-`  G u?]?)-^ )-Fn< }gR }?H<*|2w.*.8<HFCzY,wYI*YI<HFC2 w? "Show message"x?& "Allow players to change their name"@@ "Mute all players"I "Reconnect"Zy?a ? bZa k)R%a &$9a )Q%a %$9a IP%,@ N Nz?J;O RNJRPrJI :R,Reconnect4 ~?|Uj|$:|, ;:|~$:| (] :|w# t|:|O":|~@(.8 3|r%r,wrI*rI 3|||$h:|,^:|}%!d:|}:|}%L|!d| N@OLyv!dL.8 LOsQ,wQI*QI LO5:O}L O%A@ "Ban"C@ "Kick"Z?c ?OZc k)O%c &$9c )N%c %$9c  E@ "Set name"{>R H$j3R -R -|,x%:R :R ,|:R |,| F@ "(Un)mute"G@ "IP address"Q@ "Client ID"W "OverrideClass"H@ "Botpack.CHSpectator"I@ "Reconnect"ZJ@f ?$zbZf k)L%f &$9f )K%f %$9f WJ%,@ I% ","NK@X># NXYrXW :Y,(b"OverrideClassBotpack.CHSpectator'Reconnect4 d@y3aѭKIU:yw:ywU:yO"M%:y~@' |T TS@ ""T@ "Send password"U@ "Stop match"V@ "Start match"W@ "Separate now"]@! "Automatically separate by tag"Z "Password"X@ "OverrideClass"Y@ "Reconnect"Z@ "Botpack.CHSpectator"Z[@J ?)]ZJ k)H%J &$9J )G%J %$9J DnJ F%BCD%,@ZE%,@D, _@ "Separate players by tag"@\@B%#I LD$ i 2_PasswordC-MB% h@5 "Automatically pause the game when a player leaves"a@@b@@@N^@E[ 'NEDrEZ :D,i ]_i $E_PasswordD i bReconnect4%rEC :D,C-(b"OverrideClassBotpack.CHSpectator'Reconnect4 y@C%>A{_-I T ,UwT I*|T IlC%-I'\T w-IT Iy* fiF1RIFF> WAVEfmt "VDdata #y[ 9 MJ \4][Y "*/.)!ɖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖζL̲ǨQNi .28<+:2-'wǖ)ۋͻS@݌& z'./1.(xJ] TO .@p ]@l.]U^  (  ^1LLISTBINFOICRD 1997-04-25IENG J@KER !ISFTSound Forge 4.0o@Fd)JB:Fa/!{ w*t.FF HTi@: "Automatically lock teams at the beginning of each game"j@7 "Switch back to last map when the server has crashed"k@# "Mute spectators during the game"l@9 "Allow spectators to enter the game without a password"q@ "Current game"B 60Zm@j?$"Zjk)@%j&$9jadj$B%Bdj~$B&Bj,Bj,Bj,Bjb}$,@ c2::$a  @n@|$#J za {$@ p|$\n@{@  o,X~@ \nE@ X@ @ X}\no%~,<~ZEoE~E%|EE|EEEEEoB  ||zE o,%XoxX,XBXK r@ "Number of games"u@ "Match settings"t@@o@z@ "Players"Z/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenUtil * $VERSION 1.15 (2-8-2008 15:14) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Utility class. Contains some usefull general purpose functions. * **************************************************************************************************/ class NexgenUtil extends Object; var float version; // Nexgen version number. var int versionCode; // Internal version number. var int internalVersion; // Internal version number. var string packageName; // Name of the Nexgen package. var string countryFlagsPkg; // Package containing the flag textures. const keyChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; const keyFormat = "5-5-5-5-5-5-4"; //const dateFormat = "mm/dd/yyyy"; const nexgenCommand = "NSC"; const separator = ","; const assignment = "="; const escapeToken = "\\"; const illegalFileNameChars = "\\/*?:<>\"|"; /*************************************************************************************************** * * $DESCRIPTION Generates a new unique key. * $RETURN A string containing a new unique key. * **************************************************************************************************/ static function string makeKey() { local string key; local int index; local string cs; local int size; local int count; for (index = 0; index < len(keyFormat); index++) { cs = mid(keyFormat, index, 1); if ("0" <= cs && cs <= "9") { size = int(cs); for (count = 0; count < size; count++) { key = key $ mid(keyChars, rand(len(keyChars)), 1); } } else { key = key $ cs; } } return key; } /*************************************************************************************************** * * $DESCRIPTION Replaces a specified substring in a string with another substring. * $PARAM source The original string, which is to be filtered. * $PARAM oldStr Substring in the original string that is to be replaced. * $PARAM newStr Replacement for the substring to be replaced. * $RETURN The specified string where all occurrences of oldStr are replaced with newStr. * **************************************************************************************************/ static function string replace(coerce string source, coerce string oldStr, coerce string newStr) { local bool bDone; local int subStrIndex; local string result; local string strLeft; strLeft = source; // Replace each occurrence of oldStr with newStr. while (!bDone) { // Find index of oldStr in the part not examined yet. subStrIndex = instr(strLeft, oldStr); // Update examined and unexamined parts. if (subStrIndex < 0) { bDone = true; result = result $ strLeft; } else { result = result $ left(strLeft, subStrIndex) $ newStr; strLeft = mid(strLeft, subStrIndex + len(oldStr)); } } // Return the filtered string. return result; } /*************************************************************************************************** * * $DESCRIPTION Formats the given string by inserting the specified strings into the proper * positions. The positions are indicated by the "%n" tags, where n is number of the * string to insert. * $PARAM source The string that is to be formatted. * $PARAM str1 String number 1 to insert. * $PARAM str2 String number 2 to insert. * $PARAM str3 String number 3 to insert. * $PARAM str4 String number 4 to insert. * $RETURN The formatted string. * **************************************************************************************************/ static function string format(string source, optional coerce string str1, optional coerce string str2, optional coerce string str3, optional coerce string str4) { local string formattedStr; formattedStr = replace(source, "%1", str1); formattedStr = replace(formattedStr, "%2", str2); formattedStr = replace(formattedStr, "%3", str3); formattedStr = replace(formattedStr, "%4", str4); return formattedStr; } /*************************************************************************************************** * * $DESCRIPTION Removes leading and trailing spaces from the given string. * $PARAM source The string for which the leading and trailing spaces are to be removed. * $RETURN The original string with all spaces removed from the front and back of the string. * $ENSURE len(result) > 0 ? left(result, 1) != " " && right(result, 1) != " " : true * **************************************************************************************************/ static function string trim(string source) { local int index; local string result; // Remove leading spaces. result = source; while (index < len(result) && mid(result, index, 1) == " ") { index++; } result = mid(result, index); // Remove trailing spaces. index = len(result) - 1; while (index >= 0 && mid(result, index, 1) == " ") { index--; } result = left(result, index + 1); // Return new string. return result; } /*************************************************************************************************** * * $DESCRIPTION Fills the given string from the left until it has a minimum length. * $PARAM source The original string. * $PARAM minLength Minimum length of the string. * $PARAM fillStr String used to fill up the original string. * $PARAM maxLength Maximum length of the string. * $REQUIRE minLength >= 0 && len(fillStr) > 0 * $RETURN The original string filled to a minimum length. * $ENSURE minLength <= len(result) && (maxLength >= minLength? len(result) <= maxLength : true) * **************************************************************************************************/ static function string lfill(coerce string source, int minLength, string fillStr, optional int maxLength) { local string result; // Add leading string until minLength is reached. result = source; while (len(result) < minLength) { result = fillStr $ result; } // Cut off. if (maxLength >= minLength && len(result) > maxLength) { result = right(result, maxLength); } // Return string. return result; } /*************************************************************************************************** * * $DESCRIPTION Fills the given string from the left until it has a minimum length. * $PARAM source The original string. * $PARAM minLength Minimum length of the string. * $PARAM fillStr String used to fill up the original string. * $PARAM maxLength Maximum length of the string. * $REQUIRE minLength >= 0 && len(fillStr) > 0 * $RETURN The original string filled to a minimum length. * $ENSURE minLength <= len(result) && (maxLength >= minLength? len(result) <= maxLength : true) * **************************************************************************************************/ static function string rfill(coerce string source, int minLength, string fillStr, optional int maxLength) { local string result; // Add trailing string until minLength is reached. result = source; while (len(result) < minLength) { result = result $ fillStr; } // Cut off. if (maxLength >= minLength && len(result) > maxLength) { result = left(result, maxLength); } // Return string. return result; } /*************************************************************************************************** * * $DESCRIPTION Parses the given command string. * $PARAM cmdStr The string containing the command and parameters. * $PARAM cmdName Name of the parsed command. * $PARAM args Arguments of the parsed command. * $RETURN True if the command is a Nexgen command, false if not. * **************************************************************************************************/ static function bool parseCommandStr(string cmdStr, out string cmdName, out string args[10]) { local string cmd; local int index; local int argCount; local string cc; local string lc; local int recStart; local int recEnd; local bool bRecStr; // Check command string. cmd = trim(cmdStr); index = instr(cmd, " "); if (index < 0 || caps(left(cmd, index)) != nexgenCommand) { // Not a valid command. return false; } // Get command name. cmd = trim(mid(cmd, index)); index = instr(cmd, " "); if (index < 0) { // No arguments, but it still is a commmand. cmdName = cmd; return true; } // Get command arguments. cmdName = left(cmd, index); cmd = mid(cmd, index) $ " "; // The extra space is to make sure the last argument gets stored. index = 0; recStart = -1; recEnd = -1; while (index < len(cmd) && argCount < arrayCount(args)) { // Fetch current character. cc = mid(cmd, index, 1); // Handle current character. if (cc == " ") { if (recStart >= 0 && !bRecStr) { // End of current argument. recEnd = index; } } else if (cc == "\"") { if (recStart < 0) { // Start recording a new argument. recStart = index + 1; bRecStr = true; } else if (lc != "\\") { // End of current argument. recEnd = index; bRecStr = false; } } else { if (recStart < 0) { // Start recording a new argument. recStart = index; } } // Store recorded strings. if (recEnd >= 0) { args[argCount++] = replace(mid(cmd, recStart, recEnd - recStart), "\\\"", "\""); recStart = -1; recEnd = -1; } // Continue with next character. lc = cc; index++; } // Yeah, it's a command. return true; } /*************************************************************************************************** * * $DESCRIPTION Adds a property to the given properties string. * $PARAM propStr The string where the property is to be added to. * $PARAM propName Name of the property to add. * $PARAM propValue The value of the property that is to be added. * $REQUIRE propName != "" * $ENSURE new.getProperty(propStr, propName) == propValue * **************************************************************************************************/ static function addProperty(out string propStr, string propName, coerce string propValue) { local string formattedValue; // Format value (in case it includes the separator tokens). formattedValue = replace(propValue, separator, escapeToken $ separator); // Update property string. if (propStr == "") { propStr = propName $ assignment $ formattedValue; } else { propStr = propStr $ separator $ propName $ assignment $ formattedValue; } } /*************************************************************************************************** * * $DESCRIPTION Reads a property from the given properties string. * $PARAM propStr The string where the property is to be read from. * $PARAM propName Name of the property to read. * $PARAM propDefaultValue The default value of the property to return if the property * string doesn't contain the specified property. * $REQUIRE propName != "" * $RETURN The value of the specified property in the given property string. * **************************************************************************************************/ static function string getProperty(string propStr, string propName, optional string propDefaultValue) { local int index; local bool bFound; local string remaining; local string saved; // Search until property is found or there are no properties left. remaining = propStr $ separator; index = instr(remaining, separator); while (!bFound && index >= 0) { // Check if the separator is preceeded by a escape token, i.e. a formatted value. if (index - len(escapeToken) >= 0 && mid(remaining, index - len(escapeToken), len(escapeToken)) == escapeToken) { // Escape token found, continue with next separator token. saved = saved $ left(remaining, index - len(escapeToken)) $ separator; remaining = mid(remaining, index + len(separator)); index = instr(remaining, separator); } else { // Property separator found, check name. saved = saved $ left(remaining, index); if (left(saved, len(propName) + len(assignment)) ~= (propName $ assignment)) { // Property found. bFound = true; } else { // Property name does not match continue search. saved = ""; remaining = mid(remaining, index + len(separator)); index = instr(remaining, separator); } } } // Return result. if (bFound) { return mid(saved, len(propName) + len(assignment)); } else { return propDefaultValue; } } /*************************************************************************************************** * * $DESCRIPTION Computes the date 'daysToCount' days after the specified date. * $PARAM daysToCount Number of days after the specified date. * $PARAM year Year of the starting date. * $PARAM month Month of the starting date. * $PARAM day Day of the starting date. * **************************************************************************************************/ static function computeDate(int daysToCount, out int year, out int month, out int day) { local int daysRemaining; daysRemaining = daysToCount; // Add years. while (daysRemaining > daysInYear(year)) { daysRemaining -= daysInYear(year); year++; } // Add months. while (daysRemaining > daysInMonth(year, month)) { daysRemaining -= daysInMonth(year, month); if (++month > 12) { month = 1; year++; } } // Add days. if (daysRemaining > daysInMonth(year, month) - day) { day = daysRemaining - daysInMonth(year, month) + day; if (++month > 12) { month = 1; year++; } } else { day += daysRemaining; } } /*************************************************************************************************** * * $DESCRIPTION Gives the number of days in the specified year. * $PARAM Year The year for which the number of days has to be returned. * $RETURN The number of days in the specified year. * $ENSURE result == isLeapYear(year) ? 366 : 365 * **************************************************************************************************/ static function int daysInYear(int year) { if (isLeapYear(year)) { return 366; } else { return 365; } } /*************************************************************************************************** * * $DESCRIPTION Gives the number of days in the specified year and month. * $PARAM Year The year for which the number of days has to be returned. * $PARAM Month The month for which the number of days has to be returned. * $RETURN The number of days in the specified year and month. * $ENSURE 28 <= result && result <= 31 * **************************************************************************************************/ static function int daysInMonth(int year, int month) { switch (month) { case 1: return 31; // January case 2: if (isLeapYear(year)) return 29; else return 28; // February case 3: return 31; // March case 4: return 30; // April case 5: return 31; // May case 6: return 30; // June case 7: return 31; // July case 8: return 31; // August case 9: return 30; // September case 10: return 31; // October case 11: return 30; // November case 12: return 31; // December }; } /*************************************************************************************************** * * $DESCRIPTION Checks whether the given year is a leap year. * $PARAM year The year for which has to be checked if it is a leap year or not. * $RETUN True if the specified year is a leap year, false if not. * **************************************************************************************************/ static function bool isLeapYear(int year) { return (year % 400 == 0) || (year % 4 == 0) && (year % 100 != 0); } /*************************************************************************************************** * * $DESCRIPTION Checks whether the given IP address is valid. * $PARAM ipAddress The IP address that is to be checked. * $RETURN True if the specified IP address is valid, false if not. * **************************************************************************************************/ static function bool isValidIPAddress(string ipAddress) { local bool bValid; local string remaining; local int index; local int currentSection; local string section; local int char; // Check each section. bValid = true; currentSection = 1; remaining = ipAddress; while (bValid && currentSection <= 4) { // Get section split point. index = instr(remaining, "."); // Split head section from tail. if (currentSection == 4 && index > 0) { // Already at byte 4, but still some sections remaining. bValid = false; } else if (index < 0 && currentSection != 4) { // Premature end of address. bValid = false; } else if (index > 0) { section = left(remaining, index); remaining = mid(remaining, index + 1); } else { section = remaining; remaining = ""; } // Check section. if (bValid) { // Check section length. bValid = section != "" && len(section) <= 3; // Check section characters. index = 0; while (bValid && index < len(section)) { char = asc(caps(mid(section, index, 1))); bValid = asc("0") <= char && char <= asc("9"); index++; } // Check section value. bValid = bValid && int(section) < 256; // Section check completed. currentSection++; } } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Checks whether the given client ID is valid. * $PARAM clientID The client ID that is to be checked. * $RETURN True if the specified client ID is valid, false if not. * **************************************************************************************************/ static function bool isValidClientID(string clientID) { local bool bValid; local int index; local int char; // Check length. bValid = len(clientID) == 32; // Check characters. while (bValid && index < 32) { char = asc(caps(mid(clientID, index, 1))); if (!(asc("0") <= char && char <= asc("9")) && !(asc("A") <= char && char <= asc("F"))) { bValid = false; } else { index++; } } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Checks whether the specified key is valid. * $PARAM key The key that is to be checked. * $RETURN True if the specified key is valid, false if not. * **************************************************************************************************/ static function bool isValidKey(string key) { local bool bValid; local int formatIndex; local int keyIndex; local int size; local int count; local string cs; bValid = true; // Check format. while (bValid && formatIndex < len(keyFormat)) { cs = mid(keyFormat, formatIndex, 1); // Check format token. if ("0" <= cs && cs <= "9") { // Check key characters. size = int(cs); count = 0; while (bValid && count < size && keyIndex < len(key)) { if (instr(keyChars, mid(key, keyIndex, 1)) < 0) { bValid = false; } else { count++; keyIndex++; } } } else { // Check literal token. if (mid(key, keyIndex, 1) != cs) { bValid = false; } else { keyIndex++; } } // Continue with next format token. formatIndex++; } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Serializes the specified date to a compact date description string. * $PARAM year Year of the specified date. * $PARAM month Month of the specified date. * $PARAM day Day of the specified date. * $PARAM hour Hour of the specified date. * $PARAM minute Minute of the specified date. * $REQUIRE (1 <= month && moth <= 12) && (1 <= day && day <= 31) && * (0 <= hour && hour <= 23) && (0 <= minute && minute <= 59) * $RETURN A description string of the serialized date. * **************************************************************************************************/ static function string serializeDate(int year, int month, int day, int hour, int minute) { return lfill(year, 4, "0") $ "_" $ lfill(month, 2, "0") $ "_" $ lfill(day, 2, "0") $ "_" $ lfill(hour, 2, "0") $ "_" $ lfill(minute, 2, "0"); } /*************************************************************************************************** * * $DESCRIPTION Parses the given date string. * $PARAM dateStr The date string to parse. * $PARAM year Year of the specified date. * $PARAM month Month of the specified date. * $PARAM day Day of the specified date. * $PARAM hour Hour of the specified date. * $PARAM minute Minute of the specified date. * $RETURN True if the specified date string was valid, false if not. When false is returned * the outcome (the date) should be ignored. * **************************************************************************************************/ static function bool readDate(string dateStr, out int year, out int month, out int day, out int hour, out int minute) { local bool bValid; local string remaining; local int index; bValid = true; remaining = class'NexgenUtil'.static.trim(dateStr); // Parse year. index = instr(remaining, "_"); if (index >= 0) { year = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } // Parse month. if (bValid) { index = instr(remaining, "_"); if (index >= 0) { month = int(left(remaining, index)); remaining = class'NexgenUtil'.static.trim(mid(remaining, index + 1)); } else { bValid = false; } } // Parse day. if (bValid) { index = instr(remaining, "_"); if (index >= 0) { day = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } } // Parse hour. if (bValid) { index = instr(remaining, "_"); if (index >= 0) { hour = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } } // Parse minute. if (bValid) { minute = int(remaining); } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Splits the head element for the tail in given string list. Elements are separated * by the separator token. * $PARAM list The list that is to be split. * $PARAM head The first element in the list. * $PARAM tail The remaining elements in the list. * **************************************************************************************************/ static function split(string list, out string head, out string tail) { local int index; index = instr(list, separator); if (index < 0) { head = list; tail = ""; } else { head = left(list, index); tail = mid(list, index + len(separator)); } } /*************************************************************************************************** * * $DESCRIPTION Splits the head element for the tail in given string list. Elements are separated * by the separator token. * $PARAM list The list that is to be split. * $PARAM head The first element in the list. * $PARAM tail The remaining elements in the list. * $PARAM separator The separator token to split on. * **************************************************************************************************/ static function split2(string list, out string head, out string tail, string separator) { local int index; index = instr(list, separator); if (index < 0) { head = list; tail = ""; } else { head = left(list, index); tail = mid(list, index + len(separator)); } } /*************************************************************************************************** * * $DESCRIPTION Gives the formatted GUID string of the raw GUID. * $PARAM rawGUIDStr The raw GUID string. * $REQUIRE len(rawGUIDStr) == 32 * $RETURN The formatted GUID string. * $ENSURE len(result) == 36 * **************************************************************************************************/ static function string formatGUID(string rawGUIDStr) { return left(rawGUIDStr, 8) $ "-" $ mid(rawGUIDStr, 8, 4) $ "-" $ mid(rawGUIDStr, 12, 4) $ "-" $ mid(rawGUIDStr, 16, 4) $ "-" $ mid(rawGUIDStr, 20, 12); } /*************************************************************************************************** * * $DESCRIPTION Removes the leading color tag from the specified message. * $PARAM msg The message for which the color tag has to be removed. * $RETURN The original message without a leading color tag. * **************************************************************************************************/ static function string removeMessageColorTag(string msg) { if (left(msg, 2) ~= "") { return mid(msg, 5); } else { return msg; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the base color of the message. * $PARAM msg The message for which the base color is be determined. * $RETURN The base color of the message based on the leading color tag, or -1 if none is * present. * **************************************************************************************************/ static function int getMessageColor(string msg) { if (left(msg, 2) ~= "") { return int(mid(msg, 2, 2)); } else { return -1; } } /*************************************************************************************************** * * $DESCRIPTION Gives the integer hash value of a string. * $PARAM str The string that is to be hashed. * $RETURN The hash value of the given string. * **************************************************************************************************/ static function int stringHash(coerce string str) { local int hash; local int index; for (index = 0; index < len(str); index++) { hash = 31 * hash + asc(mid(str, index, 1)); } return hash; } /*************************************************************************************************** * * $DESCRIPTION Auto formats the specified string by inserting the values into the placeholders. * $PARAM control The Nexgen controller. * $PARAM msg The message that is to be auto formatted. * $REQUIRE control != none * $RETURN The auto formatted string. * **************************************************************************************************/ static function string autoFormat(NexgenController control, string msg) { local string output; output = msg; if (instr(output, "%port%") >= 0) { output = replace(output, "%port%", control.level.game.getServerPort()); } if (instr(output, "%name%") >= 0 && control.sConf != none) { output = replace(output, "%name%", control.sConf.serverName); } if (instr(output, "%admin%") >= 0 && control.sConf != none) { output = replace(output, "%admin%", control.sConf.adminName); } if (instr(output, "%serverid%") >= 0 && control.sConf != none) { output = replace(output, "%serverid%", control.sConf.serverID); } output = control.lng.getCurrentDate(output); return output; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the file name of the specified level. * $RETURN The filename of the specified level. * **************************************************************************************************/ static function string getLevelFileName(LevelInfo lvl) { local string levelFile; levelFile = string(lvl); levelFile = left(levelFile, instr(levelFile, ".")) $ ".unr"; return levelFile; } /*************************************************************************************************** * * $DESCRIPTION Validates the specified file name by replacing the illegal characters with a * valid character. * $PARAM fileName name of the file that is to be validated. * $RETURN A valid file name. * $ENSURE foreach(char in illegalFileNameChars) instr(result, char) < 0 * **************************************************************************************************/ static function string validateFileName(string fileName) { local int index; local string output; output = fileName; for (index = 0; index < len(illegalFileNameChars); index++) { output = replace(output, mid(illegalFileNameChars, index, 1), "_"); } return output; } /*************************************************************************************************** * * $DESCRIPTION Checks whether the specified level is a valid game map. Use this function to * filter the Unreal Tournament system and tutorial maps from a list. * $PARAM levelFile File name of the level which is to be checked. In case no extension is * specified, the file name will be appended with ".unr" * $RETURN True if the specified level is valid for play, false if not. * **************************************************************************************************/ static function bool isValidLevel(string levelFile) { local string mapName; local bool bInvalidMap; // Get map name. mapName = levelFile; if (instr(mapName, ".") < 0) { mapName = mapName $ ".unr"; } // Check if the map is invalid. bInvalidMap = mapName ~= "CityIntro.unr" || mapName ~= "AutoPlay.unr" || mapName ~= "Entry.unr" || mapName ~= "UTCredits.unr" || mapName ~= "UT-Logo-Map.unr" || instr(caps(mapName), separator) >= 0 || instr(caps(mapName), "EOL_") >= 0 || instr(caps(mapName), "TUTORIAL") >= 0; // Return result. return !bInvalidMap; } /*************************************************************************************************** * * $DESCRIPTION Encodes the specified string as if it is an URL. * $PARAM url The string that is to be encoded as an URL. * $PARAM maxLength The maximum length of the output. A value below 1 means the length of * the output won't be limited. * $RETURN Returns a string in which all non-alphanumeric characters except -_. have been * replaced with a percent (%) sign followed by two hex digits and spaces encoded as * plus (+) signs. * **************************************************************************************************/ static function string urlEncode(string url, optional int maxLength) { local int index; local string cs; local string ns; local string output; local bool bMaxOutputLengthReached; // Encode each character in the url string. while (!bMaxOutputLengthReached && index < len(url)) { // Retrieve character to encode. cs = mid(url, index, 1); // Encode character. if (("0" <= cs && cs <= "9") || ("a" <= cs && cs <= "z") || ("A" <= cs && cs <= "Z") || (cs == "-") || (cs == "_") || (cs == ".")) { ns = cs; } else if (cs == " ") { ns = "+"; } else { ns = "%" $ class'MD5Hash'.static.decToHex(asc(cs), 1); } // Add character if it doesn't exceed the maximum length of the output string. if ((maxLength > 0) && (len(output) + len(ns) > maxLength)) { bMaxOutputLengthReached = true; } else { output = output $ ns; index++; } } // Return URL encoded string return output; } /*************************************************************************************************** * * $DESCRIPTION Splits the given string in two parts: the first line and the rest. * $PARAM str The string that should be splitted. * $RETURN The first line in the given string. * **************************************************************************************************/ static function string getNextLine(out string str) { local string line; local int indexCRLF; local int indexCR; local int indexLF; // Get location of newline token. indexCRLF = instr(str, chr(13) $ chr(10)); indexCR = instr(str, chr(13)); indexLF = instr(str, chr(10)); // Split data. if (indexCRLF >= 0) { line = left(str, indexCRLF); str = mid(str, indexCRLF + 2); } else if (indexCR >= 0) { line = left(str, indexCR); str = mid(str, indexCR + 1); } else if (indexLF >= 0) { line = left(str, indexLF); str = mid(str, indexLF + 1); } else { line = str; str = ""; } // Return result. return line; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ ]1/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenTextFile * $VERSION 1.01 (17-6-2008 13:53) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION General purpose class to support writing to text files. * **************************************************************************************************/ class NexgenTextFile extends StatLogFile; var bool bIsOpen; // Whether the text file is open. /*************************************************************************************************** * * $DESCRIPTION Called when this object is spawned. * $OVERRIDE * **************************************************************************************************/ function beginPlay() { // Do nothing, just prevent setTimer() from being called. } /*************************************************************************************************** * * $DESCRIPTION Creates a new text file. Initially the file will be named 'tempFileName'. Once the * file is closed it will be renamed to 'fileName'. * $RETRUN True if the text file was successfully opened, false if it failed. * $ENSURE imply(result == true, bIsOpen) * **************************************************************************************************/ function bool openFile(string tempFileName, string fileName) { if (tempFileName == "" || fileName == "" || bIsOpen) { return false; } statLogFile = tempFileName; statLogFinal = fileName; openLog(); bIsOpen = true; return true; } /*************************************************************************************************** * * $DESCRIPTION Closes the file. Before the file is closed any buffered text will be flushed. * **************************************************************************************************/ function closeFile() { if (bIsOpen) { fileFlush(); closeLog(); bIsOpen = false; } } /*************************************************************************************************** * * $DESCRIPTION Writes a new line to the text file. * $PARAM text The text that is to be written to the file * $PARAM bNoFlush Whether the text should be buffered, instead of written immediately. * **************************************************************************************************/ function println(string text, optional bool bBuffer) { if (bIsOpen) { logEventString(text); if (!bBuffer) fileFlush(); } } /*************************************************************************************************** * * $DESCRIPTION Flushes the buffer. Any text remaining in the buffer will be written to the file. * **************************************************************************************************/ function flush() { if (bIsOpen) { fileFlush(); } } ~/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenTeamBalancer * $VERSION 1.03 (28-12-2007 21:16) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Team balancing support class. The sole purpose of this class is to provide team * balancing support. This support has been put in a separate class so plugins can * change the default team balancing routine to a custom routine. * **************************************************************************************************/ class NexgenTeamBalancer extends Info; var NexgenController control; // The Nexgen controller. const maxTeamCount = 4; // Maximum number of teams supported. /*************************************************************************************************** * * $DESCRIPTION Initializes the team balancer. * $OVERRIDE * **************************************************************************************************/ function preBeginPlay() { // Check owner. if (owner == none || !owner.isA('NexgenController')) { destroy(); return; } // Set controller. control = NexgenController(owner); } /*************************************************************************************************** * * $DESCRIPTION Attempts to balance the current teams. * $RETURN True if the teams have been balanced, false if they are already balanced. * **************************************************************************************************/ function bool balanceTeams() { local NexgenClient client; local int teamSize[4]; local int totalPlayers; local int numTeams; local int minPlayersPerTeam; local int index; local int targetTeam; local NexgenClient preferredSwitchers[32]; // Assume the game has at most 32 players. local int prefSwitchTeamOffsets[4]; local int switchedCount[4]; // Get number of teams. if (level.game.isA('TeamGamePlus')) { numTeams = TeamGamePlus(level.game).maxTeams; } else { // Not a team game, so we're unable to balance the teams. return false; } // Get current team sizes. for (client = control.clientList; client != none; client = client.nextClient) { if (!client.bSpectator && 0 <= client.team && client.team < maxTeamCount) { teamSize[client.team]++; totalPlayers++; } } // Check if teams are already balanced. if (teamSize[getLargestTeam(teamSize, numTeams)] - teamSize[getSmallestTeam(teamSize, numTeams)] < 2) { return false; } // Calculate minimum players per team. minPlayersPerTeam = totalPlayers / numTeams; // Get player switch desirability rankings. initPreferredSwitchers(preferredSwitchers, prefSwitchTeamOffsets); // Determine rebalance actions. for (index = 0; index < numTeams; index++) { while(teamSize[index] < minPlayersPerTeam || teamSize[index] > minPlayersPerTeam + 1) { // Switch a player. if (teamSize[index] < minPlayersPerTeam) { // Too few players, steal one from the largest team. targetTeam = getLargestTeam(teamSize, numTeams); teamSize[index]++; teamSize[targetTeam]--; switchPreferredPlayer(targetTeam, index, preferredSwitchers, prefSwitchTeamOffsets, switchedCount); } else { // Too many players, dump one at the smallest team. targetTeam = getSmallestTeam(teamSize, numTeams); teamSize[index]--; teamSize[targetTeam]++; switchPreferredPlayer(index, targetTeam, preferredSwitchers, prefSwitchTeamOffsets, switchedCount); } } } // Team balance complete. return true; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the index of the team with the most players. * $PARAM teamSize The current team sizes. * $PARAM numTeams The number of teams available in the current game. * $REQUIRE 0 < numTeams && numTeams <= maxTeamCount * $RETURN The team number of the biggest team. * $ENSURE 0 <= result && result < numTeams * **************************************************************************************************/ function int getLargestTeam(int teamSize[4], int numTeams) { local int largest; local int index; // Find largest team. for (index = 1; index < numTeams; index++) { if (teamSize[index] > teamSize[largest]) { largest = index; } } // Return result. return largest; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the index of the team with the least players. * $PARAM teamSize The current team sizes. * $PARAM numTeams The number of teams available in the current game. * $REQUIRE 0 < numTeams && numTeams <= maxTeamCount * $RETURN The team number of the smallest team. * $ENSURE 0 <= result && result < numTeams * **************************************************************************************************/ function int getSmallestTeam(int teamSize[4], int numTeams) { local int smallest; local int index; // Find smallest team. for (index = 1; index < numTeams; index++) { if (teamSize[index] < teamSize[smallest]) { smallest = index; } } // Return result. return smallest; } /*************************************************************************************************** * * $DESCRIPTION Initializes the list containing the players with the highest switch desirability. * $PARAM preferredSwitchers List containing the most preferred players for team * switching per team. Sorted in descending order. * $PARAM prefSwitchTeamOffsets Starting offsets in the preferredSwitchers array for each team. * **************************************************************************************************/ function initPreferredSwitchers(out NexgenClient preferredSwitchers[32], out int prefSwitchTeamOffsets[4]) { local int team; local int nextOffset; local NexgenClient client; local NexgenClient tempClient; local bool bSorted; local int index; // Add preferred players for each team. for (team = 0; team < maxTeamCount; team++) { prefSwitchTeamOffsets[team] = nextOffset; // Add each player belonging to this team. for (client = control.clientList; client != none; client = client.nextClient) { if (client.team == team && nextOffset < arrayCount(preferredSwitchers)) { // Add to end of list. preferredSwitchers[nextOffset] = client; // Sort list. bSorted = false; index = nextOffset - 1; while (!bSorted && index >= prefSwitchTeamOffsets[team]) { // Player is correctly positioned in the list? if (compareSwitchDesirability(preferredSwitchers[index], preferredSwitchers[index + 1]) >= 0) { // Yes, list sort done. bSorted = true; } else { // No, switch players. tempClient = preferredSwitchers[index]; preferredSwitchers[index] = preferredSwitchers[index + 1]; preferredSwitchers[index + 1] = tempClient; index--; } } // Update next player offset. nextOffset++; } } } } /*************************************************************************************************** * * $DESCRIPTION Switches the next preferred player from team oldTeam to newTeam. * $PARAM oldTeam The team from which a player is to be switched. * $PARAM newTeam Target team for the player. * $PARAM preferredSwitchers List containing the most preferred players for team * switching per team. Sorted in descending order. * $PARAM prefSwitchTeamOffsets Starting offsets in the preferredSwitchers array for each team. * $PARAM switchedCount Number of players that already have been switched for each team. * $REQUIRE 0 <= oldTeam && oldTeam <= maxTeamCount && * 0 <= newTeam && newTeam <= maxTeamCount && * oldTeam != newTeam * $ENSURE old.switchedCount[oldTeam] = old.switchedCount[oldTeam] + 1 * **************************************************************************************************/ function switchPreferredPlayer(int oldTeam, int newTeam, NexgenClient preferredSwitchers[32], int prefSwitchTeamOffsets[4], out int switchedCount[4]) { local NexgenClient preferred; // Get preferred player. preferred = preferredSwitchers[prefSwitchTeamOffsets[oldTeam] + switchedCount[oldTeam]]; // Switch the player. switchedCount[oldTeam]++; preferred.setTeam(newTeam); } /*************************************************************************************************** * * $DESCRIPTION Compares the switch desirability of two players. * $PARAM client1 The client of the first player. * $PARAM client2 The client of the second player. * $REQUIRE client1 != none && client2 != none && client1.team == client2.team * $RETURN -1 if the switch desirability of the first player is lower then the switch * desirability of the second player, 1 if it is higher and 0 if they are equal. * $ENSURE result == -1 || result == 0 || result == 1 * **************************************************************************************************/ function int compareSwitchDesirability(NexgenClient client1, NexgenClient client2) { if (client1.lastSwitchTime < client2.lastSwitchTime && client2.player.playerReplicationInfo.hasFlag == none || client1.player.playerReplicationInfo.hasFlag != none) { return -1; } else { return 1; } } {@z$S-?-C H,5rHI*-C'<H-CM az$M  M RM |A%HIM M  }@ "Author"DAy$K y$ Np@dSNdgQrdb :g,he ij4 ~@ "Title"@ "File"@A "Level"CA "Mutators"Zv$F?qDZFk)v$F&$9F)u$F%$ F/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenSimplePlayerListBox * $VERSION 1.00 (13-10-2007 18:28) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Simple player listbox GUI component. * **************************************************************************************************/ class NexgenSimplePlayerListBox extends NexgenPlayerListBox; /*************************************************************************************************** * * $DESCRIPTION Returns the text displayed for a list item. * $PARAM item The item for which its display text has to be determined. * $REQUIRE item != none * $RETURN The text that should be displayed for the specified item in the listbox. * $OVERRIDE * **************************************************************************************************/ function string getDisplayText(NexgenPlayerList item) { return item.pName; } FA "Name change allowed"EAt$db"t$w$-x$ WAjEe-:j&b"OverrideClass'kk:j,(b"OverrideClassBotpack.CHSpectator'Reconnect GA "Teams are locked"HA "Team balancing enabled"JA "Team switch enabled"p$@KA "Game speed"RA "Team score limit"i "OverrideClass"LA "Reconnect"MA "Botpack.CHSpectator"ZNAe ?)FZe k)s$e &$9e )r$e %$9e ne xo$,@ip$,@ u/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenSimpleListItem * $VERSION 1.00 (14-10-2007 22:36) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Simple list item description class. Stores only two properties a display name and * an item identifier. * **************************************************************************************************/ class NexgenSimpleListItem extends UWindowListBoxItem; var string displayText; var int itemID; /*************************************************************************************************** * * $DESCRIPTION Compares two UWindowList items. * $PARAM a First item to compare. * $PARAM b Second item to compare. * $REQUIRE a != none && b != none * $RETURNS -1 If the first item is 'smaller' then the second item, otherwise 1 is returned. * $OVERRIDE * **************************************************************************************************/ function int compare(UWindowList a, UWindowList b) { if (NexgenSimpleListItem(a).displayText < NexgenSimpleListItem(b).displayText) { return -1; } else { return 1; } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ @OAn$#E5 4n)  q$n$m$l$ SA "Score limit"TA "Time limit"XA "Date"@NQAtVtNtsPrti :s,Reconnect4rtx :s,x-(b"OverrideClassBotpack.CHSpectator'Reconnect4 vAreHw.*.L..~o-'oZ{r.8 mr YA "FPH"ZA "Top players"\A "Total caps"x4/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenSimpleListBox * $VERSION 1.01 (31-10-2007 13:44) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Simple listbox GUI component. * **************************************************************************************************/ class NexgenSimpleListBox extends UWindowListBox; /*************************************************************************************************** * * $DESCRIPTION Renders the specified listbox item. * $PARAM c The canvas object on which the rendering will be performed. * $PARAM item Item to render. * $PARAM x Horizontal offset on the canvas. * $PARAM y Vertical offset on the canvas. * $PARAM w Width of the item that is to be rendered. * $PARAM h Height of the item that is to be rendered. * $REQUIRE c != none && item != none * $OVERRIDE * **************************************************************************************************/ function drawItem(Canvas c, UWindowList item, float x, float y, float w, float h) { if(NexgenSimpleListItem(item).bSelected) { c.drawColor.r = 0; c.drawColor.g = 0; c.drawColor.b = 128; drawStretchedTexture(c, x, y, w, h - 1, Texture'WhiteTexture'); c.drawColor.r = 255; c.drawColor.g = 255; c.drawColor.b = 255; } else { c.drawColor.r = 0; c.drawColor.g = 0; c.drawColor.b = 0; } c.font = root.fonts[F_Normal]; clipText(c, x + 2, y, NexgenSimpleListItem(item).displayText); } /*************************************************************************************************** * * $DESCRIPTION Retrieves the item with the specified id number. * $PARAM itemID The id number of the item to return. * $RETURN The item that has the specified id number, or none if there is no item with the * specified id number. * **************************************************************************************************/ function NexgenSimpleListItem getItemByID(int itemID) { local NexgenSimpleListItem item; // Search for item. for (item = NexgenSimpleListItem(items); item != none; item = NexgenSimpleListItem(item.next)) { if (item.itemID == itemID) { return item; } } // Item not found, return none. return none; } /*************************************************************************************************** * * $DESCRIPTION Called when an item was double clicked on. * $PARAM item The item which was double clicked. * $REQUIRE item != none * $OVERRIDE * **************************************************************************************************/ function doubleClickItem(UWindowListBoxItem item) { if (notifyWindow != none) { notifyWindow.notify(self, DE_DoubleClick); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ ]A "Total deaths"^A "Total frags"mA "Games hosted"r 4.0_A 4.0`A 4.0aA 64.0bA 16.0cA 48.0dA 12.0eA 16.0fA "say"gAp?-6mBhApm@h@r.P pmhr h$ppm@@q.P pmhq g$hAmp@@B?,@p@@B@h@@.P pmh@m@,@z 'm@Bh@Ap@h@p.P pmhp f$p$ CI/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenServerFullDialog * $VERSION 1.01 (23-12-2006 14:15) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player has entered an invalid password. * **************************************************************************************************/ class NexgenServerFullDialog extends NexgenPopupDialog; var UWindowSmallButton reconnectButton; // Reconnect button component. var UWindowSmallButton spectatorButton; // Spectator button component. var UMenuLabelControl slotLabel; // Slot label component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. var localized string slotMessage; // Message describing the amount of slots. var localized string passwordText; // Label to display before the password field. var localized string reconnectText; // Text to display on the reconnect button. var localized string spectatorText; // Text to display on the spectator button. const SSTR_OverrideClass = "OverrideClass"; // Override class setting string. const reconnectCommand = "Reconnect"; // Console command for reconnecting. const spectatorClass = "Botpack.CHSpectator"; // Override class to use for spectators. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $ENSURE reconnectButton != none && spectatorButton != none * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); addNewLine(cy); slotLabel = addLabel(cy); spectatorButton = addButton(spectatorText, 64.0); reconnectButton = addButton(reconnectText, 64.0); } /*************************************************************************************************** * * $DESCRIPTION Sets the contents for this dialog. * $PARAM playerSlots Number of slots available for regular players. * $PARAM vipSlots Number of slots available for VIPs. * $PARAM adminSlots Number of slots available for administrators. * $PARAM str4 Not used. * $OVERRIDE * **************************************************************************************************/ function setContent(optional string playerSlots, optional string vipSlots, optional string adminSlots, optional string str4) { slotLabel.setText(class'NexgenUtil'.static.format(slotMessage, playerSlots, vipSlots, adminSlots)); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the reconnect or spectator buttons have been clicked and deals with it * accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType){ super.notify(control, eventType); // Reconnect button. if (control == reconnectButton && eventType == DE_Click) { getplayerowner().consoleCommand(reconnectCommand); close(); } // Spectator button. if (control == spectatorButton && eventType == DE_Click && !spectatorButton.bDisabled) { getplayerowner().updateURL(SSTR_OverrideClass, spectatorClass, true); getplayerowner().consoleCommand(reconnectCommand); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ CiAVAD 2 jA yiCnŔ> Y7XÔ> Y> Y᱘ 3B V]"!Failed to login: server is full.m:xThe server you have tried to enter has no more player slots available. You can try again in a few minutes or reconnect immediately as a spectator. Note that the server may appear to have some unused slots available. These are reserved slots for VIPs or administrators and are not accessible for regular players.J]MKThis server has %1 regular players slots, %2 VIP slots and %3 admin slots.]] Password:i] Reconnectd] Spectatorn/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenScrollPanelContainer * $VERSION 1.01 (11-3-2008 21:32) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen control panel page container scroll version. * **************************************************************************************************/ class NexgenScrollPanelContainer extends NexgenPanelContainer; var UWindowPageWindow clientArea; // Scrollable window. var UWindowVScrollBar scrollBar; // Vertical scrollbar control. var NexgenPanel panels[32]; // Panels displayed on this panel. var int numPanels; // Number of panels displayed. var float clientAreaDesiredHeight; // Desired height of the client area. var float nextPanelOffset; // Next vertical offset on the client area. const panelDistance = 4.0; // Distance between panels. const borderDistance = 6.0; // Disatnce between panels and the border of the client area. const defaultPanelHeight = 288.0; // Default height of panels displayed on the client area. /*************************************************************************************************** * * $DESCRIPTION Creates the layout for this panel. * $OVERRIDE * **************************************************************************************************/ function created() { super(NexgenPanel).created(); clientArea = UWindowPageWindow(createWindow(class'UWindowPageWindow', 0, 0, winWidth - 16, winHeight - 6, ownerWindow)); scrollBar = UWindowVScrollbar(createWindow(class'UWindowVScrollbar', winWidth - 16, 0, 12, winHeight - 6)); scrollBar.bAlwaysOnTop = true; clientAreaDesiredHeight = 2 * borderDistance; nextPanelOffset = borderDistance; } /*************************************************************************************************** * * $DESCRIPTION Prepares the window for the paint call. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function beforePaint(Canvas c, float x, float y) { local float clientWidth, clientHeight; local bool bNeedScrollBar; clientWidth = winWidth - 12; clientHeight = clientAreaDesiredHeight; if (clientHeight <= winHeight) { clientHeight = winHeight; } else { bNeedScrollBar = true; } clientArea.setSize(clientWidth, clientHeight); if (bNeedScrollBar) { scrollBar.setRange(0, clientHeight, scrollBar.winHeight, 10); } else { scrollBar.setRange(0, 0, 0, 0); scrollBar.pos = 0; } clientArea.winTop = -scrollBar.pos; super.beforePaint(c, x, y); } /*************************************************************************************************** * * $DESCRIPTION Retrieves the desired window dimensions. * $PARAM w The desired width. * $PARAM h The desired height. * $OVERRIDE * **************************************************************************************************/ function getDesiredDimensions(out float w, out float h){ super(UWindowWindow).getDesiredDimensions(w, h); } /*************************************************************************************************** * * $DESCRIPTION Renders the GUI component. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y) { // Ignore. } /*************************************************************************************************** * * $DESCRIPTION Retrieves the panel with the specified name. * $PARAM panelName Name of the panel that is to be returned. * $REQUIRE panelName != "" * $RETURN The panel that was requested or none if the panel wasn't found. * $OVERRIDE * **************************************************************************************************/ function NexgenPanel getPanel(string panelName) { local NexgenPanel panel; local int index; // Search for panel. while (panel == none && index < numPanels) { if (panels[index].panelIdentifier ~= panelName) { panel = panels[index]; } else if (panels[index].isA('NexgenPanelContainer')) { panel = NexgenPanelContainer(panels[index]).getPanel(panelName); } index++; } // Return result. return panel; } /*************************************************************************************************** * * $DESCRIPTION Adds a new NexgenPanel to the container or one of its subcontainers. To specify * a specific parent use the parent parameter to indicate the path, e.g. * "plugin,settings". If an invalid path is specified the panel won't be created. * $PARAM title Text to display in the tab header. * $PARAM panelClass Type of NexgenPanel to add/create. * $PARAM identifier Identifier to assign to the new panel. * $PARAM parent Path where to the parent of the new panel. * $REQUIRE panelClass != none * $RETURN The panel that was created and added to the container, or none if an invalid path * to the parent container was specified. * $OVERRIDE * **************************************************************************************************/ function NexgenPanel addPanel(string title, class panelClass, optional string identifier, optional string parent) { local NexgenPanel newPanel; local string parentPanel; local string subPanels; local NexgenPanelContainer container; local bool bFound; local int index; local float desiredPanelHeight; // Add to subpanel? if (parent != "") { // Get local parent name. class'NexgenUtil'.static.split(parent, parentPanel, subPanels); // Locate local parent. while (!bFound && index < numPanels) { if (panels[index].isA('NexgenPanelContainer') && NexgenPanelContainer(panels[index]).panelIdentifier ~= parentPanel ) { bFound = true; newPanel = NexgenPanelContainer(panels[index]).addPanel(title, panelClass, identifier, subPanels); } else { index++; } } } else { // Nope, add it to the scroll panel. if (numPanels < arrayCount(panels)) { // Determine panel height. desiredPanelHeight = panelClass.default.panelHeight; if (desiredPanelHeight <= 0) { desiredPanelHeight = defaultPanelHeight; } // Create control. newPanel = NexgenPanel(clientArea.createWindow(panelClass, borderDistance, nextPanelOffset, clientArea.winWidth - 2 * borderDistance, desiredPanelHeight)); panels[numPanels] = newPanel; if (identifier != "") { newPanel.panelIdentifier = identifier; } newPanel.client = self.client; newPanel.setContent(); // Update client area metrics. clientAreaDesiredHeight += desiredPanelHeight; if (numPanels > 0) { clientAreaDesiredHeight += panelDistance; } nextPanelOffset += desiredPanelHeight + panelDistance; numPanels++; } } // Return created panel. return newPanel; } /*************************************************************************************************** * * $DESCRIPTION Selects the panel with the specified name. * $PARAM panelName The name of the panel that is to be selected. * $RETURN True if the panel was selected, false if it wasn't found. * $OVERRIDE * **************************************************************************************************/ function bool selectPanel(string panelName) { local int index; local bool bFound; while (!bFound && index < numPanels) { // Check panel. if (panels[index].panelIdentifier ~= panelName) { // Panel found, select it. bFound = true; } else if (panels[index].isA('NexgenPanelContainer')) { // No, but page is a NexgenPanelContainer, so it may include the panel. bFound = NexgenPanelContainer(panels[index]).selectPanel(panelName); } // Panel found? if (bFound) { // Panel found, select it. scrollBar.pos = panels[index].winTop; } else { // No, continue with next page. index++; } } return bFound; } /*************************************************************************************************** * * $DESCRIPTION Notifies the sub panels on this panel that the server configuration has been * updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { local int index; for (index = 0; index < numPanels; index++) { panels[index].configChanged(configType); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * $OVERRIDE * **************************************************************************************************/ function gameInfoChanged(byte infoType) { local int index; for (index = 0; index < numPanels; index++) { panels[index].gameInfoChanged(infoType); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * $OVERRIDE * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { local int index; for (index = 0; index < numPanels; index++) { panels[index].playerEvent(playerNum, eventType, args); } } /*************************************************************************************************** * * $DESCRIPTION Called when a general event has occurred in the system. * $PARAM type The type of event that has occurred. * $PARAM argument Optional arguments providing details about the event. * **************************************************************************************************/ function notifyEvent(string type, optional string arguments) { local int index; for (index = 0; index < numPanels; index++) { panels[index].notifyEvent(type, arguments); } } e/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenResidentConfigDialog * $VERSION 1.00 (16-12-2007 15:32) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog displayed if a resident Nexgen configuration is detected. * **************************************************************************************************/ class NexgenResidentConfigDialog extends NexgenPopupDialog; var localized string caption; // Caption to display on the dialog. var localized string message; // Message to dispay on the dialog. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ oA "Stats"hAvy\<vc$b$vQ pA "Server ID"qA "Message of the day"yA "Contact address"nAJm~JKHrJr :K,. 4rJq :K,@W:$ rJ@ :K,Q ClAAAF 2sAGCn V]&%Local Nexgen configuration detected!mRPA Nexgen configuration has been detected on your client. This may prevent your client from initializing correctly. If you experience problems delete Nexgen.ini or the Nexgen configuration stored UnrealTournament.ini. You can find these files in the system folder of your Unreal Tournament installation.\n \nSorry for the inconvenience.e"Ny/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPUserAccounts * $VERSION 1.03 (9-8-2008 19:28) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen user account control panel page. * **************************************************************************************************/ class NexgenRCPUserAccounts extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var UWindowCheckbox rightEnableInp[18]; var NexgenPlayerACListBox playerList; var NexgenSimpleListBox accountList; var UWindowComboControl accountTypeList; var NexgenEditControl accountNameInp; var NexgenEditControl accountTitleInp; var UWindowSmallButton addButton; var UWindowSmallButton updateButton; var UWindowSmallButton deleteButton; const invalidAccountType = -1; // Invalid or no account type selected. const customAccountType = 0; // Custom account type selected. const defaultAccountType = 1; // Default account type selected. /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int index; local string rightDef; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist); divideRegionH(2, defaultComponentDist); // User info panel. p = addContentPanel(); p.splitRegionH(64); p.splitRegionV(96); p.splitRegionH(16, , , true); p.divideRegionH(3); p.divideRegionH(3); p.divideRegionV(2, defaultComponentDist); p.splitRegionV(192); p.addLabel(client.lng.userNameTxt, true); p.addLabel(client.lng.accountTypeTxt, true); p.addLabel(client.lng.userTitleTxt, true); accountNameInp = p.addEditBox(); accountTypeList = p.addListCombo(); accountTitleInp = p.addEditBox(); p.divideRegionH(arraycount(rightEnableInp) / 2); p.divideRegionH(arraycount(rightEnableInp) / 2); p.divideRegionV(3, defaultComponentDist); p.skipRegion(); for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightDef == "") { rightEnableInp[index] = p.addCheckBox(TA_Left, client.lng.format(client.lng.rightNotDefinedTxt, string(index + 1))); } else { rightEnableInp[index] = p.addCheckBox(TA_Left, mid(rightDef, instr(rightDef, client.sConf.separator) + 1)); } } updateButton = p.addButton(client.lng.updateTxt); addButton = p.addButton(client.lng.addTxt); deleteButton = p.addButton(client.lng.deleteTxt); // Account / player lists. splitRegionH(16); splitRegionH(16); addLabel(client.lng.onlineTxt, true, TA_Center); playerList = NexgenPlayerACListBox(addListBox(class'NexgenPlayerACListBox')); addLabel(client.lng.offlineTxt, true, TA_Center); accountList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); // Configure components. accountNameInp.setMaxLength(32); accountTitleInp.setMaxLength(24); accountTypeList.setEditable(false); playerList.register(self); accountList.register(self); updateButton.register(self); deleteButton.register(self); accountTypeList.register(self); loadUserAccounts(); loadAccountTypes(); accountSelected(); } /*************************************************************************************************** * * $DESCRIPTION Loads the account types. * **************************************************************************************************/ function loadAccountTypes() { local int index; accountTypeList.clear(); accountTypeList.addItem(client.lng.customAccountTxt, string(-1)); while(index < arrayCount(client.sConf.atTypeName) && client.sConf.atTypeName[index] != "") { accountTypeList.addItem(client.sConf.atTypeName[index], string(index)); index++; } } /*************************************************************************************************** * * $DESCRIPTION Load the user account list. * **************************************************************************************************/ function loadUserAccounts() { local int index; local NexgenPlayerACListItem playerItem; local NexgenSimpleListItem accountItem; // Clear account list. accountList.items.clear(); accountList.selectedItem = none; // Load each user account. while (index < arrayCount(client.sConf.paPlayerID) && client.sConf.paPlayerID[index] != "") { playerItem = NexgenPlayerACListItem(playerList.getPlayerByID(client.sConf.paPlayerID[index])); // Client is online? if (playerItem == none) { // Nope, add to account list. accountItem = NexgenSimpleListItem(accountList.items.append(class'NexgenSimpleListItem')); accountItem.itemID = index; accountItem.displayText = "[" $ client.sConf.getUserAccountTitle(index) $ "] " $ client.sConf.paPlayerName[index]; } // Continue with next user account. index++; } // Sort list. accountList.items.sort(); // Load account info for online players. updatePlayerList(); } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { local NexgenPlayerACListItem playerItem; local NexgenSimpleListItem accountItem; local bool bFound; local int accountNum; // Player has joined the game? if (eventType == client.PE_PlayerJoined) { // Add player. playerItem = NexgenPlayerACListItem(addPlayerToList(playerList, playerNum, args)); playerList.items.sort(); // Check if player has an account. accountNum = client.sConf.getUserAccountIndex(playerItem.pClientID); if (accountNum >= 0) { // Player has an account. // Update attributes. playerItem.bHasAccount = true; playerItem.accountNum = accountNum; // Move account item to player list. accountItem = accountList.getItemByID(accountNum); if (accountList.selectedItem == accountItem) { playerItem.bSelected = true; playerList.selectedItem = playerItem; accountList.selectedItem = none; } accountItem.remove(); } } // Player has left the game? if (eventType == client.PE_PlayerLeft) { // Check if player has an account. playerItem = NexgenPlayerACListItem(playerList.getPlayer(playerNum)); if (playerItem != none && playerItem.bHasAccount) { accountItem = NexgenSimpleListItem(accountList.items.append(class'NexgenSimpleListItem')); accountItem.itemID = playerItem.accountNum; accountItem.displayText = "[" $ client.sConf.getUserAccountTitle(playerItem.accountNum) $ "] " $ client.sConf.paPlayerName[playerItem.accountNum]; accountList.items.sort(); if (playerList.selectedItem == playerItem) { accountItem.bSelected = true; accountList.selectedItem = accountItem; playerList.selectedItem = none; } } // Delete from player list. playerList.removePlayer(playerNum); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local string clientID; local string accountName; local int accountType; local string rights; local string title; super.notify(control, eventType); setRPCI(); // Online player selected. if (control == playerList && eventType == DE_Click) { if (accountList.selectedItem != none) { accountList.selectedItem.bSelected = false; accountList.selectedItem = none; } accountSelected(); } // Offline player selected. if (control == accountList && eventType == DE_Click) { if (playerList.selectedItem != none) { playerList.selectedItem.bSelected = false; playerList.selectedItem = none; } accountSelected(); } // Account type selected. if (control == accountTypeList && eventType == DE_Change) { accountTypeSelected(); } // Delete button clicked. if (control == deleteButton && eventType == DE_Click && !deleteButton.bDisabled && rpci != none) { rpci.deleteAccount(getSelectedAccountNum()); } // Update button clicked. if (control == updateButton && eventType == DE_Click && !updateButton.bDisabled && rpci != none) { accountName = class'NexgenUtil'.static.trim(accountNameInp.getValue()); accountType = accountTypeList.getSelectedIndex() - 1; if (accountType < 0) { rights = getCurrentRights(); title = class'NexgenUtil'.static.trim(accountTitleInp.getValue()); } else { rights = ""; title = ""; } rpci.updateAccount(getSelectedAccountNum(), accountName, accountType, rights, title); } // Add button clicked. if (control == addButton && eventType == DE_Click && !addButton.bDisabled && rpci != none) { clientID = NexgenPlayerACListItem(playerList.selectedItem).pClientID; accountName = class'NexgenUtil'.static.trim(accountNameInp.getValue()); accountType = accountTypeList.getSelectedIndex() - 1; if (accountType < 0) { rights = getCurrentRights(); title = class'NexgenUtil'.static.trim(accountTitleInp.getValue()); } else { rights = ""; title = ""; } rpci.addAccount(clientID, accountName, accountType, rights, title); } } /*************************************************************************************************** * * $DESCRIPTION Returns a string containing the currently selected rights. * $RETURN A string containing the rights currently selected. * **************************************************************************************************/ function string getCurrentRights() { local string rights; local string rightDef; local int index; // Check for each right if it is selected. for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightEnableInp[index].bChecked && rightDef != "") { if (rights == "") { rights = left(rightDef, instr(rightDef, separator)); } else { rights = rights $ separator $ left(rightDef, instr(rightDef, separator)); } } } // Return result. return rights; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the account number of the account currently selected from the online or * offline account lists. * $RETURN The account number of the currently selected account, or -1 if no account was * selected. * **************************************************************************************************/ function int getSelectedAccountNum() { local int accountNum; // Get account number of selected online / offline account. if (playerList.selectedItem != none) { // Online account selected. accountNum = NexgenPlayerACListItem(playerList.selectedItem).accountNum; } else if (accountList.selectedItem != none) { // Offline account selected. accountNum = NexgenSimpleListItem(accountList.selectedItem).itemID; } else { // No account selected. accountNum = -1; } // Return account number. return accountNum; } /*************************************************************************************************** * * $DESCRIPTION Checks if the currently selected item has an user account. * $RETURN True if the currently selected item has an user account, false if not. * **************************************************************************************************/ function bool selectionHasAccount() { local bool bHasAccount; // Check if selected item has an account. if (playerList.selectedItem != none) { // Online account selected. bHasAccount = NexgenPlayerACListItem(playerList.selectedItem).bHasAccount; } else if (accountList.selectedItem != none) { // Offline account selected. bHasAccount = true; } else { // No account selected. bHasAccount = false; } // Return result. return bHasAccount; } /*************************************************************************************************** * * $DESCRIPTION Called when an user account was selected from the list. * **************************************************************************************************/ function accountSelected() { local bool bItemSelected; local bool bHasAccount; local int index; local int accountNum; // Get account number of selected online / offline account. accountNum = getSelectedAccountNum(); bHasAccount = selectionHasAccount(); // Account selected? bItemSelected = accountNum >= 0; accountNameInp.setDisabled(!bItemSelected); updateButton.bDisabled = !bItemSelected || !bHasAccount || !canEditAccount(accountNum); deleteButton.bDisabled = !bItemSelected || !bHasAccount || !canEditAccount(accountNum); addButton.bDisabled = !bItemSelected || bHasAccount; // $TODO Implement UWindowComboControl class that can be disabled. if (bHasAccount && bItemSelected) { accountNameInp.setValue(client.sConf.paPlayerName[accountNum]); accountTypeList.setSelectedIndex(client.sConf.get_paAccountType(accountNum) + 1); } else if (!bHasAccount && bItemSelected) { accountNameInp.setValue(NexgenPlayerACListItem(playerList.selectedItem).pName); accountTypeList.setSelectedIndex(defaultAccountType); } else { accountNameInp.setValue(""); accountTypeList.setSelectedIndex(invalidAccountType); } } /*************************************************************************************************** * * $DESCRIPTION Checks whether this client can delete the specified account. * $PARAM accountNum The number of the account for which has to be checked if it can be * deleted by this client. * $REQUIRE 0 <= accountNum && accountNum < arrayCount(client.sConf.paPlayerID) && * paPlayerID[accountNum] != none * $RETURN True if account can be deleted by this client, false if not. * **************************************************************************************************/ function bool canEditAccount(int accountNum) { local string rights; // Get rights of target account. if (client.sConf.get_paAccountType(accountNum) < 0) { rights = client.sConf.paCustomRights[accountNum]; } else { rights = client.sConf.atRights[client.sConf.get_paAccountType(accountNum)]; } // Return result. return client.hasRight(client.R_ServerAdmin) || !hasRight(rights, client.R_ServerAdmin); } /*************************************************************************************************** * * $DESCRIPTION Checks whether the specified right is included in the given right string. * $PARAM rights The rights specifier string. * $PARAM rightID String identifier of the client right. * $REQUIRE rightID != "" * $RETURN True if the right is included, false if not. * **************************************************************************************************/ function bool hasRight(string rights, string rightID) { return instr(rights $ separator, rightID $ separator) >= 0; } /*************************************************************************************************** * * $DESCRIPTION Called when an account type was selected from the list. * **************************************************************************************************/ function accountTypeSelected() { local int accountTypeNum; local int accountNum; local int index; local string rightDef; local string rightStr; local bool bItemSelected; local bool bHasAccount; local string title; local bool bClientIsServerAdmin; bClientIsServerAdmin = client.hasRight(client.R_ServerAdmin); // Get currently selected account type. accountTypeNum = accountTypeList.getSelectedIndex(); // Get account number of selected online / offline account. accountNum = getSelectedAccountNum(); bItemSelected = accountNum >= 0; bHasAccount = selectionHasAccount(); // Retieve title. if (accountTypeNum == invalidAccountType) { title = ""; } else if (accountTypeNum == customAccountType) { if (bHasAccount) { title = client.sConf.paCustomTitle[accountNum]; } else { title = client.sConf.getAccountTypeTitle(0); } } else { title = client.sConf.getAccountTypeTitle(accountTypeNum - 1); } // Update GUI. if (accountTypeNum == invalidAccountType) { addButton.bDisabled = true; updateButton.bDisabled = true; } else if (bHasAccount) { addButton.bDisabled = true; updateButton.bDisabled = !canEditAccount(accountNum) || !bClientIsServerAdmin && !canUseAccountType(accountTypeNum); } else { addButton.bDisabled = !bClientIsServerAdmin && !canUseAccountType(accountTypeNum); updateButton.bDisabled = true; } // Update title. accountTitleInp.setValue(title); accountTitleInp.setDisabled(accountTypeNum != customAccountType); // Retrieve rights. if (accountTypeNum == invalidAccountType) { rightStr = ""; } else if (accountTypeNum == customAccountType) { if (bHasAccount) { rightStr = client.sConf.paCustomRights[accountNum]; } else { rightStr = client.sConf.atRights[0]; } } else { rightStr = client.sConf.atRights[accountTypeNum - 1]; } // Update rights. for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightDef == "") { rightEnableInp[index].bDisabled = true; } else { rightEnableInp[index].bDisabled = accountTypeNum != customAccountType || !bClientIsServerAdmin && !client.hasRight(left(rightDef, instr(rightDef, separator))); rightEnableInp[index].bChecked = hasRight(rightStr, left(rightDef, instr(rightDef, separator))); } } } /*************************************************************************************************** * * $DESCRIPTION Checks whether this client can grant the specified account type. * $PARAM accountType The account type that is to be checked. * $REQUIRE 0 <= accountType && accountType <= arrayCount(client.atTypeName) * $RETURN True if the client can grant the specified account type, false if not. * **************************************************************************************************/ function bool canUseAccountType(int accountType) { return (accountType == customAccountType) || (client.hasRights(client.sConf.atRights[accountType - 1])); } /*************************************************************************************************** * * $DESCRIPTION Updates the player list. Iterates over all players in the player list and resets * their account attributes. * **************************************************************************************************/ function updatePlayerList() { local NexgenPlayerACListItem item; local int index; // For each player... for (item = NexgenPlayerACListItem(playerList.items); item != none; item = NexgenPlayerACListItem(item.next)) { // Check account... index = client.sConf.getUserAccountIndex(item.pClientID); // Set account info... if (index >= 0) { item.bHasAccount = true; item.accountNum = index; item.pTitle = client.sConf.getUserAccountTitle(index); } else { item.bHasAccount = false; item.accountNum = 0; item.pTitle = client.sConf.getAccountTypeTitle(0); } } // Sort list. playerList.items.sort(); } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_AccountTypes) { loadUserAccounts(); loadAccountTypes(); accountSelected(); } if (configType == client.sConf.CT_UserAccounts) { loadUserAccounts(); accountSelected(); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ rAnQQn@ O{n@ sayn PBd$Mڕw}Md$e$i$j$k$}L}}~o-'oZ zy<za$`$zQ A 5.0zA "Administrator"{A "Reboot"}A& "Pre switch server console commands"_/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPServerSettings * $VERSION 1.03 (7-10-2007 13:21) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen server settings control panel page. * **************************************************************************************************/ class NexgenRCPServerSettings extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var UWindowSmallButton resetButton; var UWindowSmallButton saveButton; var UWindowEditControl serverNameInp; var UWindowEditControl shortServerNameInp; var UWindowEditControl MOTDInp[4]; var UWindowEditControl adminNameInp; var UWindowEditControl adminEmailInp; var UWindowEditControl serverPasswordInp; var UWindowEditControl adminPasswordInp; var UWindowEditControl playerSlotsInp; var UWindowEditControl vipSlotsInp; var UWindowEditControl adminSlotsInp; var UWindowEditControl specSlotsInp; var UWindowCheckbox doUplinkInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; // Create layout & add components. createWindowRootRegion(); splitRegionH(20, defaultComponentDist, , true); p = addContentPanel(); splitRegionV(196, , , true); skipRegion(); divideRegionV(2, defaultComponentDist); saveButton = addButton(client.lng.saveTxt); resetButton = addButton(client.lng.resetTxt); p.splitRegionH(55, , true); p.splitRegionV(100); p.splitRegionV(30, defaultComponentDist, true); p.divideRegionH(6); p.divideRegionH(6); p.splitRegionV(100); p.splitRegionV(100); p.addLabel(client.lng.serverNameTxt, true); p.addLabel(client.lng.shortServerNameTxt, true); p.addLabel(client.lng.format(client.lng.MOTDLineTxt, 1), true); p.addLabel(client.lng.format(client.lng.MOTDLineTxt, 2), true); p.addLabel(client.lng.format(client.lng.MOTDLineTxt, 3), true); p.addLabel(client.lng.format(client.lng.MOTDLineTxt, 4), true); serverNameInp = p.addEditBox(); shortServerNameInp = p.addEditBox(); MOTDInp[0] = p.addEditBox(); MOTDInp[1] = p.addEditBox(); MOTDInp[2] = p.addEditBox(); MOTDInp[3] = p.addEditBox(); p.divideRegionH(5); p.divideRegionH(5); p.divideRegionH(5); p.divideRegionH(5); p.addLabel(client.lng.playerSlotsTxt, true); p.addLabel(client.lng.vipSlotsTxt, true); p.addLabel(client.lng.adminSlotsTxt, true); p.addLabel(client.lng.specSlotsTxt, true); p.addLabel(client.lng.advertiseTxt, true); playerSlotsInp = p.addEditBox( , 48, AL_Left); vipSlotsInp = p.addEditBox( , 48, AL_Left); adminSlotsInp = p.addEditBox( , 48, AL_Left); specSlotsInp = p.addEditBox( , 48, AL_Left); doUplinkInp = p.addCheckBox(TA_Right); p.addLabel(client.lng.adminNameTxt, true); p.addLabel(client.lng.adminEmailTxt, true); p.addLabel(client.lng.serverPasswordTxt, true); p.addLabel(client.lng.adminPasswordTxt, true); p.skipRegion(); adminNameInp = p.addEditBox(); adminEmailInp = p.addEditBox(); serverPasswordInp = p.addEditBox(); adminPasswordInp = p.addEditBox(); // Configure components. serverNameInp.setMaxLength(128); shortServerNameInp.setMaxLength(32); MOTDInp[0].setMaxLength(192); MOTDInp[1].setMaxLength(192); MOTDInp[2].setMaxLength(192); MOTDInp[3].setMaxLength(192); adminNameInp.setMaxLength(64); adminEmailInp.setMaxLength(64); serverPasswordInp.setMaxLength(30); adminPasswordInp.setMaxLength(30); playerSlotsInp.setNumericOnly(true); vipSlotsInp.setNumericOnly(true); adminSlotsInp.setNumericOnly(true); specSlotsInp.setNumericOnly(true); playerSlotsInp.setMaxLength(3); vipSlotsInp.setMaxLength(3); adminSlotsInp.setMaxLength(3); specSlotsInp.setMaxLength(3); setValues(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of all input components to the current server settings. * **************************************************************************************************/ function setValues() { serverNameInp.setValue(client.sConf.serverName); shortServerNameInp.setValue(client.sConf.shortName); adminNameInp.setValue(client.sConf.adminName); adminEmailInp.setValue(client.sConf.adminEmail); serverPasswordInp.setValue(client.sConf.decode(client.sConf.globalServerPassword)); adminPasswordInp.setValue(client.sConf.decode(client.sConf.globalAdminPassword)); MOTDInp[0].setValue(client.sConf.MOTDLine[0]); MOTDInp[1].setValue(client.sConf.MOTDLine[1]); MOTDInp[2].setValue(client.sConf.MOTDLine[2]); MOTDInp[3].setValue(client.sConf.MOTDLine[3]); playerSlotsInp.setValue(string(client.sConf.playerSlots)); vipSlotsInp.setValue(string(client.sConf.vipSlots)); adminSlotsInp.setValue(string(client.sConf.adminSlots)); specSlotsInp.setValue(string(client.sConf.spectatorSlots)); doUplinkInp.bChecked = client.sConf.enableUplink; } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_GlobalServerSettings) { setValues(); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled) { switch (control) { case resetButton: setValues(); break; case saveButton: saveSettings(); break; } } } /*************************************************************************************************** * * $DESCRIPTION Saves the server settings. * **************************************************************************************************/ function saveSettings() { local string serverName; local string shortServerName; local string MOTDLine[4]; local string adminName; local string adminEmail; local string serverPassword; local string adminPassword; local int playerSlots; local int vipSlots; local int adminSlots; local int specSlots; local bool bEnableUplink; // Make sure the RPC interface is available. if (!setRPCI()) return; // Collect data from the GUI. serverName = serverNameInp.getValue(); shortServerName = shortServerNameInp.getValue(); MOTDLine[0] = MOTDInp[0].getValue(); MOTDLine[1] = MOTDInp[1].getValue(); MOTDLine[2] = MOTDInp[2].getValue(); MOTDLine[3] = MOTDInp[3].getValue(); adminName = adminNameInp.getValue(); adminEmail = adminEmailInp.getValue(); serverPassword = serverPasswordInp.getValue(); adminPassword = adminPasswordInp.getValue(); playerSlots = int(playerSlotsInp.getValue()); vipSlots = int(vipSlotsInp.getValue()); adminSlots = int(adminSlotsInp.getValue()); specSlots = int(specSlotsInp.getValue()); bEnableUplink = doUplinkInp.bChecked; // Save settings. rpci.setServerSettings(serverName, shortServerName, MOTDLine[0], MOTDLine[1], MOTDLine[2], MOTDLine[3], adminName, adminEmail, serverPassword, adminPassword, playerSlots, vipSlots, adminSlots, specSlots, bEnableUplink); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ A# "Additional command line options"J?/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPServerInfo * $VERSION 1.01 (10-11-2007 19:10) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen server info control panel page. * **************************************************************************************************/ class NexgenRCPServerInfo extends NexgenPanel; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local GameReplicationInfo GRI; local TournamentGameReplicationInfo TGRI; local NexgenContentPanel p; GRI = client.player.gameReplicationInfo; TGRI = TournamentGameReplicationInfo(GRI); // Create layout & add components. createWindowRootRegion(); splitRegionH(32, defaultComponentDist); // Title. p = addContentPanel(); p.addLabel(GRI.serverName, true, TA_Center); // Contact info. splitRegionH(128, defaultComponentDist); p = addContentPanel(); p.splitRegionV(128); p.divideRegionH(7); p.divideRegionH(7); p.addLabel(client.lng.administratorTxt, true); p.addLabel(client.lng.contactAddrTxt, true); p.addLabel(client.lng.msgOfTheDayTxt, true); p.skipRegion(); p.skipRegion(); p.skipRegion(); p.addLabel(client.lng.serverIDTxt, true); p.addLabel(fixStr(GRI.adminName)); p.addLabel(fixStr(GRI.adminEmail)); p.addLabel(fixStr(GRI.MOTDLine1)); p.addLabel(fixStr(GRI.MOTDLine2)); p.addLabel(fixStr(GRI.MOTDLine3)); p.addLabel(fixStr(GRI.MOTDLine4)); p.addLabel(class'NexgenUtil'.static.formatGUID(client.serverID)); // Server game stats. if (TGRI != none) { splitRegionV(160, defaultComponentDist); // Server stats. p = addContentPanel(); p.splitRegionH(20, , true); p.addLabel(client.lng.statisticsTxt, true, TA_Center); p.splitRegionV(100); p.divideRegionH(4); p.divideRegionH(4); p.addLabel(client.lng.totalGamesTxt, true); p.addLabel(client.lng.totalFragsTxt, true); p.addLabel(client.lng.totalDeathsTxt, true); p.addLabel(client.lng.totalFlagsTxt, true); p.addLabel(TGRI.totalGames); p.addLabel(TGRI.totalFrags); p.addLabel(TGRI.totalDeaths); p.addLabel(TGRI.totalFlags); // Top players. p = addContentPanel(); p.splitRegionH(20, , true); p.addLabel(client.lng.bestPlayersTxt, true, TA_Center); p.splitRegionV(160, , , true); p.divideRegionH(4); p.splitRegionV(48); p.addLabel(client.lng.playerNameTxt, true); p.addLabel(fixStr(TGRI.bestPlayers[0])); p.addLabel(fixStr(TGRI.bestPlayers[1])); p.addLabel(fixStr(TGRI.bestPlayers[2])); p.divideRegionH(4); p.divideRegionH(4); p.addLabel(client.lng.FPHTxt, true); p.addLabel(TGRI.bestFPHs[0]); p.addLabel(TGRI.bestFPHs[1]); p.addLabel(TGRI.bestFPHs[2]); p.addLabel(client.lng.recordSetTxt, true); p.addLabel(fixStr(TGRI.bestRecordDate[0])); p.addLabel(fixStr(TGRI.bestRecordDate[1])); p.addLabel(fixStr(TGRI.bestRecordDate[2])); } } /*************************************************************************************************** * * $DESCRIPTION Makes sure a non empty string is returned. * **************************************************************************************************/ static function string fixStr(coerce string str) { if (class'NexgenUtil'.static.trim(str) == "") { return "-"; } else { return str; } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ AB "Map prefix"zr/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPReplacementHUDSettings * $VERSION 1.03 (20-6-2008 14:14) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen about control panel page. * **************************************************************************************************/ class NexgenRCPReplacementHUDSettings extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenSimpleListBox hudReplacementList; var UWindowSmallButton hudReplSaveButton; var UWindowSmallButton hudReplRemButton; var NexgenEditControl originalHUDClassInp; var NexgenEditControl replacementHUDClassInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { // Create layout & add components. createPanelRootRegion(); splitRegionV(256, defaultComponentDist); hudReplacementList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); divideRegionH(4); addLabel(client.lng.hudReplaceClassesTxt, true, TA_Center); splitRegionV(128); splitRegionV(128); splitRegionV(192); addLabel(client.lng.originalHUDClassTxt); originalHUDClassInp = addEditBox(); addLabel(client.lng.replacementHUDClassTxt); replacementHUDClassInp = addEditBox(); divideRegionV(2, defaultComponentDist); skipRegion(); hudReplSaveButton = addButton(client.lng.saveTxt); hudReplRemButton = addButton(client.lng.removeTxt); // Configure components. originalHUDClassInp.setMaxLength(64); replacementHUDClassInp.setMaxLength(64); loadHUDReplacementList(); } /*************************************************************************************************** * * $DESCRIPTION Loads the HUD class replacement list. * **************************************************************************************************/ function loadHUDReplacementList() { local int index; local NexgenSimpleListItem item; // Clear list. hudReplacementList.selectedItem = none; hudReplacementList.items.clear(); // Add weapon classes. while (index < arrayCount(client.sConf.replacementClass) && client.sConf.replacementClass[index] != "") { item = NexgenSimpleListItem(hudReplacementList.items.append(class'NexgenSimpleListItem')); item.displayText = client.sConf.replacementClass[index]; item.itemID = index; index++; } // Add 'add new item' option if list isn't full. if (index < arrayCount(client.sConf.replacementClass)) { item = NexgenSimpleListItem(hudReplacementList.items.insert(class'NexgenSimpleListItem')); item.displayText = client.lng.addNewItemTxt; item.itemID = -1; } // Signal item select event. hudReplacementSelected(); } /*************************************************************************************************** * * $DESCRIPTION Called when an item from the hud replacement list was selected. * **************************************************************************************************/ function hudReplacementSelected() { local NexgenSimpleListItem item; local string str; // Get selected item. item = NexgenSimpleListItem(hudReplacementList.selectedItem); // Update GUI. hudReplSaveButton.bDisabled = (item == none); hudReplRemButton.bDisabled = (item == none) || (item.itemID < 0); originalHUDClassInp.setDisabled((item == none)); replacementHUDClassInp.setDisabled((item == none)); if (item == none) { originalHUDClassInp.setValue(""); replacementHUDClassInp.setValue(""); } else if (item.itemID < 0) { originalHUDClassInp.setValue(""); replacementHUDClassInp.setValue(""); } else { str = client.sConf.replacementClass[item.itemID]; originalHUDClassInp.setValue(left(str, instr(str, "="))); replacementHUDClassInp.setValue(mid(str, instr(str, "=") + 1)); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // HUD replacement selected? if (control == hudReplacementList && eventType == DE_Click) { hudReplacementSelected(); } // Remove HUD replacement selected? if (control == hudReplRemButton && eventType == DE_Click && !hudReplRemButton.bDisabled && setRPCI()) { rpci.delHUDReplacementClass(NexgenSimpleListItem(hudReplacementList.selectedItem).itemID); } // Save HUD replacement selected? if (control == hudReplSaveButton && eventType == DE_Click && !hudReplSaveButton.bDisabled && setRPCI()) { rpci.saveHUDReplacementClass(NexgenSimpleListItem(hudReplacementList.selectedItem).itemID, class'NexgenUtil'.static.trim(originalHUDClassInp.getValue()), class'NexgenUtil'.static.trim(replacementHUDClassInp.getValue())); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_HUDReplacementList) { loadHUDReplacementList(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ IB "Game type"B/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPPrivateMsg * $VERSION 1.03 (21-10-2007 14:38) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen private message system control panel page. * **************************************************************************************************/ class NexgenRCPPrivateMsg extends NexgenPanel; var NexgenClientCore rpci; var UWindowDynamicTextArea history; var NexgenSimplePlayerListBox playerList; var NexgenSimplePlayerListBox blockedPlayerList; var UWindowSmallButton blockToggleButton; var UWindowSmallButton sendNormalButton; var UWindowSmallButton sendWindowedButton; var UWindowEditControl msgInp; var UWindowCheckbox blockAllInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist); // Player / blocked player list. p = addContentPanel(); p.divideRegionH(2, defaultComponentDist); p.splitRegionH(16); p.splitRegionH(16); p.addLabel(client.lng.playerListTxt, true, TA_Center); playerList = NexgenSimplePlayerListBox(p.addListBox(class'NexgenSimplePlayerListBox')); p.addLabel(client.lng.blockedListTxt, true, TA_Center); p.splitRegionH(32, defaultComponentDist, , true); blockedPlayerList = NexgenSimplePlayerListBox(p.addListBox(class'NexgenSimplePlayerListBox')); p.divideRegionH(2); blockToggleButton = p.addButton(client.lng.blockToggleTxt); blockAllInp = p.addCheckBox(TA_Left, client.lng.blockAllPMsTxt); // 'Say' panel. splitRegionH(64, defaultComponentDist); p = addContentPanel(); p.divideRegionH(3, defaultComponentDist); p.addLabel(client.lng.messageTxt, true, TA_Center); msgInp = p.addEditbox(); p.splitRegionV(256); p.divideRegionV(2, defaultComponentDist); p.skipRegion(); sendNormalButton = p.addButton(client.lng.sendNormalPMTxt); sendWindowedButton = p.addButton(client.lng.sendWindowedPMTxt); // History panel. p = addContentPanel(); p.splitRegionH(16); p.addLabel(client.lng.historyTxt, true, TA_Center); history = p.addDynamicTextArea(); // Configure components. playerList.register(self); blockedPlayerList.register(self); blockToggleButton.register(self); blockAllInp.register(self); sendNormalButton.register(self); sendWindowedButton.register(self); sendWindowedButton.bDisabled = !client.hasRight(client.R_Moderate); msgInp.register(self); msgInp.setMaxLength(255); } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // Make sure the RPC interface is available. setRPCI(); // Player has joined the game? if (eventType == client.PE_PlayerJoined) { if (rpci != none && rpci.isBlocked(class'NexgenUtil'.static.getProperty(args, client.PA_ClientID))) { addPlayerToList(blockedPlayerList, playerNum, args); } else { addPlayerToList(playerList, playerNum, args); } } // Player has left the game? if (eventType == client.PE_PlayerLeft) { playerList.removePlayer(playerNum); blockedPlayerList.removePlayer(playerNum); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); updatePlayerInfo(blockedPlayerList, playerNum, args); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local NexgenPlayerList selected; setRPCI(); // Block all clicked. if (control == blockAllInp && eventType == DE_Click && rpci != none) { rpci.bBlockAll = blockAllInp.bChecked; } // Send normal clicked. if (control == sendNormalButton && eventType == DE_Click) { sendMessage(false); } // Enter button pressed on message edit box. if (control == msgInp && eventType == DE_EnterPressed) { sendMessage(false); } // Send windowed clicked. if (control == sendWindowedButton && eventType == DE_Click && !sendWindowedButton.bDisabled) { sendMessage(true); } // Block / Unblock clicked. if (control == blockToggleButton && eventType == DE_Click && rpci != none) { if (playerList.selectedItem != none) { selected = NexgenPlayerList(playerList.selectedItem); rpci.blockPlayer(selected.pClientID); addHistoryMsg(client.lng.format(client.lng.blockMsg, selected.pName)); playerList.moveSelectedPlayerTo(blockedPlayerList); } else if (blockedPlayerList.selectedItem != none) { selected = NexgenPlayerList(blockedPlayerList.selectedItem); rpci.unblockPlayer(selected.pClientID); addHistoryMsg(client.lng.format(client.lng.unblockMsg, selected.pName)); blockedPlayerList.moveSelectedPlayerTo(playerList); } } // Unblocked player selected. if (control == playerList && eventType == DE_Click) { if (blockedPlayerList.selectedItem != none) { blockedPlayerList.selectedItem.bSelected = false; blockedPlayerList.selectedItem = none; } } // Blocked player selected. if (control == blockedPlayerList && eventType == DE_Click) { if (playerList.selectedItem != none) { playerList.selectedItem.bSelected = false; playerList.selectedItem = none; } } // Double click on unblocked player -> block that player. if (control == playerList && eventType == DE_DoubleClick && playerList.selectedItem != none && rpci != none) { selected = NexgenPlayerList(playerList.selectedItem); rpci.blockPlayer(selected.pClientID); addHistoryMsg(client.lng.format(client.lng.blockMsg, selected.pName)); playerList.moveSelectedPlayerTo(blockedPlayerList); } // Double click on blocked player -> unblock that player. if (control == blockedPlayerList && eventType == DE_DoubleClick && blockedPlayerList.selectedItem != none && rpci != none) { selected = NexgenPlayerList(blockedPlayerList.selectedItem); rpci.unblockPlayer(selected.pClientID); addHistoryMsg(client.lng.format(client.lng.unblockMsg, selected.pName)); blockedPlayerList.moveSelectedPlayerTo(playerList); } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to the to message history box. * $PARAM msg The message to add. * **************************************************************************************************/ function addHistoryMsg(string msg) { local string timeStamp; timeStamp = "[" $ right("0" $ client.level.hour, 2) $ ":" $ right("0" $ client.level.minute, 2) $ "]"; history.addText(timeStamp @ msg); } /*************************************************************************************************** * * $DESCRIPTION Send the currently enterted message to the selected player. * $PARAM bWindowed Whether the message to send should popup in a window. * **************************************************************************************************/ function sendMessage(optional bool bWindowed) { local NexgenPlayerList selectedPlayer; // Make sure the RPC interface is available. if (rpci == none) return; // Get selected player. if (playerList.selectedItem != none) { selectedPlayer = NexgenPlayerList(playerList.selectedItem); } else if (blockedPlayerList.selectedItem != none) { selectedPlayer = NexgenPlayerList(blockedPlayerList.selectedItem); } // Send message. if (selectedPlayer != none && msgInp.getValue() != "" && !client.isMuted() && !( // Spectators muted during matches? client.sConf.matchModeActivated && client.sConf.muteSpectatorsDuringMatch && client.gInf.gameState == client.gInf.GS_Playing && client.bSpectator && !selectedPlayer.isSpectator() && !client.hasRight(client.R_MatchAdmin) && !client.hasRight(client.R_Moderate) ) ) { addHistoryMsg(client.lng.format(client.lng.sendMsgTxt, selectedPlayer.pName, msgInp.getValue())); rpci.sendPM(selectedPlayer.pNum, msgInp.getValue(), bWindowed); msgInp.setValue(""); } // $TODO Play sound on error. } /*************************************************************************************************** * * $DESCRIPTION Called when a new private message was received. Adds the received message to the * chat history. * $PARAM msg The message that was received. * $PARAM pri Player replication info actor of the player that has send the message. * $REQUIRE pri != none * **************************************************************************************************/ function receiveMessage(string msg, PlayerReplicationInfo pri) { addHistoryMsg(client.lng.format(client.lng.receivedMsgTxt, pri.playerName, msg)); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ O/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPModerate * $VERSION 1.01 (1-8-2008 20:50) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen moderator control panel page. * **************************************************************************************************/ class NexgenRCPModerate extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenPlayerListBox playerList; var UMenuLabelControl ipAddressLabel; var UMenuLabelControl clientIDLabel; var UWindowSmallButton copyIPAddressButton; var UWindowSmallButton copyClientIDButton; var UWindowSmallButton muteToggleButton; var UWindowSmallButton setNameButton; var UWindowSmallButton kickButton; var UWindowSmallButton banButton; var UWindowSmallButton showMsgButton; var UWindowEditControl playerNameInp; var UWindowEditControl banReasonInp; var NexgenEditControl numMatchesInp; var NexgenEditControl numDaysInp; var UWindowEditControl messageInp; var UWindowCheckbox banForeverInp; var UWindowCheckbox banMatchesInp; var UWindowCheckbox banDaysInp; var UWindowCheckbox muteAllInp; var UWindowCheckbox allowNameChangeInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist); playerList = NexgenPlayerListBox(addListBox(class'NexgenPlayerListBox')); // Player info. splitRegionH(49, defaultComponentDist); p = addContentPanel(); p.divideRegionH(2); p.splitRegionV(64); p.splitRegionV(64); p.addLabel(client.lng.ipAddressTxt, true); p.splitRegionV(48, , , true); p.addLabel(client.lng.clientIDTxt, true); p.splitRegionV(48, , , true); ipAddressLabel = p.addLabel(); copyIPAddressButton = p.addButton(client.lng.copyTxt); clientIDLabel = p.addLabel(); copyClientIDButton = p.addButton(client.lng.copyTxt); // Player controller. splitRegionH(51, defaultComponentDist); p = addContentPanel(); p.divideRegionH(2); p.splitRegionV(96, defaultComponentDist); p.splitRegionV(96, defaultComponentDist); muteToggleButton = p.addButton(client.lng.muteToggleTxt); p.skipRegion(); setNameButton = p.addButton(client.lng.setPlayerNameTxt); playerNameInp = p.addEditBox(); // Ban controller. splitRegionH(107, defaultComponentDist); p = addContentPanel(); p.divideRegionH(5); p.splitRegionV(96, defaultComponentDist); p.splitRegionV(96, defaultComponentDist); p.splitRegionV(96, defaultComponentDist); p.splitRegionV(96, defaultComponentDist); p.splitRegionV(96, defaultComponentDist); p.addLabel(client.lng.banReasonTxt); banReasonInp = p.addEditBox(); kickButton = p.addButton(client.lng.kickPlayerTxt); p.skipRegion(); banButton = p.addButton(client.lng.banPlayerTxt); p.splitRegionV(96, defaultComponentDist); p.skipRegion(); p.splitRegionV(96, defaultComponentDist); p.skipRegion(); p.splitRegionV(96, defaultComponentDist); banForeverInp = p.addCheckBox(TA_Left, client.lng.banForeverTxt); p.skipRegion(); banMatchesInp = p.addCheckBox(TA_Left, client.lng.banMatchesTxt); numMatchesInp = p.addEditBox(); banDaysInp = p.addCheckBox(TA_Left, client.lng.banDaysTxt); numDaysInp = p.addEditBox(); // Game controller. splitRegionH(65); p = addContentPanel(); p.divideRegionH(3); muteAllInp = p.addCheckBox(TA_Left, client.lng.muteAllTxt); allowNameChangeInp = p.addCheckBox(TA_Left, client.lng.allowNameChangeTxt); p.splitRegionV(96, defaultComponentDist); showMsgButton = p.addButton(client.lng.showAdminMessageTxt); messageInp = p.addEditBox(); // Configure components. playerNameInp.setMaxLength(32); banReasonInp.setMaxLength(250); numMatchesInp.setMaxLength(4); numMatchesInp.setNumericOnly(true); numDaysInp.setMaxLength(4); numDaysInp.setNumericOnly(true); messageInp.setMaxLength(250); playerList.register(self); muteToggleButton.register(self); setNameButton.register(self); kickButton.register(self); banButton.register(self); showMsgButton.register(self); banForeverInp.register(self); banMatchesInp.register(self); banDaysInp.register(self); muteAllInp.register(self); allowNameChangeInp.register(self); banMatchesInp.bChecked = true; numMatchesInp.setValue("3"); numDaysInp.setValue("7"); playerSelected(); banPeriodSelected(); setValues(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of all input components to the current game info settings. * **************************************************************************************************/ function setValues() { muteAllInp.bChecked = client.gInf.bMuteAll; allowNameChangeInp.bChecked = !client.gInf.bNoNameChange; } /*************************************************************************************************** * * $DESCRIPTION Called when a player was selected from the list. * **************************************************************************************************/ function playerSelected() { local NexgenPlayerList item; item = NexgenPlayerList(playerList.selectedItem); muteToggleButton.bDisabled = (item == none); setNameButton.bDisabled = (item == none); kickButton.bDisabled = (item == none); banButton.bDisabled = (item == none || !client.hasRight(client.R_BanOperator)); copyIPAddressButton.bDisabled = (item == none); copyClientIDButton.bDisabled = (item == none); if (item == none) { playerNameInp.setValue(""); ipAddressLabel.setText(""); clientIDLabel.setText(""); } else { playerNameInp.setValue(item.pName); ipAddressLabel.setText(item.pIPAddress); clientIDLabel.setText(item.pClientID); } } /*************************************************************************************************** * * $DESCRIPTION Called when a ban period was selected from the list. * **************************************************************************************************/ function banPeriodSelected() { numMatchesInp.setDisabled(!banMatchesInp.bChecked); numDaysInp.setDisabled(!banDaysInp.bChecked); } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Bans the currently selected player. * **************************************************************************************************/ function banPlayer() { local byte banPeriodType; local int banPeriodArgs; if (banMatchesInp.bChecked) { banPeriodType = client.sConf.BP_Matches; banPeriodArgs = int(class'NexgenUtil'.static.trim(numMatchesInp.getValue())); } else if (banDaysInp.bChecked) { banPeriodType = client.sConf.BP_UntilDate; banPeriodArgs = int(class'NexgenUtil'.static.trim(numDaysInp.getValue())); } else { banPeriodType = client.sConf.BP_Forever; } rpci.banPlayer(NexgenPlayerList(playerList.selectedItem).pNum, banPeriodType, banPeriodArgs, class'NexgenUtil'.static.trim(banReasonInp.getValue())); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local NexgenPlayerList item; super.notify(control, eventType); setRPCI(); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled && rpci != none) { switch (control) { case muteToggleButton: rpci.togglePlayerMute(NexgenPlayerList(playerList.selectedItem).pNum); break; case setNameButton: rpci.setPlayerName(NexgenPlayerList(playerList.selectedItem).pNum, class'NexgenUtil'.static.trim(playerNameInp.getValue())); break; case kickButton: rpci.kickPlayer(NexgenPlayerList(playerList.selectedItem).pNum, class'NexgenUtil'.static.trim(banReasonInp.getValue())); break; case banButton: banPlayer(); break; case showMsgButton: rpci.showAdminMessage(class'NexgenUtil'.static.trim(messageInp.getValue())); break; case copyIPAddressButton: item = NexgenPlayerList(playerList.selectedItem); if (item != none) { getPlayerOwner().copyToClipboard(item.pIPAddress); } break; case copyClientIDButton: item = NexgenPlayerList(playerList.selectedItem); if (item != none) { getPlayerOwner().copyToClipboard(item.pClientID); } break; } } // Player selected? if (control == playerList && eventType == DE_Click) { playerSelected(); } // Ban period selected? if (control == banForeverInp && eventType == DE_Click) { banForeverInp.bChecked = true; banMatchesInp.bChecked = false; banDaysInp.bChecked = false; banPeriodSelected(); } else if (control == banMatchesInp && eventType == DE_Click) { banForeverInp.bChecked = false; banMatchesInp.bChecked = true; banDaysInp.bChecked = false; banPeriodSelected(); } else if (control == banDaysInp && eventType == DE_Click) { banForeverInp.bChecked = false; banMatchesInp.bChecked = false; banDaysInp.bChecked = true; banPeriodSelected(); } // Toggle mute all clicked? if (control == muteAllInp && eventType == DE_Click && rpci != none) { rpci.toggleGlobalMute(); } // Toggle allow name change clicked? if (control == allowNameChangeInp && eventType == DE_Click && rpci != none) { rpci.toggleGlobalNameChange(); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // Player has joined the game? if (eventType == client.PE_PlayerJoined) { addPlayerToList(playerList, playerNum, args); } // Player has left the game? if (eventType == client.PE_PlayerLeft) { playerList.removePlayer(playerNum); playerSelected(); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); playerSelected(); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * $OVERRIDE * **************************************************************************************************/ function gameInfoChanged(byte infoType) { if (infoType == client.gInf.IT_GlobalRights) { setValues(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ e 5DBm&RA}A ,i .pp T#.A  Hi *-L' EBGBT: -Lmi  FBNUJ NeeNQQNXXNw w NEENA A NqqNi i N-L-L MB "Server boot command line"HBKBT^ :q, W/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPMiscNexgenSettings * $VERSION 1.06 (4-8-2008 16:19) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen extra server settings control panel page. * **************************************************************************************************/ class NexgenRCPMiscNexgenSettings extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var UWindowSmallButton resetButton; var UWindowSmallButton saveButton; var UWindowCheckbox autoUpdateBansInp; var UWindowCheckbox autoDelExpiredBansInp; var UWindowCheckbox broadcastAdminActionsInp; var UWindowCheckbox announceTeamKillsInp; var UWindowCheckbox enableNexgenMessageHUDInp; var UWindowCheckbox enableNexgenStartControlInp; var UWindowCheckbox restoreScoreOnTeamSwitchInp; var UWindowCheckbox defaultAllowTeamSwitchInp; var UWindowCheckbox defaultAllowTeamBalanceInp; var UWindowCheckbox defaultAllowNameChangeInp; var UWindowCheckbox autoRegisterServerInp; var UWindowEditControl gameWaitTimeInp; var UWindowEditControl gameStartDelayInp; var UWindowEditControl autoReconnectTimeInp; var UWindowEditControl maxIdleTimeInp; var UWindowEditControl maxIdleTimeCPInp; var UWindowEditControl spawnProtectTimeInp; var UWindowEditControl teamKillDmgProtectInp; var UWindowEditControl teamKillPushProtectInp; var UWindowEditControl autoDisableMatchTimeInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { // Create layout & add components. createPanelRootRegion(); splitRegionH(12, defaultComponentDist); addLabel(client.lng.nexgenMiscSettingsPanelTitle, true, TA_Center); splitRegionH(1, defaultComponentDist); addComponent(class'NexgenDummyComponent'); divideRegionV(2, 2 * defaultComponentDist); divideRegionH(11); divideRegionH(11); autoUpdateBansInp = addCheckBox(TA_Left, client.lng.autoUpdateBansTxt, true); autoDelExpiredBansInp = addCheckBox(TA_Left, client.lng.autoDelExpiredBansTxt, true); broadcastAdminActionsInp = addCheckBox(TA_Left, client.lng.broadcastAdminActionsTxt, true); announceTeamKillsInp = addCheckBox(TA_Left, client.lng.announceTeamKillsTxt, true); enableNexgenMessageHUDInp = addCheckBox(TA_Left, client.lng.enableNexgenMessageHUDTxt, true); enableNexgenStartControlInp = addCheckBox(TA_Left, client.lng.enableNexgenStartControlTxt, true); restoreScoreOnTeamSwitchInp = addCheckBox(TA_Left, client.lng.restoreScoreOnTeamSwitchTxt, true); defaultAllowTeamSwitchInp = addCheckBox(TA_Left, client.lng.defaultAllowTeamSwitchTxt, true); defaultAllowTeamBalanceInp = addCheckBox(TA_Left, client.lng.defaultAllowTeamBalanceTxt, true); defaultAllowNameChangeInp = addCheckBox(TA_Left, client.lng.defaultAllowNameChangeTxt, true); autoRegisterServerInp = addCheckBox(TA_Left, client.lng.autoRegisterServerTxt, true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); splitRegionV(64, , , true); skipRegion(); splitRegionV(196, , , true); addLabel(client.lng.gameWaitTimeTxt, true); gameWaitTimeInp = addEditBox(); addLabel(client.lng.gameStartDelayTxt, true); gameStartDelayInp = addEditBox(); addLabel(client.lng.autoReconnectTimeTxt, true); autoReconnectTimeInp = addEditBox(); addLabel(client.lng.maxIdleTimeTxt, true); maxIdleTimeInp = addEditBox(); addLabel(client.lng.maxIdleTimeCPTxt, true); maxIdleTimeCPInp = addEditBox(); addLabel(client.lng.spawnProtectTimeTxt, true); spawnProtectTimeInp = addEditBox(); addLabel(client.lng.teamKillDmgProtectTxt, true); teamKillDmgProtectInp = addEditBox(); addLabel(client.lng.teamKillPushProtectTxt, true); teamKillPushProtectInp = addEditBox(); addLabel(client.lng.autoDisableMatchTimeTxt, true); autoDisableMatchTimeInp = addEditBox(); skipRegion(); divideRegionV(2, defaultComponentDist); saveButton = addButton(client.lng.saveTxt); resetButton = addButton(client.lng.resetTxt); /* splitRegionH(20, defaultComponentDist, , true); p = addContentPanel(); splitRegionV(196, , , true); skipRegion(); divideRegionV(2, defaultComponentDist); saveButton = addButton(client.lng.saveTxt); resetButton = addButton(client.lng.resetTxt); p.divideRegionV(2, 2 * defaultComponentDist); p.divideRegionH(10); p.splitRegionV(64, , , true); autoUpdateBansInp = p.addCheckBox(TA_Left, client.lng.autoUpdateBansTxt, true); autoDelExpiredBansInp = p.addCheckBox(TA_Left, client.lng.autoDelExpiredBansTxt, true); broadcastAdminActionsInp = p.addCheckBox(TA_Left, client.lng.broadcastAdminActionsTxt, true); announceTeamKillsInp = p.addCheckBox(TA_Left, client.lng.announceTeamKillsTxt, true); enableNexgenMessageHUDInp = p.addCheckBox(TA_Left, client.lng.enableNexgenMessageHUDTxt, true); enableNexgenStartControlInp = p.addCheckBox(TA_Left, client.lng.enableNexgenStartControlTxt, true); restoreScoreOnTeamSwitchInp = p.addCheckBox(TA_Left, client.lng.restoreScoreOnTeamSwitchTxt, true); defaultAllowTeamSwitchInp = p.addCheckBox(TA_Left, client.lng.defaultAllowTeamSwitchTxt, true); defaultAllowTeamBalanceInp = p.addCheckBox(TA_Left, client.lng.defaultAllowTeamBalanceTxt, true); defaultAllowNameChangeInp = p.addCheckBox(TA_Left, client.lng.defaultAllowNameChangeTxt, true); p.divideRegionH(10); p.divideRegionH(10); p.addLabel(client.lng.gameWaitTimeTxt, true); p.addLabel(client.lng.gameStartDelayTxt, true); p.addLabel(client.lng.autoReconnectTimeTxt, true); p.addLabel(client.lng.maxIdleTimeTxt, true); p.addLabel(client.lng.maxIdleTimeCPTxt, true); p.addLabel(client.lng.spawnProtectTimeTxt, true); p.addLabel(client.lng.teamKillDmgProtectTxt, true); p.addLabel(client.lng.teamKillPushProtectTxt, true); p.addLabel(client.lng.autoDisableMatchTimeTxt, true); p.skipRegion(); gameWaitTimeInp = p.addEditBox(); gameStartDelayInp = p.addEditBox(); autoReconnectTimeInp = p.addEditBox(); maxIdleTimeInp = p.addEditBox(); maxIdleTimeCPInp = p.addEditBox(); spawnProtectTimeInp = p.addEditBox(); teamKillDmgProtectInp = p.addEditBox(); teamKillPushProtectInp = p.addEditBox(); autoDisableMatchTimeInp = p.addEditBox(); */ // Configure components. gameWaitTimeInp.setMaxLength(2); gameStartDelayInp.setMaxLength(2); autoReconnectTimeInp.setMaxLength(2); maxIdleTimeInp.setMaxLength(3); maxIdleTimeCPInp.setMaxLength(3); spawnProtectTimeInp.setMaxLength(2); teamKillDmgProtectInp.setMaxLength(2); teamKillPushProtectInp.setMaxLength(2); autoDisableMatchTimeInp.setMaxLength(2); gameWaitTimeInp.setNumericOnly(true); gameStartDelayInp.setNumericOnly(true); autoReconnectTimeInp.setNumericOnly(true); maxIdleTimeInp.setNumericOnly(true); maxIdleTimeCPInp.setNumericOnly(true); spawnProtectTimeInp.setNumericOnly(true); teamKillDmgProtectInp.setNumericOnly(true); teamKillPushProtectInp.setNumericOnly(true); autoDisableMatchTimeInp.setNumericOnly(true); setValues(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of all input components to the current server settings. * **************************************************************************************************/ function setValues() { autoUpdateBansInp.bChecked = client.sConf.autoUpdateBans; autoDelExpiredBansInp.bChecked = client.sConf.removeExpiredBans; broadcastAdminActionsInp.bChecked = client.sConf.broadcastAdminActions; announceTeamKillsInp.bChecked = client.sConf.broadcastTeamKillAttempts; enableNexgenMessageHUDInp.bChecked = client.sConf.useNexgenMessageHUD; enableNexgenStartControlInp.bChecked = client.sConf.enableNexgenStartControl; restoreScoreOnTeamSwitchInp.bChecked = client.sConf.restoreScoreOnTeamSwitch; defaultAllowTeamSwitchInp.bChecked = client.sConf.allowTeamSwitch; defaultAllowTeamBalanceInp.bChecked = client.sConf.allowTeamBalance; defaultAllowNameChangeInp.bChecked = client.sConf.allowNameChange; autoRegisterServerInp.bChecked = client.sConf.autoRegisterServer; gameWaitTimeInp.setValue(string(client.sConf.waitTime)); gameStartDelayInp.setValue(string(client.sConf.startTime)); autoReconnectTimeInp.setValue(string(client.sConf.autoReconnectTime)); maxIdleTimeInp.setValue(string(client.sConf.maxIdleTime)); maxIdleTimeCPInp.setValue(string(client.sConf.maxIdleTimeCP)); spawnProtectTimeInp.setValue(string(client.sConf.spawnProtectionTime)); teamKillDmgProtectInp.setValue(string(client.sConf.teamKillDamageProtectionTime)); teamKillPushProtectInp.setValue(string(client.sConf.teamKillPushProtectionTime)); autoDisableMatchTimeInp.setValue(string(client.sConf.autoDisableMatchTime)); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled) { switch (control) { case resetButton: setValues(); break; case saveButton: saveSettings(); break; } } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_ExtraServerSettings) { setValues(); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Saves the server settings. * **************************************************************************************************/ function saveSettings() { // Make sure the RPC interface is available. if (!setRPCI()) return; // Save settings. rpci.setServerSettingsExt1(autoUpdateBansInp.bChecked, autoDelExpiredBansInp.bChecked, broadcastAdminActionsInp.bChecked, announceTeamKillsInp.bChecked, enableNexgenMessageHUDInp.bChecked, enableNexgenStartControlInp.bChecked, restoreScoreOnTeamSwitchInp.bChecked, defaultAllowTeamSwitchInp.bChecked, defaultAllowTeamBalanceInp.bChecked, defaultAllowNameChangeInp.bChecked, autoRegisterServerInp.bChecked); rpci.setServerSettingsExt2(int(gameWaitTimeInp.getValue()), int(gameStartDelayInp.getValue()), int(autoReconnectTimeInp.getValue()), int(maxIdleTimeInp.getValue()), int(maxIdleTimeCPInp.getValue()), int(spawnProtectTimeInp.getValue()), int(teamKillDmgProtectInp.getValue()), int(teamKillPushProtectInp.getValue()), int(autoDisableMatchTimeInp.getValue())); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ UB "Mutators not used"l{J!a.){X`.)RX\.){Q[.)RQsa`za`s\[z\[%&& xA 20.0RBhN/ro*iwo*KowK*pKa/!iK4KKBh *g+i *f+|oh@Joi@Ko *|Jhi..*K.k .8g %g ,wg I*g IVg  aSBbJgAro*ib Ze+c Za+^ob@`oc@Yo Z^`bc}.ZY}C}B2}Av }@F}4 aBiNio.Co-on gro*o| * aWB "Mutators used"W/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPMatchSet * $VERSION 1.04 (10-8-2008 11:39) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen match setup control panel page. * **************************************************************************************************/ class NexgenRCPMatchSet extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var UWindowSmallButton saveButton; var UWindowSmallButton startStopButton; var UWindowSmallButton resetButton; var NexgenPlayerListBox playerList; var UWindowEditControl tagInp[4]; var UWindowEditControl numGamesInp; var UWindowEditControl currGameInp; var UWindowEditControl passwordInp; var UWindowCheckbox specNeedNoPWInp; var UWindowCheckbox muteSpecsInp; var UWindowCheckbox enableBootControlInp; var UWindowCheckbox autoLockInp; var UWindowCheckbox autoPauseInp; var UWindowCheckbox autoSeperateInp; var UWindowSmallButton separateButton; var UWindowSmallButton sendPasswordButton; const numTeams = 4; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenPlayerList playerItem; local NexgenContentPanel p; local int region; local int index; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist, , true); p = addContentPanel(); // Match settings. p.splitRegionH(144, defaultComponentDist); p.splitRegionH(16); region = p.currRegion; p.skipRegion(); p.addLabel(client.lng.matchSettingsTxt, true, TA_Center); p.divideRegionH(7); p.divideRegionV(2); p.splitRegionV(96); specNeedNoPWInp = p.addCheckBox(, client.lng.matchSpecNoPassTxt); muteSpecsInp = p.addCheckBox(, client.lng.matchMuteSpecsTxt); enableBootControlInp = p.addCheckBox(, client.lng.matchBootControlTxt); autoLockInp = p.addCheckBox(, client.lng.matchAutoLockTeamsTxt); autoPauseInp = p.addCheckBox(, client.lng.matchAutoPauseTxt); //p.addCheckBox(, "Automatically take a screenshot at the end of each game"); // Should be a client option! p.splitRegionV(96); p.splitRegionV(96); p.addLabel(client.lng.passwordTxt); passwordInp = p.addEditBox(); p.addLabel(client.lng.matchNumOfGamesTxt); numGamesInp = p.addEditBox(, 48, AL_Left); p.addLabel(client.lng.matchCurrGameNumTxt); currGameInp = p.addEditBox(, 48, AL_Left); // Separate by tag settings. p.selectRegion(region); p.selectRegion(p.splitRegionH(72, defaultComponentDist)); p.splitRegionH(1); region = p.currRegion; p.skipRegion(); p.addComponent(class'NexgenDummyComponent'); p.splitRegionH(16); p.addLabel(client.lng.matchSeparateByTagTxt, true, TA_Center); p.splitRegionH(16, defaultComponentDist, , true); p.divideRegionH(2); p.splitRegionV(20); p.divideRegionV(numTeams); p.divideRegionV(numTeams); autoSeperateInp = p.addCheckBox(TA_Right); p.splitRegionV(192); for (index = 0; index < numTeams; index++) { p.addLabel(client.lng.getTeamName(index), , TA_Center); } for (index = 0; index < numTeams; index++) { tagInp[index] = p.addEditBox(, 64, AL_Center); tagInp[index].setMaxLength(16); } p.addLabel(client.lng.matchAutoTagSeparateTxt); p.splitRegionV(80, , , true); p.skipRegion(); separateButton = p.addButton(client.lng.matchDoSeparateTxt); // Match setup control buttons. p.selectRegion(region); p.selectRegion(p.splitRegionH(1)); p.addComponent(class'NexgenDummyComponent'); p.splitRegionH(16, , , true); p.skipRegion(); p.divideRegionV(3, defaultComponentDist); saveButton = p.addButton(client.lng.saveTxt); startStopButton = p.addButton(); resetButton = p.addButton(client.lng.resetTxt); // Send password to. splitRegionH(16, defaultComponentDist, , true); playerList = NexgenPlayerListBox(addListBox(class'NexgenSimplePlayerListBox')); sendPasswordButton = addButton(client.lng.sendPasswordTxt); // Configure components. numGamesInp.setNumericOnly(true); numGamesInp.setMaxLength(2); currGameInp.setNumericOnly(true); currGameInp.setMaxLength(2); passwordInp.setMaxLength(32); playerItem = playerList.addPlayer(); playerItem.pNum = -1; playerItem.pName = client.lng.allPlayersTxt; playerItem.pTeam = 4; separateButton.bDisabled = !client.player.gameReplicationInfo.bTeamGame; saveButton.register(self); startStopButton.register(self); resetButton.register(self); separateButton.register(self); playerList.register(self); sendPasswordButton.register(self); numGamesInp.register(self); currGameInp.register(self); passwordInp.register(self); specNeedNoPWInp.register(self); muteSpecsInp.register(self); enableBootControlInp.register(self); autoLockInp.register(self); autoPauseInp.register(self); autoSeperateInp.register(self); for (index = 0; index < numTeams; index++) { tagInp[index].register(self); } loadMatchSettings(); playerSelected(); } /*************************************************************************************************** * * $DESCRIPTION Loads the match settings. * **************************************************************************************************/ function loadMatchSettings() { local int index; numGamesInp.setValue(string(client.sConf.matchesToPlay)); currGameInp.setValue(string(client.sConf.currentMatch)); passwordInp.setValue(client.sConf.decode(client.sConf.serverPassword)); specNeedNoPWInp.bChecked = !client.sConf.spectatorsNeedPassword; muteSpecsInp.bChecked = client.sConf.muteSpectatorsDuringMatch; enableBootControlInp.bChecked = client.sConf.enableMatchBootControl; autoLockInp.bChecked = client.sConf.matchAutoLockTeams; autoPauseInp.bChecked = client.sConf.matchAutoPause; autoSeperateInp.bChecked = client.sConf.matchAutoSeparate; for (index = 0; index < numTeams; index++) { tagInp[index].setValue(client.sConf.tagsToSeparate[index]); } if (client.sConf.matchModeActivated) { startStopButton.setText(client.lng.stopMatchTxt); } else { startStopButton.setText(client.lng.startMatchTxt); } startStopButton.bDisabled = false; } /*************************************************************************************************** * * $DESCRIPTION Called when a player was selected from the list. * **************************************************************************************************/ function playerSelected() { sendPasswordButton.bDisabled = playerList.selectedItem == none; } /*************************************************************************************************** * * $DESCRIPTION Separates the players by the currently entered tags. * **************************************************************************************************/ function separatePlayers() { local string teamTags[4]; local int index; // Make sure the RPC interface is available. if (!setRPCI()) return; // Get tags. for (index = 0; index < numTeams; index++) { teamTags[index] = class'NexgenUtil'.static.trim(tagInp[index].getValue()); } // Separate players. rpci.separatePlayers(teamTags); } /*************************************************************************************************** * * $DESCRIPTION Sends the password to the currently selected player. * **************************************************************************************************/ function sendPassword() { // Make sure the RPC interface is available. if (!setRPCI()) return; // Send password. rpci.sendPassword(NexgenPlayerList(playerList.selectedItem).pNum, class'NexgenUtil'.static.trim(passwordInp.getValue())); } /*************************************************************************************************** * * $DESCRIPTION Sends the current match settings to the server. * **************************************************************************************************/ function saveSettings() { local string teamTags[4]; local int index; // Make sure the RPC interface is available. if (!setRPCI()) return; // Get tags. for (index = 0; index < numTeams; index++) { teamTags[index] = class'NexgenUtil'.static.trim(tagInp[index].getValue()); } // Update settings. rpci.updateMatchSettings(int(numGamesInp.getValue()), int(currGameInp.getValue()), passwordInp.getValue(), !specNeedNoPWInp.bChecked, muteSpecsInp.bChecked, enableBootControlInp.bChecked, autoLockInp.bChecked, autoPauseInp.bChecked, autoSeperateInp.bChecked, teamTags[0], teamTags[1], teamTags[2], teamTags[3]); } /*************************************************************************************************** * * $DESCRIPTION Starts / stops the match. * **************************************************************************************************/ function toggleMatchMode() { // Make sure the RPC interface is available. if (!setRPCI()) return; // Start / stop match. rpci.toggleMatchMode(); } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // Player has joined the game? if (eventType == client.PE_PlayerJoined) { addPlayerToList(playerList, playerNum, args); } // Player has left the game? if (eventType == client.PE_PlayerLeft) { playerList.removePlayer(playerNum); playerSelected(); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled) { switch (control) { case resetButton: loadMatchSettings(); break; case saveButton: saveSettings(); break; case separateButton: separatePlayers(); break; case sendPasswordButton: sendPassword(); break; case startStopButton: toggleMatchMode(); break; } } // Player selected? if (control == playerList && eventType == DE_Click) { playerSelected(); } // Check if some settings were changed. if (eventType == DE_Change && !client.sConf.matchModeActivated && control != none && (control.isA('UWindowEditControl') || control.isA('UWindowCheckbox'))) { startStopButton.bDisabled = true; } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_MatchSettings) { loadMatchSettings(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ YB "Restart game on last map">W$J84s. W$>. V$>6& ZB "Enable Nexgen boot control"]B "Remove"@/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPMatchControl * $VERSION 1.04 (22-6-2008 17:59) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen match control panel page. * **************************************************************************************************/ class NexgenRCPMatchControl extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenPlayerListBox playerList; var UWindowSmallButton teamButtons[4]; var UWindowSmallButton pauseButton; var UWindowSmallButton endButton; var UWindowSmallButton restartButton; var UWindowSmallButton sendToURLButton; var UWindowSmallButton reconnectAsPlayerButton; var UWindowSmallButton reconnectAsSpecButton; var UWindowSmallButton disableTeamSwitchButton; var UWindowEditControl urlInp; var UWindowCheckbox allowTeamSwitchInp; var UWindowCheckbox allowTeamBalanceInp; var UWindowCheckbox lockTeamsInp; var UWindowCheckbox tournamentModeInp; var UWindowComboControl favouritesList; var color teamColor[4]; var color defaultButtonColor; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int index; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist); playerList = NexgenPlayerListBox(addListBox(class'NexgenPlayerListBox')); splitRegionH(184, defaultComponentDist); // Player controls. p = addContentPanel(); p.splitRegionV(128, defaultComponentDist); p.divideRegionH(8); p.divideRegionH(8); for (index = 0; index < arrayCount(teamButtons); index++) { teamButtons[index] = p.addButton(client.lng.format(client.lng.switchToTeamTxt, client.lng.getTeamName(index))); } sendToURLButton = p.addButton(client.lng.sendToURLTxt); reconnectAsPlayerButton = p.addButton(client.lng.reconnectAsPlayerTxt); reconnectAsSpecButton = p.addButton(client.lng.reconnectAsSpecTxt); disableTeamSwitchButton = p.addButton(client.lng.disableTeamSwitchTxt); p.skipRegion(); p.skipRegion(); p.skipRegion(); favouritesList = p.addListCombo(); urlInp = p.addEditBox(); // Global match controls. splitRegionV(140, defaultComponentDist); p = addContentPanel(); p.divideRegionH(3); pauseButton = p.addButton(client.lng.pauseGameTxt); endButton = p.addButton(client.lng.endGameTxt); restartButton = p.addButton(client.lng.restartGameTxt); p = addContentPanel(); p.divideRegionH(4); allowTeamSwitchInp = p.addCheckBox(TA_Left, client.lng.allowTeamSwitchTxt); allowTeamBalanceInp = p.addCheckBox(TA_Left, client.lng.allowTeamBalanceTxt); lockTeamsInp = p.addCheckBox(TA_Left, client.lng.lockTeamsTxt); tournamentModeInp = p.addCheckBox(TA_Left, client.lng.tournamentModeTxt); // Configure components. urlInp.setMaxLength(128); playerList.register(self); allowTeamSwitchInp.register(self); allowTeamBalanceInp.register(self); lockTeamsInp.register(self); tournamentModeInp.register(self); favouritesList.register(self); allowTeamSwitchInp.bDisabled = !client.player.gameReplicationInfo.bTeamGame; allowTeamBalanceInp.bDisabled = !client.player.gameReplicationInfo.bTeamGame; playerSelected(); setValues(); loadFavourites(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of all input components to the current game info settings. * **************************************************************************************************/ function setValues() { allowTeamSwitchInp.bChecked = !client.gInf.bNoTeamSwitch; allowTeamBalanceInp.bChecked = !client.gInf.bNoTeamBalance; lockTeamsInp.bChecked = client.gInf.bTeamsLocked; tournamentModeInp.bChecked = client.gInf.bTournamentMode; } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * $OVERRIDE * **************************************************************************************************/ function gameInfoChanged(byte infoType) { if (infoType == client.gInf.IT_GlobalRights || infoType == client.gInf.IT_GameSettings) { setValues(); } } /*************************************************************************************************** * * $DESCRIPTION Called when a player was selected from the list. * **************************************************************************************************/ function playerSelected() { local NexgenPlayerList player; local int index; local bool bTeamGame; // Get selected player. player = NexgenPlayerList(playerList.selectedItem); // Determine which buttons can be used. bTeamGame = client.player.gameReplicationInfo.bTeamGame; if (player == none) { for (index = 0; index < arrayCount(teamButtons); index++) { teamButtons[index].bDisabled = true; teamButtons[index].setTextColor(defaultButtonColor); } sendToURLButton.bDisabled = true; reconnectAsPlayerButton.bDisabled = true; reconnectAsSpecButton.bDisabled = true; disableTeamSwitchButton.bDisabled = true; } else { for (index = 0; index < arrayCount(teamButtons); index++) { teamButtons[index].bDisabled = !bTeamGame || player.isSpectator() || index == player.pTeam || index >= client.gInf.maxTeams; if (teamButtons[index].bDisabled) { teamButtons[index].setTextColor(defaultButtonColor); } else { teamButtons[index].setTextColor(teamColor[index]); } } sendToURLButton.bDisabled = false; reconnectAsPlayerButton.bDisabled = !player.isSpectator(); reconnectAsSpecButton.bDisabled = player.isSpectator(); disableTeamSwitchButton.bDisabled = player.isSpectator() || !bTeamGame; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // Player has joined the game? if (eventType == client.PE_PlayerJoined) { addPlayerToList(playerList, playerNum, args); } // Player has left the game? if (eventType == client.PE_PlayerLeft) { playerList.removePlayer(playerNum); playerSelected(); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); playerSelected(); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); setRPCI(); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled && rpci != none) { switch (control) { case pauseButton: rpci.pauseGame(); break; case endButton: rpci.endGame(); break; case restartButton: rpci.restartGame(); break; case teamButtons[0]: rpci.setPlayerTeam(NexgenPlayerList(playerList.selectedItem).pNum, 0); break; case teamButtons[1]: rpci.setPlayerTeam(NexgenPlayerList(playerList.selectedItem).pNum, 1); break; case teamButtons[2]: rpci.setPlayerTeam(NexgenPlayerList(playerList.selectedItem).pNum, 2); break; case teamButtons[3]: rpci.setPlayerTeam(NexgenPlayerList(playerList.selectedItem).pNum, 3); break; case disableTeamSwitchButton: rpci.toggleTeamSwitch(NexgenPlayerList(playerList.selectedItem).pNum); break; case reconnectAsPlayerButton: rpci.reconnectPlayer(NexgenPlayerList(playerList.selectedItem).pNum, false); break; case reconnectAsSpecButton: rpci.reconnectPlayer(NexgenPlayerList(playerList.selectedItem).pNum, true); break; case sendToURLButton: rpci.sendPlayerToURL(NexgenPlayerList(playerList.selectedItem).pNum, class'NexgenUtil'.static.trim(urlInp.getValue())); break; } } // Checkbox pressed? if (control != none && eventType == DE_Click && control.isA('UWindowCheckbox') && !UWindowCheckbox(control).bDisabled && rpci != none) { switch (control) { case allowTeamSwitchInp: rpci.toggleGlobalTeamSwitch(); break; case allowTeamBalanceInp: rpci.toggleGlobalTeamBalance(); break; case lockTeamsInp: rpci.toggleLockedTeams(); break; case tournamentModeInp: rpci.toggleGlobalTournamentMode(); break; } } // Player selected? if (control == playerList && eventType == DE_Click) { playerSelected(); } // Server selected? if (control == favouritesList && eventType == DE_Change) { serverSelected(); } } /*************************************************************************************************** * * $DESCRIPTION Load the favourites from this client. * **************************************************************************************************/ function loadFavourites() { local int index; local int favsCount; local string favStr; local string serverName; local string serverIP; local string serverPort; // Get current favorites. favsCount = class'UBrowserFavoritesFact'.default.favoriteCount; for (index = 0; index < favsCount; index++) { favStr = class'UBrowserFavoritesFact'.default.favorites[index]; class'NexgenUtil'.static.split2(favStr, serverName, favStr, "\\"); class'NexgenUtil'.static.split2(favStr, serverIP, favStr, "\\"); class'NexgenUtil'.static.split2(favStr, serverPort, favStr, "\\"); serverName = class'NexgenUtil'.static.trim(serverName); if (serverName != "") { favouritesList.addItem(serverName, "unreal://" $ serverIP $ ":" $ (int(serverPort) - 1)); } } favouritesList.addItem("", ""); } /*************************************************************************************************** * * $DESCRIPTION Called when a server has been selected from the favourites list.. * **************************************************************************************************/ function serverSelected() { urlInp.setValue(favouritesList.getValue2()); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ _B "Remove ban"Mk/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPLogSettings * $VERSION 1.01 (18-6-2008 12:43) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen log settings control panel page. * **************************************************************************************************/ class NexgenRCPLogSettings extends NexgenPanel; var NexgenClientCore rpci; var UWindowSmallButton resetButton; var UWindowSmallButton saveButton; var UWindowCheckbox logToConsoleInp; var UWindowCheckbox logEventsInp; var UWindowCheckbox logMessagesInp; var UWindowCheckbox logChatMessagesInp; var UWindowCheckbox logPrivateMessagesInp; var UWindowCheckbox logAdminActionsInp; var UWindowCheckbox logToFileInp; var UWindowEditControl logFilePathInp; var UWindowEditControl logFileExtensionInp; var UWindowEditControl logFileNameFormatInp; var UWindowEditControl logTimeStampFormatInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local int region; rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); // Create layout & add components. createPanelRootRegion(); splitRegionH(12, defaultComponentDist); addLabel(client.lng.logSettingsPanelTitle, true, TA_Center); splitRegionH(1, defaultComponentDist); addComponent(class'NexgenDummyComponent'); divideRegionV(2, 2 * defaultComponentDist); divideRegionH(6); divideRegionH(6); logToConsoleInp = addCheckBox(TA_Left, client.lng.logToConsoleTxt, true); logEventsInp = addCheckBox(TA_Left, client.lng.logEventsTxt, true); logMessagesInp = addCheckBox(TA_Left, client.lng.logMessagesTxt, true); logChatMessagesInp = addCheckBox(TA_Left, client.lng.logChatMessagesTxt, true); logPrivateMessagesInp = addCheckBox(TA_Left, client.lng.logPrivateMessagesTxt, true); logAdminActionsInp = addCheckBox(TA_Left, client.lng.logAdminActionsTxt, true); logToFileInp = addCheckBox(TA_Left, client.lng.logToFileTxt, true); splitRegionV(80); splitRegionV(80); splitRegionV(80); splitRegionV(80); splitRegionV(196, , , true); addLabel(client.lng.logFilePathTxt, true); logFilePathInp = addEditBox(); addLabel(client.lng.logFileExtensionTxt, true); logFileExtensionInp = addEditBox(); addLabel(client.lng.logFileNameFormatTxt, true); logFileNameFormatInp = addEditBox(); addLabel(client.lng.logTimeStampFormatTxt, true); logTimeStampFormatInp = addEditBox(); skipRegion(); divideRegionV(2, defaultComponentDist); saveButton = addButton(client.lng.saveTxt); resetButton = addButton(client.lng.resetTxt); // Configure components. logFilePathInp.setMaxLength(200); logFileExtensionInp.setMaxLength(10); logFileNameFormatInp.setMaxLength(100); logTimeStampFormatInp.setMaxLength(100); setValues(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of all input components to the current settings. * **************************************************************************************************/ function setValues() { logToConsoleInp.bChecked = client.sConf.logToConsole; logEventsInp.bChecked = client.sConf.logEvents; logMessagesInp.bChecked = client.sConf.logSystemMessages; logChatMessagesInp.bChecked = client.sConf.logChatMessages; logPrivateMessagesInp.bChecked = client.sConf.logPrivateMessages; logAdminActionsInp.bChecked = client.sConf.logAdminActions; logToFileInp.bChecked = client.sConf.logToFile; logFilePathInp.setValue(client.sConf.logPath); logFileExtensionInp.setValue(client.sConf.logFileExtension); logFileNameFormatInp.setValue(client.sConf.logFileNameFormat); logTimeStampFormatInp.setValue(client.sConf.logFileTimeStampFormat); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled) { switch (control) { case resetButton: setValues(); break; case saveButton: saveSettings(); break; } } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_LogSettings) { setValues(); } } /*************************************************************************************************** * * $DESCRIPTION Saves the server settings. * **************************************************************************************************/ function saveSettings() { rpci.setLogSettings(logEventsInp.bChecked, logMessagesInp.bChecked, logChatMessagesInp.bChecked, logPrivateMessagesInp.bChecked, logAdminActionsInp.bChecked, logToConsoleInp.bChecked, logToFileInp.bChecked, logFilePathInp.getValue(), logFileExtensionInp.getValue(), logFileNameFormatInp.getValue(), logTimeStampFormatInp.getValue()); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ dB "Update ban"MeD5wR$YQYe}eI$fYO%oO,WpWv :Of&O9W  eBY$G8TfaY$-]']-] {a (ada-]d-] Y@gB "Create new ban"iBS$'&~pp,f ,pp,S$,% Jz/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPIgnoredWeaponsSettings * $VERSION 1.03 (20-6-2008 14:24) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen about control panel page. * **************************************************************************************************/ class NexgenRCPIgnoredWeaponsSettings extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenSimpleListBox ignoredWeaponList; var UWindowSmallButton weapSaveButton; var UWindowSmallButton weapRemButton; var UWindowCheckbox ignorePrimaryFireInp; var UWindowCheckbox ignoreAltFireInp; var NexgenEditControl weaponClassInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { // Create layout & add components. createPanelRootRegion(); // Ignored weapons. splitRegionV(256, defaultComponentDist); ignoredWeaponList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); divideRegionH(4); addLabel(client.lng.ignoredWeaponsTxt, true, TA_Center); splitRegionV(96); divideRegionV(2, 2 * defaultComponentDist); splitRegionV(192); addLabel(client.lng.weaponClassTxt); weaponClassInp = addEditBox(); ignorePrimaryFireInp = addCheckBox(TA_Left, client.lng.ignorePrimaryFireTxt); ignoreAltFireInp = addCheckBox(TA_Left, client.lng.ignoreAltFireTxt); divideRegionV(2, defaultComponentDist); skipRegion(); weapSaveButton = addButton(client.lng.saveTxt); weapRemButton = addButton(client.lng.removeTxt); // Configure components. weaponClassInp.setMaxLength(64); loadIgnoredWeaponList(); } /*************************************************************************************************** * * $DESCRIPTION Loads the list of weapons ignored by the spawn protector. * **************************************************************************************************/ function loadIgnoredWeaponList() { local int index; local NexgenSimpleListItem item; local string weaponClass; local string remaining; // Clear list. ignoredWeaponList.selectedItem = none; ignoredWeaponList.items.clear(); // Add weapon classes. while (index < arrayCount(client.sConf.spawnProtectExcludeWeapons) && client.sConf.spawnProtectExcludeWeapons[index] != "") { class'NexgenUtil'.static.split(client.sConf.spawnProtectExcludeWeapons[index], weaponClass, remaining); item = NexgenSimpleListItem(ignoredWeaponList.items.append(class'NexgenSimpleListItem')); item.displayText = weaponClass; item.itemID = index; index++; } // Add 'add new item' option if list isn't full. if (index < arrayCount(client.sConf.spawnProtectExcludeWeapons)) { item = NexgenSimpleListItem(ignoredWeaponList.items.insert(class'NexgenSimpleListItem')); item.displayText = client.lng.addNewItemTxt; item.itemID = -1; } // Signal item select event. weaponSelected(); } /*************************************************************************************************** * * $DESCRIPTION Called when an item from the ignored weapon list was selected. * **************************************************************************************************/ function weaponSelected() { local NexgenSimpleListItem item; local string weaponClass; local string excludedModes; // Get selected item. item = NexgenSimpleListItem(ignoredWeaponList.selectedItem); // Update GUI. weapSaveButton.bDisabled = (item == none); weapRemButton.bDisabled = (item == none) || (item.itemID < 0); ignorePrimaryFireInp.bDisabled = (item == none); ignoreAltFireInp.bDisabled = (item == none); weaponClassInp.setDisabled((item == none)); if (item == none) { ignorePrimaryFireInp.bChecked = false; ignoreAltFireInp.bChecked = false; weaponClassInp.setValue(""); } else if (item.itemID < 0) { ignorePrimaryFireInp.bChecked = false; ignoreAltFireInp.bChecked = false; weaponClassInp.setValue(""); } else { class'NexgenUtil'.static.split(client.sConf.spawnProtectExcludeWeapons[item.itemID], weaponClass, excludedModes); ignorePrimaryFireInp.bChecked = (instr(excludedModes, client.sConf.IW_Fire) >= 0); ignoreAltFireInp.bChecked = (instr(excludedModes, client.sConf.IW_AltFire) >= 0); weaponClassInp.setValue(weaponClass); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Weapon selected? if (control == ignoredWeaponList && eventType == DE_Click) { weaponSelected(); } // Remove weapon selected? if (control == weapRemButton && eventType == DE_Click && !weapRemButton.bDisabled && setRPCI()) { rpci.delIgnoredWeapon(NexgenSimpleListItem(ignoredWeaponList.selectedItem).itemID); } // Save weapon selected? if (control == weapSaveButton && eventType == DE_Click && !weapSaveButton.bDisabled && setRPCI()) { rpci.saveIgnoredWeapon(NexgenSimpleListItem(ignoredWeaponList.selectedItem).itemID, class'NexgenUtil'.static.trim(weaponClassInp.getValue()), ignorePrimaryFireInp.bChecked, ignoreAltFireInp.bChecked); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_ExclWeaponList) { loadIgnoredWeaponList(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ hB "Client IDs"kB "IP addresses"qBj F|[j  N\j %T-F{R Spectatork{ n$f % qY-_ '{ g=j  Oj %f j  bf  Oj  qYMB-F{R SpectatorY{ n$ ~}/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPHome * $VERSION 1.04 (27-11-2007 23:11) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen client start/home control panel page. * **************************************************************************************************/ class NexgenRCPHome extends NexgenPanel; var UWindowSmallButton teamBalanceButton; var UWindowSmallButton teamButton[4]; var UWindowSmallButton playSpecButton; var UWindowSmallButton reconnectButton; var UWindowSmallButton disconnectButton; var UWindowSmallButton exitButton; var UWindowSmallButton mapVoteButton; var UWindowSmallButton startButton; var UWindowSmallButton loginButton; var UMenuLabelControl serverTitleLabel; var color teamColor[4]; var color rightGranted; var color rightDenied; var color rightNotDefined; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local NexgenContentPanel rightPanel; local UMenuLabelControl l; local int index; local string rightDef; // Create layout & add components. createWindowRootRegion(); splitRegionV(96, defaultComponentDist, , true); splitRegionH(32, defaultComponentDist); divideRegionH(14); // Title. p = addContentPanel(); serverTitleLabel = p.addLabel(client.sConf.serverName, true, TA_Center); // Rights overview. p = addContentPanel(); p.splitRegionH(32, defaultComponentDist); p.divideRegionH(2); p.divideRegionV(2, defaultComponentDist); p.addLabel(client.lng.format(client.lng.welcomeTxt, client.playerName, client.title), true); p.addLabel(client.lng.rightsOverviewTxt); p.divideRegionH(arraycount(client.sConf.rightsDef) / 2, defaultComponentDist); p.divideRegionH(arraycount(client.sConf.rightsDef) / 2, defaultComponentDist); for (index = 0; index < arraycount(client.sConf.rightsDef); index++) { rightPanel = p.addContentPanel(PBT_Transparent); l = rightPanel.addLabel("", true, TA_Center); rightDef = client.sConf.rightsDef[index]; if (rightDef == "") { l.setText(client.lng.format(client.lng.rightNotDefinedTxt, string(index + 1))); l.setTextColor(rightNotDefined); } else { l.setText(mid(rightDef, instr(rightDef, client.sConf.separator) + 1)); if (client.hasRight(left(rightDef, instr(rightDef, client.sConf.separator)))) { l.setTextColor(rightGranted); rightPanel.panelBGType = PBT_Default; } else { l.setTextColor(rightDenied); } } } // Sidebar buttons. teamBalanceButton = addButton(client.lng.teamBalanceTxt); teamButton[0] = addButton(client.lng.redTeamTxt); teamButton[1] = addButton(client.lng.blueTeamTxt); teamButton[2] = addButton(client.lng.greenTeamTxt); teamButton[3] = addButton(client.lng.goldTeamTxt); skipRegion(); playSpecButton = addButton(); reconnectButton = addButton(client.lng.reconnectTxt); disconnectButton = addButton(client.lng.disconnectTxt); exitButton = addButton(client.lng.exitTxt); skipRegion(); mapVoteButton = addButton(client.lng.mapVoteTxt); startButton = addButton(client.lng.startTxt); loginButton = addButton(client.lng.loginTxt); // Configure components. if (client.bSpectator) { playSpecButton.setText(client.lng.playTxt); } else { playSpecButton.setText(client.lng.spectateTxt); } setupTeamButtons(); if (client.gInf.gameState > client.gInf.GS_Ready) { startButton.bDisabled = true; } } /*************************************************************************************************** * * $DESCRIPTION Sets the properties of the team control buttons. * **************************************************************************************************/ function setupTeamButtons() { local TournamentGameReplicationInfo gri; local int index; // Check which buttons should be disabled. if (client.bSpectator || !client.player.gameReplicationInfo.bTeamGame) { if (!client.player.gameReplicationInfo.bTeamGame) { teamBalanceButton.bDisabled = true; } for (index = 0; index < arrayCount(teamButton); index++) { teamButton[index].bDisabled = true; } } else { for (index = 0; index < arrayCount(teamButton); index++) { teamButton[index].bDisabled = index >= client.gInf.maxTeams; } } // Set button colors. for (index = 0; index < arrayCount(teamButton); index++) { if (!teamButton[index].bDisabled) { teamButton[index].setTextColor(teamColor[index]); } } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Button pressed? if (control != none && eventType == DE_Click && control.isA('UWindowSmallButton') && !UWindowSmallButton(control).bDisabled) { switch (control) { case teamBalanceButton: client.player.consoleCommand("mutate nsc balanceteams"); break; case teamButton[0]: client.player.consoleCommand("mutate nsc setteam 0"); break; case teamButton[1]: client.player.consoleCommand("mutate nsc setteam 1"); break; case teamButton[2]: client.player.consoleCommand("mutate nsc setteam 2"); break; case teamButton[3]: client.player.consoleCommand("mutate nsc setteam 3"); break; case playSpecButton: if (client.bSpectator) { client.player.consoleCommand("mutate nsc play"); } else { client.player.consoleCommand("mutate nsc spectate"); } UWindowFramedWindow(getParent(class'UWindowFramedWindow')).close(); break; case reconnectButton: client.player.consoleCommand("reconnect"); UWindowFramedWindow(getParent(class'UWindowFramedWindow')).close(); break; case disconnectButton: client.player.consoleCommand("disconnect"); UWindowFramedWindow(getParent(class'UWindowFramedWindow')).close(); break; case exitButton: client.player.consoleCommand("exit"); break; case mapVoteButton: client.player.consoleCommand("mutate nsc openvote"); UWindowFramedWindow(getParent(class'UWindowFramedWindow')).close(); break; case startButton: client.player.consoleCommand("mutate nsc start"); break; case loginButton: client.showPopup("NexgenAdminLoginDialog"); break; } } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_GlobalServerSettings) { serverTitleLabel.setText(client.sConf.serverName); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ lB "Until 'date'"nB "'x' days"x/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPGameInfo * $VERSION 1.04 (6-11-2007 11:49) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen game information overview control panel page. * **************************************************************************************************/ class NexgenRCPGameInfo extends NexgenPanel; var NexgenPlayerListBox playerList; var NexgenSimpleListBox mutatorList; var UMenuLabelControl timeLimitLabel; var UMenuLabelControl fragLimitLabel; var UMenuLabelControl teamScoreLimitLabel; var UMenuLabelControl gameSpeedLabel; var UWindowCheckbox enableTeamSwitchInp; var UWindowCheckbox enableTeamBalanceInp; var UWindowCheckbox teamsLockedInp; var UWindowCheckbox allowNameChangeInp; var UMenuLabelControl fileLabel; var UMenuLabelControl titleLabel; var UMenuLabelControl authorLabel; var UMenuLabelControl playersLabel; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; // Create layout & add components. createWindowRootRegion(); divideRegionV(2, defaultComponentDist); splitRegionH(160, defaultComponentDist); splitRegionH(96, defaultComponentDist); splitRegionH(16); splitRegionH(16); splitRegionH(16); splitRegionH(16); // Game info. addLabel(client.player.gameReplicationInfo.gameName, true, TA_Center); p = addContentPanel(); p.splitRegionV(200/3, , true); p.divideRegionH(8); p.divideRegionH(8); p.addLabel(client.lng.timeLimitTxt, true); p.addLabel(client.lng.scoreLimitTxt, true); p.addLabel(client.lng.teamScoreLimitTxt, true); p.addLabel(client.lng.gameSpeedTxt, true); p.addLabel(client.lng.teamSwitchEnabledTxt, true); p.addLabel(client.lng.teamBalanceEnabledTxt, true); p.addLabel(client.lng.teamsLockedTxt, true); p.addLabel(client.lng.nameChangeAllowedTxt, true); timeLimitLabel = p.addLabel(); fragLimitLabel = p.addLabel(); teamScoreLimitLabel = p.addLabel(); gameSpeedLabel = p.addLabel(); enableTeamSwitchInp = p.addCheckBox(TA_right); enableTeamBalanceInp = p.addCheckBox(TA_right); teamsLockedInp = p.addCheckBox(TA_right); allowNameChangeInp = p.addCheckBox(TA_right); // Mutators. addLabel(client.lng.mutatorsTxt, true, TA_Center); mutatorList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); // Level info. addLabel(client.lng.levelTxt, true, TA_Center); p = addContentPanel(); p.splitRegionV(72, defaultComponentDist); if (client.player.level.screenshot == none) { p.addComponent(class'NexgenDummyComponent', 64, 64, AL_Center, AL_Center); } else { p.addImageBox(client.player.level.screenshot, true, 64, 64); } p.splitRegionV(48); p.divideRegionH(4); p.divideRegionH(4); p.addLabel(client.lng.fileTxt, true); p.addLabel(client.lng.titleTxt, true); p.addLabel(client.lng.authorTxt, true); p.addLabel(client.lng.idealPlayerCountTxt, true); fileLabel = p.addLabel(); titleLabel = p.addLabel(); authorLabel = p.addLabel(); playersLabel = p.addLabel(); // Player info. addLabel(client.lng.playerListTxt, true, TA_Center); playerList = NexgenPlayerListBox(addListBox(class'NexgenPlayerListBox')); // Configure components. enableTeamSwitchInp.bDisabled = true; enableTeamBalanceInp.bDisabled = true; teamsLockedInp.bDisabled = true; allowNameChangeInp.bDisabled = true; setGameInfo(); setLevelInfo(); loadMutatorList(); } /*************************************************************************************************** * * $DESCRIPTION Sets the values of the game info labels. * **************************************************************************************************/ function setGameInfo() { local GameReplicationInfo GRI; local TournamentGameReplicationInfo TGRI; GRI = client.player.gameReplicationInfo; TGRI = TournamentGameReplicationInfo(GRI); if (TGRI != none) { timeLimitLabel.setText(string(TGRI.timeLimit)); fragLimitLabel.setText(string(TGRI.fragLimit)); teamScoreLimitLabel.setText(string(TGRI.goalTeamScore)); } gameSpeedLabel.setText(int(100.0 * client.gInf.gameSpeed) $ "%"); enableTeamSwitchInp.bChecked = !client.gInf.bNoTeamSwitch; enableTeamBalanceInp.bChecked = !client.gInf.bNoTeamBalance; teamsLockedInp.bChecked = client.gInf.bTeamsLocked; allowNameChangeInp.bChecked = !client.gInf.bNoNameChange; } /*************************************************************************************************** * * $DESCRIPTION Sets the values of the level info labels. * **************************************************************************************************/ function setLevelInfo() { local string levelFile; levelFile = string(client); levelFile = left(levelFile, instr(levelFile, ".")) $ ".unr"; fileLabel.setText(levelFile); titleLabel.setText(client.player.level.summary.title); authorLabel.setText(client.player.level.summary.author); playersLabel.setText(client.player.level.summary.idealPlayerCount); } /*************************************************************************************************** * * $DESCRIPTION Loads the list of active mutators. * **************************************************************************************************/ function loadMutatorList() { local NexgenSimpleListItem item; local string remaining; local string mutatorIndex; local string mutatorInfo; local string mutatorClass; local string mutatorName; // For each mutator index.. remaining = client.sConf.activeMutatorIndices; while (remaining != "") { // Get index. class'NexgenUtil'.static.split(remaining, mutatorIndex, remaining); // Get mutator info. mutatorInfo = client.sConf.mutatorInfo[int(mutatorIndex)]; class'NexgenUtil'.static.split(mutatorInfo, mutatorClass, mutatorName); // Add mutator to the list. item = NexgenSimpleListItem(mutatorList.items.append(class'NexgenSimpleListItem')); item.displayText = mutatorName; } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // Player has joined the game? if (eventType == client.PE_PlayerJoined) { addPlayerToList(playerList, playerNum, args); } // Player has left the game? if (eventType == client.PE_PlayerLeft) { playerList.removePlayer(playerNum); } // Attribute changed? if (eventType == client.PE_AttributeChanged) { updatePlayerInfo(playerList, playerNum, args); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * $OVERRIDE * **************************************************************************************************/ function gameInfoChanged(byte infoType) { if (infoType == client.gInf.IT_GlobalRights) { setGameInfo(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ pB "'x' matches"O[/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPClientConfig * $VERSION 1.06 (8-3-2008 22:13) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen client settings control panel page. * **************************************************************************************************/ class NexgenRCPClientConfig extends NexgenPanel; var UWindowCheckbox enableNexgenHUDInp; var UWindowCheckbox useMsgFlashEffectInp; var UWindowCheckbox showPlayerLocationInp; var UWindowCheckbox playPMSoundInp; var UWindowCheckbox autoSSNormalGameInp; var UWindowCheckbox autoSSMatchInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int index; // Create layout & add components. setAcceptsFocus(); createPanelRootRegion(); //createWindowRootRegion(); splitRegionV(196, defaultComponentDist); // Keybindings. addSubPanel(class'NexgenCPKeyBind'); // User Interface settings. splitRegionH(96, defaultComponentDist); p = addContentPanel(); p.splitRegionH(16); p.addLabel(client.lng.UISettingsTxt, true, TA_Center); p.divideRegionH(4); enableNexgenHUDInp = p.addCheckBox(TA_Left, client.lng.enableMsgHUDTxt); useMsgFlashEffectInp = p.addCheckBox(TA_Left, client.lng.msgFlashEffectTxt); showPlayerLocationInp = p.addCheckBox(TA_Left, client.lng.showPlayerLocationTxt); playPMSoundInp = p.addCheckBox(TA_Left, client.lng.pmSoundTxt); // Other stuff. splitRegionH(64, defaultComponentDist); p = addContentPanel(); p.splitRegionH(16); p.addLabel(client.lng.miscSettingsTxt, true, TA_Center); p.divideRegionH(2); autoSSNormalGameInp = p.addCheckBox(TA_Left, client.lng.autoSSNormalGameTxt); autoSSMatchInp = p.addCheckBox(TA_Left, client.lng.autoSSMatchTxt); // Configure components. enableNexgenHUDInp.register(self); useMsgFlashEffectInp.register(self); showPlayerLocationInp.register(self); playPMSoundInp.register(self); autoSSNormalGameInp.register(self); autoSSMatchInp.register(self); enableNexgenHUDInp.bChecked = client.gc.get(client.SSTR_UseNexgenHUD, "true") ~= "true"; useMsgFlashEffectInp.bChecked = client.gc.get(client.SSTR_FlashMessages, "true") ~= "true"; showPlayerLocationInp.bChecked = client.gc.get(client.SSTR_ShowPlayerLocation, "true") ~= "true"; playPMSoundInp.bChecked = client.gc.get(client.SSTR_PlayPMSound, "true") ~= "true"; autoSSNormalGameInp.bChecked = client.gc.get(client.SSTR_AutoSSNormalGame, "false") ~= "true"; autoSSMatchInp.bChecked = client.gc.get(client.SSTR_AutoSSMatch, "true") ~= "true"; } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Toggle Nexgen HUD on/off. if (control == enableNexgenHUDInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_UseNexgenHUD, string(enableNexgenHUDInp.bChecked)); client.gc.saveConfig(); // Change HUD on the fly! if (client.sConf.HUDReplacementClass != none) { if (enableNexgenHUDInp.bChecked) { client.setNexgenMessageHUD(true); } else { client.setNexgenMessageHUD(false); } } } // Toggle message flash effect on/off. if (control == useMsgFlashEffectInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_FlashMessages, string(useMsgFlashEffectInp.bChecked)); client.gc.saveConfig(); // Apply setting. client.nscHUD.bFlashMessages = useMsgFlashEffectInp.bChecked; } // Toggle show player location in teamsay messages on/off. if (control == showPlayerLocationInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_ShowPlayerLocation, string(showPlayerLocationInp.bChecked)); client.gc.saveConfig(); // Apply setting. client.nscHUD.bShowPlayerLocation = showPlayerLocationInp.bChecked; } // Toggle private message sound on/off. if (control == playPMSoundInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_PlayPMSound, string(playPMSoundInp.bChecked)); client.gc.saveConfig(); } // Toggle auto screenshot for normal games on/off. if (control == autoSSNormalGameInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_AutoSSNormalGame, string(autoSSNormalGameInp.bChecked)); client.gc.saveConfig(); } // Toggle auto screenshot for matches on/off. if (control == autoSSMatchInp && eventType == DE_Click) { // Save setting. client.gc.set(client.SSTR_AutoSSMatch, string(autoSSMatchInp.bChecked)); client.gc.saveConfig(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ tB "Forever"sBi$x::$T fiuw*ST!uw*-zSi!uST!u }/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPBootControl * $VERSION 1.05 (15-12-2007 15:38) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen boot control panel page. * **************************************************************************************************/ class NexgenRCPBootControl extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var UWindowComboControl gameTypeList; var NexgenSimpleListBox inclMutatorList; var NexgenSimpleListBox exclMutatorList; var UWindowSmallButton rebootButton; var UWindowSmallButton saveButton; var UWindowSmallButton resetButton; var NexgenEditControl mapPrefixInp; var NexgenEditControl extraOptionsInp; var NexgenEditControl commandsInp; var UWindowCheckbox enableBootControlInp; var UWindowCheckbox restartOnLastGameInp; var UWindowDynamicTextArea previewBox; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int region; // Create layout & add components. createWindowRootRegion(); splitRegionH(20, defaultComponentDist); divideRegionV(2); splitRegionH(20, defaultComponentDist, , true); splitRegionV(20, defaultComponentDist); splitRegionV(20, defaultComponentDist); p = addContentPanel(); splitRegionV(196, , , true); enableBootControlInp = addCheckBox(TA_Right); addLabel(client.lng.enableBootCtrlTxt, true); restartOnLastGameInp = addCheckBox(TA_Right); addLabel(client.lng.restartOnLastGameTxt, true); rebootButton = addButton(client.lng.rebootTxt, 96, AL_Left); divideRegionV(2, defaultComponentDist); saveButton = addButton(client.lng.saveTxt); resetButton = addButton(client.lng.resetTxt); // Mutator list. p.splitRegionV(65, 2 * defaultComponentDist, true); region = p.currRegion; p.skipRegion(); p.divideRegionH(2); p.splitRegionH(16); p.splitRegionH(16); p.addLabel(client.lng.inclMutatorsTxt, true); inclMutatorList = NexgenSimpleListBox(p.addListBox(class'NexgenSimpleListBox')); p.addLabel(client.lng.exclMutatorsTxt, true); exclMutatorList = NexgenSimpleListBox(p.addListBox(class'NexgenSimpleListBox')); // Server boot command line preview. p.selectRegion(region); p.selectRegion(p.splitRegionH(128, defaultComponentDist)); region = p.currRegion; p.skipRegion(); p.splitRegionH(16); p.addLabel(client.lng.bootCmdLineTxt, True); previewBox = p.addDynamicTextArea(); // Server boot options. p.selectRegion(region); p.selectRegion(p.divideRegionH(4, defaultComponentDist)); p.splitRegionV(64); p.splitRegionV(64); p.splitRegionH(16); p.splitRegionH(16); p.addLabel(client.lng.gameTypeTxt, true); gameTypeList = p.addListCombo(); p.addLabel(client.lng.mapPrefixTxt, true); mapPrefixInp = p.addEditBox(); p.addLabel(client.lng.extraCmdLineOptTxt, true); extraOptionsInp = p.addEditBox(); p.addLabel(client.lng.preSwitchCommandsTxt, true); commandsInp = p.addEditBox(); // Configure components. mapPrefixInp.setMaxLength(8); extraOptionsInp.setMaxLength(255); commandsInp.setMaxLength(255); resetButton.register(self); inclMutatorList.register(self); exclMutatorList.register(self); gameTypeList.register(self); mapPrefixInp.register(self); extraOptionsInp.register(self); rebootButton.register(self); loadGameTypeList(); loadMutatorList(); loadBootControlSettings(); previewBox.bTopCentric = true; inclMutatorList.bCanDrag = true; } /*************************************************************************************************** * * $DESCRIPTION Loads the game type list. * **************************************************************************************************/ function loadGameTypeList() { local int index; local string gameClass; local string mapPrefix; local string gameName; while (index < arrayCount(client.sConf.gameTypeInfo) && client.sConf.gameTypeInfo[index] != "") { class'NexgenUtil'.static.split(client.sConf.gameTypeInfo[index], gameClass, mapPrefix); class'NexgenUtil'.static.split(mapPrefix, mapPrefix, gameName); gameTypeList.addItem(gameName, string(index)); index++; } } /*************************************************************************************************** * * $DESCRIPTION Loads the mutator list. * **************************************************************************************************/ function loadMutatorList() { local int index; local NexgenSimpleListItem item; local string mutatorClass; local string mutatorName; while (index < arrayCount(client.sConf.mutatorInfo) && client.sConf.mutatorInfo[index] != "") { class'NexgenUtil'.static.split(client.sConf.mutatorInfo[index], mutatorClass, mutatorName); item = NexgenSimpleListItem(exclMutatorList.items.append(class'NexgenSimpleListItem')); item.displayText = mutatorName; item.itemID = index; index++; } exclMutatorList.items.sort(); } /*************************************************************************************************** * * $DESCRIPTION Loads the boot control settings. * **************************************************************************************************/ function loadBootControlSettings() { local NexgenSimpleListItem oldItem; local NexgenSimpleListItem newItem; local string remaining; local string mutatorIndex; local int index; // Select game type. index = client.sConf.getGameIndex(client.sConf.bootGameType); gameTypeList.setSelectedIndex(index); // Move all mutators to excluded list. for (oldItem = NexgenSimpleListItem(inclMutatorList.items); oldItem != none; oldItem = NexgenSimpleListItem(oldItem.next)) { if (oldItem.itemID >= 0) { newItem = NexgenSimpleListItem(exclMutatorList.items.append(class'NexgenSimpleListItem')); newItem.displayText = oldItem.displayText; newItem.itemID = oldItem.itemID ; } } inclMutatorList.items.clear(); inclMutatorList.selectedItem = none; // Load included mutator list. if (exclMutatorList.selectedItem != none) { exclMutatorList.selectedItem.bSelected = false; exclMutatorList.selectedItem = none; } remaining = client.sConf.bootMutatorIndices; while (remaining != "") { class'NexgenUtil'.static.split(remaining, mutatorIndex, remaining); index = int(mutatorIndex); oldItem = exclMutatorList.getItemByID(index); newItem = NexgenSimpleListItem(inclMutatorList.items.append(class'NexgenSimpleListItem')); newItem.displayText = oldItem.displayText; newItem.itemID = oldItem.itemID; oldItem.remove(); } exclMutatorList.items.sort(); // Load other settings. mapPrefixInp.setValue(client.sConf.bootMapPrefix); extraOptionsInp.setValue(client.sConf.bootOptions); commandsInp.setValue(client.sConf.bootCommands); enableBootControlInp.bChecked = client.sConf.enableBootControl; restartOnLastGameInp.bChecked = client.sConf.restartOnLastGame; // Update preview. updatePreview(); } /*************************************************************************************************** * * $DESCRIPTION Updates the server boot command line preview. * **************************************************************************************************/ function updatePreview() { local string bootCmd; local string gameType; local string mutators; local string mutator; local string remaining; local int index; local NexgenSimpleListItem item; // Get game type. index = gameTypeList.getSelectedIndex(); if (index >= 0) { class'NexgenUtil'.static.split(client.sConf.gameTypeInfo[index], gameType, remaining); } // Get mutators. for (item = NexgenSimpleListItem(inclMutatorList.items); item != none; item = NexgenSimpleListItem(item.next)) { if (item.itemID >= 0) { class'NexgenUtil'.static.split(client.sConf.mutatorInfo[item.itemID], mutator, remaining); if (mutators == "") { mutators = mutator; } else { mutators = mutators $ separator $ " " $ mutator; } } } // Create boot command string. bootCmd = class'NexgenUtil'.static.trim(mapPrefixInp.getValue()) $ "-*.unr"; if (gameType != "") bootCmd = bootCmd $ " ?game=" $ gameType; if (mutators != "") bootCmd = bootCmd $ " ?mutator=" $ mutators; bootCmd = bootCmd $ " " $ class'NexgenUtil'.static.trim(extraOptionsInp.getValue()); // Set preview box contents. previewBox.clear(); previewBox.addText(bootCmd); } /*************************************************************************************************** * * $DESCRIPTION Automatically selects the map prefix for the selected game type. * **************************************************************************************************/ function updateMapPrefix() { local int index; local string gameClass; local string mapPrefix; local string remaining; // Get map prefix. index = gameTypeList.getSelectedIndex(); if (index >= 0) { class'NexgenUtil'.static.split(client.sConf.gameTypeInfo[index], gameClass, remaining); class'NexgenUtil'.static.split(remaining, mapPrefix, remaining); } else { mapPrefix = ""; } // Set map prefix. mapPrefixInp.setValue(mapPrefix); } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Sends the new boot control settings to the server. * $REQUIRE rpci != none * **************************************************************************************************/ function updateBootControl() { local string mutators; local NexgenSimpleListItem item; // Get mutators. for (item = NexgenSimpleListItem(inclMutatorList.items); item != none; item = NexgenSimpleListItem(item.next)) { if (item.itemID >= 0) { if (mutators == "") { mutators = string(item.itemID); } else { mutators = mutators $ separator $ " " $ item.itemID; } } } // Send new settings to the server. rpci.updateBootControl(enableBootControlInp.bChecked, restartOnLastGameInp.bChecked, gameTypeList.getSelectedIndex(), mutators, class'NexgenUtil'.static.trim(mapPrefixInp.getValue()), class'NexgenUtil'.static.trim(extraOptionsInp.getValue()), class'NexgenUtil'.static.trim(commandsInp.getValue())); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local NexgenSimpleListItem newItem; super.notify(control, eventType); setRPCI(); // Reset button pressed? if (control == resetButton && eventType == DE_Click) { loadBootControlSettings(); } // Save button pressed? if (control == saveButton && eventType == DE_Click && rpci != none) { updateBootControl(); } // Reboot button pressed? if (control == rebootButton && eventType == DE_Click && rpci != none) { rpci.rebootServer(); } // Mutator selected? if (control == inclMutatorList && eventType == DE_Click) { if (exclMutatorList.selectedItem != none) { exclMutatorList.selectedItem.bSelected = false; exclMutatorList.selectedItem = none; } } else if (control == exclMutatorList && eventType == DE_Click) { if (inclMutatorList.selectedItem != none) { inclMutatorList.selectedItem.bSelected = false; inclMutatorList.selectedItem = none; } } // Mutator double clicked? if (control == inclMutatorList && eventType == DE_DoubleClick && inclMutatorList.selectedItem != none) { newItem = NexgenSimpleListItem(exclMutatorList.items.append(class'NexgenSimpleListItem')); newItem.displayText = NexgenSimpleListItem(inclMutatorList.selectedItem).displayText; newItem.itemID = NexgenSimpleListItem(inclMutatorList.selectedItem).itemID; if (exclMutatorList.selectedItem != none) { exclMutatorList.selectedItem.bSelected = false; } exclMutatorList.selectedItem = newItem; newItem.bSelected = true; inclMutatorList.selectedItem.remove(); inclMutatorList.selectedItem = none; exclMutatorList.sort(); updatePreview(); } else if (control == exclMutatorList && eventType == DE_DoubleClick && exclMutatorList.selectedItem != none) { newItem = NexgenSimpleListItem(inclMutatorList.items.append(class'NexgenSimpleListItem')); newItem.displayText = NexgenSimpleListItem(exclMutatorList.selectedItem).displayText; newItem.itemID = NexgenSimpleListItem(exclMutatorList.selectedItem).itemID; if (inclMutatorList.selectedItem != none) { inclMutatorList.selectedItem.bSelected = false; } inclMutatorList.selectedItem = newItem; newItem.bSelected = true; exclMutatorList.selectedItem.remove(); exclMutatorList.selectedItem = none; updatePreview(); } // Game type selected? if (control == gameTypeList && eventType == DE_Change) { updateMapPrefix(); //updatePreview(); } // Map prefix changed? if (control == mapPrefixInp && eventType == DE_Change) { updatePreview(); } // Extra options changed? if (control == extraOptionsInp && eventType == DE_Change) { updatePreview(); } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_BootControl) { loadBootControlSettings(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ |BhvRh vB "Ban period"g/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPBanControl * $VERSION 1.01 (2-11-2007 21:12) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen ban control panel page. * **************************************************************************************************/ class NexgenRCPBanControl extends NexgenPanel; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenSimpleListBox banList; var NexgenSimpleListBox ipList; var NexgenSimpleListBox idList; var UWindowSmallButton addBanButton; var UWindowSmallButton updateBanButton; var UWindowSmallButton deleteBanButton; var UWindowEditControl playerNameInp; var UWindowEditControl banReasonInp; var UWindowCheckbox banPeriodInp[3]; var NexgenEditControl matchCountInp; var NexgenEditControl dateInp; var UWindowSmallButton addIPButton; var UWindowSmallButton delIPButton; var UWindowSmallButton addIDButton; var UWindowSmallButton delIDButton; var UWindowEditControl ipAddressInp; var UWindowEditControl clientIDInp; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int region; local int index; // Create layout & add components. createWindowRootRegion(); splitRegionV(160, defaultComponentDist); splitRegionH(72, defaultComponentDist, , true); // Ban entry editor. p = addContentPanel(); // Player name & ban reason. region = p.splitRegionH(40, defaultComponentDist) + 1; p.splitRegionV(96); p.skipRegion(); p.divideRegionH(2); p.divideRegionH(2); p.addLabel(client.lng.playerNameTxt, true); p.addLabel(client.lng.banReasonTxt, true); playerNameInp = p.addEditBox(); banReasonInp = p.addEditBox(); // Ban period. p.selectRegion(region); p.selectRegion(p.splitRegionH(64, defaultComponentDist)); region = p.currRegion + 1; p.splitRegionH(1); p.skipRegion(); p.addComponent(class'NexgenDummyComponent'); p.splitRegionV(96); p.divideRegionH(3); p.splitRegionV(96, defaultComponentDist); p.addLabel(client.lng.banPeriodTxt, true); p.skipRegion(); p.skipRegion(); p.divideRegionH(3); p.divideRegionH(3); banPeriodInp[0] = p.addCheckBox(TA_Left, client.lng.banForeverTxt); banPeriodInp[1] = p.addCheckBox(TA_Left, client.lng.banMatchesTxt); banPeriodInp[2] = p.addCheckBox(TA_Left, client.lng.banUntilDateTxt); p.skipRegion(); matchCountInp = p.addEditBox(); dateInp = p.addEditBox(); // Banned IP's and ID's. p.selectRegion(region); p.selectRegion(p.splitRegionH(1, defaultComponentDist)); p.addComponent(class'NexgenDummyComponent'); p.divideRegionH(2, defaultComponentDist); p.splitRegionV(224, defaultComponentDist, , true); p.splitRegionV(224, defaultComponentDist, , true); p.splitRegionH(56); ipList = NexgenSimpleListBox(p.addListBox(class'NexgenSimpleListBox')); p.splitRegionH(56); idList = NexgenSimpleListBox(p.addListBox(class'NexgenSimpleListBox')); p.divideRegionH(3); p.skipRegion(); p.divideRegionH(3); p.skipRegion(); p.addLabel(client.lng.ipAddressesTxt, true); p.divideRegionV(2, defaultComponentDist); ipAddressInp = p.addEditBox(); p.addLabel(client.lng.clientIDsTxt, true); p.divideRegionV(2, defaultComponentDist); clientIDInp = p.addEditBox(); addIPButton = p.addButton(client.lng.addTxt); delIPButton = p.addButton(client.lng.removeTxt); addIDButton = p.addButton(client.lng.addTxt); delIDButton = p.addButton(client.lng.removeTxt); // Ban list. banList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); // Ban list editor. p = addContentPanel(); p.divideRegionH(3); addBanButton = p.addButton(client.lng.addBanTxt); updateBanButton = p.addButton(client.lng.updateBanTxt); deleteBanButton = p.addButton(client.lng.delBanTxt); // Configure components. ipAddressInp.setMaxLength(15); clientIDInp.setMaxLength(32); playerNameInp.setMaxLength(32); banReasonInp.setMaxLength(255); matchCountInp.setMaxLength(3); matchCountInp.setNumericOnly(true); dateInp.setMaxLength(24); banList.register(self); ipList.register(self); idList.register(self); addIPButton.register(self); delIPButton.register(self); addIDButton.register(self); delIDButton.register(self); addBanButton.register(self); updateBanButton.register(self); deleteBanButton.register(self); for (index = 0; index < arrayCount(banPeriodInp); index++) { banPeriodInp[index].register(self); } loadBanList(); banPeriodInp[0].bChecked = true; banPeriodTypeSelected(); delIPButton.bDisabled = true; delIDButton.bDisabled = true; dateInp.setValue(client.lng.dateFormatStr); } /*************************************************************************************************** * * $DESCRIPTION Load the banlist. * **************************************************************************************************/ function loadBanList() { local int index; local NexgenSimpleListItem item; local int numBans; // Clear list. banList.items.clear(); banList.selectedItem = none; // Add bans. while(index < arrayCount(client.sConf.bannedName) && client.sConf.bannedName[index] != "") { item = NexgenSimpleListItem(banList.items.append(class'NexgenSimpleListItem')); item.displayText = client.sConf.bannedName[index]; item.itemID = index; index++; } // Configure components. numBans = index; addBanButton.bDisabled = numBans >= arrayCount(client.sConf.bannedName); banSelected(); } /*************************************************************************************************** * * $DESCRIPTION Called when a ban entry has been selected. Loads the info for the selected ban * entry & configures the components. * **************************************************************************************************/ function banSelected() { // Item selected? if (banList.selectedItem == none) { // No. updateBanButton.bDisabled = true; deleteBanButton.bDisabled = true; } else { // Yes. updateBanButton.bDisabled = false; deleteBanButton.bDisabled = false; loadBanInfo(NexgenSimpleListItem(banList.selectedItem).itemID); } } /*************************************************************************************************** * * $DESCRIPTION Loads the information for the specified ban entry. * $PARAM entryNum The entry number in the ban list. * $REQUIRE 0 <= entryNum && entryNum < arrayCount(client.sConf.bannedName) && * client.sConf.bannedName[entryNum] != "" * **************************************************************************************************/ function loadBanInfo(int entryNum) { local string remaining; local string part; local NexgenSimpleListItem item; local byte banPeriodType; local string banArgs; local int index; // Player name & ban reason. playerNameInp.setValue(client.sConf.bannedName[entryNum]); banReasonInp.setValue(client.sConf.banReason[entryNum]); // Ban period. client.sConf.getBanPeriodType(client.sConf.banPeriod[entryNum], banPeriodType, banArgs); for (index = 0; index < arrayCount(banPeriodInp); index++) { banPeriodInp[index].bChecked = index == banPeriodType; } if (banPeriodType == client.sConf.BP_Matches) { matchCountInp.setDisabled(false); matchCountInp.setValue(banArgs); dateInp.setDisabled(true); dateInp.setValue(""); } else if (banPeriodType == client.sConf.BP_UntilDate) { matchCountInp.setDisabled(true); matchCountInp.setValue(""); dateInp.setDisabled(false); dateInp.setValue(client.lng.getLocalizedDateStr(banArgs)); } else { matchCountInp.setDisabled(true); matchCountInp.setValue(""); dateInp.setDisabled(true); dateInp.setValue(""); } // Load ip addresses. ipList.items.clear(); ipList.selectedItem = none; remaining = client.sConf.bannedIPs[entryNum]; while (remaining != "") { // Split head element from tail. index = instr(remaining, separator); if (index < 0) { part = remaining; remaining = ""; } else { part = left(remaining, index); remaining = mid(remaining, index + len(separator)); } // Add element to list. item = NexgenSimpleListItem(ipList.items.append(class'NexgenSimpleListItem')); item.displayText = part; } addIPButton.bDisabled = ipList.items.countShown() >= client.sConf.maxBanIPAddresses; delIPButton.bDisabled = true; // Load client id's. idList.items.clear(); idList.selectedItem = none; remaining = client.sConf.bannedIDs[entryNum]; while (remaining != "") { // Split head element from tail. index = instr(remaining, separator); if (index < 0) { part = remaining; remaining = ""; } else { part = left(remaining, index); remaining = mid(remaining, index + len(separator)); } // Add element to list. item = NexgenSimpleListItem(idList.items.append(class'NexgenSimpleListItem')); item.displayText = part; } addIDButton.bDisabled = idList.items.countShown() >= client.sConf.maxBanClientIDs; delIDButton.bDisabled = true; } /*************************************************************************************************** * * $DESCRIPTION Called when a ban period type was selected. * **************************************************************************************************/ function banPeriodTypeSelected() { matchCountInp.setDisabled(!banPeriodInp[client.sConf.BP_Matches].bChecked); dateInp.setDisabled(!banPeriodInp[client.sConf.BP_UntilDate].bChecked); } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_BanList) { loadBanList(); } } /*************************************************************************************************** * * $DESCRIPTION Assembles the current ban period string. * $RETURN The ban period string for the currently selected settings. * **************************************************************************************************/ function string getCurrentBanPeriod() { if (banPeriodInp[client.sConf.BP_Matches].bChecked) { return "M" $ matchCountInp.getValue(); } else if (banPeriodInp[client.sConf.BP_UntilDate].bChecked) { return "U" $ client.lng.getDelocalizedDateStr(dateInp.getValue()); } else { return ""; } } /*************************************************************************************************** * * $DESCRIPTION Returns the ip addresses entered in the ip list. * $RETURN A string containing all ip addresses entered in the ip list. * **************************************************************************************************/ function string getIPList() { local NexgenSimpleListItem item; local string list; // Assemble list. for (item = NexgenSimpleListItem(ipList.items); item != none; item = NexgenSimpleListItem(item.next)) { if (item.displayText != "") { if (list == "") { list = item.displayText; } else { list = list $ separator $ item.displayText; } } } // Return the list. return list; } /*************************************************************************************************** * * $DESCRIPTION Returns the client id's entered in the id list. * $RETURN A string containing all client id's entered in the id list. * **************************************************************************************************/ function string getIDList() { local NexgenSimpleListItem item; local string list; // Assemble list. for (item = NexgenSimpleListItem(idList.items); item != none; item = NexgenSimpleListItem(item.next)) { if (item.displayText != "") { if (list == "") { list = item.displayText; } else { list = list $ separator $ item.displayText; } } } // Return the list. return list; } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local int index; local int selectedIndex; local string value; local NexgenSimpleListItem item; local string playerName; super.notify(control, eventType); setRPCI(); // Add ban entry button clicked? if (control == addBanButton && eventType == DE_Click && !addBanButton.bDisabled) { playerName = class'NexgenUtil'.static.trim(playerNameInp.getValue()); if (playerName != "") { rpci.addBan(playerName, getIPList(), getIDList(), class'NexgenUtil'.static.trim(banReasonInp.getValue()), getCurrentBanPeriod()); } } // Update ban entry button clicked? if (control == updateBanButton && eventType == DE_Click && !updateBanButton.bDisabled) { playerName = class'NexgenUtil'.static.trim(playerNameInp.getValue()); if (playerName != "") { rpci.updateBan(NexgenSimpleListItem(banList.selectedItem).itemID, playerName, getIPList(), getIDList(), class'NexgenUtil'.static.trim(banReasonInp.getValue()), getCurrentBanPeriod()); } } // Delete ban entry button clicked? if (control == deleteBanButton && eventType == DE_Click && !deleteBanButton.bDisabled) { rpci.deleteBan(NexgenSimpleListItem(banList.selectedItem).itemID); } // Ban entry selected? if (control == banList && eventType == DE_Click) { banSelected(); } // IP address selected? if (control == ipList && eventType == DE_Click) { delIPButton.bDisabled = ipList.selectedItem == none; if (ipList.selectedItem != none) { ipAddressInp.setValue(NexgenSimpleListItem(ipList.selectedItem).displayText); } } // Client ID selected? if (control == idList && eventType == DE_Click) { delIDButton.bDisabled = idList.selectedItem == none; if (idList.selectedItem != none) { clientIDInp.setValue(NexgenSimpleListItem(idList.selectedItem).displayText); } } // Add IP address pressed? if (control == addIPButton && eventType == DE_Click && !addIPButton.bDisabled) { value = class'NexgenUtil'.static.trim(ipAddressInp.getValue()); if (class'NexgenUtil'.static.isValidIPAddress(value)) { item = NexgenSimpleListItem(ipList.items.append(class'NexgenSimpleListItem')); item.displayText = value; addIPButton.bDisabled = ipList.items.countShown() >= client.sConf.maxBanIPAddresses; } } // Del IP address pressed? if (control == delIPButton && eventType == DE_Click && !delIPButton.bDisabled) { ipList.selectedItem.remove(); ipList.selectedItem = none; delIPButton.bDisabled = true; addIPButton.bDisabled = ipList.items.countShown() >= client.sConf.maxBanIPAddresses; } // Del client ID pressed? if (control == addIDButton && eventType == DE_Click && !addIDButton.bDisabled) { value = class'NexgenUtil'.static.trim(clientIDInp.getValue()); if (class'NexgenUtil'.static.isValidClientID(value)) { item = NexgenSimpleListItem(idList.items.append(class'NexgenSimpleListItem')); item.displayText = value; addIDButton.bDisabled = idList.items.countShown() >= client.sConf.maxBanClientIDs; } } // Del client ID pressed? if (control == delIDButton && eventType == DE_Click && !delIDButton.bDisabled) { idList.selectedItem.remove(); idList.selectedItem = none; delIDButton.bDisabled = true; addIDButton.bDisabled = idList.items.countShown() >= client.sConf.maxBanClientIDs; } // Ban period type selected? if (eventType == DE_Click && control.isA('UWindowCheckbox')) { // Find selected type. selectedIndex = -1; while (selectedIndex < 0 && index < arrayCount(banPeriodInp)) { if (control == banPeriodInp[index]) { selectedIndex = index; } else { index++; } } // Has a period been selected? if (selectedIndex >= 0) { // Yes, update components. for (index = 0; index < arrayCount(banPeriodInp); index++) { banPeriodInp[index].bChecked = index == selectedIndex; } banPeriodTypeSelected(); } } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ xB "Ban/kick reason"}/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPAccountTypes * $VERSION 1.01 (20-10-2007 10:50) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen account type manager control panel page. * **************************************************************************************************/ class NexgenRCPAccountTypes extends NexgenPanel; var int numAccountTypes; var NexgenClientCore rpci; // Remote Procedure Call interface. var NexgenSimpleListBox accountTypeList; var UWindowSmallButton addAccountTypeButton; var UWindowSmallButton deleteAccountTypeButton; var UWindowSmallButton moveUpButton; var UWindowSmallButton moveDownButton; var UWindowEditControl accountNameInp; var UWindowEditControl accountTitleInp; var UWindowEditControl accountPasswordInp; var UWindowCheckbox rightEnableInp[18]; var UWindowSmallButton resetButton; var UWindowSmallButton saveButton; /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local NexgenContentPanel p; local int index; local string rightDef; // Create layout & add components. createWindowRootRegion(); splitRegionV(192, defaultComponentDist); splitRegionH(96, defaultComponentDist, , true); // Account info panel. p = addContentPanel(); p.splitRegionH(64); p.splitRegionV(96); p.splitRegionH(16, , , true); p.divideRegionH(3); p.divideRegionH(3); p.divideRegionV(2, defaultComponentDist); p.splitRegionV(182); p.addLabel(client.lng.accountNameTxt, true); p.addLabel(client.lng.accountTitleTxt, true); p.addLabel(client.lng.passwordTxt, true); accountNameInp = p.addEditBox(); accountTitleInp = p.addEditBox(); accountPasswordInp = p.addEditBox(); p.divideRegionH(arraycount(rightEnableInp) / 2); p.divideRegionH(arraycount(rightEnableInp) / 2); p.divideRegionV(2, defaultComponentDist); p.skipRegion(); for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightDef == "") { rightEnableInp[index] = p.addCheckBox(TA_Left, client.lng.format(client.lng.rightNotDefinedTxt, string(index + 1))); rightEnableInp[index].bDisabled = true; } else { rightEnableInp[index] = p.addCheckBox(TA_Left, mid(rightDef, instr(rightDef, client.sConf.separator) + 1)); } } saveButton = p.addButton(client.lng.saveTxt); resetButton = p.addButton(client.lng.resetTxt); // Account type list. accountTypeList = NexgenSimpleListBox(addListBox(class'NexgenSimpleListBox')); // Account type controls. p = addContentPanel(); p.divideRegionH(4); addAccountTypeButton = p.addButton(client.lng.addAccountTypeTxt); deleteAccountTypeButton = p.addButton(client.lng.delAccountTypeTxt); moveUpButton = p.addButton(client.lng.moveUpTxt); moveDownButton = p.addButton(client.lng.moveDownTxt); // Configure components. accountNameInp.setMaxLength(24); accountTitleInp.setMaxLength(24); accountPasswordInp.setMaxLength(32); accountTypeList.register(self); addAccountTypeButton.register(self); deleteAccountTypeButton.register(self); moveUpButton.register(self); moveDownButton.register(self); resetButton.register(self); saveButton.register(self); loadAccountTypes(); accountTypeSelected(); } /*************************************************************************************************** * * $DESCRIPTION Loads the account types. * **************************************************************************************************/ function loadAccountTypes() { local int index; local NexgenSimpleListItem item; accountTypeList.items.clear(); accountTypeList.selectedItem = none; while(index < arrayCount(client.sConf.atTypeName) && client.sConf.atTypeName[index] != "") { item = NexgenSimpleListItem(accountTypeList.items.append(class'NexgenSimpleListItem')); item.displayText = client.sConf.atTypeName[index]; item.itemID = index; index++; } numAccountTypes = index; } /*************************************************************************************************** * * $DESCRIPTION Loads the settings for the specified account type. * $PARAM accountTypeNum The ID number of the account type to load. * $REQUIRE 0 <= accountTypeNum && accountTypeNum <= arrayCount(client.sConf.atTypeName) * **************************************************************************************************/ function loadAccountTypeInfo(int accountTypeNum) { local int index; local string accountRights; local string rightDef; local string rightID; // Cancel on error. In theory this should not happen. if (client.sConf.atTypeName[accountTypeNum] == "") { return; } // Load general info. accountNameInp.setValue(client.sConf.atTypeName[accountTypeNum]); accountTitleInp.setValue(client.sConf.atTitle[accountTypeNum]); accountPasswordInp.setValue(client.sConf.decode(client.sConf.atPassword[accountTypeNum])); // Load right assignment. accountRights = client.sConf.atRights[accountTypeNum]; for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightDef == "") { // Right isn't defined. rightEnableInp[index].bChecked = false; } else { rightID = left(rightDef, instr(rightDef, separator)); rightEnableInp[index].bChecked = hasRight(accountRights, rightID); } } } /*************************************************************************************************** * * $DESCRIPTION Called when an account type was selected from the list. * **************************************************************************************************/ function accountTypeSelected() { local NexgenSimpleListItem selected; // Check which buttons should be enabled / disabled. if (accountTypeList.selectedItem == none) { // No item selected. deleteAccountTypeButton.bDisabled = true; moveUpButton.bDisabled = true; moveDownButton.bDisabled = true; resetButton.bDisabled = true; saveButton.bDisabled = true; } else { // Other account type selected. selected = NexgenSimpleListItem(accountTypeList.selectedItem); deleteAccountTypeButton.bDisabled = selected.itemID < 1; moveUpButton.bDisabled = selected.itemID < 2; moveDownButton.bDisabled = selected.itemID < 1 || selected.itemID + 1 == numAccountTypes; resetButton.bDisabled = false; saveButton.bDisabled = false; } // Load account info. if (accountTypeList.selectedItem != none) { loadAccountTypeInfo(NexgenSimpleListItem(accountTypeList.selectedItem).itemID); } } /*************************************************************************************************** * * $DESCRIPTION Checks whether the specified right is included in the given right string. * $PARAM rights The rights specifier string. * $PARAM rightID String identifier of the client right. * $REQUIRE rightID != "" * $RETURN True if the right is included, false if not. * **************************************************************************************************/ function bool hasRight(string rights, string rightID) { return instr(rights $ separator, rightID $ separator) >= 0; } /*************************************************************************************************** * * $DESCRIPTION Returns a string containing the currently selected rights. * $RETURN A string containing the rights currently selected. * **************************************************************************************************/ function string getCurrentRights() { local string rights; local string rightDef; local int index; // Check for each right if it is selected. for (index = 0; index < arraycount(rightEnableInp); index++) { rightDef = client.sConf.rightsDef[index]; if (rightEnableInp[index].bChecked && rightDef != "") { if (rights == "") { rights = left(rightDef, instr(rightDef, separator)); } else { rights = rights $ separator $ left(rightDef, instr(rightDef, separator)); } } } // Return result. return rights; } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); setRPCI(); // Account type selected. if (control == accountTypeList && eventType == DE_Click) { accountTypeSelected(); } // Reset account type info. if (control == resetButton && !resetButton.bDisabled && eventType == DE_Click) { loadAccountTypeInfo(NexgenSimpleListItem(accountTypeList.selectedItem).itemID); } // Save account type info. if (control == saveButton && !saveButton.bDisabled && eventType == DE_Click && rpci != none) { rpci.updateAccountType(NexgenSimpleListItem(accountTypeList.selectedItem).itemID, accountNameInp.getValue(), getCurrentRights(), accountTitleInp.getValue(), accountPasswordInp.getValue()); } // Add account type. if (control == addAccountTypeButton && !addAccountTypeButton.bDisabled && eventType == DE_Click && rpci != none) { rpci.addAccountType(accountNameInp.getValue(), getCurrentRights(), accountTitleInp.getValue(), accountPasswordInp.getValue()); } // Delete account type. if (control == deleteAccountTypeButton && !deleteAccountTypeButton.bDisabled && eventType == DE_Click && rpci != none) { rpci.deleteAccountType(NexgenSimpleListItem(accountTypeList.selectedItem).itemID); } // Move account type up. if (control == moveUpButton && !moveUpButton.bDisabled && eventType == DE_Click && rpci != none) { rpci.moveAccountType(NexgenSimpleListItem(accountTypeList.selectedItem).itemID, false); } // Move account type down. if (control == moveDownButton && !moveDownButton.bDisabled && eventType == DE_Click && rpci != none) { rpci.moveAccountType(NexgenSimpleListItem(accountTypeList.selectedItem).itemID, true); } } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the RPC interface for this control panel. * $REQUIRE client != none * $RETURN True if the RPC interface has been set, false if not. * $ENSURE result == true ? rcpi != none : true * **************************************************************************************************/ function bool setRPCI() { // Check if RPC interface is already set. if (rpci == none) { // Attempt to get the RPC interface. rpci = NexgenClientCore(client.getController(class'NexgenClientCore'.default.ctrlID)); return rpci != none; } else { // It is. return true; } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { // Relevant settings for this panel? if (configType == client.sConf.CT_AccountTypes) { loadAccountTypes(); accountTypeSelected(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ yB "Player name"zB "Tournament mode"{B "Lock the game"~B "Allow team balancing"BJ$IWq-z(-J$0rf*frv*va Uvfva/!Z.a v|.fNwv*-z'vfa/!r .f*wf*f K"/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenRCPAbout * $VERSION 1.00 (10-3-2007 21:20) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen about control panel page. * **************************************************************************************************/ class NexgenRCPAbout extends NexgenPanel; #exec TEXTURE IMPORT NAME=logo FILE=Resources\logo.pcx GROUP="GFX" FLAGS=1 MIPS=Off /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { // Create layout & add components. createWindowRootRegion(); divideRegionV(2); addImageBox(Texture'logo'); divideRegionH(17); skipRegion(); addLabel("Nexgen Server Controller", true, TA_Center); addLabel("version" @ left(class'NexgenUtil'.default.version, 4) @ "build" @ class'NexgenUtil'.default.internalVersion, , TA_Center); addLabel("Copyright 2006-2008 Zeropoint productions", , TA_Center); addLabel("d.scheerens@gmail.com", , TA_Center); skipRegion(); addLabel("Development", true, TA_Center); addLabel("Daan \"Defrost\" Scheerens", , TA_Center); skipRegion(); addLabel("Credits and thanks to", true, TA_Center); addLabel("Mickal \"ATHoS\" DEHEZ", , TA_Center); addLabel("Matthew \"MSuLL\" Sullivan", , TA_Center); addLabel("David \"The_Dave\" Schwartzstein", , TA_Center); addLabel("Zohar \"SuB\" Zada", , TA_Center); addLabel("*TNT*CryptKeeper", , TA_Center); addLabel("[BOSS]Snipes", , TA_Center); skipRegion(); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ BC "Allow team switching"NCw `yalfNa :Z|22UseNexgenHUDtruetruew U*I'Na?@'w %w ,ww I*w Ihw wMJ22RunCount0&2ERunCountSM2b^M, $ ?Welcome to Nexgen, type !open to open the control panel.h HN/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPrivateMsgDialog * $VERSION 1.00 (25-12-2006 17:06) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player is banned from the server. * **************************************************************************************************/ class NexgenPrivateMsgDialog extends NexgenPopupDialog; var UMenuLabelControl msgLabel[5]; // Message content label components. var UMenuLabelControl senderLabel; // Message sender label component. var UWindowSmallButton replyButton; // Reply button component. var localized string caption; // Caption to display on the dialog. var localized string senderText; // Message sender label text. var localized string messageText; // Received message label text. var localized string replyButtonText; // Received message label text. const firstLineWrapLen = 60; // Wrap lenght at the first message line. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); senderLabel = addPropertyLabel(cy, senderText, 64.0); msgLabel[0] = addPropertyLabel(cy, messageText, 64.0); msgLabel[1] = addLabel(cy); msgLabel[2] = addLabel(cy); msgLabel[3] = addLabel(cy); msgLabel[4] = addLabel(cy); replyButton = addButton(replyButtonText, 64.0); } /*************************************************************************************************** * * $DESCRIPTION Sets the contents for this dialog. * $PARAM message The message that was received. * $PARAM sender Name of the player that has send the message. * $PARAM str3 Not used. * $PARAM str4 Not used. * $OVERRIDE * **************************************************************************************************/ function setContent(optional string message, optional string sender, optional string str3, optional string str4) { local int lineNum; local int index; local string remaining; local string lineStr; local int wrapLen; local int wrapPos; local string lineEntry; // Set sender label. senderLabel.setText(sender); // Set message labels. remaining = message $ newlineToken; while (remaining != "" && lineNum < arrayCount(msgLabel)) { // Split at new line tokens. index = instr(remaining, newlineToken); lineStr = left(remaining, index); remaining = mid(remaining, index + len(newlineToken)); // Split at wrap length. do { // Get wrap position. if (lineNum == 0) { wrapLen = firstLineWrapLen; } else { wrapLen = wrapLength; } wrapPos = getWrapPosition(lineStr, wrapLen); // Split line. if (wrapPos < 0) { lineEntry = lineStr; lineStr = ""; } else { lineEntry = left(lineStr, wrapPos); lineStr = mid(lineStr, wrapPos); } msgLabel[lineNum++].setText(class'NexgenUtil'.static.trim(lineEntry)); } until (lineStr == "" || lineNum >= arrayCount(msgLabel)); } // Clean empty lines. for (index = lineNum; index < arrayCount(msgLabel); index++) { msgLabel[index].setText(""); } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the reconnect or spectator buttons have been clicked and deals with it * accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Reply button. if (control == replyButton && eventType == DE_Click) { client.showPanel(class'NexgenRCPPrivateMsg'.default.panelIdentifier); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ C@C|@[ 2 AC;Cn9ˉi'r᱘᱘ 3B᱘ V]*)You have received a new private message.M]From:L] Message:K]Replye"OEC "Restart game"y2/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPopupFrame * $VERSION 1.03 (8-3-2008 16:12) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen GUI popup window class. An instance of this class defines the frame for a * popup window. * **************************************************************************************************/ class NexgenPopupFrame extends UMenuFramedWindow; var float windowWidth; // Width of the popup window frame (in pixels). var float windowHeight; // Height of the popup window frame (in pixels). var NexgenClient client; // Nexgen client instance. var GeneralConfig gc; // General client configuration. var ServerConfig sc; // Server specific client configuration. var string serverID; // Identification code of the server where has been connected to. /*************************************************************************************************** * * $DESCRIPTION Makes sure the popup frame will be properly setup. * $OVERRIDE * **************************************************************************************************/ function created() { super.created(); windowTitle = "Nexgen Server Controller v" $ left(class'NexgenUtil'.default.version, 4); bLeaveOnScreen = true; bMoving = true; } /*************************************************************************************************** * * $DESCRIPTION Changes the contents of the popup window. * $PARAM popupClass The dialog class used for the contents of the popup frame. * $PARAM str1 Dialog specific content data. * $PARAM str2 Dialog specific content data. * $PARAM str3 Dialog specific content data. * $PARAM str4 Dialog specific content data. * $REQUIRE the specified popup class exists and is a subclass of NexgenPopupDialog * **************************************************************************************************/ function showPopup(string popupClass, optional string str1, optional string str2, optional string str3, optional string str4) { local NexgenPopupDialog dialog; local Class dialogClass; // Get the object class. if (instr(popupClass, ".") < 0) { popupClass = class'NexgenUtil'.default.packageName $ "." $ popupClass; } dialogClass = class(DynamicLoadObject(popupClass, class'Class')); // Set popup contents. dialog = NexgenPopupDialog(createWindow(dialogClass, 4, 16, winWidth - 4, winHeight - 16)); dialog.gc = gc; dialog.sc = sc; dialog.serverID = serverID; dialog.client = client; dialog.setContent(str1, str2, str3, str4); clientArea = dialog; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ W/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPopupDialog * $VERSION 1.06 (21-10-2007 15:28) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Parent class for all popup dialogs. * **************************************************************************************************/ class NexgenPopupDialog extends UWindowDialogClientWindow; var NexgenClient client; // Nexgen client instance. var GeneralConfig gc; // General client configuration. var ServerConfig sc; // Server specific client configuration. var string serverID; // Identification code of the server. var bool hasCloseButton; // Automatically add a close button to the dialog? var UWindowSmallButton closeButton; // Default close button. var int wrapLength; // Insert a new line after this many characters. // NOTE: This value is only an estimation for word wrapping. const minWrapRetain = 0.60; // Minimum size of the text before wrapping inside words // will occur. const wrapChars = " -,."; // Preferred characters where wrapping should occur. var bool autoCloseControlPanel; // Automatically close the control panel once the dialog is // shown? // Component positioning. All values are measured in pixels. var float nextButtonPos; // Next horizontal position of a button that is to be added. var float borderSize; // Distance between objects on the dialog and its borders. var float labelHeight; // Height of label objects. var float editControlHeight; // Height of edit control objects. var float editControlLabelVOffset; // Vertical offset of labels relative to their edit control. var float buttonPanelBorderSize; // Distance between the dialog borders and the button panel. var float buttonPanelHeight; // The height of the button panel. var float buttonHeight; // Height of buttons on this dialog. var float buttonWidth; // Default width of a button on this dialog. var float buttonSpace; // Space between two buttons. const newLineToken = "\\n"; // Token used to detect new lines in texts. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $ENSURE hasCloseButton ? closeButton != none : true * $OVERRIDE * **************************************************************************************************/ function created() { local UMenuLabelControl label; local UWindowRootWindow rootWin; local UWindowWindow win; super.created(); nextButtonPos = winWidth - buttonSpace - buttonPanelBorderSize; // Automatically add close button? if (hasCloseButton) { closeButton = addButton("Close"); } // Automatically close control panel? if (autoCloseControlPanel) { // Yes, iterate over each window. rootWin = WindowConsole(getPlayerOwner().player.console).root; if (rootWin != none) { win = rootWin.firstChildWindow; while (win != none) { // Window is a control panel? if (win.isA('NexgenMainFrame')) { // Yes, close it. win.close(); } // Continue with next window. win = win.nextSiblingWindow; } } } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * This function will only check if the close button has been clicked. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType){ super.notify(control, eventType); if (control == closeButton && eventType == DE_Click) { close(); } } /*************************************************************************************************** * * $DESCRIPTION Adds a new button to the dialog. The button will be added to the button panel of * the dialog and will be automatically positioned. * $PARAM text Text to display on the button. * $PARAM width Width of the button in pixels. * $RETURN The button that has been added to the button panel of this dialog. * $ENSURE result != none * **************************************************************************************************/ function UWindowSmallButton addButton(string text, optional int width) { local float cx, cy, cw, ch; local UWindowSmallButton newButton; if (width > 0.0) { cw = width; } else { cw = buttonWidth; } ch = buttonHeight; cx = nextButtonPos - cw; cy = winHeight - buttonPanelHeight - buttonPanelBorderSize + (buttonPanelHeight - ch) / 2.0 - 3; newButton = UWindowSmallButton(createControl(class'UWindowSmallButton', cx, cy, cw, ch)); newButton.setText(text); nextButtonPos -= cw + buttonSpace; return newButton; } /*************************************************************************************************** * * $DESCRIPTION Adds a new label component to the dialog. * $PARAM yPos Vertical position on the dialog where the text will be added. * $REQUIRE yPos >= 0 * $RETURN The label that has been added to the dialog. * $ENSURE result != none * **************************************************************************************************/ function UMenuLabelControl addLabel(out float yPos) { local float cx, cy, cw, ch; // Initialze position & dimensions. cx = borderSize; cy = yPos; cw = winWidth - 2.0 * borderSize; ch = labelHeight; yPos += ch; // Create label. return UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); } /*************************************************************************************************** * * $DESCRIPTION Adds a new label component to the dialog with a property description label in * front of the label. * $PARAM yPos Vertical position on the dialog where the text will be added. * $PARAM text Property name / description. * $PARAM labelWidth Width of the property name label (in pixels). * $REQUIRE yPos >= 0 && labelWidth > 0 * $RETURN The label that has been added to the dialog. * $ENSURE result != none * **************************************************************************************************/ function UMenuLabelControl addPropertyLabel(out float yPos, string text, float labelWidth) { local float cx, cy, cw, ch; local UMenuLabelControl label; cx = borderSize; cy = yPos; cw = labelWidth; ch = labelHeight; label = UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); label.setText(text); label.setFont(F_Bold); cx += labelWidth; cw = winWidth - 2.0 * borderSize - labelWidth; yPos += ch; return UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); } /*************************************************************************************************** * * $DESCRIPTION Adds a text to the dialog. This function detects new line tokens and writes the * after the token on a new line. Note that it doesn't support word wrapping. The * fontType and align properties will be maintained for all lines written. * $PARAM text The text to write to the dialog. * $PARAM yPos Vertical position on the dialog where the text will be added. * $PARAM fontType Type of font used to display the text. * $PARAM align Horizontal alignment of the text to add. * $PARAM wrapLen Maximum characters on a line. For word wrapping. * $REQUIRE yPos >= 0 && (fontType == F_Normal || fontType == F_Bold) && * (align == TA_Left || align == TA_Center || align == TA_Right) * **************************************************************************************************/ function addText(string text, out float yPos, int fontType, TextAlign align, optional int wrapLen) { local float cx, cy, cw, ch; local UMenuLabelControl label; local string textStr; local string lineStr; local int newLinePos; local string wrapStr; local int wrapPos; // Set proper wrapping length. if (wrapLen <= 0) { wrapLen = wrapLength; } // Initialze position & dimensions. cx = borderSize; cy = yPos; cw = winWidth - 2.0 * borderSize; ch = labelHeight; // Create a label for each line in the text string. textStr = text; while (textStr != "") { // Get text for the current line. newLinePos = instr(textStr, newLineToken); if (newLinePos < 0) { lineStr = textStr; textStr = ""; } else { lineStr = left(textStr, newLinePos); textStr = mid(textStr, newLinePos + len(newLineToken)); } // Word wrapping for the current line. while (lineStr != "") { wrapPos = getWrapPosition(lineStr, wrapLen); // Wrap current line. if (wrapPos < 0) { wrapStr = lineStr; lineStr = ""; } else { wrapStr = left(lineStr, wrapPos + 1); lineStr = mid(lineStr, wrapPos + 1); } // Create label. label = UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); label.setText(wrapStr); label.setFont(fontType); label.align = align; // Update vertical offset. cy += ch; } } // Update vertical offset. yPos = cy; } /*************************************************************************************************** * * $DESCRIPTION Gets the first position in the given string where a new line should be inserted * for word wrapping. * $PARAM text The string for which the first wrapping position is to be determined. * $PARAM maxChars Maximum characters allowed on a line. * $REQUIRE maxChars > 0 * $RETURN The first position in the specified string where word wrapping should occur, or * -1 if no wrapping is necessary. * $ENSURE result >= 0 && result < len(text) && result < maxChars || result == -1 * **************************************************************************************************/ function int getWrapPosition(string text, int maxChars) { local int index; // Find wrap position. if (len(text) < maxChars) { // No wrapping necessary. index = -1; } else { // Start at the back. index = maxChars - 1; while ((instr(wrapChars, mid(text, index, 1)) < 0) && (index >= minWrapRetain * maxChars)) { index--; } // Wrap at least after 1 character. index = max(1, index); } return index; } /*************************************************************************************************** * * $DESCRIPTION Adds an empty line in this dialog. No control object is created, only the value of * yPos will be increased. * $PARAM yPos Vertical position of the new line on this dialog. * $ENSURE new.yPos >= old.yPos * **************************************************************************************************/ function addNewLine(out float yPos) { yPos += labelHeight; } /*************************************************************************************************** * * $DESCRIPTION Adds a new edit control object to this dialog. * $PARAM yPos Vertical position of the edit control on this dialog. * $PARAM labelText Label to display before the edit control. * $PARAM labelWidth Width of the label to display * $REQUIRE yPos >= 0 && (labelText != "" ? labelWidth > 0 : true) * $RETURN The edit control object created for this dialog. * $ENSURE result != none * **************************************************************************************************/ function UWindowEditControl addEditControl(out float yPos, optional string labelText, optional float labelWidth) { local float cx, cy, cw, ch; local UMenuLabelControl label; local UWindowEditControl editControl; // Set control position & dimension. ch = editControlHeight; cx = borderSize; cy = yPos; if (labelText != "") { // Add a label before the edit control. cw = labelWidth; cy += editControlLabelVOffset; label = UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); label.setText(labelText); label.setFont(F_Bold); cx += labelWidth; cy = yPos; cw = winWidth - 2.0 * borderSize - labelWidth; } else { cw = winWidth - 2.0 * borderSize; } yPos = cy + ch; // Create & setup the edit control. editControl = UWindowEditControl(createControl(class'UWindowEditControl', cx, cy, cw, ch)); editControl.editBoxWidth = cw; editControl.setMaxLength(250); // Return the control. return editControl; } /*************************************************************************************************** * * $DESCRIPTION Paints the dialog area. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y){ local float cx, cy, cw, ch; super.paint(c, x, y); // Draw the button panel. cx = buttonPanelBorderSize; cy = winHeight - buttonPanelHeight - buttonPanelBorderSize; cw = winWidth - buttonPanelBorderSize * 2; ch = buttonPanelHeight; drawUpBevel(c, cx, cy, cw, ch, getLookAndFeelTexture()); } /*************************************************************************************************** * * $DESCRIPTION Closes the dialog. * $PARAM bByParent The close call was issued by the parent of the dialog. * $OVERRIDE * **************************************************************************************************/ function close(optional bool bByParent) { local UWindowRootWindow rootWin; local UWindowWindow win; local bool bWindowVisible; // Check if there is another visible window. rootWin = WindowConsole(getPlayerOwner().player.console).root; if (rootWin != none) { win = rootWin.firstChildWindow; while (!bWindowVisible && win != none) { // Current window visible? bWindowVisible = win != parentWindow && win.windowIsVisible() && win.bLeaveOnscreen; // Continue with next window. win = win.nextSiblingWindow; } } // Close the window. if (!bWindowVisible) { WindowConsole(getPlayerOwner().player.console).closeUWindow(); } super.close(bByParent); } /*************************************************************************************************** * * $DESCRIPTION Parses a boolean string value. * $PARAM str The string representation of a boolean value. * $RETURN True if the string equals "true" (case insensitive), false otherwise. * **************************************************************************************************/ function bool parseBool(string str) { return str ~= "true"; } /*************************************************************************************************** * * $DESCRIPTION Sets the contents for this dialog. * $PARAM str1 Dialog specific content data. * $PARAM str2 Dialog specific content data. * $PARAM str3 Dialog specific content data. * $PARAM str4 Dialog specific content data. * $ABSTRACT * **************************************************************************************************/ function setContent(optional string str1, optional string str2, optional string str3, optional string str4); /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ HC "End game"A/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlugin * $VERSION 1.16 (10-8-2008 11:05) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen controller plugin. This is the base class used for nexgen plugins. The * plugin is being setup from here. An instance of this class also receives events * emitted by the Nexgen Server Controller. * **************************************************************************************************/ class NexgenPlugin extends Info abstract; var NexgenController control; // The Nexgen Server Controller instance. var String pluginName; // Name of the plugin. var String pluginAuthor; // Who developed the plugin. var String pluginVersion; // Plugin version description. /*************************************************************************************************** * * $DESCRIPTION Starts up the plugin. First the Nexgen controller is located. Once it has been * found initialize() is called. If the initialization was successfull the plugin * will be registered at the server controller. If any error occurs during the load * process the plugin will be destroyed. * **************************************************************************************************/ function preBeginPlay() { // Locate Nexgen Controller. foreach allActors(class'NexgenController', control) { if (control != none) { break; } } // Quit on error. if (control == none) { warn("CRITICAL EXCEPTION, Nexgen controller not detected."); destroy(); return; } // Don't load on special mode. if (control.bSpecialMode) { destroy(); return; } // Initialize plugin. control.nscLog(control.lng.format(control.lng.loadingPluginMsg, pluginName, pluginVersion)); if (initialize()) { // Register plugin. if (!control.registerPlugin(self)) { // Failed to register, destroy instance. control.nscLog(control.lng.format(control.lng.regFailedMsg, string(self))); destroy(); } } else { // Initialization failed, destroy instance. control.nscLog(control.lng.format(control.lng.initFailedMsg, string(self))); destroy(); } // Make sure the checksums are up to date. control.sConf.updateDynamicChecksums(); control.sConf.staticChecksum = control.sConf.calcStaticChecksum(); } /*************************************************************************************************** * * $DESCRIPTION Initializes the plugin. Note that if this function returns false the plugin will * be destroyed and is not to be used anywhere. * $RETURN True if the initialization succeeded, false if it failed. * **************************************************************************************************/ function bool initialize() { // To implement in subclass. return true; } /*************************************************************************************************** * * $DESCRIPTION Called when a new client has been created. Use this function to setup the new * client with your own extensions (in order to support the plugin). * $PARAM client The client that was just created. * $REQUIRE client != none * **************************************************************************************************/ function clientCreated(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a client is attempting to login. This allows to plugin to accept or * reject the login request. If the function returns false the login request will be * rejected (player will be disconnected). Please make sure the reason parameter * is set in that case, as it will be written to the log. * $PARAM client Client that is requesting to login to the server. * $PARAM rejectType Reject type identification code. * $PARAM reason Message describing why the login is rejected. * $PARAM popupWindowClass Class name of the popup window that is to be shown at the client. * $PARAM popupArgs Optional arguments for the popup window. Note you may have to * explicitly reset them if you change the popupWindowClass. * $REQUIRE client != none * $RETURN True if the login request is accepted, false if it should be rejected. * $ENSURE result == false ? new.reason != "" : true * **************************************************************************************************/ function bool checkLogin(NexgenClient client, out name rejectType, out string reason, out string popupWindowClass, out string popupArgs[4]) { // To implement in subclass. return true; } /*************************************************************************************************** * * $DESCRIPTION Called whenever the login request of a player has been rejected and allows the * plugin to modify the behaviour. * $PARAM client The client that was denied access to the server. * $PARAM rejectType Reject type identification code. * $PARAM reason Reason why the player was rejected from the server. * $PARAM popupWindowClass Class name of the popup window that is to be shown at the client. * $PARAM popupArgs Optional arguments for the popup window. Note you may have to * explicitly reset them if you change the popupWindowClass. * $REQUIRE client != none * **************************************************************************************************/ function modifyLoginReject(NexgenClient client, out name rejectType, out string reason, out string popupWindowClass, out string popupArgs[4]) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called whenever a player has joined the game (after its login has been accepted). * $PARAM client The player that has joined the game. * $REQUIRE client != none * **************************************************************************************************/ function playerJoined(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called whenever a client has finished its initialisation process. During this * process things such as the remote control window are created. So only after the * client is fully initialized all functions can be safely called. * $PARAM client The client that has finished initializing. * $REQUIRE client != none * **************************************************************************************************/ function clientInitialized(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a player (re)spawns and allows us to modify the player. * $PARAM client The client of the player that was respawned. * $REQUIRE client != none * **************************************************************************************************/ function playerRespawned(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called if a player has left the server. * $PARAM client The player that has left the game. * $REQUIRE client != none * **************************************************************************************************/ function playerLeft(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Deals with a client that has switched to another team. * $PARAM client The client that has changed team. * $REQUIRE client != none * **************************************************************************************************/ function playerTeamChanged(NexgenClient client) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Deals with a client that has changed his or her name. * $PARAM client The client that has changed name. * $PARAM oldName The old name of the player. * $PARAM bWasForcedChanged Whether the name change was forced by the controller. * $REQUIRE client != none * **************************************************************************************************/ function playerNameChanged(NexgenClient client, string oldName, bool bWasForcedChanged) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when the game has started. * **************************************************************************************************/ function gameStarted() { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when the game has ended. * **************************************************************************************************/ function gameEnded() { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called to check if the specified message should be send to the given receiver. * $PARAM sender The actor that has send the message. * $PARAM receiver Pawn receiving the message. * $PARAM msg The message that is to be send. * $PARAM bBeep Whether or not to make a beep sound once received. * $PARAM type Type of the message that is to be send. * $RETURN True if the message should be send, false if it should be suppressed. * **************************************************************************************************/ function bool mutatorBroadcastMessage(Actor sender, Pawn receiver, out coerce string msg, optional bool bBeep, out optional name type) { // To implement in subclass. return true; } /*************************************************************************************************** * * $DESCRIPTION Called to check if the specified team message should be send to the given * receiver. * is called if a message is send to player. * $PARAM sender The actor that has send the message. * $PARAM receiver Pawn receiving the message. * $PARAM pri Player replication info of the sending player. * $PARAM s The message that is to be send. * $PARAM type Type of the message that is to be send. * $PARAM bBeep Whether or not to make a beep sound once received. * $RETURN True if the message should be send, false if it should be suppressed. * **************************************************************************************************/ function bool mutatorTeamMessage(Actor sender, Pawn receiver, PlayerReplicationInfo pri, coerce string s, name type, optional bool bBeep) { // To implement in subclass. return true; } /*************************************************************************************************** * * $DESCRIPTION Called to check if the given localized message should be send to the specified * receiver. * $PARAM sender The actor that has send the message. * $PARAM receiver Pawn receiving the message. * $PARAM message The class of the localized message that is to be send. * $PARAM switch Optional message switch argument. * $PARAM relatedPRI_1 PlayerReplicationInfo of a player that is related to the message. * $PARAM relatedPRI_2 PlayerReplicationInfo of a player that is related to the message. * $PARAM optionalObject Optional object used to construct the message string. * $REQUIRE message != none * $RETURN True if the message should be send, false if it should be suppressed. * **************************************************************************************************/ 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) { // To implement in subclass. return true; } /*************************************************************************************************** * * $DESCRIPTION Called when a player has send a mutate call to the server. * $PARAM mutateString Mutator specific string (indicates the action to perform). * $PARAM sender Player that has send the message. * **************************************************************************************************/ function mutate(string mutateString, PlayerPawn sender) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a player attempts to login to the server. Allows mutators to modify * some of the login parameters. * $PARAM spawnClass The PlayerPawn class to use for the player. * $PARAM portal Name of the portal where the player wishes to spawn. * $PARAM option Login option parameters. * **************************************************************************************************/ function modifyLogin(out class spawnClass, out string portal, out string options) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a player (re)spawns and allows us to modify the player. * $PARAM other The pawn/player that has (re)spawned. * $REQUIRE other != none * **************************************************************************************************/ function modifyPlayer(Pawn other) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a pawn takes damage. * $PARAM actualDamage The amount of damage sustained by the pawn. * $PARAM victim Pawn that has become victim of the damage. * $PARAM instigatedBy The pawn that has instigated the damage to the victim. * $PARAM hitLocation Location where the damage was dealt. * $PARAM momentum Momentum of the damage that has been dealt. * $PARAM damageType Type of damage dealt to the victim. * $REQUIRE victim != none * **************************************************************************************************/ function mutatorTakeDamage(out int actualDamage, Pawn victim, Pawn instigatedBy, out vector hitLocation, out vector momentum, name damageType) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when the server wants to check if a players death should be prevented. * $PARAM victim The pawn that was killed. * $PARAM killer The pawn that has killed the victim. * $PARAM damageType Type of damage dealt to the victim. * $PARAM hitLocation Location where the damage was dealt. * $RETURN True if the players death should be prevented, false if not. * **************************************************************************************************/ function bool preventDeath(Pawn victim, Pawn killer, name damageType, vector hitLocation) { // To implement in subclass. return false; } /*************************************************************************************************** * * $DESCRIPTION Called when a player was killed by another player. * $PARAM killer The pawn that killed the other pawn. Might be none. * $PARAM victim Pawn that was the victim. * **************************************************************************************************/ function scoreKill(Pawn killer, Pawn victim) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Notifies this plugin that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * **************************************************************************************************/ function configChanged(byte configType) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a general event has occurred in the system. * $PARAM type The type of event that has occurred. * $PARAM argument Optional arguments providing details about the event. * **************************************************************************************************/ function notifyEvent(string type, optional string arguments) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Plugin timer driven by the Nexgen controller. Ticks at a frequency of 1 Hz and is * independent of the game speed. * **************************************************************************************************/ function virtualTimer() { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when the server is about to perform a server travel. Note that the server * travel may fail to switch to the desired map. In that case the server will * continue running the current game or a second notifyBeforeLevelChange() call may * occur when trying to switch to another map. So be carefull what you do in this * function!!! * **************************************************************************************************/ function notifyBeforeLevelChange() { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Handles a potential command message. * $PARAM sender PlayerPawn that has send the message in question. * $PARAM msg Message send by the player, which could be a command. * $REQUIRE sender != none * $RETURN True if the specified message is a command, false if not. * **************************************************************************************************/ function bool handleMsgCommand(PlayerPawn sender, string msg) { return false; } h/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlayerListBox * $VERSION 1.03 (20-10-2007 14:45) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Player listbox GUI component. * **************************************************************************************************/ class NexgenPlayerListBox extends UWindowListBox; #exec TEXTURE IMPORT NAME=noCountry FILE=Resources\NoCountry.pcx GROUP="GFX" FLAGS=2 MIPS=Off var color baseColor; // Default color used to render textures in their original color. var color selectColor; // Background color of selected items. var color teamColor[6]; // Team colors used for drawing the items text. var bool bShowCountryFlag; // Indicates if little country flags should be displayed. /*************************************************************************************************** * * $DESCRIPTION Renders the specified listbox item. * $PARAM c The canvas object on which the rendering will be performed. * $PARAM item Item to render. * $PARAM x Horizontal offset on the canvas. * $PARAM y Vertical offset on the canvas. * $PARAM w Width of the item that is to be rendered. * $PARAM h Height of the item that is to be rendered. * $REQUIRE c != none && item != none * $OVERRIDE * **************************************************************************************************/ function drawItem(Canvas c, UWindowList item, float x, float y, float w, float h) { local int offsetX; local texture flagTex; local color backgroundColor; // Draw background. backgroundColor = getBackgroundColor(NexgenPlayerList(item)); if (backgroundColor != baseColor) { c.drawColor = backgroundColor; drawStretchedTexture(c, x, y, w, h - 1, Texture'WhiteTexture'); } // Draw country flag. offsetX = 2; if (bShowCountryFlag) { c.drawColor = baseColor; flagTex = NexgenPlayerList(item).getFlagTex(); if (flagTex == none) { flagTex = texture'noCountry'; } drawClippedTexture(c, x + offsetX, y + 1, flagTex); offsetX += 18; } // Draw text. c.drawColor = getDisplayColor(NexgenPlayerList(item)); c.font = getDisplayFont(NexgenPlayerList(item)); clipText(c, x + offsetX, y, getDisplayText(NexgenPlayerList(item))); } /*************************************************************************************************** * * $DESCRIPTION Called when an item was double clicked on. * $PARAM item The item which was double clicked. * $REQUIRE item != none * $OVERRIDE * **************************************************************************************************/ function doubleClickItem(UWindowListBoxItem item) { if (notifyWindow != none) { notifyWindow.notify(self, DE_DoubleClick); } } /*************************************************************************************************** * * $DESCRIPTION Returns the font in which the text should be displayed for a list item. * $PARAM item The item for which its display font has to be determined. * $REQUIRE item != none * $RETURN The font in which the text should be displayed for the specified item. * **************************************************************************************************/ function font getDisplayFont(NexgenPlayerList item) { return root.fonts[F_Bold]; } /*************************************************************************************************** * * $DESCRIPTION Returns the text displayed for a list item. * $PARAM item The item for which its display text has to be determined. * $REQUIRE item != none * $RETURN The text that should be displayed for the specified item in the listbox. * **************************************************************************************************/ function string getDisplayText(NexgenPlayerList item) { return "[" $ item.pTitle $ "] " $ item.pName; } /*************************************************************************************************** * * $DESCRIPTION Returns the color of the background in which the text should be displayed for a * list item. * $PARAM item The item for which its background color has to be determined. * $REQUIRE item != none * $RETURN The background color of the the specified item. * **************************************************************************************************/ function color getBackgroundColor(NexgenPlayerList item) { if (item.bSelected) { return selectColor; } else { return baseColor; } } /*************************************************************************************************** * * $DESCRIPTION Returns the color in which the text should be displayed for a list item. * $PARAM item The item for which its display color has to be determined. * $REQUIRE item != none * $RETURN The color in which the text should be displayed for the specified item. * **************************************************************************************************/ function color getDisplayColor(NexgenPlayerList item) { return teamColor[item.pTeam]; } /*************************************************************************************************** * * $DESCRIPTION Adds a new player to the list. * $RETURN The player item that was added to the list. * $ENSURE result != none * **************************************************************************************************/ function NexgenPlayerList addPlayer() { return NexgenPlayerList(items.append(listClass)); } /*************************************************************************************************** * * $DESCRIPTION Removes the player with the specified player code from the list. * $PARAM playerNum The player to remove. * $REQUIRE playerNum >= 0 * $ENSURE getPlayer(playerNum) == none * **************************************************************************************************/ function removePlayer(int playerNum) { local NexgenPlayerList item; // Search for player. for (item = NexgenPlayerList(items); item != none; item = NexgenPlayerList(item.next)) { if (item.pNum == playerNum) { item.remove(); } } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the player item with the specified player number. * $PARAM playerNum Indicates the player to return. * $REQUIRE playerNum >= 0 * $RETURN The player item that has the specified player number, or none if there is no * player item with the specified player number. * **************************************************************************************************/ function NexgenPlayerList getPlayer(int playerNum) { local NexgenPlayerList item; // Search for player. for (item = NexgenPlayerList(items); item != none; item = NexgenPlayerList(item.next)) { if (item.pNum == playerNum) { return item; } } // Player not found, return none. return none; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the player item with the specified player number. * $PARAM playerNum Indicates the player to return. * $REQUIRE playerNum >= 0 * $RETURN The player item that has the specified player number, or none if there is no * player item with the specified player number. * **************************************************************************************************/ function NexgenPlayerList getPlayerByID(string clientID) { local NexgenPlayerList item; // Search for player. for (item = NexgenPlayerList(items); item != none; item = NexgenPlayerList(item.next)) { if (item.pClientID ~= clientID) { return item; } } // Player not found, return none. return none; } /*************************************************************************************************** * * $DESCRIPTION Moves the selected item to the specified player listbox. * $PARAM target The player listbox where the currently selected item should be moved to. * $REQUIRE target != none * $ENSURE selectedItem == none * **************************************************************************************************/ function moveSelectedPlayerTo(NexgenPlayerListBox target) { local NexgenPlayerList item; if (selectedItem != none) { item = target.addPlayer(); NexgenPlayerList(selectedItem).copyTo(item); selectedItem.remove(); selectedItem = none; target.setSelectedItem(item); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ IC "Pause game"KC "(Dis)allow team switch"c?/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlayerList * $VERSION 1.04 (24-10-2007 20:25) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Player list item description class. Stores the basic player attributes, such as * name, team and clientID. * **************************************************************************************************/ class NexgenPlayerList extends UWindowListBoxItem; var int pNum; // Player num. var string pName; // Name used by the player. var string pTitle; // Title of the players account. var string pIPAddress; // IP Address. var string pClientID; // Client identification code. var string pCountry; // Country code based on the IP Address. var byte pTeam; // Team number. var texture flagTex; // Flag texture for the country. var bool bFlagTexSet; // Whether or not the flag texture has been set. const specTeam = 5; // Team used to indicate spectators. /*************************************************************************************************** * * $DESCRIPTION Sets the flag texture based on the current country code of the player. If the * country code is invalid the flag texture will be set to none. * $ENSURE bFlagTexSet * **************************************************************************************************/ function setFlagTex() { if (len(pCountry) == 2) { flagTex = texture(dynamicLoadObject(class'NexgenUtil'.default.countryFlagsPkg $ "." $ pCountry, class'Texture')); } else { flagTex = none; } bFlagTexSet = true; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the flag texture associated with the country code of the player. Note * that if the country code was changed setFlagTex() has to be called first in order * to update the texture. * $RETURN A texture of the country flag of the player, might be none if an invalid country * code is used. * **************************************************************************************************/ function texture getFlagTex() { if (!bFlagTexSet) { setFlagTex(); } return flagTex; } /*************************************************************************************************** * * $DESCRIPTION Copies the attributes of this player list item to the specified player list item. * $PARAM target The player list item where the attributes should be copied to. * $REQUIRE target != none * **************************************************************************************************/ function copyTo(NexgenPlayerList target) { target.pNum = self.pNum; target.pName = self.pName; target.pTitle = self.pTitle; target.pIPAddress = self.pIPAddress; target.pClientID = self.pClientID; target.pCountry = self.pCountry; target.pTeam = self.pTeam; target.flagTex = self.flagTex; target.bFlagTexSet = self.bFlagTexSet; } /*************************************************************************************************** * * $DESCRIPTION Checks whether this player is a spectator. * $RETURN True if this player is a spectator, false if not. * **************************************************************************************************/ function bool isSpectator() { return pTeam == specTeam; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ LC "Reconnect as spectator"OC "Reconnect as player"su/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlayerData * $VERSION 1.00 (24-11-2007 15:28) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Saved player data support class. An instance of this class can be used to store * attributes of a leaving player, which can later be retrieved once the player * reconnects. * **************************************************************************************************/ class NexgenPlayerData extends info; struct AttributeEntry { // Attribute data structure. var string name; // Name of the attribute. var string value; // Value of the attribute. }; var private AttributeEntry attributes[64]; // Attributes for this player. var string clientID; // ClientID of the player. var NexgenPlayerData next; // Next player data instance. /*************************************************************************************************** * * $DESCRIPTION Removes all attributes stored in this NexgenPlayerData instance. * **************************************************************************************************/ function clearData() { local int index; // Clear entries. while (index < arrayCount(attributes)) { attributes[index].name = ""; attributes[index].value = ""; index++; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the value of the specified attribute. * $PARAM name Name of the attribute that is to be retrieved. * $PARAM defaultValue Value to return if the attribute couldn't been found. * $RETURN The value of the specified attribute, or the default value if the attribute * doesn't exist. * **************************************************************************************************/ function string get(string name, optional string defaultValue) { local int index; local bool bFound; // Locate index of attribute. while (!bFound && index < arrayCount(attributes)) { if (attributes[index].name ~= name) { bFound = true; } else { index++; } } // Return attribute value, or the default value if the attribute wasn't found. if (bFound) { return attributes[index].value; } else { return defaultValue; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the boolean value of the specified attribute. * $PARAM name Name of the attribute that is to be retrieved. * $PARAM defaultValue Value to return if the attribute couldn't been found. * $RETURN The value of the specified attribute, or the default value if the attribute * doesn't exist. * **************************************************************************************************/ function bool getBool(string name, optional bool defaultValue) { local string value; value = class'NexgenUtil'.static.trim(get(name)); if (value == "") { return defaultValue; } else { return value ~= string(true); } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the byte value of the specified attribute. * $PARAM name Name of the attribute that is to be retrieved. * $PARAM defaultValue Value to return if the attribute couldn't been found. * $RETURN The value of the specified attribute, or the default value if the attribute * doesn't exist. * **************************************************************************************************/ function byte getByte(string name, optional byte defaultValue) { local string value; value = class'NexgenUtil'.static.trim(get(name)); if (value == "") { return defaultValue; } else { return byte(value); } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the integer value of the specified attribute. * $PARAM name Name of the attribute that is to be retrieved. * $PARAM defaultValue Value to return if the attribute couldn't been found. * $RETURN The value of the specified attribute, or the default value if the attribute * doesn't exist. * **************************************************************************************************/ function int getInt(string name, optional int defaultValue) { local string value; value = class'NexgenUtil'.static.trim(get(name)); if (value == "") { return defaultValue; } else { return int(value); } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the floating point value of the specified attribute. * $PARAM name Name of the attribute that is to be retrieved. * $PARAM defaultValue Value to return if the attribute couldn't been found. * $RETURN The value of the specified attribute, or the default value if the attribute * doesn't exist. * **************************************************************************************************/ function float getFloat(string name, optional float defaultValue) { local string value; value = class'NexgenUtil'.static.trim(get(name)); if (value == "") { return defaultValue; } else { return float(value); } } /*************************************************************************************************** * * $DESCRIPTION Updates the specified attribute with the given value. * $PARAM name Name of the attribute that is to be stored. * $PARAM value (New) Value of the attribute to store. * $REQUIRE name != "" * $RETURN True if the attribute was updated/save, false if not. * $ENSURE result == true ? new.get(name) == value : true * **************************************************************************************************/ function bool set(string name, coerce string value) { local int index; local bool bFound; // Check if attribute already exists. while (!bFound && index < arrayCount(attributes)) { if (attributes[index].name ~= name) { bFound = true; } else { index++; } } // It doesn't, search for an empty entry. if (!bFound) { index = 0; while (!bFound && index < arrayCount(attributes)) { if (attributes[index].name == "") { bFound = true; } else { index++; } } } // Save attribute. if (bFound) { attributes[index].name = name; attributes[index].value = value; } return bFound; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ PC@$jXga(/^^^~^:-Fa/!|\@$l E$FRK QC "Send to URL"WCw>dH.GV\l Jj\l _ RC "Switch to %1"SC ""ZC "Delete"a/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlayerACListItem * $VERSION 1.01 (21-10-2007 11:24) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Online user acccount list item description class. * **************************************************************************************************/ class NexgenPlayerACListItem extends NexgenPlayerList; var bool bHasAccount; var byte accountNum; /*************************************************************************************************** * * $DESCRIPTION Compares two UWindowList items. * $PARAM a First item to compare. * $PARAM b Second item to compare. * $REQUIRE a != none && b != none * $RETURNS -1 If the first item is 'smaller' then the second item, otherwise 1 is returned. * $OVERRIDE * **************************************************************************************************/ function int compare(UWindowList a, UWindowList b) { local string pTitleA, pTitleB; local string pNameA, pNameB; pTitleA = caps(NexgenPlayerACListItem(a).pTitle); pTitleB = caps(NexgenPlayerACListItem(b).pTitle); pNameA = caps(NexgenPlayerACListItem(a).pName); pNameB = caps(NexgenPlayerACListItem(b).pName); if (pTitleA < pTitleB) { return -1; } else if (pTitleA == pTitleB) { if (pNameA < pNameB) { return -1; } else if (pNameA == pNameB) { return 0; } else { return 1; } } else { return 1; } } g%/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPlayerACListBox * $VERSION 1.00 (20-10-2007 15:47) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Online player account listbox GUI component. * **************************************************************************************************/ class NexgenPlayerACListBox extends NexgenPlayerListBox; var color accountColor; var color selectedAccountColor; /*************************************************************************************************** * * $DESCRIPTION Returns the font in which the text should be displayed for a list item. * $PARAM item The item for which its display font has to be determined. * $REQUIRE item != none * $RETURN The font in which the text should be displayed for the specified item. * $OVERRIDE * **************************************************************************************************/ function font getDisplayFont(NexgenPlayerList item) { if (NexgenPlayerACListItem(item).bHasAccount) { return root.fonts[F_Bold]; } else { return root.fonts[F_Normal]; } } /*************************************************************************************************** * * $DESCRIPTION Returns the color of the background in which the text should be displayed for a * list item. * $PARAM item The item for which its background color has to be determined. * $REQUIRE item != none * $RETURN The background color of the the specified item. * $OVERRIDE * **************************************************************************************************/ function color getBackgroundColor(NexgenPlayerList item) { if (item.bSelected) { if (NexgenPlayerACListItem(item).bHasAccount) { return selectedAccountColor; } else { return selectColor; } } else { return baseColor; } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ {M/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPasswordDialog * $VERSION 1.01 (23-12-2006 14:15) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player has entered an invalid password. * **************************************************************************************************/ class NexgenPasswordDialog extends NexgenPopupDialog; var UWindowSmallButton reconnectButton; // Reconnect button component. var UWindowSmallButton spectatorButton; // Spectator button component. var UWindowEditControl passwordInput; // Password input field component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. var localized string passwordText; // Label to display before the password field. var localized string reconnectText; // Text to display on the reconnect button. var localized string spectatorText; // Text to display on the spectator button. const SSTR_ServerPassword = "Password"; // Server password setting string. const SSTR_OverrideClass = "OverrideClass"; // Override class setting string. const reconnectCommand = "Reconnect"; // Console command for reconnecting. const spectatorClass = "Botpack.CHSpectator"; // Override class to use for spectators. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $ENSURE reconnectButton != none && spectatorButton != none && passwordInput != none * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); addNewLine(cy); passwordInput = addEditControl(cy, passwordText, 64.0); spectatorButton = addButton(spectatorText, 64.0); reconnectButton = addButton(reconnectText, 64.0); // Set component properties. passwordInput.setMaxLength(24); } /*************************************************************************************************** * * $DESCRIPTION Sets the contents for this dialog. * $PARAM allowSpecs Indicates if reconnecting as spectator should be allowed. * $PARAM str2 Not used. * $PARAM str3 Not used. * $PARAM str4 Not used. * $OVERRIDE * **************************************************************************************************/ function setContent(optional string allowSpecs, optional string str2, optional string str3, optional string str4) { // sc.get(serverID, NexgenClient.SSTR_ServerPassword); // Bah, doesn't work! passwordInput.setValue(sc.get(serverID, SSTR_ServerPassword)); spectatorButton.bDisabled = !parseBool(allowSpecs); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the reconnect or spectator buttons have been clicked and deals with it * accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType){ super.notify(control, eventType); // Reconnect button. if (control == reconnectButton && eventType == DE_Click) { // Update password. sc.visitServer(serverID); sc.set(serverID, SSTR_ServerPassword, passwordInput.getValue()); sc.saveConfig(); // Reconnect. getplayerowner().consoleCommand(reconnectCommand); close(); } // Spectator button. if (control == spectatorButton && eventType == DE_Click && !spectatorButton.bDisabled) { getplayerowner().updateURL(SSTR_OverrideClass, spectatorClass, true); getplayerowner().consoleCommand(reconnectCommand); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ pCt,bECw!*:!4!&KMutate NSC START o\C "Add"XC]C "Update"_C "Offline"`C "Online"aC "User title"dC "Account type"R fG "User name"fC "Move up"gC "Delete account type"iC "Add account type"jC "Password"kC "Account title"lC "Account name"qC "%1: %2"CVCc@b 2nC֒CnMMtM> Y7XÔ> Y> YtM7XÑt V]$#Failed to login: invalid password.]DThis server is password protected. You have either entered an invalid password or no password at all. Please enter the password for this server and click reconnect to login with the new password.]] Password:i] Reconnectd] SpectatorJ/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPanelContainer * $VERSION 1.03 (11-3-2008 21:31) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen control panel page container. * **************************************************************************************************/ class NexgenPanelContainer extends NexgenPanel; var UWindowPageControl pages; // Page control for panels added on this container. /*************************************************************************************************** * * $DESCRIPTION Creates the layout for this panel. * $OVERRIDE * **************************************************************************************************/ function created() { super.created(); pages = UWindowPageControl(createWindow(class'UWindowPageControl', 0, 0, winWidth - 2, winHeight - 3)); } /*************************************************************************************************** * * $DESCRIPTION Retrieves the panel with the specified name. * $PARAM panelName Name of the panel that is to be returned. * $REQUIRE panelName != "" * $RETURN The panel that was requested or none if the panel wasn't found. * **************************************************************************************************/ function NexgenPanel getPanel(string panelName) { local UWindowPageControlPage pageControl; local NexgenPanel panel; local bool bFound; // Search for panel. pageControl = pages.firstPage(); while (!bFound && pageControl != none) { panel = NexgenPanel(pageControl.page); // Is this the one we are looking for? if (panel != none) { if (panel.panelIdentifier ~= panelName) { // Yeah, stop looking and return result. bFound = true; } else if (panel.isA('NexgenPanelContainer')) { // No, but it is a panel container so it might contain the one we're looking for. panel = NexgenPanelContainer(panel).getPanel(panelName); bFound = panel != none; } } // Continue with next page if not found yet. if (!bFound) { pageControl = pageControl.nextPage(); } } // Return result. if (bFound) { return panel; } else { return none; } } /*************************************************************************************************** * * $DESCRIPTION Adds a new NexgenPanel to the container or one of its subcontainers. To specify * a specific parent use the parent parameter to indicate the path, e.g. * "plugin,settings". If an invalid path is specified the panel won't be created. * $PARAM title Text to display in the tab header. * $PARAM panelClass Type of NexgenPanel to add/create. * $PARAM identifier Identifier to assign to the new panel. * $PARAM parent Path where to the parent of the new panel. * $REQUIRE panelClass != none * $RETURN The panel that was created and added to the container, or none if an invalid path * to the parent container was specified. * **************************************************************************************************/ function NexgenPanel addPanel(string title, class panelClass, optional string identifier, optional string parent) { local UWindowPageControlPage pageControl; local NexgenPanel newPanel; local string parentPanel; local string subPanels; local bool bFound; local NexgenPanelContainer container; // Add to subpanel? if (parent != "") { // Get local parent name. if (instr(parent, separator) > 0) { parentPanel = left(parent, instr(parent, separator)); subPanels = mid(parent, instr(parent, separator) + 1); } else { parentPanel = parent; } // Locate local parent. pageControl = pages.firstPage(); while (!bFound && pageControl != none) { container = NexgenPanelContainer(pageControl.page); if (container != none && container.panelIdentifier ~= parentPanel) { bFound = true; } else { pageControl = pageControl.nextPage(); } } // Delegate action. if (bFound) { // NOTE: Recursion can be avoided here, but the performance gain is insignificant. newPanel = container.addPanel(title, panelClass, identifier, subPanels); } } else { // Create panel. pageControl = pages.addPage(title, panelClass); if (pageControl != none) { newPanel = NexgenPanel(pageControl.page); if (identifier != "") { newPanel.panelIdentifier = identifier; } newPanel.client = self.client; newPanel.setContent(); } } // Return created panel. return newPanel; } /*************************************************************************************************** * * $DESCRIPTION Selects the panel with the specified name. * $PARAM panelName The name of the panel that is to be selected. * $RETURN True if the panel was selected, false if it wasn't found. * **************************************************************************************************/ function bool selectPanel(string panelName) { local UWindowPageControlPage pageControl; local NexgenPanel panel; local bool bFound; pageControl = pages.firstPage(); while (!bFound && pageControl != none) { panel = NexgenPanel(pageControl.page); // Check panel. if (panel.panelIdentifier ~= panelName) { // Panel found, select it. bFound = true; } else if (panel.isA('NexgenPanelContainer')) { // No, but page is a NexgenPanelContainer, so it may include the panel. bFound = NexgenPanelContainer(panel).selectPanel(panelName); } // Panel found? if (bFound) { // Panel found, select it. pages.gotoTab(pageControl, true); } else { // No, continue with next page. pageControl = pageControl.nextPage(); } } return bFound; } /*************************************************************************************************** * * $DESCRIPTION Notifies the sub panels on this panel that the server configuration has been * updated. * $PARAM configType Type of settings that have been changed. * $OVERRIDE * **************************************************************************************************/ function configChanged(byte configType) { local UWindowPageControlPage pageControl; for (pageControl = pages.firstPage(); pageControl != none; pageControl = pageControl.nextPage()) { if (NexgenPanel(pageControl.page) != none) { NexgenPanel(pageControl.page).configChanged(configType); } } } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * $OVERRIDE * **************************************************************************************************/ function gameInfoChanged(byte infoType) { local UWindowPageControlPage pageControl; for (pageControl = pages.firstPage(); pageControl != none; pageControl = pageControl.nextPage()) { if (NexgenPanel(pageControl.page) != none) { NexgenPanel(pageControl.page).gameInfoChanged(infoType); } } } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * $OVERRIDE * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { local UWindowPageControlPage pageControl; for (pageControl = pages.firstPage(); pageControl != none; pageControl = pageControl.nextPage()) { if (NexgenPanel(pageControl.page) != none) { NexgenPanel(pageControl.page).playerEvent(playerNum, eventType, args); } } } /*************************************************************************************************** * * $DESCRIPTION Called when a general event has occurred in the system. * $PARAM type The type of event that has occurred. * $PARAM argument Optional arguments providing details about the event. * $OVERRIDE * **************************************************************************************************/ function notifyEvent(string type, optional string arguments) { local UWindowPageControlPage pageControl; for (pageControl = pages.firstPage(); pageControl != none; pageControl = pageControl.nextPage()) { if (NexgenPanel(pageControl.page) != none) { NexgenPanel(pageControl.page).notifyEvent(type, arguments); } } } wCbCs\tDr**:%:%'E Vk-N  o,{o v $(o v~R a|E ~-N 'R   R -R ~R  P%:%.~R  S%:%hob-R  rC "Send to %1: %2"sC "%1 has been unblocked."tC "%1 has been blocked."uC "History"yC "Send windowed PM"et/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenPanel * $VERSION 1.08 (11-3-2008 21:30) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen control panel page. * **************************************************************************************************/ class NexgenPanel extends NexgenContentPanel; var string panelIdentifier; // Unique panel identifier. var NexgenClient client; // Nexgen client instance. var float panelHeight; // Desired panel height. /*************************************************************************************************** * * $DESCRIPTION Sets the contents for this panel. This function is automatically called after * the panel has been successfully created and all variables have been set. This * applies in particular for the client variable which is often required to setup the * contents of the panel. * **************************************************************************************************/ function setContent() { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the server configuration has been updated. * $PARAM configType Type of settings that have been changed. * **************************************************************************************************/ function configChanged(byte configType) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Notifies this panel that the extended game info has been updated. * $PARAM infoType Type of information that has been changed. * **************************************************************************************************/ function gameInfoChanged(byte infoType) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Notifies the client of a player event. Additional arguments to the event should be * combined into one string which then can be send along with the playerEvent call. * $PARAM playerNum Player identification number. * $PARAM eventType Type of event that has occurred. * $PARAM args Optional arguments. * $REQUIRE playerNum >= 0 * **************************************************************************************************/ function playerEvent(int playerNum, string eventType, optional string args) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Called when a general event has occurred in the system. * $PARAM type The type of event that has occurred. * $PARAM argument Optional arguments providing details about the event. * **************************************************************************************************/ function notifyEvent(string type, optional string arguments) { // To implement in subclass. } /*************************************************************************************************** * * $DESCRIPTION Adds a new player to the specified player listbox. * $PARAM list The player listbox where the new player should be added to. * $PARAM playerNum The player code of the new player to add. * $PARAM args Player joined event arguments. * $REQUIRE list != none && playerNum >= 0 * $RETURN The player item that was added to the list. * $ENSURE result != none * **************************************************************************************************/ function NexgenPlayerList addPlayerToList(NexgenPlayerListBox list, int playerNum, string args) { local NexgenPlayerList playerItem; playerItem = list.addPlayer(); playerItem.pNum = playerNum; playerItem.pName = class'NexgenUtil'.static.getProperty(args, client.PA_Name); playerItem.pTitle = class'NexgenUtil'.static.getProperty(args, client.PA_Title); playerItem.pIPAddress = class'NexgenUtil'.static.getProperty(args, client.PA_IPAddress); playerItem.pClientID = class'NexgenUtil'.static.getProperty(args, client.PA_ClientID); playerItem.pCountry = class'NexgenUtil'.static.getProperty(args, client.PA_Country); playerItem.pTeam = byte(class'NexgenUtil'.static.getProperty(args, client.PA_Team)); return playerItem; } /*************************************************************************************************** * * $DESCRIPTION Updates the attributes of the specified player in the given player listbox. * $PARAM list The player listbox where the player info should be updated. * $PARAM playerNum The player code of the player to update. * $PARAM args Player attribute change event arguments. * $REQUIRE list != none && playerNum >= 0 * $RETURN The player item that was updated in the list. Might be none if the list didn't * contain the player with the specified player code. * **************************************************************************************************/ function NexgenPlayerList updatePlayerInfo(NexgenPlayerListBox list, int playerNum, string args) { local NexgenPlayerList playerItem; local string value; playerItem = list.getPlayer(playerNum); if (playerItem != none) { // Name attribute. value = class'NexgenUtil'.static.getProperty(args, client.PA_Name); if (value != "") { playerItem.pName = value; } // Title attribute. value = class'NexgenUtil'.static.getProperty(args, client.PA_Title); if (value != "") { playerItem.pTitle = value; } // Country attribute. value = class'NexgenUtil'.static.getProperty(args, client.PA_Country); if (value != "") { playerItem.pCountry = value; playerItem.setFlagTex(); } // Team attribute. value = class'NexgenUtil'.static.getProperty(args, client.PA_Team); if (value != "") { playerItem.pTeam = byte(value); } } return playerItem; } /*************************************************************************************************** * * $DESCRIPTION Adds a new component container panel to the current region. * $PARAM bgType Panel border/background style. * $REQUIRE 0 <= currRegion && currRegion < regionCount * $RETURN The raised that has been added to the panel. * $ENSURE result != none * **************************************************************************************************/ function NexgenPanel addSubPanel(class panelClass, optional EPanelBackType bgType) { local NexgenPanel panel; panel = NexgenPanel(addComponent(panelClass)); panel.panelBGType = bgType; panel.parentCP = self; panel.client = self.client; panel.setContent(); return panel; } xCi \uJh1zSi ::$ w* -y :% -Z-Z't:%-Z-Z(- -H [S-H 'p-H --H (pp-H : A% -zS[< A-z'E:!4!,a(b #???,b _ ?,h ?,w-F Ez_ w.-h i h ?% t%ww%D?& th &_ i _ ?% p%w&w%D?& p_ fw% w, w_  i e@ 'w%MNexgenIdleKickedDialogKDisconnectw%_ ?,h ?,wf::$n?%Rg?(w* s%:!4!,nv $ni n?%v $v =:Cn&a ?%a i a ?%{ ${ =:Ca &fI?%Ii UI?%i$fi=:CI& Cc g9?::$-{ - {F w* w *w.* wG*] VG-{ (w-{  SAa(a-{ -y -f w!*!d% w* {f -I -t'S?, c %-t c ,wc I*-tc Inc X-t-y (a(`-^ U-y  n?%:!4!,nSn?%Sn@ -q-SAt|22AutoSSNormalGamefalsetrue?|22AutoSSMatchtruetrue -GA -q'::$1-^  r*a(a-^  SAa(R2Login timeout forRU zC "Send normal PM"{C "Message"|C "Block all private messages"}C "Block / Unblock"AD "Blocked"n/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenNullMessage * $VERSION 1.00 (6-4-2008 11:59) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Special placeholder message. This localized message is used by the * NexgenHUDWrapper class to clear the local message queue in the original HUD. * **************************************************************************************************/ class NexgenNullMessage extends LocalMessagePlus; /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ @D];QL-2a v a  a a?@'Oa  GDc|7Y.::$.a?@'W::$-{ '-y 'w BD "Players"CD) "Auto screenshot at the end of matches"DD. "Auto screenshot at the end of normal games"ED "Miscellaneous settings"FD/ "Play a sound when a private message arrives"ID, "Show player location on teamsay messages"HD 10ND 10JD! "Enable message 'flash' effect"KD "Enable Nexgen message HUD"LD "User interface"MD "Pause game"PD "Open control panel"OD 30.0SD 2.0\D "Open map vote"o@v  "0123456789ABCDEF"TD 4.0XD 1.25uVXu22u ClientKeyK u22u ClientIDzXX wK  U DXu2Eu ClientKeyXu2Eu ClientIDK u2b{ U DXK X wK  U DXu2Eu ClientKeyXu2Eu ClientIDK u2bluv '2uFu PasswordQ{l #[w u Passwordl $[w u ClientKeyX  w0/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenNoPlayRightDialog * $VERSION 1.00 (23-12-2006 19:18) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player hasn't got the right to play on the server. * **************************************************************************************************/ class NexgenNoPlayRightDialog extends NexgenPopupDialog; var UWindowSmallButton spectatorButton; // Spectator button component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. var localized string spectatorText; // Text to display on the spectator button. const SSTR_OverrideClass = "OverrideClass"; // Override class setting string. const spectatorClass = "Botpack.CHSpectator"; // Override class to use for spectators. const reconnectCommand = "Reconnect"; // Console command for reconnecting. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $ENSURE spectatorButton != none * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); addNewLine(cy); spectatorButton = addButton(spectatorText, 64.0); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the spectator button has been clicked and deals with it accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType){ super.notify(control, eventType); // Spectator button. if (control == spectatorButton && eventType == DE_Click) { getplayerowner().updateURL(SSTR_OverrideClass, spectatorClass, true); getplayerowner().consoleCommand(reconnectCommand); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ CVDM@d 2WDfCnŔ> Y> Y V].-Failed to login: you have no playing rights.]DThis server has playing rights disabled by default. You can't play on this server unless an administrator has explicitly allowed you to play. Meanwhile you can still be a spectator on the server.d] SpectatorZD 0.50L[/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenMainPanelBar * $VERSION 1.02 (4-3-2007 23:06) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen control panel root toolbar. * **************************************************************************************************/ class NexgenMainPanelBar extends UWindowDialogClientWindow; var UWindowSmallButton closeButton; // Button to close the control panel. var UWindowSmallButton sendButton; // Button to send the message entered in the msgInp EditBox. var UWindowEditControl msgInp; // Input field for the chat message. var localized string closeButtonText; // Text displayed on the close button. var localized string sendButtonText; // Text displayed on the send button. var localized string msgLabelText; // Label text displayed in front of the input field. const borderDist = 4.0; // Minimum distance between a component and vertical edges. const separatorDist = 4.0; // Extra distance between components for separation. const componentDist = 4.0; // Horizontal distance between components (in pixels). const buttonWidth = 64.0; // Width of button components. const buttonHeight = 16.0; // Height of button components. const labelWidth = 48.0; // Width of label components. const labelHeight = 12.0; // Height of label components. const editCtrlHeight = 16.0; // Height of edit control components. const sayCommand = "say"; // Chat message console command. /*************************************************************************************************** * * $DESCRIPTION Creates the layout for this GUI component. * $OVERRIDE * **************************************************************************************************/ function created() { local float cx, cy, cw, ch; local UMenuLabelControl label; super.created(); // Add close button. cw = buttonWidth; ch = buttonHeight; cx = winWidth - cw - borderDist; cy = (winHeight - ch) / 2.0; closeButton = UWindowSmallButton(createControl(class'UWindowSmallButton', cx, cy, cw, ch)); closeButton.setText(closeButtonText); // Add send button. cx = cx - cw - componentDist - separatorDist; sendButton = UWindowSmallButton(createControl(class'UWindowSmallButton', cx, cy, cw, ch)); sendButton.setText(sendButtonText); // Add message input field. ch = editCtrlHeight; cw = cx - borderDist - labelWidth - 2 * componentDist; cx = borderDist + labelWidth + componentDist; cy = (winHeight - ch) / 2.0; msgInp = UWindowEditControl(createControl(class'UWindowEditControl', cx, cy, cw, ch)); msgInp.editBoxWidth = cw; msgInp.setMaxLength(250); msgInp.setHistory(true); // Add 'say' label. cw = labelWidth; ch = labelHeight; cx = borderDist; cy = (winHeight - ch) / 2.0; label = UMenuLabelControl(createControl(class'UMenuLabelControl', cx, cy, cw, ch)); label.setText(msgLabelText); label.align = TA_Center; } /*************************************************************************************************** * * $DESCRIPTION Paints the dialog area. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y){ super.paint(c, x, y); drawUpBevel(c, 0, 0, winWidth, winHeight, getLookAndFeelTexture()); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType){ super.notify(control, eventType); if (control == closeButton && eventType == DE_Click) { UWindowFramedWindow(getParent(class'UWindowFramedWindow')).close(); } if (control == sendButton && eventType == DE_Click) { msgInp.editBox.keyDown(getPlayerOwner().EInputKey.IK_Enter, 0.0, 0.0); } if (control == msgInp && eventType == DE_EnterPressed) { sendMessage(); } } /*************************************************************************************************** * * $DESCRIPTION Sends the message in the msgInp EditBox to the server and clears the value of the * editBox. No message will be send if the message is an empty string. * $ENSURE msgInp.getValue() == "" * **************************************************************************************************/ function sendMessage() { local string msg; // Get chat message. msg = msgInp.getValue(); // Send message & reset edit box value. if (msg != "") { msgInp.setValue(""); getPlayerOwner().consoleCommand(sayCommand @ msg); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ _D 15UD^WFR -S  b^\-S k (H^l ^ ClientKey-S  gk-S -S z U Dk^\-S   bD "Suicide"S _,/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenMainPanel * $VERSION 1.01 (3-3-2007 17:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen control panel root. * **************************************************************************************************/ class NexgenMainPanel extends NexgenPanelContainer; const barHeight = 22; /*************************************************************************************************** * * $DESCRIPTION Creates the layout for this panel. * $OVERRIDE * **************************************************************************************************/ function created() { super(NexgenPanel).created(); pages = UWindowPageControl(createWindow(class'UWindowPageControl', 0, 0, winWidth, winHeight - barHeight - 3)); createWindow(class'NexgenMainPanelBar', 0, winHeight - barHeight - 3, winWidth, barHeight); } /*************************************************************************************************** * * $DESCRIPTION Notifies the window that a new level is going to be loaded. * $OVERRIDE * **************************************************************************************************/ function notifyBeforeLevelChange() { super.notifyBeforeLevelChange(); close(); } /*************************************************************************************************** * * $DESCRIPTION Closes the dialog. * $PARAM bByParent The close call was issued by the parent of the dialog. * $OVERRIDE * **************************************************************************************************/ function close(optional bool bByParent) { local UWindowRootWindow rootWin; local UWindowWindow win; local bool bWindowVisible; // Check if there is another visible window. rootWin = WindowConsole(getPlayerOwner().player.console).root; if (rootWin != none) { win = rootWin.firstChildWindow; while (!bWindowVisible && win != none) { // Current window visible? bWindowVisible = win != parentWindow && win.windowIsVisible() && win.bLeaveOnscreen; // Continue with next window. win = win.nextSiblingWindow; } } // Close the window. if (!bWindowVisible) { WindowConsole(getPlayerOwner().player.console).closeUWindow(); } super.close(bByParent); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ aD 4M/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenMainFrame * $VERSION 1.00 (28-1-2007 18:28) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen GUI main window class. Defines the frame for the Nexgen main window. * **************************************************************************************************/ class NexgenMainFrame extends UMenuFramedWindow; var float windowWidth; // Width of the main window frame (in pixels). var float windowHeight; // Height of the main window frame (in pixels). var NexgenMainPanel mainPanel; // Control panel root. /*************************************************************************************************** * * $DESCRIPTION Makes sure the main frame is properly setup. * $ENSURE mainPanel != none * $OVERRIDE * **************************************************************************************************/ function created() { super.created(); windowTitle = "Nexgen Server Controller v" $ left(class'NexgenUtil'.default.version, 4); clientArea = createWindow(class'NexgenMainPanel', 4, 16, winWidth - 4, winHeight - 16); mainPanel = NexgenMainPanel(clientArea); bLeaveOnScreen = true; bMoving = true; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ nD 192dD "Switch to yellow"B_/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenLogFile * $VERSION 1.01 (17-6-2008 13:53) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Class that handles the writing of Nexgen logs to a file. * **************************************************************************************************/ class NexgenLogFile extends NexgenTextFile; var NexgenController control; // The Nexgen controller. var NexgenLang lng; // The language support instance. var string timeStampFormat; // Time stamp format used. const defaultLogFileExtension = "log"; // The default log file extension, if none is specified. const tempLogFileExtension = "tmp"; // File extension for temp files. /*************************************************************************************************** * * $DESCRIPTION Initializes the log file. Start the log based on the settings contained by the * NexgenConfig object in the Nexgen server controller (control.sConf). If the log * file was successfully created bIsOpen will be set to true. * $REQUIRE owner != none && owner.isA('NexgenController') * **************************************************************************************************/ function preBeginPlay() { local string logFilePath; local string logFileName; local string logFileExtension; local string tempLogFile; local string logFile; local bool bSuccess; super.preBeginPlay(); // Get controller. control = NexgenController(owner); lng = control.lng; // Construct log file name. logFileName = class'NexgenUtil'.static.autoFormat(control, control.sConf.logFileNameFormat); logFileName = class'NexgenUtil'.static.validateFileName(logFileName); if (logFileName != "") { logFileExtension = class'NexgenUtil'.static.trim(control.sConf.logFileExtension); if (left(logFileExtension, 1) == ".") { logFileExtension = mid(logFileExtension, 1); } if (logFileExtension == "") { logFileExtension = defaultLogFileExtension; } logFilePath = class'NexgenUtil'.static.trim(control.sConf.logPath); if (logFilePath != "") { logFilePath = class'NexgenUtil'.static.replace(logFilePath, "\\", "/"); if (right(logFilePath, 1) == "/") { logFilePath = left(logFilePath, len(logFilePath) - 1); } } logFile = logFilePath $ "/" $ logFileName $ "." $ logFileExtension; tempLogFile = logFile $ "." $ tempLogFileExtension; } // Open the log file. bSuccess = openFile(tempLogFile, logFile); if (bSuccess) { timeStampFormat = control.sConf.logFileTimeStampFormat; beginLog(); control.nscLog(lng.format(lng.logFileCreated, tempLogFile)); } else { control.nscLog(lng.format(lng.logFileCreateFailed, logFileName)); //destroy(); } } /*************************************************************************************************** * * $DESCRIPTION Writes the log header. * **************************************************************************************************/ function beginLog() { local NexgenLogEntry logEntry; local string logLine; // Write header. println(lng.logFileTitle, true); println("", true); println(lng.format(lng.logFileEngineVersion, level.engineVersion), true); println(lng.format(lng.logFileNexgenVersion, class'NexgenCorePlugin'.default.pluginVersion), true); println(lng.format(lng.logFileServerID, class'NexgenUtil'.static.formatGUID(control.sConf.serverID)), true); println(lng.format(lng.logFileServerName, control.sConf.serverName), true); println(lng.format(lng.logFileServerPort, level.game.getServerPort()), true); println(lng.format(lng.logFileGameClass, level.game.class), true); println(lng.format(lng.logFileLevelName, class'NexgenUtil'.static.getLevelFileName(level)), true); println(lng.format(lng.logFileLevelTitle, level.summary.title), true); println("", true); println(lng.format(lng.logFileStart, lng.getCurrentDate(lng.longDateTimeFormat)), true); println("", true); // Write buffered logs. for (logEntry = control.logBuffer; logEntry != none; logEntry = logEntry.nextLogEntry) { logLine = control.getLogTypeTag(logEntry.type) @ logEntry.message; if (timeStampFormat != "") { logLine = lng.getDate(timeStampFormat, logEntry.year, logEntry.month, logEntry.day, logEntry.dayOfWeek, logEntry.hour, logEntry.minute, logEntry.second) @ logLine; } println(logLine, true); } // Flush output. flush(); } /*************************************************************************************************** * * $DESCRIPTION Ends the log file. * $ENSURE !bIsOpen * **************************************************************************************************/ function endLog() { if (bIsOpen) { println("", true); println(lng.format(lng.logFileClose, lng.getCurrentDate(lng.longDateTimeFormat)), true); closeFile(); } } /*************************************************************************************************** * * $DESCRIPTION Adds a new entry to the log file. * $PARAM msg Message that should be written to the log. * $PARAM logType The type of log message. * **************************************************************************************************/ function addLog(string msg, optional byte logType) { if (bIsOpen) { if (timeStampFormat == "") { println(control.getLogTypeTag(logType) @ msg); } else { println(lng.getCurrentDate(timeStampFormat) @ control.getLogTypeTag(logType) @ msg); } } } tD "Switch to green"_( "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"eD "5-5-5-5-5-5-4"fD "NSC"gD ","hD "="iD "\\"jD "\\/*?:<>\"|"kDmDw,Gd%d}5-5-5-5-5-5-4 5-5-5-5-5-5-4d&x0  x 9K!J g%gK!I pI ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&gnI pI  dI   I @qD "country"|/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenLogEntry * $VERSION 1.00 (16-6-2008 11:31) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Class that describes a log entry. * **************************************************************************************************/ class NexgenLogEntry extends info; var NexgenLogEntry nextLogEntry; // Next log entry. var string message; // The log message. var byte type; // The type of message. var int year; // Year when the message was generated. var int month; // Month when the message was generated. var int day; // Day when the message was generated. var int dayOfWeek; // Day of the week when the message was generated. var int hour; // Hour when the message was generated. var int minute; // Minute when the message was generated. var int second; // Second when the message was generated. /*************************************************************************************************** * * $DESCRIPTION Called when the NexgenLogEntry was destroyed. Destroys the next log entry. * $ENSURE nextLogEntry == none * $OVERRIDE * **************************************************************************************************/ function destroyed() { if (nextLogEntry != none) { nextLogEntry.destroy(); nextLogEntry = none; } } A/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenLang * $VERSION 1.37 (2-8-2008 14:17) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Localization support class. Provides the language dependant functionality of the * Nexgen server controller. * **************************************************************************************************/ class NexgenLang extends Info; const dateFormatStr = "dd/mm/yyyy hh:mm"; const defaultLogFileNameFormat = "nsc_%Y_%m_%d_%H_%i_%s"; const defaultLogFileTimeStampFormat = "[%d/%m/%Y %H:%i:%s]"; const longDateTimeFormat = "%l, %F %j, %Y, %H:%i:%s"; const startingControllerMsg = "Starting Nexgen Server Controller..."; const noDedicatedServerMsg = "Failed, your server should be dedicated."; const compatibilityModeMsg = "%1 has been detected, entering compatibility mode..."; const autoInstallMsg = "First time run, executing default installation..."; const autoUpdateMsg = "Updating Nexgen configuration to version %1..."; const invalidConfigMsg = "Configuration file has been automatically repaired."; const attrServerIDMsg = "ServerID = %1"; const nexgenBootMsg = "Server crash/reboot detected, executing Nexgen boot sequence..."; const nexgenMapLoadFailMsg = "Warning, attempt to load %1 has failed!"; const nexgenBootFailMsg = "Nexgen boot sequence failed, resuming to normal mode."; const execCommandMsg = "EXEC %1"; const bootLevelSwitchMsg = "Restarting server on %1"; const nexgenActiveMsg = "Nexgen Server Controller is active."; const logFileCreateFailed = "Failed to create log file: %1"; const logFileCreated = "Log file created, logging to: %1"; const loadingPluginMsg = "Loading %1 %2..."; const initFailedMsg = "Failed to initialize %1, destroying..."; const regFailedMsg = "Failed to register %1, destroying..."; const noHUDReplacementClassMsg = "No replacement class found for %1"; const loginRequestMsg = "Login request for %1"; const attrClientIPMsg = "IP = %1"; const attrClientIDMsg = "ClientID = %1"; const attrPasswordMsg = "Password = %1"; const illegalLoginParametersMsg = "Illegal login parameters (possible hack)."; const duplicateIDMsg = "Client ID already in use."; const bannedMsg = "Kicked/banned from the server."; const invalidPassMsg = "Invalid password."; const serverCapacityMsg = "Server is full."; const noPlayRightMsg = "No playing rights."; const loginAcceptedMsg = "Login accepted."; const loginRejectedMsg = "Login denied. Reason: %1"; const logFileTitle = "NEXGEN LOG FILE"; const logFileEngineVersion = "engine-version: %1"; const logFileNexgenVersion = "nexgen-version: %1"; const logFileServerID = "server-id : %1"; const logFileServerName = "server-name : %1"; const logFileServerPort = "server-port : %1"; const logFileGameClass = "game-class : %1"; const logFileLevelName = "level-name : %1"; const logFileLevelTitle = "level-title : %1"; const logFileStart = "Log started at %1"; const logFileClose = "Log closed at %1"; const gameStartedMsg = "The game has started."; const gameEndedMsg = "The game has ended after %1 sec."; const playerJoinMsg = "(+%2) %1"; const playerLeaveMsg = "(-%2) %1"; const playerNameChangeMsg = "%1 has changed his/her name to %2."; const playerLeaveLogMsg = "%1 has left the server."; const teamSwitchFailMsg = "Failed to switch team, %1."; const teamsLockedMsg = "the teams are locked"; const nameChangeFailMsg = "Failed to change name, %1."; const nameChangeDisabled = "name change has been disabled"; const invalidCommandMsg = "Invalid Nexgen command or parameters."; const commandFailedMsg = "Failed to execute command, %1."; const internalErrorMsg = "internal error"; const teamSwitchFailedMsg = "Failed to switch team, %1."; const specTeamSwitchMsg = "spectators can't switch team"; const teamSwitchDisabledMsg = "team switching is disabled on this server"; const playerTeamSwitchDisabledMsg = "you are not allowed to change from team"; const invalidTeamMsg = "team doesn't exist"; const sameTeamMsg = "you are already on %1"; const noSpecsAllowedMsg = "this server doesn't allow spectators"; const noMoreSpecSlotsMsg = "all spectator slots are taken"; const noPlayingRightsMsg = "you do not have playing rights on this server"; const noMorePlayerSlotsMsg = "all player slots are taken"; const teamBalanceFailedMsg = "Failed to balance teams, %1."; const notATeamGameMsg = "this command is only available for team games"; const teamBalanceDisabledMsg = "team balancing is disabled"; const teamsAlreadyBalancedMsg = "the teams are already balanced"; const balanceMsg = "%1 has balanced the teams."; const launchMsg = "%1 has started the game."; const playerReadyMsg = "%1 is READY!"; const forcedEndMsg = "The game has been forced to an end."; const rootAdminTitle = "Root Admin"; const specTitle = "Spectator"; const deathPreventedMsg = "The server has prevented you from dying."; const mutedReminderMsg = "Unable to send message, you are muted."; const accountTypeNameStr = "Account type %1"; const teamKillAttemptMsg = "%1 had a team kill attempt against %2."; const httpClientErrorMsg = "HTTP client error: %1"; const controllerSystemLogTag = "[NSC-SYS]"; const eventLogTag = "[ EVENT ]"; const messageLogTag = "[MESSAGE]"; const chatMessageLogTag = "[ SAY ]"; const teamSayMessageLogTag = "[TEAMSAY]"; const privateMessageLogTag = "[ PMSAY ]"; const adminActionLogTag = "[ ADMIN ]"; const allowedToPlayRightDesc = "Allowed to play on server."; const vipSlotAccessRightDesc = "VIP slot access."; const adminSlotAccessRightDesc = "Admin slot access."; const needsNoPWRightDesc = "Password immune."; const canBeIdleRightDesc = "Can be idle."; const matchAdminRightDesc = "Game supervisor."; const matchSetRightDesc = "Setup matches."; const moderatorRightDesc = "Moderate."; const banOpRightDesc = "Ban operator."; const accountMngrRightDesc = "Manage accounts."; const serverAdminRightDesc = "Server administrator."; const canBanAccountsRightDesc = "Ban registered players."; const hiddenAdminRightDesc = "Hidden admin."; const launchGameMsg = "Press [Fire] to start the game."; const adminLaunchGameMsg = "Please wait, an administrator is going to start the game."; const tournamentLaunchGameMsg = "Waiting for ready signals, press [Fire] to send your ready signal!"; const serverCrashedClientMsg = "The server has crashed and has been reloaded!"; const bootFailedClientMsg = "The Nexgen boot sequence has failed, please contact the server administrator!"; const serverAdminRebootClientMsg = "The server was restarted by an administrator and has been reloaded!"; const welcomeMsg = "Welcome to Nexgen, type !open to open the control panel."; const settingsSavedMsg = "New settings have been saved."; const receivedPMMsg = "[PM] %3 %1: %2"; const receivedPWMsg = "Match password received: '%1'"; const passwordSendMsg = "The password has been send."; const noBanAccountRightMsg = "You are not allowed to kick or ban players that have an account on this server."; const adminTeamSwitchMsg = "%1 has moved %2 to %3."; const adminPauseGameMsg = "%1 has paused the game."; const adminResumeGameMsg = "%1 has resumed the game."; const adminRestartGameMsg = "%1 has restarted the game."; const adminStopGameMsg = "%1 has stopped the game."; const adminPlayerTeamSwitchDisableMsg = "%1 has disabled team switching for %2."; const adminPlayerTeamSwitchEnableMsg = "%1 has enabled team switching for %2."; const adminReconnectAsPlayerMsg = "%1 has reconnected %2 as player."; const adminReconnectAsSpecMsg = "%1 has reconnected %2 as spectator."; const adminSendToURLMsg = "%1 has send %2 to %3."; const adminDisableTeamSwitchMsg = "%1 has disabled team switching."; const adminEnableTeamSwitchMsg = "%1 has enabled team switching."; const adminDisableTeamBalanceMsg = "%1 has disabled team balancing."; const adminEnableTeamBalanceMsg = "%1 has enabled team balancing."; const adminLockTeamsMsg = "%1 has locked the teams."; const adminUnlockTeamsMsg = "%1 has unlocked the teams."; const adminAddBanMsg = "%1 has added %2 to the banlist."; const adminDeleteBanMsg = "%1 has removed %2 from the banlist."; const adminEnableMatchModeMsg = "%1 has set the server in match mode."; const adminDisableMatchModeMsg = "%1 has reset the server in normal mode."; const adminMutePlayerMsg = "%1 has muted %2."; const adminUnmutePlayerMsg = "%1 has unmuted %2."; const adminSetNameMsg = "%1 has renamed %2 to %3."; const adminKickPlayerMsg = "%1 has kicked %2 from the server."; const adminBanPlayerMsg = "%1 has banned %2 from the server."; const adminMuteAllMsg = "%1 has muted all players."; const adminUnmuteAllMsg = "%1 has unmuted all players."; const adminEnableNameChangeMsg = "%1 has allowed nickname changing on the server."; const adminDisableNameChangeMsg = "%1 has disabled nickname changing on the server."; const adminRebootServerMsg = "%1 has rebooted the server."; const adminEnableTournamentModeMsg = "%1 has enabled tournament mode."; const adminDisableTournamentModeMsg = "%1 has disabled tournament mode."; const adminAddAccountType = "%1 has created a new account type named: %2."; const adminUpdateAccountType = "%1 has modified the %2 account type."; const adminRemoveAccountType = "%1 has removed the %2 account type."; const adminMoveAccountType = "%1 has repositioned the %2 account type."; const adminRemoveAccount = "%1 has deleted the account %3 for %2."; const adminUpdateAccount = "%1 has modified the account for %2."; const adminAddAccount = "%1 has created a new %3 account for %2."; const adminUpdateBanMsg = "%1 has modified the ban entry for %2."; const adminUpdateBootControl = "%1 has modified the boot control settings."; const adminSeparateByTag = "%1 has separated the players by their tag."; const adminUpdateMatchSettings = "%1 has modified the match settings."; const adminUpdateIgnoredWeaponList = "%1 has modified the spawn protect ignored weapon list."; const adminUpdateHUDReplacementList = "%1 has modified the HUD replacement list."; const adminUpdateGlobalServerSettings = "%1 has modified the basic server settings."; const adminUpdateMiscNexgenSettings = "%1 has modified the general Nexgen settings."; const adminUpdateLogServerSettings = "%1 has modified the log settings."; const invalidPasswordMsg = "Unable to login as administrator, invalid password."; const adminLoginMsg = "%1 has logged in as %2."; const autoReconnectAlert = "Connection lost!\\nReconnecting in %1..."; const reconnectingAlert = "Connection lost!\\nReconnecting now..."; const rebootAlert = "Warning, reboot sequence activated!\\nRebooting server in %1..."; const idleAlert = "Idle / camper detection activated!\\nMove or be kicked in %1..."; const waitingState = "Waiting [%1]"; const waitingStateUnknownTime = "Waiting..."; const readyState = "Ready..."; const readySignalWaitState = "Ready [%1/%2]"; const startingState = "Starting [%1]"; const onlineState = "Online [%1]"; const offlineState = "Offline"; const offlineStateRCN = "Offline [%1]"; const endedState = "Ended"; const pausedState = "Paused"; const loginState = "Logging in"; const idleState = "Idle [%1]"; const mutedState = "Muted"; const protectedState = "Protected [%1]"; const deadState = "Dead"; const matchState = "Match [%1]"; const clientTabTxt = "Client"; const homeTabTxt = "Home"; const settingsTabTxt = "Settings"; const privateMessageTabTxt = "Private message"; const gameTabTxt = "Game"; const playersTabTxt = "Players"; const moderatorTabTxt = "Moderator"; const matchControlTabTxt = "Match control"; const matchSetupTabTxt = "Match setup"; const serverTabTxt = "Server"; const infoTabTxt = "Info"; const banControlTabTxt = "Ban control"; const accountsTabTxt = "Accounts"; const accountTypesTabTxt = "Account types"; const basicSettingsTabTxt = "Basic"; const nexgenSettingsTabTxt = "Nexgen"; const bootTabTxt = "Boot control"; const pluginsTabTxt = "Plugins"; const aboutTabTxt = "About"; const welcomeTxt = "Welcome %1, you are logged in as %2."; const rightsOverviewTxt = "The following privileges / rights are available to you on this server:"; const rightNotDefinedTxt = "Privilege %1 (not defined)."; const teamBalanceTxt = "Team balance"; const redTeamTxt = "Red"; const blueTeamTxt = "Blue"; const greenTeamTxt = "Green"; const goldTeamTxt = "Yellow"; const playTxt = "Play"; const spectateTxt = "Spectate"; const reconnectTxt = "Reconnect"; const disconnectTxt = "Disconnect"; const exitTxt = "Exit"; const mapVoteTxt = "Open mapvote"; const startTxt = "Start game"; const loginTxt = "Admin login"; const serverNameTxt = "Server name:"; const shortServerNameTxt = "Short server name:"; const MOTDLineTxt = "MOTD line %1"; const adminNameTxt = "Admin name:"; const adminEmailTxt = "Admin email:"; const serverPasswordTxt = "Server password:"; const adminPasswordTxt = "Admin password:"; const playerSlotsTxt = "Player slots:"; const vipSlotsTxt = "VIP slots:"; const adminSlotsTxt = "Admin slots:"; const specSlotsTxt = "Spectator slots:"; const advertiseTxt = "Advertise server:"; const resetTxt = "Reset"; const saveTxt = "Save"; const keyBindsTxt = "Keybinds"; const balanceBindTxt = "Balance teams"; const switchRedBindTxt = "Switch to red"; const switchBlueBindTxt = "Switch to blue"; const switchGreenBindTxt = "Switch to green"; const switchGoldBindTxt = "Switch to yellow"; const suicideBindTxt = "Suicide"; const openMapVoteBindTxt = "Open map vote"; const openCPBindTxt = "Open control panel"; const pauseGameBindTxt = "Pause game"; const UISettingsTxt = "User interface"; const enableMsgHUDTxt = "Enable Nexgen message HUD"; const msgFlashEffectTxt = "Enable message 'flash' effect"; const showPlayerLocationTxt = "Show player location on teamsay messages"; const pmSoundTxt = "Play a sound when a private message arrives"; const miscSettingsTxt = "Miscellaneous settings"; const autoSSNormalGameTxt = "Auto screenshot at the end of normal games"; const autoSSMatchTxt = "Auto screenshot at the end of matches"; const playerListTxt = "Players"; const blockedListTxt = "Blocked"; const blockToggleTxt = "Block / Unblock"; const blockAllPMsTxt = "Block all private messages"; const messageTxt = "Message"; const sendNormalPMTxt = "Send normal PM"; const sendWindowedPMTxt = "Send windowed PM"; const historyTxt = "History"; const blockMsg = "%1 has been blocked."; const unblockMsg = "%1 has been unblocked."; const sendMsgTxt = "Send to %1: %2"; const receivedMsgTxt = "%1: %2"; const accountNameTxt = "Account name"; const accountTitleTxt = "Account title"; const passwordTxt = "Password"; const addAccountTypeTxt = "Add account type"; const delAccountTypeTxt = "Delete account type"; const moveUpTxt = "Move up"; const moveDownTxt = "Move down"; const userNameTxt = "User name"; const accountTypeTxt = "Account type"; const userTitleTxt = "User title"; const onlineTxt = "Online"; const offlineTxt = "Offline"; const updateTxt = "Update"; const addTxt = "Add"; const deleteTxt = "Delete"; const customAccountTxt = ""; const switchToTeamTxt = "Switch to %1"; const sendToURLTxt = "Send to URL"; const reconnectAsPlayerTxt = "Reconnect as player"; const reconnectAsSpecTxt = "Reconnect as spectator"; const disableTeamSwitchTxt = "(Dis)allow team switch"; const pauseGameTxt = "Pause game"; const endGameTxt = "End game"; const restartGameTxt = "Restart game"; const allowTeamSwitchTxt = "Allow team switching"; const allowTeamBalanceTxt = "Allow team balancing"; const lockTeamsTxt = "Lock the game"; const tournamentModeTxt = "Tournament mode"; const playerNameTxt = "Player name"; const banReasonTxt = "Ban/kick reason"; const banPeriodTxt = "Ban period"; const banForeverTxt = "Forever"; const banMatchesTxt = "'x' matches"; const banDaysTxt = "'x' days"; const banUntilDateTxt = "Until 'date'"; const ipAddressesTxt = "IP addresses"; const clientIDsTxt = "Client IDs"; const addBanTxt = "Create new ban"; const updateBanTxt = "Update ban"; const delBanTxt = "Remove ban"; const removeTxt = "Remove"; const enableBootCtrlTxt = "Enable Nexgen boot control"; const restartOnLastGameTxt = "Restart game on last map"; const inclMutatorsTxt = "Mutators used"; const exclMutatorsTxt = "Mutators not used"; const bootCmdLineTxt = "Server boot command line"; const gameTypeTxt = "Game type"; const mapPrefixTxt = "Map prefix"; const extraCmdLineOptTxt = "Additional command line options"; const preSwitchCommandsTxt = "Pre switch server console commands"; const rebootTxt = "Reboot"; const administratorTxt = "Administrator"; const contactAddrTxt = "Contact address"; const msgOfTheDayTxt = "Message of the day"; const serverIDTxt = "Server ID"; const statisticsTxt = "Stats"; const totalGamesTxt = "Games hosted"; const totalFragsTxt = "Total frags"; const totalDeathsTxt = "Total deaths"; const totalFlagsTxt = "Total caps"; const bestPlayersTxt = "Top players"; const FPHTxt = "FPH"; const recordSetTxt = "Date"; const timeLimitTxt = "Time limit"; const scoreLimitTxt = "Score limit"; const teamScoreLimitTxt = "Team score limit"; const gameSpeedTxt = "Game speed"; const teamSwitchEnabledTxt = "Team switch enabled"; const teamBalanceEnabledTxt = "Team balancing enabled"; const teamsLockedTxt = "Teams are locked"; const nameChangeAllowedTxt = "Name change allowed"; const mutatorsTxt = "Mutators"; const levelTxt = "Level"; const fileTxt = "File"; const titleTxt = "Title"; const authorTxt = "Author"; const idealPlayerCountTxt = "Players"; const matchSettingsTxt = "Match settings"; const matchNumOfGamesTxt = "Number of games"; const matchCurrGameNumTxt = "Current game"; const matchSpecNoPassTxt = "Allow spectators to enter the game without a password"; const matchMuteSpecsTxt = "Mute spectators during the game"; const matchBootControlTxt = "Switch back to last map when the server has crashed"; const matchAutoLockTeamsTxt = "Automatically lock teams at the beginning of each game"; const matchAutoPauseTxt = "Automatically pause the game when a player leaves"; const matchSeparateByTagTxt = "Separate players by tag"; const matchAutoTagSeparateTxt = "Automatically separate by tag"; const matchDoSeparateTxt = "Separate now"; const startMatchTxt = "Start match"; const stopMatchTxt = "Stop match"; const sendPasswordTxt = "Send password"; const allPlayersTxt = ""; const clientIDTxt = "Client ID"; const ipAddressTxt = "IP address"; const muteToggleTxt = "(Un)mute"; const setPlayerNameTxt = "Set name"; const kickPlayerTxt = "Kick"; const banPlayerTxt = "Ban"; const muteAllTxt = "Mute all players"; const allowNameChangeTxt = "Allow players to change their name"; const showAdminMessageTxt = "Show message"; const copyTxt = "Copy"; const nexgenMiscSettingsPanelTitle = "General Nexgen settings"; const autoUpdateBansTxt = "Automatically update ban entries"; const autoDelExpiredBansTxt = "Automatically remove expired ban entries"; const announceTeamKillsTxt = "Broadcast team kill attempts"; const restoreScoreOnTeamSwitchTxt = "Don't decrease score on team switch"; const enableNexgenStartControlTxt = "Let Nexgen handle the game start"; const broadcastAdminActionsTxt = "Broadcast administrator actions to all players"; const enableNexgenMessageHUDTxt = "Enable the Nexgen message HUD"; const defaultAllowTeamSwitchTxt = "Team switch allowed by default"; const defaultAllowTeamBalanceTxt = "Team balance allowed by default"; const defaultAllowNameChangeTxt = "Name change allowed by default"; const autoRegisterServerTxt = "Register server in Nexgen database"; const gameWaitTimeTxt = "Game wait time (sec)"; const gameStartDelayTxt = "Game start delay (sec)"; const autoReconnectTimeTxt = "Auto reconnect time (sec)"; const maxIdleTimeTxt = "Max idle time (sec)"; const maxIdleTimeCPTxt = "Max idle time in control panel (sec)"; const spawnProtectTimeTxt = "Spawn protect time (sec)"; const teamKillDmgProtectTxt = "Team kill damage protect time (sec)"; const teamKillPushProtectTxt = "Team kill push protect time (sec)"; const autoDisableMatchTimeTxt = "Auto disable match mode time (min)"; const ignoredWeaponsTxt = "Weapons ignored by spawn protector."; const weaponClassTxt = "Weapon class"; const ignorePrimaryFireTxt = "Ignore primary fire"; const ignoreAltFireTxt = "Ignore alternate fire"; const hudReplaceClassesTxt = "HUD replacement classes."; const originalHUDClassTxt = "Original HUD class"; const replacementHUDClassTxt = "Replacement HUD class"; const addNewItemTxt = ""; const logSettingsPanelTitle = "Log settings"; const logToConsoleTxt = "Write log messages to console (stdout)"; const logToFileTxt = "Write log messages to file"; const logEventsTxt = "Write Nexgen events to the server log"; const logFilePathTxt = "Log path"; const logFileExtensionTxt = "Log extension"; const logFileNameFormatTxt = "Log file name"; const logTimeStampFormatTxt = "Time format"; const logMessagesTxt = "Write system messages to the server log"; const logChatMessagesTxt = "Write chat messages to the server log"; const logPrivateMessagesTxt = "Write private messages to the server log"; const logAdminActionsTxt = "Write administrator actions to the server log"; /*************************************************************************************************** * * $DESCRIPTION Returns the name of the team specified by the given number. * $PARAM team Number of the team whose name is to be returned. * $RETURN The name of the team, or ? if an invalid team is specified. * **************************************************************************************************/ static function string getTeamName(int team) { switch (team) { case 0: return "red"; case 1: return "blue"; case 2: return "green"; case 3: return "yellow"; } } /*************************************************************************************************** * * $DESCRIPTION Formats the given string by inserting the specified strings into the proper * positions. The positions are indicated by the "%n" tags, where n is number of the * string to insert. * $PARAM source The string that is to be formatted. * $PARAM str1 String number 1 to insert. * $PARAM str2 String number 2 to insert. * $PARAM str3 String number 3 to insert. * $PARAM str4 String number 4 to insert. * $RETURN The formatted string. * **************************************************************************************************/ static function string format(string source, optional coerce string str1, optional coerce string str2, optional coerce string str3, optional coerce string str4) { return class'NexgenUtil'.static.format(source, str1, str2, str3, str4); } /*************************************************************************************************** * * $DESCRIPTION Converts a ban period string into a human readable format. * $PARAM banPeriodStr The string describing the ban period. * $RETURN A string describing (in words) how long the ban lasts. * **************************************************************************************************/ function string getBanPeriodDescription(string banPeriodStr) { local string description; if (banPeriodStr == "") { description = "forever"; } else if (left(banPeriodStr, 1) ~= "M") { description = "for" @ mid(banPeriodStr, 1) @ "matches"; } else if (left(banPeriodStr, 1) ~= "U") { description = "until" @ getLocalizedDateStr(mid(banPeriodStr, 1)); } else { description = "forever"; } return description; } /*************************************************************************************************** * * $DESCRIPTION Returns a compact date description string for the specified date. * $PARAM year Year of the specified date. * $PARAM month Month of the specified date. * $PARAM day Day of the specified date. * $PARAM hour Hour of the specified date. * $PARAM minute Minute of the specified date. * $REQUIRE (1 <= month && moth <= 12) && (1 <= day && day <= 31) && * (0 <= hour && hour <= 23) && (0 <= minute && minute <= 59) * $RETURN The date description string for the given date. * **************************************************************************************************/ static function string getCompactDateStr(int year, int month, int day, int hour, int minute) { return class'NexgenUtil'.static.lfill(day, 2, "0") $ "/" $ class'NexgenUtil'.static.lfill(month, 2, "0") $ "/" $ class'NexgenUtil'.static.lfill(year, 4, "0") $ " " $ class'NexgenUtil'.static.lfill(hour, 2, "0") $ ":" $ class'NexgenUtil'.static.lfill(minute, 2, "0"); } /*************************************************************************************************** * * $DESCRIPTION Parses the given date string. * $PARAM dateStr The date string to parse. * $PARAM year Year of the specified date. * $PARAM month Month of the specified date. * $PARAM day Day of the specified date. * $PARAM hour Hour of the specified date. * $PARAM minute Minute of the specified date. * $REQUIRE 'dateStr follows dateFormatStr' * $RETURN True if the specified date string was valid, false if not. When false is returned * the outcome (the date) should be ignored. * **************************************************************************************************/ static function bool parseDate(string dateStr, out int year, out int month, out int day, out int hour, out int minute) { local bool bValid; local string remaining; local int index; bValid = true; remaining = class'NexgenUtil'.static.trim(dateStr); // Parse day. index = instr(remaining, "/"); if (index >= 0) { day = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } // Parse month. if (bValid) { index = instr(remaining, "/"); if (index >= 0) { month = int(left(remaining, index)); remaining = class'NexgenUtil'.static.trim(mid(remaining, index + 1)); } else { bValid = false; } } // Parse year. if (bValid) { index = instr(remaining, " "); if (index >= 0) { year = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } } // Parse hour. if (bValid) { index = instr(remaining, ":"); if (index >= 0) { hour = int(left(remaining, index)); remaining = mid(remaining, index + 1); } else { bValid = false; } } // Parse minute. if (bValid) { minute = int(remaining); } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Converts the given date string into a localized format. * $PARAM dateStr The date string to convert. * $RETURN The converted date into a localized format. * **************************************************************************************************/ function string getLocalizedDateStr(string dateStr) { local bool bValid; local int year, month, day, hour, minute; bValid = class'NexgenUtil'.static.readDate(dateStr, year, month, day, hour, minute); if (bValid) { return getCompactDateStr(year, month, day, hour, minute); } else { return dateStr; } } /*************************************************************************************************** * * $DESCRIPTION Converts the given localized date string into a standard format. * $PARAM dateStr The date string to convert. * $RETURN The converted date into a standard format. * **************************************************************************************************/ function string getDelocalizedDateStr(string dateStr) { local bool bValid; local int year, month, day, hour, minute; bValid = parseDate(dateStr, year, month, day, hour, minute); if (bValid) { return class'NexgenUtil'.static.serializeDate(year, month, day, hour, minute); } else { return dateStr; } } /*************************************************************************************************** * * $DESCRIPTION Returns the current date in the specified format. * $PARAM The format of the date. * $RETURN The current date in the the specified format. * **************************************************************************************************/ function string getCurrentDate(string format) { return getDate(format, level.year, level.month, level.day, level.dayOfWeek, level.hour, level.minute, level.second); } /*************************************************************************************************** * * $DESCRIPTION Returns given date in the specified format. * $PARAM The format of the date. * $RETURN The given date in the the specified format. * **************************************************************************************************/ static function string getDate(string format, int year, int month, int day, int dayOfWeek, int hour, int minute, int second) { local string dateStr; local int value; local string strValue; dateStr = format; // Year. if (instr(dateStr, "%Y") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%Y", class'NexgenUtil'.static.lfill(year, 4, "0")); } if (instr(dateStr, "%y") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%y", class'NexgenUtil'.static.lfill(year, 2, "0", 2)); } if (instr(dateStr, "%L") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%L", byte(class'NexgenUtil'.static.isLeapYear(year))); } // Month. if (instr(dateStr, "%m") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%m", class'NexgenUtil'.static.lfill(month, 2, "0")); } if (instr(dateStr, "%n") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%n", month); } if (instr(dateStr, "%F") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%F", getMonthName(month)); } if (instr(dateStr, "%M") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%M", getShortMonthName(month)); } if (instr(dateStr, "%t") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%t", class'NexgenUtil'.static.daysInMonth(year, month)); } // Day. if (instr(dateStr, "%d") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%d", class'NexgenUtil'.static.lfill(day, 2, "0")); } if (instr(dateStr, "%j") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%j", day); } if (instr(dateStr, "%w") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%w", dayOfWeek); } if (instr(dateStr, "%N") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%N", (dayOfWeek + 1)); } if (instr(dateStr, "%l") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%l", getDayName(dayOfWeek)); } if (instr(dateStr, "%D") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%D", getShortDayName(dayOfWeek)); } // Hour. if (instr(dateStr, "%H") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%H", class'NexgenUtil'.static.lfill(hour, 2, "0")); } if (instr(dateStr, "%h") >= 0) { value = hour % 12; if (value == 0) value = 12; dateStr = class'NexgenUtil'.static.replace(dateStr, "%h", class'NexgenUtil'.static.lfill(value, 2, "0")); } if (instr(dateStr, "%G") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%G", hour); } if (instr(dateStr, "%g") >= 0) { value = hour % 12; if (value == 0) value = 12; dateStr = class'NexgenUtil'.static.replace(dateStr, "%g", value); } if (instr(dateStr, "%a") >= 0) { if (hour == 0 || hour > 12) { strValue = "am"; } else { strValue = "pm"; } dateStr = class'NexgenUtil'.static.replace(dateStr, "%a", strValue); } if (instr(dateStr, "%A") >= 0) { if (hour == 0 || hour > 12) { strValue = "AM"; } else { strValue = "PM"; } dateStr = class'NexgenUtil'.static.replace(dateStr, "%A", strValue); } // Minute. if (instr(dateStr, "%i") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%i", class'NexgenUtil'.static.lfill(minute, 2, "0")); } // Second. if (instr(dateStr, "%s") >= 0) { dateStr = class'NexgenUtil'.static.replace(dateStr, "%s", class'NexgenUtil'.static.lfill(second, 2, "0")); } return dateStr; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the full textual representation of the specified day of the week. * $PARAM day The number of day of the week whose name is to be retrieved. * $REQUIRE 0 <= day && day <= 6 * $RETURN A full textual representation of the day of the week. * $ENSURE result != "" * **************************************************************************************************/ static function string getDayName(int day) { switch (day) { case 0: return "Sunday"; case 1: return "Monday"; case 2: return "Tuesday"; case 3: return "Wednesday"; case 4: return "Thursday"; case 5: return "Friday"; case 6: return "Saturday"; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the short textual representation of the specified day of the week, three * letters. * $PARAM day The number of day of the week whose name is to be retrieved. * $REQUIRE 0 <= day && day <= 6 * $RETURN A short textual representation of the day of the week. * $ENSURE len(result) == 3 * **************************************************************************************************/ static function string getShortDayName(int day) { switch (day) { case 0: return "Sun"; case 1: return "Mon"; case 2: return "Tue"; case 3: return "Wed"; case 4: return "Thu"; case 5: return "Fri"; case 6: return "Sat"; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the full textual representation of the specified month, such as January * or March. * $PARAM month The number of the month whose name is to be retrieved. * $REQUIRE 1 <= month && month <= 12 * $RETURN A full textual representation of the specified month. * $ENSURE result != "" * **************************************************************************************************/ static function string getMonthName(int month) { switch (month) { case 1: return "January"; case 2: return "February"; case 3: return "March"; case 4: return "April"; case 5: return "May"; case 6: return "June"; case 7: return "July"; case 8: return "August"; case 9: return "September"; case 10: return "October"; case 11: return "November"; case 12: return "December"; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the short textual representation of the specified month, three letters. * $PARAM month The number of the month whose short name is to be retrieved. * $REQUIRE 1 <= month && month <= 12 * $RETURN A short textual representation of the specified month. * $ENSURE len(result) == 3 * **************************************************************************************************/ static function string getShortMonthName(int month) { switch (month) { case 1: return "Jan"; case 2: return "Feb"; case 3: return "Mar"; case 4: return "Apr"; case 5: return "May"; case 6: return "Jun"; case 7: return "Jul"; case 8: return "Aug"; case 9: return "Sep"; case 10: return "Oct"; case 11: return "Nov"; case 12: return "Dec"; } } rD "team"uD "title"lDS#L K S#-P!e~K O!Pe%-P!'t pt K t ppt K eR#K K e}O! t   vD "Switch to blue"xD "name"}D "Switch to red"P!@KE "ip"c /*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenJustBannedDialog * $VERSION 1.00 (17-11-2007 18:34) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player just got kicked / banned from the server. * **************************************************************************************************/ class NexgenJustBannedDialog extends NexgenBannedDialog; /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ H"yDK 2zD/H"& V].-You have been kicked/banned from the server.]RAn administrator has just kicked or banned you from the server. This means you are probably not welcome for the time being. Please go play somewhere else, there are enough of other servers and games out there.L/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenImageControl * $VERSION 1.00 (10-03-2007 22:54) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Image GUI component. * **************************************************************************************************/ class NexgenImageControl extends UWindowDialogControl; var Texture image; // Image to display. var bool bStretch; // Whether to stretch the image if the dimensions do not match. /*************************************************************************************************** * * $DESCRIPTION Renders the GUI component. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y) { local float xPos; local float yPos; if (image != none) { if (bStretch) { drawStretchedTexture(c, 0, 0, winWidth, winHeight, image); } else { xPos = int((winWidth - image.uSize) / 2.0); yPos = int((winHeight - image.vSize) / 2.0); drawClippedTexture(c, xPos, yPos, image); } } } sDQ# vpvQ#%1P#vv%2O#vv%3N#vv%4M#v  ~D "Balance teams"D "Keybinds"@E "Save"AE "Reset"EE "Advertise server:"v@\/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenIllegalLoginDialog * $VERSION 1.00 (2-8-2008 14:26) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the players client ID is already in use. * **************************************************************************************************/ class NexgenIllegalLoginDialog extends NexgenPopupDialog; var UWindowSmallButton reconnectButton; // Reconnect button component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); addNewLine(cy); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ |DL# fSL#=Z}SzSZ& Z SSZZ}S&Z%zSZ& Z_SSZ&S  JE "Spectator slots:"Z@CCEB@I 2GE3Cn V])(Failed to login: illegal login attempt.]uYour client has send illegal login information to the server. This is most likely the result of a modified/hacked Nexgen package, therefore you are not allowed to enter the server.e"Ok,/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenIDUsedDialog * $VERSION 1.01 (20-1-2008 12:58) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the players client ID is already in use. * **************************************************************************************************/ class NexgenIDUsedDialog extends NexgenPopupDialog; var UWindowSmallButton reconnectButton; // Reconnect button component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. var localized string reconnectText; // Text to display on the reconnect button. const reconnectCommand = "Reconnect"; // Console command for reconnecting. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); addNewLine(cy); reconnectButton = addButton(reconnectText, 64.0); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the reconnect or spectator buttons have been clicked and deals with it * accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Reconnect button. if (control == reconnectButton && eventType == DE_Click) { // Reconnect. getplayerowner().consoleCommand(reconnectCommand); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ DEK#7m|K#1}|S!|pJ#| ecS!}|c||c|  LE "Admin slots:"ME "id"QE "VIP slots:"RE "ac"|@CHE|?H 2OECnŔ> Y V],+Failed to login: client ID already in use.mUYour client ID appears to be already in use by another player. This is probably caused because you just left the server and the server wasn't able to receive your logout notification. This can also be caused by someone that has copied your Unreal Tournament installation or by someone that has acquired your Nexgen key. If you continue to experience this problem contact the administrator of this server.i]Retrye"OIEI#uAmI#1}^!pH# ea^!}aa  SE "Player slots:"TE "pl"XE "Admin password:"YE "pj"@l,/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenIdleKickedDialog * $VERSION 1.00 (13-10-2007 17:54) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dialog to display if the player is kicked for being idle on the server. * **************************************************************************************************/ class NexgenIdleKickedDialog extends NexgenPopupDialog; var UWindowSmallButton reconnectButton; // Reconnect button component. var localized string caption; // Caption to display on the dialog. var localized string message; // Dialog help / info / description message. var localized string reconnectText; // Text to display on the reconnect button. const reconnectCommand = "Reconnect"; // Console command for reconnecting. /*************************************************************************************************** * * $DESCRIPTION Creates the dialog. Calling this function will setup the static dialog contents. * $OVERRIDE * **************************************************************************************************/ function created() { local float cy; super.created(); // Add components. cy = borderSize; addText(caption, cy, F_Bold, TA_Center); addNewLine(cy); addText(message, cy, F_Normal, TA_Left); reconnectButton = addButton(reconnectText, 64.0); } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * Checks if the reconnect or spectator buttons have been clicked and deals with it * accordingly. * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $REQUIRE control != none * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { super.notify(control, eventType); // Reconnect button. if (control == reconnectButton && eventType == DE_Click) { // Reconnect. getplayerowner().consoleCommand(reconnectCommand); close(); } } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ PEG#Xv" L G#\~L H\%{L\NSC(L L\\~L \%c!L'c!L\LpL\ \%QY \}L d!, fL\&3zf 0Q% -]Y \zf"dQ%Q\&-]'{h!\Y \-](Q%Q\Y %d!F#LQY Q\""QY h!f\'  ZE "Server password:"^E ","gE "Admin email:"LCVEr?G 2\E=CnŔ> Y V]! You are kicked from the server.]ywThe server has disconnected your client because you were idle for too long. You can reconnect as soon as you get back.i] Reconnecte"OI{/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDxTDM * $VERSION 1.01 (31-12-2006 16:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended TDM HUD that uses the Nexgen HUD to render the messages. * **************************************************************************************************/ class NexgenHUDxTDM extends ChallengeTeamHUD; struct SavedMessage { // Structure used for buffered messages. var string msg; // Message string. var name msgType; // Type of the message. var PlayerReplicationInfo pri1; // Related player information 1. var PlayerReplicationInfo pri2; // Related player information 2. }; var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). var float lastCheck; // Last time we checked if the NexgenHUD is available. var SavedMessage savedMessages[10]; // Messages received before the NexgenHUD was available. var int savedMsgCount; // Number of messages saved. /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the parent class * and the renderMessageBox() function on the NexgenHUD if it is available. When the * NexgenHUD is not available an attempt is made to locate it. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function postRender(Canvas c) { super.postRender(c); if (nscHUD == none) { setNexgenHUD(); } else { nscHUD.renderMessageBox(c); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { super.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { super.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the NexgenHUD instance. Once the HUD has been located any saved * messages will be restored. To save processing resources the attemps will have a * minimum interval of 0.2 seconds. * $REQUIRE nscHUD == none * $ENSURE nscHUD != none ? savedMsgCount == 0 : true * **************************************************************************************************/ simulated function setNexgenHUD() { local int index; if (level.timeSeconds - lastCheck >= 0.2) { // Locate NexgenHUD instance. lastCheck = level.timeSeconds; foreach allActors(class'NexgenHUD', nscHUD) { if (nscHUD != none) { break; } } // Restore saved messages. if (nscHUD != none) { for (index = 0; index < savedMsgCount; index++) { nscHUD.message(savedMessages[index].msg, savedMessages[index].msgType, savedMessages[index].pri1, savedMessages[index].pri2); } savedMsgCount = 0; } } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int index; if (nscHUD == none) { // Buffer the message. if (savedMsgCount < arrayCount(savedMessages)) { index = savedMsgCount; savedMsgCount++; } else { for (index = 1; index < savedMsgCount; index++) { savedMessages[index - 1] = savedMessages[index]; } savedMsgCount = savedMsgCount - 1; } savedMessages[index].msg = msg; savedMessages[index].msgType = msgType; savedMessages[index].pri1 = pri1; savedMessages[index].pri2 = pri2; } else { // Pass it to the Nexgen HUD. nscHUD.message(msg, msgType, pri1, pri2); } } `E "Botpack.CHSpectator"]EL0F 6 _E9^>:>&:>&ElElEl:>&u&OcE "Mutate NSC START"O{/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDxDOM * $VERSION 1.01 (31-12-2006 16:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended DOM HUD that uses the Nexgen HUD to render the messages. * **************************************************************************************************/ class NexgenHUDxDOM extends ChallengeDominationHUD; struct SavedMessage { // Structure used for buffered messages. var string msg; // Message string. var name msgType; // Type of the message. var PlayerReplicationInfo pri1; // Related player information 1. var PlayerReplicationInfo pri2; // Related player information 2. }; var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). var float lastCheck; // Last time we checked if the NexgenHUD is available. var SavedMessage savedMessages[10]; // Messages received before the NexgenHUD was available. var int savedMsgCount; // Number of messages saved. /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the parent class * and the renderMessageBox() function on the NexgenHUD if it is available. When the * NexgenHUD is not available an attempt is made to locate it. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function postRender(Canvas c) { super.postRender(c); if (nscHUD == none) { setNexgenHUD(); } else { nscHUD.renderMessageBox(c); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { super.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { super.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the NexgenHUD instance. Once the HUD has been located any saved * messages will be restored. To save processing resources the attemps will have a * minimum interval of 0.2 seconds. * $REQUIRE nscHUD == none * $ENSURE nscHUD != none ? savedMsgCount == 0 : true * **************************************************************************************************/ simulated function setNexgenHUD() { local int index; if (level.timeSeconds - lastCheck >= 0.2) { // Locate NexgenHUD instance. lastCheck = level.timeSeconds; foreach allActors(class'NexgenHUD', nscHUD) { if (nscHUD != none) { break; } } // Restore saved messages. if (nscHUD != none) { for (index = 0; index < savedMsgCount; index++) { nscHUD.message(savedMessages[index].msg, savedMessages[index].msgType, savedMessages[index].pri1, savedMessages[index].pri2); } savedMsgCount = 0; } } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int index; if (nscHUD == none) { // Buffer the message. if (savedMsgCount < arrayCount(savedMessages)) { index = savedMsgCount; savedMsgCount++; } else { for (index = 1; index < savedMsgCount; index++) { savedMessages[index - 1] = savedMessages[index]; } savedMsgCount = savedMsgCount - 1; } savedMessages[index].msg = msg; savedMessages[index].msgType = msgType; savedMessages[index].pri1 = pri1; savedMessages[index].pri2 = pri2; } else { // Pass it to the Nexgen HUD. nscHUD.message(msg, msgType, pri1, pri2); } } aEI3E 6 bELUO4:>&:>&ElElEl:>&u&OfE "Exit"WEg[EV+g[E#,p\,Bzggppi!=[egppppg,i!=[  B{/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDxDM * $VERSION 1.01 (31-12-2006 16:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended DM HUD that uses the Nexgen HUD to render the messages. * **************************************************************************************************/ class NexgenHUDxDM extends ChallengeHUD; struct SavedMessage { // Structure used for buffered messages. var string msg; // Message string. var name msgType; // Type of the message. var PlayerReplicationInfo pri1; // Related player information 1. var PlayerReplicationInfo pri2; // Related player information 2. }; var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). var float lastCheck; // Last time we checked if the NexgenHUD is available. var SavedMessage savedMessages[10]; // Messages received before the NexgenHUD was available. var int savedMsgCount; // Number of messages saved. /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the parent class * and the renderMessageBox() function on the NexgenHUD if it is available. When the * NexgenHUD is not available an attempt is made to locate it. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function postRender(Canvas c) { super.postRender(c); if (nscHUD == none) { setNexgenHUD(); } else { nscHUD.renderMessageBox(c); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { super.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { super.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the NexgenHUD instance. Once the HUD has been located any saved * messages will be restored. To save processing resources the attemps will have a * minimum interval of 0.2 seconds. * $REQUIRE nscHUD == none * $ENSURE nscHUD != none ? savedMsgCount == 0 : true * **************************************************************************************************/ simulated function setNexgenHUD() { local int index; if (level.timeSeconds - lastCheck >= 0.2) { // Locate NexgenHUD instance. lastCheck = level.timeSeconds; foreach allActors(class'NexgenHUD', nscHUD) { if (nscHUD != none) { break; } } // Restore saved messages. if (nscHUD != none) { for (index = 0; index < savedMsgCount; index++) { nscHUD.message(savedMessages[index].msg, savedMessages[index].msgType, savedMessages[index].pri1, savedMessages[index].pri2); } savedMsgCount = 0; } } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int index; if (nscHUD == none) { // Buffer the message. if (savedMsgCount < arrayCount(savedMessages)) { index = savedMsgCount; savedMsgCount++; } else { for (index = 1; index < savedMsgCount; index++) { savedMessages[index - 1] = savedMessages[index]; } savedMsgCount = savedMsgCount - 1; } savedMessages[index].msg = msg; savedMessages[index].msgType = msgType; savedMessages[index].pri1 = pri1; savedMessages[index].pri2 = pri2; } else { // Pass it to the Nexgen HUD. nscHUD.message(msg, msgType, pri1, pri2); } } hE "Disconnect"jE "Admin name:"kE "Reconnect"dED#HcY0copD#,w~o,9-Y w%w}\%zow}\}\\~pp~ow}\,oow},w~o,6~p~ow|~}Z}=pZ=-Y'6~oow},w~o, [-Y~}Z}=aC#  lE "MOTD line %1"oE 2sE "Short server name:"w@eEV,D 6 nE6&^!:>&:>&ElElEl:>&u&O@F 1H{/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDxCTF * $VERSION 1.01 (31-12-2006 16:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended CTF HUD that uses the Nexgen HUD to render the messages. * **************************************************************************************************/ class NexgenHUDxCTF extends ChallengeCTFHUD; struct SavedMessage { // Structure used for buffered messages. var string msg; // Message string. var name msgType; // Type of the message. var PlayerReplicationInfo pri1; // Related player information 1. var PlayerReplicationInfo pri2; // Related player information 2. }; var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). var float lastCheck; // Last time we checked if the NexgenHUD is available. var SavedMessage savedMessages[10]; // Messages received before the NexgenHUD was available. var int savedMsgCount; // Number of messages saved. /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the parent class * and the renderMessageBox() function on the NexgenHUD if it is available. When the * NexgenHUD is not available an attempt is made to locate it. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function postRender(Canvas c) { super.postRender(c); if (nscHUD == none) { setNexgenHUD(); } else { nscHUD.renderMessageBox(c); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { super.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { super.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the NexgenHUD instance. Once the HUD has been located any saved * messages will be restored. To save processing resources the attemps will have a * minimum interval of 0.2 seconds. * $REQUIRE nscHUD == none * $ENSURE nscHUD != none ? savedMsgCount == 0 : true * **************************************************************************************************/ simulated function setNexgenHUD() { local int index; if (level.timeSeconds - lastCheck >= 0.2) { // Locate NexgenHUD instance. lastCheck = level.timeSeconds; foreach allActors(class'NexgenHUD', nscHUD) { if (nscHUD != none) { break; } } // Restore saved messages. if (nscHUD != none) { for (index = 0; index < savedMsgCount; index++) { nscHUD.message(savedMessages[index].msg, savedMessages[index].msgType, savedMessages[index].pri1, savedMessages[index].pri2); } savedMsgCount = 0; } } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int index; if (nscHUD == none) { // Buffer the message. if (savedMsgCount < arrayCount(savedMessages)) { index = savedMsgCount; savedMsgCount++; } else { for (index = 1; index < savedMsgCount; index++) { savedMessages[index - 1] = savedMessages[index]; } savedMsgCount = savedMsgCount - 1; } savedMessages[index].msg = msg; savedMessages[index].msgType = msgType; savedMessages[index].pri1 = pri1; savedMessages[index].pri2 = pri2; } else { // Pass it to the Nexgen HUD. nscHUD.message(msg, msgType, pri1, pri2); } } pEP1C 6 qE?:>&:>&ElElEl:>&u&OiEB#_a7ZB#<ZcEZcEE ZPEUZPEUU, U&E<ZPEUhhZPEUhU, U&EhZ  yE "Server name:"~z/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDxAS * $VERSION 1.01 (31-12-2006 16:01) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended AS HUD that uses the Nexgen HUD to render the messages. * **************************************************************************************************/ class NexgenHUDxAS extends AssaultHUD; struct SavedMessage { // Structure used for buffered messages. var string msg; // Message string. var name msgType; // Type of the message. var PlayerReplicationInfo pri1; // Related player information 1. var PlayerReplicationInfo pri2; // Related player information 2. }; var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). var float lastCheck; // Last time we checked if the NexgenHUD is available. var SavedMessage savedMessages[10]; // Messages received before the NexgenHUD was available. var int savedMsgCount; // Number of messages saved. /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the parent class * and the renderMessageBox() function on the NexgenHUD if it is available. When the * NexgenHUD is not available an attempt is made to locate it. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function postRender(Canvas c) { super.postRender(c); if (nscHUD == none) { setNexgenHUD(); } else { nscHUD.renderMessageBox(c); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { super.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { super.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the NexgenHUD instance. Once the HUD has been located any saved * messages will be restored. To save processing resources the attemps will have a * minimum interval of 0.2 seconds. * $REQUIRE nscHUD == none * $ENSURE nscHUD != none ? savedMsgCount == 0 : true * **************************************************************************************************/ simulated function setNexgenHUD() { local int index; if (level.timeSeconds - lastCheck >= 0.2) { // Locate NexgenHUD instance. lastCheck = level.timeSeconds; foreach allActors(class'NexgenHUD', nscHUD) { if (nscHUD != none) { break; } } // Restore saved messages. if (nscHUD != none) { for (index = 0; index < savedMsgCount; index++) { nscHUD.message(savedMessages[index].msg, savedMessages[index].msgType, savedMessages[index].pri1, savedMessages[index].pri2); } savedMsgCount = 0; } } } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int index; if (nscHUD == none) { // Buffer the message. if (savedMsgCount < arrayCount(savedMessages)) { index = savedMsgCount; savedMsgCount++; } else { for (index = 1; index < savedMsgCount; index++) { savedMessages[index - 1] = savedMessages[index]; } savedMsgCount = savedMsgCount - 1; } savedMessages[index].msg = msg; savedMessages[index].msgType = msgType; savedMessages[index].pri1 = pri1; savedMessages[index].pri2 = pri2; } else { // Pass it to the Nexgen HUD. nscHUD.message(msg, msgType, pri1, pri2); } } tEy6B 6 uEH:>&:>&ElElEl:>&u&OB/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUDWrapper * $VERSION 1.02 (6-4-2008 11:46) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION HUD Wrapper class. Used to support the Nexgen message HUD with custom HUDs. This * class simply passes all calls to the original HUD, except in the cases where the * Nexgen message HUD kicks in. * **************************************************************************************************/ class NexgenHUDWrapper extends ChallengeHUD; var ChallengeHUD originalHUD; // Original HUD. var NexgenHUD nscHUD; // The Nexgen HUD instance (which will do the rendering). /*************************************************************************************************** * * $DESCRIPTION Initializes the HUD wrapper. * $PARAM originalHUD The original HUD that was used by the player. * $PARAM nscHUD The Nexgen message HUD. * $REQUIRE originalHUD != none && nscHUD != none * **************************************************************************************************/ function initialize(ChallengeHUD originalHUD, NexgenHUD nscHUD) { local int index; // Copy control variables. self.originalHUD = originalHUD; self.nscHUD = nscHUD; playerOwner = originalHUD.playerOwner; // Clear messages. for (index = 0; index < arrayCount(shortMessageQueue); index++) { originalHUD.message(none, "", ''); } for (index = 0; index < arrayCount(localMessages); index++) { originalHUD.localizedMessage(class'NexgenNullMessage'); } } /*************************************************************************************************** * * $DESCRIPTION Prepares the system for the HUD render phase. Probably never used. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated event preRender(Canvas c) { if (originalHUD != none) originalHUD.preRender(c); } /*************************************************************************************************** * * $DESCRIPTION Renders the HUD. It will simply call the postRender() function of the original HUD * and also calls the renderMessageBox() function on the NexgenHUD. * $PARAM c The canvas object on which the rendering will be done. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated event postRender(Canvas c) { local Console cons; local bool bWasTyping; if (originalHUD != none) { // Copy HUD settings. originalHUD.bHideHUD = bHideHUD; originalHUD.bHideAllWeapons = bHideAllWeapons; originalHUD.bHideStatus = bHideStatus; originalHUD.bHideAmmo = bHideAmmo; originalHUD.bHideTeamInfo = bHideTeamInfo; originalHUD.bHideFrags = bHideFrags; originalHUD.bUseTeamColor = bUseTeamColor; originalHUD.opacity = opacity; originalHUD.hudScale = hudScale; originalHUD.weaponScale = weaponScale; originalHUD.statusScale = statusScale; originalHUD.favoriteHUDColor = favoriteHUDColor; originalHUD.crosshairColor = CrosshairColor; originalHUD.hudMutator = hudMutator; // Save data & fool the original HUD. cons = playerOwner.player.console; bWasTyping = cons.bTyping; cons.bTyping = false; originalHUD.bHideFaces = true; // Let the original HUD render it's stuff. originalHUD.postRender(c); // Restore data. cons.bTyping = bWasTyping; } nscHUD.renderMessageBox(c); } /*************************************************************************************************** * * $DESCRIPTION Called when the player switches to the specified weapon group. Doesn't appear to * be used anywhere. * $PARAM f The number of the weapon group to which the player is about to switch. * $OVERRIDE * **************************************************************************************************/ simulated function inputNumber(byte f) { if (originalHUD != none) originalHUD.inputNumber(f); } /*************************************************************************************************** * * $DESCRIPTION Changes the HUD mode. Not used in Unreal Tournament. * $PARAM d Number to add to the HUD mode number (delta). * $OVERRIDE * **************************************************************************************************/ simulated function changeHud(int d) { if (originalHUD != none) originalHUD.changeHud(d); } /*************************************************************************************************** * * $DESCRIPTION Changes the crosshair to use. * $PARAM d Number to add to the crosshair number (delta). * $OVERRIDE * **************************************************************************************************/ simulated function changeCrosshair(int d) { if (originalHUD != none) originalHUD.changeCrosshair(d); } /*************************************************************************************************** * * $DESCRIPTION Renders the crosshair on the screen. * $PARAM c The canvas object on which the rendering will be done. * $PARAM startX Horizontal offset. * $PARAM startX Vertical offset. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ simulated function drawCrossHair(Canvas c, int startX, int startY) { if (originalHUD != none) originalHUD.drawCrossHair(c, startX, startY); } /*************************************************************************************************** * * $DESCRIPTION Displays a new message on the screen. * $PARAM pri Information about the player that is related with this message. * $PARAM msg String containing the message to be displayed. * $PARAM msgType Type of the message. * $OVERRIDE * **************************************************************************************************/ simulated function message(PlayerReplicationInfo pri, coerce string msg, name msgType) { local bool bHandleByParent; // Check class responsible for this message. bHandleByParent = msgType == 'CriticalEvent'; // Handle message. if (bHandleByParent) { if (originalHUD != none) originalHUD.message(pri, msg, msgType); } else { addMessage(msg, msgType, pri, none); } } /*************************************************************************************************** * * $DESCRIPTION Displays a new localized message on the screen. * $PARAM message Class used to construct the localized message string. * $PARAM switch Message selection switch number. * $PARAM relatedPRI_1 First player that is related to this message. * $PARAM relatedPRI_2 Second player that is related to this message. * $PARAM optionalObject Object involved in the construction of the message string. * $PARAM criticalString Critical message string. * $OVERRIDE * **************************************************************************************************/ simulated function localizedMessage(class message, optional int switch, optional PlayerReplicationInfo relatedPRI_1, optional PlayerReplicationInfo relatedPRI_2, optional Object optionalObject, optional string criticalString) { local bool bHandleByParent; local string msgStr; // Check class responsible for this message. bHandleByParent = message.default.bIsSpecial; // Handle message. if (bHandleByParent) { if (originalHUD != none) originalHUD.localizedMessage(message, switch, relatedPRI_1, relatedPRI_2, optionalObject, criticalString); } else { // Get message string. if (message.default.bComplexString) { msgStr = criticalString; } else { msgStr = message.static.getString(switch, relatedPRI_1, relatedPRI_2, optionalObject); } // Add the message. addMessage(msgStr, '', relatedPRI_1, relatedPRI_2); } } /*************************************************************************************************** * * $DESCRIPTION Displays the specified message. Doesn't appear to be used. * $PARAM s The message to display. * $PARAM pName Name of the player that created the message? * $PARAM pZone Location of the player that created the message? * $OVERRIDE * **************************************************************************************************/ simulated function playReceivedMessage(string s, string pName, ZoneInfo pZone) { if (originalHUD != none) originalHUD.playReceivedMessage(s, pName, pZone); } /*************************************************************************************************** * * $DESCRIPTION Checks whether this HUD is responsible for displaying messages. * $RETURN True if this HUD handles the messages instead of the console. * $ENSURE result == true * $OVERRIDE * **************************************************************************************************/ simulated function bool displayMessages(Canvas c) { return true; } /*************************************************************************************************** * * $DESCRIPTION Called by the engine when a key, mouse, or joystick button is pressed or released, * or any analog axis movement is processed. * $PARAM key The key that was involved. * $PARAM action The action that was taken on the involved key. * $PARAM delta Amount of time elapsed/used for the action. * $OVERRIDE * **************************************************************************************************/ function bool processKeyEvent(int key, int action, float delta) { if (originalHUD != none) return originalHUD.processKeyEvent(key, action, delta); return false; } /*************************************************************************************************** * * $DESCRIPTION Sets the location where the player took damage. * $PARAM hitLoc The location where the player was hit. * $PARAM damage The amount of damage taken by the player. * $OVERRIDE * **************************************************************************************************/ function setDamage(vector hitLoc, float damage) { if (originalHUD != none) originalHUD.setDamage(hitLoc, damage); } /*************************************************************************************************** * * $DESCRIPTION Draws the typing prompt on the specified canvas. * $PARAM canv The canvas on which the typing prompt should be rendered. * $PARAM cons Console containing the typed message. * $OVERRIDE * **************************************************************************************************/ simulated function drawTypingPrompt(Canvas canv, Console cons) { // Suppress! This is taken care of in NexgenHUD.renderMessageBox(). } /*************************************************************************************************** * * $DESCRIPTION Adds a new message to display. If the message can't be added directly because the * NexgenHUD object hasn't been set, the message will be buffered. * $PARAM msg String containing the message to add. * $PARAM msgType Type of the message. * $PARAM pri1 First player that is related to this message. * $PARAM pri2 Second player that is related to this message. * **************************************************************************************************/ simulated function addMessage(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { if (nscHUD != none) nscHUD.message(msg, msgType, pri1, pri2); } /*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHUD * $VERSION 1.19 (6-4-2008 16:31) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen HUD extension class. * **************************************************************************************************/ class NexgenHUD extends Mutator; #exec OBJ LOAD FILE=..\Textures\LadrStatic.utx PACKAGE=Botpack.LadrStatic #exec TEXTURE IMPORT NAME=base FILE=Resources\base.pcx GROUP="GFX" FLAGS=2 MIPS=OFF #exec TEXTURE IMPORT NAME=grad32 FILE=Resources\grad32.pcx GROUP="GFX" FLAGS=2 MIPS=OFF #exec TEXTURE IMPORT NAME=grad64 FILE=Resources\grad64.pcx GROUP="GFX" FLAGS=2 MIPS=OFF #exec TEXTURE IMPORT NAME=playerIcon FILE=Resources\PlayerIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=playerIcon2 FILE=Resources\PlayerIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=serverIcon FILE=Resources\ServerIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=serverIcon2 FILE=Resources\ServerIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=offlineIcon FILE=Resources\OfflineIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=offlineIcon2 FILE=Resources\OfflineIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=waitIcon FILE=Resources\WaitIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=waitIcon2 FILE=Resources\WaitIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=specIcon FILE=Resources\SpecIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=specIcon2 FILE=Resources\SpecIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=shieldIcon FILE=Resources\ShieldIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=shieldIcon2 FILE=Resources\ShieldIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=idleIcon FILE=Resources\IdleIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=idleIcon2 FILE=Resources\IdleIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=mutedIcon FILE=Resources\MutedIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=mutedIcon2 FILE=Resources\MutedIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=matchIcon FILE=Resources\MatchIcon.pcx GROUP="GFX" FLAGS=3 MIPS=OFF #exec TEXTURE IMPORT NAME=matchIcon2 FILE=Resources\MatchIcon2.pcx GROUP="GFX" FLAGS=3 MIPS=OFF var NexgenClient client; // Client owning this HUD. var float lastSetupTime; // Last time setup() was called. var Font baseFont; // Base font to use for rendering text. var Color blankColor; // White color (#FFFFFF). var Color baseHUDColor; // Base color of the HUD (background color). var Color baseColors[6]; // Base colors available for the HUD. var Color colors[11]; // List of colors for text. var float baseFontHeight; // Height of the base font. struct MessageInfo { // Structure for storing message information. var string text[5]; // Message text list. var int col[5]; // Message text colors. var float timeStamp; // Time at which the message was received. }; struct PanelInfo { // Panel info container structure. var string text; // Text displayed on the panel. var Color textCol; // Color of the text to display. var Texture icon; // Icon displayed in front of the text. var Texture solidIcon; // Solid version of the icon. var bool bBlink; // Indicates if the text should 'blink'. }; var MessageInfo chatMessages[3]; // List of chat messages. var MessageInfo messages[5]; // List of all other messages. var int chatMsgCount; // Number of chat messages stored in the list. var int msgCount; // Number of other messages stored. var Texture faceImg; // Face texture to display in the chat message box. var float msgBoxWidth; // Width of the message box. var float msgBoxLineHeight; // Height of a line in the message box. var float msgBoxHeight; // Total height of the message box. var float minPanelWidth; // Minimum size of the panel. var bool bFlashMessages; // Whether new messages should flash. var float lastResX; // Horizontal resolution at last setup call. var float lastResY; // Vertical resolution at last setup call. var byte lastTeam; // Team number at last setup call. var float lastLevelTimeSeconds; // Last value of level.time seconds. var float timeSeconds; // Gamespeed independent timeSeconds, that keeps counting // even when the game is paused. var bool bShowPlayerLocation; // Show player location name in teamsay messages? const iconSize = 24.0; // Size of the status icons. const chatMessageLifeTime = 16.0; // The amount of time a chat message is diplayed (in sec). const messageLifeTime = 12.0; // Amount of time any other message is displayed (in sec). const messageBlinkTime = 4.0; // How long a message is highlighted (in sec). const messageBlinkRate = 4.0; // Message highlight blink rate (in Hz). const panelBlinkRate = 2.0; // Panel text highlight blink rate (in Hz). const blinkColorDamp = 0.70; // Dampening factor for blinking text. const connectionAlertDelay = 2; // Time to wait before showing the bad connection alert. const secPerMinute = 60; // Number of seconds per minute -- duh! const matchInfoSwitchTime = 4; // Number of seconds to wait before switching between time // remaining and match num. // Alert window settings. const hDefBarSize = 20; // Animated horizontal bar size. const alertAnimTime = 0.5; // Animation cycle time. const alertAnimDist = 64; // Distance the animated bar moves away from the window. const alertBorderSize = 32; // Distance between borders and text of the window. const newLineToken = "\\n"; // Token used to break the text in multiple lines. // Colors. const C_RED = 0; const C_BLUE = 1; const C_GREEN = 2; const C_YELLOW = 3; const C_WHITE = 4; const C_BLACK = 5; const C_PINK = 6; const C_CYAN = 7; const C_METAL = 8; const C_ORANGE = 9; // Server states. const SS_Offline = 'ssoffline'; // Connection with server is failing. const SS_Waiting = 'sswaiting'; // Server is waiting for players. const SS_Ready = 'ssready'; // Game is ready to start. const SS_Starting = 'ssstaring'; // Game is counting down to start. const SS_Ended = 'ssended'; // Game is ended. const SS_Paused = 'sspaused'; // Game is paused. const SS_Match = 'ssmatch'; // A match is in progress. const SS_Normal = 'ssnormal'; // A normal game is in progress. // Client states. const CS_Login = 'cslogin'; // Client is logging in. const CS_Idle = 'csidle'; // Client is idle or camping. const CS_Protected = 'csprotected'; // Client is (damage) protected. const CS_Muted = 'csmuted'; // Client is muted. const CS_Dead = 'csdead'; // Client is dead. const CS_Normal = 'csnormal'; // Client is in normal state. /*************************************************************************************************** * * $DESCRIPTION Initializes the extended HUD. * $REQUIRE owner != none && owner.isA('NexgenClient') * $ENSURE client != none * $OVERRIDE * **************************************************************************************************/ function postBeginPlay() { client = NexgenClient(owner); registerHUDMutator(); bFlashMessages = client.gc.get(client.SSTR_FlashMessages, "true") ~= "true"; bShowPlayerLocation = client.gc.get(client.SSTR_ShowPlayerLocation, "true") ~= "true"; } /*************************************************************************************************** * * $DESCRIPTION Renders the extended Nexgen HUD. * $PARAM c Canvas object that provides the drawing capabilities. * $REQUIRE c != none * $OVERRIDE * **************************************************************************************************/ function postRender(Canvas c) { local float badConnectionTime; local int timeRemaining; // Let other HUD mutators do their job first. if (nextHUDMutator != none) { nextHUDMutator.postRender(c); } // Render alerts. setup(c); badConnectionTime = client.timeSeconds - client.badConnectionSince; if (client.bBadConnectionDetected && client.sConf.autoReconnectTime > 0 && (badConnectionTime > connectionAlertDelay || client.gInf.rebootCountDown > 0)) { // Connection lost alert. timeRemaining = client.sConf.autoReconnectTime - badConnectionTime + 1; if (timeRemaining > 0) { renderAlert(c, client.lng.format(client.lng.autoReconnectAlert, timeRemaining), colors[C_RED], colors[C_RED]); } else { renderAlert(c, client.lng.reconnectingAlert, colors[C_RED], colors[C_RED]); } } else if (client.gInf.rebootCountDown > 0) { // Reboot warning. timeRemaining = client.gInf.rebootCountDown; renderAlert(c, client.lng.format(client.lng.rebootAlert, timeRemaining), colors[C_WHITE], baseHUDColor); } else if (client.idleTimeRemaining >= 0 && client.idleTimeRemaining <= client.idleTimeWarning) { // Idle warning. timeRemaining = client.idleTimeRemaining; renderAlert(c, client.lng.format(client.lng.idleAlert, timeRemaining), colors[C_WHITE], baseHUDColor); } } /*************************************************************************************************** * * $DESCRIPTION Renders an alert window. * $PARAM msg The message to display on the alert window. * $PARAM textColor Color of the text displayed on the alert window. * $PARAM baseColor Background color of the alert window. * **************************************************************************************************/ simulated function renderAlert(Canvas c, string msg, color textColor, color baseColor) { local int windowWidth; local int windowHeight; local int cx, cy; local float animIndex; local int dist; local int hBarSize; local float textWidth; local int maxTextWidth; local float textHeight; local int lineCount; local string remaining; local int index; local string text; // Initialize. c.font = ChallengeHUD(c.viewport.actor.myHUD).myFonts.getStaticHugeFont(c.clipX); remaining = msg; lineCount = 0; while (remaining != "") { index = instr(remaining, newLineToken); if (index > 0) { text = left(remaining, index); remaining = mid(remaining, index + len(newLineToken)); } else { text = remaining; remaining = ""; } c.strLen(text, textWidth, textHeight); maxTextWidth = max(maxTextWidth, textWidth); lineCount++; } windowWidth = maxTextWidth + 2 * alertBorderSize; windowHeight = lineCount * textHeight + 2 * alertBorderSize; cx = (c.clipX - windowWidth) / 2; cy = (c.clipY - windowHeight) / 2; // Render frame background. c.style = ERenderStyle.STY_Translucent; c.drawColor = baseColor * 0.4; c.setPos(cx, cy); c.drawTile(Texture'grad64', windowWidth, windowHeight, 0.0, 0.0, 64.0, 64.0); // Render borders. c.drawColor = baseColor * 0.8; c.setPos(cx - 3.0, cy - 1.0); c.drawTile(Texture'base', 2.0, windowHeight + 2.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 1.0 + windowWidth, cy - 1.0); c.drawTile(Texture'base', 2.0, windowHeight + 2.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx - 3.0, cy - 2.0); c.drawTile(Texture'base', hDefBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx - 3.0, cy + 1.0 + windowHeight); c.drawTile(Texture'base', hDefBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 3.0 + windowWidth - hDefBarSize, cy - 2.0); c.drawTile(Texture'base', hDefBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 3.0 + windowWidth - hDefBarSize, cy + 1.0 + windowHeight); c.drawTile(Texture'base', hDefBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); // High detail animation effect. if (level.bHighDetailMode) { animIndex = (client.timeSeconds % alertAnimTime) / alertAnimTime; c.drawColor = baseColor * (1.0 - animIndex); dist = sin(animIndex * pi * 0.5) * alertAnimDist; hBarSize = hDefBarSize + hDefBarSize * ((windowWidth + alertAnimDist) / windowWidth) * animIndex; c.setPos(cx - 3.0 - dist, cy - 1.0 - dist); c.drawTile(Texture'base', 2.0, windowHeight + 2.0 + 2 * dist, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 1.0 + windowWidth + dist, cy - 1.0 - dist); c.drawTile(Texture'base', 2.0, windowHeight + 2.0 + 2 * dist, 0.0, 0.0, 1.0, 1.0); c.setPos(cx - 3.0 - dist, cy - 2.0 - dist); c.drawTile(Texture'base', hBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx - 3.0 - dist, cy + 1.0 + windowHeight + dist); c.drawTile(Texture'base', hBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 3.0 + windowWidth - hBarSize + dist, cy - 2.0 - dist); c.drawTile(Texture'base', hBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(cx + 3.0 + windowWidth - hBarSize + dist, cy + 1.0 + windowHeight + dist); c.drawTile(Texture'base', hBarSize, 1.0, 0.0, 0.0, 1.0, 1.0); } // Render text. remaining = msg; lineCount = 0; c.drawColor = textColor; while (remaining != "") { index = instr(remaining, newLineToken); if (index > 0) { text = left(remaining, index); remaining = mid(remaining, index + len(newLineToken)); } else { text = remaining; remaining = ""; } c.setPos(cx + alertBorderSize, cy + alertBorderSize + lineCount * textHeight); c.drawText(text, false); lineCount++; } } /*************************************************************************************************** * * $DESCRIPTION Adds a message to the message HUD. * $PARAM msg The message that is to be displayed. * $PARAM msgType Message type identifier. * $PARAM pri1 Replication info of the first player involved. * $PARAM pri2 Replication info of the second player involved. * **************************************************************************************************/ simulated function message(string msg, name msgType, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local int playerColor; local int messageColor; local bool bIsSpecSayMsg; local PlayerReplicationInfo specPRI; local GameReplicationInfo gri; local int index; local string locationName; // Check if the message was send by a spectator using say. if (msgType == 'Event' && instr(msg, ":") >= 0) { // Get shortcut to the game replication info. gri = client.player.gameReplicationInfo; // Find a player. while (index < arrayCount(gri.PRIArray) && gri.PRIArray[index] != none) { if (gri.PRIArray[index].bIsSpectator && left(msg, len(gri.PRIArray[index].playerName) + 1) ~= (gri.PRIArray[index].playerName $ ":")) { if (bIsSpecSayMsg) { if (len(gri.PRIArray[index].playerName) > len(pri1.playerName)) { pri1 = gri.PRIArray[index]; } } else { bIsSpecSayMsg = true; pri1 = gri.PRIArray[index]; } } index++; } } // Check message type. if (bIsSpecSayMsg) { // Chat message. Special case: player is spec and using say (not teamsay). if (pri1.talkTexture != none) { faceImg = pri1.talkTexture; } addChatMsg(C_METAL, pri1.playerName $ ": ", C_METAL, mid(msg, len(pri1.playerName) + 1)); } else if (pri1 != none && msg != "" && (msgType == 'Say' || msgType == 'TeamSay')) { // Chat message. playerColor = getPlayerColor(pri1); if (pri1.talkTexture != none) { faceImg = pri1.talkTexture; } if (msgType == 'TeamSay') { if (pri1.bIsSpectator && !pri1.bWaitingPlayer) { messageColor = C_WHITE; } else { messageColor = playerColor; } if (!pri1.bIsSpectator) { if (pri1.playerLocation != none) { locationName = pri1.playerLocation.locationName; } else if (pri1.playerZone != none) { locationName = pri1.playerZone.zoneName; } } } else { if (pri1.bIsSpectator && !pri1.bWaitingPlayer) { messageColor = C_METAL; } else { messageColor = C_ORANGE; } } if (locationName != "" && bShowPlayerLocation) { addChatMsg(playerColor, pri1.playerName, C_CYAN, " (" $ locationName $ "): ", messageColor, msg); } else { addChatMsg(playerColor, pri1.playerName $ ": ", messageColor, msg); } } else if (msg != "") { // Other message. addColorizedMessage(msg, pri1, pri2); } } /*************************************************************************************************** * * $DESCRIPTION Adds a message to the area just below the chatbox. Before the message is added an * attempt will be made to highlight player names. This is done by checking if the * messages contain the names of the given player replication info objects. * $PARAM msg Message to add. * $PARAM pri1 Replication info of the first player involved. * $PARAM pri2 Replication info of the second player involved. * **************************************************************************************************/ simulated function addColorizedMessage(string msg, PlayerReplicationInfo pri1, PlayerReplicationInfo pri2) { local string firstPlayerName; local string secondPlayerName; local int firstIndex; local int secondIndex; local int firstPlayerColor; local int secondPlayerColor; local string msgPart1; local string msgPart2; local string msgPart3; local int msgColor; local string tempPlayerName; local int tempIndex; local int tempPlayerColor; // Get message color. msgColor = class'NexgenUtil'.static.getMessageColor(msg); if (msgColor < 0) { msgColor = C_ORANGE; } msg = class'NexgenUtil'.static.removeMessageColorTag(msg); // Get player name indices. getPlayerNameIndices(msg, pri1, pri2, firstIndex, secondIndex); // Get player names & colors. if (pri1 != none) { firstPlayerName = pri1.playerName; firstPlayerColor = getPlayerColor(pri1); } if (pri2 != none) { secondPlayerName = pri2.playerName; secondPlayerColor = getPlayerColor(pri2); } // Swap first and second player if necessary. if (secondIndex >= 0 && (secondIndex < firstIndex || firstIndex < 0)) { tempPlayerName = secondPlayerName; tempIndex = secondIndex; tempPlayerColor = secondPlayerColor; secondPlayerName = firstPlayerName; secondIndex = firstIndex; secondPlayerColor = firstPlayerColor; firstPlayerName = tempPlayerName; firstIndex = tempIndex; firstPlayerColor = tempPlayerColor; } // Split message. if (firstIndex >= 0 && secondIndex >= 0) { msgPart1 = left(msg, firstIndex); msgPart2 = mid(msg, firstIndex + len(firstPlayerName), secondIndex - firstIndex - len(firstPlayerName)); msgPart3 = mid(msg, secondIndex + len(secondPlayerName)); } else if (firstIndex >= 0) { msgPart1 = left(msg, firstIndex); msgPart2 = mid(msg, firstIndex + len(firstPlayerName)); secondPlayerName = ""; } else { firstPlayerName = ""; secondPlayerName = ""; msgPart1 = msg; } // Add message. addMsg(msgColor, msgPart1, firstPlayerColor, firstPlayerName, msgColor, msgPart2, secondPlayerColor, secondPlayerName, msgColor, msgPart3); } /*************************************************************************************************** * * $DESCRIPTION Attemps to locate the indices of player names in the given message. To speed up * the locating process you can pass the player replication info actors of the * players that are most likely to be included in the message. * $PARAM msg The message which may contain player names. * $PARAM pri1 Replication info of the first player involved. * $PARAM pri2 Replication info of the second player involved. * $PARAM index1 The location in the string where the first player name occurs. * $PARAM index2 The location in the string where the second player name occurs. * $ENSURE (index1 >= 0 ? pri1 != none : true) && (index2 >= 0 ? pri2 != none : true) * **************************************************************************************************/ simulated function getPlayerNameIndices(string msg, out PlayerReplicationInfo pri1, out PlayerReplicationInfo pri2, out int index1, out int index2) { local PlayerReplicationInfo tmpPRI; local GameReplicationInfo gri; local int index; local int nameIndex; local int tmpIndex; // Get shortcut to the game replication info. gri = client.player.gameReplicationInfo; // Initially no indices have been found. index1 = -1; index2 = -1; // Check if the first PRI is actually in the message. This appears not to be the case for some // messages (for example with the Stranglove weapon mod). if (pri1 != none && instr(msg, pri1.playerName) < 0) { pri1 = none; } // Swap player replication info's if needed. if (pri1 == none && pri2 != none) { pri1 = pri2; pri2 = none; } else if (pri1 != none && pri2 != none && len(pri2.playerName) > len(pri1.playerName)) { // Ensure the longest playername is located first. tmpPRI = pri1; pri1 = pri2; pri2 = tmpPRI; } // Get the position of the first player name in the message. if (pri1 == none) { // No PRI found, try to find one. index = 0; while (index < arrayCount(gri.PRIArray) && gri.PRIArray[index] != none) { // Get current player replication info. tmpPRI = gri.PRIArray[index]; // Get position of the players name in the message. nameIndex = instr(msg, tmpPRI.playerName); // Select PRI? if (nameIndex >= 0 && (pri1 == none || len(tmpPRI.playerName) > len(pri1.playerName))) { // Yes, no name has been found so far or a longer player name has been found. pri1 = tmpPRI; index1 = nameIndex; } // Continue with next player name. index++; } } else { // Already got PRI, just find the index of the name. index1 = instr(msg, pri1.playerName); } // Get the position of the second player name in the message. if (pri1 != none && pri2 == none) { // No PRI found, try to find one. index = 0; while (index < arrayCount(gri.PRIArray) && gri.PRIArray[index] != none) { // Get current player replication info. tmpPRI = gri.PRIArray[index]; // Get position of the players name in the message. nameIndex = instr(msg, tmpPRI.playerName); // Check for overlap. if (index1 >=0 && nameIndex >= 0 && index1 <= nameIndex && nameIndex < index1 + len(pri1.playerName)) { // Overlap detected, check if name occurs after the first player name. nameIndex = instr(mid(msg, index1 + len(pri1.playerName)), tmpPRI.playerName); if (nameIndex >= 0) { nameIndex += index1 + len(pri1.playerName); } } // Select PRI? if (nameIndex >= 0 && (pri2 == none || len(tmpPRI.playerName) > len(pri2.playerName))) { // Yes, no name has been found so far or a longer player name has been found. pri2 = tmpPRI; index2 = nameIndex; } // Continue with next player name. index++; } } else if (pri2 != none) { // Already got PRI, just find the index of the name. nameIndex = instr(msg, pri2.playerName); // Check for overlap. if (index1 >= 0 && nameIndex >= 0 && index1 <= nameIndex && nameIndex < index1 + len(pri1.playerName)) { // Overlap detected, check if name occurs after the first player name. nameIndex = instr(mid(msg, index1 + len(pri1.playerName)), pri2.playerName); if (nameIndex >= 0) { nameIndex += index1 + len(pri1.playerName); } } // Set index. index2 = nameIndex; } } /*************************************************************************************************** * * $DESCRIPTION Adds a message to the chatbox. The message is split in several parts, so each can * be displayed in a specified color. * $PARAM col1 Color of the first part of the message. * $PARAM text1 First part of the message. * $PARAM col2 Color of the second part of the message. * $PARAM text2 Second part of the message. * $PARAM col3 Color of the third part of the message. * $PARAM text3 Third part of the message. * $PARAM col4 Color of the fourth part of the message. * $PARAM text4 Fourth part of the message. * $PARAM col5 Color of the fifth part of the message. * $PARAM text5 Fifth part of the message. * **************************************************************************************************/ simulated function addChatMsg(int col1, string text1, optional int col2, optional string text2, optional int col3, optional string text3, optional int col4, optional string text4, optional int col5, optional string text5) { local int index; // Find position in messages list. if (chatMsgCount < arrayCount(chatMessages)) { index = chatMsgCount; chatMsgCount++; } else { // List is full, shift messages. for (index = 1; index < chatMsgCount; index++) { chatMessages[index - 1] = chatMessages[index]; } index = chatMsgCount - 1; } // Store message. chatMessages[index].text[0] = text1; chatMessages[index].text[1] = text2; chatMessages[index].text[2] = text3; chatMessages[index].text[3] = text4; chatMessages[index].text[4] = text5; chatMessages[index].col[0] = col1; chatMessages[index].col[1] = col2; chatMessages[index].col[2] = col3; chatMessages[index].col[3] = col4; chatMessages[index].col[4] = col5; chatMessages[index].timeStamp = timeSeconds; } /*************************************************************************************************** * * $DESCRIPTION Adds a message to the area below the chatbox. The message is split in several * parts, so each can be displayed in a specified color. * $PARAM col1 Color of the first part of the message. * $PARAM text1 First part of the message. * $PARAM col2 Color of the second part of the message. * $PARAM text2 Second part of the message. * $PARAM col3 Color of the third part of the message. * $PARAM text3 Third part of the message. * $PARAM col4 Color of the fourth part of the message. * $PARAM text4 Fourth part of the message. * $PARAM col5 Color of the fifth part of the message. * $PARAM text5 Fifth part of the message. * **************************************************************************************************/ simulated function addMsg(int col1, string text1, optional int col2, optional string text2, optional int col3, optional string text3, optional int col4, optional string text4, optional int col5, optional string text5) { local int index; // Find position in messages list. if (msgCount < arrayCount(messages)) { index = msgCount; msgCount++; } else { // List is full, shift messages. for (index = 1; index < msgCount; index++) { messages[index - 1] = messages[index]; } index = msgCount - 1; } // Store message. messages[index].text[0] = text1; messages[index].text[1] = text2; messages[index].text[2] = text3; messages[index].text[3] = text4; messages[index].text[4] = text5; messages[index].col[0] = col1; messages[index].col[1] = col2; messages[index].col[2] = col3; messages[index].col[3] = col4; messages[index].col[4] = col5; messages[index].timeStamp = timeSeconds; } /*************************************************************************************************** * * $DESCRIPTION Initializes/updates the variables used in the rendering procedure. * $PARAM c Canvas object that provides the drawing capabilities. * $REQUIRE c != none * $ENSURE c.font != none * **************************************************************************************************/ simulated function setup(Canvas c) { local int index; local bool bUpdateBase; // Make sure the font ain't none. if (baseFont == none) baseFont = Font'SmallFont'; c.font = baseFont; // Prevent redundant setups. if (lastSetupTime == level.timeSeconds) { return; } // Timer control. timeSeconds += (level.timeSeconds - lastLevelTimeSeconds) / level.timeDilation; lastLevelTimeSeconds = level.timeSeconds; // Check if the base variables need to be updated. bUpdateBase = lastResX != c.clipX || lastResY != c.clipY || lastTeam != client.player.playerReplicationInfo.team; // Update HUD base variables. if (bUpdateBase) { // General variables. baseFont = ChallengeHUD(c.viewport.actor.myHUD).myFonts.getStaticSmallestFont(c.clipX); c.font = baseFont; c.strLen("Online [00:00]", minPanelWidth, baseFontHeight); if (client.player.playerReplicationInfo.bIsSpectator && !client.player.playerReplicationInfo.bWaitingPlayer) { index = 4; } else if (0 <= client.player.playerReplicationInfo.team && client.player.playerReplicationInfo.team <= 3) { index = client.player.playerReplicationInfo.team; } else { index = 5; } baseHUDColor = baseColors[index]; lastResX = c.clipX; lastResY = c.clipY; lastTeam = client.player.playerReplicationInfo.team; // Message box info. msgBoxWidth = int(c.clipX * 0.75); msgBoxLineHeight = int(baseFontHeight + 4.0); msgBoxHeight = msgBoxLineHeight * arrayCount(chatMessages); } // Remove expired messages. if (chatMsgCount > 0 && timeSeconds - chatMessages[0].timeStamp > chatMessageLifeTime) { for (index = 1; index < chatMsgCount; index++) { chatMessages[index - 1] = chatMessages[index]; } chatMsgCount--; if (chatMsgCount == 0) { faceImg = none; } } if (msgCount > 0 && timeSeconds - messages[0].timeStamp > messageLifeTime) { for (index = 1; index < msgCount; index++) { messages[index - 1] = messages[index]; } msgCount--; } lastSetupTime = level.timeSeconds; } /*************************************************************************************************** * * $DESCRIPTION Renders the chat message box. * $PARAM c Canvas object that provides the drawing capabilities. * $REQUIRE c != none * **************************************************************************************************/ simulated function renderMessageBox(Canvas c) { local float panelWidth; local float panelHeight; local PanelInfo serverState; local PanelInfo clientState; local int index; local float cx; local float cy; // Initialize. setup(c); panelHeight = int((msgBoxHeight - 3.0) / 2.0); serverState = getServerState(); clientState = getClientState(); panelWidth = fMax(getPanelWidth(serverState, c, panelHeight), getPanelWidth(clientState, c, panelHeight)); // Background. c.style = ERenderStyle.STY_Translucent; c.drawColor = baseHUDColor * 0.4; c.setPos(1.0, 1.0); c.drawTile(Texture'grad64', msgBoxWidth - 2.0, msgBoxHeight - 2.0, 0.0, 0.0, 64.0, 64.0); // Borders. c.drawColor = baseHUDColor * 0.8; c.setPos(0.0, 0.0); c.drawTile(Texture'base', msgBoxWidth, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(0.0, msgBoxHeight - 1.0); c.drawTile(Texture'base', msgBoxWidth, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(msgBoxWidth - 1.0 - panelWidth, panelHeight + 1.0); c.drawTile(Texture'base', panelWidth, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(0.0, 1.0); c.drawTile(Texture'base', 1.0, msgBoxHeight - 2.0, 0.0, 0.0, 1.0, 1.0); c.setPos(msgBoxWidth - 1.0, 1.0); c.drawTile(Texture'base', 1.0, msgBoxHeight - 2.0, 0.0, 0.0, 1.0, 1.0); c.setPos(msgBoxHeight - 1.0, 1.0); c.drawTile(Texture'base', 1.0, msgBoxHeight - 2.0, 0.0, 0.0, 1.0, 1.0); c.setPos(msgBoxWidth - 2.0 - panelWidth, 1.0); c.drawTile(Texture'base', 1.0, msgBoxHeight - 2.0, 0.0, 0.0, 1.0, 1.0); // Panels. renderPanel(serverState, c, panelHeight, msgBoxWidth - panelWidth - 1.0, 1.0); renderPanel(clientState, c, panelHeight, msgBoxWidth - panelWidth - 1.0, panelHeight + 2.0); // Face image. if (faceImg != none) { c.style = ERenderStyle.STY_Normal; c.drawColor = blankColor; c.setPos(1.0, 1.0); c.drawTile(faceImg, msgBoxHeight - 2.0, msgBoxHeight - 2.0, 0.0, 0.0, faceImg.uSize, faceImg.vSize); c.style = ERenderStyle.STY_Translucent; c.drawColor = baseHUDColor * 0.25; c.setPos(1.0, 1.0); c.drawTile(Texture'LadrStatic.Static_a00', msgBoxHeight - 2.0, msgBoxHeight - 2.0, 0.0, 0.0, Texture'LadrStatic.Static_a00'.uSize, Texture'LadrStatic.Static_a00'.vSize); } // Typing prompt. if (client.player.player.console.bTyping) { renderTypingPromt(c, "(>" $ client.player.player.console.typedStr $ "_"); } // Chat messages. cx = msgBoxHeight + 2.0; cy = (msgBoxLineHeight - baseFontHeight) / 2.0; for (index = 0; index < chatMsgCount; index++) { renderMessage(c, cx, cy, chatMessages[index]); cy += msgBoxLineHeight; } // Other messages. cx = 1.0; cy = msgBoxHeight + 2.0; if (client.player.player.console.bTyping) { cy += msgBoxLineHeight; } for (index = 0; index < msgCount; index++) { renderMessage(c, cx, cy, messages[index]); cy += baseFontHeight; } } /*************************************************************************************************** * * $DESCRIPTION Renders the typing promt for the chat message box. * $PARAM c Canvas object that provides the drawing capabilities. * $REQUIRE c != none * **************************************************************************************************/ simulated function renderTypingPromt(Canvas c, string msg) { local float msgOffset; // Background. c.style = ERenderStyle.STY_Translucent; c.drawColor = baseHUDColor * 0.4; c.setPos(1.0, msgBoxHeight); c.drawTile(Texture'grad32', msgBoxWidth - 2.0, msgBoxLineHeight - 1.0, 0.0, 0.0, 32.0, 32.0); // Borders. c.drawColor = baseHUDColor * 0.8; c.setPos(0.0, msgBoxHeight + msgBoxLineHeight - 1.0); c.drawTile(Texture'base', msgBoxWidth, 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(0.0, msgBoxHeight); c.drawTile(Texture'base', 1.0, msgBoxLineHeight - 1.0, 0.0, 0.0, 1.0, 1.0); c.setPos(msgBoxWidth - 1.0, msgBoxHeight); c.drawTile(Texture'base', 1.0, msgBoxLineHeight - 1.0, 0.0, 0.0, 1.0, 1.0); // Message. msgOffset = (msgBoxLineHeight - baseFontHeight) / 2.0; c.font = baseFont; c.style = ERenderStyle.STY_Normal; c.drawColor = colors[C_WHITE]; c.setPos(msgOffset, msgOffset + msgBoxHeight); c.drawText(msg, false); } /*************************************************************************************************** * * $DESCRIPTION Renders the specified message. * $PARAM c Canvas object that provides the drawing capabilities. * $PARAM x Horizontal offset. * $PARAM y Vertical offset. * $PARAM msg The message that is to be rendered. * $REQUIRE c != none && msg != none * **************************************************************************************************/ simulated function renderMessage(Canvas c, float x, float y, MessageInfo msg) { local float cx; local int msgIndex; local float msgWidth; local float msgHeight; local float lifeTime; local float blinkFactor; local float blinkIntensity; // Check if the message should blink. lifeTime = (timeSeconds - msg.timeStamp); if (bFlashMessages && lifeTime < messageBlinkTime) { blinkFactor = (1.0 + cos(lifeTime * 2 * pi * messageBlinkRate)) / 2.0; blinkIntensity = (1.0 - blinkFactor) * 255.0; } // Render message. cx = x; c.font = baseFont; c.style = ERenderStyle.STY_Normal; for (msgIndex = 0; msgIndex < 5; msgIndex++) { c.setPos(cx, y); c.drawColor = colors[msg.col[msgIndex]]; if (bFlashMessages && lifeTime < messageBlinkTime) { c.drawColor = c.drawColor * blinkColorDamp; c.drawColor.r = int(float(c.drawColor.r) * blinkFactor + blinkIntensity); c.drawColor.g = int(float(c.drawColor.g) * blinkFactor + blinkIntensity); c.drawColor.b = int(float(c.drawColor.b) * blinkFactor + blinkIntensity); } c.drawText(msg.text[msgIndex], false); c.strLen(msg.text[msgIndex], msgWidth, msgHeight); cx += msgWidth; } } /*************************************************************************************************** * * $DESCRIPTION Retrieves the current state of the server. The result will be stored in a * PanelInfo struct so it can be immediately rendered. * $RETURN The current server state. * $ENSURE result != none * **************************************************************************************************/ simulated function PanelInfo getServerState() { local PanelInfo pInf; local string stateInfo; local int remainingTime; local int minutes, seconds; local name stateType; local byte bBlink; local int index; // Check current state. if (client.player.bBadConnectionAlert) { // Server is offline. stateType = SS_Offline; if (client.sConf.autoReconnectTime > 0) { stateInfo = string(max(0, 1 + client.sConf.autoReconnectTime - (client.timeSeconds - client.badConnectionSince))); pInf.text = client.lng.format(client.lng.offlineStateRCN, stateInfo); } else { pInf.text = client.lng.offlineState; } pInf.textCol = colors[C_RED]; pInf.icon = Texture'offlineIcon'; pInf.solidIcon = Texture'offlineIcon2'; } else if (client.gInf.gameState == client.gInf.GS_Waiting) { // Waiting for players. stateType = SS_Waiting; if (client.gInf.countDown <= 0 || !client.sConf.enableNexgenStartControl) { pInf.text = client.lng.waitingStateUnknownTime; } else { pInf.text = client.lng.format(client.lng.waitingState, client.gInf.countDown); } pInf.textCol = colors[C_RED]; pInf.icon = Texture'waitIcon'; pInf.solidIcon = Texture'waitIcon2'; } else if (client.gInf.gameState == client.gInf.GS_Ready) { // Ready to start the game. stateType = SS_Ready; if (client.gInf.bTournamentMode) { pInf.text = client.lng.format(client.lng.readySignalWaitState, client.gInf.numReady, client.gInf.numRequiredReady); } else { pInf.text = client.lng.readyState; } pInf.textCol = colors[C_ORANGE]; pInf.bBlink = true; pInf.icon = Texture'waitIcon'; pInf.solidIcon = Texture'waitIcon2'; } else if (client.gInf.gameState == client.gInf.GS_Starting) { // Game is starting. stateType = SS_Starting; pInf.text = client.lng.format(client.lng.startingState, client.gInf.countDown); pInf.textCol = colors[C_YELLOW]; pInf.bBlink = true; pInf.icon = Texture'waitIcon'; pInf.solidIcon = Texture'waitIcon2'; } else if (client.gInf.gameState == client.gInf.GS_Ended) { // Game has ended. stateType = SS_Ended; pInf.text = client.lng.endedState; pInf.textCol = colors[C_YELLOW]; pInf.icon = Texture'serverIcon'; pInf.solidIcon = Texture'serverIcon2'; } else if (level.pauser != "") { // Game has been paused. stateType = SS_Paused; pInf.text = client.lng.pausedState; pInf.textCol = colors[C_METAL]; pInf.bBlink = true; pInf.icon = Texture'offlineIcon'; pInf.solidIcon = Texture'offlineIcon2'; } else if (client.sConf.matchModeActivated) { // Match in progress. stateType = SS_Match; remainingTime = client.player.gameReplicationInfo.remainingTime ; if (remainingTime > 0 && (remainingTime / matchInfoSwitchTime) % 2 == 1) { minutes = remainingTime / secPerMinute; seconds = remainingTime % secPerMinute; stateInfo = right("0" $ minutes, 2) $ ":" $ right("0" $ seconds, 2); } else { stateInfo = client.sConf.currentMatch $ "/" $ client.sConf.matchesToPlay; } pInf.text = client.lng.format(client.lng.matchState, stateInfo); pInf.textCol = colors[C_YELLOW]; pInf.icon = Texture'matchIcon'; pInf.solidIcon = Texture'matchIcon2'; } else { // Game in progress. stateType = SS_Normal; remainingTime = client.player.gameReplicationInfo.remainingTime ; if (remainingTime > 0) { minutes = remainingTime / secPerMinute; seconds = remainingTime % secPerMinute; stateInfo = right("0" $ minutes, 2) $ ":" $ right("0" $ seconds, 2); } else { stateInfo = right("0" $ level.hour, 2) $ ":" $ right("0" $ level.minute, 2); } pInf.text = client.lng.format(client.lng.onlineState, stateInfo); pInf.textCol = colors[C_GREEN]; pInf.icon = Texture'serverIcon'; pInf.solidIcon = Texture'serverIcon2'; } // Allow plugins to modify the state panel. bBlink = byte(pInf.bBlink); while (index < arrayCount(client.clientCtrl) && client.clientCtrl[index] != none) { if (client.clientCtrl[index].bCanModifyHUDStatePanel) { client.clientCtrl[index].modifyServerState(stateType, pInf.text, pInf.textCol, pInf.icon, pInf.solidIcon, bBlink); } index++; } pInf.bBlink = bool(bBlink); // Return state panel. return pInf; } /*************************************************************************************************** * * $DESCRIPTION Retrieves the current state of the client. The result will be stored in a * PanelInfo struct so it can be immediately rendered. * $RETURN The current client state. * $ENSURE result != none * **************************************************************************************************/ simulated function PanelInfo getClientState() { local PanelInfo pInf; local string stateInfo; local byte protectTime; local name stateType; local byte bBlink; local int index; pInf.icon = Texture'playerIcon'; pInf.solidIcon = Texture'playerIcon2'; // Check current state. if (!client.loginComplete) { // Logging in to the server. stateType = CS_Login; pInf.text = client.lng.loginState; pInf.textCol = colors[C_WHITE]; } else if (client.idleTimeRemaining >= 0) { // Idle / camping. stateType = CS_Idle; stateInfo = string(client.idleTimeRemaining); pInf.text = client.lng.format(client.lng.idleState, stateInfo); pInf.textCol = colors[C_CYAN]; pInf.icon = Texture'idleIcon'; pInf.solidIcon = Texture'idleIcon2'; pInf.bBlink = true; } else if (client.spawnProtectionTime > 0 || client.tkDmgProtectionTime > 0 || client.tkPushProtectionTime > 0) { // Client is damage protected. stateType = CS_Protected; protectTime = max(max(client.spawnProtectionTime, client.tkDmgProtectionTime), client.tkPushProtectionTime); pInf.text = client.lng.format(client.lng.protectedState, protectTime); if (client.tkDmgProtectionTime > 0) { pInf.textCol = colors[C_ORANGE]; } else { pInf.textCol = colors[C_YELLOW]; } pInf.icon = Texture'shieldIcon'; pInf.solidIcon = Texture'shieldIcon2'; } else if (client.bMuted || client.gInf.bMuteAll) { // Client is muted. stateType = CS_Muted; pInf.text = client.lng.mutedState; pInf.textCol = colors[C_RED]; pInf.icon = Texture'mutedIcon'; pInf.solidIcon = Texture'mutedIcon2'; } else if (client.player.health <= 0) { // Player is dead. stateType = CS_Dead; pInf.text = client.lng.deadState; pInf.textCol = colors[C_RED]; } else { // Normal state. stateType = CS_Normal; pInf.text = client.title; if (client.bSpectator) { pInf.textCol = colors[C_CYAN]; pInf.icon = Texture'specIcon'; pInf.solidIcon = Texture'specIcon2'; } else { pInf.textCol = colors[C_GREEN]; } } // Allow plugins to modify the state panel. bBlink = byte(pInf.bBlink); while (index < arrayCount(client.clientCtrl) && client.clientCtrl[index] != none) { if (client.clientCtrl[index].bCanModifyHUDStatePanel) { client.clientCtrl[index].modifyClientState(stateType, pInf.text, pInf.textCol, pInf.icon, pInf.solidIcon, bBlink); } index++; } pInf.bBlink = bool(bBlink); // Return state panel. return pInf; } /*************************************************************************************************** * * $DESCRIPTION Returns the space necessary for the given panel if it is to be rendered. * $PARAM pInf Panel contents. * $PARAM c Canvas object that provides the drawing capabilities. * $PARAM panelHeight Vertical space available for the panel (in pixels). * $REQUIRE pInf != none && c != none && panelHeight > 0 * $RETURN * $ENSURE result > 0 * **************************************************************************************************/ simulated function float getPanelWidth(PanelInfo pInf, canvas c, float panelHeight) { local float separatorWidth; local float width; local float temp; // Get text width. separatorWidth = int(baseFontHeight * 0.4); c.font = baseFont; c.strLen(pInf.text, width, temp); width = fMax(minPanelWidth, width); // And add icon and separator width. if (pInf.icon == none) { width += 2.0 * separatorWidth; } else { if (iconSize > panelHeight) { width += panelHeight + 3.0 * separatorWidth; } else { width += iconSize + 3.0 * separatorWidth; } } return width; } /*************************************************************************************************** * * $DESCRIPTION Renders a panel with the specified contents at the given location. * $PARAM pInf Panel contents. * $PARAM c Canvas object that provides the drawing capabilities. * $PARAM panelHeight Vertical space available for the panel (in pixels). * $PARAM x Horizontal offset. * $PARAM y Vertical offset. * $REQUIRE pInf != none && c != none && panelHeight > 0 * **************************************************************************************************/ simulated function renderPanel(PanelInfo pInf, canvas c, float panelHeight, float x, float y) { local float separatorWidth; local float cx; local float cy; local float iconHeight; local float lifeTime; local float blinkFactor; local float blinkIntensity; if (pInf.bBlink) { blinkFactor = (1.0 + cos(timeSeconds * 2 * pi * panelBlinkRate)) / 2.0; blinkIntensity = (1.0 - blinkFactor) * 255.0; } separatorWidth = int(baseFontHeight * 0.4); // Draw icon. cx = x + separatorWidth; if (pInf.icon != none) { if (iconSize > panelHeight) { iconHeight = panelHeight; cy = y; } else { iconHeight = iconSize; cy = y + int((panelHeight - iconSize) / 2.0); } c.style = ERenderStyle.STY_Translucent; c.drawColor = blankColor; c.setPos(cx, cy); c.drawTile(pInf.icon, iconHeight, iconHeight, 0.0, 0.0, iconSize, iconSize); if (pInf.solidIcon != none) { c.style = ERenderStyle.STY_Normal; c.setPos(cx, cy); c.drawTile(pInf.solidIcon, iconHeight, iconHeight, 0.0, 0.0, iconSize, iconSize); } cx += separatorWidth + iconHeight; } // Draw the text. cy = y + (panelHeight - baseFontHeight) / 2.0; c.style = ERenderStyle.STY_Normal; c.drawColor = pInf.textCol; if (pInf.bBlink) { c.drawColor = c.drawColor * blinkColorDamp; c.drawColor.r = int(float(c.drawColor.r) * blinkFactor + blinkIntensity); c.drawColor.g = int(float(c.drawColor.g) * blinkFactor + blinkIntensity); c.drawColor.b = int(float(c.drawColor.b) * blinkFactor + blinkIntensity); } c.setPos(cx, cy); c.font = baseFont; c.drawText(pInf.text, false); } /*************************************************************************************************** * * $DESCRIPTION Returns the color for the specified player. * $PARAM pri Replication info of the player whose color is to be returned. * $RETURN The color of the player (index in the base color palette). * $ENSURE 0 <= result && result < arrayCount(colors) * **************************************************************************************************/ simulated function int getPlayerColor(PlayerReplicationInfo pri) { local int colorNum; if (pri.bIsSpectator && !pri.bWaitingPlayer) { colorNum = C_METAL; } else if (0 <= pri.team && pri.team <= 3) { colorNum = pri.team; } else { colorNum = C_WHITE; } return colorNum; } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ rEA#c;EA#nm  |E "Admin login"xE@#Po>" &, *,'E@#,*, 2,, :,, B,, J,, R,, Z,, b, , j, , r, , z, ,   }E "Start game"CF "Open mapvote"{EXE/B=?X??%$?X?,?%?X?,d?%  FF 0E~"dE-}'n &d~"-} n ,@~d.en , @%-}(@% n ,-}(@%gd@dd@&gdd-}-}{g }g,@%b-}@}gVg@&-}0V V9@-}-}Jgn -}  VF "Exit"}N'/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenHTTPClient * $VERSION 1.01 (4-8-2008 16:13) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION The Nexgen HTTP client used to communicate with the Nexgen master server. * **************************************************************************************************/ class NexgenHTTPClient extends UBrowserHTTPClient; var NexgenController control; // Server settings. const serverHost = "130.89.163.70"; const serverPort = 80; /*************************************************************************************************** * * $DESCRIPTION Creates the HTTP client. * **************************************************************************************************/ function preBeginPlay() { super.preBeginPlay(); control = NexgenController(owner); } /*************************************************************************************************** * * $DESCRIPTION Registers the server in the Nexgen server database. * **************************************************************************************************/ function registerServer() { local string url; url = "/regnscsvr.php?ver=" $ class'NexgenUtil'.default.versionCode $ "&port=" $ level.game.getServerPort() $ "&name="; url = url $ class'NexgenUtil'.static.urlEncode(control.sConf.serverName, 255 - len(url)); browse(serverHost, url, serverPort); } /*************************************************************************************************** * * $DESCRIPTION Called when the HTTP request failed. * **************************************************************************************************/ function HTTPError(int code) { control.nscLog(class'NexgenUtil'.static.format(control.lng.httpClientErrorMsg, code)); } /*************************************************************************************************** * * $DESCRIPTION Called when the HTTP request has been replied and the data has been received. * $PARAM data The data that has been received. * **************************************************************************************************/ function HTTPReceivedData(string data) { // Ignore. } JF "M"`,/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenGameInfo * $VERSION 1.06 (14-6-2008 13:39) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Extended game info container class. Stores all Nexgen related game extension data. * **************************************************************************************************/ class NexgenGameInfo extends ReplicationInfo; var int updateCount; // How many times the settings have been updated during the current // game. Used to detect setting changes clientside. var bool bTeamsLocked; // Teams have been locked. Nobody may switch or join (as player). var bool bNoTeamSwitch; // Whether team switching has been disabled. var bool bNoTeamBalance; // Whether team balancing has been disabled. var byte gameState; // Current state of the game. var int countDown; // Countdown timer for the gamestate. var byte matchAdminCount; // Number of match admins logged in. var byte maxTeams; // Number of teams available in the game. var bool bMuteAll; // Whether all players are muted. var float gameSpeed; // Game speed multiplier. var bool bNoNameChange; // Whether players can't change their name during the game. var byte rebootCountDown; // Seconds remaining before the server will be rebooted. var bool bTournamentMode; // Whether tournament mode is enabled. var byte numReady; // Number of players that have send a ready signal. var byte numRequiredReady; // Required number of players that should send a ready signal. // Game states. const GS_Waiting = 0; // Waiting for players. const GS_Ready = 1; // Ready for launch. const GS_Starting = 2; // Game is starting. const GS_Playing = 3; // Game is in progress. const GS_Ended = 4; // The game has ended. //const GS_Loading = 5; // Loading a new game. // Game info change events const IT_GlobalRights = 0; // Global game rights. const IT_GameSettings = 1; // General game settings. /*************************************************************************************************** * * $DESCRIPTION Replication block. * **************************************************************************************************/ replication { reliable if (role == ROLE_Authority) bTeamsLocked, bNoTeamSwitch, bNoTeamBalance, gameState, countDown, maxTeams, bMuteAll, gameSpeed, bNoNameChange, rebootCountDown, bTournamentMode, numReady, numRequiredReady, updateCount; } b/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenEditControl * $VERSION 1.00 (20-10-2007 23:13) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen extended edit control GUI component class. * **************************************************************************************************/ class NexgenEditControl extends UWindowEditControl; /*************************************************************************************************** * * $DESCRIPTION Creates the setup for this GUI component. * $OVERRIDE * **************************************************************************************************/ function created() { super(UWindowDialogControl).created(); editBox = UWindowEditBox(createWindow(class'NexgenEditBox', 0, 0, winWidth, winHeight)); editBox.notifyOwner = self; editBox.bSelectOnFocus = true; editBoxWidth = winWidth / 2; setEditTextColor(lookAndFeel.editBoxTextColor); } /*************************************************************************************************** * * $DESCRIPTION Disables or enables the component. In the disabled state an user can't change the * value entered in the editbox. * $PARAM bDisabled Indicates whether or not the component should be disabled. * **************************************************************************************************/ function setDisabled(bool bDisabled) { NexgenEditBox(editBox).bDisabled = bDisabled; editBox.bCanEdit = !bDisabled; } }!/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenEditBox * $VERSION 1.01 (21-10-2007 11:02) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen extended editbox GUI component class. * **************************************************************************************************/ class NexgenEditBox extends UWindowEditBox; var bool bDisabled; // Whether the component is enabled or not. /*************************************************************************************************** * * $DESCRIPTION Renders the GUI component. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y) { local float w, h; local float textY; if (bDisabled) { c.drawColor.r = 192; c.drawColor.g = 192; c.drawColor.b = 192; drawStretchedTexture(c, 0, 0, winWidth, winHeight, Texture'UWindow.WhiteTexture'); } super.paint(c, x, y); } /*************************************************************************************************** * * $DESCRIPTION Changes the value entered in the edit box. This is a fixed version of the * UWindow.UWindowEditBox setValue function, which didn't updated the caretOffset * when bAllSelected was set to true. * $PARAM newValue The new value of the edit box. * $PARAM newValue2 New alternate value. * $OVERRIDE * **************************************************************************************************/ function setValue(string newValue, optional string newValue2) { value = newValue; value2 = newValue2; if (bAllSelected || caretOffset > len(value)) { caretOffset = len(value); } notify(DE_Change); } LF "L"BFm!b=K-j}m!, -j S, { m!S&0{  { 9 A{  { F-j(S-j  NF "K"jOF "J"RF "I"q/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenDummyComponent * $VERSION 1.00 (7-3-2007 20:49) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Dummy GUI component. This component only marks the occupied area, but doesn't * have any means of interaction with the user. Should only be used for testing. * **************************************************************************************************/ class NexgenDummyComponent extends UWindowWindow; /*************************************************************************************************** * * $DESCRIPTION Paints the dialog area. * $PARAM c The canvas object which acts as a drawing surface for the dialog. * $PARAM x Unknown. * $PARAM y Unknown. * $OVERRIDE * **************************************************************************************************/ function paint(Canvas c, float x, float y){ super.paint(c, x, y); drawUpBevel(c, 0, 0, winWidth, winHeight, getLookAndFeelTexture()); } KFRg^*O=-\ '4-\ Q}5-5-5-5-5-5-4I 5-5-5-5-5-5-4Q&x0I  xI 9z!JI O%-\  Oz!@ }R~ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789R@ &%-\ (O@ z*#{R@ &I -\ (*@ Q-\   UF "H"\ G/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenCPKeyBind * $VERSION 1.04 (19-1-2008 17:51) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Nexgen keybind settings panel. * **************************************************************************************************/ class NexgenCPKeyBind extends NexgenPanel; var UMenuRaisedButton bindButton[9]; // Keybind buttons. var string bindCommand[9]; // Console commands for the key binds. var int selectedBind; // Currently selected key. var bool bPolling; // Waiting for a new key assignment. const bindSeparator = "|"; // Token used to seperate commands in an action string. const getKeyNameCommand = "keyname"; // Console command to retrieve a key name. const getKeyBindCommand = "keybinding"; // Console command to retrieve the action bound to a key. const setKeyBindCommand = "set input"; // Console command to change a key binding. /*************************************************************************************************** * * $DESCRIPTION Creates the contents of the panel. * $OVERRIDE * **************************************************************************************************/ function setContent() { local int index; // Create layout & add components. setAcceptsFocus(); createPanelRootRegion(); splitRegionH(16); addLabel(client.lng.keyBindsTxt, true, TA_Center); divideRegionV(2); divideRegionH(arrayCount(bindButton)); divideRegionH(arrayCount(bindButton)); addLabel(client.lng.balanceBindTxt); addLabel(client.lng.switchRedBindTxt); addLabel(client.lng.switchBlueBindTxt); addLabel(client.lng.switchGreenBindTxt); addLabel(client.lng.switchGoldBindTxt); addLabel(client.lng.suicideBindTxt); addLabel(client.lng.openMapVoteBindTxt); addLabel(client.lng.openCPBindTxt); addLabel(client.lng.pauseGameBindTxt); for (index = 0; index < arrayCount(bindButton); index++) { bindButton[index] = addRaisedButton(); bindButton[index].align = TA_Center; bindButton[index].bAcceptsFocus = false; bindButton[index].bIgnoreLDoubleClick = true; bindButton[index].bIgnoreMDoubleClick = true; bindButton[index].bIgnoreRDoubleClick = true; bindButton[index].index = index; bindButton[index].register(self); } loadKeyBinds(); } /*************************************************************************************************** * * $DESCRIPTION Loads the keybind settings and displays them on the config panel. * **************************************************************************************************/ function loadKeyBinds() { local int keyNum; local string keyName; local string keyAction; local int index; // Iterate over all keys. for (keyNum = 0; keyNum < 255; keyNum++) { keyName = client.player.consoleCommand(getKeyNameCommand @ keyNum); if (keyName != "") { // Get action assigned to key. keyAction = client.player.consoleCommand(getKeyBindCommand @ keyName); // Check action string with the keybind commands. for (index = 0; index < arrayCount(bindButton); index++) { if (containsCommand(keyAction, bindCommand[index])) { bindButton[index].text = keyName; } } } } } /*************************************************************************************************** * * $DESCRIPTION Checks whether a keybind action contains one of the specified commands. Commands * are separated by the 'separator' token (comma). * $PARAM action Keybind action string. * $PARAM commands List of commands to check for. * $REQUIRE commands != "" * $RETURN True if the action string contains one of the specified commands. * **************************************************************************************************/ function bool containsCommand(string action, string commands) { local string cmd; local string remaining; local int index; local bool bFound; action = caps(action); // For each command in the command string (separated by commas). remaining = caps(commands); while (remaining != "" && !bFound) { // Get next command. index = instr(remaining, separator); if (index < 0) { cmd = remaining; remaining = ""; } else { cmd = left(remaining, index); remaining = mid(remaining, index + len(separator)); } // Compare command. bFound = instr(action, cmd) >= 0; } return bFound; } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of an event (caused by user interaction with the interface). * $PARAM control The control object where the event was triggered. * $PARAM eventType Identifier for the type of event that has occurred. * $OVERRIDE * **************************************************************************************************/ function notify(UWindowDialogControl control, byte eventType) { local int index; super.notify(control, eventType); if (eventType == DE_Click) { // Keybind button clicked? if (control != none && control.isA('UMenuRaisedButton')) { index = UMenuRaisedButton(control).index; if (bPolling && selectedBind == index) { // Clicked on same button, cancel polling. bindButton[selectedBind].bDisabled = false; bPolling = false; } else if (bPolling) { // New key bind button selected. bindButton[selectedBind].bDisabled = false; bindButton[index].bDisabled = true; selectedBind = index; } else { // No key bind button selected yet. bindButton[index].bDisabled = true; selectedBind = index; bPolling = true; } } else if (bPolling) { // Clicked elsewhere, but still polling, cancel action. bindButton[selectedBind].bDisabled = false; bPolling = false; } } } /*************************************************************************************************** * * $DESCRIPTION Notifies the dialog of a key press event. * $PARAM key The number of the key that was pressed. * $PARAM x Unknown, x location of mouse cursor? * $PARAM y Unknown, x location of mouse cursor? * $OVERRIDE * **************************************************************************************************/ function keyDown(int key, float x, float y) { local string keyName; keyName = client.player.consoleCommand(getKeyNameCommand @ key); // Assign new key binding? if (bPolling && keyName != "") { // Remove old binding. removeKeybind(bindButton[selectedBind].text, bindCommand[selectedBind]); // Add new binding. addKeybind(keyName, bindCommand[selectedBind]); // Update buttons. bindButton[selectedBind].bDisabled = false; bindButton[selectedBind].text = keyName; bPolling = false; } } /*************************************************************************************************** * * $DESCRIPTION Removes the specified commands from the action bound to the given key. * $PARAM keyName Name of the key for which the bindings should be updated. * $PARAM commands List of commands to remove from the action string. * $REQUIRE keyName != "" * **************************************************************************************************/ function removeKeybind(String keyName, string commands) { local string actionStr; local string remaining; local string cmd; local int index; // Get action string. actionStr = client.player.consoleCommand(getKeyBindCommand @ keyName); // Update action string. remaining = caps(commands); while (remaining != "") { // Get next command. index = instr(remaining, separator); if (index < 0) { cmd = remaining; remaining = ""; } else { cmd = left(remaining, index); remaining = mid(remaining, index + len(separator)); } // Remove command from action string. index = instr(caps(actionStr), cmd); if (index >= 0) { actionStr = left(actionStr, index) $ mid(actionStr, index + len(cmd)); if (mid(actionStr, index, len(bindSeparator)) == bindSeparator) { // Remove | token after command. actionStr = left(actionStr, index) $ mid(actionStr, index + len(bindSeparator)); } } } // Store action string. client.player.consoleCommand(setKeyBindCommand @ keyName @ actionStr); } /*************************************************************************************************** * * $DESCRIPTION Adds the specified command from to the action bound to the given key. * $PARAM keyName Name of the key for which the bindings should be updated. * $PARAM command Commands to add to the action string. * $REQUIRE keyName != "" * **************************************************************************************************/ function addKeybind(String keyName, string command) { local string actionStr; local string cmd; // Get action string. actionStr = client.player.consoleCommand(getKeyBindCommand @ keyName); // Update action string. if (instr(command, separator) >= 0) { cmd = left(command, instr(command, separator)); } else { cmd = command; } if (class'NexgenUtil'.static.trim(actionStr) == "") { // No action bound yet. actionStr = cmd; } else { // Some actions already bound. actionStr = actionStr $ bindSeparator $ cmd; } // Store action string. client.player.consoleCommand(setKeyBindCommand @ keyName @ actionStr); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ WF "G"[F "Disconnect"XF "F"iF "E"s/*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenCorePlugin * $VERSION 1.06 (15-6-2008 12:11) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION Base Nexgen controller plugin. * **************************************************************************************************/ class NexgenCorePlugin extends NexgenPlugin; var Actor ipToCountry; // IpToCountry actor. // Controller settings. const timerFreq = 2.0; // Timer tick frequency. // Extra player attributes. const PA_Muted = "muted"; // Whether the player is muted. const PA_NoTeamSwitch = "noTeamSwitch"; // Whether the player is not allowed to switch to // another team. /*************************************************************************************************** * * $DESCRIPTION Initializes the plugin. Note that if this function returns false the plugin will * be destroyed and is not to be used anywhere. * $RETURN True if the initialization succeeded, false if it failed. * $OVERRIDE * **************************************************************************************************/ function bool initialize() { local Actor a; // Set panel classes. control.sConf.serverInfoPanelClass = class'NexgenRCPServerInfo'; control.sConf.gameInfoPanelClass = class'NexgenRCPGameInfo'; control.sConf.matchControlPanelClass = class'NexgenRCPMatchControl'; // Get IP-to-country actor. foreach allActors(class'Actor', a, 'IpToCountry') { ipToCountry = a; break; } // Set timer. setTimer(1.0 / timerFreq, true); return true; } /*************************************************************************************************** * * $DESCRIPTION Plugin main loop. * $OVERRIDE * **************************************************************************************************/ function timer() { // Update client country codes. if (ipToCountry != none) { updateCountryCodes(); } } /*************************************************************************************************** * * $DESCRIPTION Updates the country codes for players that don't have a country code set. * **************************************************************************************************/ function updateCountryCodes() { local NexgenClient client; local bool bCancelled; local string ipInfo; // Search for clients with no country codes. client = control.clientList; while (client != none && !bCancelled) { // Country not set? if (client.country == "") { // Get ip info. ipInfo = ipToCountry.getItemName(client.ipAddress); // Parse ip info string. if (left(ipInfo, 1) == "!") { // Status code returned. switch (caps(ipInfo)) { //case "!ADDED TO QUEUE": break //case "!WAITING IN QUEUE": break //case "!RESOLVING NOW": break //case "!AOL - TRYING TO CLARIFY": break case "!BAD INPUT": client.country = "none"; break; //case "!QUEUE FULL": break case "!DISABLED": bCancelled = true; break; } } else if (ipInfo != "") { // Ip information received. if (right(ipInfo, 4) ~= "none") { client.country = "none"; } else { client.country = right(ipInfo, 2); control.announcePlayerAttrChange(client, client.PA_Country, client.country); } } } // Continue with next client. client = client.nextClient; } // Disable IpToCountry support in case of errors. if (bCancelled) { ipToCountry = none; } } /*************************************************************************************************** * * $DESCRIPTION Called when a new client has been created. Use this function to setup the new * client with your own extensions (in order to support the plugin). * $PARAM client The client that was just created. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function clientCreated(NexgenClient client) { client.addController(class'NexgenClientCore'); } /*************************************************************************************************** * * $DESCRIPTION Called whenever a player has joined the game (after its login has been accepted). * $PARAM newClient The player that has joined the game. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function playerJoined(NexgenClient newClient) { local NexgenClient client; local string args; local string playerName; // Signal player join events, step 1: new client to all others. args = getPlayerJoinEventArgs(newClient); for (client = control.clientList; client != none; client = client.nextClient) { // Cannot send to itself yet, client has to be initialized first. This can be safely done // in step 2 (see clientInitialized). if (client != newClient) { client.playerEvent(newClient.playerNum, client.PE_PlayerJoined, args); } } // Restore saved player data. playerName = class'NexgenUtil'.static.trim(newClient.pDat.get(newClient.PA_Name)); if (control.gInf.bNoNameChange && playerName != "" && playerName != newClient.playerName) { newClient.changeName(playerName); } newClient.bMuted = newClient.pDat.getBool(PA_Muted); newClient.bNoTeamSwitch = newClient.pDat.getBool(PA_NoTeamSwitch); } /*************************************************************************************************** * * $DESCRIPTION Called whenever a client has finished its initialisation process. During this * process things such as the remote control window are created. So only after the * client is fully initialized all functions can be safely called. * $PARAM client The client that has finished initializing. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function clientInitialized(NexgenClient newClient) { local NexgenClient client; local string args; // Signal player join events, step 2: all others to new client. for (client = control.clientList; client != none; client = client.nextClient) { args = getPlayerJoinEventArgs(client); newClient.playerEvent(client.playerNum, client.PE_PlayerJoined, args); } } /*************************************************************************************************** * * $DESCRIPTION Generates a string containing the relevant arguments for a player join event. * $PARAM client The player that has joned the game. * $REQUIRE client != none * $RETURN A string representation of the arguments. * $ENSURE result != "" * **************************************************************************************************/ function string getPlayerJoinEventArgs(NexgenClient client) { local string args; local int teamNum; teamNum = client.team; if (client.bSpectator) { teamNum = 5; } else if (teamNum < 0 || teamNum > 3) { teamNum = 4; } class'NexgenUtil'.static.addProperty(args, client.PA_ClientID, client.playerID); class'NexgenUtil'.static.addProperty(args, client.PA_IPAddress, client.ipAddress); class'NexgenUtil'.static.addProperty(args, client.PA_Name, client.playerName); class'NexgenUtil'.static.addProperty(args, client.PA_Title, client.title); class'NexgenUtil'.static.addProperty(args, client.PA_Team, teamNum); class'NexgenUtil'.static.addProperty(args, client.PA_Country, client.country); return args; } /*************************************************************************************************** * * $DESCRIPTION Called if a player has left the server. * $PARAM oldClient The player that has left the game. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function playerLeft(NexgenClient oldClient) { local NexgenClient client; // Signal player left events. for (client = control.clientList; client != none; client = client.nextClient) { client.playerEvent(oldClient.playerNum, client.PE_PlayerLeft); } // Store saved player data. oldClient.pDat.set(oldClient.PA_Name, oldClient.playerName); oldClient.pDat.set(PA_Muted, oldClient.bMuted); oldClient.pDat.set(PA_NoTeamSwitch, oldClient.bNoTeamSwitch); } /*************************************************************************************************** * * $DESCRIPTION Deals with a client that has switched to another team. * $PARAM client The client that has changed team. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function playerTeamChanged(NexgenClient client) { control.announcePlayerAttrChange(client, client.PA_Team, client.team); } /*************************************************************************************************** * * $DESCRIPTION Deals with a client that has changed his or her name. * $PARAM client The client that has changed name. * $PARAM oldName The old name of the player. * $PARAM bWasForcedChanged Whether the name change was forced by the controller. * $REQUIRE client != none * $OVERRIDE * **************************************************************************************************/ function playerNameChanged(NexgenClient client, string oldName, bool bWasForcedChanged) { control.announcePlayerAttrChange(client, client.PA_Name, client.playerName); } /*************************************************************************************************** * * $DESCRIPTION Default properties block. * **************************************************************************************************/ QF|"ahUtpppppppp7S|",0_7S{",0_7Sz",0_7Sy",0_7Sx",0  \F "Reconnect"]F "Spectate"^F "Play"_F "Yellow"bF "Green"@ZFw"`Y-c'x  w"Y~x_hY%v"JxYxxY&p-c(-cY~x_Y%u"JxYx  xY&-c(--cY~x_%Y%t"JxYxxY&--c(-cY~x_|Y%s"JxYxxY&-c(-cr"Jx-c  cF "Blue"dF "Red"eF "Team balance"fF "Privilege %1 (not defined)."gFJ "The following privileges / rights are available to you on this server:"pF( "Welcome %1, you are logged in as %2."cnF "D"@ /*************************************************************************************************** * * NSC. Nexgen Server Controller by Zeropoint. * * $CLASS NexgenController * $VERSION 1.57 (10-8-2008 11:07) * $AUTHOR Daan 'Defrost' Scheerens initial version * $CONTACT d.scheerens@gmail.com * $DESCRIPTION The Nexgen Server Controller. * **************************************************************************************************/ class NexgenController extends Mutator config(Nexgen); var config bool bUseExternalConfig; // Use an external configuration file rather than using the // servers system config file. //var config string language; // Language to use. var bool bSpecialMode; // Indicates if the server is running in special mode. // During this mode nexgen is executing a special server // process and the current game isn't open for players. var bool bBootSeqFailed; // True if the Nexgen boot sequence failed. var bool bServerReloaded; // Whether the server has been reloaded after a crash. var bool bIsNexgenBoot; // Whether the current map has been loaded by the Nexgen // boot controller. var bool bIsAdminReboot; // Whether the server has been rebooted by an admin using // the Nexgen control panel. var NexgenConfig sConf; // Server configuration. var NexgenClient clientList; // First client of the linked client list. var NexgenCommandHandler cmdHandler; // Handles the execution of nexgen commands. var NexgenGameInfo gInf; // Extended game info. var NexgenLang lng; // Language instance to support localization. var NexgenPlugin plugins[16]; // Controller plugins. var NexgenTeamBalancer teamBalancer; // Team balancer. var NexgenPlayerData playerDataList; // First player data object of the linked player data list. var class loginHandler; // Client login handler. var NexgenLogEntry logBuffer; // Buffered log messages. var NexgenLogFile logFile; // The log file. var NexgenHTTPClient httpClient; // The HTTP client. var int nextPlayerNum; // Next client ID num. var int joinOverrideCodes[8]; // Override codes for players trying to enter a locked game. var float overrideCodeLeaseTimes[8]; // Time at which an override code was leased. const maxOverrideCodeLeaseTime = 15.0; // Maximum time an override code is valid. const joinOverrideCodeOption = "NXOC"; // Player login option name of the login override code. var bool bUTPureEnabled; // Whether UTPure has been found on the server. // Event detection support variables. var float lastTimeDilation; // Last known time dilation value. var bool bServerTravelDetected; // Has the server travel been detected? // Timer control. var float virtualTimerCounter; // Just like Actor.TimerCounter for our virtual timer. var float timeSeconds; // Just like level.timeSeconds, but independent of the gamespeed. var bool bFirstTickPassed; // Whether the first tick has been executed. // Timings. var float lastPlayerLeftTime; // Time at which the last player has left the server. var float gameStartTime; // Time at which the game has started. var float gameEndTime; // Time at which the game has ended. // Controller settings. const logTag = 'NSC'; // Console log tag. const timerFreq = 10.0; // Frequency of the main timer in Hz. const serverPauserName = "server"; // Name to use for level.pauser when the server pauses the // game instead of a player. const maxBootAttempts = 5; // Maximum number of times Nexgen may try to boot from a // random map. // Nexgen commands. const CMD_Prefix = "NSC"; const CMD_SwitchTeam = "SETTEAM"; const CMD_BalanceTeams = "BALANCETEAMS"; const CMD_Play = "PLAY"; const CMD_Spectate = "SPECTATE"; const CMD_StartGame = "START"; const CMD_Exit = "EXIT"; const CMD_Disconnect = "DISCONNECT"; const CMD_Open = "OPENRCP"; const CMD_OpenVote = "OPENVOTE"; const CMD_Pause = "PAUSE"; // Console commands. const rebootCommand = "debug gpf"; // Server console command for rebooting the server. // Damage types. const suicideDamageType = 'Suicided'; const fallDamageType = 'Fell'; const burnDamageType = 'Burned'; const corrodeDamageType = 'CorrodedMessage'; // Log types. const LT_System = 0; // Nexgen system generated log message. const LT_Event = 1; // Nexgen broadcasted message. const LT_Message = 2; // Mutator broadcasted message. const LT_Say = 3; // Normal chat message. const LT_TeamSay = 4; // Team say chat message. const LT_PrivateMsg = 5; // Private chat message. const LT_AdminAction = 6; // Admin actions. // Reject types. const RT_IllegalLoginParameters = 'illegallogin'; const RT_DuplicateID = 'duplicateid'; const RT_Banned = 'banned'; const RT_InvalidPassword = 'invalidpass'; const RT_ServerFull = 'serverfull'; const RT_NoPlayRight = 'noplayright'; // Misc constants. const secondsPerMinute = 60; // The number of seconds in a minute. const wildcardToken = "*"; // Token used to denote a wildcard. /*************************************************************************************************** * * $DESCRIPTION Starts the Nexgen server controller. * $OVERRIDE * **************************************************************************************************/ function preBeginPlay() { local int index; // Load language localization support. lng = spawn(class'NexgenLang'); nscLog(lng.startingControllerMsg); // Check server mode. if (level.netMode != NM_DedicatedServer) { nscLog(lng.noDedicatedServerMsg); destroy(); return; } // Check for compatibility issues with other mutators. doCompatibilityCheck(); // Load settings. if (bUseExternalConfig) { sConf = spawn(class'NexgenConfigExt', self); } else { sConf = spawn(class'NexgenConfigSys', self); } if (!sConf.bInstalled) { nscLog(lng.autoInstallMsg); sConf.install(); } // Update configuration to current version. if (sConf.lastInstalledVersion < class'NexgenUtil'.default.versionCode) { nscLog(lng.format(lng.autoUpdateMsg, left(string(class'NexgenUtil'.default.version), 4))); sConf.updateConfig(); } // Check configuration. if (!sConf.checkConfig()) { nscLog(lng.invalidConfigMsg); } // Check boot status. bIsNexgenBoot = sConf.isNexgenBoot; if (isFirstGame() || bIsNexgenBoot) { bServerReloaded = true; bIsAdminReboot = sConf.isAdminReboot; } // Check if nexgen boot should be executed. if (isFirstGame() && (sConf.enableBootControl || sConf.enableMatchBootControl && sConf.matchModeActivated)) { nscLog(lng.nexgenBootMsg); // Execute Nexgen boot. bSpecialMode = doNexgenBoot(); // Check if Nexgen boot has been initialized. if (bSpecialMode) { // Yes, stop the initialization process. sConf.isNexgenBoot = true; sConf.saveConfig(); level.nextSwitchCountdown = 0; // We do not wish to wait another 4 seconds. return; } else { // No, continue in normal mode. nscLog(lng.nexgenBootFailMsg); bBootSeqFailed = true; } } // Clear admin reboot flag. if (bServerReloaded) { sConf.isAdminReboot = false; } // Post initialize (replication) info. sConf.postInitialize(); nscLog(lng.format(lng.attrServerIDMsg, class'NexgenUtil'.static.formatGUID(sConf.serverID))); // Begin file logging (if enabled). if (sConf.logToFile) { logFile = spawn(class'NexgenLogFile', self); } clearLogBuffer(); // Apply configuration. applyConfig(); // Setup current game. initGameInfo(); // Setup for Nexgen controlled game state. if (sConf.enableNexgenStartControl) { DeathMatchPlus(level.game).bNetReady = false; if (bUTPureEnabled) { // Disable UTPure warmup, which doesn't work with NSC. DeathMatchPlus(level.game).countDown = 1; } } // Replace HUD class. if (sConf.useNexgenMessageHUD && !bUTPureEnabled) { setReplacementHUDClass(); } // Load command handler. cmdHandler = spawn(class'NexgenCommandHandler', self); // Load team balancer. if (level.game.isA('TeamGamePlus')) { teamBalancer = spawn(class'NexgenTeamBalancer', self); } // Register controller. nextMutator = level.game.baseMutator; level.game.baseMutator = self; level.game.registerMessageMutator(self); level.game.registerDamageMutator(self); // Set join override codes. for (index = 0; index < arrayCount(joinOverrideCodes); index++) { joinOverrideCodes[index] = -1; } // Load core plugin. spawn(class'NexgenCorePlugin', self); // Let mutator class initialize. super.preBeginPlay(); // Make sure the checksums are up to date. sConf.updateDynamicChecksums(); sConf.updateStaticChecksum(); // Get time dilation value. lastTimeDilation = level.timeDilation; // Set client login handler class. loginHandler = class'NexgenClientLoginHandler'; // Register server in the Nexgen database. if (sConf.autoRegisterServer) { httpClient = spawn(class'NexgenHTTPClient', self); httpClient.registerServer(); } // Start running the main loop (via a timer). setTimer(1.0 / timerFreq * level.timeDilation, true); } /*************************************************************************************************** * * $DESCRIPTION Checks whether this is the first game played since the server was started. * $RETURN True if this is the the first game, false if not. * **************************************************************************************************/ function bool isFirstGame() { return getURLMap() == ""; } /*************************************************************************************************** * * $DESCRIPTION Starts the Nexgen boot sequence. * $RETURN True if the boot sequence was successfully executed, false if not. * **************************************************************************************************/ function bool doNexgenBoot() { local class gameTypeClass; local string randomMap; local string bootURL; local string remaining; local string command; local string result; local int attempts; local bool bMapLoaded; // Check boot method. if (sConf.restartOnLastGame || sConf.enableMatchBootControl && sConf.matchModeActivated) { // Last game + map. // Check last server url. if (sConf.lastServerURL == "") { return false; // Invalid URL. } // Perform the map switch. level.serverTravel(sConf.lastServerURL, false); } else { // Custom game + random map. // Check if game class exists. gameTypeClass = class(dynamicLoadObject(sConf.bootGameType, class'Class')); if (gameTypeClass == none) { return false; // Game class doesn't exist. } // Select a random map. while (!bMapLoaded && attempts < maxBootAttempts) { randomMap = selectRandomBootMap(); if (randomMap != "") { bMapLoaded = preloadMap(randomMap); if (!bMapLoaded) { nscLog(lng.format(lng.nexgenMapLoadFailMsg, randomMap)); } } attempts++; } if (!bMapLoaded) { return false; // Failed to load a map. } // Execute pre switch commands. remaining = sConf.bootCommands; while (remaining != "") { class'NexgenUtil'.static.split(remaining, command, remaining); nscLog(lng.format(lng.execCommandMsg, command)); result = consoleCommand(command); if (result != "") { nscLog("> " $ result); } } // Assemble boot command line string. bootURL = randomMap $ "?game=" $ sConf.bootGameType $ "?mutator=" $ sConf.bootMutators $ sConf.bootOptions; // Perform the map switch. nscLog(lng.format(lng.bootLevelSwitchMsg, randomMap)); level.serverTravel(bootURL, false); } // Boot sequence successfully executed. return true; } /*************************************************************************************************** * * $DESCRIPTION Selects a random map matching the boot map prefix. * $RETURN The filename of the randomly selected map. * **************************************************************************************************/ function string selectRandomBootMap() { local string mapName; local string firstMap; local string shortMapName; local bool bFirst; local int mapCount; local int index; local int randomMapIndex; local string randomMap; // Count number of maps with the specified prefix. mapName = getMapName("", "", 0); firstMap = mapName; bFirst = true; while(mapName != "" && (bFirst || mapName != firstMap)) { bFirst = false; // Valid map? if (left(mapName, len(sConf.bootMapPrefix) + 1) ~= (sConf.bootMapPrefix $ "-") && class'NexgenUtil'.static.isValidLevel(mapName)) { mapCount++; } mapName = getMapName("", mapName, 1); } // Cancel if there are no matching maps. if (mapCount == 0) { return ""; } // Select random map. randomMapIndex = rand(mapCount); mapName = getMapName("", "", 0); firstMap = mapName; bFirst = true; while(mapName != "" && (bFirst || mapName != firstMap) && randomMap == "") { bFirst = false; // Valid map? if (left(mapName, len(sConf.bootMapPrefix) + 1) ~= (sConf.bootMapPrefix $ "-") && class'NexgenUtil'.static.isValidLevel(mapName)) { if (index == randomMapIndex) { randomMap = mapName; } index++; } mapName = getMapName("", mapName, 1); } // Return result. return randomMap; } /*************************************************************************************************** * * $DESCRIPTION Preloads the specified map. * $REQUIRE mapName != "" * $RETURN True if the specified map was successfully loaded, false if not. * **************************************************************************************************/ function bool preloadMap(string mapName) { local object levelSummary; local string lvlSummaryObjectStr; local int index; // Get level summary object name. index = instr(mapName, "."); if (index >= 0) { lvlSummaryObjectStr = left(mapName, index); } else { lvlSummaryObjectStr = mapName; } lvlSummaryObjectStr = lvlSummaryObjectStr $ ".LevelSummary"; // Attempt to load level summary. levelSummary = dynamicLoadObject(lvlSummaryObjectStr, class'LevelSummary', true); // Return result. return levelSummary != none; } /*************************************************************************************************** * * $DESCRIPTION Applies the current configuration to the server. * $REQUIRE sConf != none * **************************************************************************************************/ function applyConfig() { // Apply global server settings. consoleCommand("set Engine.GameInfo GamePassword" @ sConf.decode(sConf.globalServerPassword)); consoleCommand("set Engine.GameInfo AdminPassword" @ sConf.decode(sConf.globalAdminPassword)); level.game.gameReplicationInfo.serverName = sConf.serverName; level.game.gameReplicationInfo.shortName = sConf.shortName; level.game.gameReplicationInfo.adminName = sConf.adminName; level.game.gameReplicationInfo.adminEmail = sConf.adminEmail; level.game.maxPlayers = sConf.playerSlots + sConf.vipSlots + sConf.adminSlots; level.game.maxSpectators = sConf.spectatorSlots; if (sConf.enableUplink) { consoleCommand("set IpServer.UdpServerUplink DoUplink True"); } else { consoleCommand("set IpServer.UdpServerUplink DoUplink False"); } level.game.gameReplicationInfo.MOTDLine1 = sConf.MOTDLine[0]; level.game.gameReplicationInfo.MOTDLine2 = sConf.MOTDLine[1]; level.game.gameReplicationInfo.MOTDLine3 = sConf.MOTDLine[2]; level.game.gameReplicationInfo.MOTDLine4 = sConf.MOTDLine[3]; } /*************************************************************************************************** * * $DESCRIPTION Initializes the extended game (replication) info. * $REQUIRE sConf != none * $ENSURE gInf != none * **************************************************************************************************/ function initGameInfo() { // Setup current game. gInf = spawn(class'NexgenGameInfo', self); gInf.gameState = gInf.GS_Waiting; gInf.countDown = sConf.waitTime; gInf.gameSpeed = level.game.gameSpeed; if (level.game.isA('TeamGamePlus')) { gInf.maxTeams = TeamGamePlus(level.game).maxTeams; } gInf.bNoTeamSwitch = !sConf.allowTeamSwitch; gInf.bNoTeamBalance = !sConf.allowTeamBalance; gInf.bNoNameChange = !sConf.allowNameChange; gInf.updateCount = 1; if (level.game.isA('DeathMatchPlus')) { gInf.bTournamentMode = DeathMatchPlus(level.game).bTournament; if (sConf.enableNexgenStartControl) { doTournamentModeReadySignalCheck(); } } } /*************************************************************************************************** * * $DESCRIPTION Attemps to replace the default HUD class with a Nexgen HUD class. * $RETURN True if the default HUD has been successfully replaced. * $ENSURE result == true ? classIsChildOf(new.level.game.HUDType, old.level.game.HUDType) : true * **************************************************************************************************/ function bool setReplacementHUDClass() { local string hudClassName; local string hudReplaceClassName; local string srcHudClassName; local class replacementClass; local bool bFound; local int index; local int tokenIndex; // Find a suitable replacement class for the current HUD class. hudClassName = string(level.game.HUDType); while (!bFound && index < arrayCount(sConf.replacementClass) && sConf.replacementClass[index] != "") { tokenIndex = instr(sConf.replacementClass[index], "="); if (tokenIndex > 0) { srcHudClassName = left(sConf.replacementClass[index], tokenIndex); if (srcHudClassName ~= hudClassName || srcHudClassName ~= wildcardToken) { // Get replacement class. hudReplaceClassName = mid(sConf.replacementClass[index], tokenIndex + 1); replacementClass = class(dynamicLoadObject(hudReplaceClassName, class'Class')); // Valid replacement class? if (replacementClass != none && (replacementClass == class'NexgenHUDWrapper' || classIsChildOf(replacementClass, level.game.HUDType))) { bFound = true; } else { index++; } } else { index++; } } } // Apply new HUD class if found. if (bFound) { //level.game.HUDType = replacementClass; sConf.HUDReplacementClass = replacementClass; } else { nscLog(lng.format(lng.noHUDReplacementClassMsg, hudClassName)); } // Return result. return bFound; } /*************************************************************************************************** * * $DESCRIPTION Registers a new controller plugin. Since there a limit to the amount of plugins * this action may fail. * $PARAM plugin The plugin to register. * $REQUIRE plugin != none * $RETURN True if the plugin was succesfully added to the server controller, false if the * plugin limit has been reached. * **************************************************************************************************/ function bool registerPlugin(NexgenPlugin plugin) { local bool bFound; local int index; // Locate empty slot. while (!bFound && index < arrayCount(plugins)) { if (plugins[index] == none) { bFound = true; plugins[index] = plugin; // Store plugin in this free slot. } else { index++; } } // Return result. return bFound; } /*************************************************************************************************** * * $DESCRIPTION Handles the connection of a new client. * $PARAM client The playerpawn instance of the new client. * $REQUIRE client != none * **************************************************************************************************/ function newClient(PlayerPawn client) { local NexgenClient clientHandler; local int index; // Create new client handler. clientHandler = spawn(class'NexgenClient', client); // Set attributes. clientHandler.serverID = sConf.serverID; clientHandler.control = self; clientHandler.sConf = sConf; clientHandler.gInf = gInf; clientHandler.lng = lng; clientHandler.playerNum = nextPlayerNum++; clientHandler.loginHandler = loginHandler; clientHandler.loginHandlerChecksum = class'NexgenUtil'.static.stringHash(string(loginHandler)); // Notify plugins. while (index < arrayCount(plugins) && plugins[index] != none) { plugins[index].clientCreated(clientHandler); index++; } } /*************************************************************************************************** * * $DESCRIPTION Called when a player attempts to login to the server. Allows mutators to modify * some of the login parameters. * $PARAM spawnClass The PlayerPawn class to use for the player. * $PARAM portal Name of the portal where the player wishes to spawn. * $PARAM option Login option parameters. * **************************************************************************************************/ function modifyLogin(out class spawnClass, out string portal, out string options) { local int overrideCode; local int index; // Only continue if the login wasn't denied. if (spawnClass == none) { return; } // Check if the player isn't allowed to join the game as player. overrideCode = level.game.getIntOption(options, joinOverrideCodeOption, -1); if (gInf.bTeamsLocked && !isValidJoinOverrideCode(overrideCode)) { spawnClass = class'Botpack.CHSpectator'; } // Notify plugins. while (index < arrayCount(plugins) && plugins[index] != none) { plugins[index].modifyLogin(spawnClass, portal, options); index++; } // Allow other mutators to do their job. if (nextMutator != none) { nextMutator.modifyLogin(spawnClass, portal, options); } } /*************************************************************************************************** * * $DESCRIPTION Checks whether the given login override code is correct. * **************************************************************************************************/ function bool isValidJoinOverrideCode(int overrideCode) { local bool bValid; local bool bInvalid; local int index; // Check override code. while (!bValid && !bInvalid && index < arrayCount(joinOverrideCodes)) { if (joinOverrideCodes[index] == overrideCode) { // Check if lease has expired. if (timeSeconds - overrideCodeLeaseTimes[index] <= maxOverrideCodeLeaseTime) { bValid = true; } else { bInvalid = true; } // Clear override code. joinOverrideCodes[index] = -1; overrideCodeLeaseTimes[index] = 0; } else { index++; } } // Return result. return bValid; } /*************************************************************************************************** * * $DESCRIPTION Gives the specified client a login override code, so he or she can join a locked * game as player. * **************************************************************************************************/ function giveJoinOverrideCode(NexgenClient client) { local int index; local bool bFound; // Find a free slot. while (!bFound && index < arrayCount(joinOverrideCodes)) { // Check if current slot is free. if (joinOverrideCodes[index] < 0 || timeSeconds - overrideCodeLeaseTimes[index] > maxOverrideCodeLeaseTime) { // Slot is free, use this one. bFound = true; } else { // Nope, maybe next one. index++; } } // Create override code & send to client. if (bFound) { joinOverrideCodes[index] = rand(maxInt); overrideCodeLeaseTimes[index] = timeSeconds; client.updateLoginOption(joinOverrideCodeOption, joinOverrideCodes[index]); } } /*************************************************************************************************** * * $DESCRIPTION Checks if the login request of the specified client should be accepted. If the * request is rejected, this function will automatically kill the client. * $PARAM client The client whose login request is to be checked. * $REQUIRE client != none * **************************************************************************************************/ function checkLogin(NexgenClient client) { local string password; local bool bRejected; local string reason; local string banReason; local string banPeriod; local bool allowSpecReconnect; local int index; local int k; local string cs; local name rejectType; local string popupWindowClass; local string popupArgs[4]; // Get login options. password = class'NexgenUtil'.static.getProperty(client.loginOptions, client.SSTR_ServerPassword); // Log the login request. nscLog(lng.format(lng.loginRequestMsg, client.playerName)); nscLog(lng.format(lng.attrClientIPMsg, client.ipAddress)); nscLog(lng.format(lng.attrClientIDMsg, class'NexgenUtil'.static.formatGUID(client.playerID))); if (password != "") { nscLog(lng.format(lng.attrPasswordMsg, password)); } // Check login parameters. if (!loginHandler.static.checkLoginParameters(client)) { bRejected = true; rejectType = RT_IllegalLoginParameters; reason = lng.illegalLoginParametersMsg; popupWindowClass = "NexgenIllegalLoginDialog"; } // Check for duplicate ID's. if ((!bRejected) && !hasUniqueKey(client)) { bRejected = true; rejectType = RT_DuplicateID; reason = lng.duplicateIDMsg; popupWindowClass = "NexgenIDUsedDialog"; } // Check for bans. if ((!bRejected) && isBanned(client, banReason, banPeriod)) { bRejected = true; rejectType = RT_Banned; reason = lng.bannedMsg; popupWindowClass = "NexgenBannedDialog"; popupArgs[0] = banReason; popupArgs[1] = banPeriod; } // Check password. if ((!bRejected) && (sConf.matchModeActivated) && (sConf.serverPassword != "") && (password != sConf.decode(sConf.serverPassword)) && (!client.hasRight(client.R_NeedsNoPW)) && (!client.bSpectator || sConf.spectatorsNeedPassword)) { bRejected = true; rejectType = RT_InvalidPassword; reason = lng.invalidPassMsg; allowSpecReconnect = !client.bSpectator && !sConf.spectatorsNeedPassword; popupWindowClass = "NexgenPasswordDialog"; popupArgs[0] = string(allowSpecReconnect); } // Check slots. if ((!bRejected) && !canGetSlot(client)) { bRejected = true; rejectType = RT_ServerFull; reason = lng.serverCapacityMsg; popupWindowClass = "NexgenServerFullDialog"; popupArgs[0] = string(sConf.playerSlots); popupArgs[1] = string(sConf.vipSlots); popupArgs[2] = string(sConf.adminSlots); } // Check play rights. if ((!bRejected) && (!client.bSpectator) && (!client.hasRight(client.R_MayPlay))) { bRejected = true; rejectType = RT_NoPlayRight; reason = lng.noPlayRightMsg; popupWindowClass = "NexgenNoPlayRightDialog"; } // Get player data object for this client. setPlayerData(client); // Check with plugins. while (!bRejected && index < arrayCount(plugins) && plugins[index] != none) { bRejected = !plugins[index].checkLogin(client, rejectType, reason, popupWindowClass, popupArgs); index++; } // Accept or reject player. if (bRejected) { // Allow plugins to modify the rejection of this player. index = 0; while (index < arrayCount(plugins) && plugins[index] != none) { plugins[index].modifyLoginReject(client, rejectType, reason, popupWindowClass, popupArgs); index++; } // Reject the player. if (popupWindowClass != "") { client.showPopup(popupWindowClass, popupArgs[0], popupArgs[1], popupArgs[2], popupArgs[3]); } disconnectClient(client); nscLog(lng.format(lng.loginRejectedMsg, reason)); } else { // Send encryption paramters. Only players with an account receive the right paramters. if (client.bHasAccount) { sConf.getEncryptionParams(k, cs); } client.setEncryptionParams(k, cs); // Signal events. nscLog(lng.loginAcceptedMsg); playerJoined(client); } } /*************************************************************************************************** * * $DESCRIPTION Checks if the player ID of the specified client is unique. * $PARAM client The client whose player ID is to be checked. * $REQUIRE client != none * $RETURN True none of the other clients has the same player ID, false otherwise. * **************************************************************************************************/ function bool hasUniqueKey(NexgenClient client) { local bool bUnique; local NexgenClient currClient; // Compare each ID of the other clients with the ID of the specified client. bUnique = true; currClient = clientList; while (bUnique && currClient != none) { // Same ID? if (currClient != client && currClient.playerID ~= client.playerID) { bUnique = false; } // Compare ID with the next client. currClient = currClient.nextClient; } // Return result. return bUnique; } /*************************************************************************************************** * * $DESCRIPTION Checks if the specified client is banned on this server. * $PARAM client The client for which the ban is to be checked. * $PARAM banReason Description of why the client was banned. * $PARAM banPeriod Textual description indicating how long the player is banned. * $REQUIRE client != none * $RETURN True if the client is banned, false if not. * $ENSURE result == true ? new.banPeriod != "" : true * **************************************************************************************************/ function bool isBanned(NexgenClient client, out string banReason, out string banPeriod) { local int banIndex; local bool bBanned; // Get ban entry. banIndex = sConf.getBanIndex(client.playerName, client.ipAddress, client.playerID); // Check if player is banned and the ban hasn't expired. if (banIndex >= 0) { if (sConf.autoUpdateBans) { if (sConf.updateBan(banIndex, client.ipAddress, client.playerID)) { // Ban entry was changed, update dynamic config data checksum & notify clients. signalConfigUpdate(sConf.CT_BanList); } } banReason = sConf.banReason[banIndex]; banPeriod = lng.getBanPeriodDescription(sConf.banPeriod[banIndex]); bBanned = !sConf.isExpiredBan(banIndex); } // Return result. return bBanned; } /*************************************************************************************************** * * $DESCRIPTION Checks if the specified client can get a player slot on the server, i.e. the * server isn't full for this client. * $PARAM client The client for which is to be checked if a slot available. * $REQUIRE client != none * $RETURN True if there is an empty slot available that the specified client may occupy, * false if not. * *************