/*============================================================================= Name : MultiplayerGame.c Purpose : Logic for the multiplayergame setup. Created 6/22/1998 by ddunlop Copyright Relic Entertainment, Inc. All rights reserved. =============================================================================*/ #include #include #include "MultiplayerGame.h" #include "MultiplayerLANGame.h" #include "feflow.h" #include "utility.h" #include "scenpick.h" #include "uicontrols.h" #include "TitanInterfaceC.h" #include "titannet.h" #include "region.h" #include "mouse.h" #include "fontreg.h" #include "scroller.h" #include "linkedlist.h" #include "prim2d.h" #include "randy.h" #include "chatting.h" #include "commandnetwork.h" #include "globals.h" #include "msg\serverstatus.h" #include "ChannelFSM.h" #include "colpick.h" #include "mainswitches.h" #include "chatting.h" #include "strings.h" #include "queue.h" #include "titan.h" #include "file.h" #include "statscript.h" #include "titannet.h" #include "universe.h" #include "gamechat.h" #include "SaveGame.h" // for ConvertNumToPointerInList #ifdef HW_Debug #ifdef gshaw #define NEED_MIN_TWO_HUMAN_PLAYERS 0 #endif #endif /*============================================================================= Defines: =============================================================================*/ #define MG_FIBFile_SERVERS "FEMan\\Choose_Server.FIB" #define MG_FontNameLength 64 #define MG_VertSpacing (fontHeight(" ") >> 1) #define MG_HorzSpacing (fontWidth(" ")) // defines for type of sort for the list of games window #define MG_SortByGameName 0 #define MG_SortByPingTime 1 #define MG_SortByNumPlayers 2 #define MG_SortByMapName 3 #define MG_ServerSortByName 0 #define MG_ServerSortByDescription 1 #define MG_ServerSortByPing 2 #define MG_ServerSortByLoad 3 #define MG_ServerSortByReliability 4 // defines for the type of WON query #define MG_WONLogin 1 #define MG_WONNewUser 2 #define MG_WONChangePassword 3 #define PING_INTERVAL_TIME 1.0f //task parameters #define MG_TaskStackSize 4096 #define MG_TaskServicePeriod 0.25f // maximum chat history list window items #define MG_MaxChatHistory 300 #define MG_QUEUEBUFFERSIZE 50000 #define mg_ArrowInterSpacing 16 #define mg_ArrowMarginTop 4 #define mg_ArrowClickStart 4 //from top of region #define mgArrowClickSpacing 30 //base to base #define mgArrowClickHeight 12 //height of button // defines for which screen is currently active // enumeration for all of the screens in the multiplayer front end. /* enum { MGS_Connection_Method, MGS_Internet_Login, MGS_Password_Change, MGS_LAN_Login, MGS_Connecting, MGS_New_Account, MGS_Channel_Chat, MGS_Available_Channels, MGS_Player_Options, MGS_Create_Channel, MGS_Available_Games, MGS_Player_Wait, MGS_Captain_Wait, MGS_Basic_Options, MGS_Advanced_Options, MGS_Resource_Options, MGS_Basic_Options_Change, MGS_Advanced_Options_Change, MGS_Resource_Options_Change, MGS_Basic_Options_View, MGS_Advanced_Options_View, MGS_Resource_Options_View, MGS_Skirmish_Basic, MGS_Skirmish_Advanced, MGS_Skirmish_Resource, MGS_Game_Password, MGS_Quit_WON, MGS_Message_Box }; */ #define MG_JustOneDisappear 10 // This is the maximum number of items that can be transfered between threads // using the statically allocated arrays. #define MAX_NUM_ITEMS 40 #define MAX_NEW_CHAT_ITEMS 80 #define MG_WAIT_ACC 0.25f // These defines are used for the chat command interface real32 mgAccTime = 0.0f; /*============================================================================= Data: =============================================================================*/ sdword gameNum; // multiplayer game base region regionhandle mgBaseRegion = NULL; fibfileheader *mgScreensHandle = NULL; fibfileheader *mgScreensHandleServers = NULL; // booleans indicating the status of the user in the screens. sdword ConnectionType = -1; // is person waiting for a game ? int WaitingForGame = FALSE; // did the person create the game int GameCreator = FALSE; // is the person logged into WON bool LoggedIn = FALSE; // is this a LAN game - shared stuff int LanProtocalsValid = 0; // 1 indicates IPX, 2 indicates TCP/IP, 3 indicates both int LanProtocalButton = 0; // 0 indicates IPX, 1 indicates TCP/IP (same as IPGame) int LANGame = FALSE; // use int not bool becuase CPP gets confused with our bool's. int IPGame = 1; // DO NOT USE TRUE, use 1 or CPP gets confused // if we are using IP protocal (LAN or Internet) unsigned long firewallButton = FIREWALL_AUTODETECT; //bool8 mgLeftArrowActive = FALSE; //bool8 mgRightArrowActive = FALSE; bool8 mgHumanLeftArrowActive = FALSE; bool8 mgHumanRightArrowActive = FALSE; bool8 mgCPULeftArrowActive = FALSE; bool8 mgCPURightArrowActive = FALSE; //sdword mgArrowIndex = -1; sdword mgHumanArrowIndex = -1; sdword mgCPUArrowIndex = -1; // This flag is returned from the refresh task, will be changed when the observation server goes into effect. bool donerefreshing = TRUE; bool donepinging = TRUE; bool mgCreatingNetworkGame = FALSE; // structures and variables for creating a game. CaptainGameInfo tpGameCreated= // N P M D u p nc sf bs sr ii ia lt la ad ab p f {L"", L"", "", "", 0, 0,0,0, 0, 1, 3, 1, 1440, 2000, 19200, 2000, 50, 50, 0, 22058}; CaptainGameInfo BackupGameCreated; sdword spCurrentSelectedBack; char scenPickBack[]; Address myAddress; // tweakable fonthandles. fonthandle mgListOfGamesFont=0; fonthandle mgChatWindowFont=0; fonthandle mgUserNameFont=0; fonthandle mgCurrentChannelFont=0; fonthandle mgChannelListTitleFont=0; fonthandle mgChannelListFont=0; fonthandle mgGameListTitleFont=0; fonthandle mgGameChatFont=0; fonthandle mgGameUserNameFont=0; fonthandle mgCurrentGameFont=0; fonthandle mgOptionsFont=0; fonthandle mgConnectingFont=0; fonthandle mgMessageBoxFont=0; char mgListOfGamesFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgChatWindowFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgUserNameFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgCurrentChannelFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgChannelListTitleFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgChannelListFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgGameListTitleFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgGameChatFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgGameUserNameFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgCurrentGameFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgOptionsFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgConnectingFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; char mgMessageBoxFontName [MG_FontNameLength] = "Small_Fonts_8.hff"; // handles for the text entry boxes textentryhandle mgNameEntryBox = NULL; textentryhandle mgPasswordEntryBox = NULL; textentryhandle mgOldPasswordChangeEntryBox = NULL; textentryhandle mgNewPasswordChangeEntryBox = NULL; textentryhandle mgConfirmPasswordChangeEntryBox = NULL; textentryhandle mgChatTextEntryBox = NULL; textentryhandle mgChannelNameEntryBox = NULL; textentryhandle mgChannelDescriptionEntryBox = NULL; textentryhandle mgChannelPasswordEntryBox = NULL; textentryhandle mgChannelConfirmEntryBox = NULL; textentryhandle mgGameNameTextEntryBox = NULL; textentryhandle mgGameChatTextEntryBox = NULL; textentryhandle mgNewAccountPasswordEntryBox = NULL; textentryhandle mgNewAccountConfirmEntryBox = NULL; textentryhandle mgGamePasswordEntryBox = NULL; textentryhandle mgGamePasswordConfirmEntryBox = NULL; textentryhandle mgResourceInjectionIntervalEntryBox = NULL; textentryhandle mgResourceInjectionAmountEntryBox = NULL; textentryhandle mgResourceLumpSumIntervalEntryBox = NULL; textentryhandle mgResourceLumpSumAmountEntryBox = NULL; textentryhandle mgGamePasswordEntryEntryBox = NULL; // handles for all of the listwindow's listwindowhandle mgChatHistoryWindow = NULL; listwindowhandle mgUserNameWindowWindow = NULL; listwindowhandle mgListOfGamesWindow = NULL; listwindowhandle mgGameChatWindowWindow = NULL; listwindowhandle mgListOfChannelsWindow = NULL; listwindowhandle mgListOfServersWindow = NULL; listwindowhandle mgGameUserNameWindow = NULL; listwindowhandle mgConnectingStatusWindow = NULL; // colors for all of the tweakable colors in the screens. color mgGameWhisperedColor = colRGB(255,0,255); color mgGamePrivateChatColor = colRGB(20,255,50); color mgGameNormalChatColor = colRGB(180,180,180); color mgGameMessageChatColor = colRGB(255,255,0); color mgWhisperedColor = colRGB(255,0,255); color mgPrivateChatColor = colRGB(20,255,50); color mgNormalChatColor = colRGB(180,180,180); color mgMessageChatColor = colRGB(255,255,0); color mgUserNameColor = colRGB(180,180,180); color mgCurrentChannelColor = colRGB(20,200,20); color mgChannelTitleColor = colRGB(50,255,50); color mgChannelListNormalColor = colRGB(180,180,180); color mgChannelListSelectedColor= colRGB(255,255,255); color mgTitleFlashColor = colRGB(255,255,50); color mgGameListTitleColor = colRGB(50,255,50); color mgGameListNormalColor = colRGB(180,180,180); color mgGameListSelectedColor = colRGB(255,255,255); color mgGameListStartedColor = colRGB(100,100,100); color mgGameListDiffVersionColor= colRGB(140,140,140); color mgCurrentGameColor = colRGB(20,200,20); color mgNumberOfHumansColor = colRGB(20,200,20); color mgNumberOfComputersColor = colRGB(20,200,20); color mgConnectingStatusColor = colRGB(180,180,180); color mgMessageBoxColor = colRGB(180,180,180); // variable for flashing the title when it is clicked on. real32 mgTitleFlashTimer = 0.0f; // linked lists with the local copy of info for channels and stuff. // this linked list holds all of the current games in this channel LinkedList listofgames; // this list has all of the available channels in it LinkedList listofchannels; // this list has all of the servers in it (hwds) LinkedList listofservers; // this list has all of the Room chat history LinkedList listofchatinfo; // this list has all of the users in the Current Room in it LinkedList listofusersinfo; // this is the list of games to ping LinkedList listtoping; // this is the list of topics in the status window listbox LinkedList statusitemlist; // this is the list of players in the current game LinkedList listofplayers; // this is a temporary storage list for the players in a game to compare // and check if someone has joined or left. LinkedList listofplayersold; // this holds all of the history for the game chat window LinkedList listofgamechatinfo; // These lists are used to hold the list of people ignored or banned that are online LinkedList listofIgnoreUsers; LinkedList listofBannedUsers; typedef struct mgUserNameList { Node link; char name[MAX_PERSONAL_NAME_LEN]; } mgUserNameList; void mgProcessIgnore(char *name, char *retmessage); void mgProcessKick(char *name, char *retmessage); void mgProcessBan(char *name, char *retmessage); void mgProcessLimit(char *name, char *retmessage); typedef void (*mgCommandFunc)(char *name, char *retmessage); typedef struct mgCommandInfo { char *Command; mgCommandFunc callback; bool hasnamearg; bool captainonly; bool roomchat; bool pregamechat; } mgCommandInfo; mgCommandInfo *mgCommandInfoPtr; mgCommandInfo mgCommandEnglish[] = { // nam cap roo pre {"Ignore", mgProcessIgnore, 1, 0, 1, 0 }, {"Kick", mgProcessKick, 1, 1, 0, 1 }, {"Ban", mgProcessBan, 1, 1, 0, 1 }, {"Limit", mgProcessLimit, 0, 1, 0, 1 }, {"", NULL, 0, 1, 0, 1 } }; mgCommandInfo mgCommandFrench[] = { {"Ignorer", mgProcessIgnore, 1, 0, 1, 0 }, {"Exclure", mgProcessKick, 1, 1, 0, 1 }, {"Bannir", mgProcessBan, 1, 1, 0, 1 }, {"Limiter", mgProcessLimit, 0, 1, 0, 1 }, {"", NULL, 0, 1, 0, 1 } }; mgCommandInfo mgCommandGerman[] = { {"Ignorieren", mgProcessIgnore, 1, 0, 1, 0 }, {"Entfernen", mgProcessKick, 1, 1, 0, 1 }, {"Verbannen", mgProcessBan, 1, 1, 0, 1 }, {"Begrenzen", mgProcessLimit, 0, 1, 0, 1 }, {"", NULL, 0, 1, 0, 1 } }; mgCommandInfo mgCommandSpanish[] = { {"Ignorar", mgProcessIgnore, 1, 0, 1, 0 }, {"Acabar", mgProcessKick, 1, 1, 0, 1 }, {"Prohibición", mgProcessBan, 1, 1, 0, 1 }, {"Límite", mgProcessLimit, 0, 1, 0, 1 }, {"", NULL, 0, 1, 0, 1 } }; mgCommandInfo mgCommandItalian[] = { {"Ignora", mgProcessIgnore, 1, 0, 1, 0 }, {"Elimina", mgProcessKick, 1, 1, 0, 1 }, {"Bando", mgProcessBan, 1, 1, 0, 1 }, {"Limite", mgProcessLimit, 0, 1, 0, 1 }, {"", NULL, 0, 1, 0, 1 } }; bool gamestarted = FALSE; bool newscreen = FALSE; // Queue for transfering packets between threads. Queue mgThreadTransfer; // mutually exclusive handles for locking data between threads. void *changescreenmutex; void *gamestartedmutex; // info for spacing in the list of games screen sdword mgGameNameWidth = 150; sdword mgPingTimeWidth = 50; sdword mgNumPlayerWidth = 50; sdword mgMapNameWidth = 110; sdword mgGameNotesWidth = 100; // info for spacing in the list of channels screen sdword mgChannelNameWidth = 185; sdword mgChannelDescriptionWidth = 185; sdword mgChannelNumberWidth = 25; sdword mgChannelNotesWidth = 100; // info for spacing in the list of servers screen sdword mgServerNameWidth = 185; sdword mgServerDescriptionWidth = 185; sdword mgServerPingWidth = 50; sdword mgServerLoadWidth = 50; sdword mgServerReliabilityWidth = 50; // for pinging the servers list BabyCallBack *pingserversbaby=NULL; udword pingservernum = 0; // for refreshing the game list BabyCallBack *refreshbaby=NULL; // for pinging all of the games BabyCallBack *pinggamesbaby=NULL; // is the multiplayer game screens running. bool mgRunning=FALSE; // currently active screen sdword currentScreen=-1; // last active screen sdword lastScreen=-1; // used for starting a screen in a separate thread. sdword screenaskedfor=-1; //sdword mgScreensAdded=0; bool hideallscreens=TRUE; // type of query asked for from titan. sdword mgQueryType=-1; // handle for the task that transfers the informatoin from titan to the main game thread. taskhandle ProccessCallback=0; // pointer to the game that we want to join tpscenario *joingame=NULL; // room we want to join wchar_t joinchannelname[MAX_CHANNEL_NAME_LEN] = L""; wchar_t joinchanneldescription[MAX_CHANNEL_DESCRIPTION_LEN] = L""; // string that is displayed in the message box char messageBoxString[256]; char messageBoxString2[256]; // userid of this player udword mgMyChatUserID=0; // variable that indicates which screen is displayed after a user hits cancel on the conneting screen sdword mgConnectingScreenGoto=-1; // pre set games GameTypes *preSetGames = NULL; // variables for the hokey color and race picker screen udword BaseColorSave; udword StripeColorSave; uword RaceSave; bool refreshChannelsScreenRequest = FALSE; bool refreshServersScreenRequest = FALSE; extern color PATCHBARCOLOR; extern color PATCHBAROUTLINECOLOR; //bool tempstartship; //need to update titannet.h for captaingameinfo // this is the width in pixels of the chat windows sdword chatwindowwidth = 384-20; // patch variables int patchLenSoFar = 0; int patchTotalLen = 0; int patchErrorMsg = 0; int patchAbortRequest = 0; int patchComplete = 0; #if PUBLIC_BETA // public beta variables int betaVerifying = 0; int betaVerified = 0; int betaDoneVerifying = 0; #endif // temporary variable for storing name, in case of cancel char tempname[64]; wchar_t GameWereInterestedIn[MAX_TITAN_GAME_NAME_LEN] = L""; void *GameWereInterestedInMutex; CaptainGameInfo joinBackuptpGameCreated; bool joinBackuptpGameCreatedValid = FALSE; udword mgPlayerLimit = 0; /*============================================================================= Function Callback Prototypes: =============================================================================*/ // Callbacks for the connection type screen. void mgConnectionBack (char *name, featom *atom); void mgSkirmish (char *name, featom *atom); void mgLANIPX (char *name, featom *atom); void mgInternetWON (char *name, featom *atom); // Callbacks for the Login screen to Internet WON void mgPasswordEntry (char *name, featom *atom); void mgChangePassword (char *name, featom *atom); void mgNewAccount (char *name, featom *atom); void mgLaunchWON (char *name, featom *atom); void mgFirewallButton (char *name, featom *atom); // Shared between the internet screen and the lan screen void mgNameEntry (char *name, featom *atom); void mgBackToConnection (char *name, featom *atom); // Callbacks for the Password Changer Screen. void mgOldPasswordChangeEntry (char *name, featom *atom); void mgNewPasswordChangeEntry (char *name, featom *atom); void mgConfirmPasswordChangeEntry (char *name, featom *atom); void mgChangePasswordBack (char *name, featom *atom); void mgChangePasswordNow (char *name, featom *atom); // Callbacks from the new account Screen. void mgNewAccountPassword (char *name, featom *atom); void mgNewAccountConfirm (char *name, featom *atom); void mgNewAccountBack (char *name, featom *atom); void mgCreateNewAccountNow (char *name, featom *atom); // Callbacks for the channel chatting screen. void mgChatTextEntry (char *name, featom *atom); void mgViewChannels (char *name, featom *atom); void mgViewGames (char *name, featom *atom); void mgCreateGame (char *name, featom *atom); void mgBackToLogin (char *name, featom *atom); void mgChangeColors (char *name, featom *atom); void mgChatWindowInit (char *name, featom *atom); void mgUserNameWindowInit (char *name, featom *atom); void mgCurrentChannelDraw (featom *atom, regionhandle region); // Callbacks for the Channel Picker screen. void mgJoinChannel (char *name, featom *atom); void mgCreateChannel (char *name, featom *atom); void mgBackToChannelChat (char *name, featom *atom); void mgListOfChannelsInit (char *name, featom *atom); // Callbacks for the Channel Creation Screen. void mgChannelNameEntry (char *name, featom *atom); void mgChannelDescriptionEntry (char *name, featom *atom); void mgChannelProtected (char *name, featom *atom); void mgChannelPasswordEntry (char *name, featom *atom); void mgChannelConfirmEntry (char *name, featom *atom); void mgCreateChannelNow (char *name, featom *atom); void mgBackToAvailableChannels (char *name, featom *atom); // Callbacks for the Available Games screen. void mgPingAllGames (char *name, featom *atom); void mgSeeDetails (char *name, featom *atom); void mgJoinGame (char *name, featom *atom); void mgListOfGamesInit (char *name, featom *atom); void mgListOfGamesBack (char *name, featom *atom); bool Refresh (udword num, void *data, struct BabyCallBack *baby); bool PingAllGames (udword num, void *data, struct BabyCallBack *baby); bool PingAllServers (udword num, void *data, struct BabyCallBack *baby); // Callbacks for the waiting for game screens. void mgGameChatWindowInit (char *name, featom *atom); void mgGameUserNameWindowInit (char *name, featom *atom); void mgViewDetails (char *name, featom *atom); void mgLeaveGame (char *name, featom *atom); void mgSetupGame (char *name, featom *atom); void mgStartGame (char *name, featom *atom); void mgGameChatTextEntry (char *name, featom *atom); void mgCurrentGameDraw (featom *atom, regionhandle region); // Callbacks for the Basic Game Options game screen. void mgCreateGameNow (char *name, featom *atom); void mgGameNameTextEntry (char *name, featom *atom); void mgChooseScenario (char *name, featom *atom); //void mgAddOpponent (char *name, featom *atom); //void mgRemoveOpponent (char *name, featom *atom); void mgAddCPUOpponent (featom *atom, regionhandle region); void mgRemoveCPUOpponent (featom *atom, regionhandle region); void mgPickGameType (char *name, featom *atom); void mgStartingFleet (char *name, featom *atom); void mgStartShip (char *name, featom *atom); void mgGameType (char *name, featom *atom); void mgNumberOfComputers (featom *atom, regionhandle region); //void mgLeftArrowDraw(featom *atom, regionhandle region); //void mgRightArrowDraw(featom *atom, regionhandle region); //void mgLeftArrowDraw(featom *atom, regionhandle region); //void mgRightArrowDraw(featom *atom, regionhandle region); // Callbacks for the Advanced Options game Screen. void mgHyperspace (char *name, featom *atom); void mgAlliedVictory (char *name, featom *atom); void mgLastMotherShip (char *name, featom *atom); void mgCaptureCapitalShip (char *name, featom *atom); void mgResearchEnabled (char *name, featom *atom); //void mgBountiesEnabled (char *name, featom *atom); void mgBountySize (char *name, featom *atom); void mgPasswordProtected (char *name, featom *atom); void mgGamePassword (char *name, featom *atom); void mgGamePasswordConfirm (char *name, featom *atom); void mgUnitCapsEnabled (char *name, featom *atom); void mgFuelBurnEnabled (char *name, featom *atom); void mgCratesEnabled (char *name, featom *atom); // Callbacks for the Resourceing Optinos game Screen. void mgHarvestingEnabled (char *name, featom *atom); void mgStartingResources (char *name, featom *atom); void mgResourceInjections (char *name, featom *atom); void mgResourceInjectionInterval (char *name, featom *atom); void mgResourceInjectionAmount (char *name, featom *atom); void mgResourceLumpSum (char *name, featom *atom); void mgResourceLumpSumInterval (char *name, featom *atom); void mgResourceLumpSumAmount (char *name, featom *atom); // Callbacks shared by all of the Game Options screens void mgBackFromOptions (char *name, featom *atom); void mgBasicOptions (char *name, featom *atom); void mgAdvancedOptions (char *name, featom *atom); void mgResourceOptions (char *name, featom *atom); // Callbacks for the Player options screen. void mgSetColorsNow (char *name, featom *atom); void mgBackFromPlayerOptions (char *name, featom *atom); // Callbacks for the Connecting Status screen. void mgConnectingStatusInit (char *name, featom *atom); void mgConnectingCancel (char *name, featom *atom); // Callbacks for the game entry screen. void mgGamePasswordEntry (char *name, featom *atom); void mgBackFromPassword (char *name, featom *atom); void mgGoPassword (char *name, featom *atom); void mgBackFromRoomPassword (char *name, featom *atom); void mgGoRoomPassword (char *name, featom *atom); // Callbacks for the quit WON question screen. void mgYesQuitWON (char *name, featom *atom); void mgDontQuitWON (char *name, featom *atom); // Callbacks for downloading patch void mgYesDownloadPatch (char *name, featom *atom); void mgNoDownloadPatch (char *name, featom *atom); void mgDrawPatchProgress (featom *atom, regionhandle region); void mgAbortDownloadPatch (char *name, featom *atom); // Callbacks from the message box screen. void mgMessageOk (char *name, featom *atom); void mgDrawMessageBox (featom *atom, regionhandle region); // Callbacks for choose servers void mgGoChooseServer (char *name, featom *atom); void mgCancelChooseServer (char *name, featom *atom); void mgListOfServersInit (char *name, featom *atom); /*============================================================================= Function Prototypes for the draw callbacks: =============================================================================*/ /*============================================================================= List of Callbacks for adding to the region processor: =============================================================================*/ fecallback mgCallBack[]= { // Callbacks for the connection type screen. {mgConnectionBack , "MG_ConnectionBack" }, {mgSkirmish , "MG_Skirmish" }, {mgLANIPX , "MG_LANIPX" }, {mgInternetWON , "MG_InternetWON" }, // Callbacks for the Login screen to Internet WON {mgPasswordEntry , "MG_PasswordEntry" }, {mgChangePassword , "MG_ChangePassword" }, {mgNewAccount , "MG_NewAccount" }, {mgLaunchWON , "MG_LaunchWON" }, {mgFirewallButton , "MG_FirewallButton" }, // Shared between the internet screen and the lan screen {mgNameEntry , "MG_NameEntry" }, {mgBackToConnection , "MG_BackToConnection" }, // Callbacks for the Password Changer Screen. {mgOldPasswordChangeEntry , "MG_OldPasswordChangeEntry" }, {mgNewPasswordChangeEntry , "MG_NewPasswordChangeEntry" }, {mgConfirmPasswordChangeEntry , "MG_ConfirmPasswordChangeEntry" }, {mgChangePasswordBack , "MG_ChangePasswordBack" }, {mgChangePasswordNow , "MG_ChangePasswordNow" }, // Callbacks from the new account Screen. {mgNewAccountPassword , "MG_NewAccountPassword" }, {mgNewAccountConfirm , "MG_NewAccountConfirm" }, {mgNewAccountBack , "MG_NewAccountBack" }, {mgCreateNewAccountNow , "MG_CreateNewAccountNow" }, // Callbacks for the channel chatting screen. {mgChatTextEntry , "MG_ChatTextEntry" }, {mgViewChannels , "MG_ViewChannels" }, {mgViewGames , "MG_ViewGames" }, {mgCreateGame , "MG_CreateGame" }, {mgBackToLogin , "MG_BackToLogin" }, {mgChangeColors , "MG_ChangeColors" }, {mgChatWindowInit , "MG_ChatHistoryWindow" }, {mgUserNameWindowInit , "MG_UserNameWindow" }, // Callbacks for the Channel Picker screen. {mgJoinChannel , "MG_JoinChannel" }, {mgCreateChannel , "MG_CreateChannel" }, {mgBackToChannelChat , "MG_BackToChannelChat" }, {mgListOfChannelsInit , "MG_ListOfChannels" }, // Callbacks for the Channel Creation Screen. {mgChannelNameEntry , "MG_ChannelNameEntry" }, {mgChannelDescriptionEntry , "MG_ChannelDescriptionEntry" }, {mgChannelProtected , "MG_ChannelProtected" }, {mgChannelPasswordEntry , "MG_ChannelPasswordEntry" }, {mgChannelConfirmEntry , "MG_ChannelConfirmEntry" }, {mgCreateChannelNow , "MG_CreateChannelNow" }, {mgBackToAvailableChannels , "MG_BackToAvailableChannels" }, // Callbacks for the Available Games screen. {mgPingAllGames , "MG_PingAllGames" }, {mgSeeDetails , "MG_SeeDetails" }, {mgJoinGame , "MG_JoinGame" }, {mgListOfGamesInit , "MG_ListOfGames" }, {mgListOfGamesBack , "MG_ListOfGamesBack" }, // Callbacks for the waiting for game screens. {mgGameChatWindowInit , "MG_GameChatWindow" }, {mgGameUserNameWindowInit , "MG_GameUserName" }, {mgViewDetails , "MG_ViewDetails" }, {mgLeaveGame , "MG_LeaveGame" }, {mgSetupGame , "MG_SetupGame" }, {mgStartGame , "MG_StartGame" }, {mgGameChatTextEntry , "MG_GameChatTextEntry" }, // Callbacks for the Basic Game Options screen. {mgCreateGameNow , "MG_CreateGameNow" }, {mgGameNameTextEntry , "MG_GameNameTextEntry" }, {mgChooseScenario , "MG_ChooseScenario" }, {mgPickGameType , "MG_PickGameType" }, {mgStartingFleet , "MG_StartingFleet" }, {mgStartShip , "MG_StartShip" }, {mgGameType , "MG_GameType" }, // Callbacks for the Advanced Options game Screen. {mgHyperspace , "MG_Hyperspace" }, {mgAlliedVictory , "MG_AlliedVictory" }, {mgLastMotherShip , "MG_LastMotherShip" }, {mgCaptureCapitalShip , "MG_CaptureCapitalShip" }, {mgResearchEnabled , "MG_ResearchEnabled" }, //{mgBountiesEnabled , "MG_BountiesEnabled" }, {mgBountySize , "MG_BountySize" }, {mgPasswordProtected , "MG_PasswordProtected" }, {mgGamePassword , "MG_GamePassword" }, {mgGamePasswordConfirm , "MG_GamePasswordConfirm" }, {mgUnitCapsEnabled , "MG_UnitCapsEnabled" }, {mgFuelBurnEnabled , "MG_NoFuelBurn" }, {mgCratesEnabled , "MG_CratesEnabled" }, // Callbacks for the Resourceing Optinos game Screen. {mgHarvestingEnabled , "MG_HarvestingEnabled" }, {mgStartingResources , "MG_StartingResources" }, {mgResourceInjections , "MG_ResourceInjections" }, {mgResourceInjectionInterval , "MG_ResourceInjectionInterval" }, {mgResourceInjectionAmount , "MG_ResourceInjectionAmount" }, {mgResourceLumpSum , "MG_ResourceLumpSum" }, {mgResourceLumpSumInterval , "MG_ResourceLumpSumInterval" }, {mgResourceLumpSumAmount , "MG_ResourceLumpSumAmount" }, // Callbacks shared by all of the Game Options screens {mgBackFromOptions , "MG_BackFromOptions" }, {mgBasicOptions , "MG_BasicOptions" }, {mgAdvancedOptions , "MG_AdvancedOptions" }, {mgResourceOptions , "MG_ResourceOptions" }, // Callbacks for the Player options screen. {mgSetColorsNow , "MG_SetColorsNow" }, {mgBackFromPlayerOptions , "MG_BackFromPlayerOptions" }, // Callbacks for the scenario picker screen. In scenpick.h {spDonePicking , "CS_Done" }, {spBackPicking , "CS_Back" }, // {spScroller , "CS_Scroller" }, // Callbacks for the Connecting Status screen. {mgConnectingStatusInit , "MG_ConnectingStatus" }, {mgConnectingCancel , "MG_ConnectingCancel" }, // Callbacks for the password entry screen. {mgGamePasswordEntry , "MG_GamePasswordEntry" }, {mgBackFromPassword , "MG_BackFromPassword" }, {mgGoPassword , "MG_GoPassword" }, // Callbacks for the password entry screen. {mgGamePasswordEntry , "MG_RoomPasswordEntry" }, {mgBackFromRoomPassword , "MG_BackFromRoomPassword" }, {mgGoRoomPassword , "MG_GoRoomPassword" }, // Callbacks from the are you sure, WON quit screen {mgYesQuitWON , "MG_YesQuitWON" }, {mgDontQuitWON , "MG_DontQuitWON" }, // Callbacks from the message box screen. {mgMessageOk , "MG_MessageOk" }, {mgYesDownloadPatch , "MG_YesDownloadPatch" }, {mgNoDownloadPatch , "MG_NoDownloadPatch" }, {mgAbortDownloadPatch , "MG_AbortDownloadPatch" }, {NULL , NULL } }; fecallback mgCallBackServers[] = { { mgGoChooseServer , "MG_GoChooseServer" }, { mgCancelChooseServer , "MG_CancelChooseServer" }, { mgListOfServersInit , "MG_ListOfServers" }, {NULL , NULL } }; fedrawcallback mgDrawCallback[] = { {mgCurrentChannelDraw , "MG_CurrentChannel" }, {mgCurrentGameDraw , "MG_CurrentGame" }, {mgNumberOfComputers , "MG_NumberOfComputers" }, {mgDrawMessageBox , "MG_DrawMessageBox" }, {mgAddCPUOpponent , "MG_AddCPUOpponent" }, {mgRemoveCPUOpponent , "MG_RemoveCPUOpponent" }, {mgDrawPatchProgress , "MG_DrawPatchProgress" }, {NULL , NULL } }; #if 0 fedrawcallback mgDrawCallbackServers[] = { {NULL , NULL } }; #endif void mgProcessCallBacksTask(void); void mgGameTypeScriptInit(); /*============================================================================= Functions: =============================================================================*/ /*----------------------------------------------------------------------------- Name : mgBackuptpGameCreated Description : called whenever tpGameCreated will be overwritten due to joining game, etc. Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void mgBackuptpGameCreated(void) { if (joinBackuptpGameCreatedValid) { return; // already backed up } else if (!GameCreator) { joinBackuptpGameCreated = tpGameCreated; joinBackuptpGameCreatedValid = TRUE; } } /*----------------------------------------------------------------------------- Name : mgRestoretpGameCreated Description : will restore tpGameCreated if it was overwritten due to joining game, etc. Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void mgRestoretpGameCreated(void) { if (joinBackuptpGameCreatedValid) { tpGameCreated = joinBackuptpGameCreated; joinBackuptpGameCreatedValid = FALSE; } } /*----------------------------------------------------------------------------- Name : mgResetNamePassword Description : resets the name and password, other attributes which you think should be reset everytime person creates a new game. Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void mgResetNamePassword(void) { tpGameCreated.Name[0] = 0; tpGameCreated.Password[0] = 0; bitClear(tpGameCreated.flag,MG_PasswordProtected); } void mgGameInterestedIn(wchar_t *interested) { LockMutex(GameWereInterestedInMutex); wcscpy(GameWereInterestedIn,interested); UnLockMutex(GameWereInterestedInMutex); } void mgGameInterestedOff() { LockMutex(GameWereInterestedInMutex); GameWereInterestedIn[0] = 0; UnLockMutex(GameWereInterestedInMutex); } // this function parses the chat message entered and checks to see if they wanted to send // a private message. It has to search through two different lists of users, depending // on whether it is in game chat or the room chat that they are typing in. void *mgParseChatEntry(char *messageorig, bool preGameChat) { udword i,nummatches; char toname[64], ampremoved[64], messagetmp[280], *message; bool done=FALSE; Node *walk=NULL; userlist *user, *matched=NULL; gameplayerinfo *guser, *gmatched=NULL; message = (char *)&messagetmp[0]; memset(messagetmp, 0, 280); gcRemoveAmpersands(message, messageorig); // if not private at all then return NULL if (message[0]!='/') return(NULL); message++; i=0; if (message[0] == 0) done = TRUE; while (!done) { // copy the name over character by character toname[i] = message[0]; i++; toname[i]=0; message++; // do we already know that it is a match? if (matched==NULL) { // no then see if we can exclude all but one name nummatches = 0; if (!preGameChat) { walk = listofusersinfo.head; while (walk != NULL) { user = listGetStructOfNode(walk); gcRemoveAmpersands(ampremoved, user->userName); if (strnicmp(ampremoved,toname,i)==0) { // found a match so far matched = user; nummatches++; } walk = walk->next; } if (nummatches!=1) { // more than one possible match, then we must search again matched=NULL; } } else { walk = listofplayers.head; while (walk != NULL) { guser = listGetStructOfNode(walk); gcRemoveAmpersands(ampremoved, guser->name); if (strnicmp(ampremoved,toname,i)==0) { // found a match so far gmatched = guser; nummatches++; } walk = walk->next; } if (nummatches!=1) { // more than one possible match, then we must search again gmatched=NULL; } } } if (!preGameChat) { if (matched != NULL) { return (matched); } } else { if (gmatched != NULL) { return (gmatched); } } if (message[0] == 0) { done = TRUE; } } return NULL; } void *mgCompleteRoomPlayerName(char *message, char *compname, bool preGameChat) { udword i,nummatches; char toname[64], ampremoved[64]; bool done=FALSE; Node *walk=NULL; userlist *user, *matched=NULL; gameplayerinfo *guser, *gmatched=NULL; while (message[0] == ' ') message++; i=0; if (message[0] == 0) done = TRUE; while (!done) { // copy the name over character by character toname[i] = message[0]; i++; toname[i]=0; message++; // do we already know that it is a match? if (matched==NULL) { // no then see if we can exclude all but one name nummatches = 0; if (!preGameChat) { walk = listofusersinfo.head; while (walk != NULL) { user = listGetStructOfNode(walk); gcRemoveAmpersands(ampremoved, user->userName); if (strnicmp(ampremoved,toname,i)==0) { // found a match so far matched = user; nummatches++; } walk = walk->next; } if (nummatches!=1) { // more than one possible match, then we must search again matched=NULL; } } else { walk = listofplayers.head; while (walk != NULL) { guser = listGetStructOfNode(walk); gcRemoveAmpersands(ampremoved, guser->name); if (strnicmp(ampremoved,toname,i)==0) { // found a match so far gmatched = guser; nummatches++; } walk = walk->next; } if (nummatches!=1) { // more than one possible match, then we must search again gmatched=NULL; } } } if (!preGameChat) { if (matched != NULL) { strcpy(compname, ((userlist *)matched)->userName); return (matched); } } else { if (gmatched != NULL) { strcpy(compname, ((gameplayerinfo *)gmatched)->name); return (gmatched); } } if (message[0] == 0) { done = TRUE; } } return NULL; } Node *mgIsUserInList(LinkedList *list, char *name) { Node *search = list->head; mgUserNameList *namestruct; while (search != NULL) { namestruct = (mgUserNameList *)listGetStructOfNode(search); if (strnicmp(name, namestruct->name, MAX_PERSONAL_NAME_LEN)==0) { return(search); } search = search->next; } return(NULL); } void mgProcessIgnore(char *name, char *retmessage) { mgUserNameList *newname; Node *search; if ((search=mgIsUserInList(&listofIgnoreUsers,name))==NULL) { newname = (mgUserNameList *)memAlloc(sizeof(mgUserNameList),"IgnoreUserList",NonVolatile); strcpy(newname->name,name); listAddNode(&listofIgnoreUsers, &newname->link, (void *)newname); sprintf(retmessage, strGetString(strCommandIgnoreOn), name); } else { listDeleteNode(search); sprintf(retmessage, strGetString(strCommandIgnoreOff), name); } } void mgProcessKick(char *name, char *retmessage) { Node *node; gameplayerinfo *pinfo; retmessage[0] = 0; if (!GameCreator) { return; } // find player in list listofplayers for (node = listofplayers.head; node != NULL; node = node->next) { pinfo = (gameplayerinfo *)listGetStructOfNode(node); if (strcmp(pinfo->name,name) == 0) { if (titanKickPlayer(pinfo->index)) { sprintf(retmessage, strGetString(strCommandKickCaptain), name); } } } } void mgProcessBan(char *name, char *retmessage) { mgUserNameList *newname; Node *search; if ((search=mgIsUserInList(&listofBannedUsers,name))==NULL) { newname = (mgUserNameList *)memAlloc(sizeof(mgUserNameList),"BanUserList",NonVolatile); strcpy(newname->name,name); listAddNode(&listofBannedUsers, &newname->link, (void *)newname); sprintf(retmessage, strGetString(strCommandBanOn), name); } else { listDeleteNode(search); sprintf(retmessage, strGetString(strCommandBanOff), name); } } bool mgIsUserBanned(char *name) { if (mgIsUserInList(&listofBannedUsers,name) != NULL) { return(TRUE); } else { return(FALSE); } } void mgProcessLimit(char *name, char *retmessage) { udword limit = 0; limit = atoi(name); if ((limit > 1) && (limit < MAX_MULTIPLAYER_PLAYERS)) { mgPlayerLimit = limit; sprintf(retmessage, strGetString(strCommandLimit), limit); } else { mgPlayerLimit = 0; sprintf(retmessage, strGetString(strCommandLimitOff)); } return; } sdword mgCommandEntered(char *text, bool preGameChat) { char *parse=text, *space=text; sdword i=0, command=-1; if (parse[0] == '!') { parse++; while ((space[0] != ' ') && (space[0] != 0)) space++; while (mgCommandInfoPtr[i].callback != NULL) { if ((strnicmp(parse, mgCommandInfoPtr[i].Command, max(strlen(mgCommandInfoPtr[i].Command),space-text-1))==0) && (space[0] == ' ') && ( ((GameCreator) && (mgCommandInfoPtr[i].captainonly)) || ((preGameChat)&&(mgCommandInfoPtr[i].pregamechat)) || ((!preGameChat)&&(mgCommandInfoPtr[i].roomchat))) ) { command = i; break; } i++; } return (command); } else { return(-1); } } sdword mgCommandExecute(char *text, char *retmessage, bool preGameChat) { sdword command; char *name = text; command = mgCommandEntered(text, preGameChat); if (command != -1) { name += 1 + strlen(mgCommandInfoPtr[command].Command); while (name[0] == ' ') name++; mgCommandInfoPtr[command].callback(name, retmessage); } return(command); } sdword mgCommandComplete(char *text, char *commandstr, bool preGameChat) { sdword j,i,nummatches, command=-1; char toname[64], compname[64]; bool done=FALSE; bool matched=FALSE; // if not command at all then return NULL if (text[0]!='!') return(-1); if ((command = mgCommandEntered(text,preGameChat)) == -1) { text++; i=0; if (text[0] == 0) done = TRUE; while (!done) { // copy the name over character by character toname[i] = text[0]; i++; toname[i]=0; text++; // do we already know that it is a match? if (command==-1) { // no then see if we can exclude all but one name nummatches = 0; for (j=0;mgCommandInfoPtr[j].callback != NULL;j++) { if ((strnicmp(toname, mgCommandInfoPtr[j].Command, strlen(toname))==0) && ( ((GameCreator) && (mgCommandInfoPtr[j].captainonly)) || ((preGameChat)&&(mgCommandInfoPtr[j].pregamechat)) || ((!preGameChat)&&(mgCommandInfoPtr[j].roomchat))) ) { command = j; nummatches++; } } if (nummatches != 1) { command = -1; } } if (command != -1) { sprintf(commandstr, "!%s ", mgCommandInfoPtr[command].Command); return (command); } if (text[0] == 0) { done = TRUE; } } } else if (mgCommandInfoPtr[command].hasnamearg) { text += 1 + strlen(mgCommandInfoPtr[command].Command); if (mgCompleteRoomPlayerName(text, compname, FALSE)!=NULL) { sprintf(commandstr, "!%s %s", mgCommandInfoPtr[command].Command, compname); return (command); } } return (-1); } /*----------------------------------------------------------------------------- Name : mgScreensDisappear Description : a wrapper for front end screens. It makes all screens added dissapear; Inputs : Outputs : Return : void ----------------------------------------------------------------------------*/ void mgScreensDisappear(void) { while (feStackIndex > 0) { feScreenDisappear(NULL,NULL); } } /*----------------------------------------------------------------------------- Name : mgDisplayScreen Description : a wrapper for front end screens, cleans up the current screen and displays the screen asked for. Inputs : Outputs : Return : void ----------------------------------------------------------------------------*/ void mgShowScreen(sdword screennum, bool disappear) { char screenname[64]; sdword curscreen=currentScreen; if (disappear != FALSE) { if (disappear == MG_JustOneDisappear) { // just hide one screen feScreenDisappear(NULL,NULL); currentScreen = lastScreen; } else { // hide all of the screens mgScreensDisappear(); } } if (screennum != -1) { switch (screennum) { case MGS_Connection_Method : strcpy(screenname, "Connection_Method"); break; case MGS_Internet_Login : strcpy(screenname, "Internet_Login"); break; case MGS_Password_Change : strcpy(screenname, "Password_Change"); break; case MGS_LAN_Login : strcpy(screenname, "LAN_Login"); break; case MGS_Connecting : strcpy(screenname, "Connecting"); break; case MGS_New_Account : strcpy(screenname, "New_Account"); break; case MGS_Channel_Chat : strcpy(screenname, "Channel_Chat"); break; case MGS_Available_Channels : strcpy(screenname, "Available_Channels"); break; case MGS_Player_Options : strcpy(screenname, "Player_Options"); break; case MGS_Create_Channel : strcpy(screenname, "Create_Channel"); break; case MGS_Available_Games : strcpy(screenname, "Available_Games"); break; case MGS_Player_Wait : strcpy(screenname, "Player_Wait"); break; case MGS_Captain_Wait : strcpy(screenname, "Captain_Wait"); break; case MGS_Basic_Options : strcpy(screenname, "Basic_Options"); break; case MGS_Advanced_Options : strcpy(screenname, "Advanced_Options"); break; case MGS_Resource_Options : strcpy(screenname, "Resource_Options"); break; case MGS_Skirmish_Basic : strcpy(screenname, "Skirmish_Basic"); break; case MGS_Skirmish_Advanced : strcpy(screenname, "Skirmish_Advanced"); break; case MGS_Skirmish_Resource : strcpy(screenname, "Skirmish_Resource"); break; case MGS_Game_Password : strcpy(screenname, "Game_Password"); break; case MGS_Room_Password : strcpy(screenname, "Room_Password"); break; case MGS_Quit_WON : strcpy(screenname, "Quit_WON"); break; case MGS_Message_Box : strcpy(screenname, "Message_Box"); break; case MGS_Download_Patch: strcpy(screenname, "Download_Patch"); break; case MGS_Downloading_Patch: strcpy(screenname, "Downloading_Patch"); break; case MGS_Basic_Options_Change : strcpy(screenname, "Basic_Options_Change"); break; case MGS_Advanced_Options_Change: strcpy(screenname, "Advanced_Options_Change"); break; case MGS_Resource_Options_Change: strcpy(screenname, "Resource_Options_Change"); break; case MGS_Basic_Options_View: strcpy(screenname, "Basic_Options_View"); break; case MGS_Advanced_Options_View: strcpy(screenname, "Advanced_Options_View"); break; case MGS_Resource_Options_View: strcpy(screenname, "Resource_Options_View"); break; //LAN screens case LGS_LAN_Login : strcpy(screenname, "LLAN_Login"); break; case LGS_Channel_Chat : strcpy(screenname, "LChannel_Chat"); break; case LGS_Player_Options : strcpy(screenname, "Player_Options"); break; case LGS_Available_Games : strcpy(screenname, "LAvailable_Games"); break; case LGS_Player_Wait : strcpy(screenname, "LPlayer_Wait"); break; case LGS_Captain_Wait : strcpy(screenname, "LCaptain_Wait"); break; case LGS_Quit_WON : strcpy(screenname, "LQuit_WON"); break; case LGS_Message_Box : strcpy(screenname, "LMessage_Box"); break; case LGS_Game_Password : strcpy(screenname, "LGame_Password"); break; // Choose Server screens case MGS_Choose_Server: strcpy(screenname, "ChooseServer"); break; default: dbgFatal(DBG_Loc,"Unknown MultiplayerGame screen to display"); break; } // start the screen that we want mgBaseRegion = feScreenStart(ghMainRegion, screenname); currentScreen = screennum; } lastScreen = curscreen; } /*============================================================================= Functions for locking and unlocking mutualy exclusive blocks of code.: =============================================================================*/ /*----------------------------------------------------------------------------- Name : LockMutex Description : Inputs : Outputs : Return : void ----------------------------------------------------------------------------*/ void LockMutex(void *mutex) { DWORD result = WaitForSingleObject((HANDLE)mutex, INFINITE); dbgAssert(result != WAIT_FAILED); } /*----------------------------------------------------------------------------- Name : UnLockMutex Description : Inputs : Outputs : Return : void ----------------------------------------------------------------------------*/ void UnLockMutex(void *mutex) { BOOL result = ReleaseMutex((HANDLE)mutex); dbgAssert(result); } /*----------------------------------------------------------------------------- Name : CreateMutex Description : creates a mutex Inputs : Outputs : Return : returns mutex ----------------------------------------------------------------------------*/ void *gameCreateMutex() { return (void *)CreateMutex(NULL,FALSE,NULL); } /*----------------------------------------------------------------------------- Name : CloseMutex Description : closes a mutex Inputs : mutex Outputs : Return : ----------------------------------------------------------------------------*/ void gameCloseMutex(void *mutex) { CloseHandle((HANDLE)mutex); } /*============================================================================= Miscelanious functions to encapsulate certain repetetive things.: =============================================================================*/ // this function adds a chat message to the room chat window void mgAddChatToRoomChat(chatlist *newchat, listwindowhandle listwindow, LinkedList *list) { fonthandle oldfont; sdword width,addwidth,nCharacters,length; char temp[512]; chatlist *chatinfo; color col; oldfont = fontMakeCurrent(mgChatWindowFont); switch (newchat->messagetype) { case MG_NORMALCHAT: { sprintf(temp,"<%s> ",newchat->userName); width = MG_HorzSpacing + fontWidth(temp); if (list == &listofchatinfo) col = mgNormalChatColor; else col = mgGameNormalChatColor; } break; case MG_WHISPEREDCHAT: { sprintf(temp,"<%s>%s ",newchat->userName, strGetString(strWhisperedMessage)); width = MG_HorzSpacing + fontWidth(temp); if (list == &listofchatinfo) col = mgPrivateChatColor; else col = mgGameWhisperedColor; } break; case MG_MESSAGECHAT: { sprintf(temp,"%s",newchat->userName); width = MG_HorzSpacing + fontWidth(temp); if (list == &listofchatinfo) col = mgMessageChatColor; else col = mgGameMessageChatColor; } break; case MG_WRAPEDCHAT: { width = newchat->indent; col = newchat->baseColor; } break; case MG_GENERALMESSAGE: { width = 0; col = mgMessageChatColor; strcpy(temp, ""); } break; default : width = 0; break; } if (width+fontWidth(newchat->chatstring) > chatwindowwidth) { chatinfo = (chatlist *)memAlloc(sizeof(chatlist),"GameChat",NonVolatile); strcpy(chatinfo->userName, newchat->userName); chatinfo->baseColor = col; chatinfo->messagetype = MG_WRAPEDCHAT; chatinfo->index = newchat->index; chatinfo->indent = 0; nCharacters = strlen(newchat->chatstring); addwidth = fontWidth(newchat->chatstring); while (nCharacters>0 && width + addwidth > chatwindowwidth) { addwidth = fontWidthN(newchat->chatstring,nCharacters); nCharacters--; } length = nCharacters; while ((newchat->chatstring[nCharacters] != ' ') && (nCharacters > 0) ) { nCharacters--; } if (nCharacters == 0) { strcpy(chatinfo->chatstring, newchat->chatstring + length); newchat->chatstring[length] = 0; } else { strcpy(chatinfo->chatstring, newchat->chatstring + nCharacters + 1); newchat->chatstring[nCharacters] = 0; } listAddNode(list, &newchat->link, newchat); if (listwindow != NULL) { newchat->item = uicListAddItem(listwindow,(ubyte *)newchat,0,UICLW_AddToTail); } mgAddChatToRoomChat(chatinfo, listwindow, list); } else { listAddNode(list, &newchat->link, newchat); if (listwindow != NULL) { newchat->item = uicListAddItem(listwindow,(ubyte *)newchat,0,UICLW_AddToTail); } } if (listwindow != NULL) { while (listofchatinfo.num > MG_MaxChatHistory) { newchat = listGetStructOfNode(listofchatinfo.head); uicListRemoveItem(listwindow, newchat->item); listDeleteNode(listofchatinfo.head); } } else while (listofchatinfo.num > MG_MaxChatHistory) { listDeleteNode(listofchatinfo.head); } fontMakeCurrent(oldfont); } /*============================================================================= Callbacks for the connection type screen.: =============================================================================*/ void mgConnectionBack(char *name, featom *atom) { mgBaseRegion = NULL; mgScreensDisappear(); mgShutdownMultiPlayerGameScreens(); feScreenStart(ghMainRegion, "Main_game_screen"); // mgScreensAdded=0; currentScreen = -1; } void mgSkirmish(char *name, featom *atom) { #if defined(DLPublicBeta) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { return; } LANGame = FALSE; IPGame = 1; // DO NOT USE TRUE for CPP reasons tpGameCreated.numComputers = 1; tpGameCreated.numPlayers = 1; mgShowScreen(MGS_Skirmish_Basic, TRUE); #endif } void mgInternetWON(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { return; } WaitingForGame = FALSE; GameCreator = FALSE; LANGame = FALSE; IPGame = 1; // DO NOT USE TRUE for CPP reasons tpGameCreated.numComputers = 0; if (!titanStart(LANGame,IPGame)) { mgPrepareMessageBox(strGetString(strNoInternetTCPIP),NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } mgShowScreen(MGS_Internet_Login,TRUE); #endif } void mgLANIPX(char *name, featom *atom) { //mgShowScreen(MGS_LAN_Login,TRUE); #if defined(DLPublicBeta) || defined(Downloadable) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { return; } LanProtocalsValid = 0; LANGame = TRUE; if (titanCheckCanNetwork(LANGame,0)) { LanProtocalsValid |= LANIPX_VALID; } else { // disable IPX button if (LanProtocalButton == 0) { LanProtocalButton = 1; } } if (titanCheckCanNetwork(LANGame,1)) { LanProtocalsValid |= LANTCPIP_VALID; } else { // disable TCP/IP button if (LanProtocalButton == 1) { LanProtocalButton = 0; } } mgShutdownMultiPlayerGameScreens(); lgStartMultiPlayerLANGameScreens(ghMainRegion, 0, 0, 0, FALSE); #endif } /*============================================================================= Callbacks for the Login screen to Internet WON: =============================================================================*/ void mgFirewallButton(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, firewallButton); } else { firewallButton = (ubyte)atom->pData; } } void mgValidateName(void) { char temp[64]; sdword index,pos; strcpy(temp, utyName); for (index=0,pos=0;index < strlen(temp); index++) { if (!( ((temp[index] >= 0x00) && (temp[index] <=0x1F)) || (temp[index] == 0x22) || (temp[index] == 0x27) || (temp[index] == 0x7F) ) ) { utyName[pos++] = temp[index]; } } utyName[pos] = 0x00; } // This function will strip all of the invalid characters from peoples names! void mgVerifyValidNameChars(textentryhandle entry, bool login) { char key = entry->textBuffer[entry->iCharacter-1]; if (!login) { if ( ((key >= 0x00) && (key <=0x1F)) || (key == 0x22) || (key == 0x27) || (key == 0x2C) || (key == 0x2E) || (key == 0x2F) || (key == 0x3B) || (key == 0x5C) || (key == 0x60) || (key == 0x7C) || (key == 0x7F) ) { uicBackspaceCharacter(entry); } } else { if ( ((key >= 0x00) && (key <=0x1F)) || (key == 0x22) || (key == 0x27) || (key == 0x7F) ) { uicBackspaceCharacter(entry); } } } void mgNameEntry(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgNameEntryBox = (textentryhandle)atom->pData; mgValidateName(); uicTextEntrySet(mgNameEntryBox,utyName,strlen(utyName)+1); uicTextBufferResize(mgNameEntryBox,MAX_USERNAME_LENGTH); uicTextEntryInit(mgNameEntryBox,UICTE_UserNameEntry|UICTE_ChatTextEntry); // only accept valid characters and call this function for every key press return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : strcpy(utyName,mgNameEntryBox->textBuffer); break; case CM_GainFocus : break; case CM_KeyPressed : if (currentScreen==MGS_Internet_Login) { mgVerifyValidNameChars(mgNameEntryBox, TRUE); } else if (currentScreen==MGS_New_Account) { mgVerifyValidNameChars(mgNameEntryBox, FALSE); } break; } } void mgPasswordEntry(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgPasswordEntryBox = (textentryhandle)atom->pData; uicTextEntrySet(mgPasswordEntryBox,utyPassword,strlen(utyPassword)+1); uicTextEntryInit(mgPasswordEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgPasswordEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : strcpy(utyPassword,mgPasswordEntryBox->textBuffer); break; case CM_GainFocus : break; } } void mgChangePassword(char *name, featom *atom) { mgConnectingScreenGoto = MGS_Internet_Login; // verify we have a valid version if (!titanCheckValidVersion(versionString)) { // we don't have a valid version, time for patching? mgShowScreen(MGS_Download_Patch,FALSE); return; } strcpy(tempname, utyName); mgShowScreen(MGS_Password_Change,TRUE); } void mgNewAccount(char *name, featom *atom) { mgConnectingScreenGoto = MGS_Internet_Login; // verify we have a valid version if (!titanCheckValidVersion(versionString)) { // we don't have a valid version, time for patching? mgShowScreen(MGS_Download_Patch,FALSE); return; } mgShowScreen( MGS_New_Account, TRUE); } void mgLaunchWON(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else listDeleteAll(&listofgames); listDeleteAll(&listofchannels); listDeleteAll(&listofservers); listDeleteAll(&listofchatinfo); listDeleteAll(&listofusersinfo); listDeleteAll(&listtoping); listDeleteAll(&statusitemlist); listDeleteAll(&listofplayers); listDeleteAll(&listofplayersold); listDeleteAll(&listofgamechatinfo); listDeleteAll(&listofIgnoreUsers); listDeleteAll(&listofBannedUsers); mgPlayerLimit = 0; if (noAuthorization) { strcpy(utyName,mgNameEntryBox->textBuffer); mgShowScreen(MGS_Channel_Chat,TRUE); LoggedIn = TRUE; } else { // do they at least have a two character name before they try to log on if (strlen(mgNameEntryBox->textBuffer) < 2) return; #if 0 // if we don't have valid version information yet, titanCheckValidVersion will assume we have a correct version // and return TRUE // verify we have valid version information if (!HaveValidVersions) { mgPrepareMessageBox(strGetString(strErrorStillWaitingVersionInfo),NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } #endif mgConnectingScreenGoto = MGS_Internet_Login; // verify we have a valid version if (!titanCheckValidVersion(versionString)) { // we don't have a valid version, time for patching? mgShowScreen(MGS_Download_Patch,FALSE); return; } // we are trying to log on to won mgQueryType = MG_WONLogin; strcpy(utyName,mgNameEntryBox->textBuffer); // call the autenticate function authAuthenticate(mgNameEntryBox->textBuffer,mgPasswordEntryBox->textBuffer); // bring up the connecting status screen mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Internet_Login; mgDisplayMessage(strGetString(strSendingLogin)); //authReceiveReply(StatusCommon_Success); } #endif } void mgBackToConnection(char *name, featom *atom) { // closedown the titan engine titanShutdown(); #if PUBLIC_BETA if (betaVerifying) mgConnectionBack(NULL,NULL); else #endif mgShowScreen(MGS_Connection_Method,TRUE); } /*============================================================================= Callbacks for the Password Changer Screen.: =============================================================================*/ void mgOldPasswordChangeEntry(char*name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgOldPasswordChangeEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgOldPasswordChangeEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgOldPasswordChangeEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgNewPasswordChangeEntry(char*name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgNewPasswordChangeEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgNewPasswordChangeEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgNewPasswordChangeEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgConfirmPasswordChangeEntry(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgConfirmPasswordChangeEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgConfirmPasswordChangeEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgConfirmPasswordChangeEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgChangePasswordBack(char*name,featom *atom) { strcpy(utyName, tempname); mgShowScreen(MGS_Internet_Login,TRUE); } void mgChangePasswordNow(char *name, featom *atom) { if (strlen(mgNameEntryBox->textBuffer) < 2) return; if ((strlen(mgNewPasswordChangeEntryBox->textBuffer) < 2) || (strcmp(mgNewPasswordChangeEntryBox->textBuffer,mgConfirmPasswordChangeEntryBox->textBuffer) != 0)) { mgPrepareMessageBox(strGetString(strErrorTypingPassword),strGetString(strMustBeAtLeast2Chars)); mgShowScreen(MGS_Message_Box,FALSE); return; } // trying to change our password mgQueryType = MG_WONChangePassword; strcpy(utyName,mgNameEntryBox->textBuffer); strcpy(utyPassword, mgNewPasswordChangeEntryBox->textBuffer); // call the pasword changer function. authChangePassword(mgNameEntryBox->textBuffer,mgOldPasswordChangeEntryBox->textBuffer,mgNewPasswordChangeEntryBox->textBuffer); mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Password_Change; mgDisplayMessage(strGetString(strChangingPassword)); } /*============================================================================= Callbacks for the New account screen: =============================================================================*/ void mgNewAccountPassword(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgNewAccountPasswordEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgNewAccountPasswordEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgNewAccountPasswordEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgNewAccountConfirm(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgNewAccountConfirmEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgNewAccountConfirmEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgNewAccountConfirmEntryBox,MAX_PASSWORD_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgNewAccountBack(char *name, featom *atom) { mgShowScreen(MGS_Internet_Login,TRUE); } void mgCreateNewAccountNow(char *name, featom *atom) { if (strlen(mgNameEntryBox->textBuffer) < 2) return; if ((strlen(mgNewAccountPasswordEntryBox->textBuffer) < 2) || (strcmp(mgNewAccountPasswordEntryBox->textBuffer,mgNewAccountConfirmEntryBox->textBuffer) != 0)) { mgPrepareMessageBox(strGetString(strErrorTypingPassword),strGetString(strMustBeAtLeast2Chars)); mgShowScreen(MGS_Message_Box,FALSE); return; } // creating new user mgQueryType = MG_WONNewUser; strcpy(utyName,mgNameEntryBox->textBuffer); strcpy(utyPassword, mgNewAccountPasswordEntryBox->textBuffer); // create the new user authCreateUser(mgNameEntryBox->textBuffer,mgNewAccountPasswordEntryBox->textBuffer); mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_New_Account; mgDisplayMessage(strGetString(strCreatingUser)); } /*============================================================================= Callbacks for the channel chatting screen.: =============================================================================*/ void mgChatTextEntry(char*name,featom *atom) { chatlist *newchat; userlist *user; char temp[512]; wchar_t aWideStringP[MAX_CHATSTRING_LENGTH]; size_t aNumChars; sdword CommandType; if (FEFIRSTCALL(atom)) { // initialize button here mgChatTextEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgChatTextEntryBox,UICTE_NoLossOfFocus|UICTE_ChatTextEntry|UICTE_SpecialChars); uicTextBufferResize(mgChatTextEntryBox,MAX_CHATSTRING_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_AcceptText: if (strlen(mgChatTextEntryBox->textBuffer)>0) { newchat = (chatlist *)memAlloc(sizeof(chatlist),"ListofChannelChat",NonVolatile); // check if message is a private message or not if ((user=mgParseChatEntry(mgChatTextEntryBox->textBuffer, FALSE))!=NULL) { // yes it is if (user->userID == mgMyChatUserID) { // talking to yourself eh! strcpy(newchat->chatstring,mgChatTextEntryBox->textBuffer+strlen(user->userName)+2); strcpy(newchat->userName, user->userName); newchat->messagetype = MG_WHISPEREDCHAT; } else { char *strptr = mgChatTextEntryBox->textBuffer+strlen(user->userName)+2; strcpy(newchat->chatstring,strptr); strcpy(newchat->userName, utyName); newchat->messagetype = MG_WHISPEREDCHAT; // send the message to the intended recipient aNumChars = mbstowcs(aWideStringP, strptr, (uword)strlen(strptr)); if (aNumChars != (size_t)-1) { SendPrivateChatMessage(&user->userID,1,(uword)(aNumChars*2),aWideStringP); } } } else if (mgCommandEntered(mgChatTextEntryBox->textBuffer, FALSE) != -1) { mgCommandExecute(mgChatTextEntryBox->textBuffer, temp, FALSE); // public chat message strcpy(newchat->chatstring,temp); strcpy(newchat->userName, ""); newchat->messagetype = MG_MESSAGECHAT; } else { // public chat message strcpy(newchat->chatstring,mgChatTextEntryBox->textBuffer); strcpy(newchat->userName, utyName); newchat->messagetype = MG_NORMALCHAT; // broadcast it to everyone aNumChars = mbstowcs(aWideStringP, mgChatTextEntryBox->textBuffer, strlen(mgChatTextEntryBox->textBuffer)); if (aNumChars != (size_t)-1) { BroadcastChatMessage((uword)(aNumChars*2),aWideStringP); uicTextEntrySet(mgChatTextEntryBox,"",0); } } mgAddChatToRoomChat(newchat, mgChatHistoryWindow, &listofchatinfo); uicTextEntrySet(mgChatTextEntryBox,"",0); } break; case CM_KeyPressed: { if ((user=mgParseChatEntry(mgChatTextEntryBox->textBuffer, FALSE))!=NULL) { sprintf(temp, "/%s ", user->userName); if (strlen(mgChatTextEntryBox->textBuffer) < strlen(temp)) uicTextEntrySet(mgChatTextEntryBox, temp, strlen(temp)); } else if ((CommandType = mgCommandComplete(mgChatTextEntryBox->textBuffer, temp, FALSE)) != -1) { if (strlen(mgChatTextEntryBox->textBuffer) < strlen(temp)) uicTextEntrySet(mgChatTextEntryBox, temp, strlen(temp)); } } break; case CM_SpecialKey: { #ifdef DEBUG_STOMP regVerify((regionhandle)&mgChatHistoryWindow->reg); #endif if (mgChatTextEntryBox->key==PAGEUPKEY) { uicListWindowPageUp(mgChatHistoryWindow); mgChatHistoryWindow->reg.status |= RSF_DrawThisFrame; } else if (mgChatTextEntryBox->key==PAGEDOWNKEY) { uicListWindowPageDown(mgChatHistoryWindow); mgChatHistoryWindow->reg.status |= RSF_DrawThisFrame; } } break; case CM_GainFocus: break; } } void mgViewChannels(char *name,featom *atom) { mgShowScreen(MGS_Available_Channels,TRUE); } void mgViewGames(char *name,featom *atom) { mgShowScreen(MGS_Available_Games,TRUE); } void mgCreateGame(char *name,featom *atom) { mgCreatingNetworkGame = TRUE; mgRestoretpGameCreated(); mgResetNamePassword(); mgShowScreen(MGS_Basic_Options,TRUE); } void mgBackToLogin(char *name,featom *atom) { mgShowScreen(MGS_Quit_WON, FALSE); } void mgChangeColors(char *name, featom *atom) { // save the colors so if they change their minds it is backed up BaseColorSave = utyBaseColor; StripeColorSave = utyStripeColor; RaceSave = whichRaceSelected; cpSetColorsToModify(&utyBaseColor, &utyStripeColor); mgShowScreen(MGS_Player_Options,TRUE); } void mgDrawChatWindowItem(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; color c; fonthandle oldfont; chatlist *chatinfo = (chatlist *)data->data; oldfont = fontMakeCurrent(mgChatWindowFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; switch (chatinfo->messagetype) { case MG_NORMALCHAT: { sprintf(temp,"<%s> ",chatinfo->userName); // fontPrint(x,y,mgNormalChatColor,temp); fontPrint(x,y,colWhite,temp); x+=fontWidth(temp); c = mgNormalChatColor; } break; case MG_WHISPEREDCHAT: { sprintf(temp,"<%s>",chatinfo->userName); fontPrint(x,y,mgPrivateChatColor,temp); x+=fontWidth(temp); sprintf(temp, "%s ", strGetString(strWhisperedMessage)); fontPrint(x,y,mgWhisperedColor, temp); x+=fontWidth(temp); c = mgPrivateChatColor; } break; case MG_MESSAGECHAT: { sprintf(temp,"%s",chatinfo->userName); fontPrint(x,y,mgMessageChatColor,temp); x+=fontWidth(temp); c = mgMessageChatColor; } break; case MG_WRAPEDCHAT: { c = chatinfo->baseColor; x += chatinfo->indent - MG_HorzSpacing; } break; case MG_GENERALMESSAGE: { c = chatinfo->baseColor; } break; } sprintf(temp,"%s",chatinfo->chatstring); // don't comment out these lines! fontPrint(x,y,c,temp); // don't comment out these lines! fontMakeCurrent(oldfont); } void mgChatWindowInit(char *name, featom *atom) { fonthandle oldfont; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgChatWindowFont); mgChatHistoryWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgChatHistoryWindow, NULL, // title draw, no title NULL, // double click process 0, // title height, no title mgDrawChatWindowItem, // item draw funtcion fontHeight(" "), // item height UICLW_AutoScroll); chatwindowwidth = atom->width-20; if (listofchatinfo.num!=0) { walk = listofchatinfo.head; while (walk!=NULL) { ((chatlist *)listGetStructOfNode(walk))->item = uicListAddItem(mgChatHistoryWindow,(ubyte *)listGetStructOfNode(walk),0,UICLW_AddToTail); walk = walk->next; } } fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { mgChatHistoryWindow = NULL; return; } } void mgDrawUserNameWindowItem(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; fonthandle oldfont; userlist *userinfo = (userlist *)data->data; oldfont = fontMakeCurrent(mgUserNameFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; sprintf(temp,"%s",userinfo->userName); fontPrint(x,y,mgUserNameColor,temp); fontMakeCurrent(oldfont); } void mgUserNameWindowInit(char *name, featom *atom) { fonthandle oldfont; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgUserNameFont); mgUserNameWindowWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgUserNameWindowWindow, NULL, // title draw, no title NULL, // title click process, no title 0, // title height, no title mgDrawUserNameWindowItem, // item draw funtcion fontHeight(" "), // item height 0); if (listofusersinfo.num!=0) { walk = listofusersinfo.head; while (walk!=NULL) { ((userlist *)listGetStructOfNode(walk))->item = uicListAddItem(mgUserNameWindowWindow,(ubyte *)listGetStructOfNode(walk),0,UICLW_AddToTail); walk = walk->next; } } fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { mgUserNameWindowWindow = NULL; return; } } void mgCurrentChannelDraw(featom *atom, regionhandle region) { fonthandle oldfont; wchar_t *channelname; static char asciichannelname[MAX_CHANNEL_NAME_LEN]; oldfont = fontMakeCurrent(mgCurrentChannelFont); channelname = GetCurrentChannel(); if (channelname[0] == 0) fontPrint(region->rect.x0,region->rect.y0, mgCurrentChannelColor, strGetString(strNoRoom)); else { if (wcstombs(asciichannelname, channelname, MAX_CHANNEL_NAME_LEN) > 0) fontPrint(region->rect.x0,region->rect.y0, mgCurrentChannelColor, asciichannelname); } fontMakeCurrent(oldfont); } /*============================================================================= Callbacks for the Channel Picker screen.: =============================================================================*/ void mgJoinChannelNow(wchar_t *channelname,wchar_t *description) { cJoinChannelRequest(channelname,description); listDeleteAll(&listofgames); listDeleteAll(&listofchatinfo); listDeleteAll(&listofusersinfo); // clear room ready for use fix later mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Available_Channels; } void mgJoinChannel(char*name,featom*atom) { sdword i; channellist *channelinfo; if (mgListOfChannelsWindow->CurLineSelected!=NULL) { channelinfo = (channellist *)mgListOfChannelsWindow->CurLineSelected->data; for (i = 0; i < tpChannelList.numChannels; i++) { if (wcscmp(tpChannelList.tpChannels[i].ChannelName,channelinfo->channelname)==0) { if (tpChannelList.tpChannels[i].roomflags & ROOMFLAGS_PASSWORDPROTECTED) { wcscpy(joinchannelname,channelinfo->channelname); wcscpy(joinchanneldescription,channelinfo->description); mgShowScreen(MGS_Room_Password,FALSE); } else { ChannelPassword[0] = 0; mgJoinChannelNow(channelinfo->channelname,channelinfo->description); } } } } } void mgCreateChannel(char*name,featom*atom) { mgShowScreen(MGS_Create_Channel,TRUE); } void mgBackToChannelChat(char*name,featom *atom) { donerefreshing=TRUE; if (WaitingForGame) { if (GameCreator) { mgShowScreen(MGS_Captain_Wait,TRUE); } else { mgShowScreen(MGS_Player_Wait,TRUE); } } else { mgShowScreen(MGS_Channel_Chat,TRUE); } } void mgDrawListOfChannelsTitle(rectangle *rect) { sdword x, y; fonthandle oldfont; oldfont = fontMakeCurrent(mgChannelListTitleFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing; fontPrintf(x,y,mgChannelTitleColor,strGetString(strChannelNameHeading)); x += mgChannelNameWidth; fontPrintf(x,y,mgChannelTitleColor,strGetString(strChannelDescHeading)); x += mgChannelDescriptionWidth; if (strCurLanguage>=3) { x -= 15; } fontPrintf(x,y,mgChannelTitleColor,strGetString(strChannelNumberHeading)); x += mgChannelNumberWidth; fontMakeCurrent(oldfont); } void mgDrawListOfChannelsItem(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; color c; fonthandle oldfont; channellist *channelinfo = (channellist *)data->data; oldfont = fontMakeCurrent(mgChannelListFont); if (data->flags&UICLI_Selected) c = mgChannelListSelectedColor; else c = mgChannelListNormalColor; x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; wcstombs(temp,channelinfo->channelname,512); fontPrint(x,y,c,temp); x += mgChannelNameWidth; wcstombs(temp,channelinfo->description,512); fontPrint(x,y,c,temp); x += mgChannelDescriptionWidth; if (channelinfo->numpeople >= 0) { sprintf(temp,"%d",channelinfo->numpeople); fontPrint(x,y,c,temp); } x += mgChannelNumberWidth; if (strCurLanguage>=3) { x -= 15; } if (channelinfo->roomflags) { if (channelinfo->roomflags & ROOMFLAGS_PASSWORDPROTECTED) { fontPrint(x,y,c,strGetString(strPasswordProtected)); } } fontMakeCurrent(oldfont); } void mgListOfChannelsInit(char *name, featom *atom) { fonthandle oldfont; sdword titleheight, itemheight; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgChannelListTitleFont); titleheight = fontHeight(" ")*2; fontMakeCurrent(mgChannelListFont); itemheight = fontHeight(" ")+MG_VertSpacing; mgListOfChannelsWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgListOfChannelsWindow, mgDrawListOfChannelsTitle, // title draw, no title NULL, // title click process, no title titleheight, // title height, no title mgDrawListOfChannelsItem, // item draw funtcion itemheight, // item height UICLW_CanSelect); if (listofchannels.num!=0) { walk = listofchannels.head; while (walk!=NULL) { ((channellist *)listGetStructOfNode(walk))->item = uicListAddItem(mgListOfChannelsWindow,(ubyte *)listGetStructOfNode(walk),UICLI_CanSelect,UICLW_AddToTail); walk = walk->next; } } titanRefreshRequest(NULL); //titanQueryRoutingServers(); refreshbaby = taskCallBackRegister(Refresh, 0, NULL, (real32)TITAN_PICKER_REFRESH_TIME); donerefreshing=FALSE; fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { taskCallBackRemove(refreshbaby); donerefreshing = TRUE; mgListOfChannelsWindow = NULL; return; } else if (mgListOfChannelsWindow->message == CM_DoubleClick) { mgJoinChannel(NULL, NULL); } } /*============================================================================= Callbacks for the Channel Creation Screen.: =============================================================================*/ void mgChannelNameEntry(char*name,featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgChannelNameEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgChannelNameEntryBox,0); uicTextBufferResize(mgChannelNameEntryBox,MAX_CHANNELNAME_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgChannelDescriptionEntry(char*name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgChannelDescriptionEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgChannelDescriptionEntryBox,0); uicTextBufferResize(mgChannelDescriptionEntryBox,MAX_DESCRIPTION_LENGTH); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgChannelProtected(char*name,featom *atom) { if (FEFIRSTCALL(atom)) { ChannelProtectedFlag = 0; feToggleButtonSet(name, ChannelProtectedFlag); } else { if (FECHECKED(atom)) ChannelProtectedFlag = 1; else ChannelProtectedFlag = 0; } } void mgChannelPasswordEntry(char*name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgChannelPasswordEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgChannelPasswordEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgChannelPasswordEntryBox,MAX_PASSWORD_LENGTH-2); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgChannelConfirmEntry(char*name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgChannelConfirmEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgChannelConfirmEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgChannelConfirmEntryBox,MAX_PASSWORD_LENGTH-2); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } bool channelAlreadyExists(wchar_t *channelname) { sdword i; tpLockChannelList(); for (i = 0; i < tpChannelList.numChannels; i++) { if (wcscmp(tpChannelList.tpChannels[i].ChannelName,channelname) == 0) { tpUnLockChannelList(); return TRUE; } } tpUnLockChannelList(); return FALSE; } void mgCreateChannelNow(char*name,featom *atom) { static wchar_t widechannelname[MAX_CHANNEL_NAME_LEN]; static wchar_t widechanneldescription[MAX_CHANNEL_DESCRIPTION_LEN]; if (strlen(mgChannelNameEntryBox->textBuffer) < 2) { return; } mbstowcs(widechannelname, mgChannelNameEntryBox->textBuffer, strlen(mgChannelNameEntryBox->textBuffer)+1); if (channelAlreadyExists(widechannelname)) { mgPrepareMessageBox(strGetString(strErrorRoomAlreadyExists),NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } if (ChannelProtectedFlag) { if ((strlen(mgChannelPasswordEntryBox->textBuffer) < 2) || (strcmp(mgChannelPasswordEntryBox->textBuffer,mgChannelConfirmEntryBox->textBuffer) != 0)) { mgPrepareMessageBox(strGetString(strErrorTypingPassword),strGetString(strMustBeAtLeast2Chars)); mgShowScreen(MGS_Message_Box,FALSE); return; } mbstowcs(ChannelPassword, mgChannelPasswordEntryBox->textBuffer, strlen(mgChannelPasswordEntryBox->textBuffer)+1); } else ChannelPassword[0] = 0; mbstowcs(widechanneldescription, mgChannelDescriptionEntryBox->textBuffer, strlen(mgChannelDescriptionEntryBox->textBuffer)+1); mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Create_Channel; cCreateChannel(widechannelname, widechanneldescription); listDeleteAll(&listofgames); listDeleteAll(&listofchatinfo); listDeleteAll(&listofusersinfo); } void mgBackToAvailableChannels(char *name, featom *atom) { mgShowScreen(MGS_Available_Channels,TRUE); } /*============================================================================= Callbacks for the available games screen: =============================================================================*/ Node *pingwalk; bool firstping=FALSE; void mgPingAllGames(char*name,featom *atom) { Node *walk, *isthere; newping *pinginfo; bool found=FALSE; gamelist *game; newping *ping; if (donepinging == FALSE) { listDeleteAll(&listtoping); pingwalk = NULL; } donepinging = FALSE; if (listofgames.num!=0) { walk = listofgames.head; listDeleteAll(&listtoping); while (walk!=NULL) { game = (gamelist *)listGetStructOfNode(walk); isthere = listtoping.head; found = FALSE; dbgAssert(!LANGame); while (isthere != NULL) { ping = (newping *)listGetStructOfNode(isthere); if (ping->IP== GetIPFromInternetAddress(game->game.directoryCustomInfo.pingAddress)) { found = TRUE; break; } isthere = isthere->next; } if ((!found) && (! (game->game.directoryCustomInfo.flag & GAME_IN_PROGRESS) )) { pinginfo = memAlloc(sizeof(newping),"GamesToPing",NonVolatile); pinginfo->IP = GetIPFromInternetAddress(game->game.directoryCustomInfo.pingAddress); pinginfo->Port = GetPortFromInternetAddress(game->game.directoryCustomInfo.pingAddress); listAddNode(&listtoping, &pinginfo->link, pinginfo); } walk = walk->next; } firstping = TRUE; pinggamesbaby = taskCallBackRegister(PingAllGames, 0, NULL, (real32)PING_INTERVAL_TIME); } } void mgSeeDetails(char*name,featom*atom) { } void titanJoinGameRequest(tpscenario *gametojoin) { PlayerJoinInfo pInfo; mgGameInterestedIn(gametojoin->Name); pInfo.baseColor = utyBaseColor; pInfo.stripeColor = utyStripeColor; pInfo.colorsPicked = cpColorsPicked; pInfo.race = whichRaceSelected; pInfo.behindFirewall = titanBehindFirewall(); strcpy(pInfo.PersonalName, utyName); if (!LANGame) { titanSetGameKey(gametojoin->directoryCustomInfo.sessionKey); } titanConnectToClient(&gametojoin->directoryCustomInfo.captainAddress); titanSendPacketTo(&gametojoin->directoryCustomInfo.captainAddress,TITANMSGTYPE_JOINGAMEREQUEST,&pInfo,sizeof(pInfo)); } void mgRequestJoinGame(tpscenario *game) { mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Available_Games; mgDisplayMessage(strGetString(strRequestingToJoin)); titanJoinGameRequest(game); listDeleteAll(&listofgamechatinfo); listDeleteAll(&listofplayers); listDeleteAll(&listofplayersold); } void mgJoinGame(char*name,featom*atom) { gamelist *gameinfo; if (mgListOfGamesWindow->CurLineSelected!=NULL) { gameinfo = (gamelist *)mgListOfGamesWindow->CurLineSelected->data; if (AddressesAreEqual(gameinfo->game.directoryCustomInfo.captainAddress,myAddress)) { mgPrepareMessageBox(strGetString(strCantJoinOwnGame),NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } if (!forceLAN) // later change to a more meaningful name fix later { if (!CheckNetworkVersionCompatibility(gameinfo->game.directoryCustomInfo.versionInfo)) { mgPrepareMessageBox(strGetString(strDifferentVersions),strGetString(strMustUpgradeToSameVersion)); mgShowScreen(MGS_Message_Box,FALSE); return; } } if (wcslen(gameinfo->game.directoryCustomInfo.stringdata)>1) { joingame = &gameinfo->game; mgShowScreen(MGS_Game_Password,FALSE); } else { mgRequestJoinGame(&gameinfo->game); } } } void mgListOfGamesBack(char *name, featom *atom) { if (WaitingForGame) { if (GameCreator) { mgShowScreen(MGS_Captain_Wait,TRUE); } else { mgShowScreen(MGS_Player_Wait,TRUE); } } else { mgShowScreen(MGS_Channel_Chat,TRUE); } } // the following functions are all callbacks to do with list windows // callback for sorting the game list window bool mgListOfGamesCompare(void *firststruct,void *secondstruct) { sdword i; gamelist *one = (gamelist *)(((listitemhandle)firststruct)->data); gamelist *two = (gamelist *)(((listitemhandle)secondstruct)->data); if (one->game.directoryCustomInfo.flag & GAME_IN_PROGRESS) { if (!(two->game.directoryCustomInfo.flag & GAME_IN_PROGRESS)) return(FALSE); } else { if ((two->game.directoryCustomInfo.flag & GAME_IN_PROGRESS)) return(FALSE); } switch (mgListOfGamesWindow->sorttype) { case MG_SortByGameName: if ((i=wcsicmp( one->game.Name,two->game.Name)) > 0) return (mgListOfGamesWindow->sortOrder); else { if (i != 0) return (!mgListOfGamesWindow->sortOrder); else return (FALSE); } case MG_SortByPingTime: if (one->pingtime > two->pingtime) return (mgListOfGamesWindow->sortOrder); else { if (one->pingtime != two->pingtime) return (!mgListOfGamesWindow->sortOrder); else return (FALSE); } case MG_SortByNumPlayers: if (one->game.directoryCustomInfo.numPlayers > two->game.directoryCustomInfo.numPlayers) return (mgListOfGamesWindow->sortOrder); else { if (one->game.directoryCustomInfo.numPlayers != two->game.directoryCustomInfo.numPlayers) return (!mgListOfGamesWindow->sortOrder); else return(FALSE); } case MG_SortByMapName: { wchar_t *onemapname = one->game.directoryCustomInfo.stringdata + 1+wcslen(one->game.directoryCustomInfo.stringdata); wchar_t *twomapname = two->game.directoryCustomInfo.stringdata + 1+wcslen(two->game.directoryCustomInfo.stringdata); if ((i=wcsicmp( onemapname,twomapname)) > 0) return (mgListOfGamesWindow->sortOrder); else { if (i != 0) return (!mgListOfGamesWindow->sortOrder); else return(FALSE); } } } } // callback if the title is clicked on void mgListOfGamesTitleClick(struct tagRegion *reg, sdword xClicked) { sdword x = reg->rect.x0+mgGameNameWidth; if (mgListOfGamesWindow->ListTotal==0) return; mgTitleFlashTimer = taskTimeElapsed; #ifdef DEBUG_STOMP regVerify(reg); #endif reg->status |= RSF_DrawThisFrame; if (xClicked < x) { if (mgListOfGamesWindow->sorttype == MG_SortByGameName) mgListOfGamesWindow->sortOrder = !mgListOfGamesWindow->sortOrder; else mgListOfGamesWindow->sortOrder = TRUE; mgListOfGamesWindow->sorttype = MG_SortByGameName; uicListSort(mgListOfGamesWindow,mgListOfGamesCompare); return; } x+=mgPingTimeWidth; if (xClicked < x) { if (mgListOfGamesWindow->sorttype == MG_SortByPingTime) mgListOfGamesWindow->sortOrder = !mgListOfGamesWindow->sortOrder; else mgListOfGamesWindow->sortOrder = TRUE; mgListOfGamesWindow->sorttype = MG_SortByPingTime; uicListSort(mgListOfGamesWindow,mgListOfGamesCompare); return; } x+=mgNumPlayerWidth; if (xClicked < x) { if (mgListOfGamesWindow->sorttype == MG_SortByNumPlayers) mgListOfGamesWindow->sortOrder = !mgListOfGamesWindow->sortOrder; else mgListOfGamesWindow->sortOrder = TRUE; mgListOfGamesWindow->sorttype = MG_SortByNumPlayers; uicListSort(mgListOfGamesWindow,mgListOfGamesCompare); return; } else { if (mgListOfGamesWindow->sorttype == MG_SortByMapName) mgListOfGamesWindow->sortOrder = !mgListOfGamesWindow->sortOrder; else mgListOfGamesWindow->sortOrder = TRUE; mgListOfGamesWindow->sorttype = MG_SortByMapName; uicListSort(mgListOfGamesWindow,mgListOfGamesCompare); return; } } void mgDrawTriangle(sdword x, color col) { triangle tri; if (!mgListOfGamesWindow->sortOrder) { tri.x0 = -4 + x; tri.y0 = 4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; tri.x1 = 4 + x; tri.y1 = 4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; tri.x2 = 0 + x; tri.y2 = -4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; } else { tri.x0 = -4 + x; tri.y0 = -4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; tri.x1 = 0 + x; tri.y1 = 4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; tri.x2 = 4 + x; tri.y2 = -4 + mgListOfGamesWindow->reg.rect.y0+MG_VertSpacing+4; } primTriSolid2(&tri, col); } // callback to draw the title bar for the list void mgListOfGamesTitleDraw(rectangle *rect) { sdword x, y; fonthandle oldfont; color flashcol; oldfont = fontMakeCurrent(mgGameListTitleFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing; if (mgTitleFlashTimer + FLASH_TIMER > taskTimeElapsed) { bitSet(mgListOfGamesWindow->windowflags,UICLW_JustRedrawTitle); #ifdef DEBUG_STOMP regVerify(&mgListOfGamesWindow->reg); #endif mgListOfGamesWindow->reg.status |= RSF_DrawThisFrame; flashcol = mgTitleFlashColor; } else flashcol = mgGameListTitleColor; if (mgListOfGamesWindow->sorttype == MG_SortByGameName) { fontPrint(x,y,flashcol,strGetString(strGameNameHeading)); mgDrawTriangle(x+fontWidth(strGetString(strGameNameHeading)), flashcol); } else fontPrint(x,y,mgGameListTitleColor,strGetString(strGameNameHeading)); x+= mgGameNameWidth; if (mgListOfGamesWindow->sorttype == MG_SortByPingTime) { fontPrint(x,y,flashcol,strGetString(strGamePingHeading)); mgDrawTriangle(x+fontWidth(strGetString(strGamePingHeading)), flashcol); } else fontPrint(x,y,mgGameListTitleColor,strGetString(strGamePingHeading)); x+= mgPingTimeWidth; if (mgListOfGamesWindow->sorttype == MG_SortByNumPlayers) { fontPrint(x,y,flashcol,strGetString(strGameNumPlayerHeading)); mgDrawTriangle(x+fontWidth(strGetString(strGameNumPlayerHeading)), flashcol); } else fontPrint(x,y,mgGameListTitleColor,strGetString(strGameNumPlayerHeading)); x+= mgNumPlayerWidth; if (strCurLanguage >= 3) { x+=15; } if (mgListOfGamesWindow->sorttype == MG_SortByMapName) { fontPrint(x,y,flashcol,strGetString(strGameMapHeading)); mgDrawTriangle(x+fontWidth(strGetString(strGameMapHeading)), flashcol); } else fontPrint(x,y,mgGameListTitleColor,strGetString(strGameMapHeading)); x+=mgMapNameWidth; fontMakeCurrent(oldfont); } // callback to draw each item in the list void mgListOfGamesItemDraw(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; color c; fonthandle oldfont; gamelist *gameinfo = (gamelist *)data->data; udword passwordlen; bool gameinprogress = gameinfo->game.directoryCustomInfo.flag & GAME_IN_PROGRESS; bool diffversion = (!CheckNetworkVersionCompatibility(gameinfo->game.directoryCustomInfo.versionInfo)); oldfont = fontMakeCurrent(mgListOfGamesFont); if (data->flags&UICLI_Selected) c = mgGameListSelectedColor; else c = mgGameListNormalColor; if (diffversion != 0) c = mgGameListDiffVersionColor; if (gameinprogress) c = mgGameListStartedColor; x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; wcstombs(temp,gameinfo->game.Name,512); fontPrint(x,y,c,temp); x+=mgGameNameWidth; x+=mgPingTimeWidth; if (gameinfo->pingtime == -1) sprintf(temp,"?"); else sprintf(temp,"%i",gameinfo->pingtime); fontPrint(x-fontWidth(temp)-fontWidth("W"),y,c,temp); x+=mgNumPlayerWidth; sprintf(temp,"%i",gameinfo->game.directoryCustomInfo.numPlayers); fontPrint(x-fontWidth(temp)-fontWidth("W"),y,c,temp); passwordlen = wcslen(gameinfo->game.directoryCustomInfo.stringdata); wcstombs(temp,gameinfo->game.directoryCustomInfo.stringdata + 1+passwordlen,512); fontPrint(x,y,c,temp); x += mgMapNameWidth; if (gameinprogress) { fontPrint(x,y,c,strGetString(strInProgress)); } else if (diffversion != 0) { fontPrint(x,y,c,strGetString(strDiffVersion)); } else if (passwordlen > 1) { fontPrint(x,y,c,strGetString(strPasswordProtected)); } fontMakeCurrent(oldfont); } // initilize the list of games window structure to needed settings void mgListOfGamesInit(char *name, featom *atom) { fonthandle oldfont; sdword titleheight, itemheight; Node *walk; gamelist *gameinfo; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgGameListTitleFont); titleheight = fontHeight(" ")*2; fontMakeCurrent(mgListOfGamesFont); itemheight = fontHeight(" ")+MG_VertSpacing; mgListOfGamesWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgListOfGamesWindow, mgListOfGamesTitleDraw, // title draw, no title mgListOfGamesTitleClick, // title click process, no title titleheight, // title height, no title mgListOfGamesItemDraw, // item draw funtcion itemheight, // item height UICLW_CanSelect|UICLW_CanHaveFocus); if (listofgames.num!=0) { walk = listofgames.head; while (walk!=NULL) { gameinfo = (gamelist *)listGetStructOfNode(walk); if (gameinfo->game.directoryCustomInfo.flag & GAME_IN_PROGRESS) gameinfo->item = uicListAddItem(mgListOfGamesWindow, (ubyte *)gameinfo, 0, UICLW_AddToTail); else gameinfo->item = uicListAddItem(mgListOfGamesWindow, (ubyte *)gameinfo, UICLI_CanSelect, UICLW_AddToHead); walk = walk->next; } } refreshbaby = taskCallBackRegister(Refresh, 0, NULL, (real32)TITAN_PICKER_REFRESH_TIME); donerefreshing=FALSE; fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { taskCallBackRemove(refreshbaby); donerefreshing = TRUE; mgListOfGamesWindow = NULL; return; } else if (mgListOfGamesWindow->message == CM_DoubleClick) { mgJoinGame(NULL, NULL); } } // function called to refresh the list of games structure bool Refresh(udword num, void *data, struct BabyCallBack *baby) { //static sdword refreshcount = 0; if (!donerefreshing) { if ((currentScreen == MGS_Available_Channels) || (currentScreen == MGS_Choose_Server)) { titanRefreshRequest(NULL); #if 0 if ((++refreshcount & 1) == 0) { titanQueryRoutingServers(); } #endif } } return (donerefreshing); } bool PingAllGames(udword num, void *data, struct BabyCallBack *baby) { Address addr; if ( (pingwalk == NULL) && (firstping == TRUE) ) { firstping = FALSE; pingwalk = listtoping.head; if (pingwalk == NULL) { donepinging = TRUE; return (TRUE); } } else if ( (pingwalk == NULL) && (firstping == FALSE) ) { donepinging = TRUE; return (TRUE); } dbgAssert(!LANGame); CreateInternetAddress(addr,((newping *)pingwalk)->IP,((newping *)pingwalk)->Port); titanSendPing(&addr,2); pingwalk = pingwalk->next; return (donepinging); } void ConvertUChar6ToAddress(ubyte *uchar6,Address *address) { ubyte *IPPtr = (ubyte *)&address->AddrPart.IP; ubyte *PortPtr = (ubyte *)&address->Port; PortPtr[0] = uchar6[1]; PortPtr[1] = uchar6[0]; IPPtr[0] = uchar6[2]; IPPtr[1] = uchar6[3]; IPPtr[2] = uchar6[4]; IPPtr[3] = uchar6[5]; } void ConvertAddressToUChar6(ubyte *uchar6,Address *address) { ubyte *IPPtr = (ubyte *)&address->AddrPart.IP; ubyte *PortPtr = (ubyte *)&address->Port; uchar6[0] = PortPtr[1]; uchar6[1] = PortPtr[0]; uchar6[2] = IPPtr[0]; uchar6[3] = IPPtr[1]; uchar6[4] = IPPtr[2]; uchar6[5] = IPPtr[3]; } bool PingAllServers(udword num, void *data, struct BabyCallBack *baby) { serverlist *servertoping; Address addr; if (listofservers.num == 0) { return FALSE; } if (pingservernum >= listofservers.num) { pingservernum = 0; } servertoping = ConvertNumToPointerInList(&listofservers,pingservernum); if (servertoping == NULL) { return FALSE; } ConvertUChar6ToAddress(servertoping->addressstore,&addr); dbgMessage("\nSending ping"); titanSendPing(&addr,4); pingservernum++; return FALSE; } /*============================================================================= Callbacks for the waiting for game screens.: =============================================================================*/ void mgGameChatItemDraw(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; color c; fonthandle oldfont; chatlist *chatinfo = (chatlist *)data->data; oldfont = fontMakeCurrent(mgGameChatFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; switch (chatinfo->messagetype) { case MG_NORMALCHAT: { sprintf(temp,"<%s> ",chatinfo->userName); fontPrint(x,y,chatinfo->baseColor,temp); x+=fontWidth(temp); c = mgNormalChatColor; } break; case MG_WHISPEREDCHAT: { sprintf(temp,"<%s>",chatinfo->userName); fontPrint(x,y,chatinfo->baseColor,temp); x+=fontWidth(temp); sprintf(temp, "%s ", strGetString(strWhisperedMessage)); fontPrint(x,y,mgWhisperedColor, temp); x+=fontWidth(temp); c = mgPrivateChatColor; } break; case MG_MESSAGECHAT: { sprintf(temp,"%s",chatinfo->userName); fontPrint(x,y,mgGameMessageChatColor,temp); x+=fontWidth(temp); c = mgGameMessageChatColor; } break; case MG_WRAPEDCHAT: { c = chatinfo->baseColor; x += chatinfo->indent - MG_HorzSpacing; } break; } sprintf(temp,"%s",chatinfo->chatstring); fontPrint(x,y,c,temp); fontMakeCurrent(oldfont); } void mgGameChatWindowInit(char *name, featom *atom) { fonthandle oldfont; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgGameChatFont); mgGameChatWindowWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgGameChatWindowWindow, NULL, // title draw, no title NULL, // title click process, no title 0, // title height, no title mgGameChatItemDraw, // item draw funtcion fontHeight(" "), // item height UICLW_AutoScroll); fontMakeCurrent(oldfont); if (listofgamechatinfo.num!=0) { walk = listofgamechatinfo.head; while (walk!=NULL) { ((chatlist *)listGetStructOfNode(walk))->item = uicListAddItem(mgGameChatWindowWindow,(ubyte *)listGetStructOfNode(walk),0,UICLW_AddToTail); walk = walk->next; } } return; } if (FELASTCALL(atom)) { mgGameChatWindowWindow = NULL; return; } } void mgGameUserNameItemDraw(rectangle *rect, listitemhandle data) { gameplayerinfo *playerinfo=(gameplayerinfo *)data->data; sdword x, y; fonthandle oldfont; oldfont = fontMakeCurrent(mgGameUserNameFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; fontPrintf(x,y,playerinfo->baseColor,"%s",playerinfo->name); fontMakeCurrent(oldfont); } void mgGameUserNameWindowInit(char *name, featom *atom) { fonthandle oldfont; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgGameUserNameFont); mgGameUserNameWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgGameUserNameWindow, NULL, // title draw, no title NULL, // title click process, no title 0, // title height, no title mgGameUserNameItemDraw, // item draw funtcion fontHeight(" "), // item height 0); if (listofplayers.num!=0) { walk = listofplayers.head; while (walk!=NULL) { ((gameplayerinfo *)listGetStructOfNode(walk))->item = uicListAddItem(mgGameUserNameWindow,(ubyte *)listGetStructOfNode(walk),0,UICLW_AddToTail); walk = walk->next; } } fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { mgGameUserNameWindow = NULL; return; } } void mgViewDetails(char*name,featom *atom) { mgShowScreen(MGS_Basic_Options_View,TRUE); } void mgLeaveGame(char*name,featom*atom) { mgPlayerLimit = 0; if (GameCreator) { titanGameDisolved(FALSE); mgShowScreen(MGS_Channel_Chat,TRUE); GameCreator = FALSE; WaitingForGame = FALSE; } else { titanLeaveGame(FALSE); GameCreator = FALSE; WaitingForGame = FALSE; mgShowScreen(MGS_Channel_Chat,TRUE); } } void mgSetupGame(char*name,featom*atom) { BackupGameCreated = tpGameCreated; spCurrentSelectedBack = spCurrentSelected; mgShowScreen(MGS_Basic_Options_Change, TRUE); } void mgStartGameCB() { sdword i; DirectoryCustomInfoMax buildDirectoryCustomInfo; tpGameCreated.flag |= GAME_IN_PROGRESS; for (i=tpGameCreated.numPlayers; i < tpGameCreated.numPlayers+tpGameCreated.numComputers; i++) { tpGameCreated.playerInfo[i].race = ranRandom(0)&0x00000001; } titanBroadcastPacket(TITANMSGTYPE_GAMEISSTARTING,&tpGameCreated,sizeof(tpGameCreated)); // update directory server with inprogres flag generateDirectoryCustomInfo(&buildDirectoryCustomInfo); titanReplaceGameInfo(tpGameCreated.Name,(DirectoryCustomInfo *)&buildDirectoryCustomInfo, TRUE); sigsPlayerIndex = 0; sigsNumPlayers = tpGameCreated.numPlayers; sigsPressedStartGame = TRUE; } void mgReallyStartGame(unsigned char *routingaddress) { if (titanReadyToStartGame(routingaddress)) { mgStartGameCB(); } } void mgStartGame(char*name,featom*atom) { if (tpGameCreated.numPlayers == 0) { return; // if we haven't created a game, don't let us click start. } #if NEED_MIN_TWO_HUMAN_PLAYERS if (tpGameCreated.numPlayers < 2) { char str[200]; sprintf(str,strGetString(strMinNumPlayersRequired),2); mgPrepareMessageBox(str,NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } #endif #if NEED_MIN_TWO_HUMAN_PLAYERS if (spScenarios[spCurrentSelected].minplayers > (tpGameCreated.numPlayers + tpGameCreated.numComputers)) { char str[200]; sprintf(str,strGetString(strMinNumPlayersRequired),spScenarios[spCurrentSelected].minplayers); mgPrepareMessageBox(str,NULL); mgShowScreen(MGS_Message_Box,FALSE); return; } #endif if (tpGameCreated.userBehindFirewall) { mgShowScreen(MGS_Choose_Server,TRUE); } else { mgReallyStartGame(NULL); } } void mgGameChatTextEntry(char *name, featom *atom) { chatlist *newchat; gameplayerinfo *user; char temp[512]; sdword CommandType; if (FEFIRSTCALL(atom)) { // initialize button here mgGameChatTextEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgGameChatTextEntryBox,UICTE_NoLossOfFocus|UICTE_ChatTextEntry|UICTE_SpecialChars); uicTextBufferResize(mgGameChatTextEntryBox,MAX_CHATSTRING_LENGTH-2); return; } switch (uicTextEntryMessage(atom)) { case CM_AcceptText: if (strlen(mgGameChatTextEntryBox->textBuffer)>0) { newchat = (chatlist *)memAlloc(sizeof(chatlist),"GameChat",NonVolatile); if ((user=mgParseChatEntry(mgGameChatTextEntryBox->textBuffer, TRUE))!=NULL) { if (strcmp(user->name,utyName)==0) { strcpy(newchat->chatstring,mgGameChatTextEntryBox->textBuffer+strlen(user->name)+2); strcpy(newchat->userName, utyName); newchat->baseColor = utyBaseColor; newchat->messagetype = MG_WHISPEREDCHAT; } else { sendChatMessage(PLAYER_MASK(user->index),mgGameChatTextEntryBox->textBuffer+strlen(user->name)+2,(uword)sigsPlayerIndex); strcpy(newchat->chatstring,mgGameChatTextEntryBox->textBuffer+strlen(user->name)+2); strcpy(newchat->userName, utyName); newchat->baseColor = utyBaseColor; newchat->messagetype = MG_WHISPEREDCHAT; } } else if (mgCommandEntered(mgGameChatTextEntryBox->textBuffer, TRUE) != -1) { mgCommandExecute(mgGameChatTextEntryBox->textBuffer, temp, TRUE); // public chat message strcpy(newchat->chatstring,temp); strcpy(newchat->userName, ""); newchat->messagetype = MG_MESSAGECHAT; } else { strcpy(newchat->chatstring,mgGameChatTextEntryBox->textBuffer); strcpy(newchat->userName, utyName); newchat->baseColor = utyBaseColor; newchat->messagetype = MG_NORMALCHAT; sendChatMessage(OTHER_PLAYERS_MASK,mgGameChatTextEntryBox->textBuffer,(uword)sigsPlayerIndex); uicTextEntrySet(mgGameChatTextEntryBox,"",0); } mgAddChatToRoomChat(newchat, mgGameChatWindowWindow, &listofgamechatinfo); uicTextEntrySet(mgGameChatTextEntryBox,"",0); } break; case CM_KeyPressed: { if ((user=mgParseChatEntry(mgGameChatTextEntryBox->textBuffer, TRUE))!=NULL) { sprintf(temp, "/%s ", user->name); if (strlen(mgGameChatTextEntryBox->textBuffer) < strlen(temp)) uicTextEntrySet(mgGameChatTextEntryBox, temp, strlen(temp)); } else if ((CommandType = mgCommandComplete(mgGameChatTextEntryBox->textBuffer, temp, TRUE)) != -1) { if (strlen(mgGameChatTextEntryBox->textBuffer) < strlen(temp)) uicTextEntrySet(mgGameChatTextEntryBox, temp, strlen(temp)); } } break; case CM_SpecialKey: { #ifdef DEBUG_STOMP regVerify((regionhandle)&mgGameChatWindowWindow->reg); #endif if (mgGameChatTextEntryBox->key==PAGEUPKEY) { uicListWindowPageUp(mgGameChatWindowWindow); mgGameChatWindowWindow->reg.status |= RSF_DrawThisFrame; } else if (mgGameChatTextEntryBox->key==PAGEDOWNKEY) { uicListWindowPageDown(mgGameChatWindowWindow); mgGameChatWindowWindow->reg.status |= RSF_DrawThisFrame; } } break; case CM_GainFocus: break; } } void mgCurrentGameDraw(featom *atom, regionhandle region) { fonthandle oldfont; static char asciigamename[MAX_TITAN_GAME_NAME_LEN]; oldfont = fontMakeCurrent(mgCurrentGameFont); if (wcstombs(asciigamename, tpGameCreated.Name, MAX_TITAN_GAME_NAME_LEN) > 0) fontPrint(region->rect.x0,region->rect.y0, mgCurrentGameColor, asciigamename); fontMakeCurrent(oldfont); } /*============================================================================= Callbacks for the create game screen\Options: =============================================================================*/ /*============================================================================= Proccess Callbacks from the Skirmish basic options screen: =============================================================================*/ regionhandle mgNumCompPlayerReg = NULL; regionhandle mgNumHumanPlayerReg = NULL; void mgDirtyNumPlayerRegions() { if (mgNumCompPlayerReg!=NULL) { #ifdef DEBUG_STOMP regVerify(mgNumCompPlayerReg); #endif mgNumCompPlayerReg->status |= RSF_DrawThisFrame; } if (mgNumHumanPlayerReg!=NULL) { #ifdef DEBUG_STOMP regVerify(mgNumHumanPlayerReg); #endif mgNumHumanPlayerReg->status |= RSF_DrawThisFrame; } } bool mgInvalidGameName() { featom *atomchange; if (wcslen(tpGameCreated.Name)<2) { atomchange = feAtomFindInScreen(feStack[feStackIndex].screen, "MG_GameNameTextEntry"); if (atomchange == NULL) { mgShowScreen(MGS_Basic_Options, TRUE); atomchange = feAtomFindInScreen(feStack[feStackIndex].screen, "MG_GameNameTextEntry"); } if (atomchange != NULL) { uicClearCurrent(atomchange->region); uicSetCurrent(atomchange->region, FALSE); } mgPrepareMessageBox(strGetString(strYouMustTypeInGameName),strGetString(strAtLeast2Chars)); mgShowScreen(MGS_Message_Box,FALSE); return TRUE; } return FALSE; } bool mgInvalidGamePassword() { if (bitTest(tpGameCreated.flag,MG_PasswordProtected)) { if (wcslen(tpGameCreated.Password) < 2) { return TRUE; } } return FALSE; } void mgCreateGameNow(char *name, featom *atom) { DirectoryCustomInfoMax buildDirectoryCustomInfo; if (LANGame) { lgCreateGameNow(name, atom); } else { if (WaitingForGame) { if (GameCreator) { dbgAssert(strlen(spScenarios[spCurrentSelected].fileSpec) <= MAX_MAPNAME_LEN); memStrncpy(tpGameCreated.DisplayMapName,spScenarios[spCurrentSelected].title,MAX_MAPNAME_LEN); memStrncpy(tpGameCreated.MapName,spScenarios[spCurrentSelected].fileSpec,MAX_MAPNAME_LEN); generateDirectoryCustomInfo(&buildDirectoryCustomInfo); titanReplaceGameInfo(tpGameCreated.Name,(DirectoryCustomInfo *)&buildDirectoryCustomInfo, FALSE); titanBroadcastPacket(TITANMSGTYPE_UPDATEGAMEDATA, &tpGameCreated, sizeof(tpGameCreated)); mgShowScreen(MGS_Captain_Wait, TRUE); } else mgShowScreen(MGS_Player_Wait, TRUE); } else { DirectoryCustomInfoMax buildDirectoryCustomInfo; listDeleteAll(&listofgamechatinfo); if (mgInvalidGameName()) { return; } if (wcslen(GetCurrentChannel()) <= 0) { mgPrepareMessageBox(strGetString(strMustBeInRoomToCreateGame),strGetString(strMustBeInRoomToCreateGame2)); mgShowScreen(MGS_Message_Box,FALSE); return; } if (mgInvalidGamePassword()) { mgPrepareMessageBox(strGetString(strErrorTypingPassword),strGetString(strMustBeAtLeast2Chars)); mgShowScreen(MGS_Message_Box,FALSE); return; } tpGameCreated.numPlayers = 1; tpGameCreated.playerInfo[0].address = myAddress; tpGameCreated.playerInfo[0].playerIndex = 0; tpGameCreated.playerInfo[0].baseColor = utyBaseColor; tpGameCreated.playerInfo[0].stripeColor = utyStripeColor; tpGameCreated.playerInfo[0].colorsPicked = cpColorsPicked; tpGameCreated.playerInfo[0].race = whichRaceSelected; tpGameCreated.playerInfo[0].behindFirewall = titanBehindFirewall(); strcpy(tpGameCreated.playerInfo[0].PersonalName, utyName); dbgAssert(strlen(spScenarios[spCurrentSelected].fileSpec) <= MAX_MAPNAME_LEN); memStrncpy(tpGameCreated.DisplayMapName,spScenarios[spCurrentSelected].title,MAX_MAPNAME_LEN); memStrncpy(tpGameCreated.MapName,spScenarios[spCurrentSelected].fileSpec,MAX_MAPNAME_LEN); generateDirectoryCustomInfo(&buildDirectoryCustomInfo); buildDirectoryCustomInfo.captainAddress = myAddress; mgGameInterestedIn(tpGameCreated.Name); titanCreateGame(tpGameCreated.Name, (DirectoryCustomInfo *)&buildDirectoryCustomInfo); donerefreshing=TRUE; //WaitingForGame = TRUE; //GameCreator = TRUE; // bring up the connecting status screen mgShowScreen(MGS_Connecting,FALSE); mgConnectingScreenGoto = MGS_Captain_Wait; mgDisplayMessage(strGetString(strCreatingGame)); //mgShowScreen(MGS_Captain_Wait,TRUE); //mgUpdateGameInfo(); } } } void mgGameNameTextEntry(char *name, featom *atom) { static char asciigamename[MAX_GAMENAME_LENGTH]; if (FEFIRSTCALL(atom)) { // initialize button here mgGameNameTextEntryBox = (textentryhandle)atom->pData; uicTextEntryInit(mgGameNameTextEntryBox,0); uicTextBufferResize(mgGameNameTextEntryBox,MAX_GAMENAME_LENGTH); wcstombs(asciigamename, tpGameCreated.Name, MAX_GAMENAME_LENGTH); uicTextEntrySet(mgGameNameTextEntryBox, asciigamename, strlen(asciigamename)+1); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : mbstowcs(tpGameCreated.Name,mgGameNameTextEntryBox->textBuffer,strlen(mgGameNameTextEntryBox->textBuffer)+1); break; case CM_GainFocus : break; } } void mgChooseScenario(char *name, featom *atom) { spScenarioPick(NULL); } void mgAddCPUOpp(void) { if (tpGameCreated.numPlayers + tpGameCreated.numComputers < spScenarios[spCurrentSelected].maxplayers) { tpGameCreated.numComputers++; mgDirtyNumPlayerRegions(); } } void mgRemoveCPUOpp(void) { sdword minComp; if (LoggedIn | LANGame) { minComp = 0; } else { // CPU skirmish #ifdef fpoiker minComp = 0; #else minComp = 1; #endif } if (tpGameCreated.numComputers > minComp) { tpGameCreated.numComputers--; mgDirtyNumPlayerRegions(); } } bool mgAccelerator(void) { if (taskTimeElapsed >= mgAccTime) { mgAccTime = taskTimeElapsed + MG_WAIT_ACC; return(TRUE); } return(FALSE); /* mgAccCount--; if (!mgAccCount) { mgAccCount = mgAccRate; mgAccRate-= MG_RATE_DECREASE; if (mgAccRate < MG_MIN_ACC_RATE) mgAccRate = MG_MIN_ACC_RATE; return TRUE; } return FALSE;*/ } /*void mgAcceleratorRelease(void) { /* mgAccRate = MG_START_ACC_RATE; mgAccCount = 1; }*/ sdword mgSelectOpponentType(regionhandle region, sdword yClicked) { if ((yClicked-region->rect.y0 > mg_ArrowClickStart) && (yClicked-region->rect.y0 < mg_ArrowClickStart + mgArrowClickHeight)) { return 0; } if ((yClicked-region->rect.y0 > mg_ArrowClickStart + mgArrowClickSpacing) && (yClicked-region->rect.y0 < mg_ArrowClickStart + mgArrowClickHeight + mgArrowClickSpacing)) { return 1; } return (-1); } sdword mgRemoveCPUProcess(regionhandle region, sdword ID, udword event, udword data) { #ifdef DEBUG_STOMP regVerify(region); #endif if (event == RPE_ReleaseLeft) { mgCPULeftArrowActive = FALSE; /* mgCPUArrowIndex = -1; // mgAcceleratorRelease();*/ region->status |= RSF_DrawThisFrame; return (0); } else if (event == RPE_PressLeft) { mgAccTime = taskTimeElapsed - MG_WAIT_ACC; return(0); } else if (event == RPE_HoldLeft) { if (mgAccelerator()) mgRemoveCPUOpp(); mgCPULeftArrowActive = TRUE; /* if ( TRUE ) // max ) { mgCPULeftArrowActive = TRUE; if (mgAccelerator()) mgRemoveCPUOpp(); } else { /* Put sound effect HERE }*/ } region->status |= RSF_DrawThisFrame; return(0); } sdword mgAddCPUProcess(regionhandle region, sdword ID, udword event, udword data) { #ifdef DEBUG_STOMP regVerify(region); #endif if (event == RPE_ReleaseLeft) { mgCPURightArrowActive = FALSE; // mgCPUArrowIndex = -1; // mgAcceleratorRelease(); region->status |= RSF_DrawThisFrame; return (0); } else if (event == RPE_PressLeft) { mgAccTime = taskTimeElapsed - MG_WAIT_ACC; return(0); } else if (event == RPE_HoldLeft) { if (mgAccelerator()) mgAddCPUOpp(); mgCPURightArrowActive = TRUE; /* if ( TRUE /* max ) { mgCPURightArrowActive = TRUE; if (mgAccelerator()) { mgAddCPUOpp(); dbgMessage("."); } } else { // Put sound effect HERE }*/ } region->status |= RSF_DrawThisFrame; return(0); } /*----------------------------------------------------------------------------- Name : mgDrawArrow Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void mgDrawArrow(regionhandle region, bool leftArrow, bool human) { sdword y; rectangle *rect = ®ion->rect; triangle tri; sdword width = rect->x1 - rect->x0 - 4; bool flag; y = rect->y0 + mg_ArrowMarginTop; if(leftArrow) { tri.x0 = rect->x1 - 2; tri.x1 = rect->x0 + 2; tri.x2 = rect->x1 - 2; } else { tri.x0 = rect->x0 + 2; tri.x1 = rect->x0 + 2; tri.x2 = rect->x1 - 2; } if(leftArrow) { tri.y0 = y; tri.y1 = y + (width / 2); tri.y2 = y + width; } else { tri.y0 = y; tri.y1 = y + width; tri.y2 = y + (width / 2); } if (human) { flag = ((leftArrow && mgHumanLeftArrowActive) || (!leftArrow && mgHumanRightArrowActive)); if (flag) { mgHumanLeftArrowActive = FALSE; mgHumanRightArrowActive = FALSE; mgHumanArrowIndex = -1; primTriSolid2(&tri, colRGB(200, 0, 0)); } else if (bitTest(region->status, RSF_MouseInside) ) { primTriSolid2(&tri, colRGB(100, 100, 100)); } else { primTriSolid2(&tri, colRGB(0, 0, 0)); } } else //cpu { flag = ((leftArrow && mgCPULeftArrowActive) || (!leftArrow && mgCPURightArrowActive)); if( flag ) { mgCPULeftArrowActive = FALSE; mgCPURightArrowActive = FALSE; mgCPUArrowIndex = -1; primTriSolid2(&tri, colRGB(200, 0, 0)); } else if (bitTest(region->status, RSF_MouseInside) ) { primTriSolid2(&tri, colRGB(100, 100, 100)); } else { primTriSolid2(&tri, colRGB(0, 0, 0)); } } primTriOutline2(&tri, 1, colRGB(200, 200, 0)); } /*----------------------------------------------------------------------------- Name : mgLeftArrowDraw Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ /* void mgLeftArrowDraw(featom *atom, regionhandle region) { if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded) { //if region not processed yet region->flags = RPE_PressLeft | RPE_ReleaseLeft | RPE_HoldLeft | RPE_Enter | RPE_Exit; //receive mouse presses from now on regFunctionSet(region, mgLeftArrowProcess); //set new region handler function } //mgDrawArrow(region, TRUE); } */ /*----------------------------------------------------------------------------- Name : mgRightArrowDraw Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ /* void mgRightArrowDraw(featom *atom, regionhandle region) { if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded) { //if region not processed yet region->flags = RPE_PressLeft | RPE_ReleaseLeft | RPE_HoldLeft | RPE_Enter | RPE_Exit ; //receive mouse presses from now on regFunctionSet(region, mgRightArrowProcess); //set new region handler function } //mgDrawArrow(region, FALSE); } */ void mgAddCPUOpponent(featom *atom, regionhandle region) { if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded) { //if region not processed yet region->flags = RPE_PressLeft | RPE_ReleaseLeft | RPE_HoldLeft | RPE_Enter | RPE_Exit ; //receive mouse presses from now on if ((atom->flags & FAF_Disabled) == 0) regFunctionSet(region, (regionfunction) mgAddCPUProcess); //set new region handler function } mgDrawArrow(region, FALSE, FALSE); } void mgRemoveCPUOpponent(featom *atom, regionhandle region) { if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded) { //if region not processed yet region->flags = RPE_PressLeft | RPE_ReleaseLeft | RPE_HoldLeft | RPE_Enter | RPE_Exit ; //receive mouse presses from now on if ((atom->flags & FAF_Disabled) == 0) regFunctionSet(region, (regionfunction) mgRemoveCPUProcess); //set new region handler function } mgDrawArrow(region, TRUE, FALSE); } void mgPickGameType(char *name, featom *atom) { mgSetGameType("Give Babies A Chance"); } void mgStartingFleet(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, tpGameCreated.startingFleet); } else { tpGameCreated.startingFleet = (ubyte)atom->pData; } mgGameTypesOtherButtonPressed(); } void mgStartShip(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, bitTest(tpGameCreated.flag,MG_CarrierIsMothership) ? 1 : 0); } else { if (atom->pData) bitSet(tpGameCreated.flag,MG_CarrierIsMothership); else bitClear(tpGameCreated.flag,MG_CarrierIsMothership); } mgGameTypesOtherButtonPressed(); //#endif } void mgGameType(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, gameNum); } else { gameNum = (ubyte)atom->pData; mgSetGameTypeByNum(gameNum); //regRecursiveSetReallyDirty(feStack[feStackIndex].baseRegion); feAllCallOnCreate(feStack[feStackIndex].screen); } #endif } void mgNumberOfComputers(featom *atom, regionhandle region) { fonthandle oldfont; mgNumCompPlayerReg = region; primRectSolid2(®ion->rect,0); oldfont = fontMakeCurrent(mgOptionsFont); fontPrintf(region->rect.x0,region->rect.y0, mgNumberOfComputersColor, "%d", tpGameCreated.numComputers); fontMakeCurrent(oldfont); } /*============================================================================= Callbacks for the Advanced Game Options Screen: =============================================================================*/ void mgLastMotherShip(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_LastMotherShip)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_LastMotherShip); else bitClear(tpGameCreated.flag,MG_LastMotherShip); if ((tpGameCreated.flag & (MG_CaptureCapitalShip|MG_LastMotherShip)) == 0) { feToggleButtonSet("MG_CaptureCapitalShip",TRUE); tpGameCreated.flag |= MG_CaptureCapitalShip; } } mgGameTypesOtherButtonPressed(); } void mgCaptureCapitalShip(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_CaptureCapitalShip)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_CaptureCapitalShip); else bitClear(tpGameCreated.flag,MG_CaptureCapitalShip); if ((tpGameCreated.flag & (MG_CaptureCapitalShip|MG_LastMotherShip)) == 0) { feToggleButtonSet("MG_LastMotherShip",TRUE); tpGameCreated.flag |= MG_LastMotherShip; } } mgGameTypesOtherButtonPressed(); #endif } void mgHyperspace(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag, MG_Hyperspace)); } else { if (FECHECKED(atom)) { bitSet(tpGameCreated.flag, MG_Hyperspace); } else { bitClear(tpGameCreated.flag, MG_Hyperspace); } } mgGameTypesOtherButtonPressed(); } void mgAlliedVictory(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_AlliedVictory)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_AlliedVictory); else bitClear(tpGameCreated.flag,MG_AlliedVictory); } mgGameTypesOtherButtonPressed(); } void mgResearchEnabled(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_ResearchEnabled)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_ResearchEnabled); else bitClear(tpGameCreated.flag,MG_ResearchEnabled); } mgGameTypesOtherButtonPressed(); #endif } #if 0 void mgBountiesEnabled(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_BountiesEnabled)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_BountiesEnabled); else bitClear(tpGameCreated.flag,MG_BountiesEnabled); } mgGameTypesOtherButtonPressed(); #endif } #endif void mgBountySize(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, tpGameCreated.bountySize); } else { tpGameCreated.bountySize = (ubyte)atom->pData; } mgGameTypesOtherButtonPressed(); #endif } void mgPasswordProtected(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_PasswordProtected)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_PasswordProtected); else bitClear(tpGameCreated.flag,MG_PasswordProtected); } } void mgGamePassword(char *name, featom *atom) { static char asciipassword[MAX_PASSWORD_LENGTH]; if (FEFIRSTCALL(atom)) { // initialize button here mgGamePasswordEntryBox = (textentryhandle)atom->pData; wcstombs(asciipassword, tpGameCreated.Password, MAX_PASSWORD_LENGTH); uicTextEntrySet(mgGamePasswordEntryBox,asciipassword,strlen(asciipassword)+1); uicTextEntryInit(mgGamePasswordEntryBox,UICTE_PasswordEntry); uicTextBufferResize(mgGamePasswordEntryBox,MAX_PASSWORD_LENGTH-2); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : break; case CM_GainFocus : break; } } void mgGamePasswordConfirm(char *name, featom *atom) { static char asciipassword[MAX_PASSWORD_LENGTH]; if (FEFIRSTCALL(atom)) { // initialize button here mgGamePasswordConfirmEntryBox = (textentryhandle)atom->pData; wcstombs(asciipassword, tpGameCreated.Password, MAX_PASSWORD_LENGTH); uicTextEntrySet(mgGamePasswordConfirmEntryBox,asciipassword,strlen(asciipassword)+1); uicTextBufferResize(mgGamePasswordConfirmEntryBox,MAX_PASSWORD_LENGTH-2); uicTextEntryInit(mgGamePasswordConfirmEntryBox,UICTE_PasswordEntry); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : if (strcmp(mgGamePasswordEntryBox->textBuffer,mgGamePasswordConfirmEntryBox->textBuffer)==0) { mbstowcs(tpGameCreated.Password,mgGamePasswordEntryBox->textBuffer,strlen(mgGamePasswordEntryBox->textBuffer)+1); } break; case CM_GainFocus : break; } } void mgUnitCapsEnabled(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_UnitCapsEnabled)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_UnitCapsEnabled); else bitClear(tpGameCreated.flag,MG_UnitCapsEnabled); } mgGameTypesOtherButtonPressed(); #endif } void mgFuelBurnEnabled(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_FuelBurnEnabled)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_FuelBurnEnabled); else bitClear(tpGameCreated.flag,MG_FuelBurnEnabled); } mgGameTypesOtherButtonPressed(); #endif } void mgCratesEnabled(char *name, featom *atom) { #if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos bitSet(atom->flags, FAF_Disabled); bitSet(((region *)atom->region)->status, RSF_RegionDisabled); #else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_CratesEnabled)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_CratesEnabled); else bitClear(tpGameCreated.flag,MG_CratesEnabled); } mgGameTypesOtherButtonPressed(); #endif } /*============================================================================= Callbacks for the Resourceing Optinos Game Screen: =============================================================================*/ void mgHarvestingEnabled(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) // //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, !bitTest(tpGameCreated.flag,MG_HarvestinEnabled)); } else { if (FECHECKED(atom)) bitClear(tpGameCreated.flag,MG_HarvestinEnabled); else bitSet(tpGameCreated.flag,MG_HarvestinEnabled); } mgGameTypesOtherButtonPressed(); //#endif } void mgStartingResources(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { feRadioButtonSet(name, tpGameCreated.startingResources); } else { tpGameCreated.startingResources = (ubyte)atom->pData; } mgGameTypesOtherButtonPressed(); } void mgResourceInjections(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) // //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_ResourceInjections)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_ResourceInjections); else bitClear(tpGameCreated.flag,MG_ResourceInjections); } mgGameTypesOtherButtonPressed(); //#endif } void mgResourceInjectionInterval(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else char temp[20]; udword timemins; if (FEFIRSTCALL(atom)) { // initialize button here mgResourceInjectionIntervalEntryBox = (textentryhandle)atom->pData; timemins = (udword)((tpGameCreated.resourceInjectionInterval)/(60*UNIVERSE_UPDATE_RATE)); sprintf(temp,"%d",timemins); uicTextEntrySet(mgResourceInjectionIntervalEntryBox,temp,strlen(temp)+1); uicTextBufferResize(mgResourceInjectionIntervalEntryBox,MAX_NUM_LENGTH-2); uicTextEntryInit(mgResourceInjectionIntervalEntryBox,UICTE_NumberEntry); mgGameTypesOtherButtonPressed(); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : sscanf(mgResourceInjectionIntervalEntryBox->textBuffer,"%d",&timemins); // change the units of minutes into Univupdate slices tpGameCreated.resourceInjectionInterval = timemins*60*UNIVERSE_UPDATE_RATE; if (uicTextEntryMessage(atom)==CM_AcceptText) feToggleButtonSet("MG_ResourceInjections", TRUE); break; case CM_GainFocus : break; } mgGameTypesOtherButtonPressed(); //#endif } void mgResourceInjectionAmount(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) // //disable this function in demos /// bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else char temp[20]; if (FEFIRSTCALL(atom)) { // initialize button here mgResourceInjectionAmountEntryBox = (textentryhandle)atom->pData; sprintf(temp,"%d",tpGameCreated.resourceInjectionsAmount); uicTextEntrySet(mgResourceInjectionAmountEntryBox,temp,strlen(temp)+1); uicTextBufferResize(mgResourceInjectionAmountEntryBox,MAX_NUM_LENGTH-6); uicTextEntryInit(mgResourceInjectionAmountEntryBox,UICTE_NumberEntry); mgGameTypesOtherButtonPressed(); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : sscanf(mgResourceInjectionAmountEntryBox->textBuffer,"%d",&tpGameCreated.resourceInjectionsAmount); if (uicTextEntryMessage(atom)==CM_AcceptText) feToggleButtonSet("MG_ResourceInjections", TRUE); break; case CM_GainFocus : break; } mgGameTypesOtherButtonPressed(); //#endif } void mgResourceLumpSum(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else if (FEFIRSTCALL(atom)) { feToggleButtonSet(name, bitTest(tpGameCreated.flag,MG_ResourceLumpSum)); } else { if (FECHECKED(atom)) bitSet(tpGameCreated.flag,MG_ResourceLumpSum); else bitClear(tpGameCreated.flag,MG_ResourceLumpSum); } mgGameTypesOtherButtonPressed(); //#endif } void mgResourceLumpSumInterval(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else char temp[20]; udword timemins; if (FEFIRSTCALL(atom)) { // initialize button here mgResourceLumpSumIntervalEntryBox = (textentryhandle)atom->pData; timemins = (udword)(tpGameCreated.resourceLumpSumTime/(60*UNIVERSE_UPDATE_RATE)); sprintf(temp,"%d",timemins); uicTextEntrySet(mgResourceLumpSumIntervalEntryBox,temp,strlen(temp)+1); uicTextBufferResize(mgResourceLumpSumIntervalEntryBox,MAX_NUM_LENGTH-2); uicTextEntryInit(mgResourceLumpSumIntervalEntryBox,UICTE_NumberEntry); mgGameTypesOtherButtonPressed(); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : sscanf(mgResourceLumpSumIntervalEntryBox->textBuffer,"%d",&timemins); tpGameCreated.resourceLumpSumTime = timemins*60*UNIVERSE_UPDATE_RATE; if (uicTextEntryMessage(atom)==CM_AcceptText) feToggleButtonSet("MG_ResourceLumpSum", TRUE); break; case CM_GainFocus : break; } mgGameTypesOtherButtonPressed(); //#endif } void mgResourceLumpSumAmount(char *name, featom *atom) { //#if defined(CGW) || defined(Downloadable) || defined(OEM) //disable this function in demos // bitSet(atom->flags, FAF_Disabled); // bitSet(((region *)atom->region)->status, RSF_RegionDisabled); //#else char temp[20]; if (FEFIRSTCALL(atom)) { // initialize button here mgResourceLumpSumAmountEntryBox = (textentryhandle)atom->pData; sprintf(temp,"%d",tpGameCreated.resourceLumpSumAmount); uicTextEntrySet(mgResourceLumpSumAmountEntryBox,temp,strlen(temp)+1); uicTextBufferResize(mgResourceLumpSumAmountEntryBox,MAX_NUM_LENGTH-6); uicTextEntryInit(mgResourceLumpSumAmountEntryBox,UICTE_NumberEntry); mgGameTypesOtherButtonPressed(); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : case CM_AcceptText : sscanf(mgResourceLumpSumAmountEntryBox->textBuffer,"%d",&tpGameCreated.resourceLumpSumAmount); if (uicTextEntryMessage(atom)==CM_AcceptText) feToggleButtonSet("MG_ResourceLumpSum", TRUE); break; case CM_GainFocus : break; } mgGameTypesOtherButtonPressed(); //#endif } void mgBackFromOptions(char *name, featom *atom) { if (LANGame) { lgBackFromOptions(name, atom); } else { if (LoggedIn) { if (WaitingForGame) { if (GameCreator) { tpGameCreated = BackupGameCreated; spCurrentSelected = spCurrentSelectedBack; mgShowScreen(MGS_Captain_Wait, TRUE); } else { mgShowScreen(MGS_Player_Wait, TRUE); } } else mgShowScreen(MGS_Available_Games,TRUE); } else { mgShowScreen(MGS_Connection_Method,TRUE); } } } void mgBasicOptions(char *name,featom *atom) { if (LANGame) { lgBasicOptions(name,atom); } else { if (LoggedIn) { if (currentScreen != MGS_Basic_Options) { if (WaitingForGame) { if (GameCreator) mgShowScreen(MGS_Basic_Options_Change, TRUE); else mgShowScreen(MGS_Basic_Options_View, TRUE); } else mgShowScreen(MGS_Basic_Options,TRUE); } } else { if (currentScreen != MGS_Skirmish_Basic) { mgShowScreen(MGS_Skirmish_Basic,TRUE); } } } } void mgAdvancedOptions(char *name,featom *atom) { if (LoggedIn || LANGame) { if (currentScreen != MGS_Advanced_Options) { if (WaitingForGame) { if (GameCreator) mgShowScreen(MGS_Advanced_Options_Change, TRUE); else mgShowScreen(MGS_Advanced_Options_View, TRUE); } else mgShowScreen(MGS_Advanced_Options,TRUE); } } else { if (currentScreen != MGS_Skirmish_Advanced) { mgShowScreen(MGS_Skirmish_Advanced,TRUE); } } } void mgResourceOptions(char *name,featom *atom) { if (LoggedIn || LANGame) { if (currentScreen != MGS_Resource_Options) { if (WaitingForGame) { if (GameCreator) mgShowScreen(MGS_Resource_Options_Change, TRUE); else mgShowScreen(MGS_Resource_Options_View, TRUE); } else mgShowScreen(MGS_Resource_Options,TRUE); } } else { if (currentScreen != MGS_Skirmish_Resource) { mgShowScreen(MGS_Skirmish_Resource,TRUE); } } } /*============================================================================= Callbacks for the Player options screen: =============================================================================*/ void mgSetColorsNow(char *name, featom *atom) { cpResetRegions(); cpAcceptColors(); if (WaitingForGame) { if (GameCreator) { titanUpdatePlayer(TRUE); } else { titanUpdatePlayer(FALSE); } } dbgAssert(lastScreen != -1); mgShowScreen(lastScreen, TRUE); } void mgBackFromPlayerOptions(char *name, featom *atom) { dbgAssert(lastScreen != -1); cpResetRegions(); whichRaceSelected = RaceSave; utyBaseColor = BaseColorSave; utyStripeColor = StripeColorSave; mgShowScreen(lastScreen, TRUE); } /*============================================================================= Callbacks for the Connecting Status Screen: =============================================================================*/ void mgConnectingCancel(char *name, featom *atom) { mgQueryType = -1; cResetFSM(); titanConnectingCancelHit(); mgShowScreen(mgConnectingScreenGoto,TRUE); } void mgConnectingStatusItemDraw(rectangle *rect, listitemhandle data) { sdword x, y; fonthandle oldfont; statusline *statinfo = (statusline *)data->data; oldfont = fontMakeCurrent(mgConnectingFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; fontPrintf(x,y,mgConnectingStatusColor,"%s",statinfo->message); fontMakeCurrent(oldfont); } void mgConnectingStatusInit(char *name, featom *atom) { fonthandle oldfont; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgConnectingFont); mgConnectingStatusWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgConnectingStatusWindow, NULL, // title draw, no title NULL, // title click process, no title 0, // title height, no title mgConnectingStatusItemDraw, // item draw funtcion fontHeight(" "), // item height UICLW_AutoScroll); fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { mgConnectingStatusWindow = NULL; return; } } /*============================================================================= Callbacks for the game entry screen.: =============================================================================*/ void mgGamePasswordEntry(char *name, featom *atom) { if (FEFIRSTCALL(atom)) { // initialize button here mgGamePasswordEntryEntryBox = (textentryhandle)atom->pData; uicTextBufferResize(mgGamePasswordEntryEntryBox,MAX_PASSWORD_LENGTH-2); uicTextEntryInit(mgGamePasswordEntryEntryBox,UICTE_PasswordEntry); return; } switch (uicTextEntryMessage(atom)) { case CM_LoseFocus : break; case CM_AcceptText : if (!LANGame) { if (currentScreen == MGS_Game_Password) { mgGoPassword(NULL,NULL); } else if (currentScreen == MGS_Room_Password) { mgGoRoomPassword(NULL, NULL); } } else { lgGoPassword(NULL, NULL); } break; case CM_GainFocus : break; } } void mgBackFromPassword(char *name, featom *atom) { mgShowScreen(MGS_Available_Games,TRUE); } void mgGoPassword(char *name, featom *atom) { static wchar_t widepasswordentryboxtext[MAX_PASSWORD_LENGTH]; if (joingame!=NULL) { mbstowcs(widepasswordentryboxtext,mgGamePasswordEntryEntryBox->textBuffer,strlen(mgGamePasswordEntryEntryBox->textBuffer)+1); if (wcscmp(widepasswordentryboxtext,joingame->directoryCustomInfo.stringdata)==0) { mgRequestJoinGame(joingame); } else { mgPrepareMessageBox(strGetString(strIncorrectPassword),NULL); mgShowScreen(MGS_Message_Box,FALSE); } } } void mgBackFromRoomPassword(char *name, featom *atom) { mgShowScreen(MGS_Available_Channels,TRUE); } void mgGoRoomPassword(char *name, featom *atom) { if (wcslen(joinchannelname) >= 2) { mbstowcs(ChannelPassword,mgGamePasswordEntryEntryBox->textBuffer,strlen(mgGamePasswordEntryEntryBox->textBuffer)+1); mgJoinChannelNow(joinchannelname,joinchanneldescription); } } /*============================================================================= callbacks from the Quit WON question box.: =============================================================================*/ void mgYesQuitWON(char *name, featom *atom) { bool waitforshutdown = FALSE; LoggedIn=FALSE; if (WaitingForGame) { if (GameCreator) { titanGameDisolved(TRUE); waitforshutdown = TRUE; } else { titanLeaveGame(TRUE); waitforshutdown = TRUE; } } if (waitforshutdown) { titanWaitShutdown(); } else { titanShutdown(); } mgShowScreen(MGS_Connection_Method, TRUE); } void mgDontQuitWON(char *name, featom *atom) { mgShowScreen(-1, MG_JustOneDisappear); } /*============================================================================= Callbacks from the message box screen.: =============================================================================*/ void mgMessageOk(char *name, featom *atom) { mgShowScreen(-1, MG_JustOneDisappear); } void mgDrawMessageBox(featom *atom, regionhandle region) { sdword x, y; fonthandle oldfont; oldfont = fontMakeCurrent(mgMessageBoxFont); x = region->rect.x0 + ((region->rect.x1-region->rect.x0)-fontWidth(messageBoxString))/2; y = region->rect.y0+MG_VertSpacing/2; fontPrintf(x,y,mgMessageBoxColor,"%s",messageBoxString); if (messageBoxString2[0] != 0) { x = region->rect.x0 + ((region->rect.x1-region->rect.x0)-fontWidth(messageBoxString2))/2; y += MG_VertSpacing << 1; fontPrintf(x,y,mgMessageBoxColor,"%s",messageBoxString2); } fontMakeCurrent(oldfont); } void mgPrepareMessageBox(char *string1,char *string2) { if (string1 != NULL) { strcpy(messageBoxString,string1); } else { messageBoxString[0] = 0; } if (string2 != NULL) { strcpy(messageBoxString2,string2); } else { messageBoxString2[0] = 0; } } void GeneralMessageBox(char *string1,char *string2) // designed for external use { mgPrepareMessageBox(string1,string2); feScreenStart(ghMainRegion, "Message_Box"); } /*============================================================================= Proccess Callbacks from titan stuff.: =============================================================================*/ void mgProcessNewUserInRoom(mgqueueuserlist *user) { // see if userhere is already in the list userlist *userinfo; Node *walk; walk = listofusersinfo.head; while (walk != NULL) { userinfo = listGetStructOfNode(walk); if (strcmp(userinfo->userName,user->user.userName) == 0) { return; } walk = walk->next; } userinfo = memAlloc(sizeof(userlist), "ListofUsers",NonVolatile); strcpy(userinfo->userName, user->user.userName); userinfo->userID = user->user.userID; listAddNode(&listofusersinfo, &userinfo->link, (void *)userinfo); if (mgUserNameWindowWindow!=NULL) { userinfo->item = uicListAddItem(mgUserNameWindowWindow, (void *)userinfo, 0,UICLW_AddToTail); } } void mgProcessUserLeftRoom(mgqueueuserlist *user) { userlist *userinfo; Node *walk; walk = listofusersinfo.head; while (walk != NULL) { userinfo = listGetStructOfNode(walk); if (userinfo->userID==user->user.userID) { if (mgUserNameWindowWindow!=NULL) { uicListRemoveItem(mgUserNameWindowWindow, userinfo->item); } listDeleteNode(&userinfo->link); break; } walk = walk->next; } } void mgProcessNewRoomChat(mgqueuechatlist *chat) { userlist *userinfo; chatlist *chatinfo; Node *walk; walk = listofusersinfo.head; while (walk != NULL) { userinfo = listGetStructOfNode(walk); if ((userinfo->userID==chat->chat.index) && (!mgIsUserInList(&listofIgnoreUsers,userinfo->userName) )) { chatinfo = memAlloc(sizeof(chatlist), "ListofChat",NonVolatile); strcpy(chatinfo->chatstring, chat->chat.chatstring); strcpy(chatinfo->userName, userinfo->userName); chatinfo->messagetype = chat->chat.messagetype; mgAddChatToRoomChat(chatinfo, mgChatHistoryWindow, &listofchatinfo); break; } walk = walk->next; } } void mgProcessPingInfo(mgqueuenewping *ping) { Node *walk; gamelist *gameinfo; serverlist *serverinfo; bool foundgameping = FALSE; Address addr; walk = listofgames.head; dbgAssert(!LANGame); while (walk != NULL) { gameinfo = (gamelist *)listGetStructOfNode(walk); if (GetIPFromInternetAddress(gameinfo->game.directoryCustomInfo.pingAddress) == ping->ping.IP) { gameinfo->pingtime = ping->ping.pingtime; foundgameping = TRUE; } walk = walk->next; } walk = listofservers.head; while (walk != NULL) { serverinfo = (serverlist *)listGetStructOfNode(walk); ConvertUChar6ToAddress(serverinfo->addressstore,&addr); if (GetIPFromInternetAddress(addr) == ping->ping.IP) { serverinfo->ping = ping->ping.pingtime; refreshServersScreenRequest = TRUE; } walk = walk->next; } if ((foundgameping) && (mgListOfGamesWindow!=NULL)) { #ifdef DEBUG_STOMP regVerify(&mgListOfGamesWindow->reg); #endif mgListOfGamesWindow->reg.status |= RSF_DrawThisFrame; } } void mgProcessGameListGameAdded(mgqueuegamelistgame *added) { Node *walk; gamelist *gameinfo; // make sure we don't already have it in list walk = listofgames.head; while (walk != NULL) { gameinfo = (gamelist *)listGetStructOfNode(walk); if (wcscmp(gameinfo->game.Name,added->game.Name) == 0) { titanDebug("Warning: Game %s already present!\n",added->game.Name); return; } walk = walk->next; } // we don't have it in list, so let's add it: gameinfo = (gamelist *)memAlloc(sizeof(gamelist),"ListofGames",NonVolatile); gameinfo->game = added->game; gameinfo->pingtime = -1; listAddNode(&listofgames,&gameinfo->link, gameinfo); if (mgListOfGamesWindow!=NULL) { if (gameinfo->game.directoryCustomInfo.flag & GAME_IN_PROGRESS) gameinfo->item = uicListAddItem(mgListOfGamesWindow, (ubyte *)gameinfo, 0, UICLW_AddToTail); else gameinfo->item = uicListAddItem(mgListOfGamesWindow, (ubyte *)gameinfo, UICLI_CanSelect, UICLW_AddToHead); } else { gameinfo->item = NULL; } } void mgProcessGameListGameRemoved(mgqueuegamelistgame *removed) { Node *walk; gamelist *gameinfo; // make sure we have it walk = listofgames.head; while (walk != NULL) { gameinfo = (gamelist *)listGetStructOfNode(walk); if (wcscmp(gameinfo->game.Name,removed->game.Name) == 0) { goto foundit; } walk = walk->next; } titanDebug("Warning: Told to remove game %s I can't find!\n",removed->game.Name); return; foundit: // walk and gameinfo should be set with the game to remove now if (mgListOfGamesWindow!=NULL) { if (gameinfo->item) { uicListRemoveItem(mgListOfGamesWindow, gameinfo->item); } } listDeleteNode(walk); } void mgProcessGameListGameChanged(mgqueuegamelistgame *changed) { Node *walk; gamelist *gameinfo; // make sure we have it walk = listofgames.head; while (walk != NULL) { gameinfo = (gamelist *)listGetStructOfNode(walk); if (wcscmp(gameinfo->game.Name,changed->game.Name) == 0) { goto foundit; } walk = walk->next; } titanDebug("Warning: Told to change game %s I can't find!\n",changed->game.Name); return; foundit: gameinfo->game = changed->game; if (mgListOfGamesWindow!=NULL) { if (gameinfo->game.directoryCustomInfo.flag & GAME_IN_PROGRESS) bitClear(gameinfo->item->flags,UICLI_CanSelect); else bitSet(gameinfo->item->flags,UICLI_CanSelect); #ifdef DEBUG_STOMP regVerify(&mgListOfGamesWindow->reg); #endif mgListOfGamesWindow->reg.status |= RSF_DrawThisFrame; } } void mgProcessGameListNew(mgqueuegamelistnew *newlist) { // fill in later } void mgProcessNewStatusInfo(mgqueuestatusline *status) { statusline *statinfo; if (mgConnectingStatusWindow!=NULL) { statinfo = memAlloc(sizeof(statusline), "StatusWindowList",NonVolatile); strcpy(statinfo->message, status->status.message); listAddNode(&statusitemlist, &statinfo->link, statinfo); uicListAddItem(mgConnectingStatusWindow, (void *)statinfo, 0,UICLW_AddToTail); } } bool mgIsPlayerInList(LinkedList *list, gameplayerinfo *find) { Node *walk; gameplayerinfo *player; walk = list->head; while (walk != NULL) { player = listGetStructOfNode(walk); if (strcmp(player->name,find->name) == 0) { return (TRUE); } walk = walk->next; } return (FALSE); } void mgProcessGamePlayerInfo(mgqueuegameplayerinfo *player) { gameplayerinfo *playerinfo, *newplayer, *oldplayer; Node *oldlist, *newlist; chatlist *chatinfo; if (player->player.index == 0) { if (mgGameUserNameWindow!=NULL) { uicListCleanUp(mgGameUserNameWindow); } listMoveContentsOfList(&listofplayersold, &listofplayers); spFindMap(tpGameCreated.DisplayMapName); } playerinfo = memAlloc(sizeof(gameplayerinfo), "List Of Users", NonVolatile); strcpy(playerinfo->name, player->player.name); playerinfo->baseColor = player->player.baseColor; playerinfo->stripeColor = player->player.stripeColor; playerinfo->colorsPicked = player->player.colorsPicked; playerinfo->race = player->player.race; playerinfo->index = player->player.index; listAddNode(&listofplayers, &playerinfo->link, playerinfo); if (mgGameUserNameWindow!=NULL) { playerinfo->item = uicListAddItem(mgGameUserNameWindow, (void *)playerinfo, 0,UICLW_AddToTail); } // if last player is added, search through the two lists to see who has left and // who has joined the game. if (player->player.index == sigsNumPlayers-1) { // search the oldlist and see if you were in it and not in the new list if so then you have left the game oldlist = listofplayersold.head; while (oldlist != NULL) { oldplayer = listGetStructOfNode(oldlist); if (!mgIsPlayerInList(&listofplayers, oldplayer)) { chatinfo = memAlloc(sizeof(chatlist), "GameChat",NonVolatile); sprintf(chatinfo->chatstring, " %s ", strGetString(strHasLeft)); wcstombs(chatinfo->chatstring + strlen(chatinfo->chatstring), tpGameCreated.Name, MAX_CHATSTRING_LENGTH - strlen(chatinfo->chatstring)); strcpy(chatinfo->userName, oldplayer->name); chatinfo->messagetype = MG_MESSAGECHAT; chatinfo->baseColor = mgGameMessageChatColor; mgAddChatToRoomChat(chatinfo, mgGameChatWindowWindow, &listofgamechatinfo); } oldlist = oldlist->next; } // search the new list and see if you were in it and not in the old list then you have joined the game newlist = listofplayers.head; while (newlist != NULL) { newplayer = listGetStructOfNode(newlist); if (!mgIsPlayerInList(&listofplayersold, newplayer)) { if ( (GameCreator) || (listofplayersold.num!=0) || ( (listofplayersold.num==0) && (newplayer->index==sigsPlayerIndex)) ) { chatinfo = memAlloc(sizeof(chatlist), "GameChat",NonVolatile); sprintf(chatinfo->chatstring, " %s ", strGetString(strHasJoined)); wcstombs(chatinfo->chatstring + strlen(chatinfo->chatstring), tpGameCreated.Name, MAX_CHATSTRING_LENGTH - strlen(chatinfo->chatstring)); strcpy(chatinfo->userName, newplayer->name); chatinfo->messagetype = MG_MESSAGECHAT; mgAddChatToRoomChat(chatinfo, mgGameChatWindowWindow, &listofgamechatinfo); } } newlist = newlist->next; } listDeleteAll(&listofplayersold); } } void mgProccessNewGameChat(mgqueuechatlist *chat) { gameplayerinfo *userinfo; chatlist *chatinfo; Node *walk; walk = listofplayers.head; while (walk != NULL) { userinfo = listGetStructOfNode(walk); if (userinfo->index==chat->chat.index) { chatinfo = memAlloc(sizeof(chatlist), "GameChat",NonVolatile); strcpy(chatinfo->chatstring, chat->chat.chatstring); strcpy(chatinfo->userName, userinfo->name); chatinfo->baseColor = userinfo->baseColor; chatinfo->messagetype = chat->chat.messagetype; mgAddChatToRoomChat(chatinfo, mgGameChatWindowWindow, &listofgamechatinfo); break; } walk = walk->next; } } #if 0 void mgProcessNumPeopleRoom(mgqueuenumpeopleroominfo *numpeopleinfo) { Node *walk = listofchannels.head; channellist *channelinfo; while (walk!=NULL) { channelinfo = (channellist *)listGetStructOfNode(walk); if (wcscmp(numpeopleinfo->channelname,channelinfo->channelname)==0) { if (channelinfo->numpeople != numpeopleinfo->numpeople) { channelinfo->numpeople = numpeopleinfo->numpeople; refreshChannelsScreenRequest = TRUE; } break; } walk = walk->next; } } #endif void mgProcessChatDisconnected(void) { mgPrepareMessageBox(strGetString(strChatDisconnected),NULL); mgShowScreen(MGS_Message_Box,FALSE); } void mgProcessDisolveGame(void) { mgGameInterestedOff(); mgShowScreen(MGS_Channel_Chat,TRUE); mgPrepareMessageBox(strGetString(strCaptainDisolvedGame),NULL); mgShowScreen(MGS_Message_Box,FALSE); WaitingForGame = FALSE; GameCreator = FALSE; } void mgProcessKickedOut(void) { mgGameInterestedOff(); titanLeaveGameNotify(); mgShowScreen(MGS_Channel_Chat,TRUE); mgPrepareMessageBox(strGetString(strCommandKickPlayer),NULL); mgShowScreen(MGS_Message_Box,FALSE); WaitingForGame = FALSE; GameCreator = FALSE; } #pragma optimize("gy", off) //turn on stack frame (we need ebp for this function) void mgProcessCallBacksTask(void) { static Node *walk; static Node *nextnode; static channellist *channelinfo; static serverlist *serverinfo; static bool found; static sdword sizeofpacket, i; static ubyte *packet; static ubyte *copypacket; taskYield(0); while (1) { taskStackSaveCond(0); #if defined(OEM) || defined(Downloadable) || defined(CGW) ; #else if (mgListOfChannelsWindow!=NULL) { tpLockChannelList(); if (tpChannelList.newDataArrived) { // remove any channels that aren't there any more walk = listofchannels.head; while (walk!=NULL) { channelinfo = (channellist *)listGetStructOfNode(walk); found = FALSE; for (i = 0;i < tpChannelList.numChannels; i++) { if (wcscmp(tpChannelList.tpChannels[i].ChannelName,channelinfo->channelname)==0) { found = TRUE; break; } } nextnode = walk->next; if (!found) { // this channel isn't here anymore, so remove it: uicListRemoveItem(mgListOfChannelsWindow,channelinfo->item); listDeleteNode(walk); } else { if (channelinfo->numpeople != tpChannelList.tpChannels[i].roomfullness) { channelinfo->numpeople = tpChannelList.tpChannels[i].roomfullness; refreshChannelsScreenRequest = TRUE; } } walk = nextnode; } // add any new channels to list for (i = 0; i < tpChannelList.numChannels; i++) { walk = listofchannels.head; found = FALSE; while (walk!=NULL) { channelinfo = (channellist *)listGetStructOfNode(walk); if (wcscmp(tpChannelList.tpChannels[i].ChannelName,channelinfo->channelname)==0) { found = TRUE; break; } walk = walk->next; } if (found==FALSE) { channelinfo = (channellist *)memAlloc(sizeof(channellist),"ListofChannels",NonVolatile); wcscpy(channelinfo->channelname, tpChannelList.tpChannels[i].ChannelName); wcscpy(channelinfo->description, tpChannelList.tpChannels[i].ChannelDescription); channelinfo->roomflags = tpChannelList.tpChannels[i].roomflags; channelinfo->numpeople = tpChannelList.tpChannels[i].roomfullness; listAddNode(&listofchannels,&channelinfo->link, channelinfo); channelinfo->item = uicListAddItem(mgListOfChannelsWindow, (ubyte *)channelinfo, UICLI_CanSelect,UICLW_AddToTail); } } tpChannelList.newDataArrived = FALSE; } tpUnLockChannelList(); if (currentScreen == MGS_Available_Channels) { if (refreshChannelsScreenRequest) { regRecursiveSetReallyDirty(ghMainRegion); refreshChannelsScreenRequest = FALSE; } } } if (mgListOfServersWindow != NULL) { tpLockServerList(); if (tpServerList.newDataArrived) { // remove any servers that aren't there any more walk = listofservers.head; while (walk!=NULL) { serverinfo = (serverlist *)listGetStructOfNode(walk); found = FALSE; for (i = 0;i < tpServerList.numServers; i++) { if (wcscmp(tpServerList.tpServers[i].ServerName,serverinfo->ServerName)==0) { found = TRUE; break; } } nextnode = walk->next; if (!found) { // this Server isn't here anymore, so remove it: uicListRemoveItem(mgListOfServersWindow,serverinfo->item); listDeleteNode(walk); } else { #if 0 if (serverinfo->ping != tpServerList.tpServers[i].ping) { serverinfo->ping = tpServerList.tpServers[i].ping; refreshServersScreenRequest = TRUE; } #endif if (serverinfo->reliability != tpServerList.tpServers[i].reliability) { serverinfo->reliability = tpServerList.tpServers[i].reliability; refreshServersScreenRequest = TRUE; } if (serverinfo->flags != tpServerList.tpServers[i].flags) { serverinfo->flags = tpServerList.tpServers[i].flags; refreshServersScreenRequest = TRUE; } } walk = nextnode; } // add any new servers to list for (i = 0; i < tpServerList.numServers; i++) { walk = listofservers.head; found = FALSE; while (walk!=NULL) { serverinfo = (serverlist *)listGetStructOfNode(walk); if (wcscmp(tpServerList.tpServers[i].ServerName,serverinfo->ServerName)==0) { found = TRUE; break; } walk = walk->next; } if (found==FALSE) { serverinfo = (serverlist *)memAlloc(sizeof(serverlist),"listofservers",NonVolatile); wcscpy(serverinfo->ServerName, tpServerList.tpServers[i].ServerName); wcscpy(serverinfo->ServerDescription, tpServerList.tpServers[i].ServerDescription); serverinfo->flags = tpServerList.tpServers[i].flags; serverinfo->reliability = tpServerList.tpServers[i].reliability; serverinfo->ping = tpServerList.tpServers[i].ping; memcpy(serverinfo->addressstore,tpServerList.tpServers[i].addressstore,6); listAddNode(&listofservers,&serverinfo->link, serverinfo); serverinfo->item = uicListAddItem(mgListOfServersWindow, (ubyte *)serverinfo, UICLI_CanSelect,UICLW_AddToTail); } } tpServerList.newDataArrived = FALSE; } tpUnLockServerList(); if (currentScreen == MGS_Choose_Server) { if (refreshServersScreenRequest) { regRecursiveSetReallyDirty(ghMainRegion); refreshServersScreenRequest = FALSE; } } } LockMutex(changescreenmutex); if (newscreen==TRUE) { mgShowScreen(screenaskedfor,hideallscreens); newscreen=FALSE; } UnLockMutex(changescreenmutex); #if PUBLIC_BETA if (betaDoneVerifying) { betaDoneVerifying = FALSE; mgBackToConnection(NULL,NULL); } #endif LockMutex(gamestartedmutex); if (gamestarted) { sigsNumPlayers = tpGameCreated.numPlayers; sigsPressedStartGame = TRUE; mgShutdownMultiPlayerGameScreens(); gamestarted = FALSE; } UnLockMutex(gamestartedmutex); while (queueNumberEntries(mgThreadTransfer)!=0) { LockQueue(&mgThreadTransfer); sizeofpacket = Dequeue(&mgThreadTransfer, &packet); dbgAssert(sizeofpacket > 0); copypacket = memAlloc(sizeofpacket,"mg(mgthreadtransfer)", Pyrophoric); memcpy(copypacket, packet, sizeofpacket); UnLockQueue(&mgThreadTransfer); switch (((mgqueuegeneral *)copypacket)->packettype) { case MG_QUEUEROOMNEWUSERINFO: { mgProcessNewUserInRoom((mgqueueuserlist *)copypacket); } break; case MG_QUEUEROOMGONEUSERINFO: { mgProcessUserLeftRoom((mgqueueuserlist *)copypacket); } break; case MG_QUEUEROOMCHATINFO: { mgProcessNewRoomChat((mgqueuechatlist *)copypacket); } break; case MG_QUEUEPINGINFO: { mgProcessPingInfo((mgqueuenewping *)copypacket); } break; case MG_QUEUEGAMELISTGAMEADDED: { mgProcessGameListGameAdded((mgqueuegamelistgame *)copypacket); } break; case MG_QUEUEGAMELISTGAMEREMOVED: { mgProcessGameListGameRemoved((mgqueuegamelistgame *)copypacket); } break; case MG_QUEUEGAMELISTGAMECHANGED: { mgProcessGameListGameChanged((mgqueuegamelistgame *)copypacket); } break; case MG_QUEUEGAMELISTNEW: { mgProcessGameListNew((mgqueuegamelistnew *)copypacket); } break; case MG_QUEUESTATUSINFO: { mgProcessNewStatusInfo((mgqueuestatusline *)copypacket); } break; case MG_QUEUEGAMEPLAYER: { mgProcessGamePlayerInfo((mgqueuegameplayerinfo *)copypacket); } break; case MG_QUEUEGAMECHATINFO: { mgProccessNewGameChat((mgqueuechatlist *)copypacket); } break; case MG_QUEUEGAMEDISOLVED: { mgProcessDisolveGame(); } break; case MG_QUEUECHATDISCONNECTED: { mgProcessChatDisconnected(); } break; case MG_QUEUEKICKEDOUT: { mgProcessKickedOut(); } break; #if 0 case MG_QUEUENUMPEOPLEROOM: { mgProcessNumPeopleRoom((mgqueuenumpeopleroominfo *)copypacket); } break; #endif } memFree(copypacket); } #endif //defined(OEM) || defined(Downloadable) || defined(CGW) taskStackRestoreCond(); taskYield(0); } } #pragma optimize("", on) /*============================================================================= Startup the multiplayer game screens and display the connection screen: =============================================================================*/ void mgStartMultiPlayerGameScreens(regionhandle region, sdword ID, udword event, udword data, bool AlreadyLoggedIn) { #if 0 // relocated to mgStartup if (!mgScreensHandle) { feCallbackAddMultiple(mgCallBack); feDrawCallbackAddMultiple(mgDrawCallback); mgScreensHandle = feScreensLoad(MG_FIBFile); } #endif bitClear(tpGameCreated.flag,GAME_IN_PROGRESS); mgValidateName(); mgRunning = TRUE; WaitingForGame = FALSE; GameCreator = FALSE; listDeleteAll(&listofgames); listDeleteAll(&listofchannels); listDeleteAll(&listofchatinfo); listDeleteAll(&listofusersinfo); listDeleteAll(&listtoping); listDeleteAll(&statusitemlist); listDeleteAll(&listofplayers); listDeleteAll(&listofplayersold); listDeleteAll(&listofgamechatinfo); mgPlayerLimit = 0; mgResetNamePassword(); if (AlreadyLoggedIn) { LoggedIn=TRUE; multiPlayerGame = TRUE; mgShowScreen(MGS_Connecting,TRUE); mgConnectingScreenGoto = MGS_Channel_Chat; cJoinChannelRequest(GetCurrentChannel(),GetCurrentChannelDescription()); } else { LoggedIn=FALSE; #if PUBLIC_BETA if (!betaVerified) { betaVerifying = TRUE; mgInternetWON(NULL,NULL); } else #endif mgShowScreen(MGS_Connection_Method,TRUE); } taskResume(ProccessCallback); } void mgShutdownMultiPlayerGameScreens(void) { taskPause(ProccessCallback); listDeleteAll(&listofgames); listDeleteAll(&listofchannels); listDeleteAll(&listofchatinfo); listDeleteAll(&listofusersinfo); listDeleteAll(&listofplayers); listDeleteAll(&listofgamechatinfo); mgPlayerLimit = 0; mgRunning = FALSE; WaitingForGame = FALSE; GameCreator = FALSE; mgShowScreen(-1,TRUE); } void mgStartup(void) { mgListOfGamesFont = frFontRegister(mgListOfGamesFontName); mgChatWindowFont = frFontRegister(mgChatWindowFontName); mgUserNameFont = frFontRegister(mgUserNameFontName); mgCurrentChannelFont = frFontRegister(mgCurrentChannelFontName); mgChannelListTitleFont = frFontRegister(mgChannelListTitleFontName); mgChannelListFont = frFontRegister(mgChannelListFontName); mgGameListTitleFont = frFontRegister(mgGameListTitleFontName); mgGameChatFont = frFontRegister(mgGameChatFontName); mgGameUserNameFont = frFontRegister(mgGameUserNameFontName); mgCurrentGameFont = frFontRegister(mgCurrentGameFontName); mgOptionsFont = frFontRegister(mgOptionsFontName); mgConnectingFont = frFontRegister(mgConnectingFontName); mgMessageBoxFont = frFontRegister(mgMessageBoxFontName); if (!mgScreensHandle) { feCallbackAddMultiple(mgCallBack); feDrawCallbackAddMultiple(mgDrawCallback); mgScreensHandle = feScreensLoad(MG_FIBFile); } if (!mgScreensHandleServers) { feCallbackAddMultiple(mgCallBackServers); //feDrawCallbackAddMultiple(mgDrawCallbackServers); mgScreensHandleServers = feScreensLoad(MG_FIBFile_SERVERS); } InitQueue(&mgThreadTransfer, MG_QUEUEBUFFERSIZE); GameWereInterestedIn[0] = 0; changescreenmutex = (void *)CreateMutex(NULL,FALSE,NULL); gamestartedmutex = (void *)CreateMutex(NULL,FALSE,NULL); GameWereInterestedInMutex = (void *)CreateMutex(NULL,FALSE,NULL); ProccessCallback = taskStart(mgProcessCallBacksTask, MG_TaskServicePeriod, 0); taskPause(ProccessCallback); titanGameStartup(); switch (strCurLanguage) { case languageEnglish : mgCommandInfoPtr = mgCommandEnglish; break; case languageFrench : mgCommandInfoPtr = mgCommandFrench; break; case languageGerman : mgCommandInfoPtr = mgCommandGerman; break; case languageSpanish : mgCommandInfoPtr = mgCommandSpanish; break; case languageItalian : mgCommandInfoPtr = mgCommandItalian; break; } listInit(&listofIgnoreUsers); listInit(&listofBannedUsers); //mgGameTypeScriptInit(); } void mgShutdown(void) { CloseQueue(&mgThreadTransfer); CloseHandle((HANDLE)changescreenmutex); CloseHandle((HANDLE)gamestartedmutex); CloseHandle((HANDLE)GameWereInterestedInMutex); titanGameShutdown(); } /*============================================================================= Callbacks from the chatting system.: =============================================================================*/ void chatReceiveUserJoinReply(short status, unsigned long userID) { mgqueueuserlist user; mgqueuechatlist chat; switch (status) { case StatusRouting_InvalidPassword: mgDisplayMessage(strGetString(strInvalidRoomPassword)); cNotifyChatBadResponse(); return; case StatusRouting_UserAlreadyExists: case StatusRouting_ClientAlreadyExists: mgDisplayMessage(strGetString(strErrorUserAlreadyExists)); cNotifyChatBadResponse(); return; case StatusRouting_ServerFull: mgDisplayMessage(strGetString(strErrorRoomFull)); cNotifyChatBadResponse(); return; case StatusCommon_Success: case StatusRouting_ClientAlreadyRegistered: break; default: mgDisplayMessage(strGetString(strFailedToChat)); cNotifyChatBadResponse(); return; } cNotifyChatConnected(); LockQueue(&mgThreadTransfer); // Queue up the packet that will add you to the user list mgMyChatUserID = userID; user.header.packettype = MG_QUEUEROOMNEWUSERINFO; strcpy(user.user.userName, utyName); user.user.userID = userID; Enqueue(&mgThreadTransfer, (ubyte *)&user, sizeof(mgqueueuserlist)); // Queue up the packet that will say, have joined the room. chat.header.packettype = MG_QUEUEROOMCHATINFO; sprintf(chat.chat.chatstring," %s ", strGetString(strHasJoined)); wcstombs(chat.chat.chatstring + strlen(chat.chat.chatstring), GetCurrentChannel(), MAX_CHATSTRING_LENGTH - strlen(chat.chat.chatstring)); chat.chat.index = userID; chat.chat.messagetype = MG_MESSAGECHAT; Enqueue(&mgThreadTransfer, (ubyte *)&chat, sizeof(mgqueuechatlist)); UnLockQueue(&mgThreadTransfer); LockMutex(changescreenmutex); newscreen = TRUE; screenaskedfor = MGS_Channel_Chat; hideallscreens = TRUE; UnLockMutex(changescreenmutex); } void chatReceiveUsersHere(const char *name, unsigned long userID) { mgqueueuserlist user; LockQueue(&mgThreadTransfer); user.header.packettype = MG_QUEUEROOMNEWUSERINFO; user.user.userID = userID; strcpy(user.user.userName, name); Enqueue(&mgThreadTransfer, (ubyte *)&user, sizeof(mgqueueuserlist)); UnLockQueue(&mgThreadTransfer); } void chatReceiveUsersJoined(const char *name, unsigned long userID) { mgqueueuserlist user; mgqueuechatlist chat; LockQueue(&mgThreadTransfer); user.header.packettype = MG_QUEUEROOMNEWUSERINFO; user.user.userID = userID; strcpy(user.user.userName, name); Enqueue(&mgThreadTransfer, (ubyte *)&user, sizeof(mgqueueuserlist)); // Queue up the packet that will say, have joined the room. chat.header.packettype = MG_QUEUEROOMCHATINFO; sprintf(chat.chat.chatstring," %s ", strGetString(strHasJoined)); wcstombs(chat.chat.chatstring + strlen(chat.chat.chatstring), GetCurrentChannel(), MAX_CHATSTRING_LENGTH - strlen(chat.chat.chatstring)); chat.chat.index = userID; chat.chat.messagetype = MG_MESSAGECHAT; Enqueue(&mgThreadTransfer, (ubyte *)&chat, sizeof(mgqueuechatlist)); UnLockQueue(&mgThreadTransfer); } void chatReceiveUserLeft(unsigned long userID) { mgqueueuserlist user; mgqueuechatlist chat; LockQueue(&mgThreadTransfer); // Queue up the packet that will say, have left the room. chat.header.packettype = MG_QUEUEROOMCHATINFO; sprintf(chat.chat.chatstring," %s ", strGetString(strHasLeft)); wcstombs(chat.chat.chatstring + strlen(chat.chat.chatstring), GetCurrentChannel(), MAX_CHATSTRING_LENGTH - strlen(chat.chat.chatstring)); chat.chat.index = userID; chat.chat.messagetype = MG_MESSAGECHAT; Enqueue(&mgThreadTransfer, (ubyte *)&chat, sizeof(mgqueuechatlist)); user.header.packettype = MG_QUEUEROOMGONEUSERINFO; user.user.userID = userID; Enqueue(&mgThreadTransfer, (ubyte *)&user, sizeof(mgqueueuserlist)); UnLockQueue(&mgThreadTransfer); } void chatReceiveMessage(unsigned long originUserID, sdword whisper,unsigned long type, unsigned long size, const void* chatData) { mgqueuechatlist chat; char aNarrowString[MAX_CHATSTRING_LENGTH]; unsigned long i; unsigned long aNumChars = size >> 1; if (originUserID != mgMyChatUserID) { LockQueue(&mgThreadTransfer); chat.header.packettype = MG_QUEUEROOMCHATINFO; memset(chat.chat.chatstring,0,MAX_CHATSTRING_LENGTH); for (i = 0; i < aNumChars; ++i) { if (wctomb(aNarrowString+i, *((wchar_t*)chatData+i)) == -1) { UnLockQueue(&mgThreadTransfer); return; } } memcpy(chat.chat.chatstring,aNarrowString,aNumChars); if (whisper!=0) chat.chat.messagetype = MG_WHISPEREDCHAT; else chat.chat.messagetype = MG_NORMALCHAT; chat.chat.index = originUserID; Enqueue(&mgThreadTransfer, (ubyte *)&chat, sizeof(mgqueuechatlist)); UnLockQueue(&mgThreadTransfer); } } void patchResetVariables(void) { patchLenSoFar = 0; patchTotalLen = 0; patchErrorMsg = 0; patchAbortRequest = 0; patchComplete = 0; } // note: called from another thread void titanPatchProgressCB(int lenSoFar,int totalLen) { patchLenSoFar = lenSoFar; patchTotalLen = totalLen; } // note: called from another thread void titanGetPatchCompleteCB(void) { patchComplete = 1; } // note: called from another thread void titanGetPatchFailedCB(int patchFailErrorMsg) { patchErrorMsg = patchFailErrorMsg; } void drawBarWithOutline(rectangle *rect,real32 progress,color barcolor,color baroutlinecolor) { rectangle temp; //rectangle clear; temp.x0 = rect->x0; temp.y0 = rect->y0; temp.x1 = rect->x0 + (sdword)((rect->x1-rect->x0)*progress); temp.y1 = rect->y1; #if 0 clear.y0 = temp.y0; clear.y1 = temp.y1; clear.x0 = temp.x1; clear.x1 = rect->x1; primRectSolid2(&clear, colBlack); #endif primRectSolid2(&temp, barcolor); primRectOutline2(rect, 1, baroutlinecolor); } extern fonthandle selGroupFont1; void mgDrawPatchProgress(featom *atom, regionhandle region) { fonthandle oldfont; rectangle pos=region->rect; real32 progress; sdword fontheight; bitSet(region->flags,RPE_DrawEveryFrame); oldfont = fontMakeCurrent(selGroupFont1); fontheight = fontHeight(" "); pos.y0 += fontheight; pos.y1 = pos.y0 + fontheight; primRectSolid2(&pos,colBlack); if (patchErrorMsg) { switch (patchErrorMsg) { case PATCHFAIL_UNABLE_TO_CONNECT: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_UNABLE_TO_CONNECT)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_ERROR_SENDING_REQUEST: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_ERROR_SENDING_REQUEST)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_ERROR_RECEIVING_HTTP_HEADER: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_ERROR_RECEIVING_HTTP_HEADER)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_INVALID_FILE_LENGTH: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_INVALID_FILE_LENGTH)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_ERROR_RECEIVING_PATCH: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_ERROR_RECEIVING_PATCH)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_UNABLE_TO_START_DOWNLOAD_THREAD: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_UNABLE_TO_START_DOWNLOAD_THREAD)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_INVALID_STATUS_REPLY: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPATCHFAIL_INVALID_STATUS_REPLY)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; case PATCHFAIL_UNABLE_TO_CREATE_FILE: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchUnableCreateFile)); break; case PATCHFAIL_UNABLE_TO_WRITE_FILE: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchUnableWriteFile)); break; case PATCHFAIL_USERABORT: fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchUserAbort)); break; default: fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchGeneralError),patchErrorMsg); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strTryLaterDownloadManually)); pos.y0 += fontheight; fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, "%s", PATCHSERVER_IPSTRINGS[0]); break; } } else if (patchTotalLen > 0) { fontPrintf(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchDownloading), patchLenSoFar, patchTotalLen); pos.y0 += fontheight; pos.y1 += 100; progress = (real32)patchLenSoFar / (real32)patchTotalLen; if (progress < 0.0f) progress = 0.0f; else if (progress > 1.0f) progress = 1.0f; drawBarWithOutline(&pos,progress,PATCHBARCOLOR,PATCHBAROUTLINECOLOR); } else { fontPrint(pos.x0,pos.y0, mgMessageBoxColor, strGetString(strPatchStartingDownload)); } fontMakeCurrent(oldfont); } void mgYesDownloadPatch(char *name, featom *atom) { char patchpath[150]; mgShowScreen(MGS_Downloading_Patch,FALSE); patchResetVariables(); strcpy(patchpath,languageVersion); strcat(patchpath,"/"); strcat(patchpath,PATCHNAME); titanGetPatch(patchpath,PATCHNAME); } void mgNoDownloadPatch(char *name, featom *atom) { mgConnectingCancel(NULL,NULL); } void mgAbortDownloadPatch(char *name, featom *atom) { patchAbortRequest = 1; mgConnectingCancel(NULL,NULL); } int authReceiveReply(sword status) { switch (status) { case StatusCommon_Success : if (mgQueryType==MG_WONLogin) { mgDisplayMessage(strGetString(strConnectedWon)); #if PUBLIC_BETA if (betaVerifying) { betaVerified = TRUE; betaVerifying = FALSE; betaDoneVerifying = TRUE; mgConnectingScreenGoto = MGS_Connection_Method; //mgBackToConnection(NULL,NULL); #if 0 LockMutex(changescreenmutex); newscreen = TRUE; screenaskedfor = MGS_Connection_Method; hideallscreens = TRUE; UnLockMutex(changescreenmutex); #endif } else #endif { cJoinADefaultRoom(); LoggedIn = TRUE; mgConnectingScreenGoto = MGS_Channel_Chat; } mgQueryType = -1; } else if (mgQueryType==MG_WONChangePassword) { mgDisplayMessage(strGetString(strPasswordChangeSuccess)); LockMutex(changescreenmutex); newscreen = TRUE; screenaskedfor = MGS_Internet_Login; hideallscreens = TRUE; UnLockMutex(changescreenmutex); mgQueryType = -1; } else if (mgQueryType==MG_WONNewUser) { mgDisplayMessage(strGetString(strNewUserCreated)); LockMutex(changescreenmutex); newscreen = TRUE; screenaskedfor = MGS_Internet_Login; hideallscreens = TRUE; UnLockMutex(changescreenmutex); mgQueryType = -1; } break; case StatusCommonFailureStart : mgDisplayMessage(strGetString(strLoginFailed)); mgDisplayMessage(strGetString(strHitCancelAgain)); return 0; case StatusAuth_ExpiredKey: mgDisplayMessage(strGetString(strBadKeyExpired)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_VerifyFailed: mgDisplayMessage(strGetString(strBadKey)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_LockedOut: mgDisplayMessage(strGetString(strBadKeyLockedOut)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_KeyInUse: mgDisplayMessage(strGetString(strKeyAlreadyInUse)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_CRCFailed: mgDisplayMessage(strGetString(strAuthCRCFailed)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_UserExists: mgDisplayMessage(strGetString(strDuplicateUser)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_UserNotFound: mgDisplayMessage(strGetString(strUserNotFound)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_BadPassword: mgDisplayMessage(strGetString(strIncorrectPassword)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; case StatusAuth_DirtyWord: case StatusAuth_InvalidName: mgDisplayMessage(strGetString(strInvalidName)); mgDisplayMessage(strGetString(strHitCancelAgain)); break; default: { char errmsg[200]; sprintf(errmsg,strGetString(strUnknownAuthReply),status); mgDisplayMessage(errmsg); return 0; } break; } return 1; } void titanPingReplyReceivedCB(Address *address,unsigned long theLag) { mgqueuenewping ping; if (LANGame) { return; // ping's not supported in LAN } LockQueue(&mgThreadTransfer); ping.header.packettype = MG_QUEUEPINGINFO; ping.ping.IP = GetIPFromInternetAddress(*address); ping.ping.Port = GetPortFromInternetAddress(*address); ping.ping.pingtime = theLag; Enqueue(&mgThreadTransfer, (ubyte *)&ping, sizeof(mgqueuenewping)); UnLockQueue(&mgThreadTransfer); } void mgGameListGameAdded(tpscenario *thegame) { mgqueuegamelistgame qgame; LockQueue(&mgThreadTransfer); qgame.header.packettype = MG_QUEUEGAMELISTGAMEADDED; qgame.game = *thegame; Enqueue(&mgThreadTransfer, (ubyte *)&qgame, sizeof(mgqueuegamelistgame)); UnLockQueue(&mgThreadTransfer); } void mgGameListGameRemoved(tpscenario *thegame) { mgqueuegamelistgame qgame; LockQueue(&mgThreadTransfer); qgame.header.packettype = MG_QUEUEGAMELISTGAMEREMOVED; qgame.game = *thegame; Enqueue(&mgThreadTransfer, (ubyte *)&qgame, sizeof(mgqueuegamelistgame)); UnLockQueue(&mgThreadTransfer); } void mgGameListGameChanged(tpscenario *thegame) { mgqueuegamelistgame qgame; LockQueue(&mgThreadTransfer); qgame.header.packettype = MG_QUEUEGAMELISTGAMECHANGED; qgame.game = *thegame; Enqueue(&mgThreadTransfer, (ubyte *)&qgame, sizeof(mgqueuegamelistgame)); UnLockQueue(&mgThreadTransfer); } void mgGameListNew(void) { mgqueuegamelistnew qnew; LockQueue(&mgThreadTransfer); qnew.header.packettype = MG_QUEUEGAMELISTNEW; Enqueue(&mgThreadTransfer, (ubyte *)&qnew, sizeof(mgqueuegamelistnew)); UnLockQueue(&mgThreadTransfer); } void mgFailedToConnectToChannel(bool existing) { mgDisplayMessage(strGetString(strFailedToChat)); mgDisplayMessage(strGetString(strHitCancelContinue)); mgConnectingScreenGoto = MGS_Channel_Chat; } #if 0 void titanGotNumUsersInRoomCB(const wchar_t *theRoomName, int theNumUsers) { mgqueuenumpeopleroominfo qnew; LockQueue(&mgThreadTransfer); qnew.header.packettype = MG_QUEUENUMPEOPLEROOM; wcscpy(qnew.channelname,theRoomName); qnew.numpeople = theNumUsers; Enqueue(&mgThreadTransfer, (ubyte *)&qnew, sizeof(mgqueuenumpeopleroominfo)); UnLockQueue(&mgThreadTransfer); } #endif void mgDisplayMsgBox(void) { LockMutex(changescreenmutex); newscreen = TRUE; screenaskedfor = MGS_Connecting; hideallscreens = TRUE; UnLockMutex(changescreenmutex); } void mgDisplayMessage(char *message) { mgqueuestatusline status; LockQueue(&mgThreadTransfer); status.header.packettype = MG_QUEUESTATUSINFO; strcpy(status.status.message, message); Enqueue(&mgThreadTransfer, (ubyte *)&status, sizeof(mgqueuestatusline)); UnLockQueue(&mgThreadTransfer); } void mgNotifyKickedOut(void) { mgqueuegeneral general; LockQueue(&mgThreadTransfer); general.packettype = MG_QUEUEKICKEDOUT; Enqueue(&mgThreadTransfer, (ubyte *)&general, sizeof(general)); UnLockQueue(&mgThreadTransfer); } void mgUpdateGameInfo(void) { mgqueuegameplayerinfo player; sdword i; LockQueue(&mgThreadTransfer); for (i=0;ipacketheader.frame; memStrncpy(chat.chat.chatstring,packet->message,MAX_CHATSTRING_LENGTH); mask = PLAYER_MASK(sigsPlayerIndex); mask &= packet->users; if (mask==packet->users) chat.chat.messagetype = MG_WHISPEREDCHAT; else chat.chat.messagetype = MG_NORMALCHAT; Enqueue(&mgThreadTransfer, (ubyte *)&chat, sizeof(mgqueuechatlist)); UnLockQueue(&mgThreadTransfer); } //Game Options setting code //goes through gametypes.script and sets game options based on gameName.script void mgSetGameType(char *gameName) { udword i; for(i=0;inumGameTypes;i++) { if(strcmp(preSetGames->gameType[i].gameName,gameName) == 0) { //set game flag mgSetGameTypeByNum(i); gameNum = i; //set all on screen options to appropriate states } } } /*----------------------------------------------------------------------------- Name : mgSetGameTypeByNum Description : Set the game settings to match a particular game type Inputs : i game type, corresponds to a button number Outputs : Return : ----------------------------------------------------------------------------*/ void mgSetGameTypeByNum(sdword i) { if ((i >= 0) && (i < preSetGames->numGameTypes)) { mgSetGameTypeByStruct(&preSetGames->gameType[i]); } } /*----------------------------------------------------------------------------- Name : mgSetGameTypeByStruct Description : Sets a game settings based on a game settings structure. Inputs : game - game settings. Flags member will be set according to the flagNeeded mask and all other members will be set if they are not 0xfffffff. Outputs : Return : ----------------------------------------------------------------------------*/ void mgSetGameTypeByStruct(GameType *game) { tpGameCreated.flag = (tpGameCreated.flag & (~game->flagNeeded)) | (game->flag & game->flagNeeded); if (game->startingFleet != 0xff) { tpGameCreated.startingFleet = game->startingFleet; } if (game->bountySize != 0xff) { tpGameCreated.bountySize = game->bountySize; } if (game->startingResources != 0xff) { tpGameCreated.startingResources = game->startingResources; } if (game->resourceInjectionInterval != 0xffffffff) { tpGameCreated.resourceInjectionInterval = game->resourceInjectionInterval; } if (game->resourceInjectionsAmount != 0xffffffff) { tpGameCreated.resourceInjectionsAmount = game->resourceInjectionsAmount; } if (game->resourceLumpSumTime != 0xffffffff) { tpGameCreated.resourceLumpSumTime = game->resourceLumpSumTime; } if (game->resourceLumpSumAmount != 0xffffffff) { tpGameCreated.resourceLumpSumAmount = game->resourceLumpSumAmount; } } void mgGameTypesOtherButtonPressed(void) { sdword i; GameType *game; game = preSetGames->gameType; for(i=0; i < preSetGames->numGameTypes; i++, game++) { if((tpGameCreated.flag & game->flagNeeded) == game->flag && //tpGameCreated.numComputers == game->numComputers && (game->startingFleet == 0xff || tpGameCreated.startingFleet == game->startingFleet) && (game->bountySize == 0xff || tpGameCreated.bountySize == game->bountySize) && (game->startingResources == 0xff || tpGameCreated.startingResources == game->startingResources) && (game->resourceInjectionInterval == 0xffffffff || tpGameCreated.resourceInjectionInterval == game->resourceInjectionInterval) && (game->resourceInjectionsAmount == 0xffffffff || tpGameCreated.resourceInjectionsAmount == game->resourceInjectionsAmount) && (game->resourceLumpSumTime == 0xffffffff || tpGameCreated.resourceLumpSumTime == game->resourceLumpSumTime) && (game->resourceLumpSumAmount == 0xffffffff || tpGameCreated.resourceLumpSumAmount == game->resourceLumpSumAmount)) { //game types are the same! feRadioButtonSet("MG_GameType", i); return; } } //no game type is the same! //so set the custom button which is numbered 1 above total predefined games feRadioButtonSet("MG_GameType", preSetGames->numGameTypes); gameNum = preSetGames->numGameTypes; } void mgNotifyDirRequestFailed() { mgDisplayMessage(strGetString(strFailedToConnectToDirServer)); } /*============================================================================= Choose Server stuff: =============================================================================*/ #define mgServerListTitleFont mgChannelListTitleFont #define mgServerListFont mgChannelListFont #define mgServerTitleColor mgChannelTitleColor #define mgServerTitleFlashColor mgTitleFlashColor #define mgServerListSelectedColor mgChannelListSelectedColor #define mgServerListNormalColor mgChannelListNormalColor void mgGoChooseServer(char *name, featom *atom) { serverlist *servlist; if (mgListOfServersWindow) { if (mgListOfServersWindow->CurLineSelected) { servlist = (serverlist *)mgListOfServersWindow->CurLineSelected->data; if (servlist) { mgReallyStartGame(servlist->addressstore); } } else { mgReallyStartGame(NULL); } } } void mgStartSpecificFactServerFailedCB(void) { mgDisplayMessage(strGetString(strFailedToStartRoutingServer)); mgDisplayMessage(strGetString(strHitCancelContinue)); } void mgCancelChooseServer(char *name, featom *atom) { mgShowScreen(lastScreen, TRUE); } void mgDrawTriangleServer(sdword x, color col) { triangle tri; if (!mgListOfServersWindow->sortOrder) { tri.x0 = -4 + x; tri.y0 = 4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; tri.x1 = 4 + x; tri.y1 = 4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; tri.x2 = 0 + x; tri.y2 = -4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; } else { tri.x0 = -4 + x; tri.y0 = -4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; tri.x1 = 0 + x; tri.y1 = 4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; tri.x2 = 4 + x; tri.y2 = -4 + mgListOfServersWindow->reg.rect.y0+MG_VertSpacing+4; } primTriSolid2(&tri, col); } void mgDrawListOfServersTitle(rectangle *rect) { sdword x, y; fonthandle oldfont; color flashcol; char *string; oldfont = fontMakeCurrent(mgServerListTitleFont); x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing; if (mgTitleFlashTimer + FLASH_TIMER > taskTimeElapsed) { bitSet(mgListOfServersWindow->windowflags,UICLW_JustRedrawTitle); #ifdef DEBUG_STOMP regVerify(&mgListOfServersWindow->reg); #endif mgListOfServersWindow->reg.status |= RSF_DrawThisFrame; flashcol = mgServerTitleFlashColor; } else flashcol = mgServerTitleColor; string = strGetString(strChannelNameHeading); if (mgListOfServersWindow->sorttype == MG_ServerSortByName) { fontPrint(x,y,flashcol,string); mgDrawTriangleServer(x+fontWidth(string), flashcol); } else fontPrint(x,y,mgServerTitleColor,string); x+= mgServerNameWidth; string = strGetString(strChannelDescHeading); if (mgListOfServersWindow->sorttype == MG_ServerSortByDescription) { fontPrint(x,y,flashcol,string); mgDrawTriangleServer(x+fontWidth(string), flashcol); } else fontPrint(x,y,mgServerTitleColor,string); x+= mgServerDescriptionWidth; string = strGetString(strGamePingHeading); if (mgListOfServersWindow->sorttype == MG_ServerSortByPing) { fontPrint(x,y,flashcol,string); mgDrawTriangleServer(x+fontWidth(string), flashcol); } else fontPrint(x,y,mgServerTitleColor,string); x+= mgServerPingWidth; string = strGetString(strServerLoadHeading); if (mgListOfServersWindow->sorttype == MG_ServerSortByLoad) { fontPrint(x,y,flashcol,string); mgDrawTriangleServer(x+fontWidth(string), flashcol); } else fontPrint(x,y,mgServerTitleColor,string); x+=mgServerLoadWidth; string = strGetString(strServerReliabilityHeading); if (mgListOfServersWindow->sorttype == MG_ServerSortByReliability) { fontPrint(x,y,flashcol,string); mgDrawTriangleServer(x+fontWidth(string), flashcol); } else fontPrint(x,y,mgServerTitleColor,string); x+=mgServerReliabilityWidth; fontMakeCurrent(oldfont); } // callback for sorting the server list window bool mgListOfServersCompare(void *firststruct,void *secondstruct) { sdword i; serverlist *one = (serverlist *)(((listitemhandle)firststruct)->data); serverlist *two = (serverlist *)(((listitemhandle)secondstruct)->data); switch (mgListOfServersWindow->sorttype) { case MG_ServerSortByName: if ((i=wcsicmp( one->ServerName,two->ServerName)) > 0) return (mgListOfServersWindow->sortOrder); else { if (i != 0) return (!mgListOfServersWindow->sortOrder); else return (FALSE); } case MG_ServerSortByDescription: if ((i=wcsicmp( one->ServerDescription,two->ServerDescription)) > 0) return (mgListOfServersWindow->sortOrder); else { if (i != 0) return (!mgListOfServersWindow->sortOrder); else return (FALSE); } case MG_ServerSortByPing: if (one->ping > two->ping) return (mgListOfServersWindow->sortOrder); else { if (one->ping != two->ping) return (!mgListOfServersWindow->sortOrder); else return (FALSE); } case MG_ServerSortByLoad: if (one->flags > two->flags) return (mgListOfServersWindow->sortOrder); else { if (one->flags != two->flags) return (!mgListOfServersWindow->sortOrder); else return (FALSE); } case MG_ServerSortByReliability: if (one->reliability > two->reliability) return (mgListOfServersWindow->sortOrder); else { if (one->reliability != two->reliability) return (!mgListOfServersWindow->sortOrder); else return (FALSE); } } return FALSE; } // callback if the title is clicked on void mgListOfServersTitleClick(struct tagRegion *reg, sdword xClicked) { sdword x = reg->rect.x0+mgServerNameWidth; if (mgListOfServersWindow->ListTotal==0) return; mgTitleFlashTimer = taskTimeElapsed; #ifdef DEBUG_STOMP regVerify(reg); #endif reg->status |= RSF_DrawThisFrame; if (xClicked < x) { if (mgListOfServersWindow->sorttype == MG_ServerSortByName) mgListOfServersWindow->sortOrder = !mgListOfServersWindow->sortOrder; else mgListOfServersWindow->sortOrder = TRUE; mgListOfServersWindow->sorttype = MG_ServerSortByName; uicListSort(mgListOfServersWindow,mgListOfServersCompare); return; } x+=mgServerDescriptionWidth; if (xClicked < x) { if (mgListOfServersWindow->sorttype == MG_ServerSortByDescription) mgListOfServersWindow->sortOrder = !mgListOfServersWindow->sortOrder; else mgListOfServersWindow->sortOrder = TRUE; mgListOfServersWindow->sorttype = MG_ServerSortByDescription; uicListSort(mgListOfServersWindow,mgListOfServersCompare); return; } x+=mgServerPingWidth; if (xClicked < x) { if (mgListOfServersWindow->sorttype == MG_ServerSortByPing) mgListOfServersWindow->sortOrder = !mgListOfServersWindow->sortOrder; else mgListOfServersWindow->sortOrder = TRUE; mgListOfServersWindow->sorttype = MG_ServerSortByPing; uicListSort(mgListOfServersWindow,mgListOfServersCompare); return; } x += mgServerLoadWidth; if (xClicked < x) { if (mgListOfServersWindow->sorttype == MG_ServerSortByLoad) mgListOfServersWindow->sortOrder = !mgListOfServersWindow->sortOrder; else mgListOfServersWindow->sortOrder = TRUE; mgListOfServersWindow->sorttype = MG_ServerSortByLoad; uicListSort(mgListOfServersWindow,mgListOfServersCompare); return; } else { if (mgListOfServersWindow->sorttype == MG_ServerSortByReliability) mgListOfServersWindow->sortOrder = !mgListOfServersWindow->sortOrder; else mgListOfServersWindow->sortOrder = TRUE; mgListOfServersWindow->sorttype = MG_ServerSortByReliability; uicListSort(mgListOfServersWindow,mgListOfServersCompare); return; } } void mgDrawListOfServersItem(rectangle *rect, listitemhandle data) { char temp[512]; sdword x, y; color c; fonthandle oldfont; serverlist *serverinfo = (serverlist *)data->data; oldfont = fontMakeCurrent(mgServerListFont); if (data->flags&UICLI_Selected) c = mgServerListSelectedColor; else c = mgServerListNormalColor; x = rect->x0+MG_HorzSpacing; y = rect->y0+MG_VertSpacing/2; wcstombs(temp,serverinfo->ServerName,512); fontPrint(x,y,c,temp); x += mgServerNameWidth; wcstombs(temp,serverinfo->ServerDescription,512); fontPrint(x,y,c,temp); x += mgServerDescriptionWidth; if (serverinfo->ping <= 0) sprintf(temp,"?"); else sprintf(temp,"%i",serverinfo->ping); fontPrint(x,y,c,temp); x+=mgServerPingWidth; sprintf(temp,"%i",serverinfo->flags); fontPrint(x,y,c,temp); x+=mgServerLoadWidth; sprintf(temp,"%i",serverinfo->reliability / 3600); fontPrint(x,y,c,temp); x+=mgServerReliabilityWidth; fontMakeCurrent(oldfont); } void mgListOfServersInit(char *name, featom *atom) { fonthandle oldfont; sdword titleheight, itemheight; Node *walk; if (FEFIRSTCALL(atom)) { oldfont = fontMakeCurrent(mgServerListTitleFont); titleheight = fontHeight(" ")*2; fontMakeCurrent(mgServerListFont); itemheight = fontHeight(" ")+MG_VertSpacing; mgListOfServersWindow = (listwindowhandle)atom->pData; uicListWindowInit(mgListOfServersWindow, mgDrawListOfServersTitle, // title draw, no title mgListOfServersTitleClick, // title click process titleheight, // title height, no title mgDrawListOfServersItem, // item draw funtcion itemheight, // item height UICLW_CanSelect); if (listofservers.num!=0) { walk = listofservers.head; while (walk!=NULL) { ((serverlist *)listGetStructOfNode(walk))->item = uicListAddItem(mgListOfServersWindow,(ubyte *)listGetStructOfNode(walk),UICLI_CanSelect,UICLW_AddToTail); walk = walk->next; } } refreshbaby = taskCallBackRegister(Refresh, 0, NULL, (real32)TITAN_PICKER_REFRESH_TIME); donerefreshing=FALSE; pingserversbaby = taskCallBackRegister(PingAllServers, 0, NULL, 1.0f); pingservernum = 0; fontMakeCurrent(oldfont); return; } if (FELASTCALL(atom)) { taskCallBackRemove(refreshbaby); donerefreshing = TRUE; taskCallBackRemove(pingserversbaby); pingserversbaby = NULL; mgListOfServersWindow = NULL; return; } else if (mgListOfServersWindow->message == CM_DoubleClick) { // add double click on server later add later } }