]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
strafehud. various improvements for the more modular strafehud code
authorJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Tue, 3 Sep 2024 21:34:52 +0000 (23:34 +0200)
committerJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Tue, 3 Sep 2024 21:54:00 +0000 (23:54 +0200)
qcsrc/client/hud/panel/strafehud.qc
qcsrc/client/hud/panel/strafehud.qh
qcsrc/client/hud/panel/strafehud/core.qc
qcsrc/client/hud/panel/strafehud/core.qh
qcsrc/client/hud/panel/strafehud/draw.qc
qcsrc/client/hud/panel/strafehud/draw.qh
qcsrc/client/hud/panel/strafehud/extra.qc
qcsrc/client/hud/panel/strafehud/util.qc

index de1e8af0021c4a40c703f8a2ac19f004758149b4..8598fd7aeb87f7bb803df615b4fd8568762aaca6 100644 (file)
@@ -86,7 +86,6 @@ void HUD_StrafeHUD()
 
                static float onground_lasttime = 0;
                static bool onslick_last = false;
-
                if(onground)
                {
                        if(PHYS_FRICTION(strafeplayer) == 0)
@@ -141,8 +140,6 @@ void HUD_StrafeHUD()
                else
                        movespeed = min(movespeed, maxspeed);
 
-               float dt = DetectFrameTime();
-
                // determine whether the player is pressing forwards or backwards keys
                int keys_fwd;
                if(islocal) // if entity is local player
@@ -217,16 +214,19 @@ void HUD_StrafeHUD()
                        }
                }
 
+               float dt = DetectFrameTime();
+
                maxaccel *= dt * movespeed;
                float bestspeed = max(movespeed - maxaccel, 0); // target speed to gain maximum acceleration
 
                // use local csqcmodel entity for this even when spectating, flickers too much otherwise
                float speed = !autocvar__hud_configure ? vlen(vec2(csqcplayer.velocity)) : 1337;
+               bool moving = speed > 0;
 
                float frictionspeed; // speed lost from friction
                float strafespeed; // speed minus friction
 
-               if((speed > 0) && onground)
+               if(moving && onground)
                {
                        float strafefriction = onslick ? PHYS_FRICTION_SLICK(strafeplayer) : PHYS_FRICTION(strafeplayer);
 
@@ -239,19 +239,13 @@ void HUD_StrafeHUD()
                        strafespeed = speed;
                }
 
-               float minspeed = autocvar_hud_panel_strafehud_switch_minspeed;
-               if(minspeed < 0)
-                       minspeed = bestspeed + frictionspeed;
-
                // get current strafing angle ranging from -180° to +180°
                float angle;
                bool fwd;
-               bool straight_overturn = false;
-               float antiflicker_angle = bound(0, autocvar_hud_panel_strafehud_antiflicker_angle, 180);
 
                if(!autocvar__hud_configure)
                {
-                       if(speed > 0)
+                       if(moving)
                        {
                                // change the range from 0° - 360° to -180° - 180° to match how view_angle represents angles
                                float vel_angle = vectoangles(strafeplayer.velocity).y - (vectoangles(strafeplayer.velocity).y > 180 ? 360 : 0);
@@ -294,10 +288,6 @@ void HUD_StrafeHUD()
                                        else
                                                angle -= 180;
                                }
-
-                               // do not make the angle indicator switch side too much at ±180° if anti flicker is turned on
-                               if(angle > (180 - antiflicker_angle) || angle < (-180 + antiflicker_angle))
-                                       straight_overturn = true;
                        }
                        else
                        {
@@ -354,6 +344,7 @@ void HUD_StrafeHUD()
                float absolute_bestangle = bestangle;
                float absolute_prebestangle = prebestangle;
 
+               float antiflicker_angle = bound(0, autocvar_hud_panel_strafehud_antiflicker_angle, 180);
                float direction = StrafeHUD_determineDirection(angle, wishangle, antiflicker_angle);
 
                if(direction == STRAFEHUD_DIRECTION_LEFT) // the angle becomes negative in case we strafe left
@@ -375,7 +366,6 @@ void HUD_StrafeHUD()
 
                // best strafe acceleration angle
                float changeangle = -bestangle;
-               float bestangle_width = max(panel_size.x * autocvar_hud_panel_strafehud_switch_width, 1);
 
                bool opposite_direction = false;
                float opposite_changeangle = 0;
@@ -385,33 +375,21 @@ void HUD_StrafeHUD()
                        opposite_changeangle = opposite_bestangle + bestangle * 2;
                }
 
-               bool immobile = speed <= 0;
-
-               float currentangle = angle;
-               if(mode == STRAFEHUD_MODE_VELOCITY_CENTERED)
-                       currentangle = bound(-hudangle / 2, currentangle, hudangle / 2);
-
                // shift hud if operating in view angle centered mode
                float shift_angle = 0;
                if(mode == STRAFEHUD_MODE_VIEW_CENTERED)
                {
-                       shift_angle = -currentangle;
+                       shift_angle = -angle;
                        bestangle += shift_angle;
                        changeangle += shift_angle;
                        opposite_bestangle += shift_angle;
                        opposite_changeangle += shift_angle;
                }
 
-               if(mode == STRAFEHUD_MODE_VIEW_CENTERED || straight_overturn)
-                       currentangle = 0;
-
-               currentangle = StrafeHUD_projectAngle(currentangle, hudangle, false);
-
                StrafeHUD_DrawStrafeMeter(
-                       speed, minspeed, shift_angle, wishangle, currentangle, changeangle, bestangle,
-                       bestangle_width, absolute_bestangle, absolute_prebestangle,
-                       opposite_bestangle, opposite_changeangle, immobile,
-                       opposite_direction, direction, hudangle);
+                       speed, bestspeed, frictionspeed, shift_angle, wishangle, changeangle, bestangle,
+                       absolute_bestangle, absolute_prebestangle, opposite_bestangle, opposite_changeangle,
+                       moving, opposite_direction, direction, hudangle);
 
                float text_offset_top;
                float text_offset_bottom;
@@ -420,9 +398,9 @@ void HUD_StrafeHUD()
                StrafeHUD_DrawDirectionIndicator(direction, opposite_direction, fwd);
 
                vector angle_indicator_info = StrafeHUD_DrawAngleIndicator(
-                       angle, wishangle, currentangle, bestangle, absolute_bestangle,
-                       absolute_prebestangle, opposite_bestangle, immobile,
-                       opposite_direction, direction, hudangle);
+                       angle, wishangle, bestangle, absolute_bestangle,
+                       absolute_prebestangle, opposite_bestangle, antiflicker_angle,
+                       moving, opposite_direction, direction, mode, hudangle);
 
                // unpack return value from vector
                float strafe_ratio = angle_indicator_info.x;
index 5dbc46d2488a962f10523933b7556fee81050191..6afc88e3c51ec2a76f2f18493ed2360952b62281 100644 (file)
@@ -7,7 +7,7 @@
 
 int autocvar_hud_panel_strafehud = 3;
 bool autocvar__hud_panel_strafehud_demo = false;
-bool autocvar_hud_panel_strafehud_dynamichud    = true;
+bool autocvar_hud_panel_strafehud_dynamichud = true;
 int autocvar_hud_panel_strafehud_mode = 0;
 float autocvar_hud_panel_strafehud_range = 90;
 int autocvar_hud_panel_strafehud_style = 2;
index 954ca668d6a9b5638f040f2d3ffbe11369b8bcd8..9f38f51ec7fa4f1527b830ac5c8e0fddf6d1b795 100644 (file)
@@ -3,17 +3,17 @@
 #include <client/draw.qh>
 
 void StrafeHUD_DrawStrafeMeter(
-       float speed, float minspeed, float shift_angle, float wishangle,
-       float currentangle, float changeangle, float bestangle, float bestangle_width,
-       float absolute_bestangle, float absolute_prebestangle,
-       float opposite_bestangle, float opposite_changeangle,
-       bool immobile, bool opposite_direction, int direction, float hudangle)
+       float speed, float bestspeed, float frictionspeed, float shift_angle, float wishangle,
+       float changeangle, float bestangle, float absolute_bestangle,
+       float absolute_prebestangle, float opposite_bestangle,
+       float opposite_changeangle, bool moving, bool opposite_direction,
+       int direction, float hudangle)
 {
        // the neutral zone fills the whole strafe bar
-       if(immobile)
+       if(!moving)
        {
                // draw neutral zone
-               if(panel_size.x > 0 && panel_size.y > 0 && autocvar_hud_panel_strafehud_bar_neutral_alpha * panel_fg_alpha > 0)
+               if(panel_size.x > 0 && panel_size.y > 0 && autocvar_hud_panel_strafehud_bar_neutral_alpha > 0)
                {
                        switch(autocvar_hud_panel_strafehud_style)
                        {
@@ -37,45 +37,42 @@ void StrafeHUD_DrawStrafeMeter(
        }
        else
        {
+               // calculate various zones of the strafe-o-meter
                float accelzone_left_startangle;
                float accelzone_right_startangle;
-               float accelzone_offsetangle;
                float preaccelzone_left_startangle;
                float preaccelzone_right_startangle;
-               float preaccelzone_offsetangle;
+               float neutral_startangle;
                float overturn_startangle;
 
-               // calculate various zones of the strafe-o-meter
-               if(autocvar_hud_panel_strafehud_bar_preaccel)
-                       preaccelzone_offsetangle = absolute_bestangle - absolute_prebestangle;
-               else
+               float accelzone_offsetangle = 90 - absolute_bestangle;
+               float preaccelzone_offsetangle = absolute_bestangle - absolute_prebestangle;
+               float neutral_offsetangle = 360;
+               float overturn_offsetangle = 180;
+
+               if(!autocvar_hud_panel_strafehud_bar_preaccel)
                        preaccelzone_offsetangle = 0;
 
-               accelzone_offsetangle = 90 - absolute_bestangle;
+               // assign starting angles and shift the current offset for every element
+               float current_startangle = 0;
 
-               float overturn_offsetangle = 180;
-               float neutral_offsetangle = 360 - accelzone_offsetangle * 2 - preaccelzone_offsetangle * 2 - overturn_offsetangle;
-               float neutral_startangle;
+               preaccelzone_right_startangle = current_startangle;
+               current_startangle += preaccelzone_offsetangle;
 
-               {
-                       float current_offsetangle = 0;
-                       preaccelzone_right_startangle = current_offsetangle;
-                       current_offsetangle += preaccelzone_offsetangle;
-
-                       accelzone_right_startangle = current_offsetangle;
-                       current_offsetangle += accelzone_offsetangle;
+               accelzone_right_startangle = current_startangle;
+               current_startangle += accelzone_offsetangle;
 
-                       overturn_startangle = current_offsetangle;
-                       current_offsetangle += overturn_offsetangle;
+               overturn_startangle = current_startangle;
+               current_startangle += overturn_offsetangle;
 
-                       accelzone_left_startangle = current_offsetangle;
-                       current_offsetangle += accelzone_offsetangle;
+               accelzone_left_startangle = current_startangle;
+               current_startangle += accelzone_offsetangle;
 
-                       preaccelzone_left_startangle = current_offsetangle;
-                       current_offsetangle += preaccelzone_offsetangle;
+               preaccelzone_left_startangle = current_startangle;
+               current_startangle += preaccelzone_offsetangle;
 
-                       neutral_startangle = current_offsetangle;
-               }
+               neutral_startangle = current_startangle;
+               neutral_offsetangle = 360 - current_startangle;
 
                // calculate how far off-center the strafe zones currently are
                shift_angle += neutral_offsetangle / 2 - wishangle;
@@ -139,15 +136,18 @@ void StrafeHUD_DrawStrafeMeter(
                        autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_NONE,
                        true, hudangle);
 
+               float minspeed = autocvar_hud_panel_strafehud_switch_minspeed;
+               if(minspeed < 0)
+                       minspeed = bestspeed + frictionspeed;
+
                // only draw indicators if minspeed is reached
-               if(autocvar_hud_panel_strafehud_switch && speed >= minspeed && bestangle_width > 0 && autocvar_hud_panel_strafehud_switch_alpha > 0)
+               if(autocvar_hud_panel_strafehud_switch && speed >= minspeed && autocvar_hud_panel_strafehud_switch_alpha > 0)
                {
                        // draw the change indicator(s)
-                       float offsetangle = !opposite_direction ? changeangle : opposite_changeangle;
-                       float opposite_offsetangle = !opposite_direction ? bestangle : opposite_bestangle;
+                       float offsetangle = opposite_direction ? opposite_changeangle : changeangle;
+                       float opposite_offsetangle = opposite_direction ? opposite_bestangle : bestangle;
 
-                       offsetangle = StrafeHUD_projectAngle(offsetangle, hudangle, false);
-                       opposite_offsetangle = StrafeHUD_projectAngle(opposite_offsetangle, hudangle, false);
+                       float bestangle_width = max(panel_size.x * autocvar_hud_panel_strafehud_switch_width, 1);
 
                        // remove change indicator width from offset
                        if(direction == STRAFEHUD_DIRECTION_LEFT)
@@ -184,14 +184,25 @@ void StrafeHUD_DrawStrafeMeter(
 }
 
 // draw the actual strafe angle
-vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle, float currentangle,
+// TODO: break this apart so that each angle indicator is drawn in an individual function call
+vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle,
        float bestangle, float absolute_bestangle, float absolute_prebestangle,
-       float opposite_bestangle, bool immobile, bool opposite_direction, int direction,
-       float hudangle)
+       float opposite_bestangle, float antiflicker_angle, bool moving, bool opposite_direction, int direction,
+       int mode, float hudangle)
 {
+       float currentangle = 0;
+       if(mode == STRAFEHUD_MODE_VELOCITY_CENTERED)
+       {
+               // avoid switching side too much at ±180° if within anti flicker is triggered
+               if(fabs(angle) <= (180 - antiflicker_angle))
+                       // bound to HUD area
+                       currentangle = bound(-hudangle / 2, angle, hudangle / 2);
+                       currentangle = StrafeHUD_projectAngle(currentangle, hudangle, false);
+       }
+
        vector currentangle_color = autocvar_hud_panel_strafehud_angle_neutral_color;
        float strafe_ratio = 0;
-       if(!immobile)
+       if(moving)
        {
                float moveangle = fabs(angle + wishangle);
 
@@ -289,6 +300,7 @@ vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle, float currenta
 }
 
 // draw the arrows on the angle indicator
+// TODO: break this apart so that each angle indicator is drawn in an individual function call
 vector StrafeHUD_DrawAngleIndicatorArrow(float currentangle, vector currentangle_size,
        vector currentangle_color, float ghost_angle, float angleheight_offset,
        int direction, float hudangle)
@@ -365,9 +377,10 @@ void StrafeHUD_DrawDirectionIndicator(int direction, bool opposite_direction, bo
        if(autocvar_hud_panel_strafehud_direction &&
           direction != STRAFEHUD_DIRECTION_NONE &&
           direction_size_vertical.x > 0 &&
-          autocvar_hud_panel_strafehud_direction_alpha * panel_fg_alpha > 0)
+          autocvar_hud_panel_strafehud_direction_alpha > 0)
        {
                bool indicator_direction = direction == STRAFEHUD_DIRECTION_LEFT;
+
                // invert left/right when strafing backwards or when strafing towards the opposite side indicated by the direction variable
                // if both conditions are true then it's inverted twice hence not inverted at all
                if(!fwd != opposite_direction)
index b6294b150d9fa77f708929b28df0adaab8f216b0..da527c1119d0acea8ce8fbbcc7bd10836ce664d2 100644 (file)
@@ -2,12 +2,11 @@
 #include "../strafehud.qh"
 
 vector StrafeHUD_DrawAngleIndicatorArrow(
-    float, vector, vector, float, float, int, float);
+       float, vector, vector, float, float, int, float);
 vector StrafeHUD_DrawAngleIndicator(
-    float, float, float, float, float, float,
-    float, bool, bool, int, float);
+       float, float, float, float, float,
+       float, float, bool, bool, int, int, float);
 void StrafeHUD_DrawDirectionIndicator(int, bool, bool);
 void StrafeHUD_DrawStrafeMeter(
-    float, float, float, float, float, float,
-    float, float, float, float, float, float,
-    bool, bool, int, float);
+       float, float, float, float, float, float, float,
+       float, float, float, float, bool, bool, int, float);
index 41c548c53a09d0847d3d77437a77114e1eb72653..430449e96362b87978e5318113c18393b5f61430 100644 (file)
@@ -3,25 +3,26 @@
 #include <client/draw.qh>
 
 // functions to make hud elements align perfectly in the hud area
-void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, float alpha, int type, int gradientType, bool doProject, float range)
+void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, float alpha, int type, int gradientType, bool projectWidth, float range)
 {
        float offset = StrafeHUD_angleToOffset(startangle % 360, range);
        float width = StrafeHUD_angleToWidth(offsetangle, range);
+       float mirror_offset;
+       float mirror_width;
 
-       float mirror_offset, mirror_width;
-       vector size = panel_size;
-       vector mirror_size = panel_size;
-       float overflow_width = 0, overflow_mirror_width = 0;
-       float original_width = width; // required for gradient
-
-       if(type == STRAFEHUD_STYLE_GRADIENT && gradientType == STRAFEHUD_GRADIENT_NONE)
-               type = STRAFEHUD_STYLE_DRAWFILL;
+       if(type == STRAFEHUD_STYLE_GRADIENT)
+       {
+               projectWidth = true; // must be fully projected for gradients
+               if(gradientType == STRAFEHUD_GRADIENT_NONE)
+                       type = STRAFEHUD_STYLE_DRAWFILL;
+       }
 
        if(alpha <= 0 && type != STRAFEHUD_STYLE_GRADIENT || width <= 0)
                return;
 
        // how much is hidden by the current hud angle
        float hidden_width = (360 - range) / range * panel_size.x;
+       float original_width = width; // required for gradient
 
        if(offset < 0)
        {
@@ -36,20 +37,21 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color,
                mirror_offset = max(offset - panel_size.x - hidden_width, 0);
        }
 
+       float overflow_width = 0;
        width = max(width, 0);
        if((offset + width) > panel_size.x)
        {
                overflow_width = (offset + width) - panel_size.x;
                width = panel_size.x - offset;
        }
+       vector size = panel_size;
        size.x = width;
 
        float original_offset = offset;
-       if(doProject)
-       {
-               if(size.x > 0) size.x = StrafeHUD_projectWidth(offset, size.x, range);
-               offset = StrafeHUD_projectOffset(offset, range, false);
-       }
+       if(projectWidth && size.x > 0)
+               size.x = StrafeHUD_projectWidth(offset, size.x, range);
+
+       offset = StrafeHUD_projectOffset(offset, range, false);
 
        if(mirror_offset < 0)
        {
@@ -57,20 +59,21 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color,
                mirror_offset = 0;
        }
 
+       float overflow_mirror_width = 0;
        mirror_width = max(mirror_width, 0);
        if((mirror_offset + mirror_width) > panel_size.x)
        {
                overflow_mirror_width = (mirror_offset + mirror_width) - panel_size.x;
                mirror_width = panel_size.x - mirror_offset;
        }
+       vector mirror_size = panel_size;
        mirror_size.x = mirror_width;
 
        float original_mirror_offset = mirror_offset;
-       if(doProject)
-       {
-               if(mirror_size.x > 0) mirror_size.x = StrafeHUD_projectWidth(mirror_offset, mirror_size.x, range);
-               mirror_offset = StrafeHUD_projectOffset(mirror_offset, range, false);
-       }
+       if(projectWidth && mirror_size.x > 0)
+               mirror_size.x = StrafeHUD_projectWidth(mirror_offset, mirror_size.x, range);
+
+       mirror_offset = StrafeHUD_projectOffset(mirror_offset, range, false);
 
        switch(type)
        {
@@ -127,12 +130,12 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color,
                        StrafeHUD_drawGradient(
                                color, autocvar_hud_panel_strafehud_bar_neutral_color,
                                mirror_size, original_width, mirror_offset, original_mirror_offset,
-                               alpha, gradient_mirror_offset, gradientType, doProject, range);
+                               alpha, gradient_mirror_offset, gradientType, range);
 
                        StrafeHUD_drawGradient(
                                color, autocvar_hud_panel_strafehud_bar_neutral_color,
                                size, original_width, offset, original_offset,
-                               alpha, gradient_offset, gradientType, doProject, range);
+                               alpha, gradient_offset, gradientType, range);
        }
 }
 
@@ -147,7 +150,8 @@ vector StrafeHUD_mixColors(vector color1, vector color2, float ratio)
        return mixedColor;
 }
 
-void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float original_offset, float alpha, float gradientOffset, int gradientType, bool doProject, float range)
+// FIXME: this is very bad for performance, there should be a better way to draw gradients
+void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float original_offset, float alpha, float gradientOffset, int gradientType, float range)
 {
        float color_ratio, alpha1, alpha2;
        vector segment_size = size;
@@ -161,8 +165,7 @@ void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float ori
                segment_size.x = min(size.x - i, 1); // each gradient segment is 1 unit wide except if there is less than 1 unit of gradient remaining
                segment_offset = offset + i;
                ratio_offset = segment_offset + segment_size.x / 2;
-               if(doProject)
-                       ratio_offset = StrafeHUD_projectOffset(ratio_offset, range, true);
+               ratio_offset = StrafeHUD_projectOffset(ratio_offset, range, true);
                ratio_offset += gradientOffset;
                ratio = (ratio_offset - original_offset) / original_width * (gradientType == STRAFEHUD_GRADIENT_BOTH ? 2 : 1);
                if(ratio > 1) ratio = 2 - ratio;
index f369adcc2d3e0d7bfd76362bda3ec5b02c36082b..3c7d5b973619e5baac77e94628f307620275620b 100644 (file)
@@ -2,7 +2,7 @@
 #include "../strafehud.qh"
 
 void StrafeHUD_drawStrafeHUD(float, float, vector, float, int, int, bool, float);
-void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, float, int, bool, float);
+void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, float, int, float);
 void StrafeHUD_drawStrafeArrow(vector, float, vector, float, bool, float);
 bool StrafeHUD_drawTextIndicator(string, float, vector, float, float, float, int);
 vector StrafeHUD_mixColors(vector, vector, float);
index dc6764ca676d80a92e348b88115406368295f48f..cba63904598d649e854ef0b22022203ca3fa515c 100644 (file)
@@ -12,9 +12,9 @@
 #include <lib/csqcmodel/common.qh> // for IS_PLAYER() macro
 #include <common/resources/cl_resources.qh> // IS_DEAD() macro
 
+// slick detector
 float StrafeHUD_DrawSlickDetector(entity e, bool onslick)
 {
-       // slick detector
        float slickdetector_height = bound(0, autocvar_hud_panel_strafehud_slickdetector_height, 1);
        slickdetector_height *= panel_size.y;
        if(autocvar_hud_panel_strafehud_slickdetector &&
@@ -30,7 +30,7 @@ float StrafeHUD_DrawSlickDetector(entity e, bool onslick)
 
                slickdetected = onslick; // do not need to traceline if already touching slick
 
-               // traceline into every direction
+               // traceline downwards into every direction
                trace_dphitq3surfaceflags = 0;
                vector traceorigin = e.origin + eZ * e.mins.z;
                for(float i = 0; i < 90 && !slickdetected; i += slicksteps)
index feaff4f1c872772220edb68b9663c52e3e587549..68f957eb81f4965ef1aefc3619f6f6b4001a9c37 100644 (file)
@@ -158,9 +158,9 @@ float DetectFrameTime()
        return dt;
 }
 
+// determine player wishdir
 float DetectWishAngle(vector movement, int keys, bool islocal)
 {
-       // determine player wishdir
        float wishangle;
        if(islocal) // if entity is local player
        {