]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/hagar_notfixed
authorMario <mario@smbclan.net>
Thu, 24 Mar 2016 20:08:41 +0000 (06:08 +1000)
committerMario <mario@smbclan.net>
Thu, 24 Mar 2016 20:08:41 +0000 (06:08 +1000)
# Conflicts:
# qcsrc/common/weapons/weapon/hagar.qc

1  2 
qcsrc/client/view.qc
qcsrc/common/weapons/weapon/hagar.qc

diff --combined qcsrc/client/view.qc
index 615ec0b29f666416f5dabc49de495e9c7d6987d6,ed675fc6b7cdd34409fabefd05378f44ce0eeec2..738aca2cfbccba1fdec36b2bc315a0783f2f6eb8
@@@ -1,33 -1,38 +1,38 @@@
+ #include "view.qh"
  
  #include "announcer.qh"
  #include "hud/all.qh"
  #include "mapvoting.qh"
  #include "scoreboard.qh"
  #include "shownames.qh"
- #include "quickmenu.qh"
+ #include "hud/panel/quickmenu.qh"
  
  #include "mutators/events.qh"
  
- #include "../common/anim.qh"
- #include "../common/constants.qh"
- #include "../common/debug.qh"
- #include "../common/mapinfo.qh"
+ #include <common/animdecide.qh>
+ #include <common/ent_cs.qh>
+ #include <common/anim.qh>
+ #include <common/constants.qh>
+ #include <common/debug.qh>
+ #include <common/mapinfo.qh>
  #include <common/gamemodes/all.qh>
- #include "../common/physics/player.qh"
- #include "../common/stats.qh"
- #include "../common/triggers/target/music.qh"
- #include "../common/teams.qh"
+ #include <common/physics/player.qh>
+ #include <common/stats.qh>
+ #include <common/triggers/target/music.qh>
+ #include <common/teams.qh>
  
  #include <common/vehicles/all.qh>
  #include <common/weapons/all.qh>
- #include "../common/viewloc.qh"
- #include "../common/minigames/cl_minigames.qh"
- #include "../common/minigames/cl_minigames_hud.qh"
+ #include <common/viewloc.qh>
+ #include <common/minigames/cl_minigames.qh>
+ #include <common/minigames/cl_minigames_hud.qh>
  
- #include "../lib/csqcmodel/cl_player.qh"
+ #include <lib/csqcmodel/cl_player.qh>
+ #include <lib/csqcmodel/cl_model.qh>
+ #include "csqcmodel_hooks.qh"
  
- #include "../lib/warpzone/client.qh"
- #include "../lib/warpzone/common.qh"
+ #include <lib/warpzone/client.qh>
+ #include <lib/warpzone/common.qh>
  
  #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
  
@@@ -40,14 -45,15 +45,15 @@@ float autocvar_cl_bobmodel_up
  
  float autocvar_cl_followmodel;
  float autocvar_cl_followmodel_speed = 0.3;
- float autocvar_cl_followmodel_limit = 1000;
+ float autocvar_cl_followmodel_limit = 135;
  float autocvar_cl_followmodel_velocity_lowpass = 0.05;
  float autocvar_cl_followmodel_highpass = 0.05;
  float autocvar_cl_followmodel_lowpass = 0.03;
+ bool autocvar_cl_followmodel_velocity_absolute;
  
  float autocvar_cl_leanmodel;
  float autocvar_cl_leanmodel_speed = 0.3;
- float autocvar_cl_leanmodel_limit = 1000;
+ float autocvar_cl_leanmodel_limit = 30;
  float autocvar_cl_leanmodel_highpass1 = 0.2;
  float autocvar_cl_leanmodel_highpass = 0.2;
  float autocvar_cl_leanmodel_lowpass = 0.05;
        lowpass(value.y, frac, ref_store.y, ref_out.y); \
  } MACRO_END
  
- #define lowpass2_limited(value, frac, limit, ref_store, ref_out) MACRO_BEGIN \
- { \
-       lowpass_limited(value.x, frac, limit, ref_store.x, ref_out.x); \
-       lowpass_limited(value.y, frac, limit, ref_store.y, ref_out.y); \
- } MACRO_END
  #define highpass2(value, frac, ref_store, ref_out) MACRO_BEGIN \
  { \
        highpass(value.x, frac, ref_store.x, ref_out.x); \
        highpass(value.z, frac, ref_store.z, ref_out.z); \
  } MACRO_END
  
- #define highpass3_limited(value, frac, limit, ref_store, ref_out) MACRO_BEGIN \
- { \
-       highpass_limited(value.x, frac, limit, ref_store.x, ref_out.x); \
-       highpass_limited(value.y, frac, limit, ref_store.y, ref_out.y); \
-       highpass_limited(value.z, frac, limit, ref_store.z, ref_out.z); \
- } MACRO_END
- #define lowpass3_limited(value, frac, limit, ref_store, ref_out) MACRO_BEGIN \
- { \
-       lowpass_limited(value.x, frac, limit, ref_store.x, ref_out.x); \
-       lowpass_limited(value.y, frac, limit, ref_store.y, ref_out.y); \
-       lowpass_limited(value.z, frac, limit, ref_store.z, ref_out.z); \
- } MACRO_END
- bool autocvar_cl_followmodel_velocity_absolute;
  void viewmodel_animate(entity this)
  {
        static float prevtime;
        bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
        static bool oldonground;
        static float hitgroundtime;
-       static float lastongroundtime;
        if (clonground)
        {
                float f = time; // cl.movecmd[0].time
                if (!oldonground)
                        hitgroundtime = f;
-               lastongroundtime = f;
        }
        oldonground = clonground;
  
                        vel = view.velocity;
                else
                {
-                       vector forward, right = '0 0 0', up = '0 0 0';
+                       vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
                        MAKEVECTORS(makevectors, view_angles, forward, right, up);
                        vel.x = view.velocity * forward;
                        vel.y = view.velocity * right * -1;
                        vel.z = view.velocity * up;
                }
  
+               vel.x = bound(vel_average.x - autocvar_cl_followmodel_limit, vel.x, vel_average.x + autocvar_cl_followmodel_limit);
+               vel.y = bound(vel_average.y - autocvar_cl_followmodel_limit, vel.y, vel_average.y + autocvar_cl_followmodel_limit);
+               vel.z = bound(vel_average.z - autocvar_cl_followmodel_limit, vel.z, vel_average.z + autocvar_cl_followmodel_limit);
                frac = avg_factor(autocvar_cl_followmodel_velocity_lowpass);
-               lowpass3_limited(vel, frac, autocvar_cl_followmodel_limit, vel_average, gunorg);
+               lowpass3(vel, frac, vel_average, gunorg);
  
                gunorg *= -autocvar_cl_followmodel_speed * 0.042;
  
                if(autocvar_cl_followmodel_velocity_absolute)
                {
                        vector fixed_gunorg;
-                       vector forward, right = '0 0 0', up = '0 0 0';
+                       vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
                        MAKEVECTORS(makevectors, view_angles, forward, right, up);
                        fixed_gunorg.x = gunorg * forward;
                        fixed_gunorg.y = gunorg * right * -1;
        {
                // calculate for swinging gun model
                // the gun bobs when running on the ground, but doesn't bob when you're in the air.
-               // Sajt: I tried to smooth out the transitions between bob and no bob, which works
-               // for the most part, but for some reason when you go through a message trigger or
-               // pick up an item or anything like that it will momentarily jolt the gun.
-               float bspeed;
-               float t = 1;
-               float s = time * autocvar_cl_bobmodel_speed;
+               static float bobmodel_scale = 0;
+               static float time_ofs = 0; // makes the effect always restart in the same way
                if (clonground)
                {
-                       if (time - hitgroundtime < 0.2)
-                       {
-                               // just hit the ground, speed the bob back up over the next 0.2 seconds
-                               t = time - hitgroundtime;
-                               t = bound(0, t, 0.2);
-                               t *= 5;
-                       }
+                       if (time - hitgroundtime > 0.05)
+                               bobmodel_scale = min(1, bobmodel_scale + frametime * 5);
                }
                else
+                       bobmodel_scale = max(0, bobmodel_scale - frametime * 5);
+               if(bobmodel_scale && xyspeed)
                {
-                       // recently left the ground, slow the bob down over the next 0.2 seconds
-                       t = time - lastongroundtime;
-                       t = 0.2 - bound(0, t, 0.2);
-                       t *= 5;
-               }
-               bspeed = xyspeed * 0.01;
-               vector gunorg = '0 0 0';
-               gunorg.y += bspeed * autocvar_cl_bobmodel_side * autocvar_cl_viewmodel_scale * sin(s) * t;
-               gunorg.z += bspeed * autocvar_cl_bobmodel_up * autocvar_cl_viewmodel_scale * cos(s * 2) * t;
+                       float bspeed = xyspeed * 0.01 * autocvar_cl_viewmodel_scale * bobmodel_scale;
+                       float s = (time - time_ofs) * autocvar_cl_bobmodel_speed;
+                       vector gunorg = '0 0 0';
+                       gunorg.y = bspeed * autocvar_cl_bobmodel_side * sin(s);
+                       gunorg.z = bspeed * autocvar_cl_bobmodel_up * cos(s * 2);
  
-               this.origin += gunorg;
+                       this.origin += gunorg;
+               }
+               else
+                       time_ofs = time;
        }
  }
  
@@@ -321,19 -300,21 +300,21 @@@ void viewmodel_draw(entity this
        {
                static string name_last;
                string name = wep.mdl;
-               if (name != name_last)
+               bool swap = name != name_last;
+               // if (swap)
                {
                        name_last = name;
-                       CL_WeaponEntity_SetModel(this, name);
+                       CL_WeaponEntity_SetModel(this, name, swap);
                        this.viewmodel_origin = this.origin;
                        this.viewmodel_angles = this.angles;
                }
                anim_update(this);
 -              if (!this.animstate_override)
 +              if (!this.animstate_override && !this.animstate_looping)
                        anim_set(this, this.anim_idle, true, false, false);
        }
        float f = 0; // 0..1; 0: fully active
-       float eta = (this.weapon_nextthink - time) / STAT(WEAPONRATEFACTOR);
+       float rate = STAT(WEAPONRATEFACTOR);
+       float eta = rate ? ((this.weapon_nextthink - time) / rate) : 0;
        if (eta <= 0) f = this.weapon_eta_last;
        else switch (this.state)
        {
  entity viewmodel;
  STATIC_INIT(viewmodel) {
      viewmodel = new(viewmodel);
-     make_pure(viewmodel);
  }
  
- entity porto;
- vector polyline[16];
- void Porto_Draw(entity this)
+ void Porto_Draw(entity this);
+ STATIC_INIT(Porto)
  {
-       vector p, dir, ang, q, nextdir;
-       float portal_number, portal1_idx;
-       if(activeweapon != WEP_PORTO || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL)
-               return;
-       if(WEP_CVAR(porto, secondary))
-               return;
-       if(intermission == 1)
-               return;
-       if(intermission == 2)
-               return;
-       if (STAT(HEALTH) <= 0)
-               return;
+       entity e = new_pure(porto);
+       e.draw = Porto_Draw;
+       e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+ }
  
-       dir = view_forward;
+ const int polyline_length = 16;
+ vector polyline[polyline_length];
+ void Porto_Draw(entity this)
+ {
+       if (activeweapon != WEP_PORTO) return;
+       if (spectatee_status) return;
+       if (WEP_CVAR(porto, secondary)) return;
+       if (intermission == 1) return;
+       if (intermission == 2) return;
+       if (STAT(HEALTH) <= 0) return;
  
-       if(angles_held_status)
+       vector pos = view_origin;
+       vector dir = view_forward;
+       if (angles_held_status)
        {
                makevectors(angles_held);
                dir = v_forward;
        }
  
-       p = view_origin;
+       polyline[0] = pos;
  
-       polyline[0] = p;
-       int idx = 1;
-       portal_number = 0;
-       nextdir = dir;
-       for (;;)
+       int portal_number = 0, portal1_idx = 1, portal_max = 2;
+       int n = 1 + 2;  // 2 lines == 3 points
+       for (int idx = 0; idx < n && idx < polyline_length - 1; )
        {
-               dir = nextdir;
-               traceline(p, p + 65536 * dir, true, porto);
-               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-                       return;
-               nextdir = dir - 2 * (dir * trace_plane_normal) * trace_plane_normal; // mirror dir at trace_plane_normal
-               p = trace_endpos;
-               polyline[idx] = p;
-               ++idx;
-               if(idx >= 16)
-                       return;
-               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
-                       continue;
-               ++portal_number;
-               ang = vectoangles2(trace_plane_normal, dir);
-               ang.x = -ang.x;
-               makevectors(ang);
-               if(!CheckWireframeBox(porto, p - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
-                       return;
-               if(portal_number == 1)
+               traceline(pos, pos + 65536 * dir, true, this);
+               dir = reflect(dir, trace_plane_normal);
+               pos = trace_endpos;
+               polyline[++idx] = pos;
+               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
                {
-                       portal1_idx = idx;
-                       if(portal_number >= 2)
-                               break;
+                       n += 1;
+                       continue;
                }
-       }
-       while(idx >= 2)
-       {
-               p = polyline[idx-2];
-               q = polyline[idx-1];
-               if(idx == 2)
-                       p = p - view_up * 16;
-               if(idx-1 >= portal1_idx)
+               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
                {
-                       Draw_CylindricLine(p, q, 4, "", 1, 0, '0 0 1', 0.5, DRAWFLAG_NORMAL, view_origin);
+                       n = max(2, idx);
+                       break;
                }
-               else
+               // check size
                {
-                       Draw_CylindricLine(p, q, 4, "", 1, 0, '1 0 0', 0.5, DRAWFLAG_NORMAL, view_origin);
+                       vector ang = vectoangles2(trace_plane_normal, dir);
+                       ang.x = -ang.x;
+                       makevectors(ang);
+                       if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                       {
+                               n = max(2, idx);
+                               break;
+                       }
                }
-               --idx;
+               portal_number += 1;
+               if (portal_number >= portal_max) break;
+               if (portal_number == 1) portal1_idx = idx;
+       }
+       for (int idx = 0; idx < n - 1; ++idx)
+       {
+               vector p = polyline[idx], q = polyline[idx + 1];
+               if (idx == 0) p -= view_up * 16;  // line from player
+               vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+               Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
        }
- }
- void Porto_Init()
- {
-       porto = new(porto);
-       make_pure(porto);
-       porto.draw = Porto_Draw;
-       porto.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
  }
  
  float drawtime;
@@@ -616,12 -580,8 +580,8 @@@ const float SHOTTYPE_HITENEMY = 4
  
  void TrueAim_Init()
  {
-       trueaim = new(trueaim);
-       make_pure(trueaim);
-       trueaim.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-       trueaim_rifle = new(trueaim_rifle);
-       make_pure(trueaim_rifle);
-       trueaim_rifle.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+       (trueaim = new_pure(trueaim)).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+       (trueaim_rifle = new_pure(trueaim_rifle)).dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
  }
  
  float EnemyHitCheck()
@@@ -882,10 -842,88 +842,88 @@@ void HitSound(
        }
  }
  
- void HUD_Crosshair()
- {SELFPARAM();
+ vector crosshair_getcolor(entity this, float health_stat)
+ {
        static float rainbow_last_flicker;
        static vector rainbow_prev_color;
+       vector wcross_color = '0 0 0';
+       switch(autocvar_crosshair_color_special)
+       {
+               case 1: // crosshair_color_per_weapon
+               {
+                       if(this)
+                       {
+                               wcross_color = this.wpcolor;
+                               break;
+                       }
+                       else { goto normalcolor; }
+               }
+               case 2: // crosshair_color_by_health
+               {
+                       float x = health_stat;
+                       //x = red
+                       //y = green
+                       //z = blue
+                       wcross_color.z = 0;
+                       if(x > 200)
+                       {
+                               wcross_color.x = 0;
+                               wcross_color.y = 1;
+                       }
+                       else if(x > 150)
+                       {
+                               wcross_color.x = 0.4 - (x-150)*0.02 * 0.4;
+                               wcross_color.y = 0.9 + (x-150)*0.02 * 0.1;
+                       }
+                       else if(x > 100)
+                       {
+                               wcross_color.x = 1 - (x-100)*0.02 * 0.6;
+                               wcross_color.y = 1 - (x-100)*0.02 * 0.1;
+                               wcross_color.z = 1 - (x-100)*0.02;
+                       }
+                       else if(x > 50)
+                       {
+                               wcross_color.x = 1;
+                               wcross_color.y = 1;
+                               wcross_color.z = 0.2 + (x-50)*0.02 * 0.8;
+                       }
+                       else if(x > 20)
+                       {
+                               wcross_color.x = 1;
+                               wcross_color.y = (x-20)*90/27/100;
+                               wcross_color.z = (x-20)*90/27/100 * 0.2;
+                       }
+                       else
+                       {
+                               wcross_color.x = 1;
+                               wcross_color.y = 0;
+                       }
+                       break;
+               }
+               case 3: // crosshair_color_rainbow
+               {
+                       if(time >= rainbow_last_flicker)
+                       {
+                               rainbow_prev_color = randomvec() * autocvar_crosshair_color_special_rainbow_brightness;
+                               rainbow_last_flicker = time + autocvar_crosshair_color_special_rainbow_delay;
+                       }
+                       wcross_color = rainbow_prev_color;
+                       break;
+               }
+ LABEL(normalcolor)
+               default: { wcross_color = stov(autocvar_crosshair_color); break; }
+       }
+       return wcross_color;
+ }
+ void HUD_Crosshair()
+ {SELFPARAM();
        entity e = this;
        float f, i, j;
        vector v;
                        wcross_name = strcat("gfx/crosshair", wcross_style);
  
                // MAIN CROSSHAIR COLOR DECISION
-               switch(autocvar_crosshair_color_special)
-               {
-                       case 1: // crosshair_color_per_weapon
-                       {
-                               if(e)
-                               {
-                                       wcross_color = e.wpcolor;
-                                       break;
-                               }
-                               else { goto normalcolor; }
-                       }
-                       case 2: // crosshair_color_by_health
-                       {
-                               float x = STAT(HEALTH);
-                               //x = red
-                               //y = green
-                               //z = blue
-                               wcross_color.z = 0;
-                               if(x > 200)
-                               {
-                                       wcross_color.x = 0;
-                                       wcross_color.y = 1;
-                               }
-                               else if(x > 150)
-                               {
-                                       wcross_color.x = 0.4 - (x-150)*0.02 * 0.4;
-                                       wcross_color.y = 0.9 + (x-150)*0.02 * 0.1;
-                               }
-                               else if(x > 100)
-                               {
-                                       wcross_color.x = 1 - (x-100)*0.02 * 0.6;
-                                       wcross_color.y = 1 - (x-100)*0.02 * 0.1;
-                                       wcross_color.z = 1 - (x-100)*0.02;
-                               }
-                               else if(x > 50)
-                               {
-                                       wcross_color.x = 1;
-                                       wcross_color.y = 1;
-                                       wcross_color.z = 0.2 + (x-50)*0.02 * 0.8;
-                               }
-                               else if(x > 20)
-                               {
-                                       wcross_color.x = 1;
-                                       wcross_color.y = (x-20)*90/27/100;
-                                       wcross_color.z = (x-20)*90/27/100 * 0.2;
-                               }
-                               else
-                               {
-                                       wcross_color.x = 1;
-                                       wcross_color.y = 0;
-                               }
-                               break;
-                       }
-                       case 3: // crosshair_color_rainbow
-                       {
-                               if(time >= rainbow_last_flicker)
-                               {
-                                       rainbow_prev_color = randomvec() * autocvar_crosshair_color_special_rainbow_brightness;
-                                       rainbow_last_flicker = time + autocvar_crosshair_color_special_rainbow_delay;
-                               }
-                               wcross_color = rainbow_prev_color;
-                               break;
-                       }
-                       :normalcolor
-                       default: { wcross_color = stov(autocvar_crosshair_color); break; }
-               }
+               wcross_color = crosshair_getcolor(e, STAT(HEALTH));
  
                if(autocvar_crosshair_effect_scalefade)
                {
  
  void HUD_Draw()
  {
-       vector rgb = '0 0 0';
-       float a = 1;
        if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
        {
-               rgb = MUTATOR_ARGV(0, vector);
-               a = MUTATOR_ARGV(0, float);
+               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, MUTATOR_ARGV(0, vector), autocvar_hud_colorflash_alpha * MUTATOR_ARGV(0, float), DRAWFLAG_ADDITIVE);
        }
        else if(STAT(FROZEN))
        {
-               rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
        }
-       drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
        if(!intermission)
        if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
        {
@@@ -1396,6 -1360,7 +1360,7 @@@ float vh_notice_time
  void WaypointSprite_Load();
  void CSQC_UpdateView(float w, float h)
  {SELFPARAM();
+     TC(int, w); TC(int, h);
        entity e;
        float fov;
        float f;
        if(myteam != prev_myteam)
        {
                myteamcolors = colormapPaletteColor(myteam, 1);
-               FOREACH(hud_panels, true, LAMBDA(it.update_time = time));
+               FOREACH(hud_panels, true, it.update_time = time);
                prev_myteam = myteam;
        }
  
  
                if(ons_roundlost)
                {
-                       FOREACH_ENTITY_CLASS("onslaught_generator", it.health <= 0, LAMBDA(
+                       FOREACH_ENTITY_CLASS("onslaught_generator", it.health <= 0, {
                                gen = it;
                                break;
-                       ));
+                       });
                        if(!gen)
                                ons_roundlost = false; // don't enforce the 3rd person camera if there is no dead generator to show
                }
           mousepos = mousepos*0.5 + getmousepos();
         */
  
-       FOREACH_ENTITY(it.draw, LAMBDA(it.draw(it)));
+       FOREACH_ENTITY(it.draw, it.draw(it));
  
        addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
        renderscene();
          } else */
  
        // draw 2D entities
-       FOREACH_ENTITY(it.draw2d, LAMBDA(it.draw2d(it)));
+       FOREACH_ENTITY(it.draw2d, it.draw2d(it));
        Draw_ShowNames_All();
        Debug_Draw();
  
index f7dcef740324985739368efa5ad7b77da1a86721,2d5085fb115c82df9083585c3fefd6a4372bf0e1..2ed0ca7140ed6995069c37b793eee55eb099ebfe
@@@ -130,7 -130,7 +130,7 @@@ void W_Hagar_Attack(Weapon thiswep
  
        W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(hagar, ammo));
  
-       W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
+       W_SetupShot(self, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
  
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
@@@ -172,7 -172,7 +172,7 @@@ void W_Hagar_Attack2(Weapon thiswep
  
        W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo));
  
-       W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(self, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
  
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
@@@ -224,7 -224,7 +224,7 @@@ void W_Hagar_Attack2_Load_Release(.enti
  
        weapon_prepareattack_do(self, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
  
-       W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(self, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
        forward = v_forward;
@@@ -309,9 -309,9 +309,9 @@@ void W_Hagar_Attack2_Load(Weapon thiswe
  
        bool stopped = loaded || !enough_ammo;
  
-       if(self.BUTTON_ATCK2)
+       if(PHYS_INPUT_BUTTON_ATCK2(self))
        {
-               if(self.BUTTON_ATCK && WEP_CVAR_SEC(hagar, load_abort))
+               if(PHYS_INPUT_BUTTON_ATCK(self) && WEP_CVAR_SEC(hagar, load_abort))
                {
                        if(self.hagar_load)
                        {
                }
  
                // release if player let go of button or if they've held it in too long
-               if(!self.BUTTON_ATCK2 || (stopped && self.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
+               if(!PHYS_INPUT_BUTTON_ATCK2(self) || (stopped && self.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
                {
                        self.(weaponentity).state = WS_READY;
                        W_Hagar_Attack2_Load_Release(weaponentity);
        }
  }
  
-       int theframe = WFRAME_FIRE1;
 +void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 +{
 +      if(!(fire & 1) || actor.hagar_load || actor.hagar_loadblock)
 +      {
 +              w_ready(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +
 +      if(!thiswep.wr_checkammo1(thiswep))
 +      if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
 +      {
 +              W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
 +              w_ready(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +
 +      W_Hagar_Attack(thiswep);
 +
 +      int slot = weaponslot(weaponentity);
-               METHOD(Hagar, wr_aim, void(entity thiswep))
-               {
-                       if(random()>0.15)
-                               self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
-                       else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
-                               self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
-               }
-               METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
-               {
-                       float loadable_secondary;
-                       loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
-                       if(loadable_secondary)
-                               W_Hagar_Attack2_Load(thiswep, weaponentity); // must always run each frame
-                       if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
-                               thiswep.wr_reload(thiswep, actor, weaponentity);
-                       } else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
-                       {
-                               if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
-                                       W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
-                       }
-                       else if((fire & 2) && !loadable_secondary && WEP_CVAR(hagar, secondary))
-                       {
-                               if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire)))
-                               {
-                                       W_Hagar_Attack2(thiswep);
-                                       weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
-                               }
-                       }
-               }
-               METHOD(Hagar, wr_gonethink, void(entity thiswep))
-               {
-                       // we lost the weapon and want to prepare switching away
-                       if(self.hagar_load)
-                       {
-                               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-                               self.(weaponentity).state = WS_READY;
-                               W_Hagar_Attack2_Load_Release(weaponentity);
-                       }
-               }
-               METHOD(Hagar, wr_setup, void(entity thiswep))
-               {
-                       self.hagar_loadblock = false;
-                       if(self.hagar_load)
-                       {
-                               W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
-                               self.hagar_load = 0;
-                       }
-               }
-               METHOD(Hagar, wr_checkammo1, bool(entity thiswep))
-               {
-                       float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
-                       ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
-                       return ammo_amount;
-               }
-               METHOD(Hagar, wr_checkammo2, bool(entity thiswep))
-               {
-                       float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
-                       ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
-                       return ammo_amount;
-               }
-               METHOD(Hagar, wr_resetplayer, void(entity thiswep))
-               {
-                       self.hagar_load = 0;
-               }
-               METHOD(Hagar, wr_playerdeath, void(entity thiswep))
-               {
-                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-                       // if we have any rockets loaded when we die, release them
-                       if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
-                               W_Hagar_Attack2_Load_Release(weaponentity);
-               }
-               METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
-               {
-                       if(!self.hagar_load) // require releasing loaded rockets first
-                               W_Reload(self, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND(RELOAD));
-               }
-               METHOD(Hagar, wr_suicidemessage, int(entity thiswep))
-               {
-                       return WEAPON_HAGAR_SUICIDE;
-               }
-               METHOD(Hagar, wr_killmessage, int(entity thiswep))
-               {
-                       if(w_deathtype & HITTYPE_SECONDARY)
-                               return WEAPON_HAGAR_MURDER_BURST;
-                       else
-                               return WEAPON_HAGAR_MURDER_SPRAY;
-               }
 +      ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hagar, refire) * W_WeaponRateFactor();
++      int theframe = WFRAME_FIRE1;
 +      entity this = actor.(weaponentity);
 +      if(this)
 +      {
 +              if(this.wframe == WFRAME_FIRE1)
 +                      theframe = WFRAME_DONTCHANGE;
 +      }
 +      weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
 +}
 +
 -    } else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
 -    {
 -        if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hagar, refire)))
 -        {
 -            W_Hagar_Attack(thiswep);
 -            weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
 -        }
+ METHOD(Hagar, wr_aim, void(entity thiswep))
+ {
+     SELFPARAM();
+     if(random()>0.15)
+         PHYS_INPUT_BUTTON_ATCK(self) = bot_aim(self, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+     else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
+         PHYS_INPUT_BUTTON_ATCK2(self) = bot_aim(self, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+ }
+ METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+ {
+     float loadable_secondary;
+     loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
+     if(loadable_secondary)
+         W_Hagar_Attack2_Load(thiswep, weaponentity); // must always run each frame
+     if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
+         thiswep.wr_reload(thiswep, actor, weaponentity);
+     }
++    else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
++      {
++              if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
++                      W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
++      }
+     else if((fire & 2) && !loadable_secondary && WEP_CVAR(hagar, secondary))
+     {
+         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire)))
+         {
+             W_Hagar_Attack2(thiswep);
+             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
+         }
+     }
+ }
+ METHOD(Hagar, wr_gonethink, void(entity thiswep))
+ {
+     SELFPARAM();
+     // we lost the weapon and want to prepare switching away
+     if(self.hagar_load)
+     {
+         .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+         self.(weaponentity).state = WS_READY;
+         W_Hagar_Attack2_Load_Release(weaponentity);
+     }
+ }
+ METHOD(Hagar, wr_setup, void(entity thiswep))
+ {
+     SELFPARAM();
+     self.hagar_loadblock = false;
+     if(self.hagar_load)
+     {
+         W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
+         self.hagar_load = 0;
+     }
+ }
+ METHOD(Hagar, wr_checkammo1, bool(entity thiswep))
+ {
+     SELFPARAM();
+     float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
+     ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
+     return ammo_amount;
+ }
+ METHOD(Hagar, wr_checkammo2, bool(entity thiswep))
+ {
+     SELFPARAM();
+     float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
+     ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+     return ammo_amount;
+ }
+ METHOD(Hagar, wr_resetplayer, void(entity thiswep))
+ {
+     SELFPARAM();
+     self.hagar_load = 0;
+ }
+ METHOD(Hagar, wr_playerdeath, void(entity thiswep))
+ {
+     SELFPARAM();
+     .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+     // if we have any rockets loaded when we die, release them
+     if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
+         W_Hagar_Attack2_Load_Release(weaponentity);
+ }
+ METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+ {
+     SELFPARAM();
+     if(!self.hagar_load) // require releasing loaded rockets first
+         W_Reload(self, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
+ }
+ METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
+ {
+     return WEAPON_HAGAR_SUICIDE;
+ }
+ METHOD(Hagar, wr_killmessage, Notification(entity thiswep))
+ {
+     if(w_deathtype & HITTYPE_SECONDARY)
+         return WEAPON_HAGAR_MURDER_BURST;
+     else
+         return WEAPON_HAGAR_MURDER_SPRAY;
+ }
  
  #endif
  #ifdef CSQC
  
-               METHOD(Hagar, wr_impacteffect, void(entity thiswep))
-               {
-                       vector org2;
-                       org2 = w_org + w_backoff * 6;
-                       pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
-                       if(!w_issilent)
-                       {
-                               if(w_random<0.15)
-                                       sound(self, CH_SHOTS, SND_HAGEXP1, VOL_BASE, ATTN_NORM);
-                               else if(w_random<0.7)
-                                       sound(self, CH_SHOTS, SND_HAGEXP2, VOL_BASE, ATTN_NORM);
-                               else
-                                       sound(self, CH_SHOTS, SND_HAGEXP3, VOL_BASE, ATTN_NORM);
-                       }
-               }
+ METHOD(Hagar, wr_impacteffect, void(entity thiswep))
+ {
+     SELFPARAM();
+     vector org2;
+     org2 = w_org + w_backoff * 6;
+     pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
+     if(!w_issilent)
+     {
+         if(w_random<0.15)
+             sound(self, CH_SHOTS, SND_HAGEXP1, VOL_BASE, ATTN_NORM);
+         else if(w_random<0.7)
+             sound(self, CH_SHOTS, SND_HAGEXP2, VOL_BASE, ATTN_NORM);
+         else
+             sound(self, CH_SHOTS, SND_HAGEXP3, VOL_BASE, ATTN_NORM);
+     }
+ }
  
  #endif
  #endif