Example #1
0
//
//	[Toke - CTF] SV_CTFEvent
//	Sends CTF events to player
//
void SV_CTFEvent (flag_t f, flag_score_t event, player_t &who)
{
	if(event == SCORE_NONE)
		return;

	if(validplayer(who))
		who.points += ctf_points[event];

	for (size_t i = 0; i < players.size(); ++i)
	{
		if (!players[i].ingame())
			continue;

		client_t *cl = &players[i].client;

		MSG_WriteMarker (&cl->reliablebuf, svc_ctfevent);
		MSG_WriteByte (&cl->reliablebuf, event);
		MSG_WriteByte (&cl->reliablebuf, f);

		if(validplayer(who))
		{
			MSG_WriteByte (&cl->reliablebuf, who.id);
			MSG_WriteLong (&cl->reliablebuf, who.points);
		}
		else
		{
			MSG_WriteByte (&cl->reliablebuf, 0);
			MSG_WriteLong (&cl->reliablebuf, 0);
		}

		for(size_t j = 0; j < NUMFLAGS; j++)
			MSG_WriteLong (&cl->reliablebuf, TEAMpoints[j]);
	}
}
Example #2
0
//
//	[Toke - CTF] CL_CTFEvent
//	Deals with CTF specific network data
//
void CL_CTFEvent (void)
{
	flag_score_t event = (flag_score_t)MSG_ReadByte();

	if(event == SCORE_NONE) // CTF state refresh
	{
		CTF_Connect();
		return;
	}

	flag_t flag = (flag_t)MSG_ReadByte();
	player_t &player = idplayer(MSG_ReadByte());
	int points = MSG_ReadLong();

	if(validplayer(player))
		player.points = points;

	for(size_t i = 0; i < NUMFLAGS; i++)
		TEAMpoints[i] = MSG_ReadLong ();

	switch(event)
	{
		default:
		case SCORE_NONE:
		case SCORE_REFRESH:
		case SCORE_KILL:
		case SCORE_BETRAYAL:
		case SCORE_CARRIERKILL:
			break;

		case SCORE_GRAB:
		case SCORE_FIRSTGRAB:
		case SCORE_MANUALRETURN:
			if(validplayer(player))
				CTF_CarryFlag(player, flag);
			break;

		case SCORE_RETURN:
		case SCORE_CAPTURE:
			if(validplayer(player))
				CTF_CheckFlags(player);
			else
				CTFdata[flag].flagger = 0;
			CTFdata[flag].state = flag_home;
			if(CTFdata[flag].actor)
				CTFdata[flag].actor->Destroy();
			break;

		case SCORE_DROP:
			if(validplayer(player))
				CTF_CheckFlags(player);
			else
				CTFdata[flag].flagger = 0;
			CTFdata[flag].state = flag_dropped;
			if(CTFdata[flag].actor)
				CTFdata[flag].actor->Destroy();
			break;
	}
}
Example #3
0
//
//	[Toke - CTF] CTF_MoveFlag
//	Moves the flag that is linked to a player
//
void CTF_MoveFlags ()
{
	// denis - flag is now a boolean
	for(size_t i = 0; i < NUMFLAGS; i++)
	{
		if(CTFdata[i].flagger && CTFdata[i].actor)
		{
			player_t &player = idplayer(CTFdata[i].flagger);
			AActor *flag = CTFdata[i].actor;

			if (!validplayer(player) || !player.mo)
			{
				// [SL] 2012-12-13 - Remove a flag if it's being carried but
				// there's not a valid player carrying it (should not happen)
				CTFdata[i].flagger = 0;
				CTFdata[i].state = flag_home;
				if(CTFdata[i].actor)
					CTFdata[i].actor->Destroy();
				continue;
			}

			unsigned an = player.mo->angle >> ANGLETOFINESHIFT;
			fixed_t x = (player.mo->x + FixedMul (-2*FRACUNIT, finecosine[an]));
			fixed_t y = (player.mo->y + FixedMul (-2*FRACUNIT, finesine[an]));

			CL_MoveThing(flag, x, y, player.mo->z);
		}
	}
Example #4
0
//
// P_PreservePlayer
//
void P_PreservePlayer(player_t &player)
{
	if (!serverside || sv_gametype != GM_COOP || !validplayer(player) || !player.ingame())
		return;

	if(!unnatural_level_progression)
		player.playerstate = PST_LIVE; // denis - carry weapons and keys over to next level

	G_DoReborn(player);

	// inform client
	{
		size_t i;
		client_t *cl = &player.client;

		MSG_WriteMarker (&cl->reliablebuf, svc_playerinfo);

		for(i = 0; i < NUMWEAPONS; i++)
			MSG_WriteByte (&cl->reliablebuf, player.weaponowned[i]);

		for(i = 0; i < NUMAMMO; i++)
		{
			MSG_WriteShort (&cl->reliablebuf, player.maxammo[i]);
			MSG_WriteShort (&cl->reliablebuf, player.ammo[i]);
		}

		MSG_WriteByte (&cl->reliablebuf, player.health);
		MSG_WriteByte (&cl->reliablebuf, player.armorpoints);
		MSG_WriteByte (&cl->reliablebuf, player.armortype);
		MSG_WriteByte (&cl->reliablebuf, player.readyweapon);
		MSG_WriteByte (&cl->reliablebuf, player.backpack);
	}
}
Example #5
0
//
//	[Toke - CTF] CTF_CarryFlag
//	Spawns a flag on a players location and links the flag to the player
//
void CTF_CarryFlag (player_t &player, flag_t flag)
{
	if (!validplayer(player))
		return;

	player.flags[flag] = true;
	CTFdata[flag].flagger = player.id;
	CTFdata[flag].state = flag_carried;

	AActor *actor = new AActor(0, 0, 0, flag_table[flag][flag_carried]);
	CTFdata[flag].actor = actor->ptr();

	CTF_MoveFlags();
}
Example #6
0
//
//	[Toke - CTF] CTF_CarryFlag
//	Spawns a flag on a players location and links the flag to the player
//
void CTF_CarryFlag (player_t &player, flag_t flag)
{
	if (!validplayer(player))
		return;

	player.flags[flag] = true;
	CTFdata[flag].flagger = player.id;
	CTFdata[flag].state = flag_carried;

	// spawn visible flags on other players
	if(&player != &consoleplayer())
	{
		AActor *actor = new AActor(0, 0, 0, flag_table[flag][flag_carried]);
		CTFdata[flag].actor = actor->ptr();

		CTF_MoveFlags();
	}
}
Example #7
0
	bool tic()
	{
		if (!validplayer(idplayer(this->id)))
		{
			std::ostringstream buffer;
			buffer << this->netname << " left the server.";
			this->error = buffer.str();
			return false;
		}
		if (idplayer(this->id).spectator)
		{
			std::ostringstream buffer;
			buffer << this->netname << " became a spectator on his own.";
			this->error = buffer.str();
			return false;
		}
		return true;
	}
Example #8
0
//
// CTF_Connect
// Receive states of all flags
//
void CTF_Connect()
{
	size_t i;

	// clear player flags client may have imagined
	for(i = 0; i < players.size(); i++)
		for(size_t j = 0; j < NUMFLAGS; j++)
			players[i].flags[j] = false;

	for(i = 0; i < NUMFLAGS; i++)
	{
		CTFdata[i].state = (flag_state_t)MSG_ReadByte();
		byte flagger = MSG_ReadByte();

		if(CTFdata[i].state == flag_carried)
		{
			player_t &player = idplayer(flagger);

			if(validplayer(player))
				CTF_CarryFlag(player, (flag_t)i);
		}
	}
}
Example #9
0
//
//	[Toke - CTF] CL_CTFEvent
//	Deals with CTF specific network data
//
void CL_CTFEvent (void)
{
	flag_score_t event = (flag_score_t)MSG_ReadByte();

	if(event == SCORE_NONE) // CTF state refresh
	{
		CTF_Connect();
		return;
	}

	flag_t flag = (flag_t)MSG_ReadByte();
	player_t &player = idplayer(MSG_ReadByte());
	int points = MSG_ReadLong();

	if(validplayer(player))
		player.points = points;

	for(size_t i = 0; i < NUMFLAGS; i++)
		TEAMpoints[i] = MSG_ReadLong ();

	switch(event)
	{
		default:
		case SCORE_NONE:
		case SCORE_REFRESH:
		case SCORE_KILL:
		case SCORE_BETRAYAL:
		case SCORE_CARRIERKILL:
			break;

		case SCORE_GRAB:
		case SCORE_FIRSTGRAB:
		case SCORE_MANUALRETURN:
			if(validplayer(player))
			{
				CTF_CarryFlag(player, flag);
				if (player.id == displayplayer().id)
					player.bonuscount = BONUSADD;
			}
			break;

		case SCORE_CAPTURE:
			if (validplayer(player))
			{
				player.flags[flag] = 0;
			}

			CTFdata[flag].flagger = 0;
			CTFdata[flag].state = flag_home;
			if(CTFdata[flag].actor)
				CTFdata[flag].actor->Destroy();
			break;

		case SCORE_RETURN:
			if (validplayer(player))
			{
				player.flags[flag] = 0;
			}

			CTFdata[flag].flagger = 0;
			CTFdata[flag].state = flag_home;
			if(CTFdata[flag].actor)
				CTFdata[flag].actor->Destroy();
			break;

		case SCORE_DROP:
			if (validplayer(player))
			{
				player.flags[flag] = 0;
			}

			CTFdata[flag].flagger = 0;
			CTFdata[flag].state = flag_dropped;
			if(CTFdata[flag].actor)
				CTFdata[flag].actor->Destroy();
			break;
	}

	// [AM] Play CTF sound, moved from server.
	CTF_Sound(flag, event);
}
Example #10
0
// Distribute X number of players between teams.
bool Pickup_DistributePlayers(size_t num_players, std::string &error) {
    // This function shouldn't do anything unless you're in a teamgame.
    if (!(sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF)) {
        error = "Server is not in a team game.";
        return false;
    }

    // We can't distribute more than MAXPLAYERS so don't even try.
    if (num_players > MAXPLAYERS) {
        error = "Can't distribute that many players.";
        return false;
    }

    // Track all eligible players.
    std::vector<size_t> eligible;

    for (size_t i = 0; i < players.size(); i++) {
        if (validplayer(players[i]) && players[i].ingame() &&
                (!players[i].spectator || (players[i].spectator && players[i].ready))) {
            eligible.push_back(i);
        }
    }

    if (eligible.empty()) {
        error = "No eligible players for distribution.";
        return false;
    }

    if (eligible.size() < num_players) {
        error = "Not enough eligible players for distribution.";
        return false;
    }

    // Jumble up our eligible players and cut the number of
    // eligible players to the passed number.
    std::random_shuffle(eligible.begin(), eligible.end());
    eligible.resize(num_players);

    // Rip through our eligible vector, forcing players in the vector
    // onto alternating teams.
    team_t dest_team = TEAM_BLUE;
    for (size_t i = 0; i < eligible.size(); i++) {
        player_t &player = players[eligible[i]];

        // Force-join the player if he's spectating.
        SV_SetPlayerSpec(player, false, true);

        // Is the last player an odd-one-out?  Randomize
        // the team he is put on.
        if ((eligible.size() % 2) == 1 && i == (eligible.size() - 1)) {
            dest_team = (team_t)(P_Random() % NUMTEAMS);
        }

        // Switch player to the proper team, ensure the correct color,
        // and then update everyone else in the game about it.
        //
        // [SL] Kill the player if they are switching teams so they don't end up
        // holding their own team's flags
        if (player.mo && player.userinfo.team != dest_team)
            P_DamageMobj(player.mo, 0, 0, 1000, 0);

        SV_ForceSetTeam(player, dest_team);
        SV_CheckTeam(player);
        for (size_t j = 0; j< players.size(); j++) {
            SV_SendUserInfo(player, &clients[j]);
        }

        if (dest_team == TEAM_BLUE) {
            dest_team = TEAM_RED;
        } else {
            dest_team = TEAM_BLUE;
        }
    }

    // Force-spectate everyone who is not eligible.
    for (size_t i = 0; i < players.size(); i++) {
        if (std::find(eligible.begin(), eligible.end(), i) == eligible.end()) {
            SV_SetPlayerSpec(players[i], true, true);
        }
    }

    return true;
}
Example #11
0
void NetDemo::readSnapshotData(byte *buf, size_t length)
{
    byte cid = consoleplayer_id;
    byte did = displayplayer_id;

    P_ClearAllNetIds();

    // Remove all players
    players.clear();

    // Remove all actors
    TThinkerIterator<AActor> iterator;
    AActor *mo;
    while ( (mo = iterator.Next() ) )
        mo->Destroy();

    gameaction = ga_nothing;

    FLZOMemFile memfile;

    length = 0;
    memfile.Open(buf);		// open for reading

    FArchive arc(memfile);

    // Read the server cvars
    byte vars[4096], *vars_p;
    vars_p = vars;
    size_t len = arc.ReadCount ();
    arc.Read(vars, len);
    cvar_t::C_ReadCVars(&vars_p);

    std::string mapname;
    bool intermission;
    arc >> mapname;
    arc >> intermission;

    G_SerializeSnapshots(arc);
    P_SerializeRNGState(arc);
    P_SerializeACSDefereds(arc);

    // Read the status of flags in CTF
    for (int i = 0; i < NUMFLAGS; i++)
        arc >> CTFdata[i];

    // Read team points
    for (int i = 0; i < NUMTEAMS; i++)
        arc >> TEAMpoints[i];

    arc >> level.time;

    for (int i = 0; i < NUM_WORLDVARS; i++)
        arc >> ACS_WorldVars[i];

    for (int i = 0; i < NUM_GLOBALVARS; i++)
        arc >> ACS_GlobalVars[i];

    netgame = multiplayer = true;

    // load a base level
    savegamerestore = true;     // Use the player actors in the savegame
    serverside = false;
    G_InitNew(mapname.c_str());
    displayplayer_id = consoleplayer_id = 1;
    savegamerestore = false;

    // read consistancy marker
    byte check;
    arc >> check;

    arc.Close();

    if (check != 0x1d)
        error("Bad snapshot");

    consoleplayer_id = cid;

    // try to restore display player
    player_t *disp = &idplayer(did);
    if (validplayer(*disp) && disp->ingame() && !disp->spectator)
        displayplayer_id = did;
    else
        displayplayer_id = cid;

    // restore player colors
    for (size_t i = 0; i < players.size(); i++)
        R_BuildPlayerTranslation(players[i].id, players[i].userinfo.color);

    // Link the CTF flag actors to CTFdata[i].actor
    TThinkerIterator<AActor> flagiterator;
    while ( (mo = flagiterator.Next() ) )
    {
        if (mo->type == MT_BDWN || mo->type == MT_BCAR)
            CTFdata[it_blueflag].actor = mo->ptr();
        if (mo->type == MT_RDWN || mo->type == MT_RCAR)
            CTFdata[it_redflag].actor = mo->ptr();
    }

    // Make sure the status bar is displayed correctly
    ST_Start();
}
Example #12
0
//
// CL_PredictWorld
//
// Main function for client-side prediction.
// 
void CL_PredictWorld(void)
{
	if (gamestate != GS_LEVEL)
		return;

	player_t *p = &consoleplayer();

	if (!validplayer(*p) || !p->mo || noservermsgs || netdemo.isPaused())
		return;

	// tenatively tell the netgraph that our prediction was successful
	netgraph.setMisprediction(false);

	if (consoleplayer_id != displayplayer_id)
		CL_PredictSpying();

	// [SL] 2012-03-10 - Spectators can predict their position without server
	// correction.  Handle them as a special case and leave.
	if (consoleplayer().spectator)
	{
		CL_PredictSpectator();
		return;
	}
		
	if (p->tic <= 0)	// No verified position from the server
		return;

	// Disable sounds, etc, during prediction
	predicting = true;
	
	// Figure out where to start predicting from
	int predtic = consoleplayer().tic > 0 ? consoleplayer().tic: 0;
	// Last position update from the server is too old!
	if (predtic < gametic - MAXSAVETICS)
		predtic = gametic - MAXSAVETICS;
	
	// Save a snapshot of the player's state before prediction
	PlayerSnapshot prevsnap(p->tic, p);
	cl_savedsnaps[gametic % MAXSAVETICS] = prevsnap;

	// Move sectors to the last position received from the server
	if (cl_predictsectors)
		CL_ResetSectors();

	// Move the client to the last position received from the sever
	int snaptime = p->snapshots.getMostRecentTime();
	PlayerSnapshot snap = p->snapshots.getSnapshot(snaptime);
	snap.toPlayer(p);

	if (cl_predictlocalplayer)
	{
		while (++predtic < gametic)
		{
			if (cl_predictsectors)
				CL_PredictSectors(predtic);
			CL_PredictLocalPlayer(predtic);  
		}

		// If the player didn't just spawn or teleport, nudge the player from
		// his position last tic to this new corrected position.  This smooths the
		// view when there's a misprediction.
		if (snap.isContinuous())
		{
			PlayerSnapshot correctedprevsnap(p->tic, p);

			// Did we predict correctly?
			bool correct = (correctedprevsnap.getX() == prevsnap.getX()) &&
						   (correctedprevsnap.getY() == prevsnap.getY()) &&
						   (correctedprevsnap.getZ() == prevsnap.getZ());

			if (!correct)
			{
				// Update the netgraph concerning our prediction's error
				netgraph.setMisprediction(true);

				// Lerp from the our previous position to the correct position
				PlayerSnapshot lerpedsnap = P_LerpPlayerPosition(prevsnap, correctedprevsnap, cl_prednudge);	
				lerpedsnap.toPlayer(p);
			
				// [SL] 2012-04-26 - Snap directly to the corrected position in
				// the z direction.  This prevents players from floating above
				// lifts when the lift height is mispredicted.
				p->mo->z = correctedprevsnap.getZ();
			}
		}
	}

	predicting = false;

	// Run thinkers for current gametic
	if (cl_predictsectors)
		CL_PredictSectors(gametic);		
	CL_PredictLocalPlayer(gametic);
}
Example #13
0
void AActor::Serialize (FArchive &arc)
{
	Super::Serialize (arc);
	if (arc.IsStoring ())
	{
		int playerid = player ? player->id : 0;
		arc << x
			<< y
			<< z
			<< pitch
			<< angle
			<< roll
			<< sprite
			<< frame
			<< effects
			<< floorz
			<< ceilingz
			<< radius
			<< height
			<< momx
			<< momy
			<< momz
			<< type
			<< tics
			<< state
			<< flags
			<< health
			<< movedir
			<< visdir
			<< movecount
			/*<< target ? target->netid : 0*/
			/*<< lastenemy ? lastenemy->netid : 0*/
			<< reactiontime
			<< threshold
			<< playerid
			<< lastlook
			/*<< tracer ? tracer->netid : 0*/
			<< tid
			/*<< goal ? goal->netid : 0*/
			<< (unsigned)0
			<< translucency
			<< waterlevel;

		if (translation)
			arc << (DWORD)(translation - translationtables);
		else
			arc << (DWORD)0xffffffff;
		spawnpoint.Serialize (arc);
	}
	else
	{
		unsigned dummy;
		unsigned playerid;
		arc >> x
			>> y
			>> z
			>> pitch
			>> angle
			>> roll
			>> sprite
			>> frame
			>> effects
			>> floorz
			>> ceilingz
			>> radius
			>> height
			>> momx
			>> momy
			>> momz
			>> type
			>> tics
			>> state
			>> flags
			>> health
			>> movedir
			>> visdir
			>> movecount
			/*>> target->netid*/
			/*>> lastenemy->netid*/
			>> reactiontime
			>> threshold
			>> playerid
			>> lastlook
			/*>> tracer->netid*/
			>> tid
			/*>> goal->netid*/
			>> dummy
			>> translucency
			>> waterlevel;

		DWORD trans;
		arc >> trans;
		if (trans == (DWORD)0xffffffff)
			translation = NULL;
		else
			translation = translationtables + trans;
		spawnpoint.Serialize (arc);
		info = &mobjinfo[type];
		touching_sectorlist = NULL;
		LinkToWorld ();
		AddToHash ();
		if(playerid && validplayer(idplayer(playerid)))
		{
			player = &idplayer(playerid);
			player->mo = ptr();
			player->camera = player->mo;
		}
	}
}
Example #14
0
// Return a "spread" of personal frags or team points that the
// current player or team is ahead or behind by.
std::string PersonalSpread(int& color) {
	color = CR_BRICK;
	player_t *plyr = &displayplayer();

	if (sv_gametype == GM_DM) {
		// Seek the highest number of frags.
		byte ingame = 0;
		size_t maxother = 0;
		short maxfrags = -32768;
		for (size_t i = 0;i < players.size();i++) {
			if (!validplayer(players[i])) {
				continue;
			}

			if (!players[i].ingame() || players[i].spectator) {
				continue;
			}

			if (players[i].fragcount == maxfrags) {
				maxother++;
			}

			if (players[i].fragcount > maxfrags) {
				maxfrags = players[i].fragcount;
				maxother = 0;
			}

			ingame += 1;
		}

		// A spread needs two players to make sense.
		if (ingame <= 1) {
			return "";
		}

		// Return the correct spread.
		if (maxfrags == plyr->fragcount && maxother > 0) {
			// We have the maximum number of frags but we share the
			// throne with someone else.  But at least we can take
			// a little shortcut here.
			color = CR_GREEN;
			return "+0";
		}

		std::ostringstream buffer;
		if (maxfrags == plyr->fragcount) {
			// We have the maximum number of frags.  Calculate how
			// far above the other players we are.
			short nextfrags = -32768;

			for (size_t i = 0;i < players.size();i++) {
				if (!validplayer(players[i])) {
					continue;
				}

				if (!players[i].ingame() || players[i].spectator) {
					continue;
				}

				if (players[i].id == plyr->id) {
					continue;
				}

				if (players[i].fragcount > nextfrags) {
					nextfrags = players[i].fragcount;
				}
			}

			color = CR_GREEN;
			buffer << "+" << maxfrags - nextfrags;
			return buffer.str();
		}

		// We are behind the leader.
		buffer << (plyr->fragcount - maxfrags);
		return buffer.str();
	} else if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) {
		// Team spreads are significantly easier.  Just compare two numbers.
		// FIXME: Not if we have more than two teams!
		std::ostringstream buffer;
		switch (plyr->userinfo.team) {
		case TEAM_BLUE:
			if (TEAMpoints[TEAM_BLUE] >= TEAMpoints[TEAM_RED]) {
				color = CR_GREEN;
				buffer << "+";
			}
			buffer << (TEAMpoints[TEAM_BLUE] - TEAMpoints[TEAM_RED]);
			break;
		case TEAM_RED:
			if (TEAMpoints[TEAM_RED] >= TEAMpoints[TEAM_BLUE]) {
				color = CR_GREEN;
				buffer << "+";
			}
			buffer << (TEAMpoints[TEAM_RED] - TEAMpoints[TEAM_BLUE]);
			break;
		default:
			// No valid team?  Something is wrong...
			return "";
		}
		return buffer.str();
	}

	// We're not in an appropriate gamemode.
	return "";
}