Merge branch 'terencehill/bot_ai' into 'master'
authorMario <zacjardine@y7mail.com>
Mon, 22 Jan 2018 11:28:22 +0000 (11:28 +0000)
committerMario <zacjardine@y7mail.com>
Mon, 22 Jan 2018 11:28:22 +0000 (11:28 +0000)
Bot AI improvements

See merge request xonotic/xonotic-data.pk3dir!513

20 files changed:
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/view.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/physics/player.qc
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/common/triggers/func/door.qc
qcsrc/common/triggers/func/door_rotating.qc
qcsrc/common/triggers/func/door_secret.qc
qcsrc/common/triggers/trigger/multi.qc
qcsrc/common/viewloc.qc
qcsrc/common/weapons/weapon/crylink.qh
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/mutators/events.qh

index b52624b7026df8b2f7545ee9136e86690d68e087..0360eb07e639795ae1b23709617ef05ca2e28caf 100644 (file)
@@ -362,16 +362,18 @@ void Cmd_Scoreboard_Help()
 "ping pl name |" \
 " -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
 " -teams,lms/deaths +ft,tdm/deaths" \
+" +tdm/sum" \
 " -teams,lms,rc,cts,inv,ka/suicides +ft,tdm/suicides ?+rc,inv/suicides" \
 " -cts,dm,tdm,ka,ft/frags" /* tdm already has this in "score" */ \
 " +tdm,ft,dom,ons,as/teamkills"\
 " -rc,cts,nb/dmg -rc,cts,nb/dmgtaken" \
-" +ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes" \
+" +ctf/pickups +ctf/fckills +ctf/returns +ctf/caps +ons/takes +ons/caps" \
 " +lms/lives +lms/rank" \
-" +kh/caps +kh/pushes +kh/destroyed" \
+" +kh/kckills +kh/losses +kh/caps" \
 " ?+rc/laps ?+rc/time +rc,cts/fastest" \
 " +as/objectives +nb/faults +nb/goals" \
 " +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
+" +dom/ticks +dom/takes" \
 " -lms,rc,cts,inv,nb/score"
 
 void Cmd_Scoreboard_SetFields(int argc)
index 95a437e926dac488d40dfe96b8e879c5df7bcaf7..6a294d5ad5d35322c4576e063a844bcc0da16a15 100644 (file)
@@ -979,7 +979,7 @@ void HUD_Crosshair(entity this)
        float f, i, j;
        vector v;
        if(!scoreboard_active && !camera_active && intermission != 2 && !STAT(GAME_STOPPED) &&
-               spectatee_status != -1 && !csqcplayer.viewloc && !MUTATOR_CALLHOOK(DrawCrosshair) &&
+               spectatee_status != -1 && (!csqcplayer.viewloc || (!spectatee_status && (csqcplayer.viewloc.spawnflags & VIEWLOC_FREEAIM))) && !MUTATOR_CALLHOOK(DrawCrosshair) &&
                !HUD_MinigameMenu_IsOpened() )
        {
                if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
@@ -1010,7 +1010,10 @@ void HUD_Crosshair(entity this)
                float shottype;
 
                // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
-               wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward);
+               if(csqcplayer.viewloc && (csqcplayer.viewloc.spawnflags & VIEWLOC_FREEAIM))
+                       wcross_origin = viewloc_mousepos;
+               else
+                       wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward);
                wcross_origin.z = 0;
                if(autocvar_crosshair_hittest)
                {
@@ -1489,8 +1492,8 @@ void ViewLocation_Mouse()
        viewloc_mousepos.x = bound(0, viewloc_mousepos.x, vid_conwidth);
        viewloc_mousepos.y = bound(0, viewloc_mousepos.y, vid_conheight);
 
-       float cursor_alpha = 1 - autocvar__menu_alpha;
-       draw_cursor(viewloc_mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
+       //float cursor_alpha = 1 - autocvar__menu_alpha;
+       //draw_cursor(viewloc_mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
 }
 
 bool ov_enabled;
index 473e36e1057589e689c3f961645f7721126231e1..85bef1d49c4562a40b68dbd4e5f146551a523422 100644 (file)
@@ -178,6 +178,11 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, MakePlayerObserver)
        instagib_stop_countdown(player);
 }
 
+MUTATOR_HOOKFUNCTION(mutator_instagib, ForbidRandomStartWeapons)
+{
+       return true;
+}
+
 MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
@@ -387,7 +392,7 @@ void replace_with_insta_cells(entity item)
 {
        entity e = new(item_vaporizer_cells);
        setorigin(e, item.origin);
-       e.noalign = item.noalign;
+       e.noalign = Item_ShouldKeepPosition(item);
        e.cnt = item.cnt;
        e.team = item.team;
        e.spawnfunc_checked = true;
index ac06a8f7747160259588667e74a20ba33878da9e..d6796fc0590e0581be335989330a384934bee600 100644 (file)
@@ -15,6 +15,11 @@ MUTATOR_HOOKFUNCTION(melee_only, SetWeaponArena)
        M_ARGV(0, string) = "off";
 }
 
+MUTATOR_HOOKFUNCTION(melee_only, ForbidRandomStartWeapons)
+{
+       return true;
+}
+
 MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
 {
        return true;
index 92e16b48d22e04bc65a49f33b12dbdacbf17eee3..3dc7e4e0e3e050c4eb7e72d838945492aa552750 100644 (file)
@@ -1273,30 +1273,27 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
                }
        }
 
-       float n = 0;
+       int n = 0;
        entity o = NULL;
        if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
                n = -1;
-       else
+       else if(STAT(FROZEN, player) == 3)
        {
                vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
                n = 0;
                FOREACH_CLIENT(IS_PLAYER(it) && it != player, {
-                       if(!IS_DEAD(it))
-                       if(STAT(FROZEN, it) == 0)
-                       if(SAME_TEAM(it, player))
+                       if(!IS_DEAD(it) && STAT(FROZEN, it) == 0 && SAME_TEAM(it, player))
                        if(boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
                        {
                                if(!o)
                                        o = it;
-                               if(STAT(FROZEN, player) == 1)
-                                       it.reviving = true;
+                               it.reviving = true;
                                ++n;
                        }
                });
        }
 
-       if(n && STAT(FROZEN, player) == 3) // OK, there is at least one teammate reviving us
+       if(n > 0 && STAT(FROZEN, player) == 3) // OK, there is at least one teammate reviving us
        {
                player.revive_progress = bound(0, player.revive_progress + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
                SetResourceAmount(player, RESOURCE_HEALTH, max(1, player.revive_progress * start_health));
index 886740aedcea031e9d31632b17c3a47fb7937fa4..eb14a3159efd0f9f9e4e6fbdcc46cecb6718cb0e 100644 (file)
@@ -290,6 +290,11 @@ MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
                NIX_GiveCurrentWeapon(player);
 }
 
+MUTATOR_HOOKFUNCTION(nix, ForbidRandomStartWeapons)
+{
+       return true;
+}
+
 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
index 5eef8f2e37b4b49c96bce413c564cf2ebcbf9b28..5611042b0b3100f1bb8cb0dcd2e06e546fa9720a 100644 (file)
@@ -167,6 +167,11 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
        PHYS_INPUT_BUTTON_ATCK2(player) = false;
 }
 
+MUTATOR_HOOKFUNCTION(ok, ForbidRandomStartWeapons)
+{
+       return true;
+}
+
 MUTATOR_HOOKFUNCTION(ok, PlayerWeaponSelect)
 {
        entity player = M_ARGV(0, entity);
@@ -189,51 +194,6 @@ MUTATOR_HOOKFUNCTION(ok, PlayerWeaponSelect)
        }
 }
 
-void self_spawnfunc_weapon_hmg(entity this) { spawnfunc_weapon_hmg(this); }
-void self_spawnfunc_weapon_rpc(entity this) { spawnfunc_weapon_rpc(this); }
-
-MUTATOR_HOOKFUNCTION(ok, OnEntityPreSpawn)
-{
-       entity ent = M_ARGV(0, entity);
-
-       if(autocvar_g_powerups)
-       if(autocvar_g_overkill_powerups_replace)
-       {
-               if(ent.classname == "item_strength")
-               {
-                       entity wep = new(weapon_hmg);
-                       setorigin(wep, ent.origin);
-                       setmodel(wep, MDL_OK_HMG);
-                       wep.ok_item = true;
-                       wep.noalign = Item_ShouldKeepPosition(ent);
-                       wep.cnt = ent.cnt;
-                       wep.team = ent.team;
-                       wep.respawntime = g_pickup_respawntime_superweapon;
-                       wep.pickup_anyway = true;
-                       wep.spawnfunc_checked = true;
-                       setthink(wep, self_spawnfunc_weapon_hmg);
-                       wep.nextthink = time + 0.1;
-                       return true;
-               }
-               else if(ent.classname == "item_shield")
-               {
-                       entity wep = new(weapon_rpc);
-                       setorigin(wep, ent.origin);
-                       setmodel(wep, MDL_OK_RPC);
-                       wep.ok_item = true;
-                       wep.noalign = Item_ShouldKeepPosition(ent);
-                       wep.cnt = ent.cnt;
-                       wep.team = ent.team;
-                       wep.respawntime = g_pickup_respawntime_superweapon;
-                       wep.pickup_anyway = true;
-                       wep.spawnfunc_checked = true;
-                       setthink(wep, self_spawnfunc_weapon_rpc);
-                       wep.nextthink = time + 0.1;
-                       return true;
-               }
-       }
-}
-
 bool ok_HandleItemWaypoints(entity e)
 {
        if(!autocvar_g_overkill_itemwaypoints)
@@ -266,9 +226,42 @@ MUTATOR_HOOKFUNCTION(ok, FilterItem)
 {
        entity item = M_ARGV(0, entity);
 
-       if(item.ok_item)
+       if (item.ok_item)
+       {
                return false;
-
+       }
+       if (!autocvar_g_powerups || !autocvar_g_overkill_powerups_replace)
+       {
+               return true;
+       }
+       if (item.classname == "item_strength")
+       {
+               entity wep = new(weapon_hmg);
+               setorigin(wep, item.origin);
+               wep.ok_item = true;
+               wep.noalign = Item_ShouldKeepPosition(item);
+               wep.cnt = item.cnt;
+               wep.team = item.team;
+               wep.respawntime = g_pickup_respawntime_superweapon;
+               wep.pickup_anyway = true;
+               wep.spawnfunc_checked = true;
+               Item_Initialize(wep, "weapon_hmg");
+               return true;
+       }
+       else if (item.classname == "item_shield")
+       {
+               entity wep = new(weapon_rpc);
+               setorigin(wep, item.origin);
+               wep.ok_item = true;
+               wep.noalign = Item_ShouldKeepPosition(item);
+               wep.cnt = item.cnt;
+               wep.team = item.team;
+               wep.respawntime = g_pickup_respawntime_superweapon;
+               wep.pickup_anyway = true;
+               wep.spawnfunc_checked = true;
+               Item_Initialize(wep, "weapon_rpc");
+               return true;
+       }
        return true;
 }
 
index 20c580a8591b0e371981d671ba208a459229e2b2..7d3cab007b508fa6dafceb84a14585d0fd68f327 100644 (file)
@@ -21,7 +21,7 @@ float Physics_ClientOption(entity this, string option, float defaultval)
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
-       if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
+       if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default && autocvar_g_physics_clientselect_default != "")
        {
                string s = strcat("g_physics_", autocvar_g_physics_clientselect_default, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
index feefd10985aa37763770520146704e307b78ae87..e13df065a477b5f0f95a7370c484c5968a444ba4 100644 (file)
@@ -37,6 +37,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
 #ifdef CSQC
 bool autocvar_cl_ghost_items_vehicle = true;
 .vector item_glowmod;
+.bool item_simple; // probably not really needed, but better safe than sorry
 void Item_SetAlpha(entity this)
 {
        bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
@@ -96,14 +97,16 @@ void ItemDraw(entity this)
     {
         if(this.ItemStatus & ITS_ANIMATE1)
         {
-            this.angles += this.avelocity * frametime;
+               if(!this.item_simple)
+               this.angles += this.avelocity * frametime;
             float fade_in = bound(0, time - this.onground_time, 1);
             setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
         }
 
         if(this.ItemStatus & ITS_ANIMATE2)
         {
-            this.angles += this.avelocity * frametime;
+               if(!this.item_simple)
+               this.angles += this.avelocity * frametime;
             float fade_in = bound(0, time - this.onground_time, 1);
             setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
         }
@@ -112,19 +115,6 @@ void ItemDraw(entity this)
     Item_SetAlpha(this);
 }
 
-void ItemDrawSimple(entity this)
-{
-    if(this.gravity)
-    {
-        Movetype_Physics_MatchServer(this, false);
-
-        if(IS_ONGROUND(this))
-            this.gravity = 0;
-    }
-
-    Item_SetAlpha(this);
-}
-
 void Item_PreDraw(entity this)
 {
        if(warpzone_warpzones_exist)
@@ -228,11 +218,12 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
 
         this.mdl = "";
         string _fn = ReadString();
+        this.item_simple = false; // reset it!
 
         if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
         {
             string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
-            this.draw = ItemDrawSimple;
+            this.item_simple = true;
 
             if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3")))
                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3"));
@@ -244,12 +235,12 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
                 this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".mdl"));
             else
             {
-                this.draw = ItemDraw;
+                this.item_simple = false;
                 LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
             }
         }
 
-        if(this.draw != ItemDrawSimple)
+        if(!this.item_simple)
             this.mdl = strzone(_fn);
 
 
index 5d815cef928419eebc8b281fbba3e2423d275cbe..d2f44c61daa8e6544f44f47f4f92a61c54907218 100644 (file)
@@ -46,7 +46,6 @@ string autocvar_cl_simpleitems_postfix = "_simple";
 .vector colormod;
 
 void ItemDraw(entity this);
-void ItemDrawSimple(entity this);
 
 #endif
 #ifdef SVQC
index 392ab3e5f5f46b883793a34745656298176606b5..bb15503c7f801686a3a1ee3af473de786923fc3c 100644 (file)
@@ -765,6 +765,7 @@ spawnfunc(func_door)
 
        if (this.health)
        {
+               //this.canteamdamage = true; // TODO
                this.takedamage = DAMAGE_YES;
                this.event_damage = door_damage;
        }
index 2c72dc9cf07c1b249d91648683f0e3f4396017a9..c61a02686650eb56ae3a138d3cace85fed2a99b0 100644 (file)
@@ -109,6 +109,7 @@ spawnfunc(func_door_rotating)
 
        if (this.health)
        {
+               //this.canteamdamage = true; // TODO
                this.takedamage = DAMAGE_YES;
                this.event_damage = door_damage;
        }
index 0bad196abf3a57a79a4fbac2637170f35321bdf6..6f2d101ef9a914b61bae21278a6c5fa1c386b6a5 100644 (file)
@@ -228,6 +228,7 @@ spawnfunc(func_door_secret)
 
        if (this.spawnflags & SECRET_YES_SHOOT)
        {
+               //this.canteamdamage = true; // TODO
                this.health = 10000;
                this.takedamage = DAMAGE_YES;
                this.event_damage = fd_secret_damage;
index 5e8c641be542735efe020f155f2d7ff556f7dcbc..2f32e50fa50b92d8396a72293df0022c07413420 100644 (file)
@@ -104,6 +104,9 @@ void multi_eventdamage(entity this, entity inflictor, entity attacker, float dam
        if(this.spawnflags & DOOR_NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
+       if(this.team)
+               if(((this.spawnflags & 4) == 0) == (this.team != attacker.team))
+                       return;
        this.health = this.health - damage;
        if (this.health <= 0)
        {
@@ -169,6 +172,7 @@ spawnfunc(trigger_multiple)
        {
                if (this.spawnflags & SPAWNFLAG_NOTOUCH)
                        objerror (this, "health and notouch don't make sense\n");
+               this.canteamdamage = true;
                this.max_health = this.health;
                this.event_damage = multi_eventdamage;
                this.takedamage = DAMAGE_YES;
index 11dab52a30e6651d99cbf3b4527edebfea00226b..fd7937b5208d7f9dbd2f9aa9afcb2f99bacd99ad 100644 (file)
@@ -175,7 +175,7 @@ void viewloc_SetViewLocation()
                        } else {
                                vector mpos = CursorToWorldCoord(viewloc_mousepos);
                                mpos.x = view.origin.x; // replace the cursor's x position with the player's
-                               view_angle = aim_vec(view.origin, mpos); // get new angles
+                               view_angle = aim_vec(view.origin + view.view_ofs, mpos); // get new angles
                        }
                        view.angles_y = view_angle.y;
                        setproperty(VF_CL_VIEWANGLES, view_angle);
index 5ecef08d9f48bed31aa471cafefe95db1b158666..e48bf5fb3481e8db22c4698662997a648adc3db0 100644 (file)
@@ -4,7 +4,7 @@ CLASS(Crylink, Weapon)
 /* spawnfunc */ ATTRIB(Crylink, m_canonical_spawnfunc, string, "weapon_crylink");
 /* ammotype  */ ATTRIB(Crylink, ammo_type, int, RESOURCE_CELLS);
 /* impulse   */ ATTRIB(Crylink, impulse, int, 6);
-/* flags     */ ATTRIB(Crylink, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_CANCLIMB | WEP_FLAG_NODUAL);
+/* flags     */ ATTRIB(Crylink, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_CANCLIMB);
 /* rating    */ ATTRIB(Crylink, bot_pickupbasevalue, float, 6000);
 /* color     */ ATTRIB(Crylink, wpcolor, vector, '1 0.5 1');
 /* modelname */ ATTRIB(Crylink, mdl, string, "crylink");
index 14291d2510f7eae5261e65c35545588e3e1882e3..bffd503e5e27de3cf4f6eb6bdecb01adc149e5a2 100644 (file)
@@ -558,8 +558,11 @@ void PutPlayerInServer(entity this)
                this.health = start_health;
                this.armorvalue = start_armorvalue;
                this.weapons = start_weapons;
-               GiveRandomWeapons(this, random_start_weapons_count,
-                       autocvar_g_random_start_weapons, random_start_ammo);
+               if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
+               {
+                       GiveRandomWeapons(this, random_start_weapons_count,
+                               autocvar_g_random_start_weapons, random_start_ammo);
+               }
        }
        SetSpectatee_status(this, 0);
 
index 7ddea9f5ea8f4bd52b60dbf3997003d0e3fc2b44..e9cf6ee286a7d8831806504435737977436d8e08 100644 (file)
@@ -222,6 +222,8 @@ int have_team_spawns_forteams; // if Xth bit is 1 then team X has spawns else it
 // set when showing a kill countdown
 .entity killindicator;
 
+.bool canteamdamage;
+
 void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
 
 float lockteams;
index c0ff6b3f4ebd6c1a833f45c3b2f880ff06f1f442..029660c2bf05c2e98975f609e8c35d943d4f168d 100644 (file)
@@ -698,7 +698,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                                                                        force = '0 0 0';
                                                        }
                                                }
-                                               else
+                                               else if(!targ.canteamdamage)
                                                        damage = 0;
                                        }
                                }
index 6e3448066e5d49c7d43aac261bb8cf0a6a2f5148..fb452c3399b9bb4ab39721abb574ec32944ccff4 100644 (file)
@@ -24,6 +24,12 @@ MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
     /**/
 MUTATOR_HOOKABLE(ForbidSpawn, EV_ForbidSpawn);
 
+/** called when player spawns to determine whether to give them random start weapons. Return true to forbid giving them. */
+#define EV_ForbidRandomStartWeapons(i, o) \
+       /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+    /**/
+MUTATOR_HOOKABLE(ForbidRandomStartWeapons, EV_ForbidRandomStartWeapons);
+
 /** called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here) */
 #define EV_PlayerSpawn(i, o) \
        /** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \