Merge branch 'master' into terencehill/bot_AI_improvements
authorterencehill <piuntn@gmail.com>
Thu, 9 Feb 2017 12:58:13 +0000 (13:58 +0100)
committerterencehill <piuntn@gmail.com>
Thu, 9 Feb 2017 12:58:13 +0000 (13:58 +0100)
33 files changed:
commands.cfg
gamemodes.cfg
gfx/hud/default/minigames/snake/board.jpg [deleted file]
gfx/hud/default/minigames/snake/board_alpha.jpg [deleted file]
gfx/hud/default/minigames/snake/body.tga [deleted file]
gfx/hud/default/minigames/snake/head.tga [deleted file]
gfx/hud/default/minigames/snake/icon.jpg [deleted file]
gfx/hud/default/minigames/snake/icon_notif.jpg [deleted file]
gfx/hud/default/minigames/snake/icon_notif_alpha.jpg [deleted file]
gfx/hud/default/minigames/snake/mouse.tga [deleted file]
gfx/hud/default/minigames/snake/tail.tga [deleted file]
gfx/hud/default/minigames/snake/tongue.tga [deleted file]
mutators.cfg
qcsrc/client/main.qc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/mapinfo.qc
qcsrc/common/minigames/minigame/_mod.inc
qcsrc/common/minigames/minigame/_mod.qh
qcsrc/common/minigames/minigame/all.qh
qcsrc/common/minigames/minigame/snake.qc [deleted file]
qcsrc/common/minigames/minigame/snake.qh [deleted file]
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/wepent.qc
qcsrc/menu/xonotic/credits.qc
qcsrc/server/bot/default/bot.qc
qcsrc/server/command/cmd.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qh
qcsrc/server/race.qc

index a8de9b9..93b68f9 100644 (file)
@@ -172,7 +172,7 @@ alias team_pink "cmd selectteam pink; cmd join"
 alias team_yellow "cmd selectteam yellow; cmd join"
 alias team_auto "cmd selectteam auto; cmd join"
 
-alias spec "spectate"
+alias spec "spectate ${* ?}"
 
 // mutator aliases
 alias sandbox "cmd g_sandbox ${* ?}"
index e46c307..13a04fb 100644 (file)
@@ -309,6 +309,7 @@ set g_ctf_pass_velocity 750 "how fast or far a player can pass the flag"
 set g_ctf_allow_vehicle_touch 0 "allow flags to be picked up/captured/returned without even leaving the vehicle"
 set g_ctf_allow_vehicle_carry 1 "allow players to hold flags inside a vehicle"
 set g_ctf_allow_monster_touch 0 "allow flags to be returned by monsters"
+set g_ctf_score_ignore_fields 0 "force regular score settings to override per entity specified scores"
 
 set g_ctf_shield_max_ratio 0   "shield at most this percentage of a team from the enemy flag (try: 0.4 for 40%)"
 set g_ctf_shield_min_negscore 20       "shield the player from the flag if he's got this negative amount of points or less"
diff --git a/gfx/hud/default/minigames/snake/board.jpg b/gfx/hud/default/minigames/snake/board.jpg
deleted file mode 100644 (file)
index dfc5c3c..0000000
Binary files a/gfx/hud/default/minigames/snake/board.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/board_alpha.jpg b/gfx/hud/default/minigames/snake/board_alpha.jpg
deleted file mode 100644 (file)
index 44a8708..0000000
Binary files a/gfx/hud/default/minigames/snake/board_alpha.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/body.tga b/gfx/hud/default/minigames/snake/body.tga
deleted file mode 100644 (file)
index b8064cc..0000000
Binary files a/gfx/hud/default/minigames/snake/body.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/head.tga b/gfx/hud/default/minigames/snake/head.tga
deleted file mode 100644 (file)
index 0679f84..0000000
Binary files a/gfx/hud/default/minigames/snake/head.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/icon.jpg b/gfx/hud/default/minigames/snake/icon.jpg
deleted file mode 100644 (file)
index 14252ae..0000000
Binary files a/gfx/hud/default/minigames/snake/icon.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/icon_notif.jpg b/gfx/hud/default/minigames/snake/icon_notif.jpg
deleted file mode 100644 (file)
index 988b6db..0000000
Binary files a/gfx/hud/default/minigames/snake/icon_notif.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg b/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg
deleted file mode 100644 (file)
index 040990f..0000000
Binary files a/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/mouse.tga b/gfx/hud/default/minigames/snake/mouse.tga
deleted file mode 100644 (file)
index eda8ef7..0000000
Binary files a/gfx/hud/default/minigames/snake/mouse.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/tail.tga b/gfx/hud/default/minigames/snake/tail.tga
deleted file mode 100644 (file)
index 71a7901..0000000
Binary files a/gfx/hud/default/minigames/snake/tail.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/tongue.tga b/gfx/hud/default/minigames/snake/tongue.tga
deleted file mode 100644 (file)
index 9818d4e..0000000
Binary files a/gfx/hud/default/minigames/snake/tongue.tga and /dev/null differ
index d487327..9868c9a 100644 (file)
@@ -291,6 +291,8 @@ set cl_buffs_autoreplace 1 "automatically drop current buff when picking up anot
 set g_buffs -1 "enable buffs (requires buff items or powerups)"
 set g_buffs_effects 1 "show particle effects from carried buffs"
 set g_buffs_waypoint_distance 1024 "maximum distance at which buff waypoint can be seen from item"
+set g_buffs_pickup_anyway 0 "instantly respawn the buff when it is picked up, instead of waiting for the player to drop it"
+set g_buffs_pickup_delay 0.7 "cooldown before player can pick up another buff after dropping one"
 set g_buffs_randomize 1 "randomize buff type when player drops buff"
 set g_buffs_random_lifetime 30 "re-spawn the buff again if it hasn't been touched after this time in seconds"
 set g_buffs_random_location 0 "randomize buff location on start and when reset"
index f48c0c5..9a6c25c 100644 (file)
@@ -131,6 +131,9 @@ void CSQC_Init()
 
        registercvar("cl_spawn_near_teammate", "1");
 
+       if(autocvar_cl_lockview)
+               cvar_set("cl_lockview", "0");
+
        gametype = NULL;
 
        postinit = false;
index 0a9d2e4..b917deb 100644 (file)
@@ -910,6 +910,11 @@ METHOD(BallStealer, wr_setup, void(BallStealer this, entity actor, .entity weapo
     //weapon_setup(WEP_PORTO.m_id);
 }
 
+METHOD(BallStealer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+{
+    TC(BallStealer, this);
+}
+
 METHOD(BallStealer, wr_checkammo1, bool(BallStealer this, entity actor, .entity weaponentity))
 {
     TC(BallStealer, this);
index 2af3d90..92ed2b9 100644 (file)
@@ -9,6 +9,8 @@
     #include <common/monsters/_mod.qh>
 #endif
 
+bool autocvar_g_mapinfo_ignore_warnings;
+
 // generic string stuff
 
 int _MapInfo_Cache_Active;
@@ -547,7 +549,8 @@ void _MapInfo_Map_ApplyGametypeEx(string s, Gametype pWantedType, Gametype pThis
                if (sa == "") continue;
                int p = strstrofs(sa, "=", 0);
                if (p < 0) {
-                       LOG_WARNF("Invalid gametype setting in mapinfo for gametype %s: %s", MapInfo_Type_ToString(pWantedType), sa);
+                       if(!autocvar_g_mapinfo_ignore_warnings)
+                               LOG_WARNF("Invalid gametype setting in mapinfo for gametype %s: %s", MapInfo_Type_ToString(pWantedType), sa);
                        continue;
                }
                string k = substring(sa, 0, p);
@@ -586,7 +589,7 @@ void _MapInfo_Map_ApplyGametypeEx(string s, Gametype pWantedType, Gametype pThis
                        }
                }
                FOREACH(Gametypes, true, handled |= it.m_parse_mapinfo(k, v));
-               if (!handled)
+               if (!handled && !autocvar_g_mapinfo_ignore_warnings)
             LOG_WARNF("Invalid gametype setting in mapinfo for gametype %s: %s", MapInfo_Type_ToString(pWantedType), sa);
        }
 
@@ -607,7 +610,8 @@ Gametype MapInfo_Type_FromString(string t)
 #define deprecate(from, to) MACRO_BEGIN { \
        if (t == #from) { \
                string replacement = #to; \
-               LOG_WARNF("MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.", MapInfo_Map_bspname, t, replacement); \
+               if(!autocvar_g_mapinfo_ignore_warnings) \
+                       LOG_WARNF("MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.", MapInfo_Map_bspname, t, replacement); \
                t = replacement; \
        } \
 } MACRO_END
@@ -867,7 +871,8 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                                error("... but I just wrote it!");
                }
 
-               LOG_WARN("autogenerated mapinfo file ", fn, " has been loaded; please edit that file and move it to maps/", pFilename, ".mapinfo");
+               if(!autocvar_g_mapinfo_ignore_warnings)
+                       LOG_WARN("autogenerated mapinfo file ", fn, " has been loaded; please edit that file and move it to maps/", pFilename, ".mapinfo");
        }
 
        _MapInfo_Map_Reset();
@@ -933,10 +938,11 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                {
                        t = car(s); s = cdr(s);
                        Gametype f = MapInfo_Type_FromString(t);
-                       LOG_WARN("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.");
+                       if(!autocvar_g_mapinfo_ignore_warnings)
+                               LOG_WARN("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.");
                        if(f)
                                _MapInfo_Map_ApplyGametype (s, pGametypeToSet, f, true);
-                       else
+                       else if(!autocvar_g_mapinfo_ignore_warnings)
                                LOG_WARN("Map ", pFilename, " supports unknown game type ", t, ", ignored");
                }
                else if(t == "gametype")
@@ -945,7 +951,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                        Gametype f = MapInfo_Type_FromString(t);
                        if(f)
                                _MapInfo_Map_ApplyGametypeEx (s, pGametypeToSet, f);
-                       else
+                       else if(!autocvar_g_mapinfo_ignore_warnings)
                                LOG_WARN("Map ", pFilename, " supports unknown game type ", t, ", ignored");
                }
                else if(t == "size")
@@ -1039,7 +1045,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                                        );
                        }
                }
-               else
+               else if(!autocvar_g_mapinfo_ignore_warnings)
                        LOG_WARN("Map ", pFilename, " provides unknown info item ", t, ", ignored");
        }
        fclose(fh);
@@ -1187,6 +1193,8 @@ void MapInfo_LoadMap(string s, float reinit)
        //      MapInfo_SwitchGameType(MAPINFO_TYPE_DEATHMATCH.m_flags);
        //}
 
+       LOG_INFO("Switching to map ", s, "\n");
+
        cvar_settemp_restore();
        if(reinit)
                localcmd(strcat("\nmap ", s, "\n"));
index 0ccb46c..ac39421 100644 (file)
@@ -5,5 +5,4 @@
 #include <common/minigames/minigame/pong.qc>
 #include <common/minigames/minigame/pp.qc>
 #include <common/minigames/minigame/ps.qc>
-#include <common/minigames/minigame/snake.qc>
 #include <common/minigames/minigame/ttt.qc>
index 5098420..fe8378b 100644 (file)
@@ -5,5 +5,4 @@
 #include <common/minigames/minigame/pong.qh>
 #include <common/minigames/minigame/pp.qh>
 #include <common/minigames/minigame/ps.qh>
-#include <common/minigames/minigame/snake.qh>
 #include <common/minigames/minigame/ttt.qh>
index 74df391..5bbb7eb 100644 (file)
@@ -69,7 +69,6 @@ that .owner is set to the minigame session entity and .minigame_autoclean is tru
 #include "pong.qc"
 #include "ps.qc"
 #include "pp.qc"
-#include "snake.qc"
 #include "bd.qc"
 
 /**
diff --git a/qcsrc/common/minigames/minigame/snake.qc b/qcsrc/common/minigames/minigame/snake.qc
deleted file mode 100644 (file)
index 3aedeb0..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-#include "snake.qh"
-REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE
-
-const float SNAKE_TURN_MOVE  = 0x0100; // the snake is moving, player must control it
-const float SNAKE_TURN_WIN   = 0x0200; // multiplayer victory
-const float SNAKE_TURN_LOSS  = 0x0400; // they did it?!
-const float SNAKE_TURN_TYPE  = 0x0f00; // turn type mask
-
-const int SNAKE_TURN_TEAM  = 0x000f; // turn team mask
-
-const int SNAKE_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
-
-const int SNAKE_LET_CNT = 15;
-const int SNAKE_NUM_CNT = 15;
-
-const int SNAKE_TILE_SIZE = 15;
-
-const int SNAKE_TEAMS = 6;
-
-bool autocvar_sv_minigames_snake_wrap = false;
-float autocvar_sv_minigames_snake_delay_initial = 0.7;
-float autocvar_sv_minigames_snake_delay_multiplier = 50;
-float autocvar_sv_minigames_snake_delay_min = 0.1;
-#ifdef SVQC
-int autocvar_sv_minigames_snake_lives = 3;
-#endif
-
-.int snake_score;
-
-.float snake_delay;
-.vector snake_dir;
-
-.entity snake_next, snake_last, snake_prev;
-
-.bool snake_tail;
-
-.int snake_lives[SNAKE_TEAMS + 1];
-
-.int snake_lost_teams;
-
-bool snake_alone(entity minig)
-{
-       int headcount = 0;
-       entity e = NULL;
-       while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.cnt == 1 )
-                       ++headcount;
-
-       return headcount <= 1;
-}
-
-// find same game piece given its tile name
-entity snake_find_piece(entity minig, string tile)
-{
-       entity e = NULL;
-       while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.netname == tile )
-                       return e;
-       return NULL;
-}
-
-// find same game piece given its cnt
-entity snake_find_cnt(entity minig, int steam, int tile)
-{
-       entity e = NULL;
-       while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam )
-                       return e;
-       return NULL;
-}
-
-// check if the tile name is valid (15x15 grid)
-bool snake_valid_tile(string tile)
-{
-       if ( !tile )
-               return false;
-       int number = minigame_tile_number(tile);
-       int letter = minigame_tile_letter(tile);
-       return 0 <= number && number < SNAKE_NUM_CNT && 0 <= letter && letter < SNAKE_LET_CNT;
-}
-
-entity snake_find_head(entity minig, int steam)
-{
-       entity e = NULL;
-       while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam )
-                       return e;
-       return NULL;
-}
-
-void snake_new_mouse(entity minigame)
-{
-       RandomSelection_Init();
-       int i, j;
-       for(i = 0; i < SNAKE_LET_CNT; ++i)
-       for(j = 0; j < SNAKE_NUM_CNT; ++j)
-       {
-               string pos = minigame_tile_buildname(i, j);
-               if(!snake_find_piece(minigame, pos))
-                       RandomSelection_AddString(pos, 1, 1);
-       }
-
-       entity piece = msle_spawn(minigame,"minigame_board_piece");
-       piece.team = 0;
-       piece.netname = strzone(RandomSelection_chosen_string);
-       minigame_server_sendflags(piece,MINIG_SF_ALL);
-
-       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-}
-
-entity snake_get_player(entity minigame, int pteam);
-int snake_winning_team(entity minigame)
-{
-       int winning_team = 0;
-       for(int i = 1; i <= SNAKE_TEAMS; ++i)
-       {
-               entity pl = snake_get_player(minigame, i);
-               if(pl && minigame.snake_lives[i] > 0)
-               {
-                       if(winning_team)
-                               return 0;
-                       winning_team = i;
-               }
-       }
-
-       return winning_team;
-}
-
-void snake_check_winner(entity minigame)
-{
-       if(snake_alone(minigame) && !minigame.snake_lost_teams)
-               return;
-
-       int winner = snake_winning_team(minigame);
-
-       int alivecnt = 0;
-       for(int i = 1; i <= SNAKE_TEAMS; ++i)
-       {
-               entity pl = snake_get_player(minigame, i);
-               if(pl && minigame.snake_lives[i] > 0)
-                       ++alivecnt;
-       }
-
-       if(!alivecnt)
-       {
-               minigame.minigame_flags = SNAKE_TURN_LOSS;
-               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-               return;
-       }
-
-       if(winner)
-       {
-               minigame.minigame_flags = SNAKE_TURN_WIN | winner;
-               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-       }
-}
-
-void snake_move_head(entity minigame, entity head);
-void snake_head_think(entity this)
-{
-       entity minigame = this.owner;
-
-       if(minigame.minigame_flags & SNAKE_TURN_MOVE)
-               snake_move_head(minigame, this);
-
-       snake_check_winner(minigame);
-
-       this.nextthink = time + this.snake_delay;
-}
-
-void minigame_setup_snake(entity minigame, int pteam)
-{
-       RandomSelection_Init();
-       int i, j;
-       for(i = 1; i < SNAKE_LET_CNT - 1; ++i)
-       for(j = 1; j < SNAKE_NUM_CNT - 1; ++j)
-       {
-               string pos = minigame_tile_buildname(i, j);
-               if(!snake_find_piece(minigame, pos))
-                       RandomSelection_AddString(pos, 1, 1);
-       }
-
-       entity piece = msle_spawn(minigame,"minigame_board_piece");
-       piece.team = pteam;
-       piece.netname = strzone(RandomSelection_chosen_string);
-       piece.cnt = 1;
-       piece.snake_next = NULL;
-       piece.snake_prev = NULL;
-       piece.snake_last = piece;
-       setthink(piece, snake_head_think);
-       piece.snake_delay = autocvar_sv_minigames_snake_delay_initial;
-       piece.nextthink = time + 0.1;
-       minigame_server_sendflags(piece,MINIG_SF_ALL);
-}
-
-void snake_setup_pieces(entity minigame)
-{
-       snake_new_mouse(minigame);
-
-       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-}
-
-entity snake_get_player(entity minigame, int pteam)
-{
-       entity e;
-#ifdef SVQC
-       for(e = minigame.minigame_players; e; e = e.list_next)
-#elif defined(CSQC)
-       e = NULL;
-       while( (e = findentity(e,owner,minigame)) )
-               if ( e.classname == "minigame_player" )
-#endif
-       if(e.team == pteam)
-               return e;
-       return NULL;
-}
-
-void snake_add_score(entity minigame, int pteam, int thescore)
-{
-#ifdef SVQC
-       if(!minigame)
-               return;
-       entity pl = snake_get_player(minigame, pteam);
-       if(pl)
-       {
-               pl.snake_score += thescore;
-               pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
-       }
-#endif
-}
-
-void snake_move_body(entity minigame, entity head, bool ate_mouse)
-{
-       for(entity e = head.snake_last; e; e = e.snake_prev)
-       {
-               if(!e || e == head) { break; }
-
-               entity nextpiece = e.snake_prev; // can be head
-
-               if(e.netname) { strunzone(e.netname); }
-               e.netname = strzone(nextpiece.netname);
-               e.snake_dir = nextpiece.snake_dir;
-               minigame_server_sendflags(e, MINIG_SF_UPDATE);
-       }
-
-       if(ate_mouse)
-       {
-               entity tail = head.snake_last;
-
-               tail.snake_tail = false;
-
-               int newcnt = tail.cnt + 1;
-               head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
-               snake_add_score(minigame, head.team, 1);
-
-               entity piece = msle_spawn(minigame,"minigame_board_piece");
-               piece.cnt = newcnt;
-               piece.team = head.team;
-               piece.snake_prev = tail;
-               piece.snake_dir = tail.snake_dir;
-               piece.snake_next = NULL;
-               piece.snake_tail = true;
-               piece.netname = strzone(tail.netname);
-
-               tail.snake_next = piece;
-               head.snake_last = piece;
-
-               minigame_server_sendflags(piece,MINIG_SF_UPDATE);
-
-               //minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-       }
-}
-
-void snake_eat_team(entity minigame, int pteam)
-{
-       entity head = snake_find_head(minigame, pteam);
-       if(!head) { return; }
-
-       minigame.snake_lives[pteam] -= 1;
-
-       entity pl = snake_get_player(minigame, pteam);
-#ifdef SVQC
-       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
-#endif
-
-       head.nextthink = time + 1; // make sure they don't to eat us somehow
-
-       entity e = NULL;
-       while ( ( e = findentity(e,owner,minigame) ) )
-               if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
-               {
-                       if(e.netname) { strunzone(e.netname); }
-                       delete(e);
-               }
-
-       if(minigame.snake_lives[pteam] <= 0)
-               minigame.snake_lost_teams |= BIT(pteam);
-
-       if(pl && minigame.snake_lives[pteam] > 0)
-               minigame_setup_snake(minigame, pteam);
-}
-
-void snake_move_head(entity minigame, entity head)
-{
-       if(!head.snake_dir_x && !head.snake_dir_y)
-               return; // nope!
-
-       string newpos;
-
-       if(autocvar_sv_minigames_snake_wrap)
-               newpos = minigame_relative_tile(head.netname, head.snake_dir_x, head.snake_dir_y, SNAKE_NUM_CNT, SNAKE_LET_CNT);
-       else
-       {
-               int myx = minigame_tile_letter(head.netname);
-               int myy = minigame_tile_number(head.netname);
-
-               myx += head.snake_dir_x;
-               myy += head.snake_dir_y;
-
-               newpos = minigame_tile_buildname(myx, myy);
-       }
-
-       entity hit = snake_find_piece(minigame, newpos);
-
-       if(!snake_valid_tile(newpos) || (hit && hit.cnt && hit.team == head.team))
-       {
-               if(snake_alone(minigame))
-               {
-                       minigame.minigame_flags = SNAKE_TURN_LOSS;
-                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-               }
-               else
-               {
-                       snake_add_score(minigame, head.team, -1);
-                       snake_eat_team(minigame, head.team);
-               }
-
-               return;
-       }
-
-       bool ate_mouse = (hit && !hit.cnt);
-
-       // move the body first, then set the new head position?
-       snake_move_body(minigame, head, ate_mouse);
-
-       if(head.netname) { strunzone(head.netname); }
-       head.netname = strzone(newpos);
-       minigame_server_sendflags(head,MINIG_SF_UPDATE);
-
-       // above check makes sure it's not our team
-       if(hit.cnt)
-       {
-               snake_eat_team(minigame, hit.team);
-               snake_add_score(minigame, head.team, 1);
-       }
-
-       if(ate_mouse)
-       {
-               if(hit.netname) { strunzone(hit.netname); }
-               delete(hit);
-
-               snake_new_mouse(minigame);
-       }
-}
-
-// make a move
-void snake_move(entity minigame, entity player, string dxs, string dys )
-{
-       if ( minigame.minigame_flags & SNAKE_TURN_MOVE )
-       if ( dxs || dys )
-       {
-               //if ( snake_valid_tile(pos) )
-               //if ( snake_find_piece(minigame, pos) )
-               {
-                       entity head = snake_find_head(minigame, player.team);
-                       if(!head)
-                               return; // their head is already dead
-
-                       int dx = ((dxs) ? bound(-1, stof(dxs), 1) : 0);
-                       int dy = ((dys) ? bound(-1, stof(dys), 1) : 0);
-
-                       int myl = minigame_tile_letter(head.netname);
-                       int myn = minigame_tile_number(head.netname);
-
-                       entity check_piece = snake_find_piece(minigame, minigame_tile_buildname(myl + dx, myn + dy));
-                       if(check_piece && check_piece.cnt == 2)
-                               return; // nope!
-
-                       if(head.snake_dir == '0 0 0')
-                               head.nextthink = time; // TODO: make sure this can't be exploited!
-                       head.snake_dir_x = dx;
-                       head.snake_dir_y = dy;
-                       head.snake_dir_z = 0;
-                       minigame_server_sendflags(head,MINIG_SF_UPDATE);
-                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-               }
-       }
-}
-
-#ifdef SVQC
-
-
-// required function, handle server side events
-int snake_server_event(entity minigame, string event, ...)
-{
-       switch(event)
-       {
-               case "start":
-               {
-                       snake_setup_pieces(minigame);
-                       minigame.minigame_flags = SNAKE_TURN_MOVE;
-                       minigame.snake_lost_teams = 0;
-
-                       if(SNAKE_TEAMS > 1)
-                       {
-                               for(int i = 1; i <= SNAKE_TEAMS; ++i)
-                                       minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives;
-                       }
-                       else
-                               minigame.snake_lives[1] = 1;
-
-                       return true;
-               }
-               case "end":
-               {
-                       entity e = NULL;
-                       while( (e = findentity(e, owner, minigame)) )
-                       if(e.classname == "minigame_board_piece")
-                       {
-                               if(e.netname) { strunzone(e.netname); }
-                               delete(e);
-                       }
-                       return false;
-               }
-               case "join":
-               {
-                       int pl_num = minigame_count_players(minigame);
-
-                       if(pl_num >= SNAKE_TEAMS) { return false; }
-
-                       int t = 1; // Team 1 by default
-
-                       for(int i = 1; i <= SNAKE_TEAMS; ++i)
-                       {
-                               entity e = snake_get_player(minigame, i);
-                               if(!e)
-                               {
-                                       t = i;
-                                       break;
-                               }
-                       }
-
-                       if(!snake_find_head(minigame, t) && !(minigame.snake_lost_teams & BIT(t)))
-                       {
-                               entity pl = ...(1,entity);
-                               if(pl)
-                               {
-                                       //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
-                                       // send score anyway, lives are set
-                                       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
-                               }
-                               minigame_setup_snake(minigame, t);
-                       }
-
-                       return t;
-               }
-               case "cmd":
-               {
-                       switch(argv(0))
-                       {
-                               case "move":
-                                       snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null));
-                                       return true;
-                       }
-
-                       return false;
-               }
-               case "network_send":
-               {
-                       entity sent = ...(0,entity);
-                       int sf = ...(1,int);
-                       if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
-                       {
-                               int letter = minigame_tile_letter(sent.netname);
-                               int number = minigame_tile_number(sent.netname);
-
-                               WriteByte(MSG_ENTITY,letter);
-                               WriteByte(MSG_ENTITY,number);
-
-                               WriteByte(MSG_ENTITY,sent.cnt);
-                               WriteByte(MSG_ENTITY,sent.snake_tail);
-
-                               int dx = sent.snake_dir_x;
-                               int dy = sent.snake_dir_y;
-                               if(dx == -1) dx = 2;
-                               if(dy == -1) dy = 2;
-                               WriteByte(MSG_ENTITY,dx);
-                               WriteByte(MSG_ENTITY,dy);
-                       }
-                       else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
-                       {
-                               WriteLong(MSG_ENTITY,sent.snake_score);
-                               WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team]));
-                       }
-                       else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) )
-                       {
-                               WriteByte(MSG_ENTITY,autocvar_sv_minigames_snake_wrap);
-                       }
-                       return false;
-               }
-       }
-
-       return false;
-}
-
-
-#elif defined(CSQC)
-
-vector snake_boardpos; // HUD board position
-vector snake_boardsize;// HUD board size
-
-bool snake_wrap;
-
-vector snake_teamcolor(int steam)
-{
-       switch(steam)
-       {
-               case 1: return '1 0 0';
-               case 2: return '0 0 1';
-               case 3: return '1 1 0';
-               case 4: return '1 0 1';
-               case 5: return '0 1 0';
-               case 6: return '0 1 1';
-       }
-
-       return '1 1 1';
-}
-
-// Required function, draw the game board
-void snake_hud_board(vector pos, vector mySize)
-{
-       minigame_hud_fitsqare(pos, mySize);
-       snake_boardpos = pos;
-       snake_boardsize = mySize;
-
-       minigame_hud_simpleboard(pos,mySize,minigame_texture("snake/board"));
-
-       vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize);
-       vector tile_pos;
-
-       entity e;
-       FOREACH_MINIGAME_ENTITY(e)
-       {
-               if ( e.classname == "minigame_board_piece" )
-               {
-                       tile_pos = minigame_tile_pos(e.netname,SNAKE_NUM_CNT,SNAKE_LET_CNT);
-                       tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-
-                       vector tile_color = snake_teamcolor(e.team);
-
-                       string thepiece = "snake/mouse";
-                       if(e.cnt)
-                               thepiece = "snake/body";
-                       if(e.snake_tail)
-                               thepiece = "snake/tail";
-                       if(e.cnt == 1)
-                       {
-                               int dx = minigame_tile_letter(e.netname) + e.snake_dir_x * 2;
-                               int dy = minigame_tile_number(e.netname) + e.snake_dir_y * 2;
-                               entity mouse = snake_find_piece(active_minigame, minigame_tile_buildname(dx, dy));
-                               thepiece = "snake/head";
-                               if(mouse && mouse.team != e.team)
-                               {
-                                       float myang = 0;
-                                       int myx = minigame_tile_letter(e.netname);
-                                       int myy = minigame_tile_number(e.netname);
-                                       if(myx - 2 == dx)
-                                               myang = M_PI*3/2;
-                                       if(myx + 2 == dx)
-                                               myang = M_PI/2;
-                                       if(myy - 2 == dy)
-                                               myang = M_PI;
-
-                                       int newx = minigame_tile_letter(e.netname) + e.snake_dir_x;
-                                       int newy = minigame_tile_number(e.netname) + e.snake_dir_y;
-                                       string newpos = minigame_tile_buildname(newx, newy);
-
-                                       vector my_pos = minigame_tile_pos(newpos,SNAKE_NUM_CNT,SNAKE_LET_CNT);
-                                       my_pos = minigame_hud_denormalize(my_pos,pos,mySize);
-
-                                       drawrotpic(my_pos, myang, minigame_texture("snake/tongue"),
-                                                       tile_size, tile_size/2, tile_color,
-                                                       panel_fg_alpha, DRAWFLAG_NORMAL );
-                               }
-                       }
-
-                       if(e.cnt == 1 || e.snake_tail)
-                       {
-                               vector thedir = e.snake_dir;
-                               float theang = 0;
-                               if(e.snake_tail)
-                               {
-                                       int thex = minigame_tile_letter(e.netname);
-                                       int they = minigame_tile_number(e.netname);
-                                       entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1);
-                                       int tx = minigame_tile_letter(t.netname);
-                                       int ty = minigame_tile_number(t.netname);
-
-                                       if(thex - 1 == tx)
-                                       {
-                                               thedir_y = 0;
-                                               thedir_x = -1;
-                                       }
-                                       if(they + 1 == ty)
-                                       {
-                                               thedir_x = 0;
-                                               thedir_y = 1;
-                                       }
-                                       if(they - 1 == ty)
-                                       {
-                                               thedir_x = 0;
-                                               thedir_y = -1;
-                                       }
-                               }
-
-                               if(thedir_y == -1)
-                                       theang = M_PI;
-                               if(thedir_x == 1)
-                                       theang = M_PI/2;
-                               if(thedir_x == -1)
-                                       theang = M_PI*3/2;
-
-                               drawrotpic(tile_pos, theang, minigame_texture(thepiece),
-                                                       tile_size, tile_size/2, tile_color,
-                                                       panel_fg_alpha, DRAWFLAG_NORMAL );
-                       }
-                       else
-                       {
-                               minigame_drawpic_centered( tile_pos,
-                                               minigame_texture(thepiece),
-                                               tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
-                       }
-               }
-       }
-
-       if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) )
-       {
-               int scores = minigame_self.snake_score;
-
-               vector winfs = hud_fontsize*2;
-               string scores_text, victory_text;
-               victory_text = "Game over!";
-               scores_text = strcat("Score: ", ftos(scores));
-
-               if(active_minigame.minigame_flags & SNAKE_TURN_WIN)
-               if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
-                       victory_text = "You win!";
-               if(active_minigame.snake_lives[minigame_self.team] <= 0)
-                       victory_text = "You ran out of lives!";
-
-               vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
-               vector win_sz;
-               win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s %s", victory_text, scores_text),
-                       winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
-               drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
-
-               minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s %s", victory_text, scores_text),
-                       winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
-       }
-}
-
-
-// Required function, draw the game status panel
-void snake_hud_status(vector pos, vector mySize)
-{
-       HUD_Panel_DrawBg();
-       vector ts = minigame_drawstring_wrapped(mySize.x, pos, active_minigame.descriptor.message,
-               hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       ts.y += hud_fontsize.y;
-       pos.y += ts.y;
-       mySize.y -= ts.y;
-
-       vector player_fontsize = hud_fontsize * 1.75;
-       ts.y = player_fontsize.y + (mySize.y - SNAKE_TEAMS * player_fontsize.y) / SNAKE_TEAMS;
-       ts.x = mySize_x;
-       vector mypos;
-
-       entity e;
-       FOREACH_MINIGAME_ENTITY(e)
-       {
-               if ( e.classname == "minigame_player" )
-               {
-                       mypos = pos + eY * (e.team - 1) * ts.y;
-
-                       if (e == minigame_self)
-                       {
-                               const vector hl_size = '1 1 0';
-                               drawfill(mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
-                               drawborderlines(hl_size.x, mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), panel_fg_alpha, DRAWFLAG_NORMAL);
-                       }
-                       else
-                               drawfill(mypos, ts, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
-
-                       minigame_drawcolorcodedstring_trunc(mySize.x - hud_fontsize.x * 0.5, mypos + eX * hud_fontsize.x * 0.25,
-                               entcs_GetName(e.minigame_playerslot - 1),
-                               player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
-                       mypos.y += player_fontsize.y;
-                       drawstring_aspect(mypos, ftos(e.snake_score), ts - eY * player_fontsize.y - eX * ts.x * (3 / 4),
-                                                               '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-                       drawstring_aspect(mypos + eX * ts.x * (1 / 4), strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])), ts - eY * player_fontsize.y - eX * ts.x * (1 / 4),
-                                                               '1 0.44 0.54', panel_fg_alpha, DRAWFLAG_NORMAL);
-               }
-       }
-}
-
-// Turn a set of flags into a help message
-string snake_turn_to_string(int turnflags)
-{
-       if ( turnflags & SNAKE_TURN_LOSS )
-               return _("Game over!");
-
-       if ( turnflags & SNAKE_TURN_WIN )
-       {
-               if ( (turnflags&SNAKE_TURN_TEAM) != minigame_self.team )
-                       return _("You ran out of lives!");
-               return _("You win!");
-       }
-
-       if(active_minigame.snake_lives[minigame_self.team] <= 0)
-               return _("You ran out of lives!");
-
-       if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' )
-               return _("Press an arrow key to begin the game");
-
-       if ( turnflags & SNAKE_TURN_MOVE )
-               if(snake_wrap)
-                       return _("Avoid the snake's body, collect the mice!");
-               else
-                       return _("Avoid the screen edges and the snake's body, collect the mice!");
-
-       return "";
-}
-
-// Make the correct move
-void snake_set_direction(entity minigame, int dx, int dy)
-{
-       //if ( minigame.minigame_flags == SNAKE_TURN_MOVE )
-       //{
-               minigame_cmd("move ",ftos(dx), " ", ftos(dy));
-       //}
-}
-
-// Required function, handle client events
-int snake_client_event(entity minigame, string event, ...)
-{
-       switch(event)
-       {
-               case "activate":
-               {
-                       minigame.message = snake_turn_to_string(minigame.minigame_flags);
-                       return false;
-               }
-               case "key_pressed":
-               {
-                       //if((minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
-                       {
-                               switch ( ...(0,int) )
-                               {
-                                       case K_RIGHTARROW:
-                                       case K_KP_RIGHTARROW:
-                                               snake_set_direction(minigame, 1, 0);
-                                               return true;
-                                       case K_LEFTARROW:
-                                       case K_KP_LEFTARROW:
-                                               snake_set_direction(minigame, -1, 0);
-                                               return true;
-                                       case K_UPARROW:
-                                       case K_KP_UPARROW:
-                                               snake_set_direction(minigame, 0, 1);
-                                               return true;
-                                       case K_DOWNARROW:
-                                       case K_KP_DOWNARROW:
-                                               snake_set_direction(minigame, 0, -1);
-                                               return true;
-                               }
-                       }
-
-                       return false;
-               }
-               case "network_receive":
-               {
-                       entity sent = ...(0,entity);
-                       int sf = ...(1,int);
-                       if ( sent.classname == "minigame" )
-                       {
-                               if ( sf & MINIG_SF_UPDATE )
-                               {
-                                       snake_wrap = ReadByte();
-                                       sent.message = snake_turn_to_string(sent.minigame_flags);
-                                       //if ( sent.minigame_flags & minigame_self.team )
-                                               minigame_prompt();
-                               }
-                       }
-                       else if(sent.classname == "minigame_board_piece")
-                       {
-                               if(sf & MINIG_SF_UPDATE)
-                               {
-                                       int letter = ReadByte();
-                                       int number = ReadByte();
-                                       if(sent.netname) { strunzone(sent.netname); }
-                                       sent.netname = strzone(minigame_tile_buildname(letter, number));
-
-                                       sent.cnt = ReadByte();
-                                       sent.snake_tail = ReadByte();
-
-                                       int dx = ReadByte();
-                                       int dy = ReadByte();
-
-                                       if(dx == 2) dx = -1;
-                                       if(dy == 2) dy = -1;
-
-                                       sent.snake_dir_x = dx;
-                                       sent.snake_dir_y = dy;
-                                       sent.snake_dir_z = 0;
-                               }
-                       }
-                       else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
-                       {
-                               sent.snake_score = ReadLong();
-                               minigame.snake_lives[sent.team] = ReadByte();
-                       }
-
-                       return false;
-               }
-       }
-
-       return false;
-}
-
-#endif
diff --git a/qcsrc/common/minigames/minigame/snake.qh b/qcsrc/common/minigames/minigame/snake.qh
deleted file mode 100644 (file)
index 6f70f09..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#pragma once
index edd9701..b458f73 100644 (file)
@@ -160,6 +160,7 @@ void buff_Touch(entity this, entity toucher)
        if((this.team && DIFF_TEAM(toucher, this))
        || (STAT(FROZEN, toucher))
        || (toucher.vehicle)
+       || (time < toucher.buff_shield)
        || (!this.buff_active)
        )
        {
@@ -257,7 +258,7 @@ void buff_Think(entity this)
        }
 
        if(!this.buff_active && !this.buff_activetime)
-       if(!this.owner || STAT(FROZEN, this.owner) || IS_DEAD(this.owner) || !this.owner.iscreature || !(this.owner.buffs & this.buffs))
+       if(!this.owner || STAT(FROZEN, this.owner) || IS_DEAD(this.owner) || !this.owner.iscreature || !(this.owner.buffs & this.buffs) || this.pickup_anyway > 0 || (this.pickup_anyway >= 0 && autocvar_g_buffs_pickup_anyway))
        {
                buff_SetCooldown(this, autocvar_g_buffs_cooldown_respawn + frametime);
                this.owner = NULL;
@@ -639,7 +640,8 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerUseKey, CBC_ORDER_FIRST)
                Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
 
                player.buffs = 0;
-               player.buff_time = 0; // already notified
+               player.buff_shield = time + max(0, autocvar_g_buffs_pickup_delay);
+               //player.buff_time = 0; // already notified
                sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                return true;
        }
@@ -840,6 +842,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                        else
                                Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
                        player.buffs = 0;
+                       player.buff_shield = time + max(0, autocvar_g_buffs_pickup_delay); // always put in a delay, even if small
                }
        }
 
@@ -872,8 +875,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
        }
 
        if((player.buffs & BUFF_INVISIBLE.m_itemid) && (player.oldbuffs & BUFF_INVISIBLE.m_itemid))
-       if(player.alpha != autocvar_g_buffs_invisible_alpha)
-               player.alpha = autocvar_g_buffs_invisible_alpha; // powerups reset alpha, so we must enforce this (TODO)
+               player.alpha = ((autocvar_g_buffs_invisible_alpha) ? autocvar_g_buffs_invisible_alpha : -1); // powerups reset alpha, so we must enforce this (TODO)
 
        if(player.buffs & BUFF_MEDIC.m_itemid)
        if(time >= player.buff_medic_healtime)
@@ -930,14 +932,19 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                BUFF_ONADD(BUFF_INVISIBLE)
                {
                        if(time < player.strength_finished && g_instagib)
-                               player.alpha = autocvar_g_instagib_invis_alpha;
+                               player.buff_invisible_prev_alpha = default_player_alpha; // we don't want to save the powerup's alpha, as player may lose the powerup while holding the buff
                        else
-                               player.alpha = player.buff_invisible_prev_alpha;
+                               player.buff_invisible_prev_alpha = player.alpha;
                        player.alpha = autocvar_g_buffs_invisible_alpha;
                }
 
                BUFF_ONREM(BUFF_INVISIBLE)
-                       player.alpha = player.buff_invisible_prev_alpha;
+               {
+                       if(time < player.strength_finished && g_instagib)
+                               player.alpha = autocvar_g_instagib_invis_alpha;
+                       else
+                               player.alpha = player.buff_invisible_prev_alpha;
+               }
 
                BUFF_ONADD(BUFF_FLIGHT)
                {
index 8383a72..b26d51c 100644 (file)
@@ -6,6 +6,8 @@
 
 bool  autocvar_g_buffs_effects;
 float autocvar_g_buffs_waypoint_distance;
+bool autocvar_g_buffs_pickup_anyway = false;
+float autocvar_g_buffs_pickup_delay = 0.7;
 bool autocvar_g_buffs_randomize;
 float autocvar_g_buffs_random_lifetime;
 bool autocvar_g_buffs_random_location;
@@ -70,6 +72,7 @@ float autocvar_g_buffs_luck_damagemultiplier = 3;
 .float buff_activetime_updated;
 .entity buff_waypoint;
 .int oldbuffs; // for updating effects
+.float buff_shield; // delay for players to keep them from spamming buff pickups
 .entity buff_model; // controls effects (TODO: make csqc)
 
 const vector BUFF_MIN = ('-16 -16 0');
index e8ab69a..82e1abf 100644 (file)
@@ -970,6 +970,7 @@ void vehicles_enter(entity pl, entity veh)
 
        veh.event_damage        = vehicles_damage;
        veh.nextthink           = 0;
+       pl.items &= ~IT_USING_JETPACK;
        pl.angles                       = veh.angles;
        pl.takedamage           = DAMAGE_NO;
        pl.solid                        = SOLID_NOT;
index 9cb8b74..889ca47 100644 (file)
@@ -60,9 +60,9 @@ NET_HANDLE(ENT_CLIENT_BUMBLE_RAYGUN, bool isnew)
     {
         this.cnt  = ReadByte();
         this.team = ReadByte();
-        this.cnt  = ReadByte();
+        this.count  = ReadByte();
 
-        if(this.cnt)
+        if(this.count)
             this.colormod = '1 0 0';
         else
             this.colormod = '0 1 0';
index e76117d..8268acd 100644 (file)
@@ -64,6 +64,8 @@ REGISTER_WEAPON(CRYLINK, crylink, NEW(Crylink));
 .float crylink_waitrelease;
 .entity crylink_lastgroup;
 
+.entity crylink_owner; // we can't use realowner, as that's subject to change
+
 .entity queuenext;
 .entity queueprev;
 #endif
@@ -110,7 +112,7 @@ void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
 
 void W_Crylink_Dequeue(entity e)
 {
-       W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
+       W_Crylink_Dequeue_Raw(e.crylink_owner, e.queueprev, e, e.queuenext);
 }
 
 void W_Crylink_Reset(entity this)
@@ -130,8 +132,8 @@ void W_Crylink_LinkExplode(entity e, entity e2, entity directhitentity)
        a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
 
        .entity weaponentity = e.weaponentity_fld;
-       if(e == e.realowner.(weaponentity).crylink_lastgroup)
-               e.realowner.(weaponentity).crylink_lastgroup = NULL;
+       if(e == e.crylink_owner.(weaponentity).crylink_lastgroup)
+               e.crylink_owner.(weaponentity).crylink_lastgroup = NULL;
 
        float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
 
@@ -321,8 +323,8 @@ void W_Crylink_Touch(entity this, entity toucher)
        if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
        {
                .entity weaponentity = this.weaponentity_fld;
-               if(this == this.realowner.(weaponentity).crylink_lastgroup)
-                       this.realowner.(weaponentity).crylink_lastgroup = NULL;
+               if(this == this.crylink_owner.(weaponentity).crylink_lastgroup)
+                       this.crylink_owner.(weaponentity).crylink_lastgroup = NULL;
                W_Crylink_LinkExplode(this.queuenext, this, toucher);
                this.classname = "spike_oktoremove";
                delete(this);
@@ -378,6 +380,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
                proj = new(spike);
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
+               proj.crylink_owner = actor;
                proj.weaponentity_fld = weaponentity;
                proj.bot_dodge = true;
                proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage);
@@ -490,6 +493,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
                proj.weaponentity_fld = weaponentity;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
+               proj.crylink_owner = actor;
                proj.bot_dodge = true;
                proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage);
                if(shots == 1) {
index e244e7b..8d74a7b 100644 (file)
@@ -19,8 +19,8 @@ MACRO_END
        { (viewmodels[this.m_wepent_slot]).activeweapon = Weapons_from(ReadByte()); }) \
     \
     PROP(false, m_alpha, WEPENT_SET_NORMAL, \
-       { WriteByte(chan, this.m_alpha * 16); }, \
-       { (viewmodels[this.m_wepent_slot]).alpha = ReadByte() / 16; }) \
+       { WriteByte(chan, rint(bound(-1, 254 * this.m_alpha, 254) - -1)); }, \
+       { (viewmodels[this.m_wepent_slot]).alpha = (ReadByte() + -1) / 254; }) \
     \
     PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
        { WriteByte(chan, this.vortex_charge * 16); }, \
index a28b086..7d1f2c4 100644 (file)
@@ -86,6 +86,7 @@
                PERSON(Ruszkai "CuBe0wL" Ákos) \
                PERSON(Severin "sev" Meyer) \
                PERSON(ShadoW) \
+               PERSON(t0uYK8Ne) \
        NL() \
        FUNCTION(_("Music / Sound FX")) \
                PERSON(AquaNova (Archer)) \
                        PERSON(ubone) \
                NL() \
                FUNCTION(_("Chinese (China)")) \
+                       PERSON(Antonidas) \
+                       PERSON(Armcoon) \
                        PERSON(kalawore) \
                        PERSON(sapphireliu) \
                NL() \
                        PERSON(XCostaX) \
                NL() \
                FUNCTION(_("Kazakh")) \
-                       PERSON("Артем \"bystrov.arterm\" Быстров") \
+                       PERSON("Артем "bystrov.arterm" Быстров") \
                NL() \
                FUNCTION(_("Korean")) \
                        PERSON(Jisoo "s6e9x" Lim) \
index 16a082b..3184221 100644 (file)
@@ -208,7 +208,13 @@ void bot_setnameandstuff(entity this)
 
        prio = 6;
 
-       #define READSKILL(f,w,r) if(argv(prio) != "") this.f = stof(argv(prio)) * (w); else this.f = (!autocvar_g_campaign) * (2 * random() - 1) * (r) * (w); ++prio
+       #define READSKILL(f, w, r) MACRO_BEGIN { \
+               if(argv(prio) != "") \
+                       this.f = stof(argv(prio)) * w; \
+               else \
+                       this.f = (!autocvar_g_campaign) * (2 * random() - 1) * r * w; \
+               prio++; \
+       } MACRO_END
        //print(bot_name, ": ping=", argv(9), "\n");
 
        READSKILL(havocbot_keyboardskill, 0.5, 0.5); // keyboard skill
index 1fa600e..a4145ab 100644 (file)
@@ -473,6 +473,17 @@ void ClientCommand_spectate(entity caller, float request)
                {
                        if (!intermission_running && IS_CLIENT(caller))
                        {
+                               if((IS_SPEC(caller) || IS_OBSERVER(caller)) && argv(1) != "")
+                               {
+                                       entity client = GetFilteredEntity(argv(1));
+                                       int spec_accepted = VerifyClientEntity(client, false, false);
+                                       if(spec_accepted > 0 && IS_PLAYER(client))
+                                       {
+                                               if(Spectate(caller, client))
+                                                       return; // fall back to regular handling
+                                       }
+                               }
+
                                int mutator_returnvalue = MUTATOR_CALLHOOK(ClientCommand_Spectate, caller);
 
                                if (mutator_returnvalue == MUT_SPECCMD_RETURN) return;
@@ -487,8 +498,8 @@ void ClientCommand_spectate(entity caller, float request)
                default:
                case CMD_REQUEST_USAGE:
                {
-                       sprint(caller, "\nUsage:^3 cmd spectate\n");
-                       sprint(caller, "  No arguments required.\n");
+                       sprint(caller, "\nUsage:^3 cmd spectate <client>\n");
+                       sprint(caller, "  Where 'client' can be the player to spectate.\n");
                        return;
                }
        }
index badab51..534b416 100644 (file)
@@ -91,6 +91,7 @@ float autocvar_g_ctf_flagcarrier_forcefactor;
 //float autocvar_g_ctf_flagcarrier_waypointforenemy_spotting;
 bool autocvar_g_ctf_fullbrightflags;
 bool autocvar_g_ctf_ignore_frags;
+bool autocvar_g_ctf_score_ignore_fields;
 int autocvar_g_ctf_score_capture;
 int autocvar_g_ctf_score_capture_assist;
 int autocvar_g_ctf_score_kill;
@@ -385,7 +386,7 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype)
        ctf_EventLog("dropped", player.team, player);
 
        // scoring
-       PlayerTeamScore_AddScore(player, -autocvar_g_ctf_score_penalty_drop);
+       PlayerTeamScore_AddScore(player, -((flag.score_drop) ? flag.score_drop : autocvar_g_ctf_score_penalty_drop));
        PlayerScore_Add(player, SP_CTF_DROPS, 1);
 
        // waypoints
@@ -595,7 +596,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype)
        }
 
        // scoring
-       PlayerTeamScore_AddScore(player, autocvar_g_ctf_score_capture);
+       PlayerTeamScore_AddScore(player, ((flag.score_capture) ? flag.score_capture : autocvar_g_ctf_score_capture));
        PlayerTeamScore_Add(player, SP_CTF_CAPS, ST_CTF_CAPS, 1);
 
        old_time = PlayerScore_Add(player, SP_CTF_CAPTIME, 0);
@@ -614,7 +615,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype)
                if(flag.speedrunning) { ctf_FakeTimeLimit(player, -1); }
 
                if((enemy_flag.ctf_dropper) && (player != enemy_flag.ctf_dropper))
-                       { PlayerTeamScore_AddScore(enemy_flag.ctf_dropper, autocvar_g_ctf_score_capture_assist); }
+                       { PlayerTeamScore_AddScore(enemy_flag.ctf_dropper, ((flag.score_assist) ? flag.score_assist : autocvar_g_ctf_score_capture_assist)); }
        }
 
        // reset the flag
@@ -640,7 +641,7 @@ void ctf_Handle_Return(entity flag, entity player)
        // scoring
        if(IS_PLAYER(player))
        {
-               PlayerTeamScore_AddScore(player, autocvar_g_ctf_score_return); // reward for return
+               PlayerTeamScore_AddScore(player, ((flag.score_return) ? flag.score_return : autocvar_g_ctf_score_return)); // reward for return
                PlayerScore_Add(player, SP_CTF_RETURNS, 1); // add to count of returns
 
                nades_GiveBonus(player,autocvar_g_nades_bonus_score_medium);
@@ -731,7 +732,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
        {
                case PICKUP_BASE:
                {
-                       PlayerTeamScore_AddScore(player, autocvar_g_ctf_score_pickup_base);
+                       PlayerTeamScore_AddScore(player, ((flag.score_pickup) ? flag.score_pickup : autocvar_g_ctf_score_pickup_base));
                        ctf_EventLog("steal", flag.team, player);
                        break;
                }
@@ -1272,6 +1273,10 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        flag.nextthink = time + FLAG_THINKRATE;
        flag.ctf_status = FLAG_BASE;
 
+       // crudely force them all to 0
+       if(autocvar_g_ctf_score_ignore_fields)
+               flag.score_assist = flag.score_capture = flag.score_drop = flag.score_pickup = flag.score_return = 0;
+
        string teamname = Static_Team_ColorName_Lower(teamnumber);
        // appearence
        if(!flag.scale)                         { flag.scale = FLAG_SCALE; }
index 593b0be..098a0ad 100644 (file)
@@ -48,6 +48,13 @@ const float VEHICLE_FLAG_SCALE = 1.0;
 .string snd_flag_touch;
 .string snd_flag_pass;
 
+// score fields
+.float score_assist;
+.float score_capture;
+.float score_drop; // note: negated
+.float score_pickup;
+.float score_return;
+
 // effects
 .string toucheffect;
 .string passeffect;
index 1550cd2..a70cc88 100644 (file)
@@ -290,7 +290,8 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e,
 
        if(uid2name(myuid) == "^1Unregistered Player")
        {
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_NAME, mynetname, t);
+               if(showmessage)
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_NAME, mynetname, t);
                return;
        }