//================================================================== // // P_SpawnLightFlash // // After the map has been loaded, scan each sector for specials that spawn thinkers // //================================================================== void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync) { strobe_t *flash; flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0); P_AddThinker(&flash->thinker); flash->sector = sector; flash->darktime = fastOrSlow; flash->brighttime = STROBEBRIGHT; flash->thinker.function = T_StrobeFlash; flash->maxlight = sector->lightlevel; flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); if (flash->minlight == flash->maxlight) flash->minlight = 0; sector->special = 0; // nothing special about it during gameplay if (!inSync) flash->count = (P_Random() & 7) + 1; else flash->count = 1; }
// // A_SPosAttack // // Sergeant attack. // void A_SPosAttack(actionargs_t *actionargs) { Mobj *actor = actionargs->actor; int i, bangle, slope; if (!actor->target) return; S_StartSound(actor, sfx_shotgn); A_FaceTarget(actionargs); bangle = actor->angle; slope = P_AimLineAttack(actor, bangle, MISSILERANGE, 0); // killough 8/2/98 for(i = 0; i < 3; ++i) { // haleyjd 08/05/04: use new function int angle = bangle + (P_SubRandom(pr_sposattack) << 20); int damage = ((P_Random(pr_sposattack) % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } }
// // A_Punch // void A_Punch (AActor *mo) { angle_t angle; int damage; int slope; player_t *player = mo->player; damage = (P_Random (player->mo)%10+1)<<1; if (player->powers[pw_strength]) damage *= 10; angle = player->mo->angle; angle += P_RandomDiff(player->mo) << 18; // [SL] 2011-07-12 - Move players and sectors back to their positions when // this player hit the fire button clientside. Unlag::getInstance().reconcile(player->id); slope = P_AimLineAttack (player->mo, angle, MELEERANGE); P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); // [SL] 2011-07-12 - Restore players and sectors to their current position // according to the server. Unlag::getInstance().restore(player->id); // turn to face target if (linetarget) { A_FireSound (player, "player/male/fist"); //S_Sound (player->mo, CHAN_VOICE, "*fist", 1, ATTN_NORM); player->mo->angle = P_PointToAngle (player->mo->x, player->mo->y, linetarget->x, linetarget->y); } }
void G_DeathMatchSpawnPlayer (int playernum) { int i,j; int selections; selections = deathmatch_p - deathmatchstarts; if (selections < 4) I_Error ("Only %i deathmatch spots, 4 required", selections); for (j=0 ; j<20 ; j++) { i = P_Random()%selections; if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) { deathmatchstarts[i].type = playernum+1; P_SpawnPlayer (&deathmatchstarts[i]); return; } } /* no good spot, so the player will probably get stuck */ P_SpawnPlayer (&playerstarts[playernum]); }
// // A_TroopAttack // // Imp attack. // void A_TroopAttack(actionargs_t *actionargs) { Mobj *actor = actionargs->actor; if(!actor->target) return; A_FaceTarget(actionargs); if(P_CheckMeleeRange(actor)) { int damage; S_StartSound(actor, sfx_claw); damage = (P_Random(pr_troopattack)%8+1)*3; P_DamageMobj(actor->target, actor, actor, damage, MOD_HIT); } else { // launch a missile P_SpawnMissile(actor, actor->target, E_SafeThingType(MT_TROOPSHOT), actor->z + DEFAULTMISSILEZ); } }
void A_BFGSpray(mobj_t* mo) { int i; int j; int damage; angle_t an; // offset angles from its attack angle for(i = 0; i < 40; i++) { an = mo->angle - ANG90/2 + ANG90/40*i; // mo->target is the originator (player) of the missile // // [kex] add 1 to distance so autoaim can be forced // P_AimLineAttack(mo->target, an, 0, ATTACKRANGE + 1); if(!linetarget) continue; // // [d64] shift linetarget height by 1 instead of 2 // P_SpawnMobj(linetarget->x, linetarget->y, linetarget->z + (linetarget->height >> 1), MT_BFGSPREAD); damage = 0; for(j = 0; j < 15; j++) damage += (P_Random() & 7) + 1; P_DamageMobj(linetarget, mo->target, mo->target, damage); } A_FadeAlpha(mo); }
// // EV_FlickerLight // // haleyjd 01/16/07: // Parameterized flickering light effect. Changes between maxval and minval // at a randomized time period between 0.2 and 1.8 seconds (7 to 64 tics). // Uses the normal lightflash thinker. // int EV_FlickerLight(line_t *line, int tag, int maxval, int minval) { LightFlashThinker *flash; int i, rtn = 0; bool backside = false; if(line && tag == 0) { if(!line->backsector) return rtn; i = line->backsector - sectors; backside = true; goto dobackside; } for(i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;) { dobackside: rtn = 1; flash = new LightFlashThinker; flash->addThinker(); flash->sector = §ors[i]; flash->maxlight = maxval; flash->minlight = minval; flash->maxtime = 64; flash->mintime = 7; flash->count = (P_Random(pr_lights) & flash->maxtime) + 1; flash->sector->lightlevel = flash->maxlight; if(backside) return rtn; } return rtn; }
// // P_SpawnStrobeFlash // // Spawns a blinking light thinker // // Passed the sector that spawned the thinker, speed of blinking // and whether blinking is to by syncrhonous with other sectors // // Returns nothing // void P_SpawnStrobeFlash(sector_t *sector, int fastOrSlow, int inSync) { StrobeThinker *flash; flash = new StrobeThinker; flash->addThinker(); flash->sector = sector; flash->darktime = fastOrSlow; flash->brighttime = STROBEBRIGHT; flash->maxlight = sector->lightlevel; flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); if(flash->minlight == flash->maxlight) flash->minlight = 0; // nothing special about it during gameplay sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type if(!inSync) flash->count = (P_Random(pr_lights)&7)+1; else flash->count = 1; }
// // EV_DoPlat // // Handle Plat linedef types // // Passed the linedef that activated the plat, the type of plat action, // and for some plat types, an amount to raise // Returns true if a thinker is started, or restarted from stasis // int EV_DoPlat ( line_t* line, plattype_e type, int amount ) { plat_t* plat; int secnum; int rtn; sector_t* sec; secnum = -1; rtn = 0; // Activate all <type> plats that are in_stasis switch(type) { case perpetualRaise: P_ActivateInStasis(line->tag); break; case toggleUpDn: P_ActivateInStasis(line->tag); rtn=1; break; default: break; } // act on all sectors tagged the same as the activating linedef while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) { sec = §ors[secnum]; // don't start a second floor function if already moving if (P_SectorActive(floor_special,sec)) //jff 2/23/98 multiple thinkers continue; // Create a thinker rtn = 1; plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); memset(plat, 0, sizeof(*plat)); P_AddThinker(&plat->thinker); plat->type = type; plat->sector = sec; plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers plat->thinker.function = T_PlatRaise; plat->crush = false; plat->tag = line->tag; //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then //going down forever -- default low to plat height when triggered plat->low = sec->floorheight; // set up plat according to type switch(type) { case raiseToNearestAndChange: plat->speed = PLATSPEED/2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = P_FindNextHighestFloor(sec,sec->floorheight); plat->wait = 0; plat->status = up; sec->special = 0; //jff 3/14/98 clear old field as well sec->oldspecial = 0; S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case raiseAndChange: plat->speed = PLATSPEED/2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = sec->floorheight + amount*FRACUNIT; plat->wait = 0; plat->status = up; S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov); break; case downWaitUpStay: plat->speed = PLATSPEED * 4; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = down; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; case blazeDWUS: plat->speed = PLATSPEED * 8; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = down; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; case perpetualRaise: plat->speed = PLATSPEED; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = P_FindHighestFloorSurrounding(sec); if (plat->high < sec->floorheight) plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; plat->status = P_Random(pr_plats)&1; S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); break; case toggleUpDn: //jff 3/14/98 add new type to support instant toggle plat->speed = PLATSPEED; //not used plat->wait = 35*PLATWAIT; //not used plat->crush = true; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive plat->low = sec->ceilingheight; plat->high = sec->floorheight; plat->status = down; break; default: break; } P_AddActivePlat(plat); // add plat to list of active plats } return rtn; }
// // A_WeaponSetCtr // // Sets the value of the indicated counter variable for the thing. // Can perform numerous operations -- this is more like a virtual // machine than a codepointer ;) // // args[0] : counter # to set // args[1] : value to utilize // args[2] : operation to perform // void A_WeaponSetCtr(Mobj *mo) { int cnum; int value; int specialop; int *counter; player_t *player; pspdef_t *pspr; if(!(player = mo->player)) return; pspr = &(player->psprites[player->curpsprite]); cnum = E_ArgAsInt(pspr->state->args, 0, 0); value = E_ArgAsInt(pspr->state->args, 1, 0); specialop = E_ArgAsKwd(pspr->state->args, 2, &weapsetkwds, 0); switch(cnum) { case 0: case 1: case 2: counter = &(player->weaponctrs[player->readyweapon][cnum]); break; default: return; } switch(specialop) { case CPOP_ASSIGN: *counter = value; break; case CPOP_ADD: *counter += value; break; case CPOP_SUB: *counter -= value; break; case CPOP_MUL: *counter *= value; break; case CPOP_DIV: if(value) // don't divide by zero *counter /= value; break; case CPOP_MOD: if(value > 0) // only allow modulus by positive values *counter %= value; break; case CPOP_AND: *counter &= value; break; case CPOP_ANDNOT: *counter &= ~value; break; // compound and-not operation case CPOP_OR: *counter |= value; break; case CPOP_XOR: *counter ^= value; break; case CPOP_RND: *counter = P_Random(pr_weapsetctr); break; case CPOP_RNDMOD: if(value > 0) *counter = P_Random(pr_weapsetctr) % value; break; case CPOP_SHIFTLEFT: *counter <<= value; break; case CPOP_SHIFTRIGHT: *counter >>= value; break; default: break; } }
// // A_WeaponCtrOp // // Sets the value of the indicated counter variable for the weapon // using two (possibly the same) counters as operands. // // args[0] : counter operand #1 // args[1] : counter operand #2 // args[2] : counter destination // args[3] : operation to perform // void A_WeaponCtrOp(Mobj *mo) { player_t *player; pspdef_t *pspr; int c_oper1_num; int c_oper2_num; int c_dest_num; int specialop; int *c_oper1, *c_oper2, *c_dest; if(!(player = mo->player)) return; pspr = &(player->psprites[player->curpsprite]); c_oper1_num = E_ArgAsInt(pspr->state->args, 0, 0); c_oper2_num = E_ArgAsInt(pspr->state->args, 1, 0); c_dest_num = E_ArgAsInt(pspr->state->args, 2, 0); specialop = E_ArgAsKwd(pspr->state->args, 3, &weapctropkwds, 0); switch(c_oper1_num) { case 0: case 1: case 2: c_oper1 = &(player->weaponctrs[player->readyweapon][c_oper1_num]); break; default: return; } switch(c_oper2_num) { case 0: case 1: case 2: c_oper2 = &(player->weaponctrs[player->readyweapon][c_oper2_num]); break; default: return; } switch(c_dest_num) { case 0: case 1: case 2: c_dest = &(player->weaponctrs[player->readyweapon][c_dest_num]); break; default: return; } switch(specialop) { case CPOP_ADD: *c_dest = *c_oper1 + *c_oper2; break; case CPOP_SUB: *c_dest = *c_oper1 - *c_oper2; break; case CPOP_MUL: *c_dest = *c_oper1 * *c_oper2; break; case CPOP_DIV: if(c_oper2) // don't divide by zero *c_dest = *c_oper1 / *c_oper2; break; case CPOP_MOD: if(*c_oper2 > 0) // only allow modulus by positive values *c_dest = *c_oper1 % *c_oper2; break; case CPOP_AND: *c_dest = *c_oper1 & *c_oper2; break; case CPOP_OR: *c_dest = *c_oper1 | *c_oper2; break; case CPOP_XOR: *c_dest = *c_oper1 ^ *c_oper2; break; case CPOP_DAMAGE: // do a HITDICE-style calculation if(*c_oper2 > 0) // the modulus must be positive *c_dest = *c_oper1 * ((P_Random(pr_weapsetctr) % *c_oper2) + 1); break; case CPOP_SHIFTLEFT: *c_dest = *c_oper1 << *c_oper2; break; case CPOP_SHIFTRIGHT: *c_dest = *c_oper1 >> *c_oper2; break; // unary operations (c_oper2 is unused for these) case CPOP_ABS: *c_dest = abs(*c_oper1); break; case CPOP_NEGATE: *c_dest = -(*c_oper1); break; case CPOP_NOT: *c_dest = !(*c_oper1); break; case CPOP_INVERT: *c_dest = ~(*c_oper1); break; default: break; } }
/** * Damages both enemies and players. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc) * @param source Mobj to target after taking damage. Can be @c NULL * for barrel explosions and other environmental stuff. * Source and inflictor are the same for melee attacks. * @param skipNetworkCheck Allow the damage to be done regardless of netgame status. * * @return Actual amount of damage done. */ int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, dd_bool stomping, dd_bool skipNetworkCheck) { angle_t angle; int saved, originalHealth; player_t *player; int /*temp,*/ damage; if(!target) return 0; // Wha? originalHealth = target->health; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). damage = damageP; if(!skipNetworkCheck) { if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage)) { // We're done here. return 0; } // Clients can't harm anybody. if(IS_CLIENT) return 0; } if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; if(target->player) { // Player specific. // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && G_Ruleset_Skill() == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using a melee weapon. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { uint an; coord_t thrust; angle = M_PointToAngle2(inflictor->origin, target->origin); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->origin[VZ] - inflictor->origin[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); NetSv_PlayerMobjImpulse(target, thrust * FIX2FLT(finecosine[an]), thrust * FIX2FLT(finesine[an]), 0); // $dropoff_fix: thrust objects hanging off ledges. if((target->intFlags & MIF_FALLING) && target->gear >= MAXGEAR) target->gear = 0; }
// // A_CounterOp // // Sets the value of the indicated counter variable for the thing // using two (possibly the same) counters as operands. // // args[0] : counter operand #1 // args[1] : counter operand #2 // args[2] : counter destination // args[3] : operation to perform // void A_CounterOp(Mobj *mo) { int c_oper1_num, c_oper2_num, c_dest_num, specialop; int *c_oper1, *c_oper2, *c_dest; c_oper1_num = E_ArgAsInt(mo->state->args, 0, 0); c_oper2_num = E_ArgAsInt(mo->state->args, 1, 0); c_dest_num = E_ArgAsInt(mo->state->args, 2, 0); specialop = E_ArgAsKwd(mo->state->args, 3, &cpopkwds, 0); if(c_oper1_num < 0 || c_oper1_num >= NUMMOBJCOUNTERS) return; // invalid c_oper1 = &(mo->counters[c_oper1_num]); if(c_oper2_num < 0 || c_oper2_num >= NUMMOBJCOUNTERS) return; // invalid c_oper2 = &(mo->counters[c_oper2_num]); if(c_dest_num < 0 || c_dest_num >= NUMMOBJCOUNTERS) return; // invalid c_dest = &(mo->counters[c_dest_num]); switch(specialop) { case CPOP_ADD: *c_dest = *c_oper1 + *c_oper2; break; case CPOP_SUB: *c_dest = *c_oper1 - *c_oper2; break; case CPOP_MUL: *c_dest = *c_oper1 * *c_oper2; break; case CPOP_DIV: if(c_oper2) // don't divide by zero *c_dest = *c_oper1 / *c_oper2; break; case CPOP_MOD: if(*c_oper2 > 0) // only allow modulus by positive values *c_dest = *c_oper1 % *c_oper2; break; case CPOP_AND: *c_dest = *c_oper1 & *c_oper2; break; case CPOP_OR: *c_dest = *c_oper1 | *c_oper2; break; case CPOP_XOR: *c_dest = *c_oper1 ^ *c_oper2; break; case CPOP_DAMAGE: // do a HITDICE-style calculation if(*c_oper2 > 0) // the modulus must be positive *c_dest = *c_oper1 * ((P_Random(pr_setcounter) % *c_oper2) + 1); break; case CPOP_SHIFTLEFT: *c_dest = *c_oper1 << *c_oper2; break; case CPOP_SHIFTRIGHT: *c_dest = *c_oper1 >> *c_oper2; break; // unary operations (c_oper2 is unused for these) case CPOP_ABS: *c_dest = abs(*c_oper1); break; case CPOP_NEGATE: *c_dest = -(*c_oper1); break; case CPOP_NOT: *c_dest = !(*c_oper1); break; case CPOP_INVERT: *c_dest = ~(*c_oper1); break; default: break; } }
// // Do Platforms // [RH] Changed amount to height and added delay, // lip, change, tag, and speed parameters. // BOOL EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height, int speed, int delay, int lip, int change) { DPlat *plat; int secnum; sector_t *sec; int rtn = false; BOOL manual = false; // [RH] If tag is zero, use the sector on the back side // of the activating line (if any). if (!tag) { if (!line || !(sec = line->backsector)) return false; secnum = sec - sectors; manual = true; goto manual_plat; } // Activate all <type> plats that are in_stasis switch (type) { case DPlat::platToggle: rtn = true; case DPlat::platPerpetualRaise: P_ActivateInStasis (tag); break; default: break; } secnum = -1; while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) { sec = §ors[secnum]; manual_plat: if (sec->floordata) continue; // Find lowest & highest floors around sector rtn = true; plat = new DPlat (sec); plat->m_Type = type; plat->m_Crush = false; plat->m_Tag = tag; plat->m_Speed = speed; plat->m_Wait = delay; //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then //going down forever -- default lower to plat height when triggered plat->m_Low = sec->floorheight; if (change) { if (line) sec->floorpic = sides[line->sidenum[0]].sector->floorpic; if (change == 1) sec->special = 0; // Stop damage and other stuff, if any } switch (type) { case DPlat::platRaiseAndStay: plat->m_High = P_FindNextHighestFloor (sec, sec->floorheight); plat->m_Status = DPlat::midup; plat->PlayPlatSound(); break; case DPlat::platUpByValue: case DPlat::platUpByValueStay: plat->m_High = sec->floorheight + height; plat->m_Status = DPlat::midup; plat->PlayPlatSound(); break; case DPlat::platDownByValue: plat->m_Low = sec->floorheight - height; plat->m_Status = DPlat::middown; plat->PlayPlatSound(); break; case DPlat::platDownWaitUpStay: plat->m_Low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_High = sec->floorheight; plat->m_Status = DPlat::down; plat->PlayPlatSound(); break; case DPlat::platUpWaitDownStay: plat->m_High = P_FindHighestFloorSurrounding (sec); if (plat->m_High < sec->floorheight) plat->m_High = sec->floorheight; plat->m_Status = DPlat::up; plat->PlayPlatSound(); break; case DPlat::platPerpetualRaise: plat->m_Low = P_FindLowestFloorSurrounding (sec) + lip*FRACUNIT; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_High = P_FindHighestFloorSurrounding (sec); if (plat->m_High < sec->floorheight) plat->m_High = sec->floorheight; plat->m_Status = P_Random () & 1 ? DPlat::down : DPlat::up; plat->PlayPlatSound(); break; case DPlat::platToggle: //jff 3/14/98 add new type to support instant toggle plat->m_Crush = false; //jff 3/14/98 crush anything in the way // set up toggling between ceiling, floor inclusive plat->m_Low = sec->ceilingheight; plat->m_High = sec->floorheight; plat->m_Status = DPlat::down; // SN_StartSequence (sec, "Silence"); break; case DPlat::platDownToNearestFloor: plat->m_Low = P_FindNextLowestFloor (sec, sec->floorheight) + lip*FRACUNIT; plat->m_Status = DPlat::down; plat->m_High = sec->floorheight; plat->PlayPlatSound(); break; case DPlat::platDownToLowestCeiling: plat->m_Low = P_FindLowestCeilingSurrounding (sec); plat->m_High = sec->floorheight; if (plat->m_Low > sec->floorheight) plat->m_Low = sec->floorheight; plat->m_Status = DPlat::down; plat->PlayPlatSound(); break; default: break; } if (manual) return rtn; } return rtn; }
// // P_SubRandom // // haleyjd 08/05/04: This function eliminates the need to use // temporary variables everywhere in order to subtract two random // values without incurring order of evaluation problems. // int P_SubRandom(pr_class_t pr_class) { int temp = P_Random(pr_class); return (temp - P_Random(pr_class)); }
void P_KillMobj(mobj_t *source, mobj_t *target, dd_bool stomping) { mobjtype_t item; mobj_t* mo; unsigned int an; angle_t angle; if(!target) return; // Nothing to kill... target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY); if(target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->corpseTics = 0; target->height /= 2*2; if(source && source->player) { // Count for intermission. if(target->flags & MF_COUNTKILL) { source->player->killCount++; source->player->update |= PSF_COUNTERS; } if(target->player) { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); NetSv_KillMessage(source->player, target->player, stomping); } } else if(!IS_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 the player. if(!source) { target->player->frags[target->player - players]++; NetSv_FragsForAll(target->player); NetSv_KillMessage(target->player, target->player, stomping); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->update |= PSF_STATE; target->player->plr->flags |= DDPF_DEAD; P_DropWeapon(target->player); // Don't die with the automap open. ST_AutomapOpen(target->player - players, false, false); #if __JHERETIC__ || __JHEXEN__ Hu_InventoryOpen(target->player - players, false); #endif } if(target->health < -target->info->spawnHealth && P_GetState(target->type, SN_XDEATH)) { // Extreme death. P_MobjChangeState(target, P_GetState(target->type, SN_XDEATH)); } else { // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; if(target->tics < 1) target->tics = 1; // Enemies in Chex Quest don't drop stuff. if(gameMode == doom_chex) return; // Drop stuff. // This determines the kind of object spawned during the death frame // of a thing. switch(target->type) { case MT_WOLFSS: case MT_POSSESSED: item = MT_CLIP; break; case MT_SHOTGUY: item = MT_SHOTGUN; break; case MT_CHAINGUY: item = MT_CHAINGUN; break; default: return; } // Don't drop at the exact same place, causes Z flickering with // 3D sprites. angle = P_Random() << 24; an = angle >> ANGLETOFINESHIFT; if((mo = P_SpawnMobjXYZ(item, target->origin[VX] + 3 * FIX2FLT(finecosine[an]), target->origin[VY] + 3 * FIX2FLT(finesine[an]), 0, angle, MSF_Z_FLOOR))) mo->flags |= MF_DROPPED; // Special versions of items. }
void C_DECL A_CorpseExplode(mobj_t* actor) { int i, n; mobj_t* mo; for(i = (P_Random() & 3) + 3; i; i--) { if((mo = P_SpawnMobj(MT_CORPSEBIT, actor->origin, P_Random() << 24, 0))) { P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN) + (P_Random() % 3)); mo->mom[MZ] = FIX2FLT((P_Random() & 7) + 5) * .75f; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); } } // Spawn a skull. if((mo = P_SpawnMobj(MT_CORPSEBIT, actor->origin, P_Random() << 24, 0))) { P_MobjChangeState(mo, S_CORPSEBIT_4); n = (P_Random() & 7) + 5; mo->mom[MZ] = FIX2FLT(n) * .75f; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); S_StartSound(SFX_FIRED_DEATH, mo); } P_MobjRemove(actor, false); }
static int doPlat(Line *line, int tag, plattype_e type, int amount) #endif { #if !__JHEXEN__ Sector *frontSector = (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR); #endif iterlist_t *list = P_GetSectorIterListForTag(tag, false); if(!list) return 0; int rtn = 0; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { xsector_t *xsec = P_ToXSector(sec); if(xsec->specialData) continue; // Find lowest & highest floors around sector rtn = 1; plat_t *plat = (plat_t *) Z_Calloc(sizeof(*plat), PU_MAP, 0); plat->thinker.function = T_PlatRaise; Thinker_Add(&plat->thinker); xsec->specialData = plat; plat->type = type; plat->sector = sec; plat->crush = false; plat->tag = tag; #if __JHEXEN__ plat->speed = (float) args[1] * (1.0 / 8); #endif coord_t floorHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT); switch(type) { #if !__JHEXEN__ case PT_RAISETONEARESTANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); { coord_t nextFloor; if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor)) plat->high = nextFloor; else plat->high = floorHeight; } plat->wait = 0; plat->state = PS_UP; // No more damage if applicable. xsec->special = 0; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); break; case PT_RAISEANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); plat->high = floorHeight + amount; plat->wait = 0; plat->state = PS_UP; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); break; #endif case PT_DOWNWAITUPSTAY: P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED * 4; #endif if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->state = PS_DOWN; #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif break; #if __JDOOM64__ || __JHEXEN__ case PT_UPWAITDOWNSTAY: P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->state = PS_UP; # if __JHEXEN__ plat->wait = (int) args[2]; # else plat->wait = PLATWAIT * TICSPERSEC; # endif # if __JDOOM64__ plat->speed = PLATSPEED * 8; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); # endif break; #endif #if __JDOOM64__ case PT_DOWNWAITUPDOOR: // jd64 plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; if(plat->low != floorHeight) plat->low += 6; plat->high = floorHeight; plat->wait = 50 * PLATWAIT; plat->state = PS_DOWN; break; #endif #if __JHEXEN__ case PT_DOWNBYVALUEWAITUPSTAY: plat->low = floorHeight - (coord_t) args[3] * 8; if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = (int) args[2]; plat->state = PS_DOWN; break; case PT_UPBYVALUEWAITDOWNSTAY: plat->high = floorHeight + (coord_t) args[3] * 8; if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->wait = (int) args[2]; plat->state = PS_UP; break; #endif #if __JDOOM__ || __JDOOM64__ case PT_DOWNWAITUPSTAYBLAZE: plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = PLATWAIT * TICSPERSEC; plat->state = PS_DOWN; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); break; #endif case PT_PERPETUALRAISE: P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED; #endif if(plat->low > floorHeight) plat->low = floorHeight; P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->state = platstate_e(P_Random() & 1); #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif break; default: break; } #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #endif } return rtn; }
static void P_LightningFlash(void) { int i; sector_t *tempSec; bool foundSec; int flashLight; static PointThinker thunderSndOrigin; if(LightningFlash) { LightningFlash--; if(LightningFlash) { for(i = 0; i < numsectors; i++) { tempSec = §ors[i]; if(tempSec->intflags & SIF_SKY && tempSec->oldlightlevel < tempSec->lightlevel - 4) { tempSec->lightlevel -= 4; } } } else { for(i = 0; i < numsectors; i++) { tempSec = §ors[i]; if(tempSec->intflags & SIF_SKY) tempSec->lightlevel = tempSec->oldlightlevel; } if(LevelSky != -1 && LevelTempSky != -1) skytexture = LevelSky; } } else { LightningFlash = (P_Random(pr_lightning) & 7) + 8; flashLight = 200 + (P_Random(pr_lightning) & 31); foundSec = false; for(i = 0; i < numsectors; i++) { tempSec = §ors[i]; if(tempSec->intflags & SIF_SKY) { tempSec->oldlightlevel = tempSec->lightlevel; tempSec->lightlevel = flashLight; if(tempSec->lightlevel < tempSec->oldlightlevel) tempSec->lightlevel = tempSec->oldlightlevel; foundSec = true; } } if(foundSec) { if(LevelSky != -1 && LevelTempSky != -1) skytexture = LevelTempSky; S_StartSoundAtVolume(&thunderSndOrigin, sfx_thundr, 127, ATTN_NONE, CHAN_AUTO); } if(!NextLightningFlash) { if(M_Random() < 50) NextLightningFlash = (M_Random() & 15) + 16; else { if(M_Random() < 128 && !(leveltime & 32)) NextLightningFlash = ((M_Random() & 7) + 2) * 35; else NextLightningFlash = ((M_Random() & 15) + 5) * 35; } } } }
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; } } } }
static cell AMX_NATIVE_CALL sm_random(AMX *amx, cell *params) { return P_Random(pr_script); }
// // P_RangeRandom // // haleyjd 05/31/06: Returns a random number within a given range. // int P_RangeRandom(pr_class_t pr_class, int min, int max) { return (P_Random(pr_class) % (max - min + 1)) + min; }
void P_AmbientSound(void) { afxcmd_t cmd; int sound; boolean done; if(!AmbSfxCount) { // No ambient sound sequences on current level return; } if(--AmbSfxTics) { return; } done = false; do { cmd = *AmbSfxPtr++; switch(cmd) { case afxcmd_play: AmbSfxVolume = P_Random()>>2; S_StartSoundAtVolume(NULL, *AmbSfxPtr++, AmbSfxVolume); break; case afxcmd_playabsvol: sound = *AmbSfxPtr++; AmbSfxVolume = *AmbSfxPtr++; S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); break; case afxcmd_playrelvol: sound = *AmbSfxPtr++; AmbSfxVolume += *AmbSfxPtr++; if(AmbSfxVolume < 0) { AmbSfxVolume = 0; } else if(AmbSfxVolume > 127) { AmbSfxVolume = 127; } S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); break; case afxcmd_delay: AmbSfxTics = *AmbSfxPtr++; done = true; break; case afxcmd_delayrand: AmbSfxTics = P_Random()&(*AmbSfxPtr++); done = true; break; case afxcmd_end: AmbSfxTics = 6*TICSPERSEC+P_Random(); AmbSfxPtr = LevelAmbientSfx[P_Random()%AmbSfxCount]; done = true; break; default: I_Error("P_AmbientSound: Unknown afxcmd %d", cmd); break; } } while(done == false); }
void C_DECL A_PoisonShroom(mobj_t* actor) { actor->tics = 128 + (P_Random() << 1); }
// // P_PlayerInSpecialSector // Called every tic frame // that the player origin is in a special sector // void P_PlayerInSpecialSector (player_t* player) { sector_t* sector; extern int showMessages; player2_t *player2 = p2fromp(player); static sector_t* error; sector = player->mo->subsector->sector; // Falling, not all the way down yet? if (player->mo->z != sector->floorheight) return; // Has hitten ground. switch (sector->special) { case 5: // HELLSLIME DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 10); break; case 7: // NUKAGE DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 5); break; case 16: // SUPER HELLSLIME DAMAGE case 4: // STROBE HURT if (!player->powers[pw_ironfeet] || (P_Random()<5) ) { if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); } break; case 9: // SECRET SECTOR // [crispy] show centered "Secret Revealed!" message if (showMessages && crispy_secretmessage) { player2->centermessage = HUSTR_SECRETFOUND; if (player == &players[consoleplayer]) S_StartSound(NULL, sfx_itmbk); } player->secretcount++; sector->special = 0; break; case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) player->cheats &= ~CF_GODMODE; if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); if (player->health <= 10) G_ExitLevel(); break; default: // [crispy] ignore unknown special sectors if (error != sector) { error = sector; printf ("P_PlayerInSpecialSector: " "unknown special %i\n", sector->special); } break; }; }
int P_RandomShift(int shift) { int rand = P_Random(); return (rand - P_Random()) << shift; }
// A_CentaurAttack2 // void A_CentaurAttack2(Mobj *actor) { // HEXEN_TODO } // // P_TossEquipmentItem // // Throws an object away from the source. // static void P_TossEquipmentItem(Mobj *mo, angle_t angle, int momshift, fixed_t baseZMom) { mo->momx = FixedMul(((P_Random(pr_dropequip) - 128) << momshift) + FRACUNIT, finecosine[angle >> ANGLETOFINESHIFT]); mo->momy = FixedMul(((P_Random(pr_dropequip) - 128) << momshift) + FRACUNIT, finesine[angle >> ANGLETOFINESHIFT]); mo->momz = baseZMom + (P_Random(pr_dropequip) << (momshift - 1)); } // // A_DropEquipment // // Note: was A_CentaurDropStuff in Hexen // Parameters: // * args[0] : thing type 1 // * args[1] : thing type 2
// // P_PlayerInSpecialSector // Called every tic frame // that the player origin is in a special sector // void P_PlayerInSpecialSector (player_t* player) { sector_t* sector; sector = player->mo->subsector->sector; // Falling, not all the way down yet? if (player->mo->z != sector->floorheight) return; // Has hitten ground. switch (sector->special) { case 5: // HELLSLIME DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 10); break; case 7: // NUKAGE DAMAGE if (!player->powers[pw_ironfeet]) if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 5); break; case 16: // SUPER HELLSLIME DAMAGE case 4: // STROBE HURT if (!player->powers[pw_ironfeet] || (P_Random()<5) ) { if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); } break; case 9: // SECRET SECTOR player->secretcount++; sector->special = 0; break; case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) player->cheats &= ~CF_GODMODE; if (!(leveltime&0x1f)) P_DamageMobj (player->mo, NULL, NULL, 20); if (player->health <= 10) G_ExitLevel(); break; default: I_Error ("P_PlayerInSpecialSector: " "unknown special %i", sector->special); break; }; }
//================================================================== // // Do Platforms // "amount" is only used for SOME platforms. // //================================================================== int EV_DoPlat(line_t * line, plattype_e type, int amount) { plat_t *plat; int secnum; int rtn; sector_t *sec; secnum = -1; rtn = 0; // // Activate all <type> plats that are in_stasis // switch (type) { case perpetualRaise: P_ActivateInStasis(line->tag); break; default: break; } while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) { sec = §ors[secnum]; if (sec->specialdata) continue; // // Find lowest & highest floors around sector // rtn = 1; plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0); P_AddThinker(&plat->thinker); plat->type = type; plat->sector = sec; plat->sector->specialdata = plat; plat->thinker.function = T_PlatRaise; plat->crush = false; plat->tag = line->tag; switch (type) { case raiseToNearestAndChange: plat->speed = PLATSPEED / 2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = P_FindNextHighestFloor(sec, sec->floorheight); plat->wait = 0; plat->status = up; sec->special = 0; // NO MORE DAMAGE, IF APPLICABLE S_StartSound(&sec->soundorg, sfx_stnmov); break; case raiseAndChange: plat->speed = PLATSPEED / 2; sec->floorpic = sides[line->sidenum[0]].sector->floorpic; plat->high = sec->floorheight + amount * FRACUNIT; plat->wait = 0; plat->status = up; S_StartSound(&sec->soundorg, sfx_stnmov); break; case downWaitUpStay: plat->speed = PLATSPEED * 4; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = sec->floorheight; plat->wait = 35 * PLATWAIT; plat->status = down; S_StartSound(&sec->soundorg, sfx_pstart); break; case perpetualRaise: plat->speed = PLATSPEED; plat->low = P_FindLowestFloorSurrounding(sec); if (plat->low > sec->floorheight) plat->low = sec->floorheight; plat->high = P_FindHighestFloorSurrounding(sec); if (plat->high < sec->floorheight) plat->high = sec->floorheight; plat->wait = 35 * PLATWAIT; plat->status = P_Random() & 1; S_StartSound(&sec->soundorg, sfx_pstart); break; } P_AddActivePlat(plat); } return rtn; }
void C_DECL A_PotteryChooseBit(mobj_t* actor) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH) + (P_Random() % 5) + 1); actor->tics = 256 + (P_Random() << 1); }