void P_CloseWeapons(void) { int spot; if(!MaceSpotCount) { // No maces placed return; } if(!deathmatch && P_Random() < 64) { // Sometimes doesn't show up if not in deathmatch return; } spot = P_Random() % MaceSpotCount; P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE); }
void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z) { mobj_t *th; z += ((P_Random()-P_Random())<<10); th = P_SpawnMobj (x,y,z, MT_PUFF); th->momz = FRACUNIT; th->tics -= P_Random()&1; if (th->tics < 1) th->tics = 1; /* don't make punches spark on the wall */ if (attackrange == MELEERANGE) P_SetMobjState (th, S_PUFF3); }
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) { mobj_t *th; z += ((P_Random()-P_Random())<<10); th = P_SpawnMobj (x,y,z, MT_BLOOD); th->momz = FRACUNIT*2; th->tics -= P_Random()&1; if (th->tics<1) th->tics = 1; if (damage <= 12 && damage >= 9) P_SetMobjState (th,S_BLOOD2); else if (damage < 9) P_SetMobjState (th,S_BLOOD3); }
// // P_GiveCard // static dboolean P_GiveCard(player_t* player, mobj_t *item, card_t card) { if(netgame && (item && item->flags & MF_TRIGTOUCH)) { P_SpawnMobj(item->x, item->y, item->z, item->type); return true; } if(player->cards[card]) { return false; } player->bonuscount = BONUSADD; player->cards[card] = 1; switch(card) { case it_bluecard: player->message = GOTBLUECARD; player->messagepic = 25; break; case it_yellowcard: player->message = GOTYELWCARD; player->messagepic = 26; break; case it_redcard: player->message = GOTREDCARD; player->messagepic = 27; break; case it_blueskull: player->message = GOTBLUESKUL; player->messagepic = 28; break; case it_yellowskull: player->message = GOTYELWSKUL; player->messagepic = 29; break; case it_redskull: player->message = GOTREDSKULL; player->messagepic = 30; break; } if(netgame) { return false; } return true; }
void P_SpawnPlayer (mapthing_t *mthing) { player_t *p; fixed_t x,y,z; mobj_t *mobj; int i; if (!playeringame[mthing->type-1]) return; /* not playing */ p = &players[mthing->type-1]; if (p->playerstate == PST_REBORN) G_PlayerReborn (mthing->type-1); x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; #if 0 if (mthing->type==1) { x = 0xffb00000; y = 0xff500000; } #endif z = ONFLOORZ; mobj = P_SpawnMobj (x,y,z, MT_PLAYER); mobj->angle = ANG45 * (mthing->angle/45); mobj->player = p; mobj->health = p->health; p->mo = mobj; p->playerstate = PST_LIVE; p->refire = 0; p->message = NULL; p->damagecount = 0; p->bonuscount = 0; p->extralight = 0; p->fixedcolormap = 0; p->viewheight = VIEWHEIGHT; P_SetupPsprites (p); /* setup gun psprite */ if (netgame == gt_deathmatch) for (i=0 ; i<NUMCARDS ; i++) p->cards[i] = true; /* give all cards in death match mode */ }
void P_SpawnTelefog(mobj_t *mo, void * /*context*/) { #if __JDOOM__ || __JDOOM64__ S_StartSound(SFX_ITMBK, mo); #else S_StartSound(SFX_RESPAWN, mo); #endif # if __JDOOM64__ mo->translucency = 255; mo->spawnFadeTics = 0; mo->intFlags |= MIF_FADE; # elif __JDOOM__ // Spawn the item teleport fog at the new spot. P_SpawnMobj(MT_IFOG, mo->origin, mo->angle, 0); # endif }
void C_DECL A_FogSpawn(mobj_t* actor) { mobj_t* mo = NULL; mobjtype_t type = 0; angle_t delta, angle; if(actor->special1-- > 0) return; actor->special1 = actor->args[2]; // Reset frequency count. switch(P_Random() % 3) { case 0: type = MT_FOGPATCHS; break; case 1: type = MT_FOGPATCHM; break; case 2: type = MT_FOGPATCHL; break; } delta = actor->args[1]; if(delta == 0) delta = 1; angle = ((P_Random() % delta) - (delta / 2)); angle <<= 24; if((mo = P_SpawnMobj(type, actor->origin, actor->angle + angle, 0))) { mo->target = actor; if(actor->args[0] < 1) actor->args[0] = 1; mo->args[0] = (P_Random() % (actor->args[0])) + 1; // Random speed. mo->args[3] = actor->args[3]; // Set lifetime. mo->args[4] = 1; // Set to moving. mo->special2 = P_Random() & 63; } }
// // ACS_spawn // static Mobj *ACS_spawn(mobjtype_t type, fixed_t x, fixed_t y, fixed_t z, int tid, angle_t angle, bool forced) { Mobj *mo; if(type != -1 && (mo = P_SpawnMobj(x, y, z, type))) { // If not forcing spawn, check that the position is OK. if(!forced && !P_CheckPositionExt(mo, mo->x, mo->y)) { // And if not, unmake the Mobj. mo->state = NULL; mo->removeThinker(); return NULL; } if(tid) P_AddThingTID(mo, tid); mo->angle = angle; return mo; } else return NULL; }
boolean G_CheckSpot (int playernum, mapthing_t *mthing) { fixed_t x,y; subsector_t *ss; int an; mobj_t *mo; x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; if (!P_CheckPosition (players[playernum].mo, x, y) ) return false; ss = R_PointInSubsector (x,y); an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT; /* spawn a teleport fog */ mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an], ss->sector->floorheight , MT_TFOG); S_StartSound (mo, sfx_telept); return true; }
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; }
// // TELEPORTATION // dboolean EV_Teleport(line_t *line, int side, mobj_t *thing) { thinker_t *thinker; int i; // Don't teleport missiles. // Don't teleport if hit back of line, so you can get out of teleporter. if (side || (thing->flags & MF_MISSILE)) return false; // killough 1/31/98: improve performance by using // P_FindSectorFromLineTag instead of simple linear search. for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) for (thinker = thinkerclasscap[th_mobj].cnext; thinker != &thinkerclasscap[th_mobj]; thinker = thinker->cnext) { mobj_t *m; if ((m = (mobj_t *)thinker)->type == MT_TELEPORTMAN && m->subsector->sector - sectors == i) { fixed_t oldx = thing->x; fixed_t oldy = thing->y; fixed_t oldz = thing->z; player_t *player = thing->player; // killough 5/12/98: exclude voodoo dolls: if (player && player->mo != thing) player = NULL; if (P_TeleportMove(thing, m->x, m->y, m->z, false)) // killough 8/9/98 { mobj_t *fog; fixed_t newx = m->x; fixed_t newy = m->y; // spawn teleport fog at source fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG); fog->angle = thing->angle; S_StartSound(fog, sfx_telept); // spawn teleport fog at destination thing->z = thing->floorz; if (player) { unsigned int an = m->angle >> ANGLETOFINESHIFT; newx += 20 * finecosine[an]; newy += 20 * finesine[an]; player->viewz = thing->z + player->viewheight; } fog = P_SpawnMobj(newx, newy, thing->z, MT_TFOG); fog->angle = m->angle; S_StartSound(fog, sfx_telept); if (player) { // [BH] teleport can be drawn on automap if (line->backsector) { int j; for (j = 0; j < line->backsector->linecount; j++) line->backsector->lines[j]->flags |= ML_TELEPORTTRIGGERED; } // don't move for a bit thing->reactiontime = 18; player->psprites[ps_weapon].sx = 0; player->psprites[ps_weapon].sy = WEAPONTOP; player->momx = player->momy = 0; } thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return true; } }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; fixed_t oldx; fixed_t oldy; fixed_t oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (sector-sectors != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; // The first Final Doom executable does not set thing->z // when teleporting. This quirk is unique to this // particular version; the later version included in // some versions of the Id Anthology fixed this. if (gameversion != exe_final) thing->z = thing->floorz; if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? S_StartSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } }
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; }
static void P_LightningFlash(void) { int i; sector_t *tempSec; int *tempLight; boolean foundSec; int flashLight; if(LightningFlash) { LightningFlash--; if(LightningFlash) { tempLight = LightningLightLevels; tempSec = sectors; for(i = 0; i < numsectors; i++, tempSec++) { if(tempSec->ceilingpic == skyflatnum || tempSec->special == LIGHTNING_SPECIAL || tempSec->special == LIGHTNING_SPECIAL2) { if(*tempLight < tempSec->lightlevel - 4) { tempSec->lightlevel -= 4; } tempLight++; } } } else { // remove the alternate lightning flash special tempLight = LightningLightLevels; tempSec = sectors; for(i = 0; i < numsectors; i++, tempSec++) { if(tempSec->ceilingpic == skyflatnum || tempSec->special == LIGHTNING_SPECIAL || tempSec->special == LIGHTNING_SPECIAL2) { tempSec->lightlevel = *tempLight; tempLight++; } } Rend_SkyParams(1, DD_DISABLE, 0); Rend_SkyParams(0, DD_ENABLE, 0); //Sky1Texture = P_GetMapSky1Texture(gamemap); } return; } LightningFlash = (P_Random() & 7) + 8; flashLight = 200 + (P_Random() & 31); tempSec = sectors; tempLight = LightningLightLevels; foundSec = false; for(i = 0; i < numsectors; i++, tempSec++) { if(tempSec->ceilingpic == skyflatnum || tempSec->special == LIGHTNING_SPECIAL || tempSec->special == LIGHTNING_SPECIAL2) { *tempLight = tempSec->lightlevel; if(tempSec->special == LIGHTNING_SPECIAL) { tempSec->lightlevel += 64; if(tempSec->lightlevel > flashLight) { tempSec->lightlevel = flashLight; } } else if(tempSec->special == LIGHTNING_SPECIAL2) { tempSec->lightlevel += 32; if(tempSec->lightlevel > flashLight) { tempSec->lightlevel = flashLight; } } else { tempSec->lightlevel = flashLight; } if(tempSec->lightlevel < *tempLight) { tempSec->lightlevel = *tempLight; } tempLight++; foundSec = true; } } if(foundSec) { mobj_t *plrmo = players[displayplayer].plr->mo; mobj_t *crashorigin = NULL; // Set the alternate (lightning) sky. Rend_SkyParams(0, DD_DISABLE, 0); Rend_SkyParams(1, DD_ENABLE, 0); // If 3D sounds are active, position the clap somewhere above // the player. if(cfg.snd_3D && plrmo) { // SpawnMobj calls P_Random, and we don't want that the // random number generator gets out of sync. //P_SaveRandom(); crashorigin = P_SpawnMobj(plrmo->x + (16 * (M_Random() - 127) << FRACBITS), plrmo->y + (16 * (M_Random() - 127) << FRACBITS), plrmo->z + (4000 << FRACBITS), MT_CAMERA); //P_RestoreRandom(); crashorigin->tics = 5 * 35; // Five seconds will do. } // Make it loud! S_StartSound(SFX_THUNDER_CRASH | DDSF_NO_ATTENUATION, crashorigin); } // Calculate the next lighting flash if(!NextLightningFlash) { if(P_Random() < 50) { // Immediate Quick flash NextLightningFlash = (P_Random() & 15) + 16; } else { if(P_Random() < 128 && !(leveltime & 32)) { NextLightningFlash = ((P_Random() & 7) + 2) * 35; } else { NextLightningFlash = ((P_Random() & 15) + 5) * 35; } } } }
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()); }
int EV_Teleport(Line* line, int side, mobj_t* mo, dd_bool spawnFog) { mobj_t* dest; // Clients cannot teleport on their own. if(IS_CLIENT) return 0; if(mo->flags2 & MF2_NOTELEPORT) return 0; // Don't teleport if hit back of line, so you can get out of teleporter. if(side == 1) return 0; if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL) { // A suitable destination has been found. coord_t oldPos[3], aboveFloor; angle_t oldAngle; mobj_t* fog; uint an; memcpy(oldPos, mo->origin, sizeof(mo->origin)); oldAngle = mo->angle; aboveFloor = mo->origin[VZ] - mo->floorZ; if(!P_TeleportMove(mo, dest->origin[VX], dest->origin[VY], false)) return 0; mo->origin[VZ] = mo->floorZ; if(spawnFog) { // Spawn teleport fog at source and destination. if((fog = P_SpawnMobj(MT_TFOG, oldPos, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); an = dest->angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobjXYZ(MT_TFOG, dest->origin[VX] + 20 * FIX2FLT(finecosine[an]), dest->origin[VY] + 20 * FIX2FLT(finesine[an]), mo->origin[VZ], dest->angle + ANG180, 0))) { // Emit sound, where? S_StartSound(SFX_TELEPT, fog); } } mo->angle = dest->angle; if(mo->flags2 & MF2_FLOORCLIP) { mo->floorClip = 0; if(FEQUAL(mo->origin[VZ], P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT))) { terraintype_t const *tt = P_MobjFloorTerrain(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; // $voodoodolls Must be the real player. if(mo->player && mo->player->plr->mo == mo) { mo->reactionTime = 18; // Don't move for a bit. if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0) { mo->origin[VZ] = mo->floorZ + aboveFloor; if(mo->origin[VZ] + mo->height > mo->ceilingZ) { mo->origin[VZ] = mo->ceilingZ - mo->height; } } else { //mo->dPlayer->clLookDir = 0; /* $unifiedangles */ mo->dPlayer->lookDir = 0; } mo->player->viewHeight = (coord_t) cfg.common.plrViewHeight; mo->player->viewHeightDelta = 0; mo->player->viewZ = mo->origin[VZ] + mo->player->viewHeight; mo->player->viewOffset[VX] = mo->player->viewOffset[VY] = mo->player->viewOffset[VZ] = 0; mo->player->bob = 0; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXORIGIN | DDPF_FIXMOM; } return 1; }
//=========================================================================== // 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; }
void A_FireLaser(player_t *player, pspdef_t *psp) { angle_t angleoffs; angle_t spread; mobj_t *mobj; int lasercount; int i; fixed_t slope; fixed_t x; fixed_t y; fixed_t z; byte type; laser_t *laser[3]; laserthinker_t *laserthinker[3]; //fixed_t laserfrac; mobj = player->mo; lasercount = 0; spread = 0; angleoffs = 0; // the original used a lookup table with the values "0, 1, 1, 2, 1, 2, 2, 3" // this is an alternative to using that table type = (byte)(((player->artifacts & 3) != 0) + ((player->artifacts & 3) == 3) + ((player->artifacts & 4) != 0)); // setup laser type switch(type) { case 1: // Rapid fire / single shot psp->tics = 5; lasercount = 1; angleoffs = mobj->angle; break; case 2: // Rapid fire / double shot psp->tics = 4; lasercount = 2; angleoffs = mobj->angle + 0xFF4A0000; spread = 0x16C0000; break; case 3: // Spread shot psp->tics = 4; lasercount = 3; spread = 0x2220000 + (0x2220000 * (player->refire & 3)); angleoffs = mobj->angle - spread; break; default: // Normal shot lasercount = 1; angleoffs = mobj->angle; break; } if(lasercount <= 0) return; laserCells = lasercount; // setup laser beams for(i = 0; i < lasercount; i++) { int hitdice = 0; int damage = 0; slope = P_AimLineAttack(mobj, angleoffs, LASERAIMHEIGHT, LASERRANGE); player->ammo[weaponinfo[player->readyweapon].ammo]--; // // [kex] 1/2/12 the old code is just plain bad. the original behavior was // to simply call P_AimLineAttack and use the intercept fraction to // determine where the tail end of the laser will land. this is // optimal for consoles but leads to a lot of issues when working with // plane hit detection and auto aiming. P_LineAttack will be called normally // and instead of spawning puffs or blood, the xyz values are stored so the // tail end of the laser can be setup properly here // // (unused) adjust aim fraction which will be used to determine // the endpoint of the laser /*if(aimfrac) laserfrac = (aimfrac << (FRACBITS - 4)) - (4 << FRACBITS); else laserfrac = 0x800;*/ hitdice = (P_Random() & 7); damage = (((hitdice << 2) + hitdice) << 1) + 10; P_LineAttack(mobj, angleoffs, LASERRANGE, slope, damage); // setup laser laser[i] = Z_Malloc(sizeof(*laser[i]), PU_LEVSPEC, 0); // setup laser head point laser[i]->x1 = mobj->x + FixedMul(LASERDISTANCE, dcos(mobj->angle)); laser[i]->y1 = mobj->y + FixedMul(LASERDISTANCE, dsin(mobj->angle)); laser[i]->z1 = (mobj->z + LASERAIMHEIGHT); // setup laser tail point /* laser[i]->x2 = (FixedMul(dcos(angleoffs), laserfrac) + mobj->x); laser[i]->y2 = (FixedMul(dsin(angleoffs), laserfrac) + mobj->y); laser[i]->z2 = (FixedMul(slope, laserfrac) + (mobj->z + LASERAIMHEIGHT)); */ laser[i]->x2 = laserhit_x; laser[i]->y2 = laserhit_y; laser[i]->z2 = laserhit_z; // setup movement slope laser[i]->slopex = (dcos(angleoffs) << 5); laser[i]->slopey = (dsin(angleoffs) << 5); laser[i]->slopez = slope ? (slope << 5) : 0; // setup distance info x = (laser[i]->x1 - laser[i]->x2) >> FRACBITS; y = (laser[i]->y1 - laser[i]->y2) >> FRACBITS; z = (laser[i]->z1 - laser[i]->z2) >> FRACBITS; laser[i]->dist = 0; laser[i]->distmax = (int)sqrt((x * x) + (y * y) + (z * z)); laser[i]->next = NULL; laser[i]->marker = NULL; laser[i]->angle = angleoffs; x = laser[i]->x2; y = laser[i]->y2; z = laser[i]->z2; P_LaserCrossBSP(numnodes - 1, laser[i]); laserthinker[i] = Z_Malloc(sizeof(*laserthinker[i]), PU_LEVSPEC, 0); P_AddThinker(&laserthinker[i]->thinker); laserthinker[i]->thinker.function.acp1 = (actionf_p1)T_LaserThinker; laserthinker[i]->dest = P_SpawnMobj(x, y, z, MT_PROJ_LASER); laserthinker[i]->laser = laser[i]; /*if(linetarget) { int hitdice = 0; int damage = 0; hitdice = (P_Random() & 7); damage = (((hitdice << 2) + hitdice) << 1) + 10; P_DamageMobj(linetarget, mobj, mobj, damage); } else angleoffs += spread;*/ if(!linetarget) angleoffs += spread; } S_StartSound(player->mo, sfx_laser); P_SetMobjState(player->mo, S_007); P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate); }
static void P_LaserCrossBSP(int bspnum, laser_t* laser) { node_t* node; int ds1; int ds2; int s1; int s2; int dist; int frac; mobj_t* marker; laser_t* childlaser = NULL; fixed_t x; fixed_t y; fixed_t z; while(!(bspnum & NF_SUBSECTOR)) { node = &nodes[bspnum]; // traverse nodes ds1 = P_LaserPointOnSide(laser->x1, laser->y1, node); ds2 = P_LaserPointOnSide(laser->x2, laser->y2, node); s1 = (ds1 < 0); s2 = (ds2 < 0); // did the two laser points cross the node? if(s1 == s2) { bspnum = node->children[s1]; continue; } // allocate a new child laser childlaser = (laser_t*)Z_Calloc(sizeof(laser_t), PU_LEVSPEC, NULL); childlaser->x1 = laser->x1; childlaser->y1 = laser->y1; childlaser->z1 = laser->z1; childlaser->x2 = laser->x2; childlaser->y2 = laser->y2; childlaser->z2 = laser->z2; childlaser->slopex = laser->slopex; childlaser->slopey = laser->slopey; childlaser->slopez = laser->slopez; childlaser->distmax = laser->distmax; childlaser->next = laser->next; childlaser->angle = laser->angle; // get the intercepting point of the laser and node frac = FixedDiv(ds1, ds1 - ds2); x = (F2INT(laser->x2 - laser->x1) * frac) + laser->x1; y = (F2INT(laser->y2 - laser->y1) * frac) + laser->y1; z = (F2INT(laser->z2 - laser->z1) * frac) + laser->z1; // update endpoint of current laser to intercept point laser->x2 = x; laser->y2 = y; laser->z2 = z; // childlaser begins at intercept point childlaser->x1 = x; childlaser->y1 = y; childlaser->z1 = z; // update distmax dist = F2INT(laser->distmax * frac); childlaser->distmax = laser->distmax - dist; laser->distmax = dist; // point to child laser laser->next = childlaser; // traverse child nodes P_LaserCrossBSP(node->children[s1], laser); laser = childlaser; bspnum = node->children[s2]; } // subsector was hit, spawn a marker between the two laser points x = (laser->x1 + laser->x2) >> 1; y = (laser->y1 + laser->y2) >> 1; z = (laser->z1 + laser->z2) >> 1; marker = P_SpawnMobj(x, y, z, MT_LASERMARKER); // have marker point to which laser it belongs to marker->extradata = (laser_t*)laser; laser->marker = marker; }
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle, boolean useFog) { fixed_t oldx; fixed_t oldy; fixed_t oldz; fixed_t aboveFloor; fixed_t fogDelta; player_t *player; unsigned an; mobj_t *fog; oldx = thing->x; oldy = thing->y; oldz = thing->z; aboveFloor = thing->z - thing->floorz; if(!P_TeleportMove(thing, x, y)) { return false; } if(thing->player) { player = thing->player; player->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; if(player->powers[pw_flight] && aboveFloor) { thing->z = thing->floorz + aboveFloor; if(thing->z + thing->height > thing->ceilingz) { thing->z = thing->ceilingz - thing->height; } player->plr->viewz = thing->z + player->plr->viewheight; } else { thing->z = thing->floorz; player->plr->viewz = thing->z + player->plr->viewheight; if(useFog) { player->plr->lookdir = 0; } } } else if(thing->flags & MF_MISSILE) { thing->z = thing->floorz + aboveFloor; if(thing->z + thing->height > thing->ceilingz) { thing->z = thing->ceilingz - thing->height; } } else { thing->z = thing->floorz; } // Spawn teleport fog at source and destination if(useFog) { fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); S_StartSound(SFX_TELEPORT, fog); an = angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], thing->z + fogDelta, MT_TFOG); S_StartSound(SFX_TELEPORT, fog); if(thing->player && !thing->player->powers[pw_speed]) { // Freeze player for about .5 sec thing->reactiontime = 18; } thing->angle = angle; } if(thing->flags2 & MF2_FLOORCLIP) { if(thing->z == thing->subsector->sector->floorheight && P_GetThingFloorType(thing) > FLOOR_SOLID) { thing->floorclip = 10 * FRACUNIT; } else { thing->floorclip = 0; } } if(thing->flags & MF_MISSILE) { angle >>= ANGLETOFINESHIFT; thing->momx = FixedMul(thing->info->speed, finecosine[angle]); thing->momy = FixedMul(thing->info->speed, finesine[angle]); }
// // A_Tracer // // (Accidentally?) randomized homing missile maintenance. // ioanch 20151230: fixed to be portal-aware // void A_Tracer(actionargs_t *actionargs) { angle_t exact; fixed_t dist; fixed_t slope; Mobj *actor = actionargs->actor; Mobj *dest; Mobj *th; // killough 1/18/98: this is why some missiles do not have smoke // and some do. Also, internal demos start at random gametics, // thus the bug in which revenants cause internal demos to go out // of sync. // // killough 3/6/98: fix revenant internal demo bug by subtracting // levelstarttic from gametic. // // killough 9/29/98: use new "basetic" so that demos stay in sync // during pauses and menu activations, while retaining old demo // sync. // // leveltime would have been better to use to start with in Doom, // but since old demos were recorded using gametic, we must stick // with it, and improvise around it (using leveltime causes desync // across levels). if((gametic-basetic) & 3) return; // spawn a puff of smoke behind the rocket P_SpawnPuff(actor->x, actor->y, actor->z, 0, 3, false); th = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z, E_SafeThingType(MT_SMOKE)); th->momz = FRACUNIT; th->tics -= P_Random(pr_tracer) & 3; if(th->tics < 1) th->tics = 1; // adjust direction dest = actor->tracer; if(!dest || dest->health <= 0) return; fixed_t dx = getThingX(actor, dest); fixed_t dy = getThingY(actor, dest); fixed_t dz = getThingZ(actor, dest); // change angle exact = P_PointToAngle(actor->x, actor->y, dx, dy); if(exact != actor->angle) { if(exact - actor->angle > 0x80000000) { actor->angle -= TRACEANGLE; if(exact - actor->angle < 0x80000000) actor->angle = exact; } else { actor->angle += TRACEANGLE; if(exact - actor->angle > 0x80000000) actor->angle = exact; } } exact = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul(actor->info->speed, finecosine[exact]); actor->momy = FixedMul(actor->info->speed, finesine[exact]); // change slope dist = P_AproxDistance(dx - actor->x, dy - actor->y); dist = dist / actor->info->speed; if(dist < 1) dist = 1; slope = (dz + 40*FRACUNIT - actor->z) / dist; if(slope < actor->momz) actor->momz -= FRACUNIT/8; else actor->momz += FRACUNIT/8; }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; fixed_t oldx; fixed_t oldy; fixed_t oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < P_CountSectors(); i++) { if (P_GetSector(i)->tag == tag ) { for (thinker = P_FirstThinker(); thinker; thinker = P_NextThinker(thinker)) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (P_UngetSector(sector) != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; if (!B_CheckCompat(COMPAT_TELEPORTZ)) { thing->z = thing->floorz; //fixme: not needed? } if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? S_StartSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } } return 0; }
int EV_Teleport( line_t *line,mobj_t *thing ) { int i; int tag; boolean flag; mobj_t *m,*fog; unsigned int an; sector_t *sector; fixed_t oldx, oldy, oldz; int side; side = !P_PointOnLineSide (thing->x, thing->y, line); if(thing->flags & MF_MISSILE) return 0; /* don't teleport missiles */ if(side == 1) /* don't teleport if hit back of line, */ return 0; /* so you can get out of teleporter */ tag = line->tag; for(i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { for(m = mobjhead.next; m != &mobjhead; m = m->next) { // CALICO: skip removed mobjs if(m->latecall == P_RemoveMobjDeferred) continue; if(m->type != MT_TELEPORTMAN) continue; // not a teleportman sector = m->subsector->sector; if(sector-sectors != i ) continue; // wrong sector oldx = thing->x; oldy = thing->y; oldz = thing->z; thing->flags |= MF_TELEPORT; P_Telefrag(thing, m->x, m->y); flag = P_TryMove (thing, m->x, m->y); thing->flags &= ~MF_TELEPORT; if(!flag) return 0; /* move is blocked */ thing->z = thing->floorz; /* spawn teleport fog at source and destination */ fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound(fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an], thing->z, MT_TFOG); S_StartSound(fog, sfx_telept); if(thing->player) thing->reactiontime = 18; /* don't move for a bit */ thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } } return 0; }
// // ACS_funcSetThingPosition // static void ACS_funcSetThingPosition(ACS_FUNCARG) { int32_t tid = args[0]; fixed_t x = args[1]; fixed_t y = args[2]; fixed_t z = args[3]; bool fog = args[4] ? true : false; Mobj *mo, *fogmo; if((mo = P_FindMobjFromTID(tid, NULL, thread->trigger))) { fixed_t oldx = mo->x; fixed_t oldy = mo->y; fixed_t oldz = mo->z; mo->z = z; if(P_CheckPositionExt(mo, x, y)) { subsector_t *newsubsec; newsubsec = R_PointInSubsector(x, y); // Set new position. P_UnsetThingPosition(mo); mo->floorz = mo->dropoffz = newsubsec->sector->floorheight; mo->ceilingz = newsubsec->sector->ceilingheight; mo->passfloorz = mo->secfloorz = mo->floorz; mo->passceilz = mo->secceilz = mo->ceilingz; mo->x = x; mo->y = y; mo->backupPosition(); P_SetThingPosition(mo); // Handle fog. if(fog) { // Teleport fog at source... fogmo = P_SpawnMobj(oldx, oldy, oldz + GameModeInfo->teleFogHeight, E_SafeThingName(GameModeInfo->teleFogType)); S_StartSound(fogmo, GameModeInfo->teleSound); // ... and destination. fogmo = P_SpawnMobj(x, y, z + GameModeInfo->teleFogHeight, E_SafeThingName(GameModeInfo->teleFogType)); S_StartSound(fogmo, GameModeInfo->teleSound); } *retn++ = 1; } else { mo->z = oldz; *retn++ = 0; } } else *retn++ = 0; }
void P_KillMobj(mobj_t* source, mobj_t* target) { mobjtype_t item; mobj_t* mo; target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); if(target->type != MT_SKULL && (!(target->flags & MF_GRAVITY))) { target->flags |= MF_GRAVITY; } target->flags |= MF_CORPSE|MF_DROPOFF; target->height >>= 2; if(source && source->player) { // count for intermission if(target->flags & MF_COUNTKILL) { source->player->killcount++; } if(target->player) { source->player->frags[target->player-players]++; } } else if(!netgame && (target->flags & MF_COUNTKILL)) { // count all monster deaths, // even those caused by other monsters players[0].killcount++; } if(target->player) { // count environment kills against you if(!source) { target->player->frags[target->player-players]++; } target->flags &= ~MF_SOLID; target->player->playerstate = PST_DEAD; P_DropWeapon(target->player); deathmocktics = gametic; if(target->player == &players[consoleplayer] && automapactive) { // don't die in auto map, // switch view prior to dying AM_Stop(); } // 20120123 villsa - obituaries! if(netgame) { P_Obituary(source, target); } } if(target->health < -target->info->spawnhealth && target->info->xdeathstate) { P_SetMobjState(target, target->info->xdeathstate); } else { P_SetMobjState(target, target->info->deathstate); } target->tics -= P_Random(pr_killtics)&3; if(target->tics < 1) { target->tics = 1; } // Drop stuff. // This determines the kind of object spawned // during the death frame of a thing. switch(target->type) { case MT_POSSESSED1: item = MT_AMMO_CLIP; break; case MT_POSSESSED2: item = MT_WEAP_SHOTGUN; break; default: return; } mo = P_SpawnMobj(target->x,target->y,ONFLOORZ, item); mo->flags |= MF_DROPPED; // special versions of items }
void P_SpawnMapThing (mapthing_t *mthing) { int i, bit; mobj_t *mobj; fixed_t x,y,z; /* count deathmatch start positions */ if (mthing->type == 11) { if (deathmatch_p < &deathmatchstarts[10]) D_memcpy (deathmatch_p, mthing, sizeof(*mthing)); deathmatch_p++; return; } /* check for players specially */ #if 0 if (mthing->type > 4) return; /*DEBUG */ #endif if (mthing->type <= 4) { /* save spots for respawning in network games */ if (mthing->type <= MAXPLAYERS) { playerstarts[mthing->type-1] = *mthing; if (netgame != gt_deathmatch) P_SpawnPlayer (mthing); } return; } /* check for apropriate skill level */ if ( (netgame != gt_deathmatch) && (mthing->options & 16) ) return; if (gameskill == sk_baby) bit = 1; else if (gameskill == sk_nightmare) bit = 4; else bit = 1<<(gameskill-1); if (!(mthing->options & bit) ) return; #ifdef MARS /* hack player corpses into something else, because player graphics */ /* aren't included */ if (mthing->type == 10 || mthing->type == 12) /* player corpse */ mthing->type = 18; /* possessed human corpse */ #endif /* find which type to spawn */ for (i=0 ; i< NUMMOBJTYPES ; i++) if (mthing->type == mobjinfo[i].doomednum) break; if (i==NUMMOBJTYPES) I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",mthing->type , mthing->x, mthing->y); /* don't spawn keycards and players in deathmatch */ if (netgame == gt_deathmatch && mobjinfo[i].flags & (MF_NOTDMATCH|MF_COUNTKILL) ) return; /* spawn it */ x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; if (mobjinfo[i].flags & MF_SPAWNCEILING) z = ONCEILINGZ; else z = ONFLOORZ; mobj = P_SpawnMobj (x,y,z, i); if (mobj->tics > 0) mobj->tics = 1 + (P_Random () % mobj->tics); if (mobj->flags & MF_COUNTKILL) totalkills++; if (mobj->flags & MF_COUNTITEM) totalitems++; mobj->angle = ANG45 * (mthing->angle/45); if (mthing->options & MTF_AMBUSH) mobj->flags |= MF_AMBUSH; mobj->spawnx = mthing->x; mobj->spawny = mthing->y; mobj->spawntype = mthing->type; mobj->spawnangle = mthing->angle; }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; fixed_t oldx; fixed_t oldy; fixed_t oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (sector-sectors != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; // fraggle: this was changed in final doom, // problem between normal doom2 1.9 and final doom // // Note that although chex.exe is based on Final Doom, // it does not have this quirk. if (gameversion < exe_final || gameversion == exe_chex) thing->z = thing->floorz; if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? S_StartSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; int oldx; int oldy; int oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (sector-sectors != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; thing->z = thing->floorz; //fixme: not needed? if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); I_Sound::getInstance()->startSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? I_Sound::getInstance()->startSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } }
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()); }
mobj_t *P_SpawnTeleFog(int x, int y) { subsector_t *ss = R_PointInSubsector(x, y); return P_SpawnMobj(x, y, ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); }