#include <lib/warpzone/anglestransform.qh>
#include <lib/warpzone/common.qh>
#include <lib/warpzone/util_server.qh>
+#include <server/client.qh>
#include <server/clientkill.qh>
#include <server/damage.qh>
#include <server/main.qh>
}
if(this.target != "")
InitializeEntity(this, info_autoscreenshot_findtarget, INITPRIO_FINDTARGET);
+
+ tracebox(this.origin, PL_CROUCH_MIN_CONST, PL_CROUCH_MAX_CONST, this.origin, MOVE_WORLDONLY, this);
+ if(!trace_startsolid)
+ IL_PUSH(g_observepoints, this);
}
float CheatImpulse(entity this, int imp)
UpdatePlayerSounds(e);
}
+entity SelectObservePoint(entity this)
+{
+ RandomSelection_Init();
+ IL_EACH(g_observepoints, true,
+ {
+ RandomSelection_AddEnt(it, 1, 1);
+ });
+ return RandomSelection_chosen_ent;
+}
+
/** putting a client as observer in the server */
void PutObserverInServer(entity this, bool is_forced, bool use_spawnpoint)
{
if (use_spawnpoint)
{
- entity spot = SelectSpawnPoint(this, true);
+ // first try to find a random "nice" location to view from
+ entity spot = SelectObservePoint(this);
+ bool is_observepoint = (spot != NULL);
+ if(!spot) // otherwise just use the player spawn points
+ spot = SelectSpawnPoint(this, true);
if (!spot) LOG_FATAL("No spawnpoints for observers?!?");
+
this.angles = vec2(spot.angles);
// offset it so that the spectator spawns higher off the ground, looks better this way
- setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this));
+ setorigin(this, spot.origin + (is_observepoint ? '0 0 0' : autocvar_sv_player_viewoffset));
}
else // change origin to restore previous view origin
setorigin(this, this.origin + STAT(PL_VIEW_OFS, this) - STAT(PL_CROUCH_VIEW_OFS, this));
.void(entity this, entity player) init_for_player;
IntrusiveList g_initforplayer;
-STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
+IntrusiveList g_observepoints;
+STATIC_INIT(client_lists)
+{
+ g_initforplayer = IL_NEW();
+ g_observepoints = IL_NEW();
+}
void play_countdown(entity this, float finished, Sound samp);
void player_powerups_remove_all(entity this);