//=============================================================================// // Map Vote Mutator v0.5 Copyright(C) 2005 Adam Mummery-Smith B.S.E. // //=============================================================================// class MapVoteHUDPlugin extends UIHelper; //=============================================================================// // Class: MapVoteHUDPlugin | Date: December 2005 // //-----------------------------------------------------------------------------// // Project: Map Vote Mutator | Author: Adam Mummery-Smith // //-----------------------------------------------------------------------------// // Description: Since there is no UI functionality for map voting, this class // // is responsible for displaying the map vote message when // // necessary. It also displays a quick 'Message of the Day' to // // let players know how to start a map vote. // //-----------------------------------------------------------------------------// // Usage: An instance of this class is spawned by the Player // // Controller. // //-----------------------------------------------------------------------------// // Note: Integration with non-standard UIs may be poor. Not tested on // // all resolutions but tries to be as faithful to the player // // kick-voting screen as possible. // //=============================================================================// //----------------------------------------------------------------------------- // Declarations // Fonts var Font biggerfont, bigfont, medfont1, medfont2, smallfont, tinyfont; // Colours var Color white, grey, black, red, green, blue, yellow, cyan, semitrans; var Color teamColor[2]; // Local references to replicated game objects var LevelInfo Level; var MapVoteController myOwner; var bool registered; var int CanvasX, CanvasY; // Message of the day var struct MOTDLine { var() String Text; var() Color Colour; } MOTD[5]; var int MOTDDisplayTime; var byte MOTDAlpha; var bool MOTDReplicationDone; // Make a note of when we become registered - and use to decided how long to display the MOTD var float RegisteredTime; // To determine the vote key bindings we need to find a CodeMonkey. This variable keeps track of it. var CodeMonkey LocalCodeMonkey; // Vote key bindings, retrieved from the CodeMonkey var array VoteKeys; var string VoteYesKey, VoteNoKey; // Variables to help this plugin coexist with the RaptorRace HUD plugin var bool RRCheckVerify; var bool RREnabled; //----------------------------------------------------------------------------- // This function is called by owner to the tell the object to begin trying to register // itself as a render listener. simulated function Register(coerce LevelInfo theLevel, coerce Actor owner) { Level = theLevel; myOwner = MapVoteController(owner); Log("MapVote: Trying to register the HUD Plugin every 2 seconds"); AddTimer( 'TryToRegister', 2, True ); } //----------------------------------------------------------------------------- // This function tries to register the HUD plugin at pre-defined intervals and stops when // it detects that the plugin has been registered successfully simulated function TryToRegister() { local int i; if (!registered && GetUIConsole()?) { for (i = 0; i < GetUIConsole().Helpers.length; i++) { if (MapVoteHUDPlugin(GetUIConsole().Helpers[i])?) { Log("MapVote: HUD Plugin registration failed because an instance of the Plugin already exists in the UI"); registered = true; RemoveAllTimers(); return; } } Log ("MapVote: HUD Plugin is trying to register itself with the UI"); GetUIConsole().RegisterRenderListener(self, "DrawExtendedVoteHUD"); } else if (registered) { Log("MapVote: HUD Plugin registration failed because the Plugin is already registered"); RemoveAllTimers(); } else { Log("MapVote: HUD Plugin registration failed because the UI did not respond"); } } //----------------------------------------------------------------------------- simulated event Constructed() { registered = false; SaveConfig(); } //----------------------------------------------------------------------------- // Called by the owner to check whether registration has been successful simulated function bool CheckRegistered() { return registered; } //----------------------------------------------------------------------------- // This is the function which (once the plugin is registered) will perform the extra draw tasks required simulated interface function DrawExtendedVoteHUD( Canvas C ) { local int i, j, voteStyle; local float t; local Loader L; local MapVoteGameReplicationInfo MyGRI; // If this function is called, we know that registration is successful. So set the registered flag. if (!registered) { Log("MapVote: HUD Plugin is registered successfully"); RemoveAllTimers(); registered = true; if (Level?) RegisteredTime = Level.TimeSeconds; } // Calculate time since we were registered. Used to time out the MOTD and the RaptorRace check t = (Level.TimeSeconds - RegisteredTime); // Since the MOTD may clash with the RaptorRace MOTD, we will detect RaptorRace and then adjust the // MOTD accordingly. Here we search for loaders and if we find an eq2Loader, we know that RaptorRace // is running. if (myOwner? && !RRCheckVerify) { RREnabled = false; ForEach myOwner.AllActors(class 'Loader', L) { if (L.isA('eq2loader')) { RREnabled = true; RRCheckVerify = true; break; } } } // If we haven't found an eq2Loader after 30 seconds, give up looking if (t > 30) RRCheckVerify = true; // We can retrieve key bindings from the CodeMonkey. So let's grab ourselves a reference to it. // CodeMonkey will be alongside us in the UI Helpers array, so we search that. if (!LocalCodeMonkey?) { for (i = 0; i < GetUIConsole().Helpers.length; i++) { if (CodeMonkey(GetUIConsole().Helpers[i])?) { LocalCodeMonkey = CodeMonkey(GetUIConsole().Helpers[i]); } } } // Because I'm lazy and I think it looks neater CanvasX = C.ClipX; CanvasY = C.ClipY; if (myOwner? && Level?) { if (!MOTDReplicationDone && MapVoteGameReplicationInfo(myOwner.GameReplicationInfo)?) { MyGRI = MapVoteGameReplicationInfo(myOwner.GameReplicationInfo); // Load the MOTD data from the GRI MOTDDisplayTime = MyGRI.MOTDDisplayTime; MOTD[0].Text = MyGRI.MOTD1String; MOTD[0].Colour = MyGRI.MOTD1Colour; MOTD[1].Text = MyGRI.MOTD2String; MOTD[1].Colour = MyGRI.MOTD2Colour; MOTD[2].Text = MyGRI.MOTD3String; MOTD[2].Colour = MyGRI.MOTD3Colour; MOTD[3].Text = MyGRI.MOTD4String; MOTD[3].Colour = MyGRI.MOTD4Colour; MOTD[4].Text = MyGRI.MOTD5String; MOTD[4].Colour = MyGRI.MOTD5Colour; MOTDReplicationDone = true; } C.Style = 5; C.Font = BigFont; C.bCenter = True; // Draw the Message Of The Day (MOTD) for a pre-defined time if (MOTDAlpha > 0) { // Process the fade out after the allotted time if (t > MOTDDisplayTime) MOTDAlpha = 255 - ((t - MOTDDisplayTime) / 0.007843); if (MOTDAlpha < 10) MOTDAlpha = 0; for (i = 0; i < 5; i++) { // If RaptorRace is detected, adjust the MOTD so that the MOTDs don't clash if (RREnabled) { if (i == 1 && MOTD[i].Text == "www.teambse.co.uk") {i++; j=-17;} C.SetPos(0, 298 + (i*17) - j); } else { C.SetPos(0, 145 + (i*17)); } C.DrawColor = MOTD[i].Colour; C.DrawColor.A = MOTDAlpha; C.DrawText( MOTD[i].Text, True ); } } // If we should be displaying a poll, display a poll if (myOwner.ShowMapVotePoll()) { // Get the current keybindings assigned to VoteYes and VoteNo UpdateVoteKeys(); C.DrawColor = Green; C.DrawColor.A = 255; if (myOwner.voteStyle ~= "small") voteStyle = 1; else if (myOwner.voteStyle ~= "verysmall") voteStyle = 2; else voteStyle = 0; switch (voteStyle) { case 1: // Small map vote, similar to BF2's vote query C.bCenter = False; C.Font = SmallFont; C.SetPos(52, C.ClipY - 240); if (myOwner.VotedMapDeferred()) C.DrawText( StripColours(myOwner.GetPollOwner()) $ " wants to queue " $ myOwner.GetNominatedMapName() $ " as the next map", True ); else C.DrawText( StripColours(myOwner.GetPollOwner()) $ " has initiated a vote for map " $ myOwner.GetNominatedMapName(), True ); C.SetPos(52, C.ClipY - 224); C.DrawText( "Press [" $ VoteYesKey $ "] for yes.Press [" $ VoteNoKey $ "] for no.", True ); break; case 2: // Very, very small map vote C.bCenter = False; C.Font = SmallFont; C.SetPos(52, C.ClipY - 240); if (myOwner.VotedMapDeferred()) C.DrawText( "Queue map: " $ StripColours(myOwner.GetPollOwner()) $ ": " $ myOwner.GetNominatedMapName() $ " ?", True ); else C.DrawText( "Switch map: " $ StripColours(myOwner.GetPollOwner()) $ ": " $ myOwner.GetNominatedMapName() $ " ?", True ); C.SetPos(52, C.ClipY - 224); C.DrawText( "[" $ VoteYesKey $ "] for yes. [" $ VoteNoKey $ "] for no.", True ); break; case 0: // Normal map vote, like XMP's kick/ban vote default: C.SetPos(0, CanvasY/2 - 142); if (myOwner.VotedMapDeferred()) { C.DrawText( myOwner.GetNominatedMapName() $ " to be queued as the next map", True); C.SetPos(0, CanvasY/2 - 159); C.DrawText( StripColours(myOwner.GetPollOwner()) $ " has initiated a vote for ", True ); } else C.DrawText( StripColours(myOwner.GetPollOwner()) $ " has initiated a vote for map " $ myOwner.GetNominatedMapName(), True ); C.SetPos(0, CanvasY/2 - 120); C.DrawText( "Press [" $ VoteYesKey $ "] for yes.Press [" $ VoteNoKey $ "] for no.", True ); } } // if (myOwner.GUIEditMode()) // { // myOwner.DrawGUIOverlays(C, self); // } // The Map Vote GUI is drawn by the PlayerController itself. When necessary, call the // function to display the GUI. if (myOwner.DisplayMapSelectionGUI()) { myOwner.DrawVoteUI(C, self); } // This is necessary because the last thing drawn by a HUD plugin always seems to have a higher // DrawOrder than the menu system. So we draw a transparent space. C.DrawColor.A = 0; C.SetPos(10, CanvasY - 10); C.DrawText(" ", True ); } else { Log("MapVote: Plugin registered but no owner :("); } } //----------------------------------------------------------------------------- // Queries the Local CodeMonkey and gets the key assignments of the VoteYes and VoteNo commands function UpdateVoteKeys() { local int i; if (LocalCodeMonkey?) { VoteYesKey = ""; VoteNoKey = ""; VoteKeys = LocalCodeMonkey.GetKeys("voteyes"); for (i = 0; i < VoteKeys.Length; i++) { if (VoteYesKey != "") VoteYesKey = VoteYesKey $ "/"; VoteYesKey = VoteYesKey $ VoteKeys[i]; } VoteKeys = LocalCodeMonkey.GetKeys("voteno"); for (i = 0; i < VoteKeys.Length; i++) { if (VoteNoKey != "") VoteNoKey = VoteNoKey $ "/"; VoteNoKey = VoteNoKey $ VoteKeys[i]; } } } //----------------------------------------------------------------------------- // Take the colour codes ("^#.") out of a name string. From the XMPSummoner mut. static function string StripColours(string S) { local int i; local bool bReplaced; do { bReplaced = False; for (i = 0; i < Len(S); i++) { if (Mid(S, i, 2) ~= "^#") { S = Left(S, i) $ Right(S, Len(S) - i - 3); bReplaced = True; } } } until (!bReplaced); return S; } defaultproperties { biggerfont=Font'SubTFonts.EE18' bigfont=Font'SubTFonts.EE16' medfont1=Font'HUD_Fonts.Micro10' medfont2=Font'HUD_Fonts.Micro12' SmallFont=Font'HUD_Fonts.EuroExt14' TinyFont=Font'Engine.SmallFont' White=(B=255,G=255,R=255,A=255) grey=(B=150,G=150,R=150,A=255) Black=(A=255) Red=(R=255,A=255) Green=(G=255,A=255) Blue=(B=255,A=255) Yellow=(G=255,R=255,A=255) Cyan=(B=255,G=255,A=255) semitrans=(B=255,G=255,R=255,A=160) TeamColor(0)=(R=255,A=255) TeamColor(1)=(B=255,A=255) CanvasX=640 CanvasY=480 MOTDDisplayTime=0 MOTDAlpha=255 }