예제 #1
0
void Unlag::reconcilePlayerPositions(byte shooter_id, size_t ticsago)
{
	for (size_t i=0; i<player_history.size(); i++)
	{
		player_t *player = player_history[i].player;

		// skip over the player shooting and any spectators
		if (player->id == shooter_id || player->spectator || !player->mo)
			continue;
	
		fixed_t dest_x, dest_y, dest_z; // position to move player to

		if (!reconciled)
		{
			// record the player's current position, which hasn't yet
			// been saved to the history arrays
			player_history[i].backup_x = player->mo->x;
			player_history[i].backup_y = player->mo->y;
			player_history[i].backup_z = player->mo->z;
  
  			size_t cur = (gametic - ticsago) % Unlag::MAX_HISTORY_TICS;

			dest_x = player_history[i].history_x[cur];
			dest_y = player_history[i].history_y[cur];
			dest_z = player_history[i].history_z[cur];

			if (player_history[i].history_size < ticsago)
			{
				// make the player temporarily unshootable since this player
				// was not alive when the shot was fired.  Kind of a hack.
				player_history[i].backup_flags = player->mo->flags;
				player->mo->flags &= ~(MF_SHOOTABLE | MF_SOLID);
				player_history[i].changed_flags = true;
			}

			#ifdef _UNLAG_DEBUG_
			// spawn a marker sprite at the reconciled position for debugging
	        AActor *mo = new AActor(dest_x, dest_y, dest_z, MT_KEEN);
			mo->flags &= ~(MF_SHOOTABLE | MF_SOLID);
			mo->health = -187;
			SV_SpawnMobj(mo);
			#endif // _UNLAG_DEBUG_
		}
		else
		{   // we're moving the player back to proper position
			dest_x = player_history[i].backup_x;
			dest_y = player_history[i].backup_y;
			dest_z = player_history[i].backup_z;

			// restore a player's shootability if we removed it previously
			if (player_history[i].changed_flags)
			{
				player->mo->flags = player_history[i].backup_flags;
				player_history[i].changed_flags = false;
			}
		}   

		movePlayer(player, dest_x, dest_y, dest_z); 
	}
}
예제 #2
0
//
//	[Toke - CTF] CTF_SpawnFlag
//	Spawns a flag of the designated type in the designated location
//
void CTF_SpawnFlag (flag_t f)
{
	flagdata *data = &CTFdata[f];

	AActor *flag = new AActor (data->x, data->y, data->z, flag_table[f][flag_home]);

	SV_SpawnMobj(flag);

	data->actor = flag->ptr();
	data->state = flag_home;
	data->flagger = 0;
}
예제 #3
0
//
// CTF_SpawnDroppedFlag
// Spawns a dropped flag
//
void CTF_SpawnDroppedFlag (flag_t f, int x, int y, int z)
{
	flagdata *data = &CTFdata[f];

	AActor *flag = new AActor (x, y, z, flag_table[f][flag_dropped]);

	SV_SpawnMobj(flag);

	data->actor = flag->ptr();
	data->state = flag_dropped;
	data->timeout = (size_t)(ctf_flagtimeout * TICRATE);
	data->flagger = 0;
}
예제 #4
0
//
// P_SpawnPlayer
// Called when a player is spawned on the level.
// Most of the player structure stays unchanged
//	between levels.
//
void P_SpawnPlayer (player_t &player, mapthing2_t *mthing)
{
    // denis - clients should not control spawning
    if(!serverside)
        return;

    // [RH] Things 4001-? are also multiplayer starts. Just like 1-4.
    //		To make things simpler, figure out which player is being
    //		spawned here.
    player_t *p = &player;

    // not playing?
    if(!p->ingame())
        return;

    if (p->playerstate == PST_REBORN || p->playerstate == PST_ENTER)
        G_PlayerReborn (*p);

    AActor *mobj = new AActor (mthing->x << FRACBITS, mthing->y << FRACBITS, ONFLOORZ, MT_PLAYER);

    // set color translations for player sprites
    // [RH] Different now: MF_TRANSLATION is not used.
    //		  mobj->translation = translationtables + 256*playernum;

    mobj->angle = ANG45 * (mthing->angle/45);
    mobj->pitch = mobj->roll = 0;
    mobj->player = p;
    mobj->health = p->health;

    // [RH] Set player sprite based on skin
    if(p->userinfo.skin >= numskins)
        p->userinfo.skin = 0;

    mobj->sprite = skins[p->userinfo.skin].sprite;

    p->fov = 90.0f;
    p->mo = p->camera = mobj->ptr();
    p->playerstate = PST_LIVE;
    p->refire = 0;
    p->damagecount = 0;
    p->bonuscount = 0;
    p->extralight = 0;
    p->fixedcolormap = 0;
    p->viewheight = VIEWHEIGHT;
    p->xviewshift = 0;
    p->attacker = AActor::AActorPtr();

    // Set up some special spectator stuff
    if (p->spectator)
    {
        mobj->translucency = 0;
        p->mo->flags |= MF_SPECTATOR;
        p->mo->flags2 |= MF2_FLY;
    }

    // [RH] Allow chasecam for demo watching
    //if ((demoplayback || demonew) && chasedemo)
    //	p->cheats = CF_CHASECAM;

    // setup gun psprite
    P_SetupPsprites (p);

    // give all cards in death match mode
    if (sv_gametype != GM_COOP)
    {
        for (int i = 0; i < NUMCARDS; i++)
            p->cards[i] = true;
    }

    if(serverside)
    {
        // [RH] If someone is in the way, kill them
        P_TeleportMove (mobj, mobj->x, mobj->y, mobj->z, true);

        // [BC] Do script stuff
        if (level.behavior != NULL)
        {
            if (p->playerstate == PST_ENTER)
            {
                level.behavior->StartTypedScripts (SCRIPT_Enter, p->mo);
            }
            else if (p->playerstate == PST_REBORN)
            {
                level.behavior->StartTypedScripts (SCRIPT_Respawn, p->mo);
            }
        }

        // send new objects
        SV_SpawnMobj(mobj);
    }
}
예제 #5
0
//
// P_SpawnMapThing
// The fields of the mapthing should
// already be in host byte order.
//
// [RH] position is used to weed out unwanted start spots
//
void P_SpawnMapThing (mapthing2_t *mthing, int position)
{
	int i;
	int bit;
	AActor *mobj;
	fixed_t x, y, z;

	if (mthing->type == 0 || mthing->type == -1)
		return;

	// count deathmatch start positions
	if (mthing->type == 11 || ((mthing->type == 5080 || mthing->type == 5081 || mthing->type == 5082))
		&& !sv_teamspawns)
	{
		if (deathmatch_p == &deathmatchstarts[MaxDeathmatchStarts])
		{
			// [RH] Get more deathmatchstarts
			int offset = MaxDeathmatchStarts;
			MaxDeathmatchStarts *= 2;
			deathmatchstarts = (mapthing2_t *)Realloc (deathmatchstarts, MaxDeathmatchStarts * sizeof(mapthing2_t));
			deathmatch_p = &deathmatchstarts[offset];
		}
		memcpy (deathmatch_p, mthing, sizeof(*mthing));
		deathmatch_p++;
		return;
	}

	// [Toke - CTF - starts] CTF starts - count Blue team start positions
	if (mthing->type == 5080 && sv_teamspawns)
	{
		if (blueteam_p == &blueteamstarts[MaxBlueTeamStarts])
		{
			int offset = MaxBlueTeamStarts;
			MaxBlueTeamStarts *= 2;
			blueteamstarts = (mapthing2_t *)Realloc (blueteamstarts, MaxBlueTeamStarts * sizeof(mapthing2_t));
			blueteam_p = &blueteamstarts[offset];
		}
		memcpy (blueteam_p, mthing, sizeof(*mthing));
		blueteam_p++;
		return;
	}

	// [Toke - CTF - starts] CTF starts - count Red team start positions
	if (mthing->type == 5081 && sv_teamspawns)
	{
		if (redteam_p == &redteamstarts[MaxRedTeamStarts])
		{
			int offset = MaxRedTeamStarts;
			MaxRedTeamStarts *= 2;
			redteamstarts = (mapthing2_t *)Realloc (redteamstarts, MaxRedTeamStarts * sizeof(mapthing2_t));
			redteam_p = &redteamstarts[offset];
		}
		memcpy (redteam_p, mthing, sizeof(*mthing));
		redteam_p++;
		return;
	}

	// [RH] Record polyobject-related things
	if (HexenHack)
	{
		switch (mthing->type)
		{
		case PO_HEX_ANCHOR_TYPE:
			mthing->type = PO_ANCHOR_TYPE;
			break;
		case PO_HEX_SPAWN_TYPE:
			mthing->type = PO_SPAWN_TYPE;
			break;
		case PO_HEX_SPAWNCRUSH_TYPE:
			mthing->type = PO_SPAWNCRUSH_TYPE;
			break;
		}
	}

	if (mthing->type == PO_ANCHOR_TYPE ||
		mthing->type == PO_SPAWN_TYPE ||
		mthing->type == PO_SPAWNCRUSH_TYPE)
	{
		polyspawns_t *polyspawn = new polyspawns_t;
		polyspawn->next = polyspawns;
		polyspawn->x = mthing->x << FRACBITS;
		polyspawn->y = mthing->y << FRACBITS;
		polyspawn->angle = mthing->angle;
		polyspawn->type = mthing->type;
		polyspawns = polyspawn;
		if (mthing->type != PO_ANCHOR_TYPE)
			po_NumPolyobjs++;
		return;
	}	

	// check for players specially
	if ((mthing->type <= 4 && mthing->type > 0)
		|| (mthing->type >= 4001 && mthing->type <= 4001 + MAXPLAYERSTARTS - 4))
	{
		// [RH] Only spawn spots that match position.
		if (mthing->args[0] != position)
			return;

		playerstarts.push_back(*mthing);
		return;
	}

	// [RH] sound sequence overrides
	if (mthing->type >= 1400 && mthing->type < 1410)
	{
		return;
	}
	else if (mthing->type == 1411)
	{
		int type;

		if (mthing->args[0] == 255)
			type = -1;
		else
			type = mthing->args[0];

		if (type > 63)
		{
			Printf (PRINT_HIGH, "Sound sequence %d out of range\n", type);
		}
		else
		{
		}
		return;
	}

	/*if (deathmatch)
	{
		if (!(mthing->flags & MTF_DEATHMATCH))
			return;
	}
	else if (multiplayer)
	{
		if (!(mthing->flags & MTF_COOPERATIVE))
			return;
	}

	if (!multiplayer)
	{
		if (!(mthing->flags & MTF_SINGLE))
			return;
	}*/

	// GhostlyDeath -- Correctly spawn things
	if (sv_gametype != GM_COOP && !(mthing->flags & MTF_DEATHMATCH))
		return;
	if (sv_gametype == GM_COOP && sv_maxplayers == 1 && !(mthing->flags & MTF_SINGLE))
		return;
	if (sv_gametype == GM_COOP && sv_maxplayers != 1 && !(mthing->flags & MTF_COOPERATIVE))
		return;

	// check for apropriate skill level
	if (sv_skill == sk_baby)
		bit = 1;
	else if (sv_skill == sk_nightmare)
		bit = 4;
	else
		bit = 1 << ((int)sv_skill - 2);

	if (!(mthing->flags & bit))
		return;

	// [RH] Determine if it is an old ambient thing, and if so,
	//		map it to MT_AMBIENT with the proper parameter.
	if (mthing->type >= 14001 && mthing->type <= 14064)
	{
		mthing->args[0] = mthing->type - 14000;
		mthing->type = 14065;
		i = MT_AMBIENT;
	}
	// [RH] Check if it's a particle fountain
	else if (mthing->type >= 9027 && mthing->type <= 9033)
	{
		mthing->args[0] = mthing->type - 9026;
		i = MT_FOUNTAIN;
	}
	else
	{
		// find which type to spawn
		for (i = 0; i < NUMMOBJTYPES; i++)
			if (mthing->type == mobjinfo[i].doomednum)
				break;
	}

	if (i >= NUMMOBJTYPES)
	{
		// [RH] Don't die if the map tries to spawn an unknown thing
		Printf (PRINT_HIGH, "Unknown type %i at (%i, %i)\n",
			mthing->type,
			mthing->x, mthing->y);
		i = MT_UNKNOWNTHING;
	}
	// [RH] If the thing's corresponding sprite has no frames, also map
	//		it to the unknown thing.
	else if (sprites[states[mobjinfo[i].spawnstate].sprite].numframes == 0)
	{
		Printf (PRINT_HIGH, "Type %i at (%i, %i) has no frames\n",
				mthing->type, mthing->x, mthing->y);
		i = MT_UNKNOWNTHING;
	}

	// don't spawn keycards and players in deathmatch
	if (sv_gametype != GM_COOP && mobjinfo[i].flags & MF_NOTDMATCH)
		return;

	// don't spawn deathmatch weapons in offline single player mode
	if (!multiplayer)
	{
		switch (i)
		{
			case MT_CHAINGUN:
			case MT_SHOTGUN:
			case MT_SUPERSHOTGUN:
			case MT_MISC25: 		// BFG
			case MT_MISC26: 		// chainsaw
			case MT_MISC27: 		// rocket launcher
			case MT_MISC28: 		// plasma gun
				if ((mthing->flags & (MTF_DEATHMATCH|MTF_SINGLE)) == MTF_DEATHMATCH)
					return;
				break;
			default:
				break;
		}
	}

	if (sv_nomonsters)
		if (i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL) )
			return;

	// spawn it
	x = mthing->x << FRACBITS;
	y = mthing->y << FRACBITS;

	if (i == MT_WATERZONE)
	{
		sector_t *sec = R_PointInSubsector (x, y)->sector;
		sec->waterzone = 1;
		return;
	}
	else if (i == MT_SECRETTRIGGER)
	{
		level.total_secrets++;
	}

	if (mobjinfo[i].flags & MF_SPAWNCEILING)
		z = ONCEILINGZ;
	else
		z = ONFLOORZ;

	mobj = new AActor (x, y, z, (mobjtype_t)i);

	if (z == ONFLOORZ)
		mobj->z += mthing->z << FRACBITS;
	else if (z == ONCEILINGZ)
		mobj->z -= mthing->z << FRACBITS;
	mobj->spawnpoint = *mthing;

	if (mobj->flags2 & MF2_FLOATBOB)
	{ // Seed random starting index for bobbing motion
		mobj->health = M_Random();
		mobj->special1 = mthing->z << FRACBITS;
	}

	// [RH] Set the thing's special
	mobj->special = mthing->special;
	memcpy (mobj->args, mthing->args, sizeof(mobj->args));
	
	if (mobj->tics > 0)
		mobj->tics = 1 + (P_Random () % mobj->tics);
	if (mobj->flags & MF_COUNTKILL)
		level.total_monsters++;
	if (mobj->flags & MF_COUNTITEM)
		level.total_items++;

	if (i != MT_SPARK)
		mobj->angle = ANG45 * (mthing->angle/45);

	if (mthing->flags & MTF_AMBUSH)
		mobj->flags |= MF_AMBUSH;

	// [RH] Add ThingID to mobj and link it in with the others
	mobj->tid = mthing->thingid;
	mobj->AddToHash ();

	SV_SpawnMobj(mobj);

	if (sv_gametype == GM_CTF) {
		// [Toke - CTF] Setup flag sockets
		if (mthing->type == ID_BLUE_FLAG)
		{
			flagdata *data = &CTFdata[it_blueflag];
			if (data->flaglocated)
				return;

			CTF_RememberFlagPos (mthing);
			CTF_SpawnFlag(it_blueflag);
		}

		if (mthing->type == ID_RED_FLAG)
		{
			flagdata *data = &CTFdata[it_redflag];
			if (data->flaglocated)
				return;

			CTF_RememberFlagPos (mthing);
			CTF_SpawnFlag(it_redflag);
		}
	}

	// [RH] Go dormant as needed
	if (mthing->flags & MTF_DORMANT)
		P_DeactivateMobj (mobj);
}
예제 #6
0
//
// P_RespawnSpecials
//
void P_RespawnSpecials (void)
{
	fixed_t 			x;
	fixed_t 			y;
	fixed_t 			z;

	subsector_t*			ss;
	AActor* 						mo;
	mapthing2_t* 		mthing;

	int 				i;

	if(!serverside)
		return;

	// only respawn items in deathmatch
	if (sv_gametype == GM_COOP || !sv_itemsrespawn)
		return;

	// nothing left to respawn?
	if (iquehead == iquetail)
		return;

	// wait a certain number of seconds
	if (level.time - itemrespawntime[iquetail] < sv_itemrespawntime*TICRATE)
		return;

	mthing = &itemrespawnque[iquetail];

	x = mthing->x << FRACBITS;
	y = mthing->y << FRACBITS;

	// find which type to spawn
	for (i=0 ; i< NUMMOBJTYPES ; i++)
	{
		if (mthing->type == mobjinfo[i].doomednum)
			break;
	}

	// [Fly] crashes sometimes without it
	if (i >= NUMMOBJTYPES)
	{
		// pull it from the que
		iquetail = (iquetail+1)&(ITEMQUESIZE-1);
		return;
	}

	if (mobjinfo[i].flags & MF_SPAWNCEILING)
		z = ONCEILINGZ;
	else
		z = ONFLOORZ;

	// spawn a teleport fog at the new spot
	ss = R_PointInSubsector (x, y);
	mo = new AActor (x, y, z, MT_IFOG);
	SV_SpawnMobj(mo);
    if (clientside)
        S_Sound (mo, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE);

	// spawn it
	mo = new AActor (x, y, z, (mobjtype_t)i);
	mo->spawnpoint = *mthing;
	mo->angle = ANG45 * (mthing->angle/45);

	if (z == ONFLOORZ)
		mo->z += mthing->z << FRACBITS;
	else if (z == ONCEILINGZ)
		mo->z -= mthing->z << FRACBITS;

	if (mo->flags2 & MF2_FLOATBOB)
	{ // Seed random starting index for bobbing motion
		mo->health = M_Random();
		mo->special1 = mthing->z << FRACBITS;
	}
	
	mo->special = 0;
	
	// pull it from the que
	iquetail = (iquetail+1)&(ITEMQUESIZE-1);

	SV_SpawnMobj(mo);
}