diff --git a/src/client/tfc/init.c b/src/client/tfc/init.c index 7ad1959d..dff1cd4e 100644 --- a/src/client/tfc/init.c +++ b/src/client/tfc/init.c @@ -51,6 +51,7 @@ void Client_Init(float apilevel, string enginename, float engineversion) void Client_InitDone(void) { + VGUI_ChooseTeam(); } void Game_RendererRestarted(string rstr) diff --git a/src/client/tfc/progs.src b/src/client/tfc/progs.src index c7cabe02..ea3d8cf2 100755 --- a/src/client/tfc/progs.src +++ b/src/client/tfc/progs.src @@ -16,6 +16,8 @@ ../defs.h ../../vgui/include.src +../vgui.cpp +vgui_chooseteam.cpp ../util.c init.c @@ -75,7 +77,6 @@ entities.c ../damage.c ../obituary.c ../chat.c -../vgui.cpp ../valve/hud.c ../valve/hud_weaponselect.c diff --git a/src/client/tfc/vgui_chooseteam.cpp b/src/client/tfc/vgui_chooseteam.cpp new file mode 100644 index 00000000..af6a10fe --- /dev/null +++ b/src/client/tfc/vgui_chooseteam.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static CUIWindow winChooseTeam; +static CUIWindow winCTTeam; +static CUIWindow winTTeam; + +typedef struct { + string str; + void() ptr; +} btnarr_t; + +void VGUI_TeamJoin(float i) +{ + sendevent("TeamJoin", "f", i); +} + +void VGUI_TeamBack(void) +{ + +} + +void VGUI_JoinScout_B (void) { VGUI_TeamJoin(1); } +void VGUI_JoinSniper_B (void) { VGUI_TeamJoin(2); } +void VGUI_JoinSoldier_B (void) { VGUI_TeamJoin(3); } +void VGUI_JoinDemoman_B (void) { VGUI_TeamJoin(4); } +void VGUI_JoinMedic_B (void) { VGUI_TeamJoin(5); } +void VGUI_JoinHwguy_B (void) { VGUI_TeamJoin(6); } +void VGUI_JoinPyro_B (void) { VGUI_TeamJoin(7); } +void VGUI_JoinSpy_B (void) { VGUI_TeamJoin(8); } +void VGUI_JoinEngineer_B (void) { VGUI_TeamJoin(9); } + +void VGUI_JoinScout_R (void) { VGUI_TeamJoin(11); } +void VGUI_JoinSniper_R (void) { VGUI_TeamJoin(12); } +void VGUI_JoinSoldier_R (void) { VGUI_TeamJoin(13); } +void VGUI_JoinDemoman_R (void) { VGUI_TeamJoin(14); } +void VGUI_JoinMedic_R (void) { VGUI_TeamJoin(15); } +void VGUI_JoinHwguy_R (void) { VGUI_TeamJoin(16); } +void VGUI_JoinPyro_R (void) { VGUI_TeamJoin(17); } +void VGUI_JoinSpy_R (void) { VGUI_TeamJoin(18); } +void VGUI_JoinEngineer_R (void) { VGUI_TeamJoin(19); } + +void VGUI_JoinScout_Y (void) { VGUI_TeamJoin(21); } +void VGUI_JoinSniper_Y (void) { VGUI_TeamJoin(22); } +void VGUI_JoinSoldier_Y (void) { VGUI_TeamJoin(23); } +void VGUI_JoinDemoman_Y (void) { VGUI_TeamJoin(24); } +void VGUI_JoinMedic_Y (void) { VGUI_TeamJoin(25); } +void VGUI_JoinHwguy_Y (void) { VGUI_TeamJoin(26); } +void VGUI_JoinPyro_Y (void) { VGUI_TeamJoin(27); } +void VGUI_JoinSpy_Y (void) { VGUI_TeamJoin(28); } +void VGUI_JoinEngineer_Y (void) { VGUI_TeamJoin(29); } + +void VGUI_JoinScout_G (void) { VGUI_TeamJoin(31); } +void VGUI_JoinSniper_G (void) { VGUI_TeamJoin(32); } +void VGUI_JoinSoldier_G (void) { VGUI_TeamJoin(33); } +void VGUI_JoinDemoman_G (void) { VGUI_TeamJoin(34); } +void VGUI_JoinMedic_G (void) { VGUI_TeamJoin(35); } +void VGUI_JoinHwguy_G (void) { VGUI_TeamJoin(36); } +void VGUI_JoinPyro_G (void) { VGUI_TeamJoin(37); } +void VGUI_JoinSpy_G (void) { VGUI_TeamJoin(38); } +void VGUI_JoinEngineer_G (void) { VGUI_TeamJoin(39); } + +btnarr_t red_team[] = { + {"SCOUT", VGUI_JoinScout_R }, + {"SNIPER", VGUI_JoinSniper_R }, + {"SOLDIER", VGUI_JoinSoldier_R }, + {"DEMOMAN", VGUI_JoinDemoman_R }, + {"MEDIC", VGUI_JoinMedic_R }, + {"HWGUY", VGUI_JoinHwguy_R }, + {"PYRO", VGUI_JoinPyro_R }, + {"SPY", VGUI_JoinSpy_R }, + {"ENGINEER", VGUI_JoinEngineer_R }, + {__NULL__, __NULL__ }, + {"< Back", VGUI_TeamBack } +}; + +btnarr_t blue_team[] = { + {"SCOUT", VGUI_JoinScout_B }, + {"SNIPER", VGUI_JoinSniper_B }, + {"SOLDIER", VGUI_JoinSoldier_B }, + {"DEMOMAN", VGUI_JoinDemoman_B }, + {"MEDIC", VGUI_JoinMedic_B }, + {"HWGUY", VGUI_JoinHwguy_B }, + {"PYRO", VGUI_JoinPyro_B }, + {"SPY", VGUI_JoinSpy_B }, + {"ENGINEER", VGUI_JoinEngineer_B }, + {__NULL__, __NULL__ }, + {"< Back", VGUI_TeamBack } +}; + +void +VGUI_GoSpectator(void) +{ + VGUI_TeamJoin(0); + winChooseTeam.Hide(); +} + +void VGUI_ChooseTeam_Red(void) +{ + static int initialized; + static CUIButton *btns; + + if ( !initialized ) { + vector btnpos = [16,0]; + initialized = TRUE; + winCTTeam = spawn( CUIWindow ); + winCTTeam.SetTitle( "Choose Skin" ); + winCTTeam.SetSize( [420,320] ); + g_uiDesktop.Add( winCTTeam ); + + btns = memalloc(sizeof(btnarr_t) * red_team.length); + for (int i = 0; i < red_team.length; i++) { + btnpos[1] += 30; + if ( red_team[i].ptr == __NULL__ ) { + continue; + } + btns[i] = spawn( CUIButton ); + btns[i].SetTitle( red_team[i].str ); + btns[i].SetPos( btnpos ); + btns[i].SetFunc( red_team[i].ptr ); + winCTTeam.Add( btns[i] ); + } + } + + winChooseTeam.Hide(); + winCTTeam.Show(); + winCTTeam.SetPos( ( video_res / 2 ) - ( winCTTeam.GetSize() / 2 ) ); +} + +void VGUI_ChooseTeam_Blue(void) +{ + static int initialized; + static CUIButton *btns; + + if ( !initialized ) { + vector btnpos = [16,0]; + initialized = TRUE; + winTTeam = spawn( CUIWindow ); + winTTeam.SetTitle( "Choose Skin" ); + winTTeam.SetSize( [420,320] ); + g_uiDesktop.Add( winTTeam ); + + btns = memalloc(sizeof(btnarr_t) * blue_team.length); + for (int i = 0; i < blue_team.length; i++) { + btnpos[1] += 30; + if ( blue_team[i].ptr == __NULL__ ) { + continue; + } + btns[i] = spawn( CUIButton ); + btns[i].SetTitle( blue_team[i].str ); + btns[i].SetPos( btnpos ); + btns[i].SetFunc( blue_team[i].ptr ); + winTTeam.Add( btns[i] ); + } + } + + winChooseTeam.Hide(); + winTTeam.Show(); + winTTeam.SetPos( ( video_res / 2 ) - ( winTTeam.GetSize() / 2 ) ); +} + +void VGUI_ChooseTeam(void) +{ + static int initialized; + static CUIButton btnGoRed; + static CUIButton btnGoBlue; + static CUIButton btnGoSpectator; + + if ( !initialized ) { + initialized = TRUE; + winChooseTeam = spawn( CUIWindow ); + winChooseTeam.SetTitle( "Choose Team" ); + winChooseTeam.SetSize( '420 320' ); + + btnGoRed = spawn( CUIButton ); + btnGoRed.SetTitle( "Red Team" ); + btnGoRed.SetPos( '8 132' ); + btnGoRed.SetFunc( VGUI_ChooseTeam_Red ); + + btnGoBlue = spawn( CUIButton ); + btnGoBlue.SetTitle( "Blue Team" ); + btnGoBlue.SetPos( '8 162' ); + btnGoBlue.SetFunc( VGUI_ChooseTeam_Blue ); + + btnGoSpectator = spawn( CUIButton ); + btnGoSpectator.SetTitle( "Spectator" ); + btnGoSpectator.SetPos( '8 192' ); + btnGoSpectator.SetFunc( VGUI_GoSpectator ); + + g_uiDesktop.Add( winChooseTeam ); + winChooseTeam.Add( btnGoRed ); + winChooseTeam.Add( btnGoBlue ); + winChooseTeam.Add( btnGoSpectator ); + } + + winChooseTeam.Show(); + winChooseTeam.SetPos( ( video_res / 2 ) - ( winChooseTeam.GetSize() / 2 ) ); +} diff --git a/src/server/cstrike/progs.src b/src/server/cstrike/progs.src index 82f883a3..c1c59476 100755 --- a/src/server/cstrike/progs.src +++ b/src/server/cstrike/progs.src @@ -80,6 +80,7 @@ func_buyzone.cpp func_escapezone.cpp main.c player.c +../spawn.c spawn.c ../footsteps.c ../flashlight.c diff --git a/src/server/cstrike/spawn.c b/src/server/cstrike/spawn.c index 6d76358b..267909ed 100644 --- a/src/server/cstrike/spawn.c +++ b/src/server/cstrike/spawn.c @@ -69,50 +69,6 @@ entity Spawn_FindSpawnPoint(float fTeam) return eSpot; } -/* -================= -Spawn_ObserverCam - -Look for the next spawnpoint -================= -*/ -void Spawn_ObserverCam(void) -{ - entity eTarget; - - // Go find a camera if we aren't dead - entity eCamera = find (world, classname, "trigger_camera"); - - if (eCamera) { - self.origin = eCamera.origin; - - if (eCamera.target) { - eTarget = find(world, targetname, eCamera.target); - if (eTarget) { - self.angles = vectoangles(eTarget.origin - eCamera.origin); - self.angles[0] *= -1; - } - } - } else { - // Can't find a camera? Just do this lazy thing, CS seems to do the same - eCamera = find (world, classname, "info_player_start"); - - if (eCamera) { - self.origin = eCamera.origin; - - if (eCamera.target) { - eTarget = find(world, targetname, eCamera.target); - if (eTarget) { - self.angles = vectoangles(eTarget.origin - eCamera.origin); - self.angles[0] *= -1; - } - } - } - } - - self.fixangle = TRUE; -} - /* ================= Spawn_RespawnClient diff --git a/src/server/spawn.c b/src/server/spawn.c index a1c578c8..3d84204d 100644 --- a/src/server/spawn.c +++ b/src/server/spawn.c @@ -14,6 +14,44 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +void +Spawn_ObserverCam(void) +{ + entity eTarget; + + // Go find a camera if we aren't dead + entity eCamera = find (world, classname, "trigger_camera"); + + if (eCamera) { + self.origin = eCamera.origin; + + if (eCamera.target) { + eTarget = find(world, targetname, eCamera.target); + if (eTarget) { + self.angles = vectoangles(eTarget.origin - eCamera.origin); + self.angles[0] *= -1; + } + } + } else { + // Can't find a camera? Just do this lazy thing, CS seems to do the same + eCamera = find (world, classname, "info_player_start"); + + if (eCamera) { + self.origin = eCamera.origin; + + if (eCamera.target) { + eTarget = find(world, targetname, eCamera.target); + if (eTarget) { + self.angles = vectoangles(eTarget.origin - eCamera.origin); + self.angles[0] *= -1; + } + } + } + } + + self.fixangle = TRUE; +} + float Spawn_PlayerRange(entity spot) { entity pl; float bestdist; diff --git a/src/server/tfc/client.c b/src/server/tfc/client.c index b4f861c4..74b4d5b6 100644 --- a/src/server/tfc/client.c +++ b/src/server/tfc/client.c @@ -198,68 +198,23 @@ Game_SetChangeParms(void) void Game_PutClientInServer(void) { - if (self.classname != "player") { - spawnfunc_player(); - } player pl = (player)self; - entity spot; - pl.classname = "player"; - pl.health = self.max_health = 100; - - pl.takedamage = DAMAGE_YES; - pl.solid = SOLID_SLIDEBOX; - pl.movetype = MOVETYPE_WALK; - pl.flags = FL_CLIENT; - pl.viewzoom = 1.0; - pl.model = "models/player.mdl"; - - string mymodel = infokey(pl, "model"); - - if (mymodel) { - mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel); - if (whichpack(mymodel)) { - pl.model = mymodel; - } - } - setmodel(pl, pl.model); - - setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); - pl.view_ofs = VEC_PLAYER_VIEWPOS; - pl.velocity = [0,0,0]; - pl.gravity = __NULL__; - pl.frame = 1; + pl.classname = "spectator"; + pl.health = 0; + pl.armor = 0; + pl.takedamage = DAMAGE_NO; + pl.solid = SOLID_NOT; + pl.movetype = MOVETYPE_NOCLIP; pl.SendEntity = Player_SendEntity; - pl.SendFlags = UPDATE_ALL; - - pl.customphysics = Empty; - pl.vPain = Player_Pain; - pl.vDeath = Player_Death; - pl.iBleeds = TRUE; - forceinfokey(pl, "*spec", "0"); - forceinfokey(self, "*deaths", ftos(self.deaths)); - - if (cvar("sv_playerslots") == 1) { - Game_DecodeChangeParms(); - - if (startspot != "") { - setorigin(pl, Landmark_GetSpot()); - } else { - spot = find(world, classname, "info_player_start"); - setorigin(pl, spot.origin); - pl.angles = spot.angles; - pl.fixangle = TRUE; - } - } else { - spot = Spawn_SelectRandom("info_player_deathmatch"); - setorigin(pl, spot.origin); - pl.angles = spot.angles; - pl.fixangle = TRUE; - - pl.ammo_9mm = 68; - Weapons_AddItem(pl, WEAPON_CROWBAR); - pl.g_items |= ITEM_SUIT; - } + pl.flags = FL_CLIENT; + pl.weapon = 0; + pl.viewzoom = 1.0f; + pl.model = 0; + setsize (pl, '-16 -16 -16', '16 16 16'); + pl.view_ofs = pl.velocity = '0 0 0'; + forceinfokey(pl, "*spec", "2"); + Spawn_ObserverCam(); } void diff --git a/src/server/tfc/info_player_teamspawn.cpp b/src/server/tfc/info_player_teamspawn.cpp new file mode 100644 index 00000000..467e8b47 --- /dev/null +++ b/src/server/tfc/info_player_teamspawn.cpp @@ -0,0 +1,36 @@ +class info_player_teamspawn:CBaseTrigger +{ + int m_iTeam; + + void() info_player_teamspawn; +}; + +void info_player_teamspawn::info_player_teamspawn(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "team_no": + m_iTeam = stoi(argv(i+1)); + break; + default: + break; + } + } + + switch (m_iTeam) { + case 1: + classname = "info_teamspawn_blue"; + break; + case 2: + classname = "info_teamspawn_red"; + break; + case 3: + classname = "info_teamspawn_yellow"; + break; + case 4: + classname = "info_teamspawn_green"; + break; + } +} + + diff --git a/src/server/tfc/info_tfgoal.cpp b/src/server/tfc/info_tfgoal.cpp new file mode 100644 index 00000000..da4c2f9b --- /dev/null +++ b/src/server/tfc/info_tfgoal.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +class info_tfgoal:CBaseTrigger +{ + string m_strName; + string m_strSound; + + void() info_tfgoal; + virtual void() touch; + virtual void() Respawn; +}; + +void +info_tfgoal::touch(void) +{ + if (other.classname != "player") { + return; + } + + sound(this, CHAN_ITEM, m_strSound, 1.0f, ATTN_NORM); + Logging_Pickup(other, this, m_strName); + + if (cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 30.0f; + } +} + +void +info_tfgoal::Respawn(void) +{ + solid = SOLID_TRIGGER; + movetype = MOVETYPE_NONE; + setmodel(this, m_oldModel); + setsize(this, VEC_HULL_MIN, VEC_HULL_MAX); + setorigin(this, m_oldOrigin); +} + +void +info_tfgoal::info_tfgoal(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "netname": + m_strSound = argv(i+1); + netname = __NULL__; + break; + case "noise": + m_strSound = argv(i+1); + break; + case "mdl": + model = argv(i+1); + break; + default: + break; + } + } + precache_sound(m_strSound); + + CBaseEntity::CBaseEntity(); + info_tfgoal::Respawn(); +} diff --git a/src/server/tfc/input.c b/src/server/tfc/input.c index 7191d595..927729f7 100644 --- a/src/server/tfc/input.c +++ b/src/server/tfc/input.c @@ -78,6 +78,6 @@ void Game_Input(void) bprint(PRINT_HIGH, "Respawning all map entities...\n"); } } - + self.impulse = 0; } diff --git a/src/server/tfc/item_tfgoal.cpp b/src/server/tfc/item_tfgoal.cpp new file mode 100644 index 00000000..31105992 --- /dev/null +++ b/src/server/tfc/item_tfgoal.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +class item_tfgoal:CBaseTrigger +{ + string m_strSound; + + void() item_tfgoal; + virtual void() touch; + virtual void() Respawn; +}; + +void +item_tfgoal::touch(void) +{ + if (other.classname != "player") { + return; + } + + if (cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 20.0f; + } +} + +void +item_tfgoal::Respawn(void) +{ + solid = SOLID_TRIGGER; + movetype = MOVETYPE_NONE; + setmodel(this, m_oldModel); +} + +void +item_tfgoal::item_tfgoal(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "noise": + m_strSound = argv(i+1); + break; + case "mdl": + model = argv(i+1); + break; + default: + break; + } + } + precache_sound(m_strSound); + + CBaseEntity::CBaseEntity(); + item_tfgoal::Respawn(); +} + diff --git a/src/server/tfc/progs.src b/src/server/tfc/progs.src index c5cf1f29..417956d0 100755 --- a/src/server/tfc/progs.src +++ b/src/server/tfc/progs.src @@ -15,6 +15,7 @@ ../../shared/valve/animations.h ../defs.h ../plugins.c +../logging.c ../../gs-entbase/server.src ../../shared/decals.c ../../shared/effects.c @@ -49,10 +50,14 @@ ../../shared/tfc/w_wrench.c ../valve/items.cpp ../valve/item_weaponbox.cpp +info_tfgoal.cpp +item_tfgoal.cpp +info_player_teamspawn.cpp ../../shared/tfc/weapons.c ../../shared/valve/weapon_common.c ../spawn.c +spawn.c ../vox.c ../../shared/valve/animations.c client.c diff --git a/src/server/tfc/spawn.c b/src/server/tfc/spawn.c new file mode 100644 index 00000000..6497aa40 --- /dev/null +++ b/src/server/tfc/spawn.c @@ -0,0 +1,152 @@ + +enum { + CLASS_SCOUT = 1, + CLASS_SNIPER, + CLASS_SOLDIER, + CLASS_DEMO, + CLASS_MEDIC, + CLASS_HVYWEAPON, + CLASS_PYRO, + CLASS_SPY, + CLASS_ENGINEER +}; + +string g_teammodels[] = { + "", + "models/player/scout/scout2.mdl", + "models/player/sniper/sniper2.mdl", + "models/player/soldier/soldier2.mdl", + "models/player/demo/demo.mdl", + "models/player/medic/medic2.mdl", + "models/player/hvyweapon/hvyweapon2.mdl", + "models/player/pyro/pyro2.mdl", + "models/player/spy/spy2.mdl", + "models/player/engineer/engineer2.mdl" +}; + +void +CSEv_TeamJoin_f(float f) +{ + if (self.classname != "player") { + spawnfunc_player(); + } + player pl = (player)self; + + entity spot; + pl.classname = "player"; + pl.health = self.max_health = 100; + + pl.takedamage = DAMAGE_YES; + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_WALK; + pl.flags = FL_CLIENT; + pl.viewzoom = 1.0; + + /* mess, do it better */ + if (f < 10) { + pl.team = 1; /* Blue */ + } else if (f < 20) { + pl.team = 2; /* Red */ + f -= 10; + } else if (f < 30) { + pl.team = 3; /* Yellow */ + f -= 20; + } else if (f < 40) { + pl.team = 4; /* Green */ + f -= 30; + } + + pl.model = g_teammodels[f]; + setmodel(pl, pl.model); + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + pl.view_ofs = VEC_PLAYER_VIEWPOS; + pl.velocity = [0,0,0]; + pl.gravity = __NULL__; + pl.frame = 1; + pl.SendEntity = Player_SendEntity; + pl.SendFlags = UPDATE_ALL; + pl.armor = pl.activeweapon = pl.g_items = 0; + + pl.customphysics = Empty; + pl.vPain = Player_Pain; + pl.vDeath = Player_Death; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(self, "*deaths", ftos(self.deaths)); + + switch (pl.team) { + case 1: + spot = Spawn_SelectRandom("info_teamspawn_blue"); + break; + case 2: + spot = Spawn_SelectRandom("info_teamspawn_red"); + break; + case 3: + spot = Spawn_SelectRandom("info_teamspawn_yellow"); + break; + case 4: + spot = Spawn_SelectRandom("info_teamspawn_green"); + break; + } + + setorigin(pl, spot.origin); + pl.angles = spot.angles; + pl.fixangle = TRUE; + + switch (f) { + case CLASS_SCOUT: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_NAILGUN); + break; + case CLASS_SNIPER: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SNIPER); + Weapons_AddItem(pl, WEAPON_AUTORIFLE); + Weapons_AddItem(pl, WEAPON_NAILGUN); + break; + case CLASS_SOLDIER: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_DBS); + Weapons_AddItem(pl, WEAPON_RPG); + break; + case CLASS_DEMO: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_GLAUNCHER); + Weapons_AddItem(pl, WEAPON_PIPEBOMB); + break; + case CLASS_MEDIC: + Weapons_AddItem(pl, WEAPON_MEDKIT); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_DBS); + Weapons_AddItem(pl, WEAPON_SUPERNAIL); + break; + case CLASS_HVYWEAPON: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_DBS); + Weapons_AddItem(pl, WEAPON_ASSCAN); + break; + case CLASS_PYRO: + Weapons_AddItem(pl, WEAPON_CROWBAR); + Weapons_AddItem(pl, WEAPON_SBS); + Weapons_AddItem(pl, WEAPON_FLAMER); + Weapons_AddItem(pl, WEAPON_INCENDIARY); + break; + case CLASS_SPY: + Weapons_AddItem(pl, WEAPON_KNIFE); + Weapons_AddItem(pl, WEAPON_TRANQUIL); + Weapons_AddItem(pl, WEAPON_DBS); + Weapons_AddItem(pl, WEAPON_NAILGUN); + break; + case CLASS_ENGINEER: + Weapons_AddItem(pl, WEAPON_WRENCH); + Weapons_AddItem(pl, WEAPON_RAILGUN); + Weapons_AddItem(pl, WEAPON_DBS); + break; + } + + pl.g_items |= ITEM_SUIT; +}