p_mobj.c (11614B)
1 /* P_mobj.c */ 2 3 #include "doomdef.h" 4 #include "p_local.h" 5 #include "sounds.h" 6 7 void G_PlayerReborn (int player); 8 9 extern mobj_t *cameratarget; // 800A5D70 10 extern mapthing_t *spawnlist; // 800A5D74 11 extern int spawncount; // 800A5D78 12 13 /* 14 =============== 15 = 16 = P_SpawnMobj 17 = 18 =============== 19 */ 20 21 mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // 80018a20 22 { 23 mobj_t *mobj; 24 state_t *st; 25 mobjinfo_t *info; 26 27 mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); 28 29 D_memset (mobj, 0, sizeof (*mobj)); 30 info = &mobjinfo[type]; 31 32 mobj->type = type; 33 mobj->info = info; 34 mobj->x = x; 35 mobj->y = y; 36 mobj->radius = info->radius; 37 mobj->height = info->height; 38 mobj->flags = info->flags; 39 mobj->health = info->spawnhealth; 40 mobj->reactiontime = info->reactiontime; 41 mobj->alpha = info->alpha; 42 43 /* do not set the state with P_SetMobjState, because action routines can't */ 44 /* be called yet */ 45 st = &states[info->spawnstate]; 46 47 mobj->state = st; 48 mobj->tics = st->tics; 49 mobj->sprite = st->sprite; 50 mobj->frame = st->frame; 51 52 /* set subsector and/or block links */ 53 P_SetThingPosition (mobj); 54 55 mobj->floorz = mobj->subsector->sector->floorheight; 56 mobj->ceilingz = mobj->subsector->sector->ceilingheight; 57 if (z == ONFLOORZ) 58 mobj->z = mobj->floorz; 59 else if (z == ONCEILINGZ) 60 mobj->z = mobj->ceilingz - mobj->info->height; 61 else 62 mobj->z = z; 63 64 /* */ 65 /* link into the mobj list */ 66 /* */ 67 mobjhead.prev->next = mobj; 68 mobj->next = &mobjhead; 69 mobj->prev = mobjhead.prev; 70 mobjhead.prev = mobj; 71 72 if((mobj->flags & MF_COUNTKILL) != 0) 73 totalkills++; 74 75 if((mobj->flags & MF_COUNTITEM) != 0) 76 totalitems++; 77 78 return mobj; 79 } 80 81 /* 82 ================= 83 = 84 = P_SpawnMapThing 85 = 86 = The fields of the mapthing should already be in host byte order 87 ================== 88 */ 89 90 extern mobj_t* checkthing; 91 extern int testflags; 92 extern fixed_t testradius; 93 extern fixed_t testx; 94 extern fixed_t testy; 95 96 extern boolean PB_CheckPosition(void); 97 98 mobj_t *P_SpawnMapThing (mapthing_t *mthing) // 80018C24 99 { 100 int i, bit; 101 mobj_t *mobj; 102 fixed_t x,y,z; 103 mobj_t tmp_mobj; 104 105 if (mthing->type == MAXPLAYERS) 106 { 107 playerstarts[0] = *mthing; 108 return NULL; 109 } 110 111 #if ENABLE_NIGHTMARE == 1 112 if (gameskill == sk_baby) 113 bit = 1; 114 else if (gameskill == sk_nightmare) 115 bit = 4; 116 else 117 bit = 1<<(gameskill-1); 118 #else 119 if (gameskill == sk_baby || gameskill == sk_easy) 120 bit = 1; 121 else if (gameskill == sk_medium) 122 bit = 2; 123 else if (gameskill == sk_hard) 124 bit = 4; 125 126 #endif // ENABLE_NIGHTMARE 127 128 if (!(mthing->options & bit) ) 129 return NULL; 130 131 /* find which type to spawn */ 132 for (i = 0; i < NUMMOBJTYPES; i++) 133 { 134 if (mthing->type == mobjinfo[i].doomednum) 135 break; 136 } 137 138 if (i==NUMMOBJTYPES) 139 { 140 I_Error ("P_SpawnMapThing: Unknown type %d at (%d, %d)",mthing->type , mthing->x, mthing->y); 141 } 142 143 // 144 // [d64] check if spawn is valid 145 // 146 if((mobjinfo[i].flags & MF_SOLID) != 0) 147 { 148 checkthing = &tmp_mobj; 149 testflags = mobjinfo[i].flags; 150 testradius = mobjinfo[i].radius; 151 testx = mthing->x << FRACBITS; 152 testy = mthing->y << FRACBITS; 153 154 if(!PB_CheckPosition()) 155 return NULL; 156 } 157 158 // [d64]: queue mobj for spawning later 159 if(mthing->options & MTF_SPAWN) 160 { 161 mthing->options &= ~MTF_SPAWN; 162 D_memcpy(&spawnlist[spawncount], mthing, sizeof(mapthing_t)); 163 spawncount += 1; 164 165 return NULL; 166 } 167 168 /* spawn it */ 169 x = mthing->x << FRACBITS; 170 y = mthing->y << FRACBITS; 171 if (mobjinfo[i].flags & MF_SPAWNCEILING) 172 z = ONCEILINGZ; 173 else 174 z = ONFLOORZ; 175 176 mobj = P_SpawnMobj (x,y,z, i); 177 mobj->z += (mthing->z << FRACBITS); 178 mobj->angle = ANG45 * (mthing->angle/45); 179 mobj->tid = mthing->tid; 180 181 if (mobj->tics > 0) 182 mobj->tics = 1 + (P_Random () % mobj->tics); 183 184 if (mthing->options & MTF_AMBUSH) 185 mobj->flags |= MF_AMBUSH; 186 187 if (mthing->options & MTF_ONTOUCH) 188 mobj->flags |= MF_TRIGTOUCH; 189 190 if (mthing->options & MTF_ONDEATH) 191 mobj->flags |= MF_TRIGDEATH; 192 193 if (mthing->options & MTF_SECRET) 194 { 195 mobj->flags |= MF_COUNTSECRET; 196 totalsecret++; 197 } 198 199 if (mthing->options & MTF_NOINFIGHTING) 200 mobj->flags |= MF_NOINFIGHTING; 201 202 return mobj; 203 } 204 205 /* 206 ============ 207 = 208 = P_SpawnPlayer 209 = 210 = Called when a player is spawned on the level 211 = Most of the player structure stays unchanged between levels 212 ============ 213 */ 214 215 void P_SpawnPlayer(/*mapthing_t *mthing*/) // 80018F94 216 { 217 player_t *p; 218 fixed_t x,y,z; 219 mobj_t *mobj; 220 int i; 221 int levelnum; 222 int skill; 223 224 //if (!playeringame[mthing->type-1]) 225 //return; /* not playing */ 226 227 p = &players[0]; 228 229 if (p->playerstate == PST_REBORN) 230 G_PlayerReborn(0); 231 else 232 { 233 p->killcount = 0; 234 p->secretcount = 0; 235 p->itemcount = 0; 236 } 237 238 x = playerstarts[0].x << FRACBITS; 239 y = playerstarts[0].y << FRACBITS; 240 241 z = ONFLOORZ; 242 mobj = P_SpawnMobj (x,y,z, MT_PLAYER); 243 244 mobj->angle = ANG45 * (playerstarts[0].angle/45); 245 mobj->player = p; 246 mobj->health = p->health; 247 mobj->tid = playerstarts[0].tid; 248 mobj->z = mobj->z + (playerstarts[0].z << FRACBITS); 249 p->mo = mobj; 250 p->playerstate = PST_LIVE; 251 p->refire = 0; 252 p->message = NULL; 253 p->messagetic = 0; 254 p->damagecount = 0; 255 p->bonuscount = 0; 256 p->extralight = 0; 257 p->bfgcount = 0; 258 p->viewheight = VIEWHEIGHT; 259 p->automapscale = 850; 260 p->viewz = mobj->z + VIEWHEIGHT; 261 cameratarget = p->mo; 262 263 P_SetupPsprites (0); /* setup gun psprite */ 264 265 if (doPassword != 0) 266 { 267 M_DecodePassword(Passwordbuff, &levelnum, &skill, p); 268 doPassword = false; 269 } 270 271 ST_InitEveryLevel(); 272 ST_UpdateFlash(); // ST_doPaletteStuff(); 273 } 274 275 /* 276 =============== 277 = 278 = P_RemoveMobj 279 = 280 =============== 281 */ 282 283 void P_RemoveMobj (mobj_t *mobj) // 80019130 284 { 285 /* unlink from sector and block lists */ 286 P_UnsetThingPosition (mobj); 287 288 /* unlink from mobj list */ 289 mobj->next->prev = mobj->prev; 290 mobj->prev->next = mobj->next; 291 Z_Free (mobj); 292 } 293 294 /* 295 ================ 296 = 297 = P_SetMobjState 298 = 299 = Returns true if the mobj is still present 300 ================ 301 */ 302 303 boolean P_SetMobjState (mobj_t *mobj, statenum_t state) // 80019184 304 { 305 state_t *st; 306 307 if (state == S_000) 308 { 309 mobj->state = NULL; 310 P_RemoveMobj (mobj); 311 return false; 312 } 313 314 st = &states[state]; 315 316 mobj->state = st; 317 mobj->tics = st->tics; 318 mobj->sprite = st->sprite; 319 mobj->frame = st->frame; 320 321 if (st->action) /* call action functions when the state is set */ 322 st->action (mobj); 323 324 mobj->latecall = NULL; /* make sure it doesn't come back to life... */ 325 326 return true; 327 } 328 329 /*============================================================================= */ 330 331 /* 332 =============================================================================== 333 334 GAME SPAWN FUNCTIONS 335 336 =============================================================================== 337 */ 338 339 /* 340 ================ 341 = 342 = P_SpawnPuff 343 = 344 ================ 345 */ 346 347 extern fixed_t attackrange; // 800A5704 348 349 void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z) // 80019218 350 { 351 mobj_t *th; 352 int rnd1, rnd2; 353 354 rnd1 = P_Random(); 355 rnd2 = P_Random(); 356 357 z += ((rnd2-rnd1)<<10); 358 th = P_SpawnMobj (x,y,z, MT_SMOKE_SMALL); 359 th->momz = FRACUNIT; 360 th->tics -= P_Random()&1; 361 if (th->tics < 1) 362 th->tics = 1; 363 364 /* don't make punches spark on the wall */ 365 if (attackrange == MELEERANGE) 366 P_SetMobjState (th, S_490); 367 } 368 369 370 /* 371 ================ 372 = 373 = P_SpawnBlood 374 = 375 ================ 376 */ 377 378 void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) // 800192B8 379 { 380 mobj_t *th; 381 int i; 382 383 for(i = 0; i < 3; i++) 384 { 385 x += ((P_Random()-P_Random())<<12); 386 y += ((P_Random()-P_Random())<<12); 387 z += ((P_Random()-P_Random())<<11); 388 th = P_SpawnMobj (x,y,z, MT_BLOOD); 389 th->momz = FRACUNIT*2; 390 th->tics -= P_Random()&1; 391 if (th->tics<1) 392 th->tics = 1; 393 if (damage <= 12 && damage >= 9) 394 P_SetMobjState (th, S_495); 395 else if (damage < 9) 396 P_SetMobjState (th, S_496); 397 } 398 } 399 400 /* 401 ================ 402 = 403 = P_SpawnMissile 404 = 405 ================ 406 */ 407 408 mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, fixed_t xoffs, fixed_t yoffs, fixed_t heightoffs, mobjtype_t type) // 80019410 409 { 410 mobj_t *th; 411 angle_t an; 412 int dist; 413 int speed; 414 fixed_t x, y, z; 415 int rnd1, rnd2; 416 417 x = source->x + xoffs; 418 y = source->y + yoffs; 419 z = source->z + heightoffs; 420 421 th = P_SpawnMobj (x, y, z, type); 422 if (th->info->seesound) 423 S_StartSound (source, th->info->seesound); 424 th->target = source; /* where it came from */ 425 426 if ((type == MT_PROJ_BABY) || (type == MT_PROJ_DART)) /* no aim projectile */ 427 an = source->angle; 428 else if (dest) 429 an = R_PointToAngle2(x, y, dest->x, dest->y); 430 431 if (dest && (dest->flags & MF_SHADOW)) 432 { 433 rnd1 = P_Random(); 434 rnd2 = P_Random(); 435 an += ((rnd2 - rnd1) << 20); 436 } 437 438 th->angle = an; 439 an >>= ANGLETOFINESHIFT; 440 speed = th->info->speed; 441 th->momx = speed * finecosine[an]; 442 th->momy = speed * finesine[an]; 443 444 if (dest) 445 { 446 dist = P_AproxDistance (dest->x - x, dest->y - y); 447 dist = dist / (th->info->speed << FRACBITS); 448 if (dist < 1) 449 dist = 1; 450 th->momz = ((dest->z + (dest->height >> 1)) - z) / dist; 451 } 452 453 if (!P_CheckPosition (th, th->x, th->y)) 454 P_ExplodeMissile (th); 455 456 return th; 457 } 458 459 460 /* 461 ================ 462 = 463 = P_SpawnPlayerMissile 464 = 465 = Tries to aim at a nearby monster 466 ================ 467 */ 468 extern line_t* shotline; // 800A56FC 469 extern fixed_t aimfrac; // 800A5720 470 471 void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type) // 80019668 472 { 473 mobj_t *th; 474 angle_t an; 475 fixed_t x,y,z, slope; 476 int speed; 477 fixed_t missileheight; 478 int offset; 479 480 // [d64] adjust offset and height based on missile 481 if(type == MT_PROJ_ROCKET) 482 { 483 missileheight = (42*FRACUNIT); 484 offset = 30; 485 } 486 else if(type == MT_PROJ_PLASMA) 487 { 488 missileheight = (32*FRACUNIT); 489 offset = 40; 490 } 491 else if(type == MT_PROJ_BFG) 492 { 493 missileheight = (32*FRACUNIT); 494 offset = 30; 495 } 496 else 497 { 498 missileheight = (32*FRACUNIT); 499 offset = 0; 500 } 501 502 /* */ 503 /* see which target is to be aimed at */ 504 /* */ 505 an = source->angle; 506 slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); 507 if (!linetarget) 508 { 509 an += 1<<26; 510 slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); 511 if (!linetarget) 512 { 513 an -= 2<<26; 514 slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); 515 } 516 if (!linetarget) 517 { 518 an = source->angle; 519 slope = 0; 520 } 521 } 522 523 x = source->x; 524 y = source->y; 525 z = source->z; 526 527 th = P_SpawnMobj (x,y,z+missileheight, type); 528 if (th->info->seesound) 529 S_StartSound (source, th->info->seesound); 530 th->target = source; 531 th->angle = an; 532 533 speed = th->info->speed; 534 535 th->momx = speed * finecosine[an>>ANGLETOFINESHIFT]; 536 th->momy = speed * finesine[an>>ANGLETOFINESHIFT]; 537 th->momz = speed * slope; 538 539 x = source->x + (offset * finecosine[an>>ANGLETOFINESHIFT]); 540 y = source->y + (offset * finesine[an>>ANGLETOFINESHIFT]); 541 542 // [d64]: checking against very close lines? 543 if((shotline && aimfrac <= 0xC80) || !P_TryMove(th, x, y)) 544 P_ExplodeMissile(th); 545 } 546 547 548 /* 549 =================== 550 = 551 = P_ExplodeMissile 552 = 553 =================== 554 */ 555 556 void P_ExplodeMissile (mobj_t *mo) // 800198B8 557 { 558 if(!P_SetMobjState(mo, mobjinfo[mo->type].deathstate)) 559 return; 560 561 mo->momx = mo->momy = mo->momz = 0; 562 563 mo->tics -= P_Random()&1; 564 if (mo->tics < 1) 565 mo->tics = 1; 566 567 mo->flags &= ~MF_MISSILE; 568 if (mo->info->deathsound) 569 { 570 S_StopSound(mo, 0); 571 S_StartSound(mo, mo->info->deathsound); 572 } 573 }