Пример #1
0
boolean P_SetMobjState (mobj_t *mobj, statenum_t state)
{
    state_t	*st;

    if (state == S_NULL)
    {
        mobj->state = S_NULL;
        P_RemoveMobj (mobj);
        return false;
    }

    st = &states[state];

    mobj->state = st;
    mobj->tics = st->tics;
    mobj->sprite = st->sprite;
    mobj->frame = st->frame;

    if (st->action)		/* call action functions when the state is set */
        st->action (mobj);

    mobj->latecall = NULL;	/* make sure it doesn't come back to life... */

    return true;
}
Пример #2
0
boolean
P_SetMobjState
( mobj_t*	mobj,
  statenum_t	state )
{
    state_t*	st;

    do
    {
	if (state == S_NULL)
	{
	    mobj->state = (state_t *) S_NULL;
	    P_RemoveMobj (mobj);
	    return false;
	}

	st = &states[state];
	mobj->state = st;
	mobj->tics = st->tics;
	mobj->sprite = st->sprite;
	mobj->frame = st->frame;

	// Modified handling.
	// Call action functions when the state is set
	if (st->action.acp1)		
	    st->action.acp1(mobj);	
	
	state = st->nextstate;
    } while (!mobj->tics);
				
    return true;
}
Пример #3
0
void T_LaserThinker(laserthinker_t* laserthinker)
{   
    laser_t* laser = laserthinker->laser;

    laser->dist += 64;

    // laser reached its destination?
    if(laser->dist >= laser->distmax)
    {
        // reached the end?
        if(!laser->next)
        {
            P_RemoveThinker(&laserthinker->thinker);

            // fade out the laser puff
            P_FadeMobj(laserthinker->dest, -24, 0, 0);
        }
        else
            laserthinker->laser = laser->next;  // advance to next laser point

        // remove marker and free laser
        P_RemoveMobj(laser->marker);
        Z_Free(laser);
    }
    else
    {
        // update laser's location
        laser->x1 += laser->slopex;
        laser->y1 += laser->slopey;
        laser->z1 += laser->slopez;
    }
}
Пример #4
0
//
// P_UnArchiveThinkers
//
void P_UnArchiveThinkers (void)
{
    byte		tclass;
    thinker_t*		currentthinker;
    thinker_t*		next;
    mobj_t*		mobj;
    
    // remove all the current thinkers
    currentthinker = thinkercap.next;
    while (currentthinker != &thinkercap)
    {
	next = currentthinker->next;
	
	if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
	    P_RemoveMobj ((mobj_t *)currentthinker);
	else
	    Z_Free (currentthinker);

	currentthinker = next;
    }
    P_InitThinkers ();
	
    // read in saved thinkers
    while (1)
    {
	tclass = *save_p++;
	switch (tclass)
	{
	  case tc_end:
	    return; 	// end of list
			
	  case tc_mobj:
	    PADSAVEP();
	    mobj = (mobj_t*)Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
	    memcpy (mobj, save_p, sizeof(*mobj));
	    save_p += sizeof(*mobj);
	    mobj->state = &states[(int)mobj->state];
	    mobj->target = NULL;
	    if (mobj->player)
	    {
		mobj->player = &players[(int)mobj->player-1];
		mobj->player->mo = mobj;
	    }
	    P_SetThingPosition (mobj);
	    mobj->info = &mobjinfo[mobj->type];
	    mobj->floorz = mobj->subsector->sector->floorheight;
	    mobj->ceilingz = mobj->subsector->sector->ceilingheight;
	    mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
	    P_AddThinker (&mobj->thinker);
	    break;
			
	  default:
	    I_Error ("Unknown tclass %i in savegame",tclass);
	}
	
    }

}
Пример #5
0
boolean EV_ThingSpawn(byte *args, boolean fog)
{
	int     tid;
	angle_t angle;
	mobj_t *mobj;
	mobj_t *newMobj;
	mobj_t *fogMobj;
	mobjtype_t moType;
	int     searcher;
	boolean success;
	fixed_t z;

	success = false;
	searcher = -1;
	tid = args[0];
	moType = TranslateThingType[args[1]];
	if(nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
	{							// Don't spawn monsters if -nomonsters
		return false;
	}
	angle = (int) args[2] << 24;
	while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if(mobjinfo[moType].flags2 & MF2_FLOATBOB)
		{
			z = mobj->z - mobj->floorz;
		}
		else
		{
			z = mobj->z;
		}
		newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType);
		if(P_TestMobjLocation(newMobj) == false)
		{						// Didn't fit
			P_RemoveMobj(newMobj);
		}
		else
		{
			newMobj->angle = angle;
			if(fog == true)
			{
				fogMobj =
					P_SpawnMobj(mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT,
								MT_TFOG);
				S_StartSound(SFX_TELEPORT, fogMobj);
			}
			newMobj->flags2 |= MF2_DROPPED;	// Don't respawn
			if(newMobj->flags2 & MF2_FLOATBOB)
			{
				newMobj->special1 = newMobj->z - newMobj->floorz;
			}
			success = true;
		}
	}
	return success;
}
Пример #6
0
//
// P_UnArchiveThinkers
//
void P_UnArchiveThinkers (void)
{
    byte		tclass;
    thinker_t*		currentthinker;
    thinker_t*		next;
    mobj_t*		mobj;
    
    // remove all the current thinkers
    currentthinker = thinkercap.next;
    while (currentthinker != &thinkercap)
    {
	next = currentthinker->next;
	
	if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
	    P_RemoveMobj ((mobj_t *)currentthinker);
	else
	    Z_Free (currentthinker);

	currentthinker = next;
    }
    P_InitThinkers ();
    
    // read in saved thinkers
    while (1)
    {
	tclass = saveg_read8();
	switch (tclass)
	{
	  case tc_end:
	    return; 	// end of list
			
	  case tc_mobj:
	    saveg_read_pad();
	    mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
            saveg_read_mobj_t(mobj);

	    mobj->target = NULL;
            mobj->tracer = NULL;
	    P_SetThingPosition (mobj);
	    mobj->info = &mobjinfo[mobj->type];
	    mobj->floorz = mobj->subsector->sector->floorheight;
	    mobj->ceilingz = mobj->subsector->sector->ceilingheight;
	    mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
	    P_AddThinker (&mobj->thinker);
	    break;

	  default:
	    I_Error ("Unknown tclass %i in savegame",tclass);
	}
	
    }

}
Пример #7
0
dboolean G_CheckSpot(int playernum, mapthing_t* mthing) {
    fixed_t         x;
    fixed_t         y;
    subsector_t*    ss;
    angle_t         an;
    mobj_t*         mo;
    int             i;

    if(!players[playernum].mo) {
        // first spawn of level, before corpses
        for(i = 0; i < playernum; i++) {
            if((players[i].mo->x == INT2F(mthing->x)) && (players[i].mo->y == INT2F(mthing->y))) {
                return false;
            }
        }
        return true;
    }

    x = INT2F(mthing->x);
    y = INT2F(mthing->y);

    if(!P_CheckPosition(players[playernum].mo, x, y)) {
        return false;
    }

    // flush an old corpse if needed
    if(bodyqueslot >= BODYQUESIZE) {
        P_RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]);
    }

    bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo;
    bodyqueslot++;

    // spawn a teleport fog
    ss = R_PointInSubsector(x, y);

    // 20120402 villsa - force angle_t typecast to avoid issues on 64-bit machines
    an = ANG45 * (angle_t)(mthing->angle / 45);

    mo = P_SpawnMobj(
             x + 20*dcos(an),
             y + 20*dsin(an),
             ss->sector->floorheight,
             MT_TELEPORTFOG
         );

    if(players[playernum].viewz != 1) {
        S_StartSound(mo, sfx_telept);    // don't start sound on first frame
    }

    return true;
}
Пример #8
0
boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state)
{
    state_t *st;

    if (state == S_NULL)
    {                           // Remove mobj
        mobj->state = (state_t *) S_NULL;
        P_RemoveMobj(mobj);
        return (false);
    }
    st = &states[state];
    mobj->state = st;
    mobj->tics = st->tics;
    mobj->sprite = st->sprite;
    mobj->frame = st->frame;
    return (true);
}
Пример #9
0
boolean EV_ThingRemove(int tid)
{
	mobj_t *mobj;
	int     searcher;
	boolean success;

	success = false;
	searcher = -1;
	while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
	{
		if(mobj->type == MT_BRIDGE)
		{
			A_BridgeRemove(mobj);
			return true;
		}
		P_RemoveMobj(mobj);
		success = true;
	}
	return success;
}
Пример #10
0
boolean
P_SetMobjState
( mobj_t*	mobj,
  statenum_t	state )
{
    state_t*	st;
    int	cycle_counter = 0;

    do
    {
	if (state == S_NULL)
	{
	    mobj->state = (state_t *) S_NULL;
	    P_RemoveMobj (mobj);
	    return false;
	}

	st = &states[state];
	mobj->state = st;
	mobj->tics = st->tics;
	mobj->sprite = st->sprite;
	mobj->frame = st->frame;

	// Modified handling.
	// Call action functions when the state is set
	if (st->action.acp3)
	    st->action.acp3(mobj, NULL, NULL); // [crispy] let pspr action pointers get called from mobj states
	
	state = st->nextstate;

	if (cycle_counter++ > MOBJ_CYCLE_LIMIT)
	{
	    I_Error("P_SetMobjState: Infinite state cycle detected!");
	}
    } while (!mobj->tics);
				
    return true;
}
Пример #11
0
static CMD(SpawnThing) {
    int id = 0;
    player_t *player;
    mobj_t *thing;
    fixed_t x, y, z;

    if(gamestate != GS_LEVEL) {
        return;
    }

    if(!param[0]) {
        return;
    }

    if(netgame) {
        return;
    }

    id = datoi(param[0]);
    if(id >= NUMMOBJTYPES || id < 0) {
        return;
    }

    player = &players[consoleplayer];
    x = player->mo->x + FixedMul(INT2F(64) + mobjinfo[id].radius, dcos(player->mo->angle));
    y = player->mo->y + FixedMul(INT2F(64) + mobjinfo[id].radius, dsin(player->mo->angle));
    z = player->mo->z;

    thing = P_SpawnMobj(x, y, z, id);

    if(thing->info->spawnstate == S_000) {
        P_RemoveMobj(thing);
        return;
    }

    thing->angle = player->mo->angle;
}
Пример #12
0
void P_UnArchiveMobjs(void) {
    mobj_t* current;
    mobj_t* next;
    mobj_t* mobj;
    int     i;

    // remove all the current thinkers
    current = mobjhead.next;
    while(current != &mobjhead) {
        next = current->next;
        P_RemoveMobj(current);

        current = next;
    }

    saveg_setup_mobjread();
    mobjhead.next = mobjhead.prev = &mobjhead;

    for(i = 0; i < savegmobjnum; i++) {
        mobj = savegmobj[i].mobj;

        saveg_read_pad();
        saveg_read_mobj_t(mobj);

        if(!saveg_read_marker(SAVEGAME_MOBJ))
            I_Error("P_UnArchiveMobjs: Mobj read is inconsistent\nfile offset: %i\nmobj count: %i",
                    save_offset, savegmobjnum);

        P_SetThingPosition(mobj);
        P_LinkMobj(mobj);

        mobj->info = &mobjinfo[mobj->type];
    }

    saveg_read_pad();
}
Пример #13
0
void P_XYMovement(mobj_t *mo)
{
    player_t *player;
    fixed_t  xmove, ymove;

    if (!mo->momx && !mo->momy)
    {
        if (mo->flags & MF_SKULLFLY)
        {
            // the skull slammed into something
            mo->flags &= ~MF_SKULLFLY;
            mo->momx = mo->momy = mo->momz = 0;

            P_SetMobjState(mo, (statenum_t)mo->info->spawnstate);
        }
        return;
    }

    player = mo->player;

    if (mo->type == MT_ROCKET)
    {
        if (puffcount++ > 1)
            P_SpawnPuff(mo->x, mo->y, mo->z, mo->angle);
    }

    if (mo->momx > MAXMOVE)
        mo->momx = MAXMOVE;
    else if (mo->momx < -MAXMOVE)
        mo->momx = -MAXMOVE;

    if (mo->momy > MAXMOVE)
        mo->momy = MAXMOVE;
    else if (mo->momy < -MAXMOVE)
        mo->momy = -MAXMOVE;

    xmove = mo->momx;
    ymove = mo->momy;

    do
    {
        fixed_t  ptryx, ptryy;

        if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2
            || xmove < -MAXMOVE / 2 || ymove < -MAXMOVE / 2)
        {
            ptryx = mo->x + xmove / 2;
            ptryy = mo->y + ymove / 2;
            xmove >>= 1;
            ymove >>= 1;
        }
        else
        {
            ptryx = mo->x + xmove;
            ptryy = mo->y + ymove;
            xmove = ymove = 0;
        }

        if (!P_TryMove(mo, ptryx, ptryy))
        {
            // blocked move
            if (mo->player)
            {
                // try to slide along it
                P_SlideMove(mo);
            }
            else if (mo->flags & MF_MISSILE)
            {
                // explode a missile
                if (ceilingline
                    && ceilingline->backsector
                    && ceilingline->backsector->ceilingpic == skyflatnum
                    && mo->z > ceilingline->backsector->ceilingheight)
                {
                    // Hack to prevent missiles exploding
                    // against the sky.
                    // Does not handle sky floors.
                    shootingsky = true;
                    P_RemoveMobj(mo);
                    return;
                }
                P_ExplodeMissile(mo);
            }
            else
            {
                mo->momx = mo->momy = 0;
            }
        }
    }
Пример #14
0
//
// P_UnArchiveThinkers
//
void P_UnArchiveThinkers(void)
{
    thinker_t   *currentthinker = thinkers[th_all].next;

    // remove all the current thinkers
    while (currentthinker != &thinkers[th_all])
    {
        thinker_t   *next = currentthinker->next;

        if (currentthinker->function == P_MobjThinker || currentthinker->function == MusInfoThinker)
        {
            P_RemoveMobj((mobj_t *)currentthinker);
            P_RemoveThinkerDelayed(currentthinker);
        }
        else
            Z_Free(currentthinker);

        currentthinker = next;
    }

    P_InitThinkers();

    // remove all bloodsplats
    for (int i = 0; i < numsectors; i++)
    {
        bloodsplat_t    *splat = sectors[i].splatlist;

        while (splat)
        {
            bloodsplat_t    *next = splat->snext;

            P_UnsetBloodSplatPosition(splat);
            splat = next;
        }
    }

    r_bloodsplats_total = 0;
    thingindex = 0;

    // read in saved thinkers
    while (true)
    {
        byte    tclass = saveg_read8();

        switch (tclass)
        {
            case tc_end:
                return;         // end of list

            case tc_mobj:
            {
                mobj_t  *mobj = Z_Calloc(1, sizeof(*mobj), PU_LEVEL, NULL);

                saveg_read_pad();
                saveg_read_mobj_t(mobj);

                mobj->info = &mobjinfo[mobj->type];
                P_SetThingPosition(mobj);

                mobj->thinker.function = (mobj->type == MT_MUSICSOURCE ? MusInfoThinker : P_MobjThinker);
                P_AddThinker(&mobj->thinker);
                mobj->colfunc = mobj->info->colfunc;
                mobj->altcolfunc = mobj->info->altcolfunc;
                P_SetShadowColumnFunction(mobj);
                thingindex = MIN(thingindex + 1, TARGETLIMIT - 1);
                break;
            }

            case tc_bloodsplat:
            {
                bloodsplat_t    *splat = calloc(1, sizeof(*splat));

                saveg_read_pad();
                saveg_read_bloodsplat_t(splat);

                if (r_bloodsplats_total < r_bloodsplats_max)
                {
                    splat->width = spritewidth[splat->patch];
                    splat->sector = R_PointInSubsector(splat->x, splat->y)->sector;
                    P_SetBloodSplatPosition(splat);
                    splat->colfunc = (splat->blood == FUZZYBLOOD ? fuzzcolfunc : bloodsplatcolfunc);
                    r_bloodsplats_total++;
                }

                break;
            }

            default:
                I_Error("This savegame is invalid.");
        }
    }
}
Пример #15
0
void P_SetupLevel(int map, skill_t skill)
{
    int          i;
    static char  lumpname[16];
    int          lumpnum;
    mobj_t      *mobj;
    extern int   cy;

    M_ClearRandom();

    P_LoadingPlaque();

    D_printf("P_SetupLevel(%i,%i)\n", map, skill);

    totalkills = totalitems = totalsecret = 0;
    for(i = 0; i < MAXPLAYERS; i++)
        players[i].killcount = players[i].secretcount = players[i].itemcount = 0;

    Z_CheckHeap(mainzone);
    Z_CheckHeap(refzone);

    Z_FreeTags(mainzone);

    P_InitThinkers();

    //
    // look for a regular (development) map first
    //
    lumpname[0] = 'M';
    lumpname[1] = 'A';
    lumpname[2] = 'P';
    lumpname[3] = '0' + map / 10;
    lumpname[4] = '0' + map % 10;
    lumpname[5] = 0;

    lumpnum = W_GetNumForName(lumpname);

    // note: most of this ordering is important
    P_LoadBlockMap(lumpnum+ML_BLOCKMAP);
    P_LoadVertexes(lumpnum+ML_VERTEXES);
    P_LoadSectors(lumpnum+ML_SECTORS);
    P_LoadSideDefs(lumpnum+ML_SIDEDEFS);
    P_LoadLineDefs(lumpnum+ML_LINEDEFS);
    P_LoadSubsectors(lumpnum+ML_SSECTORS);
    P_LoadNodes(lumpnum+ML_NODES);
    P_LoadSegs(lumpnum+ML_SEGS);

    rejectmatrix = W_CacheLumpNum(lumpnum + ML_REJECT, PU_LEVEL);

    P_GroupLines();

    deathmatch_p = deathmatchstarts;
    P_LoadThings(lumpnum + ML_THINGS);

    //
    // if deathmatch, randomly spawn the active players
    //
    if(netgame == gt_deathmatch)
    {
        for(i = 0; i < MAXPLAYERS; i++)
        {
            if(playeringame[i])
            {
                // must give a player spot before deathmatchspawn
                mobj = P_SpawnMobj(deathmatchstarts[0].x << 16 ,deathmatchstarts[0].y << 16, 0, MT_PLAYER);
                players[i].mo = mobj;
                G_DeathMatchSpawnPlayer(i);
                P_RemoveMobj(mobj);
            }
        }
    }

    // set up world state
    P_SpawnSpecials();
    ST_InitEveryLevel();

    cy = 4;

    iquehead = iquetail = 0;
    gamepaused = false;
}
Пример #16
0
void P_XYMovement (mobj_t* mo) 
{ 	
    fixed_t 	ptryx;
    fixed_t	ptryy;
    player_t*	player;
    fixed_t	xmove;
    fixed_t	ymove;
			
    if (!mo->momx && !mo->momy)
    {
	if (mo->flags & MF_SKULLFLY)
	{
	    // the skull slammed into something
	    mo->flags &= ~MF_SKULLFLY;
	    mo->momx = mo->momy = mo->momz = 0;

	    P_SetMobjState (mo, mo->info->spawnstate);
	}
	return;
    }
	
    player = mo->player;
		
    if (mo->momx > MAXMOVE)
	mo->momx = MAXMOVE;
    else if (mo->momx < -MAXMOVE)
	mo->momx = -MAXMOVE;

    if (mo->momy > MAXMOVE)
	mo->momy = MAXMOVE;
    else if (mo->momy < -MAXMOVE)
	mo->momy = -MAXMOVE;
		
    xmove = mo->momx;
    ymove = mo->momy;
	
    do
    {
	if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
	{
	    ptryx = mo->x + xmove/2;
	    ptryy = mo->y + ymove/2;
	    xmove >>= 1;
	    ymove >>= 1;
	}
	else
	{
	    ptryx = mo->x + xmove;
	    ptryy = mo->y + ymove;
	    xmove = ymove = 0;
	}
		
	if (!P_TryMove (mo, ptryx, ptryy))
	{
	    // blocked move
	    if (mo->player)
	    {	// try to slide along it
		P_SlideMove (mo);
	    }
	    else if (mo->flags & MF_MISSILE)
	    {
		// explode a missile
		if (ceilingline &&
		    ceilingline->backsector &&
		    ceilingline->backsector->ceilingpic == skyflatnum)
		{
		    // Hack to prevent missiles exploding
		    // against the sky.
		    // Does not handle sky floors.
		    P_RemoveMobj (mo);
		    return;
		}
		P_ExplodeMissile (mo);
	    }
	    else
		mo->momx = mo->momy = 0;
	}
    } while (xmove || ymove);
Пример #17
0
//
// P_UnArchiveThinkers
//
void P_v19_UnArchiveThinkers(void)
{
	byte    tclass;
	thinker_t *currentthinker;
	thinker_t *next;
	mobj_t *mobj;

	// remove all the current thinkers
	currentthinker = thinkercap.next;
	while(currentthinker != &thinkercap)
	{
		next = currentthinker->next;

		if(currentthinker->function == P_MobjThinker)
			P_RemoveMobj((mobj_t *) currentthinker);
		else
			Z_Free(currentthinker);

		currentthinker = next;
	}
	P_InitThinkers();

	// read in saved thinkers
	while(1)
	{
		tclass = *save_p++;
		switch (tclass)
		{
		case tc_end:
			return;				// end of list

		case tc_mobj:
			PADSAVEP();
			mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
			memset(mobj, 0, sizeof(*mobj));
			//memcpy (mobj, save_p, sizeof(*mobj));
			//P_MobjConverter(mobj, (savemobj_t*) save_p, false);
			//memcpy(mobj, save_p, sizeof(*mobj));
			SV_ReadMobj(mobj);
			//save_p += sizeof(savemobj_t);
			mobj->state = &states[(int) mobj->state];
			mobj->target = NULL;
			if(mobj->player)
			{
				int     pnum = (int) mobj->player - 1;

				mobj->player = &players[pnum];
				mobj->dplayer = mobj->player->plr;
				mobj->dplayer->mo = mobj;
				mobj->dplayer->clAngle = mobj->angle;
				mobj->dplayer->clLookDir = 0;
			}
			P_SetThingPosition(mobj);
			mobj->info = &mobjinfo[mobj->type];
			mobj->floorz = mobj->subsector->sector->floorheight;
			mobj->ceilingz = mobj->subsector->sector->ceilingheight;
			mobj->thinker.function = P_MobjThinker;
			P_AddThinker(&mobj->thinker);
			break;

		default:
			Con_Error("Unknown tclass %i in savegame", tclass);
		}
	}
}
Пример #18
0
void P_UnArchiveThinkers (void)
{
  thinker_t *th;
  mobj_t    **mobj_p;    // killough 2/14/98: Translation table
  size_t    size;        // killough 2/14/98: size of or index into table

  totallive = 0;
  // killough 3/26/98: Load boss brain state
  memcpy(&brain, save_p, sizeof brain);
  save_p += sizeof brain;

  // remove all the current thinkers
  for (th = thinkercap.next; th != &thinkercap; )
    {
      thinker_t *next = th->next;
      if (th->function == P_MobjThinker)
      {
        P_RemoveMobj ((mobj_t *) th);
        P_RemoveThinkerDelayed(th); // fix mobj leak
      }
      else
        Z_Free (th);
      th = next;
    }
  P_InitThinkers ();

  // killough 2/14/98: count number of thinkers by skipping through them
  {
    byte *sp = save_p;     // save pointer and skip header
    for (size = 1; *save_p++ == tc_mobj; size++)  // killough 2/14/98
      {                     // skip all entries, adding up count
        PADSAVEP();
        save_p += sizeof(mobj_t);//e6y
      }

    if (*--save_p != tc_end)
      I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);

    // first table entry special: 0 maps to NULL
    *(mobj_p = malloc(size * sizeof *mobj_p)) = 0;   // table of pointers
    save_p = sp;           // restore save pointer
  }

  // read in saved thinkers
  for (size = 1; *save_p++ == tc_mobj; size++)    // killough 2/14/98
    {
      mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);

      // killough 2/14/98 -- insert pointers to thinkers into table, in order:
      mobj_p[size] = mobj;

      PADSAVEP();

      memcpy (mobj, save_p, sizeof(mobj_t));
      save_p += sizeof(mobj_t);

      mobj->state = states + (int) mobj->state;

      if (mobj->player)
        (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;

      P_SetThingPosition (mobj);
      mobj->info = &mobjinfo[mobj->type];

      // killough 2/28/98:
      // Fix for falling down into a wall after savegame loaded:
      //      mobj->floorz = mobj->subsector->sector->floorheight;
      //      mobj->ceilingz = mobj->subsector->sector->ceilingheight;

      mobj->thinker.function = P_MobjThinker;
      P_AddThinker (&mobj->thinker);

      if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
        totallive++;
    }

  // killough 2/14/98: adjust target and tracer fields, plus
  // lastenemy field, to correctly point to mobj thinkers.
  // NULL entries automatically handled by first table entry.
  //
  // killough 11/98: use P_SetNewTarget() to set fields

  for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
    {
      P_SetNewTarget(&((mobj_t *) th)->target,
        mobj_p[P_GetMobj(((mobj_t *)th)->target,size)]);

      P_SetNewTarget(&((mobj_t *) th)->tracer,
        mobj_p[P_GetMobj(((mobj_t *)th)->tracer,size)]);

      P_SetNewTarget(&((mobj_t *) th)->lastenemy,
        mobj_p[P_GetMobj(((mobj_t *)th)->lastenemy,size)]);
    }

  {  // killough 9/14/98: restore soundtargets
    int i;
    for (i = 0; i < numsectors; i++)
    {
      mobj_t *target;
      memcpy(&target, save_p, sizeof target);
      save_p += sizeof target;
      // Must verify soundtarget. See P_ArchiveThinkers.
      P_SetNewTarget(&sectors[i].soundtarget, mobj_p[P_GetMobj(target,size)]);
    }
  }

  free(mobj_p);    // free translation table

  // killough 3/26/98: Spawn icon landings:
  if (gamemode == commercial)
  {
    // P_SpawnBrainTargets overwrites brain.targeton and brain.easy with zero.
    struct brain_s brain_tmp = brain; // saving

    P_SpawnBrainTargets();

    // old demos with save/load tics should not be affected by this fix
    if (!prboom_comp[PC_RESET_MONSTERSPAWNER_PARAMS_AFTER_LOADING].state)
    {
      brain = brain_tmp; // restoring
    }
  }
}
Пример #19
0
//===========================================================================
// P_CheckSpot
//  Returns false if the player cannot be respawned
//  at the given mapthing_t spot because something is occupying it 
//  FIXME: Quite a mess!
//===========================================================================
boolean P_CheckSpot(int playernum, mapthing_t * mthing, boolean doTeleSpark)
{
	fixed_t x;
	fixed_t y;
	unsigned an;
	mobj_t *mo;

#if __JDOOM__ || __JHEXEN__
	subsector_t *ss;
#endif
#if __JDOOM__
	int     i;
#endif
#if __JHERETIC__ || __JHEXEN__
	mapthing_t faraway;
	boolean using_dummy = false;
#endif

#if __JDOOM__
	if(!players[playernum].plr->mo)
	{
		// first spawn of level, before corpses
		for(i = 0; i < playernum; i++)
		{
			if(players[i].plr->mo &&
			   players[i].plr->mo->x == mthing->x << FRACBITS &&
			   players[i].plr->mo->y == mthing->y << FRACBITS)
				return false;
		}
		return true;
	}
#endif

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

#if __JHERETIC__ || __JHEXEN__
	if(!players[playernum].plr->mo)
	{
		// The player doesn't have a mobj. Let's create a dummy.
		faraway.x = faraway.y = DDMAXSHORT;
		P_SpawnPlayer(&faraway, playernum);
		using_dummy = true;
	}
	players[playernum].plr->mo->flags2 &= ~MF2_PASSMOBJ;
#endif

	if(!P_CheckPosition(players[playernum].plr->mo, x, y))
	{
#if __JHERETIC__ || __JHEXEN__
		players[playernum].plr->mo->flags2 |= MF2_PASSMOBJ;
		if(using_dummy)
		{
			P_RemoveMobj(players[playernum].plr->mo);
			players[playernum].plr->mo = NULL;
		}
#endif
		return false;
	}

#if __JHERETIC__
	players[playernum].plr->mo->flags2 |= MF2_PASSMOBJ;
#endif

#if __JHERETIC__ || __JHEXEN__
	if(using_dummy)
	{
		P_RemoveMobj(players[playernum].plr->mo);
		players[playernum].plr->mo = NULL;
	}
#endif

#if __JDOOM__
	G_QueueBody(players[playernum].plr->mo);
#endif

	if(doTeleSpark)
	{
		// spawn a teleport fog 
		an = (ANG45 * (mthing->angle / 45)) >> ANGLETOFINESHIFT;

#if __JDOOM__ || __JHEXEN__
		ss = R_PointInSubsector(x, y);
		mo = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an],
						 ss->sector->floorheight, MT_TFOG);
#else							// __JHERETIC__
		mo = P_SpawnTeleFog(x + 20 * finecosine[an], y + 20 * finesine[an]);
#endif

		// don't start sound on first frame
		if(players[consoleplayer].plr->viewz != 1)
		{
#ifdef __JHEXEN__
			S_StartSound(SFX_TELEPORT, mo);
#else
			S_StartSound(sfx_telept, mo);
#endif
		}
	}

	return true;
}
Пример #20
0
void P_UnArchiveThinkers (void)
{
   thinker_t *th;
   mobj_t    **mobj_p;    // killough 2/14/98: Translation table
   size_t    size;        // killough 2/14/98: size of or index into table

   totallive = 0;
   // killough 3/26/98: Load boss brain state
   memcpy(&brain, save_p, sizeof brain);
   save_p += sizeof brain;

   // remove all the current thinkers
   for (th = thinkercap.next; th != &thinkercap; )
   {
      thinker_t *next = th->next;
      if (th->function == P_MobjThinker)
         P_RemoveMobj ((mobj_t *) th);
      else
         Z_Free (th);
      th = next;
   }
   P_InitThinkers ();

   // killough 2/14/98: count number of thinkers by skipping through them
   {
      byte *sp = save_p;     // save pointer and skip header
      for (size = 1; *save_p++ == tc_mobj; size++)  // killough 2/14/98
      {                     // skip all entries, adding up count
         PADSAVEP();
         save_p += sizeof(mobj_t);
      }

      if (*--save_p != tc_end)
         I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);

      // first table entry special: 0 maps to NULL
      *(mobj_p = malloc(size * sizeof *mobj_p)) = 0;   // table of pointers
      save_p = sp;           // restore save pointer
   }

   // read in saved thinkers
   for (size = 1; *save_p++ == tc_mobj; size++)    // killough 2/14/98
   {
      mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);

      // killough 2/14/98 -- insert pointers to thinkers into table, in order:
      mobj_p[size] = mobj;

      PADSAVEP();
      memcpy (mobj, save_p, sizeof(mobj_t));
      save_p += sizeof(mobj_t);
      mobj->state = states + (unsigned long) mobj->state;

      if (mobj->player)
         (mobj->player = &players[(unsigned long) mobj->player - 1]) -> mo = mobj;

      P_SetThingPosition (mobj);
      mobj->info = &mobjinfo[mobj->type];

      // killough 2/28/98:
      // Fix for falling down into a wall after savegame loaded:
      //      mobj->floorz = mobj->subsector->sector->floorheight;
      //      mobj->ceilingz = mobj->subsector->sector->ceilingheight;

      mobj->thinker.function = P_MobjThinker;
      P_AddThinker (&mobj->thinker);

      if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
         totallive++;
   }

   // killough 2/14/98: adjust target and tracer fields, plus
   // lastenemy field, to correctly point to mobj thinkers.
   // NULL entries automatically handled by first table entry.
   //
   // killough 11/98: use P_SetNewTarget() to set fields

   for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
   {
      P_SetNewTarget(&((mobj_t *) th)->target,
                     mobj_p[(size_t)((mobj_t *)th)->target]);

      P_SetNewTarget(&((mobj_t *) th)->tracer,
                     mobj_p[(size_t)((mobj_t *)th)->tracer]);

      P_SetNewTarget(&((mobj_t *) th)->lastenemy,
                     mobj_p[(size_t)((mobj_t *)th)->lastenemy]);

      // phares: added two new fields for Sprite Height problem

      P_SetNewTarget(&((mobj_t *) th)->above_thing,
                     mobj_p[(size_t)((mobj_t *)th)->above_thing]);

      P_SetNewTarget(&((mobj_t *) th)->below_thing,
                     mobj_p[(size_t)((mobj_t *)th)->below_thing]);
   }

   {  // killough 9/14/98: restore soundtargets
      int i;
      for (i = 0; i < numsectors; i++)
      {
         mobj_t *target;
         memcpy(&target, save_p, sizeof target);
         save_p += sizeof target;
         P_SetNewTarget(&sectors[i].soundtarget, mobj_p[(size_t) target]);
      }
   }

   free(mobj_p);    // free translation table

   // killough 3/26/98: Spawn icon landings:
   if (gamemode == commercial)
      P_SpawnBrainTargets();
}
Пример #21
0
void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
{
	int i;
	int parm;
	char lumpname[9];
	char auxName[128];
	int lumpnum;
	mobj_t *mobj;

	for(i = 0; i < MAXPLAYERS; i++)
	{
		players[i].killcount = players[i].secretcount
			= players[i].itemcount = 0;
	}
	players[consoleplayer].viewz = 1; // will be set by player think

#ifdef __WATCOMC__
	if(i_CDMusic == false)
	{
		S_StartSongName("chess", true); // Waiting-for-level-load song
	}
#endif

	Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1);

	P_InitThinkers();
	leveltime = 0;

	if(DevMaps)
	{
		sprintf(auxName, "%sMAP%02d.WAD", DevMapsDir, map);
		W_OpenAuxiliary(auxName);
	}
	sprintf(lumpname, "MAP%02d", map);
	lumpnum = W_GetNumForName(lumpname);
	//
	// Begin processing map lumps
	// Note: most of this ordering is important
	//
	P_LoadBlockMap(lumpnum+ML_BLOCKMAP);
	P_LoadVertexes(lumpnum+ML_VERTEXES);
	P_LoadSectors(lumpnum+ML_SECTORS);
	P_LoadSideDefs(lumpnum+ML_SIDEDEFS);
	P_LoadLineDefs(lumpnum+ML_LINEDEFS);
	P_LoadSubsectors(lumpnum+ML_SSECTORS);
	P_LoadNodes(lumpnum+ML_NODES);
	P_LoadSegs(lumpnum+ML_SEGS);
	rejectmatrix = W_CacheLumpNum(lumpnum+ML_REJECT, PU_LEVEL);
	P_GroupLines();
	bodyqueslot = 0;
	po_NumPolyobjs = 0;
	deathmatch_p = deathmatchstarts;
	P_LoadThings(lumpnum+ML_THINGS);
	PO_Init(lumpnum+ML_THINGS); // Initialize the polyobjs
	P_LoadACScripts(lumpnum+ML_BEHAVIOR); // ACS object code
	//
	// End of map lump processing
	//
	if(DevMaps)
	{
		// Close the auxiliary file, but don't free its loaded lumps.
		// The next call to W_OpenAuxiliary() will do a full shutdown
		// of the current auxiliary WAD (free lumps and info lists).
		W_CloseAuxiliaryFile();
		W_UsePrimary();
	}

	// If deathmatch, randomly spawn the active players
	TimerGame = 0;
	if(deathmatch)
	{
		for (i=0 ; i<MAXPLAYERS ; i++)
		{
			if (playeringame[i])
			{   // must give a player spot before deathmatchspawn
				mobj = P_SpawnMobj (playerstarts[0][i].x<<16,
					playerstarts[0][i].y<<16,0, MT_PLAYER_FIGHTER);
				players[i].mo = mobj;
				G_DeathMatchSpawnPlayer (i);
				P_RemoveMobj (mobj);
			}
		}
		parm = M_CheckParm("-timer");
		if(parm && parm < myargc-1)
		{
			TimerGame = atoi(myargv[parm+1])*35*60;
		}
	}

// set up world state
	P_SpawnSpecials ();

// build subsector connect matrix
//      P_ConnectSubsectors ();

// Load colormap and set the fullbright flag
	i = P_GetMapFadeTable(gamemap);
	W_ReadLump(i, colormaps);
	if(i == W_GetNumForName("COLORMAP"))
	{
		LevelUseFullBright = true;
	}
	else
	{ // Probably fog ... don't use fullbright sprites
		LevelUseFullBright = false;
	}

// preload graphics
	if (precache)
		R_PrecacheLevel ();

	// Check if the level is a lightning level
	P_InitLightning();

	S_StopAllSound();
	SN_StopAllSequences();
	S_StartSong(gamemap, true);

//printf ("free memory: 0x%x\n", Z_FreeMemory());

}
Пример #22
0
//
// P_TouchSpecialThing
//
void P_TouchSpecialThing(mobj_t* special, mobj_t* toucher) {
    player_t*   player;
    fixed_t     delta;
    int         sound;
    int            i = 0;

    delta = special->z - toucher->z;

    if(delta > toucher->height
            || delta < -8*FRACUNIT) {
        // out of reach
        return;
    }


    sound = sfx_itemup;
    player = toucher->player;

    // Dead thing touching.
    // Can happen with a sliding player corpse.
    if(toucher->health <= 0) {
        return;
    }

    // Identify by sprite.
    switch(special->sprite) {
    // armor
    case SPR_ARM1:
        if(!P_GiveArmor(player, 1)) {
            return;
        }
        player->message = GOTARMOR;
        player->messagepic = 23;
        break;

    case SPR_ARM2:
        if(!P_GiveArmor(player, 2)) {
            return;
        }
        player->message = GOTMEGA;
        player->messagepic = 24;
        break;

    // bonus items
    case SPR_BON1:
        player->health+=2;               // can go over 100%
        if(player->health > 200) {
            player->health = 200;
        }
        player->mo->health = player->health;
        player->message = GOTHTHBONUS;
        player->messagepic = 3;
        break;

    case SPR_BON2:
        player->armorpoints+=2;          // can go over 100%
        if(player->armorpoints > 200) {
            player->armorpoints = 200;
        }
        if(!player->armortype) {
            player->armortype = 1;
        }
        player->message = GOTARMBONUS;
        player->messagepic = 4;
        break;

    case SPR_SOUL:
        player->health += 100;
        if(player->health > 200) {
            player->health = 200;
        }
        player->mo->health = player->health;
        player->message = GOTSUPER;
        player->messagepic = 5;
        sound = sfx_powerup;
        break;

    case SPR_MEGA:
        player->health = 200;
        player->mo->health = player->health;
        P_GiveArmor(player,2);
        player->message = GOTMSPHERE;
        player->messagepic = 6;
        sound = sfx_powerup;
        break;

    // cards
    // leave cards for everyone
    case SPR_BKEY:
        if(!(P_GiveCard(player, special, it_bluecard))) {
            return;
        }
        break;

    case SPR_YKEY:
        if(!(P_GiveCard(player, special, it_yellowcard))) {
            return;
        }
        break;

    case SPR_RKEY:
        if(!(P_GiveCard(player, special, it_redcard))) {
            return;
        }
        break;

    case SPR_BSKU:
        if(!(P_GiveCard(player, special, it_blueskull))) {
            return;
        }
        break;

    case SPR_YSKU:
        if(!(P_GiveCard(player, special, it_yellowskull))) {
            return;
        }
        break;

    case SPR_RSKU:
        if(!(P_GiveCard(player, special, it_redskull))) {
            return;
        }
        break;

    // medikits, heals
    case SPR_STIM:
        if(!P_GiveBody(player, 10)) {
            return;
        }
        player->message = GOTSTIM;
        player->messagepic = 31;
        break;

    case SPR_MEDI:
        if(!P_GiveBody(player, 25)) {
            return;
        }

        if(player->health < 25) {
            player->message = GOTMEDINEED;
            player->messagepic = 32;
        }
        else {
            player->message = GOTMEDIKIT;
            player->messagepic = 33;
        }
        break;


    // power ups
    case SPR_PINV:
        if(!P_GivePower(player, pw_invulnerability)) {
            return;
        }
        player->message = GOTINVUL;
        player->messagepic = 34;
        sound = sfx_powerup;
        break;

    case SPR_PSTR:
        if(!P_GivePower(player, pw_strength)) {
            return;
        }
        player->message = GOTBERSERK;
        player->messagepic = 35;
        if(player->readyweapon != wp_fist) {
            player->pendingweapon = wp_fist;
        }
        sound = sfx_powerup;
        break;

    case SPR_PINS:
        if(!P_GivePower(player, pw_invisibility)) {
            return;
        }
        player->message = GOTINVIS;
        player->messagepic = 36;
        sound = sfx_powerup;
        break;

    case SPR_SUIT:
        if(!P_GivePower(player, pw_ironfeet)) {
            return;
        }
        player->message = GOTSUIT;
        player->messagepic = 37;
        sound = sfx_powerup;
        break;

    case SPR_PMAP:
        if(!P_GivePower(player, pw_allmap)) {
            return;
        }
        player->message = GOTMAP;
        player->messagepic = 38;
        sound = sfx_powerup;
        break;

    case SPR_PVIS:
        if(!P_GivePower(player, pw_infrared)) {
            return;
        }
        player->message = GOTVISOR;
        player->messagepic = 39;
        sound = sfx_powerup;
        break;

    // ammo
    case SPR_CLIP:
        if(special->flags & MF_DROPPED) {
            if(!P_GiveAmmo(player,am_clip,0)) {
                return;
            }
        }
        else {
            if(!P_GiveAmmo(player,am_clip,1)) {
                return;
            }
        }
        player->message = GOTCLIP;
        player->messagepic = 7;
        break;

    case SPR_AMMO:
        if(!P_GiveAmmo(player, am_clip,5)) {
            return;
        }
        player->message = GOTCLIPBOX;
        player->messagepic = 8;
        break;

    case SPR_RCKT:
        if(!P_GiveAmmo(player, am_misl,1)) {
            return;
        }
        player->message = GOTROCKET;
        player->messagepic = 9;
        break;

    case SPR_BROK:
        if(!P_GiveAmmo(player, am_misl,5)) {
            return;
        }
        player->message = GOTROCKBOX;
        player->messagepic = 10;
        break;

    case SPR_CELL:
        if(!P_GiveAmmo(player, am_cell,1)) {
            return;
        }
        player->message = GOTCELL;
        player->messagepic = 11;
        break;

    case SPR_CELP:
        if(!P_GiveAmmo(player, am_cell,5)) {
            return;
        }
        player->message = GOTCELLBOX;
        player->messagepic = 12;
        break;

    case SPR_SHEL:
        if(!P_GiveAmmo(player, am_shell,1)) {
            return;
        }
        player->message = (gameskill == sk_baby)?GOTSHELLS2:GOTSHELLS;    //villsa
        player->messagepic = 13;
        break;

    case SPR_SBOX:
        if(!P_GiveAmmo(player, am_shell,5)) {
            return;
        }
        player->message = GOTSHELLBOX;
        player->messagepic = 14;
        break;

    case SPR_BPAK:
        if(!player->backpack) {
            for(i = 0; i < NUMAMMO; i++) {
                player->maxammo[i] *= 2;
            }

            player->backpack = true;
        }
        for(i = 0; i < NUMAMMO; i++) {
            P_GiveAmmo(player, i, 1);
        }

        player->message = GOTBACKPACK;
        player->messagepic = 15;
        break;

    // weapons
    case SPR_BFUG:
        if(!P_GiveWeapon(player, special, wp_bfg, false)) {
            return;
        }
        player->message = GOTBFG9000;
        player->messagepic = 16;
        sound = sfx_sgcock;
        break;

    case SPR_MGUN:
        if(!P_GiveWeapon(player, special, wp_chaingun, special->flags&MF_DROPPED)) {
            return;
        }
        player->message = GOTCHAINGUN;
        player->messagepic = 17;
        sound = sfx_sgcock;
        break;

    case SPR_CSAW:
        if(!P_GiveWeapon(player, special, wp_chainsaw, false)) {
            return;
        }
        player->message = GOTCHAINSAW;
        player->messagepic = 18;
        sound = sfx_sgcock;
        break;

    case SPR_LAUN:
        if(!P_GiveWeapon(player, special, wp_missile, false)) {
            return;
        }
        player->message = GOTLAUNCHER;
        player->messagepic = 19;
        sound = sfx_sgcock;
        break;

    case SPR_PLSM:
        if(!P_GiveWeapon(player, special, wp_plasma, false)) {
            return;
        }
        player->message = GOTPLASMA;
        player->messagepic = 20;
        sound = sfx_sgcock;
        break;

    case SPR_SHOT:
        if(!P_GiveWeapon(player, special, wp_shotgun, special->flags&MF_DROPPED)) {
            return;
        }
        player->message = GOTSHOTGUN;
        player->messagepic = 21;
        sound = sfx_sgcock;
        break;

    case SPR_SGN2:
        if(!P_GiveWeapon(player, special, wp_supershotgun, special->flags&MF_DROPPED)) {
            return;
        }
        player->message = GOTSHOTGUN2;
        player->messagepic = 22;
        sound = sfx_sgcock;
        break;

    case SPR_LSRG:
        if(!P_GiveWeapon(player, special, wp_laser, false)) {
            return;
        }
        player->message = GOTLASER;
        sound = sfx_sgcock;
        break;

    case SPR_ART1:
        if(netgame && player->artifacts & (1<<ART_FAST)) {
            return;
        }

        player->artifacts |= (1<<ART_FAST);
        player->message = GOTARTIFACT1;
        player->messagepic = 41;
        break;

    case SPR_ART2:
        if(netgame && player->artifacts & (1<<ART_DOUBLE)) {
            return;
        }

        player->artifacts |= (1<<ART_DOUBLE);
        player->message = GOTARTIFACT2;
        player->messagepic = 42;
        break;

    case SPR_ART3:
        if(netgame && player->artifacts & (1<<ART_TRIPLE)) {
            return;
        }

        player->artifacts |= (1<<ART_TRIPLE);
        player->message = GOTARTIFACT3;
        player->messagepic = 43;
        break;

    default:
        if(special->type != MT_FAKEITEM) {
            CON_Printf(YELLOW, "P_SpecialThing: Unknown gettable thing: %s\n", sprnames[special->sprite]);
            special->flags &= ~MF_SPECIAL;
            return;
        }
        break;
    }

    if(special->flags & MF_TRIGTOUCH || special->type == MT_FAKEITEM) {
        if(special->tid) {
            P_QueueSpecial(special);
        }
    }

    if(special->type != MT_FAKEITEM) {
        if(special->flags & MF_COUNTITEM) {
            player->itemcount++;
        }

        if(special->flags & MF_COUNTSECRET) {
            player->secretcount++;
        }

        P_RemoveMobj(special);
        player->bonuscount += BONUSADD;

        if(player == &players[consoleplayer]) {
            S_StartSound(NULL, sound);
        }
    }
}
Пример #23
0
//
// P_UnArchiveThinkers
//
void P_UnArchiveThinkers (void)
{
    byte                tclass;
    thinker_t*          currentthinker;
    thinker_t*          next;
    mobj_t*             mobj;
    
    // remove all the current thinkers
    currentthinker = thinkercap.next;
    while (currentthinker != &thinkercap)
    {
        next = currentthinker->next;

        if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
            P_RemoveMobj ((mobj_t *)currentthinker);
        else
            Z_Free (currentthinker);

        currentthinker = next;
    }
    P_InitThinkers ();
    
    // read in saved thinkers
    while (1)
    {
        tclass = saveg_read8();
        switch (tclass)
        {
        case tc_end:
            return; 	// end of list

        case tc_mobj:
            saveg_read_pad();
            mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
            saveg_read_mobj_t(mobj);

            // haleyjd 09/29/10: Strife sets the targets of non-allied creatures
            // who had a non-NULL target at save time to players[0].mo so that
            // they won't fall back asleep.
            //
            // BUG: As the player may not have been spawned yet, we could be
            // setting monsters' targets to the mobj which was spawned by 
            // P_SetupLevel and then removed just above. Due to a subtle glitch
            // in the DOOM engine whereby all things removed in this function
            // are leaked until the next time P_SetupLevel is called, this is a
            // safe operation - the call to P_InitThinkers above stops any of
            // the objects removed, including the player's previous body, from
            // being passed to Z_Free. One glitch relying on another!

            if(mobj->target != NULL && (mobj->flags & MF_ALLY) != MF_ALLY)
                mobj->target = players[0].mo;
            else
                mobj->target = NULL;

            // WARNING! Strife does not seem to set tracer! I am leaving it be
            // for now because so far no crashes have been observed, and failing
            // to set this here will almost certainly crash Choco.
            mobj->tracer = NULL;
            P_SetThingPosition (mobj);
            mobj->info = &mobjinfo[mobj->type];
            // [STRIFE]: doesn't set these
            //mobj->floorz = mobj->subsector->sector->floorheight;
            //mobj->ceilingz = mobj->subsector->sector->ceilingheight;
            mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
            P_AddThinker (&mobj->thinker);
            break;

        default:
            I_Error ("Unknown tclass %i in savegame",tclass);
        }
    }
}
Пример #24
0
void P_UnArchiveThinkers (void)
{
  thinker_t *th;
  mobj_t    **mobj_p;    // killough 2/14/98: Translation table
  size_t    size;        // killough 2/14/98: size of or index into table

  totallive = 0;
  // killough 3/26/98: Load boss brain state
  memcpy(&brain, save_p, sizeof brain);
  save_p += sizeof brain;

  // remove all the current thinkers
  for (th = thinkercap.next; th != &thinkercap; )
    {
      thinker_t *next = th->next;
      if (th->function == P_MobjThinker)
      {
        P_RemoveMobj ((mobj_t *) th);
        P_RemoveThinkerDelayed(th); // fix mobj leak
      }
      else
        Z_Free (th);
      th = next;
    }
  P_InitThinkers ();

  // killough 2/14/98: count number of thinkers by skipping through them
  {
    byte *sp = save_p;     // save pointer and skip header
    for (size = 1; *save_p++ == tc_mobj; size++)  // killough 2/14/98
      {                     // skip all entries, adding up count
        PADSAVEP();
	/* cph 2006/07/30 - see comment below for change in layout of mobj_t */
        save_p += sizeof(mobj_t)+3*sizeof(void*)-4*sizeof(fixed_t);
      }

    if (*--save_p != tc_end)
      I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);

    // first table entry special: 0 maps to NULL
    *(mobj_p = malloc(size * sizeof *mobj_p)) = 0;   // table of pointers
    save_p = sp;           // restore save pointer
  }

  // read in saved thinkers
  for (size = 1; *save_p++ == tc_mobj; size++)    // killough 2/14/98
    {
      mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);

      // killough 2/14/98 -- insert pointers to thinkers into table, in order:
      mobj_p[size] = mobj;

      PADSAVEP();
      /* cph 2006/07/30 - 
       * The end of mobj_t changed from
       *  boolean invisible;
       *  mobj_t* lastenemy;
       *  mobj_t* above_monster;
       *  mobj_t* below_monster;
       *  void* touching_sectorlist;
       * to
       *  mobj_t* lastenemy;
       *  void* touching_sectorlist;
       *  fixed_t PrevX, PrevY, PrevZ;
       * at prboom 2.4.4. There is code here to preserve the savegame format.
       *
       * touching_sectorlist is reconstructed anyway, so we now read in all 
       * but the last 5 words from the savegame (filling all but the last 2
       * fields of our current mobj_t. We then pull lastenemy from the 2nd of
       * the 5 leftover words, and skip the others.
       */
      memcpy (mobj, save_p, sizeof(mobj_t)-2*sizeof(void*)-4*sizeof(fixed_t));
      save_p += sizeof(mobj_t)-sizeof(void*)-4*sizeof(fixed_t);
      memcpy (&(mobj->lastenemy), save_p, sizeof(void*));
      save_p += 4*sizeof(void*);
      mobj->state = states + (int) mobj->state;

      if (mobj->player)
        (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;

      P_SetThingPosition (mobj);
      mobj->info = &mobjinfo[mobj->type];

      // killough 2/28/98:
      // Fix for falling down into a wall after savegame loaded:
      //      mobj->floorz = mobj->subsector->sector->floorheight;
      //      mobj->ceilingz = mobj->subsector->sector->ceilingheight;

      mobj->thinker.function = P_MobjThinker;
      P_AddThinker (&mobj->thinker);

      if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
        totallive++;
    }

  // killough 2/14/98: adjust target and tracer fields, plus
  // lastenemy field, to correctly point to mobj thinkers.
  // NULL entries automatically handled by first table entry.
  //
  // killough 11/98: use P_SetNewTarget() to set fields

  for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
    {
      P_SetNewTarget(&((mobj_t *) th)->target,
        mobj_p[P_GetMobj(((mobj_t *)th)->target,size)]);

      P_SetNewTarget(&((mobj_t *) th)->tracer,
        mobj_p[P_GetMobj(((mobj_t *)th)->tracer,size)]);

      P_SetNewTarget(&((mobj_t *) th)->lastenemy,
        mobj_p[P_GetMobj(((mobj_t *)th)->lastenemy,size)]);
    }

  {  // killough 9/14/98: restore soundtargets
    int i;
    for (i = 0; i < numsectors; i++)
    {
      mobj_t *target;
      memcpy(&target, save_p, sizeof target);
      save_p += sizeof target;
      // Must verify soundtarget. See P_ArchiveThinkers.
      P_SetNewTarget(&sectors[i].soundtarget, mobj_p[P_GetMobj(target,size)]);
    }
  }

  free(mobj_p);    // free translation table

  // killough 3/26/98: Spawn icon landings:
  if (gamemode == commercial)
    P_SpawnBrainTargets();
}
Пример #25
0
void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
{
    int i;
    int parm;
    char lumpname[9];
    int lumpnum;
    mobj_t *mobj;

    for (i = 0; i < MAXPLAYERS; i++)
    {
        players[i].killcount = players[i].secretcount
            = players[i].itemcount = 0;
    }
    players[consoleplayer].viewz = 1;   // will be set by player think

    // Waiting-for-level-load song; not played if playing music from CD
    // (the seek time will be so long it will just make loading take
    // longer)
    if (!cdmusic)
    {
        S_StartSongName("chess", true);
    }

    Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);

    P_InitThinkers();
    leveltime = 0;

    sprintf(lumpname, "MAP%02d", map);
    lumpnum = W_GetNumForName(lumpname);
    //
    // Begin processing map lumps
    // Note: most of this ordering is important
    //
    P_LoadBlockMap(lumpnum + ML_BLOCKMAP);
    P_LoadVertexes(lumpnum + ML_VERTEXES);
    P_LoadSectors(lumpnum + ML_SECTORS);
    P_LoadSideDefs(lumpnum + ML_SIDEDEFS);
    P_LoadLineDefs(lumpnum + ML_LINEDEFS);
    P_LoadSubsectors(lumpnum + ML_SSECTORS);
    P_LoadNodes(lumpnum + ML_NODES);
    P_LoadSegs(lumpnum + ML_SEGS);
    rejectmatrix = W_CacheLumpNum(lumpnum + ML_REJECT, PU_LEVEL);
    P_GroupLines();
    bodyqueslot = 0;
    po_NumPolyobjs = 0;
    deathmatch_p = deathmatchstarts;
    P_LoadThings(lumpnum + ML_THINGS);
    PO_Init(lumpnum + ML_THINGS);       // Initialize the polyobjs
    P_LoadACScripts(lumpnum + ML_BEHAVIOR);     // ACS object code
    //
    // End of map lump processing
    //

    // If deathmatch, randomly spawn the active players
    TimerGame = 0;
    if (deathmatch)
    {
        for (i = 0; i < MAXPLAYERS; i++)
        {
            if (playeringame[i])
            {                   // must give a player spot before deathmatchspawn
                mobj = P_SpawnMobj(playerstarts[0][i].x << 16,
                                   playerstarts[0][i].y << 16, 0,
                                   MT_PLAYER_FIGHTER);
                players[i].mo = mobj;
                G_DeathMatchSpawnPlayer(i);
                P_RemoveMobj(mobj);
            }
        }

        //!
        // @arg <n>
        // @category net
        // @vanilla
        //
        // For multiplayer games: exit each level after n minutes.
        //

        parm = M_CheckParmWithArgs("-timer", 1);
        if (parm)
        {
            TimerGame = atoi(myargv[parm + 1]) * 35 * 60;
        }
    }

// set up world state
    P_SpawnSpecials();

// build subsector connect matrix
//      P_ConnectSubsectors ();

// Load colormap and set the fullbright flag
    i = P_GetMapFadeTable(gamemap);
    W_ReadLump(i, colormaps);
    if (i == W_GetNumForName("COLORMAP"))
    {
        LevelUseFullBright = true;
    }
    else
    {                           // Probably fog ... don't use fullbright sprites
        LevelUseFullBright = false;
    }

// preload graphics
    if (precache)
        R_PrecacheLevel();

    // Check if the level is a lightning level
    P_InitLightning();

    S_StopAllSound();
    SN_StopAllSequences();
    S_StartSong(gamemap, true);

//printf ("free memory: 0x%x\n", Z_FreeMemory());

}
Пример #26
0
void P_SetupLevel (int map, skill_t skill)
{
	int		i;
	static char	lumpname[16];
	int		lumpnum;
	mobj_t	*mobj;
	extern	int	cy;
	
	M_ClearRandom ();

	P_LoadingPlaque ();
	
D_printf ("P_SetupLevel(%i,%i)\n",map,skill);
	
	totalkills = totalitems = totalsecret = 0;
	for (i=0 ; i<MAXPLAYERS ; i++)
	{
		players[i].killcount = players[i].secretcount 
		= players[i].itemcount = 0;
	}

Z_CheckHeap (mainzone);		
#ifndef MARS
Z_CheckHeap (refzone);
#endif

	Z_FreeTags (mainzone);
/*PrintHex (1,1,Z_FreeMemory (mainzone)); */

	P_InitThinkers ();
	
/* */
/* look for a regular (development) map first */
/* */
	lumpname[0] = 'M';
	lumpname[1] = 'A';
	lumpname[2] = 'P';
	lumpname[3] = '0' + map/10;
	lumpname[4] = '0' + map%10;
	lumpname[5] = 0;
	
	lumpnum = W_GetNumForName (lumpname);
	
/* note: most of this ordering is important	 */
	P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
	P_LoadVertexes (lumpnum+ML_VERTEXES);
	P_LoadSectors (lumpnum+ML_SECTORS);
	P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
	P_LoadLineDefs (lumpnum+ML_LINEDEFS);
	P_LoadSubsectors (lumpnum+ML_SSECTORS);
	P_LoadNodes (lumpnum+ML_NODES);
	P_LoadSegs (lumpnum+ML_SEGS);
	
#ifdef MARS
	rejectmatrix = (byte *)(wadfileptr+BIGLONG(lumpinfo[lumpnum+ML_REJECT].filepos));
#else
	rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
#endif

	P_GroupLines ();

	deathmatch_p = deathmatchstarts;
	P_LoadThings (lumpnum+ML_THINGS);
	
/* */
/* if deathmatch, randomly spawn the active players */
/* */
	if (netgame == gt_deathmatch)
	{
		for (i=0 ; i<MAXPLAYERS ; i++)
			if (playeringame[i])
			{	/* must give a player spot before deathmatchspawn */
				mobj = P_SpawnMobj (deathmatchstarts[0].x<<16
				,deathmatchstarts[0].y<<16,0, MT_PLAYER);
				players[i].mo = mobj;
				G_DeathMatchSpawnPlayer (i);
				P_RemoveMobj (mobj);
			}
	}
	
/* set up world state */
	P_SpawnSpecials ();
	ST_InitEveryLevel ();
	
/*printf ("free memory: 0x%x\n", Z_FreeMemory(mainzone)); */

	cy = 4;

#ifdef JAGUAR
{
extern byte *debugscreen;
	D_memset (debugscreen,0,32*224);
	
}
#endif

	iquehead = iquetail = 0;
	gamepaused = false;
}