]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/arena_and_ca_fixes
authorterencehill <piuntn@gmail.com>
Wed, 11 Jan 2012 12:34:08 +0000 (13:34 +0100)
committerterencehill <piuntn@gmail.com>
Wed, 11 Jan 2012 12:34:08 +0000 (13:34 +0100)
52 files changed:
commands.cfg
defaultXonotic.cfg
gfx/m_nomap.jpg [deleted file]
gfx/menu/luminos/nopreview_map.tga [new file with mode: 0644]
gfx/menu/luminos/nopreview_menuskin.tga [new file with mode: 0644]
gfx/menu/luminos/nopreview_player.tga [new file with mode: 0644]
gfx/menu/wickedx/nopreview_map.tga [new file with mode: 0644]
gfx/menu/wickedx/nopreview_menuskin.tga [new file with mode: 0644]
gfx/menu/wickedx/nopreview_player.tga [new file with mode: 0644]
gfx/menu/xaw/nopreview_map.tga [new file with mode: 0644]
gfx/menu/xaw/nopreview_menuskin.tga [new file with mode: 0644]
gfx/menu/xaw/nopreview_player.tga [new file with mode: 0644]
qcsrc/client/Defs.qc
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/autocvars.qh
qcsrc/client/command/cl_cmd.qc
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/shownames.qc
qcsrc/client/shownames.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/csqcmodellib/cl_player.qc
qcsrc/dpdefs/csprogsdefs.qc
qcsrc/menu/draw.qc
qcsrc/menu/draw.qh
qcsrc/menu/xonotic/campaign.c
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.c
qcsrc/menu/xonotic/maplist.c
qcsrc/menu/xonotic/playermodel.c
qcsrc/menu/xonotic/skinlist.c
qcsrc/server/autocvars.qh
qcsrc/server/bot/bot.qc
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/waypoints.qc
qcsrc/server/bot/waypoints.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/command/banning.qc
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/t_items.qc
qcsrc/server/t_plats.qc
qcsrc/server/w_minstanex.qc

index 21f2da6e377768830b2ad086ad9eda371ba6abf0..1f7e684588770a6e8554d6c9cc4162daabfe2899 100644 (file)
@@ -229,6 +229,7 @@ alias settemp_restore "qc_cmd_svcl settemp_restore"
 // ===================================
 alias ban                  "qc_cmd_sv     ban                  ${* ?}" // Ban an IP address or a range of addresses (like 1.2.3)
 alias banlist              "qc_cmd_sv     banlist              ${* ?}" // List all existing bans
+alias bans                 "qc_cmd_sv     bans                 ${* ?}" // COMPATIBILITY COMMAND FOR 0.5 CLIENTS
 alias kickban              "qc_cmd_sv     kickban              ${* ?}" // Disconnect a client and ban it at the same time
 alias unban                "qc_cmd_sv     unban                ${* ?}" // Remove an existing ban
 
@@ -258,18 +259,22 @@ set sv_vote_majority_factor_of_voted 0.5 "What percentage of the VOTERS constitu
 // when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities"
 set sv_vote_override_mostrecent 0
 
-alias vhelp "cmd vote help"
-alias vstatus "cmd vote status"
-alias vcall "cmd vote call ${* ?}"
-alias vstop "cmd vote stop"
-alias vmaster "cmd vote master"
-alias vlogin "cmd vote master login ${* ?}"
-alias vdo "cmd vote master do ${* ?}"
-alias vyes "cl_cmd handlevote yes; cl_cmd vyes" // NOTE: COMPATIBILITY FOR 0.5 IS ADDED HERE WITH "VYES", REMOVE LATER
-alias vno "cl_cmd handlevote no; cl_cmd vno" // ^^^ same, see above
-alias vdontcare "cmd vote abstain"
-alias vabstain "cmd vote abstain"
-
+// aliases for client only
+alias vmaster   "qc_cmd_cmd vote master"
+alias vlogin    "qc_cmd_cmd vote master login ${* ?}"
+alias vdo       "qc_cmd_cmd vote master do ${* ?}"
+alias vyes      "qc_cmd_cl handlevote yes; cl_cmd vyes" // NOTE: COMPATIBILITY FOR 0.5 IS ADDED HERE WITH "VYES", REMOVE LATER
+alias vno       "qc_cmd_cl handlevote no; cl_cmd vno" // ^^^ same, see above
+alias vdontcare "qc_cmd_cmd vote abstain"
+alias vabstain  "qc_cmd_cmd vote abstain"
+
+// aliases for both client and server
+alias vcall     "qc_cmd_svcmd vote call ${* ?}"
+alias vhelp     "qc_cmd_svcmd vote help"
+alias vstatus   "qc_cmd_svcmd vote status"
+alias vstop     "qc_cmd_svcmd vote stop"
+
+// general
 alias vmap "vcall gotomap ${1 ?}"
 alias vnextmap "vcall nextmap ${1 ?}"
 alias vkick "vcall kick ${1 ?}"
@@ -284,10 +289,4 @@ alias vdoend "vdo endmatch"
 //  rcon server commands
 // ======================
 rcon_secure 1
-set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoauto movetored movetoblue movetoyellow movetopink"
-
-// =============================
-//  other miscellaneous aliases
-// =============================
-alias autoscreenshot "screenshot screenshots/autoscreenshot/${1 !}-${2 !}.jpg; echo \"^5A screenshot has been taken at request of the server.\""
-
+set rcon_restricted_commands "restart fraglimit chmap gotomap endmatch reducematchtime extendmatchtime allready kick kickban \"sv_cmd bans\" \"sv_cmd unban *\" status \"sv_cmd teamstatus\" movetoauto movetored movetoblue movetoyellow movetopink"
\ No newline at end of file
index 75950a9cd7fec160222a90d1ef53e615d065c6b0..52c14b2be90d9f41000144d0ad6a9060b27e3e35 100644 (file)
@@ -324,14 +324,15 @@ set g_teleport_maxspeed 0 "maximum speed that a player can keep when going throu
 set g_respawn_ghosts 1 "if 1 dead bodies become ghosts and float away when the player respawns"
 set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate"
 set g_respawn_ghosts_maxtime 6 "maximum amount of time a respawn ghost can last, minimum time is half this value. 0 disables and ghosts fade when the body would"
+set cl_deathglow 0.8 "number of seconds during which dead bodies glow out"
 
 set sv_gibhealth 100 "Minus health a dead body must have in order to get gibbed"
 
 // fragmessage: This allows extra information to be displayed with the frag centerprints. 
-set sv_fraginfo_ping 1 "Enable ping display information, 0 = Never display; 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
-set sv_fraginfo_handicap 1 "Enable handicap display information, 0 = Never display; 1 = Only when the player has handicap on; 2 = Always display (Displays Off if off)"
-set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0 = Never display; 1 = Always display (Only available for the person who was killed)"
-set sv_fraginfo_typefrag 1 "Enable typefrag display information, 0 = Never display; 1 = Always display"
+set sv_fraginfo 1 "Enable extra frag message information, 0 = Never display, 1 = Display only in warmup mode; 2 = Always display"
+set sv_fraginfo_ping 1 "Enable ping display information, 0 = Never display, 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
+set sv_fraginfo_handicap 1 "Enable handicap display information, 0 = Never display, 1 = Only when the player has handicap on, 2 = Always display (Displays Off if disabled)"
+set sv_fraginfo_stats 1 "Enable statistics (health/armor) display information, 0 = Never display, 1 = Always display (Only available for the person who was killed)"
 
 // use default physics
 set sv_friction_on_land 0
@@ -437,6 +438,7 @@ set bot_ai_aimskill_order_filter_5th 0.5 "Movement prediction filter. Used rarel
 
 // waypoint editor enable
 set g_waypointeditor 0
+set g_waypointeditor_auto 0 "Automatically create waypoints for bots while playing; BEWARE, this currently creates too many of them"
 set bot_ignore_bots 0  "When set, bots don't shoot at other bots"
 set bot_join_empty 0   "When set, bots also play if no player has joined the server"
 set bot_vs_human 0     "Bots and humans play in different teams when set. positive values to make an all-bot blue team, set to negative values to make an all-bot red team, the absolute value is the ratio bots vs humans (1 for equal count). Changes will be correctly applied only from the next game"
@@ -1540,7 +1542,7 @@ set cl_handicap 1 "the higher, the more damage you will receive (client setting)
 
 seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such. (client setting) NOTE: reconnect or use sendcvar command to update the choice." 
 
-seta cl_autoscreenshot 0 "client option to automatically take a screenshot once the map has ended (see also sv_autoscreenshot)"
+seta cl_autoscreenshot 1 "Take a screenshot upon the end of a match... 0 = Disable completely, 1 = Allow sv_autoscreenshot to take a screenshot when requested, 2 = Always take an autoscreenshot anyway."
 
 // must be at the bottom of this file:
 // alias for switching the teamselect menu
diff --git a/gfx/m_nomap.jpg b/gfx/m_nomap.jpg
deleted file mode 100644 (file)
index 79675d6..0000000
Binary files a/gfx/m_nomap.jpg and /dev/null differ
diff --git a/gfx/menu/luminos/nopreview_map.tga b/gfx/menu/luminos/nopreview_map.tga
new file mode 100644 (file)
index 0000000..c4fed58
Binary files /dev/null and b/gfx/menu/luminos/nopreview_map.tga differ
diff --git a/gfx/menu/luminos/nopreview_menuskin.tga b/gfx/menu/luminos/nopreview_menuskin.tga
new file mode 100644 (file)
index 0000000..c4fed58
Binary files /dev/null and b/gfx/menu/luminos/nopreview_menuskin.tga differ
diff --git a/gfx/menu/luminos/nopreview_player.tga b/gfx/menu/luminos/nopreview_player.tga
new file mode 100644 (file)
index 0000000..c4fed58
Binary files /dev/null and b/gfx/menu/luminos/nopreview_player.tga differ
diff --git a/gfx/menu/wickedx/nopreview_map.tga b/gfx/menu/wickedx/nopreview_map.tga
new file mode 100644 (file)
index 0000000..2fc5c5d
Binary files /dev/null and b/gfx/menu/wickedx/nopreview_map.tga differ
diff --git a/gfx/menu/wickedx/nopreview_menuskin.tga b/gfx/menu/wickedx/nopreview_menuskin.tga
new file mode 100644 (file)
index 0000000..2fc5c5d
Binary files /dev/null and b/gfx/menu/wickedx/nopreview_menuskin.tga differ
diff --git a/gfx/menu/wickedx/nopreview_player.tga b/gfx/menu/wickedx/nopreview_player.tga
new file mode 100644 (file)
index 0000000..2fc5c5d
Binary files /dev/null and b/gfx/menu/wickedx/nopreview_player.tga differ
diff --git a/gfx/menu/xaw/nopreview_map.tga b/gfx/menu/xaw/nopreview_map.tga
new file mode 100644 (file)
index 0000000..7b01510
Binary files /dev/null and b/gfx/menu/xaw/nopreview_map.tga differ
diff --git a/gfx/menu/xaw/nopreview_menuskin.tga b/gfx/menu/xaw/nopreview_menuskin.tga
new file mode 100644 (file)
index 0000000..7b01510
Binary files /dev/null and b/gfx/menu/xaw/nopreview_menuskin.tga differ
diff --git a/gfx/menu/xaw/nopreview_player.tga b/gfx/menu/xaw/nopreview_player.tga
new file mode 100644 (file)
index 0000000..7b01510
Binary files /dev/null and b/gfx/menu/xaw/nopreview_player.tga differ
index 5282910a2ad6288f756e48f599f539bc9e153ac8..e4519b2b3d93fef8061208aaf78ec95c1d2b1773 100644 (file)
@@ -271,3 +271,5 @@ float nex_charge_movingavg;
 float serverflags;
 
 float uid2name_dialog;
+
+.float csqcmodel_isdead; // used by shownames and miscfunctions (float getplayerisdead(float) {}) to know when a player is dead
\ No newline at end of file
index 3798edf8a78ca20cb03853a05ccd57b6c614b926..8facbf500ff9a8e2b28567b7b96bd85c88c85ebf 100644 (file)
@@ -196,6 +196,8 @@ void CSQC_Init(void)
 
        hud_configure_prev = -1;
        tab_panel = -1;
+
+       draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin")));
 }
 
 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
index 556859a466ed66828f27fb6c72229b2653dd8126..5ab52d5f19ae51c602e624d10609e13f4067df32 100644 (file)
@@ -372,6 +372,8 @@ void CSQC_UpdateView(float w, float h)
        vector vf_size, vf_min;
        float a;
 
+       ++framecount;
+
        hud = getstati(STAT_HUD);
 
        if(checkextension("DP_CSQC_MINFPS_QUALITY"))
index 31fe318458f3af5a07e5114d6108b4094292c34f..705e2c51954524060fdd20ba399fd236c074f3e8 100644 (file)
@@ -384,3 +384,4 @@ float autocvar_cl_forcemyplayercolors;
 float autocvar__cl_playerskin;
 string autocvar__cl_playermodel;
 float autocvar_cl_precacheplayermodels;
+float autocvar_cl_deathglow;
index 77cbddd85d5a644f8c77b53d5272162937f0c9ae..95032dce7bd4b013ab22701cda09ebf3521486aa 100644 (file)
@@ -323,7 +323,7 @@ void LocalCommand_(float request)
 void LocalCommand_macro_help()
 {
        #define CLIENT_COMMAND(name,function,description) \
-               { if(strtolower(description) != string_null) { print("  ^2", name, "^7: ", description, "\n"); } }
+               { if(strtolower(description) != "") { print("  ^2", name, "^7: ", description, "\n"); } }
                
        CLIENT_COMMANDS(0, 0)
        #undef CLIENT_COMMAND
@@ -356,7 +356,7 @@ float LocalCommand_macro_usage(float argc)
 void LocalCommand_macro_write_aliases(float fh)
 {
        #define CLIENT_COMMAND(name,function,description) \
-               { CMD_Write_Alias("qc_cmd_cl", name, description); }
+               { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } }
                
        CLIENT_COMMANDS(0, 0)
        #undef CLIENT_COMMAND
index 92b8983b34428c0965aaeb972e1a8b21868a2284..a0a6e150e373dee3a051e175a75e8842cd4a4618 100644 (file)
@@ -1,3 +1,5 @@
+void CSQCModel_Hook_PreDraw();
+
 .float isplayermodel;
 
 // FEATURE: LOD
@@ -12,13 +14,6 @@ void CSQCPlayer_LOD_Apply(void)
                string modelname = self.model;
                string s;
 
-               if(!fexists(modelname))
-               {
-                       print(sprintf(_("Trying to use non existing model %s. "), modelname));
-                       modelname = cvar_defstring("_cl_playermodel");
-                       print(sprintf(_("Reverted to %s.\n"), modelname));
-               }
-
                // set modelindex
                self.lodmodelindex0 = self.modelindex;
                self.lodmodelindex1 = self.modelindex;
@@ -72,17 +67,27 @@ void CSQCPlayer_LOD_Apply(void)
 
 // FEATURE: forcemodel (MUST be called BEFORE LOD!)
 string forceplayermodels_model;
+float forceplayermodels_modelisgoodmodel;
 float forceplayermodels_modelindex;
 float forceplayermodels_skin;
 
 string forceplayermodels_mymodel;
+float forceplayermodels_myisgoodmodel;
 float forceplayermodels_mymodelindex;
 
 float forceplayermodels_attempted;
+
 .string forceplayermodels_savemodel;
 .float forceplayermodels_savemodelindex;
 .float forceplayermodels_saveskin;
 .float forceplayermodels_savecolormap;
+
+.string forceplayermodels_isgoodmodel_mdl;
+.float forceplayermodels_isgoodmodel;
+
+string forceplayermodels_goodmodel;
+float forceplayermodels_goodmodelindex;
+
 void CSQCPlayer_ForceModel_PreUpdate(void)
 {
        self.model = self.forceplayermodels_savemodel;
@@ -96,19 +101,38 @@ void CSQCPlayer_ForceModel_PostUpdate(void)
        self.forceplayermodels_savemodelindex = self.modelindex;
        self.forceplayermodels_saveskin = self.skin;
        self.forceplayermodels_savecolormap = self.colormap;
+
+       if(self.forceplayermodels_savemodel != self.forceplayermodels_isgoodmodel_mdl)
+       {
+               self.forceplayermodels_isgoodmodel = fexists(self.forceplayermodels_savemodel);
+               self.forceplayermodels_isgoodmodel_mdl = self.forceplayermodels_savemodel;
+               if(!self.forceplayermodels_isgoodmodel)
+                       print(sprintf("Warning: missing model %s has been used\n", self.forceplayermodels_savemodel));
+       }
 }
 void CSQCPlayer_ForceModel_Apply(float islocalplayer)
 {
-       // first, try finding it from the server
+       // which one is ALWAYS good?
+       if not(forceplayermodels_goodmodel)
+       {
+               entity e;
+               e = spawn();
+               setmodel(e, cvar_defstring("_cl_playermodel"));
+               forceplayermodels_goodmodel = e.model;
+               forceplayermodels_goodmodelindex = e.modelindex;
+               remove(e);
+       }
 
+       // first, try finding it from the server
        if(self.forceplayermodels_savemodelindex && self.forceplayermodels_savemodel != "null")
        {
                if(islocalplayer)
                {
                        // trust server's idea of "own player model"
-                       forceplayermodels_model = self.model;
-                       forceplayermodels_modelindex = self.modelindex;
-                       forceplayermodels_skin = self.skin;
+                       forceplayermodels_modelisgoodmodel = self.forceplayermodels_isgoodmodel;
+                       forceplayermodels_model = self.forceplayermodels_savemodel;
+                       forceplayermodels_modelindex = self.forceplayermodels_savemodelindex;
+                       forceplayermodels_skin = self.forceplayermodels_saveskin;
                        forceplayermodels_attempted = 1;
                }
        }
@@ -122,6 +146,7 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
                entity e;
                e = spawn();
                setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
+               forceplayermodels_modelisgoodmodel = fexists(e.model);
                forceplayermodels_model = e.model;
                forceplayermodels_modelindex = e.modelindex;
                forceplayermodels_skin = autocvar__cl_playerskin;
@@ -133,35 +158,42 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
                entity e;
                e = spawn();
                setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
+               forceplayermodels_myisgoodmodel = fexists(e.model);
                forceplayermodels_mymodel = e.model;
                forceplayermodels_mymodelindex = e.modelindex;
                remove(e);
        }
 
        // apply it
-       if(autocvar_cl_forcemyplayermodel != "" && forceplayermodels_mymodelindex && self.entnum == player_localnum + 1)
+       if(autocvar_cl_forcemyplayermodel != "" && forceplayermodels_myisgoodmodel && islocalplayer)
        {
                self.model = forceplayermodels_mymodel;
                self.modelindex = forceplayermodels_mymodelindex;
                self.skin = autocvar_cl_forcemyplayerskin;
        }
-       else if(autocvar_cl_forceplayermodels && forceplayermodels_modelindex)
+       else if(autocvar_cl_forceplayermodels && forceplayermodels_modelisgoodmodel)
        {
                self.model = forceplayermodels_model;
                self.modelindex = forceplayermodels_modelindex;
                self.skin = forceplayermodels_skin;
        }
-       else
+       else if(self.forceplayermodels_isgoodmodel)
        {
                self.model = self.forceplayermodels_savemodel;
                self.modelindex = self.forceplayermodels_savemodelindex;
                self.skin = self.forceplayermodels_saveskin;
        }
+       else
+       {
+               self.model = forceplayermodels_goodmodel;
+               self.modelindex = forceplayermodels_goodmodelindex;
+               self.skin = self.forceplayermodels_saveskin;
+       }
 
        // forceplayercolors too
        if(!teamplay)
        {
-               if(autocvar_cl_forcemyplayercolors && self.entnum == player_localnum + 1)
+               if(autocvar_cl_forcemyplayercolors && islocalplayer)
                        self.colormap = 1024 + autocvar_cl_forcemyplayercolors;
                else if(autocvar_cl_forceplayercolors)
                        self.colormap = player_localnum + 1;
@@ -174,6 +206,8 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
 .float csqcmodel_saveframe3;
 .float csqcmodel_saveframe4;
 .float csqcmodel_framecount;
+
+#define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1)
 void CSQCPlayer_FallbackFrame_PreUpdate(void)
 {
        self.frame = self.csqcmodel_saveframe;
@@ -193,18 +227,16 @@ void CSQCPlayer_FallbackFrame_PostUpdate(float isnew)
        if(isnew)
        {
 #define FIX_FRAMETIME(f,ft) \
-               switch(self.f) \
+               if(IS_DEAD_FRAME(self.f)) \
                { \
-                       case 0: \
-                       case 1: \
-                               self.ft = 0; \
-                               break; \
+                       self.ft = self.death_time; \
                }
                FIX_FRAMETIME(frame, frame1time)
                FIX_FRAMETIME(frame2, frame2time)
                FIX_FRAMETIME(frame3, frame3time)
                FIX_FRAMETIME(frame4, frame4time)
        }
+       self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame);
 }
 float CSQCPlayer_FallbackFrame(float f)
 {
@@ -232,16 +264,6 @@ void CSQCPlayer_FallbackFrame_Apply(void)
        self.frame4 = CSQCPlayer_FallbackFrame(self.frame4);
 }
 
-// FEATURE: auto glowmod
-.vector glowmod;
-void CSQCPlayer_GlowMod_Apply(void)
-{
-       if(self.colormap > 0)
-               self.glowmod = colormapPaletteColor(((self.colormap >= 1024) ? self.colormap : stof(getplayerkeyvalue(self.colormap - 1, "colors"))) & 0x0F, TRUE) * 2;
-       else
-               self.glowmod = '1 1 1';
-}
-
 // FEATURE: auto tag_index
 .entity tag_entity;
 .float tag_entity_lastmodelindex;
@@ -260,6 +282,15 @@ void CSQCModel_AutoTagIndex_Apply(void)
                        self.tag_entity = findfloat(world, entnum, self.tag_networkentity);
                        changed = 1;
                }
+
+               // recursive predraw call to fix issues with forcemodels and LOD if bone indexes mismatch
+               {
+                       entity oldself = self;
+                       self = self.tag_entity;
+                       CSQCModel_Hook_PreDraw();
+                       self = oldself;
+               }
+
                if(self.tag_entity.modelindex != self.tag_entity_lastmodelindex)
                {
                        self.tag_entity_lastmodelindex = self.tag_entity.modelindex;
@@ -343,7 +374,7 @@ void CSQCModel_Effects_PostUpdate(void)
 void CSQCModel_Effects_Apply(void)
 {
        float eff = self.csqcmodel_effects;
-       eff &~= CSQCMODEL_EF_INVISIBLE;
+       eff &~= CSQCMODEL_EF_RESPAWNGHOST;
 
        self.renderflags &~= (RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
        self.effects = 0;
@@ -356,7 +387,7 @@ void CSQCModel_Effects_Apply(void)
                adddynamiclight(self.origin, 400, '3 3 3');
        if(eff & EF_DIMLIGHT)
                adddynamiclight(self.origin, 200, '1.5 1.5 1.5');
-       if((eff & EF_NODRAW) || (self.csqcmodel_effects & CSQCMODEL_EF_INVISIBLE) || (self.alpha < 0))
+       if((eff & EF_NODRAW) || (self.alpha < 0))
                self.drawmask = 0;
        if(eff & EF_ADDITIVE)
                self.renderflags |= RF_ADDITIVE;
@@ -407,11 +438,45 @@ void CSQCModel_Effects_Apply(void)
                Projectile_DrawTrail(self.origin);
        else
                Projectile_ResetTrail(self.origin);
+
+       if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
+               self.renderflags |= RF_ADDITIVE;
+               // also special in CSQCPlayer_GlowMod_Apply
+}
+
+// FEATURE: auto glowmod
+.vector glowmod;
+void CSQCPlayer_GlowMod_Apply(void)
+{
+       float cm = self.colormap;
+
+       if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
+               cm = 1024;
+
+       if(self.colormap > 0)
+               self.glowmod = colormapPaletteColor(((self.colormap >= 1024) ? self.colormap : stof(getplayerkeyvalue(self.colormap - 1, "colors"))) & 0x0F, TRUE) * 2;
+       else
+               self.glowmod = '1 1 1';
+
+       if(autocvar_cl_deathglow > 0)
+               if(self.csqcmodel_isdead)
+               {
+                       self.glowmod = self.glowmod * bound(0, 1 - (time - self.death_time) / autocvar_cl_deathglow, 1);
+                       // prevent the zero vector
+                       self.glowmod_x = max(self.glowmod_x, 0.0001);
+                       self.glowmod_y = max(self.glowmod_y, 0.0001);
+                       self.glowmod_z = max(self.glowmod_z, 0.0001);
+               }
 }
 
 // general functions
-void CSQCModel_Hook_PreDraw(float isplayer, float islocalplayer)
+.float csqcmodel_predraw_run;
+void CSQCModel_Hook_PreDraw()
 {
+       if(self.csqcmodel_predraw_run == framecount)
+               return;
+       self.csqcmodel_predraw_run = framecount;
+
        if(!self.modelindex || self.model == "null")
        {
                self.drawmask = 0;
@@ -422,14 +487,13 @@ void CSQCModel_Hook_PreDraw(float isplayer, float islocalplayer)
 
        if(self.isplayermodel) // this checks if it's a player MODEL!
        {
+               CSQCPlayer_ForceModel_Apply(self.entnum == player_localnum + 1);
                CSQCPlayer_GlowMod_Apply();
-               CSQCPlayer_ForceModel_Apply(islocalplayer);
                CSQCPlayer_LOD_Apply();
                CSQCPlayer_FallbackFrame_Apply();
        }
 
-       if(!isplayer) // this checks if it's a player SLOT!
-               CSQCModel_AutoTagIndex_Apply();
+       CSQCModel_AutoTagIndex_Apply();
 
        CSQCModel_Effects_Apply();
 }
index 9349d9c5c4ce2bb13be2dba55659580467f4bcf2..43e7b64995e3b991f05b72f0623f684fa2892acd 100644 (file)
@@ -158,3 +158,4 @@ entity entcs_receiver[255]; // 255 is the engine limit on maxclients
 
 float hud;
 float view_quality;
+float framecount;
index 769b921a43fd39d3fe5bf2937b0505d542561eed..4cb8dad05fff509e7a905ffc6627a850df8459fb 100644 (file)
@@ -88,7 +88,10 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
        }
        else
        {
-               drawpic(pos, pic, img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL);
+               if(drawgetimagesize(pic) == '0 0 0')
+                       drawpic(pos, draw_UseSkinFor("nopreview_map"), img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL);
+               else
+                       drawpic(pos, pic, img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL);
        }
 
        if(id == mv_ownvote)
index 2bc20e9510f17f1c4513521e9cd9a217dca9933d..93a47f50e5f5d94cf5fb0298bf16ea0003399824 100644 (file)
@@ -591,3 +591,14 @@ vector getplayerorigin(float pl)
 
        return GETPLAYERORIGIN_ERROR;
 }
+
+float getplayerisdead(float pl)
+{
+       entity e;
+       
+       e = CSQCModel_server2csqc(pl + 1);
+       if(e)
+               return e.csqcmodel_isdead;
+       
+       return FALSE;
+}
\ No newline at end of file
index d5e24888d34a79e03d2de8db4a8c19ca22c8219f..c2bff62c89172c3a0a203a801694182235b1da0a 100644 (file)
@@ -5,7 +5,8 @@
 // self.sameteam = player is on same team as local client
 // self.fadedelay = time to wait before name tag starts fading in for enemies
 // self.pointtime = last time you pointed at this player
-//
+// self.csqcmodel_isdead = value of csqcmodel_isdead to know when the player is dead or not
+
 const float SHOWNAMES_FADESPEED = 4;
 const float SHOWNAMES_FADEDELAY = 0.4;
 void Draw_ShowNames(entity ent)
@@ -90,7 +91,7 @@ void Draw_ShowNames(entity ent)
                        ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime); 
                        ent.fadedelay = 0; // reset fade in delay, enemy has left the view
                }
-               else if(ent.healthvalue < 1) // dead player, fade out slowly
+               else if(ent.csqcmodel_isdead) // dead player, fade out slowly
                        ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime); 
                else if(overlap) // tag overlap detected, fade out
                        ent.alpha = max(0, ent.alpha - SHOWNAMES_FADESPEED * frametime); 
@@ -217,6 +218,8 @@ void Draw_ShowNames_All()
                e.origin = getplayerorigin(i);
                if(e.origin == GETPLAYERORIGIN_ERROR)
                        continue;
+                       
+               e.csqcmodel_isdead = getplayerisdead(i);
 
                Draw_ShowNames(e);
        }
index adbfa57120376e5091f3c957d05557b9873de870..6e3f899ddc31cb0754465bacec20e7fac61c0eda 100644 (file)
@@ -2,4 +2,4 @@
 .float armorvalue;
 .float sameteam;
 .float fadedelay;
-.float pointtime;
+.float pointtime;
\ No newline at end of file
index e0dfce4ca34d0ec2a3623d5f9b0ecc35eed9ff46..bdeab298ebe9172fb6239359afef528a3342ef24 100644 (file)
        CSQCMODEL_PROPERTY(4, float, ReadByte, WriteByte, modelflags) \
        CSQCMODEL_PROPERTY_SCALED(8, float, ReadByte, WriteByte, alpha, 254, -1, 254) \
        CSQCMODEL_PROPERTY(16, float, ReadByte, WriteByte, skin) \
-       CSQCMODEL_IF(isplayer) \
-       CSQCMODEL_ENDIF \
+       CSQCMODEL_PROPERTY(32, float, ReadApproxPastTime, WriteApproxPastTime, death_time) \
        CSQCMODEL_IF(!isplayer) \
-               CSQCMODEL_PROPERTY(32, TAG_ENTITY_TYPE, ReadShort, WriteEntity, TAG_ENTITY_NAME) \
-               CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \
-               CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \
-               CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \
+               CSQCMODEL_PROPERTY(64, TAG_ENTITY_TYPE, ReadShort, WriteEntity, TAG_ENTITY_NAME) \
+               CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \
+               CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \
+               CSQCMODEL_PROPERTY_SCALED(128, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \
        CSQCMODEL_ENDIF
 // TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
 
@@ -37,7 +36,7 @@
 #define CSQCMODEL_HOOK_POSTUPDATE \
        CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer);
 #define CSQCMODEL_HOOK_PREDRAW \
-       CSQCModel_Hook_PreDraw(isplayer, islocalplayer);
+       CSQCModel_Hook_PreDraw();
 #define CSQCPLAYER_HOOK_POSTCAMERASETUP
 
 // force updates of player entities that often even if unchanged
@@ -82,4 +81,4 @@ float autocvar_sv_use_csqc_players;
 # endif
 #endif
 
-#define CSQCMODEL_EF_INVISIBLE EF_SELECTABLE
+#define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
index 19339a36e99635908c379b21383ceff01d7dc42a..57e653113235c27ac3babe72102a286a1c249366 100644 (file)
@@ -39,6 +39,16 @@ void wordwrap_sprint(string s, float l)
 #endif
 #endif
 
+#ifndef SVQC
+string draw_UseSkinFor(string pic)
+{
+       if(substring(pic, 0, 1) == "/")
+               return substring(pic, 1, strlen(pic)-1);
+       else
+               return strcat(draw_currentSkin, "/", pic);
+}
+#endif
+
 string unescape(string in)
 {
        float i, len;
@@ -2164,3 +2174,41 @@ void m_shutdown()
        }
        cvar_settemp_restore(); // this must be done LAST, but in any case
 }
+
+#define APPROXPASTTIME_ACCURACY_REQUIREMENT 0.05
+#define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+// this will use the value:
+//   128
+// accuracy near zero is APPROXPASTTIME_MAX/(256*255)
+// accuracy at x is 1/derivative, i.e.
+//   APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536
+#ifdef SVQC
+void WriteApproxPastTime(float dst, float t)
+{
+       float dt = time - t;
+
+       // warning: this is approximate; do not resend when you don't have to!
+       // be careful with sendflags here!
+       // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75
+
+       // map to range...
+       dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt));
+
+       // round...
+       dt = rint(bound(0, dt, 255));
+
+       WriteByte(dst, dt);
+}
+#endif
+#ifdef CSQC
+float ReadApproxPastTime()
+{
+       float dt = ReadByte();
+
+       // map from range...PPROXPASTTIME_MAX / 256
+       dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt));
+
+       return servertime - dt;
+}
+#endif
index a8dd88c2f05b7b7490bd989a8015969533dc3106..4b0526815d65763eb11f2cbe7b51e2596a060ec4 100644 (file)
@@ -20,6 +20,11 @@ void wordwrap_sprint(string s, float l);
 #endif
 void wordwrap_cb(string s, float l, void(string) callback)
 
+#ifndef SVQC
+string draw_currentSkin;
+string draw_UseSkinFor(string pic);
+#endif
+
 // iterative depth-first search, with fields that go "up", "down left" and "right" in a tree
 // for each element, funcPre is called first, then funcPre and funcPost for all its children, and funcPost last
 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass);
@@ -285,3 +290,10 @@ float InterpretBoolean(string input);
 
 // generic shutdown handler
 void Shutdown();
+
+#ifdef SVQC
+void WriteApproxPastTime(float dst, float t);
+#endif
+#ifdef CSQC
+float ReadApproxPastTime();
+#endif
index ec7fe0ddf171d2700138aa327a029de89596a511..dc9627d9e8173fcc86a9c3a45408d71e101f0b6d 100644 (file)
@@ -99,22 +99,31 @@ void CSQCPlayer_PredictTo(float endframe)
 
        csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
 
+       // FIXME do we really NEED this? dead players have servercommandframe
+       // == 0 and thus won't predict
        if (getstatf(STAT_HEALTH) <= 0)
        {
                csqcplayer_moveframe = clientcommandframe;
                getinputstate(csqcplayer_moveframe-1);
+               print("the Weird code path got hit\n");
                return;
        }
 
-       while(csqcplayer_moveframe < endframe)
+       if(csqcplayer_moveframe >= endframe)
        {
-               if (!getinputstate(csqcplayer_moveframe))
+               getinputstate(csqcplayer_moveframe - 1);
+       }
+       else
+       {
+               do
                {
-                       break;
+                       if (!getinputstate(csqcplayer_moveframe))
+                               break;
+                       runstandardplayerphysics(self);
+                       CSQCPlayer_SetMinsMaxs();
+                       csqcplayer_moveframe++;
                }
-               runstandardplayerphysics(self);
-               CSQCPlayer_SetMinsMaxs();
-               csqcplayer_moveframe++;
+               while(csqcplayer_moveframe < endframe);
        }
 
        //add in anything that was applied after (for low packet rate protocols)
@@ -130,6 +139,9 @@ void(entity e, float fl) V_CalcRefdef = #640; // DP_CSQC_V_CALCREFDEF
 
 void CSQCPlayer_SetCamera()
 {
+       vector v0;
+       v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+
        if(csqcplayer)
        {
                entity oldself;
@@ -161,6 +173,9 @@ void CSQCPlayer_SetCamera()
 
                        // override it back just in case
                        self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+
+                       // set velocity
+                       self.velocity = v0;
                }
                else
                {
@@ -168,12 +183,11 @@ void CSQCPlayer_SetCamera()
                        {
                                vector o, v;
                                o = self.origin;
-                               v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
                                csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
                                CSQCPlayer_PredictTo(servercommandframe + 1);
                                CSQCPlayer_SetPredictionError(o - self.origin);
                                self.origin = o;
-                               self.velocity = v;
+                               self.velocity = v0;
 
                                // get crouch state from the server
                                if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
@@ -237,6 +251,13 @@ void CSQCPlayer_SetCamera()
                if(input_buttons & 4)
                        refdefflags |= REFDEFFLAG_JUMPING;
 
+               // note: these two only work in WIP2, but are harmless in WIP1
+               if(getstati(STAT_HEALTH) <= 0)
+                       refdefflags |= REFDEFFLAG_DEAD;
+
+               if(intermission)
+                       refdefflags |= REFDEFFLAG_INTERMISSION;
+
                V_CalcRefdef(view, refdefflags);
        }
        else
index 0d3088f9cfc3acb83e10eae556dea6acd0d748aa..623fb01c781a6db13f031fb69c6a16dcb3c307e4 100644 (file)
@@ -910,6 +910,7 @@ const float VF_MINFPS_QUALITY   = 401;
 //1 should lead to an unmodified view
 
 //DP_CSQC_V_CALCREFDEF_WIP1
+//DP_CSQC_V_CALCREFDEF_WIP2
 //idea: divVerent
 //darkplaces implementation: divVerent
 //builtin definitions:
@@ -919,9 +920,13 @@ float PMF_DUCKED = 4;
 float PMF_ONGROUND = 8;
 float REFDEFFLAG_TELEPORTED = 1;
 float REFDEFFLAG_JUMPING = 2;
+float REFDEFFLAG_DEAD = 4;
+float REFDEFFLAG_INTERMISSION = 8;
 //- use this on the player entity after performing prediction
 //- pass REFDEFFLAG_TELEPORTED if the player teleported since last frame
 //- pass REFDEFFLAG_JUMPING if jump button is pressed
+//- pass REFDEFFLAG_DEAD if dead (DP_CSQC_V_CALCREFDEF_WIP2)
+//- pass REFDEFFLAG_INTERMISSION if in intermission (DP_CSQC_V_CALCREFDEF_WIP2)
 //- the player entity needs to have origin, velocity, pmove_flags set according
 //  to prediction (the above two PMF_ flags are used in the player's pmove_flags)
 //- NOTE: to check for this, ALSO OR a check with DP_CSQC_V_CALCREFDEF to also support
index 12b56d8dae8f2632ef8bbb84c847a2fde28863dd..7fe4aea3bdc38e57c99eb976b90326f8658198ca 100644 (file)
@@ -2,14 +2,6 @@ string draw_mousepointer;
 vector draw_mousepointer_offset;
 vector draw_mousepointer_size;
 
-string draw_UseSkinFor(string pic)
-{
-       if(substring(pic, 0, 1) == "/")
-               return substring(pic, 1, strlen(pic)-1);
-       else
-               return strcat(draw_currentSkin, "/", pic);
-}
-
 void draw_setMousePointer(string pic, vector theSize, vector theOffset)
 {
        draw_mousepointer = strzone(draw_UseSkinFor(pic));
@@ -61,10 +53,10 @@ vector boxToGlobalSize(vector v, vector theScale)
        return v;
 }
 
-void draw_PreloadPicture(string pic)
+string draw_PreloadPicture(string pic)
 {
        pic = draw_UseSkinFor(pic);
-       precache_pic(pic);
+       return precache_pic(pic);
 }
 
 void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
index 63e22bd6357d85cea28f20cc99c825be20e7b795..0f5811713d6f3c1b66f3f38ae2742d3bb2b810ed 100644 (file)
@@ -14,7 +14,7 @@ void draw_reset(float cw, float ch, float ox, float oy);
 void draw_setMousePointer(string pic, vector theSize, vector theOffset);
 void draw_drawMousePointer(vector where);
 
-void draw_PreloadPicture(string pic);
+string draw_PreloadPicture(string pic);
 void draw_ButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha);
 void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha);
 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize);
@@ -38,7 +38,5 @@ vector globalToBoxSize(vector v, vector scale);
 
 float draw_NeedResizeNotify;
 
-string draw_currentSkin;
-
 float draw_TextWidth_WithColors(string s, vector size);
 float draw_TextWidth_WithoutColors(string s, vector size);
index 04f7a083c2d32a035ac9bb5d15e6c2e1c127b72e..0537967bd69cf564c33986968426c98e8acb69a7 100644 (file)
@@ -275,7 +275,11 @@ void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, flo
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
 
        s = ftos(p);
-       draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       if(draw_PictureSize(strcat("/maps/", campaign_mapname[i])) == '0 0 0')
+               draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       else
+               draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+
        if(i < me.campaignIndex)
                draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1);
        if(i <= me.campaignIndex)
index 31ea3e084bbe8f67623e7bd3f2c3bf1fa4922267..169e9734b16a6b69ae1b0633abb69ab75f5613e9 100644 (file)
@@ -54,7 +54,10 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, float i, entity mlb)
        me.authorLabel.setText(me.authorLabel, me.currentMapAuthor);
        me.descriptionLabel.setText(me.descriptionLabel, me.currentMapDescription);
        me.featuresLabel.setText(me.featuresLabel, me.currentMapFeaturesText);
-       me.previewImage.src = me.currentMapPreviewImage;
+       if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0')
+               me.previewImage.src = "nopreview_map";
+       else
+               me.previewImage.src = me.currentMapPreviewImage;
 
        for(i = 0; i < GameType_GetCount(); ++i)
        {
index 650e343c6b29f6c07db10bd00b91983054a3247a..14bf48ec9edf0f00282075f5549ce40f3456587b 100644 (file)
@@ -186,7 +186,11 @@ void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float is
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG);
 
        s = ftos(p);
-       draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0')
+               draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       else
+               draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+
        if(included)
                draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1);
        s = draw_TextShortenToWidth(MapInfo_Map_titlestring, me.columnNameSize, 0, me.realFontSize);
index ef02224dfaf8bc332b45d4947b78f131fcb33e83..61eb4a681651f6cd0d82ec7cac6274c26df3e499 100644 (file)
@@ -137,7 +137,10 @@ void XonoticPlayerModelSelector_go(entity me, float d)
        me.currentModelDescription = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC));
 
        // fix the image
-       me.src = me.currentModelImage;
+       if(draw_PictureSize(me.currentModelImage) == '0 0 0')
+               me.src = "nopreview_player";
+       else
+               me.src = me.currentModelImage;
        me.updateAspect(me);
 }
 
index bb01f974cbf1d0c6312b57cd8ec40c1f0107edca..68314cd027edc55b740ef325dbc6ca69e3a83065 100644 (file)
@@ -104,7 +104,10 @@ void XonoticSkinList_getSkins(entity me)
                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_NAME, substring(s, 9, strlen(s) - 24)); // the * part
                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_TITLE, _("<TITLE>"));
                bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_AUTHOR, _("<AUTHOR>"));
-               bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview"));
+               if(draw_PictureSize(strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview")) == '0 0 0')
+                       bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, "nopreview_menuskin");
+               else
+                       bufstr_set(buf, i * SKINPARM_COUNT + SKINPARM_PREVIEW, strcat("/gfx/menu/", substring(s, 9, strlen(s) - 24), "/skinpreview"));
                fh = fopen(language_filename(s), FILE_READ);
                if(fh < 0)
                {
index a5759020463d988a0817691052dc924aa1140f44..538d65307f1c3647d7c3264ae9c1e070ca99f42f 100644 (file)
@@ -1024,6 +1024,7 @@ float autocvar_g_turrets_unit_walker_turn_strafe;
 float autocvar_g_turrets_unit_walker_turn_swim;
 float autocvar_g_use_ammunition;
 float autocvar_g_waypointeditor;
+float autocvar_g_waypointeditor_auto;
 float autocvar_g_waypoints_for_items;
 float autocvar_g_weapon_charge_colormod_blue_full;
 float autocvar_g_weapon_charge_colormod_blue_half;
@@ -1104,10 +1105,10 @@ float autocvar_sv_eventlog_files_counter;
 string autocvar_sv_eventlog_files_nameprefix;
 string autocvar_sv_eventlog_files_namesuffix;
 float autocvar_sv_eventlog_files_timestamps;
+float autocvar_sv_fraginfo;
 float autocvar_sv_fraginfo_handicap;
 float autocvar_sv_fraginfo_ping;
 float autocvar_sv_fraginfo_stats;
-float autocvar_sv_fraginfo_typefrag;
 float autocvar_sv_friction;
 float autocvar_sv_friction_on_land;
 float autocvar_sv_gameplayfix_q2airaccelerate;
index 1658d7fac4f3c6de0c1313c7780258492b273914..039e21daed025bf588322272997456ed3f2fb240 100644 (file)
@@ -633,7 +633,7 @@ void bot_serverframe()
                        localcmd("quit\n");
        }
 
-       if (currentbots > 0 || autocvar_g_waypointeditor)
+       if (currentbots > 0 || autocvar_g_waypointeditor || autocvar_g_waypointeditor_auto)
        if (botframe_spawnedwaypoints)
        {
                if(botframe_cachedwaypointlinks)
@@ -685,6 +685,9 @@ void bot_serverframe()
        if (autocvar_g_waypointeditor)
                botframe_showwaypointlinks();
 
+       if (autocvar_g_waypointeditor_auto)
+               botframe_autowaypoints();
+
        if(time > bot_cvar_nextthink)
        {
                if(currentbots>0)
index 6aa6ea2a17f8a32b4f22df6d5c702df0ee591bd6..3387fdfef8fdcc1b4e5711cb9d3c165c979782b2 100644 (file)
@@ -332,12 +332,37 @@ void navigation_poproute()
        self.goalstack31 = world;
 }
 
+float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist)
+{
+       float dist;
+       dist = vlen(v - org);
+       if (bestdist > dist)
+       {
+               traceline(v, org, TRUE, ent);
+               if (trace_fraction == 1)
+               {
+                       if (walkfromwp)
+                       {
+                               if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode))
+                                       return TRUE;
+                       }
+                       else
+                       {
+                               if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode))
+                                       return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
 // find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
-entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
+entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, float bestdist)
 {
        entity waylist, w, best;
-       float dist, bestdist;
+       float dist;
        vector v, org, pm1, pm2;
+
        pm1 = ent.origin + ent.mins;
        pm2 = ent.origin + ent.maxs;
        waylist = findchain(classname, "waypoint");
@@ -362,7 +387,6 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
                te_plasmaburn(org);
 
        best = world;
-       bestdist = 1050;
 
        // box check failed, try walk
        w = waylist;
@@ -382,36 +406,20 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
                        }
                        else
                                v = w.origin;
-                       dist = vlen(v - org);
-                       if (bestdist > dist)
+                       if(navigation_waypoint_will_link(v, org, ent, walkfromwp, bestdist))
                        {
-                               traceline(v, org, TRUE, ent);
-                               if (trace_fraction == 1)
-                               {
-                                       if (walkfromwp)
-                                       {
-                                               //print("^1can I reach ", vtos(org), " from ", vtos(v), "?\n");
-                                               if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode))
-                                               {
-                                                       bestdist = dist;
-                                                       best = w;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode))
-                                               {
-                                                       bestdist = dist;
-                                                       best = w;
-                                               }
-                                       }
-                               }
+                               bestdist = vlen(v - org);
+                               best = w;
                        }
                }
                w = w.chain;
        }
        return best;
 }
+entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
+{
+       return navigation_findnearestwaypoint_withdist(ent, walkfromwp, 1050);
+}
 
 // finds the waypoints near the bot initiating a navigation query
 float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist)
index e2bcc5bd628e341000f7273cd9d7dee80da44167..4db72e407da5676ad73a15eab5a3c170a1aafd67 100644 (file)
@@ -877,3 +877,205 @@ void botframe_showwaypointlinks()
                player = find(player, classname, "player");
        }
 }
+
+float botframe_autowaypoints_fixdown(vector v)
+{
+       tracebox(v, PL_MIN, PL_MAX, v + '0 0 -64', MOVE_NOMONSTERS, world);
+       if(trace_fraction >= 1)
+               return 0;
+       return 1;
+}
+
+float botframe_autowaypoints_createwp(vector v, entity p, .entity fld)
+{
+       entity w;
+
+       w = find(world, classname, "waypoint");
+       while (w)
+       {
+               // if a matching spawnfunc_waypoint already exists, don't add a duplicate
+               if (boxesoverlap(v - '32 32 32', v + '32 32 32', w.absmin, w.absmax))
+               //if (boxesoverlap(v - '4 4 4', v + '4 4 4', w.absmin, w.absmax))
+                       return 0;
+               w = find(w, classname, "waypoint");
+       }
+
+       waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, 0));
+       return 1;
+}
+
+// return value:
+//    1 = WP created
+//    0 = no action needed
+//   -1 = temp fail, try from world too
+//   -2 = permanent fail, do not retry
+float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .entity fld)
+{
+       // make it possible to go from p to wp, if we can
+       // if wp is world, nearest is chosen
+
+       entity w;
+       vector porg;
+       float t, tmin, tmax;
+       vector o;
+       vector save;
+
+       if(!botframe_autowaypoints_fixdown(p.origin))
+               return -2;
+       porg = trace_endpos;
+
+       if(wp)
+       {
+               // if any WP w fulfills wp -> w -> porg, then switch from wp to w
+
+               // if wp -> porg, then OK
+               float maxdist;
+               if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050))
+               {
+                       // we may find a better one
+                       maxdist = vlen(wp.origin - porg);
+               }
+               else
+               {
+                       // accept any "good"
+                       maxdist = 2100;
+               }
+
+               float bestdist;
+               bestdist = maxdist;
+               w = find(world, classname, "waypoint");
+               while (w)
+               {
+                       if(w != wp && !(w.wpflags & WAYPOINTFLAG_NORELINK))
+                       {
+                               float d;
+                               d = vlen(wp.origin - w.origin) + vlen(w.origin - porg);
+                               if(d < bestdist)
+                                       if(navigation_waypoint_will_link(wp.origin, w.origin, p, walkfromwp, 1050))
+                                               if(navigation_waypoint_will_link(w.origin, porg, p, walkfromwp, 1050))
+                                               {
+                                                       bestdist = d;
+                                                       p.fld = w;
+                                               }
+                       }
+                       w = find(w, classname, "waypoint");
+               }
+               if(bestdist < maxdist)
+               {
+                       print("update chain to new nearest WP ", etos(p.fld), "\n");
+                       return 0;
+               }
+
+               if(bestdist < 2100)
+               {
+                       // we know maxdist < 2100
+                       // so wp -> porg is still valid
+                       // all is good
+                       p.fld = wp;
+                       return 0;
+               }
+
+               // otherwise, no existing WP can fix our issues
+       }
+       else
+       {
+               save = p.origin;
+               setorigin(p, porg);
+               w = navigation_findnearestwaypoint(p, walkfromwp);
+               setorigin(p, save);
+               if(w)
+               {
+                       p.fld = w;
+                       return 0;
+               }
+       }
+
+       tmin = 0;
+       tmax = 1;
+       for(;;)
+       {
+               if(tmax - tmin < 0.001)
+               {
+                       // did not get a good candidate
+                       return -1;
+               }
+
+               t = (tmin + tmax) * 0.5;
+               o = antilag_takebackorigin(p, time - t);
+               if(!botframe_autowaypoints_fixdown(o))
+                       return -1;
+               o = trace_endpos;
+
+               if(wp)
+               {
+                       if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
+                       {
+                               // we cannot walk from wp.origin to o
+                               // get closer to tmax
+                               tmin = t;
+                               continue;
+                       }
+               }
+               else
+               {
+                       save = p.origin;
+                       setorigin(p, o);
+                       w = navigation_findnearestwaypoint(p, walkfromwp);
+                       setorigin(p, save);
+                       if(!w)
+                       {
+                               // we cannot walk from any WP to o
+                               // get closer to tmax
+                               tmin = t;
+                               continue;
+                       }
+               }
+
+               // if we get here, o is valid regarding waypoints
+               // check if o is connected right to the player
+               // we break if it succeeds, as that means o is a good waypoint location
+               if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050))
+                       break;
+
+               // o is no good, we need to get closer to the player
+               tmax = t;
+       }
+
+       print("spawning a waypoint for connecting to ", etos(wp), "\n");
+       botframe_autowaypoints_createwp(o, p, fld);
+       return 1;
+}
+
+// automatically create missing waypoints
+.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
+void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
+{
+       float r;
+       r = botframe_autowaypoints_fix_from(p, walkfromwp, p.fld, fld);
+       if(r != -1)
+               return;
+       r = botframe_autowaypoints_fix_from(p, walkfromwp, world, fld);
+       if(r != -1)
+               return;
+
+       print("emergency: got no good nearby WP to build a link from, starting a new chain\n");
+       if(!botframe_autowaypoints_fixdown(p.origin))
+               return; // shouldn't happen, caught above
+       botframe_autowaypoints_createwp(trace_endpos, p, fld);
+}
+
+void botframe_autowaypoints()
+{
+       entity p;
+       entity wp0, wp1;
+       FOR_EACH_REALPLAYER(p)
+       {
+               if(p.deadflag)
+                       continue;
+               // going back is broken, so only fix waypoints to walk TO the player
+               //botframe_autowaypoints_fix(p, FALSE, botframe_autowaypoints_lastwp0);
+               botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1);
+               //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
+       }
+}
+
index 1bb800fd054ac5382b1a92491c2c6bf86ee0bc4e..fb7beea0fcaf74cfa73e4aa9deeded549cad3270 100644 (file)
@@ -57,3 +57,5 @@ entity waypoint_spawn(vector m1, vector m2, float f);
 entity waypoint_spawnpersonal(vector position);
 
 vector waypoint_fixorigin(vector position);
+
+void botframe_autowaypoints();
index f3f1d45e6617d6bfc897cfce68e1a8db92ad12a5..2ffc3e229eb28b4d509b3f5a5244dc51abb37386 100644 (file)
@@ -466,6 +466,7 @@ void PutObserverInServer (void)
        self.pauseregen_finished = 0;
        self.damageforcescale = 0;
        self.death_time = 0;
+       self.respawn_time = 0;
        self.alpha = 0;
        self.scale = 0;
        self.fade_time = 0;
@@ -775,6 +776,7 @@ void PutClientInServer (void)
                }
                self.damageforcescale = 2;
                self.death_time = 0;
+               self.respawn_time = 0;
                self.scale = 0;
                self.fade_time = 0;
                self.pain_frame = 0;
@@ -1750,7 +1752,6 @@ void UpdateChatBubble()
        else self.colormod = '1 1 1';
 }*/
 
-.float oldcolormap;
 void respawn(void)
 {
        if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
@@ -1760,21 +1761,15 @@ void respawn(void)
                self.movetype = MOVETYPE_FLY;
                self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
                self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
-               self.effects |= EF_ADDITIVE;
-               self.oldcolormap = self.colormap;
-               self.colormap = 0; // this originally was 512, but raises a warning in the engine, so get rid of it
+               self.effects |= CSQCMODEL_EF_RESPAWNGHOST;
                pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
                if(autocvar_g_respawn_ghosts_maxtime)
                        SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
        }
 
        CopyBody(1);
+
        self.effects |= EF_NODRAW; // prevent another CopyBody
-       if(self.oldcolormap)
-       {
-               self.colormap = self.oldcolormap;
-               self.oldcolormap = 0;
-       }
        PutClientInServer();
 }
 
@@ -2255,13 +2250,13 @@ void ShowRespawnCountdown()
                return;
        else
        {
-               number = ceil(self.death_time - time);
+               number = ceil(self.respawn_time - time);
                if(number <= 0)
                        return;
                if(number <= self.respawn_countdown)
                {
                        self.respawn_countdown = number - 1;
-                       if(ceil(self.death_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
+                       if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
                                AnnounceTo(self, strcat(ftos(number), ""));
                }
        }
@@ -2637,9 +2632,9 @@ void PlayerPreThink (void)
                        float button_pressed, force_respawn;
                        if(self.personal && g_race_qualifying)
                        {
-                               if(time > self.death_time)
+                               if(time > self.respawn_time)
                                {
-                                       self.death_time = time + 1; // only retry once a second
+                                       self.respawn_time = time + 1; // only retry once a second
                                        respawn();
                                        self.impulse = 141;
                                }
@@ -2669,9 +2664,9 @@ void PlayerPreThink (void)
                                }
                                else if (self.deadflag == DEAD_RESPAWNING)
                                {
-                                       if(time > self.death_time)
+                                       if(time > self.respawn_time)
                                        {
-                                               self.death_time = time + 1; // only retry once a second
+                                               self.respawn_time = time + 1; // only retry once a second
                                                respawn();
                                        }
                                }
index 1387f02dcd64b89dbd73fbb1ab56f4512d74e1dc..bdc30de4c5e14df5ff9ef4486e16e793b76c0c79 100644 (file)
@@ -166,6 +166,8 @@ void CopyBody(float keepvelocity)
        self.animstate_endtime = oldself.animstate_endtime;
        self.animstate_override = oldself.animstate_override;
        self.animstate_looping = oldself.animstate_looping;
+       self.dphitcontentsmask = oldself.dphitcontentsmask;
+       self.death_time = oldself.death_time;
        self.frame = oldself.frame;
        self.pain_finished = oldself.pain_finished;
        self.health = oldself.health;
@@ -758,13 +760,14 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                if(!waves)
                        waves = autocvar_g_respawn_waves;
                if(waves)
-                       self.death_time = ceil((time + sdelay) / waves) * waves;
+                       self.respawn_time = ceil((time + sdelay) / waves) * waves;
                else
-                       self.death_time = time + sdelay;
-               if((sdelay + waves >= 5.0) && (self.death_time - time > 1.75))
+                       self.respawn_time = time + sdelay;
+               if((sdelay + waves >= 5.0) && (self.respawn_time - time > 1.75))
                        self.respawn_countdown = 10; // first number to count down from is 10
                else
                        self.respawn_countdown = -1; // do not count down
+               self.death_time = time;
                if (random() < 0.5)
                        setanim(self, self.anim_die1, FALSE, TRUE, TRUE);
                else
@@ -976,8 +979,9 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
        if(!privatesay)
        if(source.classname != "player")
        {
-               if(teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !inWarmupStage))
-                       teamsay = -1; // spectators
+               if not(intermission_running)
+                       if(teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !inWarmupStage))
+                               teamsay = -1; // spectators
        }
 
        if(flood)
@@ -1009,22 +1013,23 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
 
        if(sourcemsgstr != "" && ret != 0)
        {
-               if(ret < 0) // fake
+               if(ret < 0) // faked message, because the player is muted
                {
                        sprint(source, sourcemsgstr);
                        if(sourcecmsgstr != "" && !privatesay)
                                centerprint(source, sourcecmsgstr);
                }
-               else if(privatesay)
+               else if(privatesay) // private message, between 2 people only, not sent to server console
                {
                        sprint(source, sourcemsgstr);
                        sprint(privatesay, msgstr);
                        if(cmsgstr != "")
                                centerprint(privatesay, cmsgstr);
                }
-               else if(teamsay > 0)
+               else if(teamsay > 0) // team message, only sent to team mates
                {
                        sprint(source, sourcemsgstr);
+                       //print(msgstr); // send to server console too
                        if(sourcecmsgstr != "")
                                centerprint(source, sourcecmsgstr);
                        FOR_EACH_REALPLAYER(head) if(head.team == source.team)
@@ -1035,22 +1040,24 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                                                centerprint(head, cmsgstr);
                                }
                }
-               else if(teamsay < 0)
+               else if(teamsay < 0) // spectator message, only sent to spectators
                {
                        sprint(source, sourcemsgstr);
+                       //print(msgstr); // send to server console too
                        FOR_EACH_REALCLIENT(head) if(head.classname != "player")
                                if(head != source)
                                        sprint(head, msgstr);
                }
-               else if(sourcemsgstr != msgstr)
+               else if(sourcemsgstr != msgstr) // trimmed/server fixed message, sent to all players
                {
                        sprint(source, sourcemsgstr);
+                       //print(msgstr); // send to server console too
                        FOR_EACH_REALCLIENT(head)
                                if(head != source)
                                        sprint(head, msgstr);
                }
                else
-                       bprint(msgstr);
+                       bprint(msgstr); // entirely normal message, sent to all players -- bprint sends to server console too.
        }
 
        return ret;
index 4a35f481b57c8a88abf53b714b0f6e2762571e6c..3b69e13eb0942f30b1e394a3a7b0813ae6e3cce7 100644 (file)
@@ -607,10 +607,6 @@ void CL_ExteriorWeaponentity_Think()
                }
                else
                        setattachment(self, self.owner, "bip01 r hand");
-
-               // if that didn't find a tag, hide the exterior weapon model
-               if (!self.tag_index)
-                       self.model = "";
        }
        self.effects = self.owner.effects;
        if(sv_pitch_min == sv_pitch_max)
index 2fbdd27a050ffbbb6eeec2287ae19cf11b89d3fe..ab58a4aee39dd12316f935087da74945e8886c6c 100644 (file)
@@ -160,9 +160,11 @@ void BanCommand_(float request)
 // ==================================
 
 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
+// but for 0.5 compat, we need "bans" here as it was replaced... REMOVE IT AFTER 0.6 RELEASE!!!!
 #define BAN_COMMANDS(request,arguments,command) \
        BAN_COMMAND("ban", BanCommand_ban(request, arguments, command), "Ban an IP address or a range of addresses (like 1.2.3)") \
        BAN_COMMAND("banlist", BanCommand_banlist(request), "List all existing bans") \
+       BAN_COMMAND("bans", BanCommand_banlist(request), "") \
        BAN_COMMAND("kickban", BanCommand_kickban(request, arguments, command), "Disconnect a client and ban it at the same time") \
        BAN_COMMAND("unban", BanCommand_unban(request, arguments), "Remove an existing ban") \
        /* nothing */
@@ -170,7 +172,7 @@ void BanCommand_(float request)
 void BanCommand_macro_help()
 {
        #define BAN_COMMAND(name,function,description) \
-               { print("  ^2", name, "^7: ", description, "\n"); }
+               { if(strtolower(description) != "") { print("  ^2", name, "^7: ", description, "\n"); } }
                
        BAN_COMMANDS(0, 0, "")
        #undef BAN_COMMAND
@@ -203,7 +205,7 @@ float BanCommand_macro_usage(float argc)
 void BanCommand_macro_write_aliases(float fh)
 {
        #define BAN_COMMAND(name,function,description) \
-               { CMD_Write_Alias("qc_cmd_sv", name, description); }
+               { if(strtolower(description) != "") { CMD_Write_Alias("qc_cmd_sv", name, description); } }
        
        BAN_COMMANDS(0, 0, "")
        #undef BAN_COMMAND
index 4f2a7456cc64f5034ecd9c4d44294f7e85f7d66a..8be0ad576bc81cff5a25302cf4820f085417dd5f 100644 (file)
@@ -510,7 +510,7 @@ void ClientCommand_tell(float request, float argc, string command)
                                        }
                                        else { print_to(self, "You can't ^2tell^7 a message to yourself."); return; }
                                }
-                               else if(strtolower(argv(1)) == "world") 
+                               else if(argv(1) == "#0") 
                                { 
                                        trigger_magicear_processmessage_forallears(self, -1, world, substring(command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token)));
                                        return;
index 7aa2fa1664d0ef60ddf4f9dc08afd11e9efafbcd..865d39b10eef9c3369ca63942b29fbd771b09f43 100644 (file)
@@ -104,6 +104,7 @@ float maxclients;
 //.float cnt2;
 
 .float play_time;
+.float respawn_time;
 .float death_time;
 .float fade_time;
 .float fade_rate;
index dde85328364070819a7b8ccdcf56398b7ac3fc81..bd4426c3aaa68e30ad4705208bf04fbcb2d81b42 100644 (file)
@@ -228,32 +228,34 @@ string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
        string handicap_output;
        string output;
 
-       // health/armor of attacker (person who killed you)
-       if(autocvar_sv_fraginfo_stats && (player.health >= 1))
-               if((autocvar_sv_fraginfo_stats == 2) || inWarmupStage)
+       if(autocvar_sv_fraginfo && ((autocvar_sv_fraginfo == 2) || inWarmupStage))
+       {
+               // health/armor of attacker (person who killed you)
+               if(autocvar_sv_fraginfo_stats && (player.health >= 1))
                        health_output = strcat("^7(Health ^1", ftos(rint(player.health)), "^7 / Armor ^2", ftos(rint(player.armorvalue)), "^7)");
-       
-       // ping display
-       if(autocvar_sv_fraginfo_ping)
-               ping_output = ((clienttype(player) == CLIENTTYPE_BOT) ? "^2Bot" : strcat("Ping ", ((player.ping >= 150) ? "^1" : "^2"), ftos(rint(player.ping)), "ms"));
                
-       // handicap display 
-       if(autocvar_sv_fraginfo_handicap) 
-       {
-               if(autocvar_sv_fraginfo_handicap == 2)  
-                       handicap_output = strcat(output, strcat("Handicap ^2", ((player.cvar_cl_handicap <= 1) ? "Off" : ftos(rint(player.cvar_cl_handicap)))));
-               else if(player.cvar_cl_handicap) // with _handicap 1, only show this if there actually is a handicap enabled.   
-                       handicap_output = strcat("Handicap ^2", ftos(rint(player.cvar_cl_handicap)));
+               // ping display
+               if(autocvar_sv_fraginfo_ping)
+                       ping_output = ((clienttype(player) == CLIENTTYPE_BOT) ? "^2Bot" : strcat("Ping ", ((player.ping >= 150) ? "^1" : "^2"), ftos(rint(player.ping)), "ms"));
+                       
+               // handicap display 
+               if(autocvar_sv_fraginfo_handicap) 
+               {
+                       if(autocvar_sv_fraginfo_handicap == 2)  
+                               handicap_output = strcat(output, strcat("Handicap ^2", ((player.cvar_cl_handicap <= 1) ? "Off" : ftos(rint(player.cvar_cl_handicap)))));
+                       else if(player.cvar_cl_handicap) // with _handicap 1, only show this if there actually is a handicap enabled.   
+                               handicap_output = strcat("Handicap ^2", ftos(rint(player.cvar_cl_handicap)));
+               }
+               
+               // format the string
+               output = strcat(health_output, (health_output ? ((ping_output || handicap_output) ? " ^7(" : "") : ((ping_output || handicap_output) ? "^7(" : "")), 
+                       ping_output, (handicap_output ? "^7 / " : ""), 
+                       handicap_output, ((ping_output || handicap_output) ? "^7)" : ""));
+               
+               // add new line to the beginning if there is a message
+               if(output) { output = strcat("\n", output); }
        }
        
-       // format the string
-       output = strcat(health_output, (health_output ? ((ping_output || handicap_output) ? " ^7(" : "") : ((ping_output || handicap_output) ? "^7(" : "")), 
-               ping_output, (handicap_output ? "^7 / " : ""), 
-               handicap_output, ((ping_output || handicap_output) ? "^7)" : ""));
-       
-       // add new line to the beginning if there is a message
-       if(output) { output = strcat("\n", output); }
-               
        return output;
 }
 
@@ -403,7 +405,7 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                                        PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
                                }
 
-                               if((autocvar_sv_fraginfo_typefrag) && (targ.BUTTON_CHAT)) {
+                               if(targ.BUTTON_CHAT) {
                                        Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL);
                                        Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL);
                                } else {
index 17b68d4f405960a0f1fd714a4e6b172fade71c24..93cea80ffd078aaac431bb5a5dbf4b4bcd699178 100644 (file)
@@ -308,6 +308,7 @@ void cvar_changes_init()
                BADCVAR("pausable");
                BADCVAR("sv_allow_fullbright");
                BADCVAR("sv_checkforpacketsduringsleep");
+               BADCVAR("sv_fraginfo");
                BADCVAR("sv_timeout");
                BADPREFIX("sv_timeout_");
                BADCVAR("welcome_message_time");
@@ -1301,12 +1302,15 @@ float mapvote_initialized;
 void IntermissionThink()
 {
        FixIntermissionClient(self);
-
-       if( (autocvar_sv_autoscreenshot || self.cvar_cl_autoscreenshot)
+       
+       float server_screenshot = (autocvar_sv_autoscreenshot && self.cvar_cl_autoscreenshot);
+       float client_screenshot = (self.cvar_cl_autoscreenshot == 2);
+       
+       if( (server_screenshot || client_screenshot)
                && ((self.autoscreenshot > 0) && (time > self.autoscreenshot)) )
        {
                self.autoscreenshot = -1;
-               if(clienttype(self) == CLIENTTYPE_REAL) { stuffcmd(self, sprintf("\nautoscreenshot \"%s\" \"%s\"\n", GetMapname(), strftime(FALSE, "%s"))); }
+               if(clienttype(self) == CLIENTTYPE_REAL) { stuffcmd(self, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"", GetMapname(), strftime(FALSE, "%s"))); }
                return;
        }
 
index 4babf32b22eb8c9e8cb8db51b5c7b066b488becf..236bea73a2ecda59e3553c7dc91243418b6b804a 100644 (file)
@@ -1606,7 +1606,7 @@ void precache()
 
 void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
 {
-       if (clienttype(e) == CLIENTTYPE_REAL)
+       if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
        {
                msg_entity = e;
                WRITESPECTATABLE_MSG_ONE({
index 79c39ae95d7998899e99529451df30ff22b05fed..46c7342f4ead3431f4a67995024da8339dab4740 100644 (file)
@@ -736,6 +736,11 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                        return;
                }
 
+               if(self.model != "")
+                       itemmodel = self.model;
+               if(self.item_pickupsound != "")
+                       pickupsound = self.item_pickupsound;
+
                self.reset = Item_Reset;
                // it's a level item
                if(self.spawnflags & 1)
index a556d6d0bb192dd72d9417d2535a7eafa3e82aac..087a048c30c84177de7cb17e97a74e32b3158ede 100644 (file)
@@ -57,7 +57,17 @@ void plat_spawn_inside_trigger()
                tmax_y = tmin_y + 1;
        }
 
-       setsize (trigger, tmin, tmax);
+       if(tmin_x > tmax_x)
+               if(tmin_y > tmax_y)
+                       if(tmin_z > tmax_z)
+                       {
+                               setsize (trigger, tmin, tmax);
+                               return;
+                       }
+
+       // otherwise, something is fishy...
+       remove(trigger);
+       objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn");
 }
 
 void plat_hit_top()
@@ -235,10 +245,10 @@ void spawnfunc_func_plat()
        self.pos2 = self.origin;
        self.pos2_z = self.origin_z - self.height;
 
-       plat_spawn_inside_trigger ();   // the "start moving" trigger
-
        self.reset = plat_reset;
        plat_reset();
+
+       plat_spawn_inside_trigger ();   // the "start moving" trigger
 }
 
 
index 3fb480df4c8c396351f2499694bfc07c8636597f..34c71cf50935508902626903d48a75cad3369c44 100644 (file)
@@ -3,6 +3,7 @@ REGISTER_WEAPON(MINSTANEX, w_minstanex, IT_CELLS, 7, WEP_FLAG_HIDDEN | WEP_FLAG_
 #else
 #ifdef SVQC
 .float minstanex_lasthit;
+.float jump_interval;
 
 void W_MinstaNex_Attack (void)
 {
@@ -207,8 +208,12 @@ float w_minstanex(float req)
                }
                else if (self.BUTTON_ATCK2)
                {
-                       if (weapon_prepareattack(1, autocvar_g_balance_minstanex_laser_refire))
+                       if (self.jump_interval <= time)
+                       if (weapon_prepareattack(1, -1))
                        {
+                               // handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib)
+                               self.jump_interval = time + autocvar_g_balance_minstanex_laser_refire * W_WeaponRateFactor();
+                               
                                // decrease ammo for the laser?
                                if(autocvar_g_balance_minstanex_laser_ammo)
                                        W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_laser_ammo, autocvar_g_balance_minstanex_reload_ammo);