├── README.md ├── MAPINFO.txt ├── .gitattributes ├── .editorconfig ├── TEXTURES.txt ├── LICENSE ├── ZScript ├── misc.txt ├── ucm_waypoints.zsc ├── ucm_math.zsc ├── ucm_interactivity.zsc └── ucm_minimap.zsc ├── ZSCRIPT.txt ├── KEYCONF.txt ├── CVARINFO.txt └── MENUDEF.txt /README.md: -------------------------------------------------------------------------------- 1 | # UltimateClassicMinimap 2 | A featureful Minimap mod for GZDoom. 3 | -------------------------------------------------------------------------------- /MAPINFO.txt: -------------------------------------------------------------------------------- 1 | GameInfo 2 | { 3 | AddEventHandlers = "UCMinimap_EventHandler", "UCMinimap_StaticHandler" 4 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | *.zsc linguist-language=C# -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # 4 space indentation 7 | [*.{zsc,cfg}] 8 | indent_style = tab 9 | indent_size = 4 -------------------------------------------------------------------------------- /TEXTURES.txt: -------------------------------------------------------------------------------- 1 | // Texture definitions generated by SLADE3 2 | // on Wed Oct 7 23:51:57 2020 3 | 4 | Sprite "SWTIND", 32, 32 5 | { 6 | XScale 2.000 7 | YScale 2.000 8 | Offset 15, 24 9 | Patch "SW1S0", 0, 0 10 | } 11 | 12 | Texture "RSWTIND", 32, 32 13 | { 14 | XScale 2.000 15 | YScale 2.000 16 | Offset 16, 24 17 | Patch "SW1S1", 0, 1 18 | } 19 | 20 | Texture "PXL", 8, 8 21 | { 22 | XScale 2.000 23 | YScale 2.000 24 | Patch "ARTIBOX", 0, 0 25 | } 26 | 27 | Texture "INDPXL", 16, 16 28 | { 29 | XScale 2.500 30 | YScale 2.500 31 | Offset 10, 14 32 | Patch "ARTIBOX", 0, 0 33 | } 34 | 35 | Texture "BLANK", 16, 16 36 | { 37 | XScale 0.100 38 | YScale 0.100 39 | Patch "ARTIBOX", 0, 0 40 | } 41 | 42 | // End of texture definitions 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Lewisk3 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ZScript/misc.txt: -------------------------------------------------------------------------------- 1 | /* 2 | // Stuff that doesn't work but, may in the future. 3 | switch(ln.locknumber) 4 | { 5 | // Red 6 | case 1: 7 | case 4: 8 | case 129: 9 | case 132: 10 | drawcol = 0xFFFF0000; 11 | break; 12 | // Yellow 13 | case 2: 14 | case 6: 15 | case 131: 16 | case 134: 17 | drawcol = 0xFFFFFF00; 18 | break; 19 | // Blue 20 | case 2: 21 | case 5: 22 | case 130: 23 | case 133: 24 | drawcol = 0xFF0000FF; 25 | break; 26 | default: 27 | drawcol = ( 28 | (ln.flags & Line.ML_BLOCKING) ? solid_linecol : 29 | actionable ? acton_linecol : linecol 30 | ); 31 | break; 32 | } 33 | int SWITCH_ACTIONS[110] = 34 | { 35 | 29,103,112,111,50,113,175,61,115,114,63,116,42,196,133,135,137,136, 36 | 134,99,159,18,131,23,101,221,55,241,71,161,160,102,140,158,189,78, 37 | 45,65,222,64,177,60,69,132,179,180,70,178,176,190166,167,203,204, 38 | 187,43,186,205,206,14,15,20,162,163,21,122,181,68,66,67,62,182,123, 39 | 211,49,164,165,168,183,184,185,188,7,127,258,259,229,233,237,234,230, 40 | 238,170,171,169,173,172,192,139,138,194,193,11,51,174,209,195,210,9, 41 | 191 42 | }; 43 | */ -------------------------------------------------------------------------------- /ZSCRIPT.txt: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2020 Lewisk3 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | version "4.0" 25 | 26 | #include "ZScript/ucm_waypoints.zsc" 27 | #include "ZScript/ucm_minimap.zsc" 28 | #include "ZScript/ucm_math.zsc" 29 | #include "ZScript/ucm_interactivity.zsc" -------------------------------------------------------------------------------- /ZScript/ucm_waypoints.zsc: -------------------------------------------------------------------------------- 1 | // Waypoints 2 | class WaypointObject : Object 3 | { 4 | String nickname; 5 | Color col; 6 | vector2 pos; 7 | 8 | static WaypointObject Init(String nickname, Color col, vector2 pos) 9 | { 10 | let wp = new("WaypointObject"); 11 | if(wp) 12 | { 13 | wp.nickname = nickname; 14 | wp.col = col; 15 | wp.pos = pos; 16 | } 17 | return wp; 18 | } 19 | } 20 | class I_WaypointStorage : Inventory 21 | { 22 | Array waypoints; 23 | Default 24 | { 25 | inventory.maxamount 1; 26 | +INVENTORY.UNDROPPABLE 27 | +INVENTORY.UNTOSSABLE 28 | } 29 | 30 | void AddWaypoint(String nickname, Color col, vector2 pos) 31 | { 32 | let wp = WaypointObject.Init(nickname,col,pos); 33 | if(wp) waypoints.Push(wp); 34 | } 35 | 36 | void RemoveNamedWaypoint(String nickname) 37 | { 38 | for(int i = 0; i < waypoints.Size(); i++) 39 | { 40 | if(nickname == waypoints[i].nickname) 41 | { 42 | waypoints.Delete(i); 43 | break; 44 | } 45 | } 46 | } 47 | void RemoveCloseWaypoint(vector2 pos) 48 | { 49 | for(int i = 0; i < waypoints.Size(); i++) 50 | { 51 | if( (waypoints[i].pos - pos).Length() < 64 ) 52 | { 53 | waypoints.Delete(i); 54 | break; 55 | } 56 | } 57 | } 58 | clearscope WaypointObject FindNamedWaypoint(String nickname) 59 | { 60 | for(int i = 0; i < waypoints.Size(); i++) 61 | if(nickname == waypoints[i].nickname) return waypoints[i]; 62 | return NULL; 63 | } 64 | } -------------------------------------------------------------------------------- /KEYCONF.txt: -------------------------------------------------------------------------------- 1 | alias +UCM_ZOOMIN "netevent \"+ucm.zoom.in\"" 2 | alias +UCM_ZOOMOUT "netevent \"+ucm.zoom.out\"" 3 | alias +UCM_PANUP "netevent \"+ucm.pan.up\"" 4 | alias +UCM_PANDOWN "netevent \"+ucm.pan.down\"" 5 | alias +UCM_PANLEFT "netevent \"+ucm.pan.left\"" 6 | alias +UCM_PANRIGHT "netevent \"+ucm.pan.right\"" 7 | alias -UCM_ZOOMIN "netevent \"-ucm.zoom.in\"" 8 | alias -UCM_ZOOMOUT "netevent \"-ucm.zoom.out\"" 9 | alias -UCM_PANUP "netevent \"-ucm.pan.up\"" 10 | alias -UCM_PANDOWN "netevent \"-ucm.pan.down\"" 11 | alias -UCM_PANLEFT "netevent \"-ucm.pan.left\"" 12 | alias -UCM_PANRIGHT "netevent \"-ucm.pan.right\"" 13 | alias UCM_TOGGLEALL "netevent \"ucm.toggleall\"" 14 | alias UCM_WAYPOINTS "netevent \"ucm.waypointmenu.open\"" 15 | alias UCM_TOGGLEMAP "netevent \"ucm.togglemap\"" 16 | alias UCM_TOGGLEFULLSCREEN "netevent \"ucm.togglefullscreen\"" 17 | alias UCM_TOGGLEFULLSIZE "netevent \"ucm.togglemaxsize\"" 18 | alias UCM_TOGGLEFOLLOW "netevent \"ucm.togglefollow\"" 19 | 20 | 21 | addkeysection "Minimap Controls" UCMControls 22 | addmenukey "Toggle" UCM_TOGGLEALL 23 | addmenukey "Zoom In" +UCM_ZOOMIN 24 | addmenukey "Zoom Out" +UCM_ZOOMOUT 25 | addmenukey "Waypoints" UCM_WAYPOINTS 26 | addmenukey "Toggle Map" UCM_TOGGLEMAP 27 | addmenukey "Toggle Fullscreen" UCM_TOGGLEFULLSCREEN 28 | addmenukey "Toggle Fullsize" UCM_TOGGLEFULLSIZE 29 | addmenukey "Toggle Following" UCM_TOGGLEFOLLOW 30 | addmenukey "Pan Up" +UCM_PANUP 31 | addmenukey "Pan Down" +UCM_PANDOWN 32 | addmenukey "Pan Left" +UCM_PANLEFT 33 | addmenukey "Pan Right" +UCM_PANRIGHT -------------------------------------------------------------------------------- /CVARINFO.txt: -------------------------------------------------------------------------------- 1 | user bool ucm_showrepeatable = true; 2 | user bool ucm_showdistance = true; 3 | user bool ucm_hide = false; 4 | user bool ucm_mustuse = true; 5 | user bool ucm_drawmap = true; 6 | user bool ucm_drawplayer = true; 7 | user bool ucm_drawrotation = true; 8 | user bool ucm_mapfollow = true; 9 | user bool ucm_drawcompass = true; 10 | user bool ucm_drawmissiles = true; 11 | user bool ucm_hidemonsters = false; 12 | user bool ucm_drawhealthbars = true; 13 | user bool ucm_markstartexit = true; 14 | user bool ucm_drawkeys = true; 15 | user int ucm_drawitems = 1; 16 | user int ucm_maprenderdist = 8192; 17 | user int ucm_specific = 0; 18 | user int ucm_maxswitchdist = 30; 19 | user int ucm_xoffset = -1; 20 | user int ucm_yoffset = -1; 21 | user int ucm_map_playtime = 0; 22 | user int ucm_map_deaths = 0; 23 | user float ucm_radarzoom = 3; 24 | user float ucm_radardist = 256; 25 | user float ucm_mapsize = 170; 26 | 27 | // Map colors 28 | user color ucm_color_normal = "B47446"; 29 | user color ucm_color_solid = "D90000"; 30 | user color ucm_color_action = "CDCE00"; 31 | user color ucm_color_border = "760000"; 32 | user color ucm_color_backg = "000000"; 33 | user color ucm_color_compas = "1614D3"; 34 | user color ucm_color_stats = "1614D3"; 35 | user float ucm_color_lum = 1.0; 36 | user float ucm_color_alpha = 1.0; 37 | user float ucm_color_backgalpha = 1.0; 38 | 39 | // Temporary 40 | noarchive user bool ucm_mapshowall = false; 41 | noarchive user bool ucm_drawmaxsize = false; 42 | noarchive user bool ucm_drawfullscreen = false; 43 | noarchive user string waypoint_name = "Waypoint"; 44 | noarchive user color waypoint_color = "00FF00"; -------------------------------------------------------------------------------- /ZScript/ucm_math.zsc: -------------------------------------------------------------------------------- 1 | extend class UCMinimap_EventHandler 2 | { 3 | // Math Util 4 | clearscope float VDist2D(Vector2 one, Vector2 two) 5 | { 6 | return (one-two).Length(); 7 | } 8 | clearscope double Lerp(double a, double b, double lerpFactor) 9 | { 10 | if(lerpFactor < 0 || lerpFactor > 1.) lerpFactor = 1.; 11 | double result = ((1. - lerpFactor) * a) + (lerpFactor * b); 12 | return result; 13 | } 14 | clearscope vector2 SwapVector(vector2 vec) 15 | { 16 | double oldx = vec.x; 17 | vec.x = vec.y; 18 | vec.y = oldx; 19 | return vec; 20 | } 21 | clearscope vector2, double clamp_vec(vector2 dest, vector2 origin, double dist) 22 | { 23 | double fulldist = VDist2D(dest, origin); 24 | if(fulldist > dist) 25 | { 26 | double vecangle = atan2(origin.y-dest.y, origin.x-dest.x); 27 | return ( (origin.x-cos(vecangle)*dist), (origin.y-sin(vecangle)*dist) ), fulldist; 28 | } 29 | return dest, fulldist; 30 | } 31 | // Draw Util 32 | ui void plotPixel (int x0, int y0, Color col = Color(0,0,0), vector2 scale = (0.5,0.5), double alpha = 1.0, uint RenderStyle = STYLE_Translucent) 33 | { 34 | if(pix) 35 | { 36 | vector2 texsize; 37 | [texsize.x, texsize.y] = TexMan.GetSize(curpix); 38 | Screen.DrawTexture(curpix,true,x0,y0, 39 | DTA_DestWidth, int(texsize.x*scale.x), 40 | DTA_DestHeight, int(texsize.y*scale.y), 41 | DTA_Alpha, alpha*0.7, 42 | DTA_ColorOverlay, col, 43 | DTA_LegacyRenderStyle, RenderStyle 44 | ); 45 | } 46 | } 47 | ui void drawLine( double x0, double y0, double x1, double y1, Color col, vector2 origin = (0,0), double maxdist = 128, double alpha = 1.0) 48 | { 49 | if( (x0 < 0 && x1 < 0) || 50 | (y0 < 0 && y1 < 0) || 51 | (x0 > scrw && x1 > scrw) || 52 | (y0 > scrh && y1 > scrh) ) return; 53 | 54 | if(maxdist < scrw) 55 | { 56 | double fromdist = VDist2D((x0,y0), origin); 57 | double todist = VDist2D((x1,y1), origin); 58 | if( (fromdist > maxdist || todist > maxdist) ) 59 | { 60 | if(fromdist > maxdist*1.2 && todist > maxdist*1.2) return; 61 | double lineangle = atan2(y1-y0, x1-x0); 62 | double dist = VDist2D((x0,y0),(x1,y1)); 63 | double step = 1; 64 | for(int i = 0; i < dist; i+=step) 65 | { 66 | vector2 pixpos = (x0+cos(lineangle)*i, y0+sin(lineangle)*i); 67 | double fulldist = VDist2D(pixpos, origin); 68 | if(fulldist > maxdist) continue; 69 | plotPixel(pixpos.x,pixpos.y, col, (0.5,0.5), alpha); 70 | } 71 | return; 72 | } 73 | } 74 | Screen.DrawThickLine(x0,y0,x1,y1,2,col,alpha*255); 75 | } 76 | ui void drawCircle(double x0, double y0, double radius=500, Color col=Color(0,0,0), double alpha = 1.0) 77 | { 78 | double step = 1.0 / (radius/100); 79 | for(double i = 0; i < 360; i+=step) 80 | { 81 | double xpos = x0+(cos(i)*radius); 82 | double ypos = y0+(sin(i)*radius); 83 | plotPixel(xpos,ypos,col, alpha:alpha); 84 | } 85 | } 86 | ui void FillCircle(double x0, double y0, double radius, Color col=Color(0xFF,0,0,0), double alpha=1.0, double points=60) 87 | { 88 | int angfrac = ceil(360/points); 89 | if(!bg_circle) 90 | { 91 | Shape2D circle = new("Shape2D"); 92 | circle.PushCoord((0,0)); // Middle 93 | for(double i = 0; i <= points; i++) circle.PushCoord((cos(angfrac*i),sin(angfrac*i))); 94 | for(double i = 1; i <= points; i++) circle.PushTriangle(i,i+1,0); 95 | bg_circle = circle; 96 | } 97 | bg_circle.Clear(Shape2D.C_Verts); 98 | bg_circle.PushVertex((x0,y0)); // Middle 99 | for(double i = 0; i <= points; i++) bg_circle.PushVertex((x0+cos(angfrac*i)*radius,y0+sin(angfrac*i)*radius)); 100 | Screen.DrawShape(TexMan.CheckForTexture("BLANK", TexMan.Type_Any), false, bg_circle, DTA_ColorOverlay, col, DTA_Alpha, alpha); 101 | } 102 | ui void DrawScaledString( Font fnt, String str, Vector2 pos, Color tint = Color(0,0,0,0), 103 | Vector2 scale = (1, 1), double Alpha = 1., 104 | int translation = Font.CR_UNTRANSLATED, int linespacing = 20 ) 105 | { 106 | Array lines; 107 | str.Split(lines, "\n"); 108 | 109 | pos.x *= 1./(scale.x*0.5); 110 | pos.y *= 1./(scale.y*0.5); 111 | 112 | for(int i = 0; i < lines.Size(); i++) 113 | { 114 | float lineoffs = (linespacing*i); 115 | Screen.DrawText(fnt, translation, pos.x, pos.y+lineoffs, 116 | lines[i], 117 | DTA_VirtualWidthF, int(1920.*(1./scale.x*0.5)), 118 | DTA_VirtualHeightF, int(1080.*(1./scale.y*0.5)), 119 | DTA_KeepRatio, true, 120 | DTA_Alpha, alpha, 121 | DTA_ColorOverlay, tint 122 | ); 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /ZScript/ucm_interactivity.zsc: -------------------------------------------------------------------------------- 1 | extend class UCMinimap_EventHandler 2 | { 3 | override bool InputProcess(InputEvent e) 4 | { 5 | if(waypointmenu_forceopen) 6 | { 7 | Menu.SetMenu("UCMWaypoints"); 8 | SendNetworkEvent("ucm.waypointmenu.done"); 9 | } 10 | return false; 11 | } 12 | 13 | // Buttons 14 | override void NetworkProcess(ConsoleEvent e) 15 | { 16 | PlayerInfo plr = players[e.Player]; 17 | if(!plr) return; 18 | 19 | // Waypoint triggers 20 | if(e.Name == "ucm.waypointmenu.open" ) 21 | { 22 | waypointmenu_forceclose = false; 23 | waypointmenu_forceopen = true; 24 | } 25 | if(e.Name == "ucm.waypointmenu.done" ) 26 | { 27 | waypointmenu_forceclose = false; 28 | waypointmenu_forceopen = false; 29 | } 30 | if(e.Name == "ucm.waypointmenu.apply") 31 | { 32 | // Add waypoint to player data 33 | let wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 34 | if(!wp_data) 35 | { 36 | plr.mo.GiveInventory("I_WaypointStorage", 1); 37 | wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 38 | } 39 | if(wp_data) 40 | { 41 | wp_data.AddWayPoint( 42 | wp_name.getString(), 43 | (0xFF<<24)+wp_color.getInt(), 44 | plr.mo.pos.xy 45 | ); 46 | } 47 | waypointmenu_forceclose = true; 48 | } 49 | if(e.Name == "ucm.waypointmenu.delete.byname") 50 | { 51 | // Add waypoint to player data 52 | let wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 53 | if(!wp_data) return; 54 | wp_data.RemoveNamedWaypoint(wp_name.getString()); 55 | waypointmenu_forceclose = true; 56 | } 57 | if(e.Name == "ucm.waypointmenu.delete.closest") 58 | { 59 | // Add waypoint to player data 60 | let wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 61 | if(!wp_data) return; 62 | wp_data.RemoveCloseWaypoint(plr.mo.pos.xy); 63 | waypointmenu_forceclose = true; 64 | } 65 | 66 | // Map controls 67 | if(e.Name == "+ucm.zoom.in" ) mapbtns |= MBT_ZOOMIN; 68 | if(e.Name == "+ucm.zoom.out" ) mapbtns |= MBT_ZOOMOUT; 69 | if(e.Name == "+ucm.pan.up" ) mapbtns |= MBT_UP; 70 | if(e.Name == "+ucm.pan.down" ) mapbtns |= MBT_DOWN; 71 | if(e.Name == "+ucm.pan.left" ) mapbtns |= MBT_LEFT; 72 | if(e.Name == "+ucm.pan.right") mapbtns |= MBT_RIGHT; 73 | if(e.Name == "-ucm.zoom.in" ) mapbtns &= ~MBT_ZOOMIN; 74 | if(e.Name == "-ucm.zoom.out" ) mapbtns &= ~MBT_ZOOMOUT; 75 | if(e.Name == "-ucm.pan.up" ) mapbtns &= ~MBT_UP; 76 | if(e.Name == "-ucm.pan.down" ) mapbtns &= ~MBT_DOWN; 77 | if(e.Name == "-ucm.pan.left" ) mapbtns &= ~MBT_LEFT; 78 | if(e.Name == "-ucm.pan.right") mapbtns &= ~MBT_RIGHT; 79 | 80 | // Other buttons 81 | if(e.Name == "ucm.switches.apply") FindSwitches(); 82 | 83 | if(e.Name == "ucm.toggleall") cv_hidden.setBool( !cv_hidden.getBool() ); 84 | if(e.Name == "ucm.togglemap") cv_drawmap.setBool(!cv_drawmap.getBool()); 85 | if(e.Name == "ucm.togglefollow") cv_mapfollow.SetBool(!cv_mapfollow.getBool()); 86 | if(e.Name == "ucm.togglefullscreen") cv_fullmapsize.setBool(!cv_fullmapsize.getBool()); 87 | if(e.Name == "ucm.togglemaxsize") cv_maxmapsize.setBool(!cv_maxmapsize.getBool()); 88 | 89 | if(e.Name == "ucm.resetcolors") 90 | { 91 | cv_color_normal.SetInt(0xB47446); 92 | cv_color_solid.SetInt(0xD90000); 93 | cv_color_action.SetInt(0xCDCE00); 94 | cv_color_border.SetInt(0x760000); 95 | cv_color_backg.SetInt(0x000000); 96 | cv_color_compass.SetInt(0x1614D3); 97 | cv_color_stats.SetInt(0x1614D3); 98 | } 99 | 100 | if(e.Name == "align.upperleft") 101 | { 102 | cv_xoffset.setInt(50); 103 | cv_yoffset.setInt(50); 104 | } 105 | if(e.Name == "align.upperright") 106 | { 107 | double faroffs = (300*(cv_mapsize.GetInt()/128.)); 108 | cv_xoffset.setInt(Screen.GetWidth()-faroffs); 109 | cv_yoffset.setInt(50); 110 | } 111 | if(e.Name == "align.lowerleft") 112 | { 113 | double faroffs = (300*(cv_mapsize.GetInt()/128.)); 114 | cv_xoffset.setInt(50); 115 | cv_yoffset.setInt(Screen.GetHeight()-faroffs); 116 | } 117 | if(e.Name == "align.lowerright") 118 | { 119 | double faroffs = (300*(cv_mapsize.GetInt()/128.)); 120 | cv_xoffset.setInt(Screen.GetWidth()-faroffs); 121 | cv_yoffset.setInt(Screen.GetHeight()-faroffs); 122 | } 123 | 124 | // Argument based commands 125 | string fullcmd = e.Name; 126 | Array cmds; 127 | fullcmd.Split(cmds,":"); 128 | if(cmds[0] == "ucm.waypoint.create") 129 | { 130 | vector2 pos = (cmds[1].ToInt(), cmds[2].ToInt()); 131 | string label = cmds[3]; 132 | Color col = cmds[4].ToInt(16); 133 | 134 | // Add waypoint to player data 135 | let wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 136 | if(!wp_data) 137 | { 138 | plr.mo.GiveInventory("I_WaypointStorage", 1); 139 | wp_data = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 140 | } 141 | if(wp_data) wp_data.AddWayPoint(label,col,pos); 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /MENUDEF.txt: -------------------------------------------------------------------------------- 1 | 2 | AddOptionMenu "OptionsMenu" 3 | { 4 | StaticText " " 5 | Submenu "UCMinimap Options", "UCMOptions" 6 | } 7 | 8 | 9 | OptionMenu "UCMOptions" 10 | { 11 | Title "UCMinimap HUD Options" 12 | SubMenu "Controls", "UCMControls" 13 | SubMenu "Switch Options", "UCMOptions_Switches" 14 | StaticText " " 15 | StaticText "General", "Gold" 16 | Option "Enabled", "ucm_hide", "NoOrYes" 17 | Option "Draw Compass", "ucm_drawcompass", "YesOrNo" 18 | Option "Draw Player", "ucm_drawplayer", "YesOrNo" 19 | StaticText " " 20 | Slider "X Position", "ucm_xoffset", -30, 9999, 1, 0 21 | Slider "Y Position", "ucm_yoffset", -30, 9999, 1, 0 22 | SubMenu "Map Alignment", "UCMOptions_Alignment" 23 | StaticText " " 24 | Slider "Size", "ucm_mapsize", 32, 512, 1, 0 25 | Option "Fullscreen", "ucm_drawfullscreen", "YesOrNo" 26 | StaticText " " 27 | StaticText "Radar", "Gold" 28 | Option "Press to Disable", "ucm_radardist", "RadarDisable" 29 | Slider "Radar Zoom", "ucm_radarzoom", 1, 100, 1, 0 30 | Slider "Radar range", "ucm_radardist", 0, 500, 1, 0 31 | StaticText "Maximum distance to display actors, 0 disables.","Black" 32 | Option "Draw Items", "ucm_drawitems", "DrawItems" 33 | Option "Draw Projectiles", "ucm_drawmissiles", "YesOrNo" 34 | Option "Draw Enemy Healthbars", "ucm_drawhealthbars", "YesOrNo" 35 | Option "Draw Keys", "ucm_drawkeys", "YesOrNo" 36 | Option "Hide Enemy Types", "ucm_hidemonsters", "YesOrNo" 37 | StaticText " " 38 | StaticText "Minimap", "Gold" 39 | Option "Enabled", "ucm_drawmap", "YesOrNo" 40 | Option "Rotate with Player", "ucm_drawrotation", "YesOrNo" 41 | Slider "Minimap Render Distance", "ucm_maprenderdist", 128, 8192, 1, 0 42 | SubMenu "Map Colors", "UCMOptions_Colors" 43 | StaticText " " 44 | StaticText "Waypoint Options", "Gold" 45 | Option "Mark Map \"Start\" and \"Exit\"", "ucm_markstartexit", "YesOrNo" 46 | StaticText " " 47 | } 48 | 49 | OptionMenu "UCMOptions_Alignment" 50 | { 51 | Title "UCMinimap HUD Options -> Map Positioning" 52 | StaticText " " 53 | Command "Top Left", "netevent \"align.upperleft\"" 54 | Command "Top Right", "netevent \"align.upperright\"" 55 | Command "Bottom Left", "netevent \"align.lowerleft\"" 56 | Command "Bottom Right", "netevent \"align.lowerright\"" 57 | } 58 | 59 | OptionMenu "UCMOptions_Colors" 60 | { 61 | Title "UCMinimap HUD Options -> Map Colors" 62 | StaticText " " 63 | ColorPicker "Normal Line", "ucm_color_normal" 64 | ColorPicker "Solid Line", "ucm_color_solid" 65 | ColorPicker "Actionable Line", "ucm_color_action" 66 | ColorPicker "Map Border", "ucm_color_border" 67 | ColorPicker "Background", "ucm_color_backg" 68 | ColorPicker "Compass", "ucm_color_compas" 69 | ColorPicker "Level Stats", "ucm_color_stats" 70 | StaticText " " 71 | Slider "Map Opacity", "ucm_color_alpha", 0, 1.0, 0.01, 2 72 | Slider "Background Opacity", "ucm_color_backgalpha", 0, 1.0, 0.01, 2 73 | StaticText " " 74 | Command "Reset Colors", "netevent ucm.resetcolors" 75 | } 76 | 77 | OptionMenu "UCMOptions_Switches" 78 | { 79 | Title "UCMinimap HUD Options -> Switches" 80 | StaticText " " 81 | Slider "Switch range", "ucm_maxswitchdist", 0, 500, 1, 0 82 | StaticText "Maximum distance to display switches, 0 disables.","Black" 83 | StaticText " " 84 | Option "Only show switches with", "ucm_specific", "SpecialAction" 85 | Slider "Only show switches with", "ucm_specific", 0, 280, 1, 0 86 | StaticText " " 87 | Option "Switch must be useable", "ucm_mustuse", "YesOrNo" 88 | Option "Draw repeatable switches", "ucm_showrepeatable", "YesOrNo" 89 | Option "Draw distance to switches", "ucm_showdistance", "YesOrNo" 90 | StaticText " " 91 | Command "Apply", "netevent \"ucm.switches.apply\"" 92 | } 93 | 94 | OptionMenu "UCMWaypoints" 95 | { 96 | Title "Customize Waypoint" 97 | StaticText " " 98 | TextField "Name", "waypoint_name" 99 | ColorPicker "Color", "waypoint_color" 100 | Command "Create", "netevent \"ucm.waypointmenu.apply\"" 101 | StaticText " " 102 | Command "Delete Closest", "netevent \"ucm.waypointmenu.delete.closest\"" 103 | Command "Delete (By Name)", "netevent \"ucm.waypointmenu.delete.byname\"" 104 | StaticText " " 105 | Command "Cancel", "closemenu UCMWaypoints" 106 | } 107 | 108 | OptionMenu "UCMControls" 109 | { 110 | Title "UCMinimap Controls" 111 | StaticText "General" 112 | Control "Toggle", "UCM_TOGGLEALL" 113 | StaticText " " 114 | StaticText "Radar controls" 115 | Control "Zoom In", "+UCM_ZOOMIN" 116 | Control "Zoom Out", "+UCM_ZOOMOUT" 117 | StaticText " " 118 | StaticText "Map controls" 119 | Control "Waypoints", "UCM_WAYPOINTS" 120 | Control "Toggle", "UCM_TOGGLEMAP" 121 | Control "Toggle Fullscreen", "UCM_TOGGLEFULLSCREEN" 122 | Control "Toggle Fullsize", "UCM_TOGGLEFULLSIZE" 123 | Control "Toggle Following", "UCM_TOGGLEFOLLOW" 124 | StaticText " " 125 | Control "Pan Up" , "+UCM_PANUP" 126 | Control "Pan Down" , "+UCM_PANDOWN" 127 | Control "Pan Left" , "+UCM_PANLEFT" 128 | Control "Pan Right", "+UCM_PANRIGHT" 129 | StaticText " " 130 | SubMenu "Back", "UCMOptions" 131 | } 132 | 133 | 134 | AddOptionMenu "CustomizeControls" 135 | { 136 | // Man this is a gross solution, i really wish there were a way to 137 | // setup ini sections in MenuDef... 138 | Submenu "UCMinimap Controls" , "UCMOptions" 139 | StaticText " " 140 | StaticText " " 141 | StaticText " " 142 | StaticText " " 143 | StaticText " " 144 | StaticText " " 145 | StaticText " " 146 | StaticText " " 147 | StaticText " " 148 | StaticText " " 149 | StaticText " " 150 | StaticText " " 151 | StaticText " " 152 | StaticText " " 153 | StaticText " " 154 | StaticText " " 155 | StaticText " " 156 | StaticText " " 157 | StaticText " " 158 | StaticText " " 159 | StaticText " " 160 | StaticText " " 161 | StaticText " " 162 | StaticText "↓ More Controls ↓" 163 | } 164 | 165 | OptionValue "YesOrNo" 166 | { 167 | 0, "No" 168 | 1, "Yes" 169 | } 170 | 171 | OptionValue "NoOrYes" 172 | { 173 | 0, "Yes" 174 | 1, "No" 175 | } 176 | 177 | OptionValue "RadarDisable" 178 | { 179 | 0, "Disabled" 180 | } 181 | 182 | OptionValue "DrawItems" 183 | { 184 | 0, "No" 185 | 1, "Yes, only counted items." 186 | 2, "Yes, all items." 187 | } 188 | 189 | OptionValue "Set" 190 | { 191 | 0, " " 192 | 1, "*" 193 | } 194 | 195 | OptionValue "SpecialAction" 196 | { 197 | 0, "Disabled" 198 | 1, "Polyobj_StartLine" 199 | 2, "Polyobj_RotateLeft" 200 | 3, "Polyobj_RotateRight" 201 | 4, "Polyobj_Move" 202 | 5, "Polyobj_ExplicitLine" 203 | 6, "Polyobj_MoveTimes8" 204 | 7, "Polyobj_DoorSwing" 205 | 8, "Polyobj_DoorSlide" 206 | 10, "Door_Close" 207 | 11, "Door_Open" 208 | 12, "Door_Raise" 209 | 13, "Door_LockedRaise" 210 | 14, "Door_Animated" 211 | 17, "Thing_Raise" 212 | 19, "Thing_Stop" 213 | 20, "Floor_LowerByValue" 214 | 21, "Floor_LowerToLowest" 215 | 22, "Floor_LowerToNearest" 216 | 23, "Floor_RaiseByValue" 217 | 24, "Floor_RaiseToHighest" 218 | 25, "Floor_RaiseToNearest" 219 | 26, "Stairs_BuildDown" 220 | 27, "Stairs_BuildUp" 221 | 28, "Floor_RaiseAndCrush" 222 | 29, "Pillar_Build" 223 | 30, "Pillar_Open" 224 | 31, "Stairs_BuildDownSync" 225 | 32, "Stairs_BuildUpSync" 226 | 34, "ClearForceField" 227 | 35, "Floor_RaiseByValueTimes8" 228 | 36, "Floor_LowerByValueTimes8" 229 | 37, "Floor_MoveToValue" 230 | 38, "Ceiling_Waggle" 231 | 39, "Teleport_ZombieChanger" 232 | 40, "Ceiling_LowerByValue" 233 | 41, "Ceiling_RaiseByValue" 234 | 42, "Ceiling_CrushAndRaise" 235 | 43, "Ceiling_LowerAndCrush" 236 | 45, "Ceiling_CrushRaiseAndStay" 237 | 47, "Ceiling_MoveToValue" 238 | 55, "Line_SetBlocking" 239 | 59, "Polyobj_OR_MoveToSpot" 240 | 60, "Plat_PerpetualRaise" 241 | 61, "Plat_Stop" 242 | 62, "Plat_DownWaitUpStay" 243 | 63, "Plat_DownByValue" 244 | 64, "Plat_UpWaitDownStay" 245 | 65, "Plat_UpByValu" 246 | 66, "Floor_LowerInstant" 247 | 67, "Floor_RaiseInstant" 248 | 68, "Floor_MoveToValueTimes8" 249 | 69, "Ceiling_MoveToValueTimes8" 250 | 70, "Teleport" 251 | 71, "Teleport_NoFog" 252 | 74, "Teleport_NewMap" 253 | 75, "Teleport_EndGame" 254 | 76, "TeleportOther" 255 | 77, "TeleportGroup" 256 | 78, "TeleportInSector" 257 | 80, "ACS_Execute" 258 | 81, "ACS_Suspend" 259 | 82, "ACS_Terminate" 260 | 83, "ACS_LockedExecute" 261 | 84, "ACS_ExecuteWithResult" 262 | 85, "ACS_LockedExecuteDoor" 263 | 86, "Polyobj_MoveToSpot" 264 | 87, "Polyobj_Stop" 265 | 88, "Polyobj_MoveTo" 266 | 89, "Polyobj_OR_MoveTo" 267 | 90, "Polyobj_OR_RotateLeft" 268 | 91, "Polyobj_OR_RotateRight" 269 | 92, "Polyobj_OR_Move" 270 | 93, "Polyobj_OR_MoveTimes8" 271 | 94, "Pillar_BuildAndCrush" 272 | 95, "FloorAndCeiling_LowerByValue" 273 | 96, "FloorAndCeiling_RaiseByValue" 274 | 99, "Floor_RaiseAndCrushDoom" 275 | 104, "Ceiling_CrushAndRaiseSilentDist" 276 | 105, "Door_WaitRaise" 277 | 106, "Door_WaitClose" 278 | 125, "Thing_Move" 279 | 127, "Thing_SetSpecial" 280 | 129, "UsePuzzleItem" 281 | 130, "Thing_Activate" 282 | 131, "Thing_Deactivate" 283 | 132, "Thing_Remove" 284 | 133, "Thing_Destroy" 285 | 134, "Thing_Projectile" 286 | 135, "Thing_Spawn" 287 | 136, "Thing_ProjectileGravity" 288 | 137, "Thing_SpawnNoFog" 289 | 138, "Floor_Waggle" 290 | 139, "Thing_SpawnFacing" 291 | 154, "Teleport_NoStop" 292 | 158, "FS_Execute" 293 | 168, "Ceiling_CrushAndRaiseDist" 294 | 169, "Generic_Crusher2" 295 | 170, "Sector_SetCeilingScale2" 296 | 171, "Sector_SetFloorScale2" 297 | 172, "Plat_UpNearestWaitDownStay" 298 | 176, "Thing_ChangeTID" 299 | 177, "Thing_Hate" 300 | 181, "Plane_Align" 301 | 183, "Line_AlignCeiling" 302 | 184, "Line_AlignFloor" 303 | 185, "Sector_SetRotation" 304 | 186, "Sector_SetCeilingPanning" 305 | 187, "Sector_SetFloorPanning" 306 | 188, "Sector_SetCeilingScale" 307 | 189, "Sector_SetFloorScale" 308 | 191, "SetPlayerProperty" 309 | 192, "Ceiling_LowerToHighestFloor" 310 | 193, "Ceiling_LowerInstant" 311 | 194, "Ceiling_RaiseInstant" 312 | 195, "Ceiling_CrushRaiseAndStayA" 313 | 196, "Ceiling_CrushAndRaiseA" 314 | 197, "Ceiling_CrushAndRaiseSilentA" 315 | 198, "Ceiling_RaiseByValueTimes8" 316 | 199, "Ceiling_LowerByValueTimes8" 317 | 200, "Generic_Floor" 318 | 201, "Generic_Ceiling" 319 | 202, "Generic_Doo" 320 | 203, "Generic_Lif" 321 | 204, "Generic_Stairs" 322 | 205, "Generic_Crusher" 323 | 206, "Plat_DownWaitUpStayLip" 324 | 207, "Plat_PerpetualRaiseLip" 325 | 214, "Sector_SetDamage" 326 | 215, "Teleport_Line" 327 | 216, "Sector_SetGravity" 328 | 217, "Stairs_BuildUpDoom" 329 | 218, "Sector_SetWind" 330 | 219, "Sector_SetFriction" 331 | 220, "Sector_SetCurrent" 332 | 223, "Scroll_Floor" 333 | 224, "Scroll_Ceiling" 334 | 225, "Scroll_Texture_Offsets" 335 | 226, "ACS_ExecuteAlways" 336 | 227, "PointPush_SetForce" 337 | 228, "Plat_RaiseAndStayTx0" 338 | 229, "Thing_SetGoal" 339 | 230, "Plat_UpByValueStayTx" 340 | 231, "Plat_ToggleCeiling" 341 | 235, "Floor_TransferTrigger" 342 | 236, "Floor_TransferNumeric" 343 | 237, "ChangeCamera" 344 | 238, "Floor_RaiseToLowestCeiling" 345 | 239, "Floor_RaiseByValueTxTy" 346 | 241, "Floor_LowerToLowestTxTy" 347 | 242, "Floor_LowerToHighest" 348 | 243, "Exit_Normal" 349 | 244, "Exit_Secret" 350 | 245, "Elevator_RaiseToNearest" 351 | 246, "Elevator_MoveToFloor" 352 | 247, "Elevator_LowerToNearest" 353 | 249, "Door_CloseWaitOpen" 354 | 250, "Floor_Donut" 355 | 251, "FloorAndCeiling_LowerRaise" 356 | 252, "Ceiling_RaiseToNearest" 357 | 253, "Ceiling_LowerToLowest" 358 | 254, "Ceiling_LowerToFloor" 359 | 255, "Ceiling_CrushRaiseAndStaySilA" 360 | 256, "Floor_LowerToHighestEE" 361 | 257, "Floor_RaiseToLowest" 362 | 258, "Floor_LowerToLowestCeiling" 363 | 259, "Floor_RaiseToCeiling" 364 | 260, "Floor_ToCeilingInstant" 365 | 261, "Floor_LowerByTexture" 366 | 262, "Ceiling_RaiseToHighest" 367 | 263, "Ceiling_ToHighestInstant" 368 | 264, "Ceiling_LowerToNearest" 369 | 265, "Ceiling_RaiseToLowest" 370 | 266, "Ceiling_RaiseToHighestFloor" 371 | 267, "Ceiling_ToFloorInstant" 372 | 268, "Ceiling_RaiseByTexture" 373 | 269, "Ceiling_LowerByTexture" 374 | 270, "Stairs_BuildDownDoom" 375 | 271, "Stairs_BuildUpDoomSync" 376 | 272, "Stairs_BuildDownDoomSync" 377 | 273, "Stairs_BuildUpDoomCrush" 378 | 274, "Door_AnimatedClose" 379 | 275, "Floor_Stop" 380 | 276, "Ceiling_Stop" 381 | 279, "Floor_MoveToValueAndCrush" 382 | 280, "Ceiling_MoveToValueAndCrush" 383 | } 384 | 385 | 386 | -------------------------------------------------------------------------------- /ZScript/ucm_minimap.zsc: -------------------------------------------------------------------------------- 1 | // Real-time playtimer 2 | class UCMinimap_StaticHandler : StaticEventHandler 3 | { 4 | transient CVar cv_playtime; 5 | transient CVar cv_mapdeaths; 6 | String curmap; 7 | override void WorldLoaded(WorldEvent e) 8 | { 9 | PlayerInfo plr = players[consoleplayer]; 10 | if(!plr) return; 11 | cv_playtime = CVar.GetCVar("ucm_map_playtime", plr); 12 | cv_mapdeaths = CVar.GetCVar("ucm_map_deaths", plr); 13 | if(curmap != level.MapName && cv_playtime && cv_mapdeaths) 14 | { 15 | cv_playtime.SetInt(0); 16 | cv_mapdeaths.SetInt(0); 17 | curmap = level.MapName; 18 | } 19 | } 20 | override void WorldThingDied(WorldEvent e) 21 | { 22 | if(PlayerPawn(e.Thing)) 23 | cv_mapdeaths.SetInt(cv_mapdeaths.GetInt()+1); 24 | } 25 | override void WorldTick() { cv_playtime.SetInt(cv_playtime.getInt()+1); } 26 | } 27 | 28 | // Minimap and Radar 29 | class UCMinimap_EventHandler : EventHandler 30 | { 31 | int playtime_tics; 32 | transient bool waypointmenu_forceopen; // Triggers waypoint menu 33 | transient bool waypointmenu_forceclose; 34 | ui transient Shape2D bg_circle; 35 | ui transient vector2 baseoffs; 36 | ui transient TextureID curpix; 37 | ui transient TextureID pix; 38 | ui transient TextureID indpix; 39 | ui transient double prevMS; 40 | ui transient double deltatime; 41 | ui transient double map_size; 42 | ui transient double scrw; 43 | ui transient double scrh; 44 | ui transient double plr_rot; 45 | ui transient double curzoom; 46 | ui transient vector2 mappos; // Interpolated player position. 47 | transient Array btn_lines; 48 | 49 | // CVars 50 | private transient CVar cv_xoffset; 51 | private transient CVar cv_yoffset; 52 | private transient CVar cv_mapfollow; 53 | private transient CVar cv_mapshowall; 54 | private transient CVar cv_hidden; 55 | private transient CVar cv_drawmap; 56 | private transient CVar cv_hidemonsters; 57 | private transient CVar cv_fullmapsize; 58 | private transient CVar cv_maxmapsize; 59 | private transient CVar cv_domaprotation; 60 | private transient CVar cv_showdist; 61 | private transient CVar cv_showrep; 62 | private transient CVar cv_mapsize; 63 | private transient CVar cv_radarzoom; 64 | private transient CVar cv_drawplayer; 65 | private transient CVar cv_drawcompass; 66 | private transient CVar cv_renderdistance; 67 | private transient CVar cv_radardistance; 68 | private transient CVar cv_switchdistance; 69 | private transient CVar cv_drawitems; 70 | private transient CVar cv_drawmissiles; 71 | private transient CVar cv_drawhealthbars; 72 | private transient CVar cv_markstartandexit; 73 | private transient CVar cv_mapdeaths; 74 | private transient CVar cv_drawkeys; 75 | private transient CVar cv_color_normal; 76 | private transient CVar cv_color_solid; 77 | private transient CVar cv_color_action; 78 | private transient CVar cv_color_border; 79 | private transient CVar cv_color_backg; 80 | private transient CVar cv_color_lum; 81 | private transient CVar cv_color_alpha; 82 | private transient CVar cv_color_backgalpha; 83 | private transient CVar cv_color_compass; 84 | private transient CVar cv_color_stats; 85 | private transient CVar cv_playtime; 86 | private transient CVar wp_name; 87 | private transient CVar wp_color; 88 | 89 | // Held button states 90 | enum MBT 91 | { 92 | MBT_UP = 1, 93 | MBT_DOWN = 1<<1, 94 | MBT_LEFT = 1<<2, 95 | MBT_RIGHT = 1<<3, 96 | MBT_ZOOMIN = 1<<4, 97 | MBT_ZOOMOUT = 1<<5 98 | }; 99 | uint mapbtns; 100 | 101 | override void OnRegister() 102 | { 103 | PlayerInfo plr = players[consoleplayer]; 104 | if(!plr) return; 105 | 106 | cv_xoffset = CVar.GetCVar("ucm_xoffset", plr); 107 | cv_yoffset = CVar.GetCVar("ucm_yoffset", plr); 108 | cv_mapfollow = CVar.GetCVar("ucm_mapfollow", plr); 109 | cv_mapshowall = CVar.GetCVar("ucm_mapshowall", plr); 110 | cv_hidden = CVar.GetCVar("ucm_hide", plr); 111 | cv_drawmap = CVar.GetCVar("ucm_drawmap", plr); 112 | cv_drawcompass = CVar.GetCVar("ucm_drawcompass", plr); 113 | cv_fullmapsize = CVar.GetCVar("ucm_drawfullscreen", plr); 114 | cv_maxmapsize = CVar.GetCVar("ucm_drawmaxsize", plr); 115 | cv_domaprotation = CVar.GetCVar("ucm_drawrotation", plr); 116 | cv_showdist = CVar.GetCVar("ucm_showdistance", plr); 117 | cv_showrep = CVar.GetCVar("ucm_showrepeatable", plr); 118 | cv_mapsize = CVar.GetCVar("ucm_mapsize", plr); 119 | cv_radarzoom = CVar.GetCVar("ucm_radarzoom", plr); 120 | cv_renderdistance = CVar.GetCVar("ucm_maprenderdist", plr); 121 | cv_drawplayer = CVar.GetCVar("ucm_drawplayer", plr); 122 | cv_radardistance = CVar.GetCVar("ucm_radardist", plr); 123 | cv_switchdistance = CVar.GetCVar("ucm_maxswitchdist", plr); 124 | cv_color_normal = CVar.GetCVar("ucm_color_normal", plr); 125 | cv_color_solid = CVar.GetCVar("ucm_color_solid", plr); 126 | cv_color_action = CVar.GetCVar("ucm_color_action", plr); 127 | cv_color_border = CVar.GetCVar("ucm_color_border", plr); 128 | cv_color_backg = CVar.GetCVar("ucm_color_backg", plr); 129 | cv_color_compass = CVar.GetCVar("ucm_color_compas", plr); 130 | cv_color_lum = CVar.GetCVar("ucm_color_lum", plr); 131 | cv_color_alpha = CVar.GetCVar("ucm_color_alpha", plr); 132 | cv_color_backgalpha = CVar.GetCVar("ucm_color_backgalpha", plr); 133 | cv_playtime = CVar.GetCVar("ucm_map_playtime", plr); 134 | cv_color_stats = CVar.GetCVar("ucm_color_stats", plr); 135 | cv_drawitems = CVar.GetCVar("ucm_drawitems", plr); 136 | cv_drawmissiles = CVar.GetCVar("ucm_drawmissiles", plr); 137 | cv_hidemonsters = CVar.GetCVar("ucm_hidemonsters", plr); 138 | cv_drawhealthbars = CVar.GetCVar("ucm_drawhealthbars", plr); 139 | cv_markstartandexit = CVar.GetCVar("ucm_markstartexit", plr); 140 | cv_mapdeaths = CVar.GetCVar("ucm_map_deaths", plr); 141 | cv_drawkeys = CVar.GetCVar("ucm_drawkeys", plr); 142 | 143 | wp_name = CVar.GetCVar("waypoint_name", plr); 144 | wp_color = CVar.GetCVar("waypoint_color", plr); 145 | } 146 | 147 | override void WorldTick() 148 | { 149 | if((mapbtns & MBT_ZOOMIN) && cv_radarzoom.GetFloat() > 0.01) 150 | cv_radarzoom.SetFloat(cv_radarzoom.GetFloat()-0.1); 151 | if((mapbtns & MBT_ZOOMOUT) && cv_radarzoom.GetFloat() < 500) 152 | cv_radarzoom.SetFloat(cv_radarzoom.getFloat()+0.1); 153 | 154 | if(cv_xoffset.GetInt() < 0 && cv_yoffset.GetInt() < 0) 155 | SendNetworkEvent("align.upperleft"); 156 | } 157 | 158 | override void RenderOverlay(RenderEvent e) 159 | { 160 | let plr = players[consoleplayer].mo; 161 | if(!plr || gamestate != GS_LEVEL) return; 162 | 163 | // Deltatime 164 | if(!prevMS) 165 | { 166 | prevMS = MSTime(); 167 | return; 168 | } 169 | double ftime = MSTime()-prevMS; 170 | prevMS = MSTime(); 171 | double dtime = 1000.0 / 60.0; 172 | deltatime = (ftime/dtime); 173 | 174 | // Setup 175 | scrw = Screen.GetWidth(); 176 | scrh = Screen.GetHeight(); 177 | if(mappos.x+mappos.y == 0) mappos = plr.pos.xy; 178 | 179 | // Face animations 180 | int faceind = (((Level.time+1) / 35) % 3); 181 | if(faceind > 2) faceind = 0; 182 | 183 | // Textures 184 | TextureID switchtex = TexMan.CheckForTexture("SWTIND",TexMan.Type_Any); 185 | TextureID rswitchtex = TexMan.CheckForTexture("RSWTIND",TexMan.Type_Any); 186 | TextureID plrtex = TexMan.CheckForTexture("STFST0" .. faceind,TexMan.Type_Any); 187 | if( !pix) pix = TexMan.CheckForTexture("PXL",TexMan.Type_Any); 188 | if(!indpix) indpix = TexMan.CheckForTexture("INDPXL",TexMan.Type_Any); 189 | curpix = pix; 190 | 191 | // CVars 192 | Vector2 useroffs = (cv_xoffset.GetInt(), cv_yoffset.GetInt()); 193 | bool dontShowAll = !cv_mapshowall.getBool() && !level.allmap; 194 | bool hidden = cv_hidden.GetBool() && map_size <= 10; 195 | bool fullmapsize = cv_fullmapsize.GetBool(); 196 | bool maxmapsize = cv_maxmapsize.GetBool(); 197 | bool domaprotation = cv_domaprotation.GetBool(); 198 | bool showdist = cv_showdist.GetBool(); 199 | bool showrep = cv_showrep.GetBool(); 200 | double to_mapsize = fullmapsize ? scrw*2 : (!maxmapsize ? cv_mapsize.getFloat() : 512); 201 | double size_mod = fullmapsize ? scrw/128. : map_size/128.; 202 | double minimap_renderdist = cv_renderdistance.getInt(); 203 | 204 | // If the map was recently loaded, reset interpolation. 205 | if(level.maptime < 5) 206 | { 207 | map_size = to_mapsize; 208 | mappos = plr.pos.xy; 209 | size_mod = map_size/128.; 210 | plr_rot = plr.angle; 211 | if(plr.player.camera) plr_rot = plr.player.camera.angle; 212 | baseoffs = ((25*size_mod)-useroffs.x, (25*size_mod)-useroffs.y); 213 | curzoom = cv_radarzoom.GetFloat(); 214 | } 215 | 216 | // Colors 217 | int col_bright = int(255.*cv_color_lum.getFloat()) << 24; 218 | int alpha_mask = 0xFF << 24; 219 | Color linecol = col_bright + cv_color_normal.getInt(); 220 | Color solid_linecol = col_bright + cv_color_solid.getInt(); 221 | Color acton_linecol = col_bright + cv_color_action.getInt(); 222 | Color radrcol = col_bright + cv_color_border.getInt(); 223 | Color backgcol = alpha_mask + cv_color_backg.getInt(); 224 | double line_alpha = cv_color_alpha.getFloat(); 225 | 226 | 227 | // Size and Offsets 228 | curzoom = Lerp(curzoom, cv_radarzoom.GetFloat(), 0.25*deltatime); 229 | if(curzoom == 0) curzoom = 1; 230 | 231 | if(!cv_hidden.GetBool()) 232 | map_size = Lerp(map_size, to_mapsize*(scrw/1920.), 0.25*deltatime); 233 | else 234 | map_size = Lerp(map_size, 0, 0.25*deltatime); 235 | 236 | float xres = 1920./scrw; 237 | float yres = 1080./scrh; 238 | 239 | if(!fullmapsize && maxmapsize) 240 | { 241 | double scrside = useroffs.x > scrw/2. ? -600 : -100; 242 | baseoffs.x = Lerp(baseoffs.x,scrside*xres,0.25*deltatime); 243 | baseoffs.y = Lerp(baseoffs.y,35*yres,0.25*deltatime); 244 | } 245 | else 246 | { 247 | baseoffs.x = Lerp(baseoffs.x,(25*size_mod)-useroffs.x,0.25*deltatime); 248 | baseoffs.y = Lerp(baseoffs.y,(25*size_mod)-useroffs.y,0.25*deltatime); 249 | } 250 | 251 | // Rotation and Positioning 252 | if(cv_mapfollow.GetBool()) 253 | { 254 | plr_rot = Lerp(plr_rot, domaprotation ? plr.angle : 90, 0.5*deltatime); 255 | if(plr.player.camera) 256 | { 257 | plr_rot = (domaprotation ? plr.player.camera.angle : 90); // Do not Lerp 258 | } 259 | mappos.x = Lerp(mappos.x, plr.pos.x, 0.5*deltatime); 260 | mappos.y = Lerp(mappos.y, plr.pos.y, 0.5*deltatime); 261 | } 262 | else 263 | { 264 | double movspd = (plr.player.cmd.buttons & BT_SPEED ? 20 : 10) * deltatime; 265 | movspd *= curzoom; 266 | plr_rot = Lerp(plr_rot, 90, 0.25*deltatime); 267 | if(mapbtns & MBT_UP ) mappos.y += movspd; 268 | if(mapbtns & MBT_DOWN ) mappos.y -= movspd; 269 | if(mapbtns & MBT_LEFT ) mappos.x -= movspd; 270 | if(mapbtns & MBT_RIGHT ) mappos.x += movspd; 271 | } 272 | Vector2 dp = Actor.RotateVector( (0,0), plr_rot-90 ); 273 | Vector2 map_middle = (dp.x-baseoffs.x+(156*size_mod),dp.y-baseoffs.y+(140*size_mod)); 274 | if(fullmapsize) 275 | { 276 | map_middle = (scrw/2., scrh/2.)-(0,90/yres); 277 | baseoffs = map_middle; 278 | } 279 | 280 | // Draw Minimap BG 281 | if(!hidden) 282 | FillCircle(map_middle.x,map_middle.y,MAP_SIZE+4,backgcol,cv_color_backgalpha.getFloat()); 283 | 284 | // Draw Minimap 285 | if( cv_drawmap.getBool() && !hidden ) 286 | { 287 | for (int i = 0; i < Level.Lines.Size(); i++) 288 | { 289 | Line ln = Level.Lines[i]; 290 | if( !(ln.flags & Line.ML_MAPPED) && dontShowAll ) continue; 291 | 292 | Vector2 ln_pos = ln.v1.p; 293 | Vector2 ln_len = ln.v2.p; 294 | 295 | // Check render distance 296 | if( 297 | abs(ln_pos.x-mappos.x) > minimap_renderdist 298 | && abs(ln_len.x-mappos.x) > minimap_renderdist 299 | || abs(ln_pos.y-mappos.y) > minimap_renderdist 300 | && abs(ln_len.y-mappos.y) > minimap_renderdist) 301 | { 302 | continue; 303 | } 304 | 305 | Vector2 amapoffs = fullmapsize ? baseoffs : -baseoffs+((156, 140)*size_mod); 306 | ln_pos = Actor.RotateVector(SwapVector(ln_pos-mappos),plr_rot+180); 307 | ln_len = Actor.RotateVector(SwapVector(ln_len-mappos),plr_rot+180); 308 | ln_pos += amapoffs*curzoom; 309 | ln_len += amapoffs*curzoom; 310 | ln_pos /= curzoom; 311 | ln_len /= curzoom; 312 | 313 | bool actionable = ln.special & SPAC_Cross || ln.special & SPAC_Use; 314 | Color drawcol = (ln.flags & Line.ML_BLOCKING) ? solid_linecol : actionable ? acton_linecol : linecol; 315 | drawLine(ln_pos.x,ln_pos.y,ln_len.x,ln_len.y,drawcol, map_middle, MAP_SIZE, line_alpha); 316 | } 317 | } 318 | 319 | // Draw Border 320 | if(!hidden && !fullmapsize) 321 | drawCircle(map_middle.x,map_middle.y, MAP_SIZE+4, radrcol, line_alpha); 322 | 323 | // Draw Switches 324 | if(switchtex && rswitchtex && plrtex && !hidden) 325 | { 326 | double maxswitch = cv_switchdistance.getInt(); 327 | 328 | for(uint i = 0; i < btn_lines.Size(); i++) 329 | { 330 | if(maxswitch <= 0) break; 331 | 332 | Line ln = Level.Lines[btn_lines[i]]; 333 | if(!ln) continue; 334 | if( ln.special == 0 ) continue; 335 | double dist = VDist2D( (ln.v1.p.x/2 + ln.v2.p.x/2, (ln.v2.p.y/2 + ln.v2.p.y/2)), mappos ) / 32; 336 | if(dist > maxswitch) continue; 337 | double l_angle = VectorAngle(ln.delta.x,ln.delta.y); 338 | int x = (mappos.x - (ln.v1.p.x/2 + ln.v2.p.x/2) ); 339 | int y = (mappos.y - (ln.v1.p.y/2 + ln.v2.p.y/2) ); 340 | Vector2 dp = Actor.RotateVector( SwapVector((x,y)), plr_rot ); 341 | dp /= curzoom; 342 | 343 | vector2 finalpos = dp+map_middle; 344 | finalpos = clamp_vec(finalpos, map_middle, MAP_SIZE-4); 345 | curpix = ((ln.flags & Line.ML_REPEAT_SPECIAL) && showrep) ? rswitchtex : switchtex; 346 | double swscale = clamp(size_mod, 0.25, 2.0); 347 | plotPixel(finalpos.x, finalpos.y, scale:(swscale,swscale)); 348 | if(showdist) Screen.DrawText("bigfont",Font.CR_GREEN,finalpos.x-5,finalpos.y-5, string.format("%d",dist)); 349 | } 350 | } 351 | 352 | // Draw Radar 353 | if(!hidden) 354 | { 355 | double frontangle = plr_rot+180; 356 | double maxdist = cv_radardistance.getFloat(); 357 | ThinkerIterator act_it = ThinkerIterator.Create("Actor"); 358 | Actor obj; 359 | while(obj = Actor(act_it.Next())) 360 | { 361 | let objItem = Inventory(obj); 362 | bool isKey = obj is "Key"; 363 | if(maxdist <= 0) break; 364 | if(!obj.bISMONSTER && !objItem && !obj.bMISSILE && !isKey) continue; 365 | if(obj.bMISSILE && !cv_drawmissiles.GetBool()) continue; 366 | if( objItem && !isKey && ( (!objItem.bCOUNTITEM && cv_drawitems.getInt() < 2) || !cv_drawitems.getInt() ) ) continue; 367 | if( objItem && !cv_drawkeys.GetBool()) continue; 368 | 369 | double angdiff = obj.bMISSILE ? 45*5 : (obj.angle-plr.AngleTo(obj))+90; 370 | TextureID stex = obj.CurState.GetSpriteTexture(((angdiff+135)%361)/45); 371 | vector2 texsize; 372 | [texsize.x, texsize.y] = TexMan.GetSize(stex); 373 | double x = mappos.x - (obj.pos.x - (texsize.x/2.)); 374 | double y = mappos.y - (obj.pos.y - (texsize.y/2.)); 375 | uint renderstyle = obj.getRenderStyle(); 376 | 377 | int dis = obj.Distance2D(plr); 378 | if( dis < (maxdist*10.) || isKey ) 379 | { 380 | vector2 delta = Actor.RotateVector( SwapVector((x,y)), frontangle); 381 | delta.x /= curzoom; 382 | delta.y /= curzoom; 383 | bool hastarget = dontShowAll ? (obj.target != NULL) : true; 384 | if( !(obj is plr.GetClass()) && (hastarget || objItem) ) 385 | { 386 | vector2 finalpos = ((map_middle.x-delta.x), (map_middle.y-delta.y)); 387 | double drawdist; 388 | [finalpos, drawdist] = clamp_vec(finalpos, map_middle, MAP_SIZE-4); 389 | 390 | Color dColor = Color(90,0xFF,0,0); 391 | double dAlpha = obj.alpha * (drawdist>MAP_SIZE-4 ? 0.6 : 1.0); 392 | double dScale = 2.0; 393 | dScale *= size_mod; 394 | dScale *= clamp(1.0-(drawdist/512.), isKey ? 0.75 : 0.35, 1.0); 395 | dScale = clamp(dScale, 0.5, 3.0); 396 | dScale /= (curzoom/6.); 397 | if(obj.bISMONSTER || obj.bMISSILE) dScale = clamp(dScale, 1.0, 3.5); 398 | if(obj.bFRIENDLY) dColor = Color(65, 0xFF, 0xFF, 0); 399 | bool radarvisible = drawdist 0) 412 | plotPixel(finalpos.x, finalpos.y, dColor, (dScale,dScale)*0.2, dAlpha*line_alpha, renderstyle); 413 | else if(radarvisible) 414 | plotPixel(finalpos.x, finalpos.y, 0, (dScale,dScale)*0.2, dAlpha*line_alpha, renderstyle); 415 | } 416 | else if(obj.bISMONSTER && obj.health > 0) 417 | { 418 | curpix = indpix; 419 | plotPixel(finalpos.x, finalpos.y, dColor, (dScale,dScale), dAlpha*line_alpha, renderstyle); 420 | } 421 | if(obj.bISMONSTER && cv_drawhealthbars.getBool() && radarvisible) 422 | { 423 | vector2 hbarpos = finalpos + (0, 5/size_mod)/yres; 424 | double curhealth = clamp(obj.health / double(obj.GetMaxHealth()), 0, 1.0); 425 | double healthmax = (20/xres) * curhealth; 426 | Color hpcol_high = 0x00FF00; 427 | Color hpcol_low = 0xFF0000; 428 | Color hpcol = (0xFF<<24) + int(Lerp(hpcol_high,hpcol_low,1. - curhealth)); 429 | Screen.DrawThickLine(hbarpos.x-healthmax/2,hbarpos.y,hbarpos.x+healthmax/2,hbarpos.y,7/xres,hpcol,floor(255*0.5)); 430 | //Screen.DrawThickLine(finalpos.x,finalpos.y-10,finalpos.x+20,finalpos.y-10,10,0xFFFF0000,255); 431 | } 432 | } 433 | } 434 | } 435 | 436 | // Draw Waypoints 437 | let wp_data = I_WaypointStorage(plr.FindInventory("I_WaypointStorage")); 438 | if(wp_data) 439 | { 440 | for(int i = 0; i < wp_data.waypoints.Size(); i++) 441 | { 442 | let wp = WaypointObject(wp_data.waypoints[i]); 443 | double x = mappos.x - wp.pos.x; 444 | double y = mappos.y - wp.pos.y; 445 | vector2 delta = Actor.RotateVector( SwapVector((x,y)), frontangle) / curzoom; 446 | vector2 finalpos = map_middle-delta; 447 | double wpscale = 4.0; 448 | finalpos = clamp_vec(finalpos, map_middle, MAP_SIZE); 449 | curpix = pix; 450 | plotPixel(finalpos.x, finalpos.y, wp.col, (wpscale,wpscale)); 451 | Color textcol = wp.col - (0x90<<24); 452 | Screen.DrawText("bigfont", Font.CR_UNTRANSLATED, 453 | finalpos.x-(wpscale/2),finalpos.y-(wpscale/2), wp.nickname, DTA_ColorOverlay, textcol); 454 | } 455 | } 456 | // Draw Player 457 | if(cv_drawplayer.GetBool()) 458 | { 459 | double plrscale = clamp(0.75*size_mod, 0.25, 1.0); 460 | curpix = plrtex; 461 | if(cv_mapfollow.GetBool()) 462 | plotPixel(map_middle.x-(16*plrscale),map_middle.y-(16*plrscale), scale:(plrscale,plrscale)); 463 | else 464 | { 465 | double x = mappos.x - plr.pos.x; 466 | double y = mappos.y - plr.pos.y; 467 | vector2 delta = Actor.RotateVector( SwapVector((x,y)), frontangle); 468 | delta.x /= curzoom; 469 | delta.y /= curzoom; 470 | vector2 finalpos = ((map_middle.x-delta.x), (map_middle.y-delta.y)); 471 | if(VDist2D(finalpos, map_middle) < MAP_SIZE+8) 472 | plotPixel(finalpos.x-(16*plrscale),finalpos.y-(16*plrscale), scale:(plrscale,plrscale)); 473 | } 474 | } 475 | // Draw Compass (Get normal map middle, when not scaled to fullscreen) 476 | double normmapsize = cv_mapsize.getFloat(); 477 | double normsizemod = normmapsize/128.; 478 | vector2 normoffs = ((25*normsizemod)-useroffs.x, (25*normsizemod)-useroffs.y); 479 | vector2 normal_mapmiddle = (dp.x-normoffs.x+(156*normsizemod),dp.y-normoffs.y+(150*normsizemod)); 480 | normal_mapmiddle = (normal_mapmiddle.x/xres, normal_mapmiddle.y/yres); 481 | if(cv_drawcompass.GetBool()) 482 | { 483 | curpix = pix; 484 | Color compasscol = (0x90 << 24) + cv_color_compass.GetInt(); 485 | double cradius = fullmapsize ? 128/xres : map_size; 486 | vector2 truemid = fullmapsize ? normal_mapmiddle : map_middle; 487 | vector2 midoffs = -(6,5); 488 | vector2 northpos = truemid+midoffs+(Actor.RotateVector((cradius,cradius)*0.78, frontangle-45 )); 489 | vector2 southpos = truemid+midoffs+(Actor.RotateVector((cradius,cradius)*0.78, frontangle-45+180)); 490 | vector2 eastpos = truemid+midoffs+(Actor.RotateVector((cradius,cradius)*0.78, frontangle-45+90 )); 491 | vector2 westpos = truemid+midoffs+(Actor.RotateVector((cradius,cradius)*0.78, frontangle-45-90 )); 492 | uint ftrns = Font.CR_UNTRANSLATED; 493 | DrawCircle(truemid.x, truemid.y, cradius*1.1, int(compasscol*0.5), 0.5); 494 | if(fullmapsize) 495 | { 496 | DrawLine(northpos.x+6,northpos.y+5,southpos.x+6,southpos.y+5,compasscol,truemid,cradius*1.1); 497 | DrawLine(eastpos.x+6,eastpos.y+5,westpos.x+6,westpos.y+5,compasscol,truemid,cradius*1.1); 498 | } 499 | Screen.DrawText("bigfont", ftrns, northpos.x, northpos.y, "N", DTA_ColorOverlay, compasscol); 500 | Screen.DrawText("bigfont", ftrns, southpos.x, southpos.y, "S", DTA_ColorOverlay, compasscol); 501 | Screen.DrawText("bigfont", ftrns, eastpos.x, eastpos.y, "E", DTA_ColorOverlay, compasscol); 502 | Screen.DrawText("bigfont", ftrns, westpos.x, westpos.y, "W", DTA_ColorOverlay, compasscol); 503 | } 504 | 505 | // Draw fullscreen text 506 | if(fullmapsize) 507 | { 508 | Color txtcol = (0x90<<24) + cv_color_stats.GetInt(); 509 | Color percol = clamp(txtcol+0x00CCCCCC, txtcol, 0x90DDDDDD); 510 | vector2 txtpos = (5,2); 511 | vector2 txtdiff = (0,6); 512 | vector2 txtscale = (0.7, 0.7); 513 | uint ftrns = Font.CR_UNTRANSLATED; 514 | double killsper = level.total_monsters ? level.killed_monsters/double(level.total_monsters)*100 : 100; 515 | double secretsper = level.total_secrets ? (level.found_secrets/double(level.total_secrets))*100 : 100; 516 | double itemsper = level.total_items ? (level.found_items/double(level.total_items))*100 : 100; 517 | double playhours = cv_playtime.getInt()/(35*60*60); 518 | double playminutes = cv_playtime.getInt()/(35*60) - (playhours*60); 519 | double playseconds = cv_playtime.getInt()/35. - (playminutes*60) - (playhours*60*60); 520 | string playtime = String.Format("Time: \c[Green]%.2d:%.2d:%.2d",playhours,playminutes,playseconds); 521 | if(playhours >= 1) playtime = playtime .. "\c[Red](SUCKS)"; 522 | string kills = String.Format("Kills \c[Green]%d/%d (%d%)", 523 | level.killed_monsters,level.total_monsters, 524 | killsper 525 | ); 526 | string secrets = String.Format("Secrets \c[Green]%d/%d (%d%)", 527 | level.found_secrets,level.total_secrets, 528 | secretsper 529 | ); 530 | string items = String.Format("Items \c[Green]%d/%d (%d%)", 531 | level.found_items,level.total_items, 532 | itemsper 533 | ); 534 | string mapinfo = String.Format("\c[Red]%s: \c[White]%s", level.MapName, level.LevelName); 535 | DrawScaledString("bigfont", kills, txtpos, 536 | killsper >= 100 ? percol : txtcol, txtscale 537 | ); 538 | txtpos += txtdiff; 539 | DrawScaledString("bigfont", secrets, txtpos, 540 | secretsper >= 100 ? percol : txtcol, txtscale 541 | ); 542 | txtpos = (424,2); 543 | DrawScaledString("bigfont", playtime, txtpos, 544 | playhours>=1 ? percol : txtcol, txtscale 545 | ); 546 | txtpos += txtdiff; 547 | DrawScaledString("bigfont", items, txtpos, 548 | itemsper >= 100 ? percol : txtcol, txtscale 549 | ); 550 | txtpos = (213,7); 551 | DrawScaledString("bigfont", mapinfo, txtpos, scale:txtscale); 552 | txtpos += txtdiff; 553 | DrawScaledString("bigfont", "Deaths: \c[Red]" .. cv_mapdeaths.getInt(), txtpos, txtcol, txtscale); 554 | } 555 | } 556 | 557 | // Waypoint menu 558 | if(waypointmenu_forceclose) 559 | { 560 | let m = Menu.getCurrentMenu(); 561 | if(m) m.Close(); 562 | SendNetworkEvent("ucm.waypointmenu.done"); 563 | } 564 | } 565 | 566 | // Fetch Switches 567 | void FindSwitches() 568 | { 569 | btn_lines.Clear(); 570 | bool mustuse = CVar.FindCVar("ucm_mustuse").getBool(); 571 | int specific = CVar.FindCVar("ucm_specific").getInt(); 572 | for(uint i = 0; i < Level.Lines.Size(); i++) 573 | { 574 | Line ln = Level.Lines[i]; 575 | bool isactivatable = (ln.special & (SPAC_Use|SPAC_Impact|SPAC_Push)); 576 | 577 | if(specific && ln.special == specific) btn_lines.Push(i); 578 | else if(specific) continue; 579 | else 580 | { 581 | if (isactivatable && mustuse) 582 | btn_lines.Push(i); 583 | else if(!mustuse && ln.special) 584 | btn_lines.Push(i); 585 | } 586 | } 587 | } 588 | bool, vector2 GetSpecialLinePos(uint special) 589 | { 590 | for(uint i = 0; i < Level.Lines.Size(); i++) 591 | { 592 | Line ln = Level.Lines[i]; 593 | if(ln.special != special) continue; 594 | return true, (ln.v1.p.x/2 + ln.v2.p.x/2, ln.v2.p.y/2 + ln.v2.p.y/2); 595 | } 596 | return false, (0, 0); 597 | } 598 | 599 | override void WorldLoaded(WorldEvent e) 600 | { 601 | PlayerInfo plr = players[consoleplayer]; 602 | if(!plr) return; 603 | 604 | FindSwitches(); 605 | let wp = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 606 | if(wp) 607 | wp.waypoints.Clear(); 608 | else 609 | { 610 | plr.mo.GiveInventory("I_WaypointStorage", 1); 611 | wp = I_WaypointStorage(plr.mo.FindInventory("I_WaypointStorage")); 612 | } 613 | 614 | // Create start and end waypoints. 615 | if(cv_markstartandexit && wp && cv_markstartandexit.GetBool()) 616 | { 617 | bool _exitpos; 618 | vector2 exitpos; 619 | [_exitpos, exitpos] = GetSpecialLinePos(243); 620 | if(!wp.FindNamedWaypoint("Start")) 621 | wp.AddWaypoint("Start", 0xFF00FF00, plr.mo.pos.xy); 622 | if(!wp.FindNamedWaypoint("Exit") && _exitpos) 623 | wp.AddWaypoint("Exit", 0xFFFF0000, exitpos); 624 | } 625 | } 626 | } 627 | --------------------------------------------------------------------------------