DEFINE_ACTION_FUNCTION(AActor, A_Beacon) { PARAM_ACTION_PROLOGUE; AActor *owner = self->target; AActor *rebel; rebel = Spawn("Rebel1", self->PosAtZ(self->floorz), ALLOW_REPLACE); if (!P_TryMove (rebel, rebel->Pos(), true)) { rebel->Destroy (); return 0; } // Once the rebels start teleporting in, you can't pick up the beacon anymore. self->flags &= ~MF_SPECIAL; static_cast<AInventory *>(self)->DropTime = 0; // Set up the new rebel. rebel->threshold = rebel->DefThreshold; rebel->target = NULL; rebel->flags4 |= MF4_INCOMBAT; rebel->LastHeard = owner; // Make sure the rebels look for targets if (deathmatch) { rebel->health *= 2; } if (owner != NULL) { // Rebels are the same color as their owner (but only in multiplayer) if (multiplayer) { rebel->Translation = owner->Translation; } rebel->SetFriendPlayer(owner->player); // Set the rebel's target to whatever last hurt the player, so long as it's not // one of the player's other rebels. if (owner->target != NULL && !rebel->IsFriend (owner->target)) { rebel->target = owner->target; } } rebel->SetState (rebel->SeeState); rebel->Angles.Yaw = self->Angles.Yaw; Spawn<ATeleportFog> (rebel->Vec3Angle(20., self->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); if (--self->health < 0) { self->SetState(self->FindState(NAME_Death)); } return 0; }
void A_BishopMissileWeave (AActor *actor) { fixed_t newX, newY; int weaveXY, weaveZ; int angle; weaveXY = actor->special2 >> 16; weaveZ = actor->special2 & 0xFFFF; angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; newX = actor->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY = actor->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); weaveXY = (weaveXY + 2) & 63; newX += FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY += FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); P_TryMove (actor, newX, newY, true); actor->z -= FloatBobOffsets[weaveZ]; weaveZ = (weaveZ + 2) & 63; actor->z += FloatBobOffsets[weaveZ]; actor->special2 = weaveZ + (weaveXY<<16); }
DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave) { fixed_t newX, newY; int weaveXY, weaveZ; int angle; if (self->special2 == 0) self->special2 = 16; weaveXY = self->special2 >> 16; weaveZ = self->special2 & 0xFFFF; angle = (self->angle + ANG90) >> ANGLETOFINESHIFT; newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); weaveXY = (weaveXY + 2) & 63; newX += FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1); newY += FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1); P_TryMove (self, newX, newY, true); self->z -= FloatBobOffsets[weaveZ]; weaveZ = (weaveZ + 2) & 63; self->z += FloatBobOffsets[weaveZ]; self->special2 = weaveZ + (weaveXY<<16); }
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; }
DEFINE_ACTION_FUNCTION(AActor, A_Beacon) { AActor *owner = self->target; AActor *rebel; angle_t an; // [BC] AActor *pFog; // [BC] This is handled server-side. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } rebel = Spawn("Rebel1", self->x, self->y, self->floorz, ALLOW_REPLACE); if (!P_TryMove (rebel, rebel->x, rebel->y, true)) { rebel->Destroy (); return; } // Once the rebels start teleporting in, you can't pick up the beacon anymore. self->flags &= ~MF_SPECIAL; static_cast<AInventory *>(self)->DropTime = 0; // Set up the new rebel. rebel->threshold = BASETHRESHOLD; rebel->target = NULL; rebel->flags4 |= MF4_INCOMBAT; rebel->LastHeard = owner; // Make sure the rebels look for targets if (deathmatch) { rebel->health *= 2; } if (owner != NULL) { // Rebels are the same color as their owner (but only in multiplayer) // [BB] Changed "multiplayer" check if ( NETWORK_GetState( ) != NETSTATE_SINGLE ) { rebel->Translation = owner->Translation; } rebel->FriendPlayer = owner->player != NULL ? BYTE(owner->player - players + 1) : 0; // Set the rebel's target to whatever last hurt the player, so long as it's not // one of the player's other rebels. if (owner->target != NULL && !rebel->IsFriend (owner->target)) { rebel->target = owner->target; } } // [BC] Spawn the rebel, and put him in the see state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVERCOMMANDS_SpawnThing( rebel ); SERVERCOMMANDS_SetThingState( rebel, STATE_SEE ); } rebel->SetState (rebel->SeeState); rebel->angle = self->angle; an = self->angle >> ANGLETOFINESHIFT; pFog = Spawn<ATeleportFog> (rebel->x + 20*finecosine[an], rebel->y + 20*finesine[an], rebel->z + TELEFOGHEIGHT, ALLOW_REPLACE); // [BC] Spawn the teleport fog. if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( pFog )) { SERVERCOMMANDS_SpawnThing( pFog ); } if (--self->health < 0) { // [BB] Tell clients to set the thing's state. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SetThingState( self, STATE_DEATH ); self->SetState(self->FindState(NAME_Death)); } }
void P_XYMovement (mobj_t* mo) { fixed_t ptryx; fixed_t ptryy; player_t* player; fixed_t xmove; fixed_t ymove; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mo->info->spawnstate); } return; } player = mo->player; if (mo->momx > MAXMOVE) mo->momx = MAXMOVE; else if (mo->momx < -MAXMOVE) mo->momx = -MAXMOVE; if (mo->momy > MAXMOVE) mo->momy = MAXMOVE; else if (mo->momy < -MAXMOVE) mo->momy = -MAXMOVE; xmove = mo->momx; ymove = mo->momy; do { if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) { ptryx = mo->x + xmove/2; ptryy = mo->y + ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if (!P_TryMove (mo, ptryx, ptryy)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove (mo); } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum) { // Hack to prevent missiles exploding // against the sky. // Does not handle sky floors. P_RemoveMobj (mo); return; } P_ExplodeMissile (mo); } else mo->momx = mo->momy = 0; } } while (xmove || ymove);
// // P_XYMovement // void P_XYMovement (AActor *mo) { // angle_t angle; fixed_t ptryx, ptryy; player_t *player = NULL; fixed_t xmove, ymove; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mo->info->spawnstate); } return; } player = mo->player; if(!player || !player->mo) player = NULL; int maxmove = (mo->waterlevel < 2) || (mo->flags & MF_MISSILE) ? MAXMOVE : MAXMOVE/4; if (mo->momx > maxmove) mo->momx = maxmove; else if (mo->momx < -maxmove) mo->momx = -maxmove; if (mo->momy > maxmove) mo->momy = maxmove; else if (mo->momy < -maxmove) mo->momy = -maxmove; xmove = mo->momx; ymove = mo->momy; maxmove /= 2; do { if (xmove > maxmove || ymove > maxmove ) { ptryx = mo->x + xmove/2; ptryy = mo->y + ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } // killough 3/15/98: Allow objects to drop off if (!P_TryMove (mo, ptryx, ptryy, true)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove (mo); } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum) { // Hack to prevent missiles exploding // against the sky. // Does not handle sky floors. mo->Destroy (); return; } P_ExplodeMissile (mo); } else { mo->momx = mo->momy = 0; } } } while (xmove || ymove);
void P_XYMovement(mobj_t *mo) { player_t *player; fixed_t xmove, ymove; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState(mo, (statenum_t)mo->info->spawnstate); } return; } player = mo->player; if (mo->type == MT_ROCKET) { if (puffcount++ > 1) P_SpawnPuff(mo->x, mo->y, mo->z, mo->angle); } if (mo->momx > MAXMOVE) mo->momx = MAXMOVE; else if (mo->momx < -MAXMOVE) mo->momx = -MAXMOVE; if (mo->momy > MAXMOVE) mo->momy = MAXMOVE; else if (mo->momy < -MAXMOVE) mo->momy = -MAXMOVE; xmove = mo->momx; ymove = mo->momy; do { fixed_t ptryx, ptryy; if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2 || xmove < -MAXMOVE / 2 || ymove < -MAXMOVE / 2) { ptryx = mo->x + xmove / 2; ptryy = mo->y + ymove / 2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if (!P_TryMove(mo, ptryx, ptryy)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove(mo); } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum && mo->z > ceilingline->backsector->ceilingheight) { // Hack to prevent missiles exploding // against the sky. // Does not handle sky floors. shootingsky = true; P_RemoveMobj(mo); return; } P_ExplodeMissile(mo); } else { mo->momx = mo->momy = 0; } } }
int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch) { if (flags & WARPF_MOVEPTR) { AActor *temp = reference; reference = caller; caller = temp; } DVector3 old = caller->Pos(); int oldpgroup = caller->Sector->PortalGroup; zofs += reference->Height * heightoffset; if (!(flags & WARPF_ABSOLUTEANGLE)) { angle += (flags & WARPF_USECALLERANGLE) ? caller->Angles.Yaw: reference->Angles.Yaw; } const double rad = radiusoffset * reference->radius; const double s = angle.Sin(); const double c = angle.Cos(); if (!(flags & WARPF_ABSOLUTEPOSITION)) { if (!(flags & WARPF_ABSOLUTEOFFSET)) { double xofs1 = xofs; // (borrowed from A_SpawnItemEx, assumed workable) // in relative mode negative y values mean 'left' and positive ones mean 'right' // This is the inverse orientation of the absolute mode! xofs = xofs1 * c + yofs * s; yofs = xofs1 * s - yofs * c; } if (flags & WARPF_TOFLOOR) { // set correct xy // now the caller's floorz should be appropriate for the assigned xy-position // assigning position again with. // extra unlink, link and environment calculation caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, 0.), true); // The two-step process is important. caller->SetZ(caller->floorz + zofs); } else { caller->SetOrigin(reference->Vec3Offset(xofs + rad * c, yofs + rad * s, zofs), true); } } else // [MC] The idea behind "absolute" is meant to be "absolute". Override everything, just like A_SpawnItemEx's. { caller->SetOrigin(xofs + rad * c, yofs + rad * s, zofs, true); if (flags & WARPF_TOFLOOR) { caller->SetZ(caller->floorz + zofs); } } if ((flags & WARPF_NOCHECKPOSITION) || P_TestMobjLocation(caller)) { if (flags & WARPF_TESTONLY) { caller->SetOrigin(old, true); } else { caller->Angles.Yaw = angle; if (flags & WARPF_COPYPITCH) caller->SetPitch(reference->Angles.Pitch, false); if (pitch != 0) caller->SetPitch(caller->Angles.Pitch + pitch, false); if (flags & WARPF_COPYVELOCITY) { caller->Vel = reference->Vel; } if (flags & WARPF_STOP) { caller->Vel.Zero(); } // this is no fun with line portals if (flags & WARPF_WARPINTERPOLATION) { // This just translates the movement but doesn't change the vector DVector3 displacedold = old + Displacements.getOffset(oldpgroup, caller->Sector->PortalGroup); caller->Prev += caller->Pos() - displacedold; caller->PrevPortalGroup = caller->Sector->PortalGroup; } else if (flags & WARPF_COPYINTERPOLATION) { // Map both positions of the reference actor to the current portal group DVector3 displacedold = old + Displacements.getOffset(reference->PrevPortalGroup, caller->Sector->PortalGroup); DVector3 displacedref = old + Displacements.getOffset(reference->Sector->PortalGroup, caller->Sector->PortalGroup); caller->Prev = caller->Pos() + displacedold - displacedref; caller->PrevPortalGroup = caller->Sector->PortalGroup; } else if (!(flags & WARPF_INTERPOLATE)) { caller->ClearInterpolation(); } if ((flags & WARPF_BOB) && (reference->flags2 & MF2_FLOATBOB)) { caller->AddZ(reference->GetBobOffset()); } P_TryMove(caller, caller->Pos(), false); } return true; } caller->SetOrigin(old, true); return false; }
void AFastProjectile::Tick () { int i; DVector3 frac; int changexy; ClearInterpolation(); double oldz = Z(); if (!(flags5 & MF5_NOTIMEFREEZE)) { //Added by MC: Freeze mode. if (bglobal.freeze || level.flags2 & LEVEL2_FROZEN) { return; } } // [RH] Ripping is a little different than it was in Hexen FCheckPosition tm(!!(flags2 & MF2_RIP)); int count = 8; if (radius > 0) { while ( fabs(Vel.X) > radius * count || fabs(Vel.Y) > radius * count) { // we need to take smaller steps. count += count; } } // Handle movement if (!Vel.isZero() || (Z() != floorz)) { // force some lateral movement so that collision detection works as intended. if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage()) { Vel.X = MinVel; } frac = Vel / count; changexy = frac.X != 0 || frac.Y != 0; int ripcount = count / 8; for (i = 0; i < count; i++) { if (changexy) { if (--ripcount <= 0) { tm.LastRipped.Clear(); // [RH] Do rip damage each step, like Hexen } if (!P_TryMove (this, Pos() + frac, true, NULL, tm)) { // Blocked move if (!(flags3 & MF3_SKYEXPLODE)) { if (tm.ceilingline && tm.ceilingline->backsector && tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum && Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(PosRelative(tm.ceilingline))) { // Hack to prevent missiles exploding against the sky. // Does not handle sky floors. Destroy (); return; } // [RH] Don't explode on horizon lines. if (BlockingLine != NULL && BlockingLine->special == Line_Horizon) { Destroy (); return; } } P_ExplodeMissile (this, BlockingLine, BlockingMobj); return; } } AddZ(frac.Z); UpdateWaterLevel (); oldz = Z(); if (oldz <= floorz) { // Hit the floor if (floorpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE)) { // [RH] Just remove the missile without exploding it // if this is a sky floor. Destroy (); return; } SetZ(floorz); P_HitFloor (this); P_ExplodeMissile (this, NULL, NULL); return; } if (Top() > ceilingz) { // Hit the ceiling if (ceilingpic == skyflatnum && !(flags3 & MF3_SKYEXPLODE)) { Destroy (); return; } SetZ(ceilingz - Height); P_ExplodeMissile (this, NULL, NULL); return; } if (!frac.isZero() && ripcount <= 0) { ripcount = count >> 3; Effect(); } } }
// // P_XYMovement // void P_XYMovement(AActor *mo) { // angle_t angle; fixed_t ptryx, ptryy; player_t *player = NULL; fixed_t xmove, ymove; fixed_t maxmove; static const int windTab[3] = {2048*5, 2048*10, 2048*25}; if (!mo->subsector) return; if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mo->info->spawnstate); } return; } maxmove = (mo->waterlevel < 2) || (mo->flags & MF_MISSILE) ? MAXMOVE : MAXMOVE/4; if (mo->flags2 & MF2_WINDTHRUST) { int special = mo->subsector->sector->special; switch (special) { case 40: case 41: case 42: // Wind_East P_ThrustMobj (mo, 0, windTab[special-40]); break; case 43: case 44: case 45: // Wind_North P_ThrustMobj (mo, ANG90, windTab[special-43]); break; case 46: case 47: case 48: // Wind_South P_ThrustMobj (mo, ANG270, windTab[special-46]); break; case 49: case 50: case 51: // Wind_West P_ThrustMobj (mo, ANG180, windTab[special-49]); break; } } xmove = mo->momx = clamp (mo->momx, -maxmove, maxmove); ymove = mo->momy = clamp (mo->momy, -maxmove, maxmove); player = mo->player; if(!player || !player->mo) player = NULL; maxmove /= 2; do { if (xmove > maxmove || ymove > maxmove ) { ptryx = mo->x + xmove/2; ptryy = mo->y + ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } // killough 3/15/98: Allow objects to drop off if (!P_TryMove (mo, ptryx, ptryy, true)) { // blocked move if (mo->flags2 & MF2_SLIDE) { // try to slide along it if (BlockingMobj == NULL) { // slide against wall if (BlockingLine != NULL && mo->player && mo->waterlevel && mo->waterlevel < 3 && (mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove) && BlockingLine->sidenum[1] != -1) { mo->momz = WATER_JUMP_SPEED; } P_SlideMove (mo); } else { // slide against mobj if (P_TryMove (mo, mo->x, ptryy, true)) { mo->momx = 0; } else if (P_TryMove (mo, ptryx, mo->y, true)) { mo->momy = 0; } else { mo->momx = mo->momy = 0; } } } else if (mo->flags & MF_MISSILE) { // explode a missile if (ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum) { // Hack to prevent missiles exploding // against the sky. // Does not handle sky floors. mo->Destroy (); return; } // [SL] 2011-06-02 - Only server should control explosions if (serverside) P_ExplodeMissile (mo); } else { mo->momx = mo->momy = 0; } } } while (xmove || ymove);
void P_XYMovement (mobj_t* mo) { fixed_t ptryx; fixed_t ptryy; player_t* player; fixed_t xmove; fixed_t ymove; // villsa [STRIFE] unused /* if (!mo->momx && !mo->momy) { if (mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mo->info->spawnstate); } return; } */ player = mo->player; if (mo->momx > MAXMOVE) mo->momx = MAXMOVE; else if (mo->momx < -MAXMOVE) mo->momx = -MAXMOVE; if (mo->momy > MAXMOVE) mo->momy = MAXMOVE; else if (mo->momy < -MAXMOVE) mo->momy = -MAXMOVE; xmove = mo->momx; ymove = mo->momy; do { if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) { ptryx = mo->x + xmove/2; ptryy = mo->y + ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if (!P_TryMove (mo, ptryx, ptryy)) { // blocked move if (mo->player) { // try to slide along it P_SlideMove (mo); } // villsa [STRIFE] check for bouncy missiles else if(mo->flags & MF_BOUNCE) { mo->momx >>= 3; mo->momy >>= 3; if (P_TryMove(mo, mo->x - xmove, ymove + mo->y)) mo->momy = -mo->momy; else mo->momx = -mo->momx; xmove = 0; ymove = 0; } else if (mo->flags & MF_MISSILE)