// // R_PointToAngle - wrapper around R_PointToAngle2 // angle_t R_PointToAngle ( fixed_t x, fixed_t y ) { return R_PointToAngle2 (viewx, viewy, x, y); }
void A_Tracer2 (AActor *self) { AActor *dest; angle_t exact; fixed_t dist; fixed_t slope; dest = self->tracer; if (dest == NULL || dest->health <= 0 || self->Speed == 0) return; // change angle exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y); if (exact != self->angle) { if (exact - self->angle > 0x80000000) { self->angle -= TRACEANGLE; if (exact - self->angle < 0x80000000) self->angle = exact; } else { self->angle += TRACEANGLE; if (exact - self->angle > 0x80000000) self->angle = exact; } } exact = self->angle >> ANGLETOFINESHIFT; self->momx = FixedMul (self->Speed, finecosine[exact]); self->momy = FixedMul (self->Speed, finesine[exact]); // change slope dist = P_AproxDistance (dest->x - self->x, dest->y - self->y); dist /= self->Speed; if (dist < 1) { dist = 1; } if (dest->height >= 56*FRACUNIT) { slope = (dest->z+40*FRACUNIT - self->z) / dist; } else { slope = (dest->z + self->height*2/3 - self->z) / dist; } if (slope < self->momz) { self->momz -= FRACUNIT/8; } else { self->momz += FRACUNIT/8; } }
BOOL R_AlignFlat (int linenum, int side, int fc) { line_t *line = lines + linenum; sector_t *sec = side ? line->backsector : line->frontsector; if (!sec) return false; fixed_t x = line->v1->x; fixed_t y = line->v1->y; angle_t angle = R_PointToAngle2 (x, y, line->v2->x, line->v2->y); angle_t norm = (angle-ANG90) >> ANGLETOFINESHIFT; fixed_t dist = -FixedMul (finecosine[norm], x) - FixedMul (finesine[norm], y); if (side) { angle = angle + ANG180; dist = -dist; } if (fc) { sec->base_ceiling_angle = 0-angle; sec->base_ceiling_yoffs = dist & ((1<<(FRACBITS+8))-1); } else { sec->base_floor_angle = 0-angle; sec->base_floor_yoffs = dist & ((1<<(FRACBITS+8))-1); } return true; }
//Called while the bot moves after its player->dest mobj //which can be a weapon/enemy/item whatever. void FCajunMaster::Roam (AActor *actor, ticcmd_t *cmd) { int delta; if (Reachable(actor, actor->player->dest)) { // Straight towards it. actor->player->angle = R_PointToAngle2(actor->x, actor->y, actor->player->dest->x, actor->player->dest->y); } else if (actor->movedir < 8) // turn towards movement direction if not there yet { actor->player->angle &= (angle_t)(7<<29); delta = actor->player->angle - (actor->movedir << 29); if (delta > 0) actor->player->angle -= ANG45; else if (delta < 0) actor->player->angle += ANG45; } // chase towards destination. if (--actor->movecount < 0 || !Move (actor, cmd)) { NewChaseDir (actor, cmd); } }
void A_Punch(player_t *player, pspdef_t *psp) { angle_t angle; int t, slope, damage = (P_Random(pr_punch)%10+1)<<1; if (player->powers[pw_strength]) damage *= 10; angle = player->mo->angle; // killough 5/5/98: remove dependence on order of evaluation: t = P_Random(pr_punchangle); angle += (t - P_Random(pr_punchangle))<<18; /* killough 8/2/98: make autoaiming prefer enemies */ if (!mbf_features || (slope = P_AimLineAttack(player->mo, angle, MELEERANGE, MF_FRIEND), !linetarget)) slope = P_AimLineAttack(player->mo, angle, MELEERANGE, 0); P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); if (!linetarget) return; S_StartSound(player->mo, sfx_punch); // turn to face target player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); R_SmoothPlaying_Reset(player); // e6y }
void A_Punch(player_t* player, pspdef_t* psp) { angle_t angle; int damage; int slope = 0; damage = ((P_Random() & 7) + 1) * 3; if(player->powers[pw_strength]) damage *= 10; angle = player->mo->angle; angle += P_RandomShift(18); slope = P_AimLineAttack(player->mo, angle, 0, MELEERANGE); P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); // turn to face target if(linetarget) { S_StartSound(player->mo, sfx_punch); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); } }
//Called while the bot moves after its dest mobj //which can be a weapon/enemy/item whatever. void DBot::Roam (ticcmd_t *cmd) { int delta; if (Reachable(dest)) { // Straight towards it. angle = R_PointToAngle2(player->mo->x, player->mo->y, dest->x, dest->y); } else if (player->mo->movedir < 8) // turn towards movement direction if not there yet { angle &= (angle_t)(7<<29); delta = angle - (player->mo->movedir << 29); if (delta > 0) angle -= ANG45; else if (delta < 0) angle += ANG45; } // chase towards destination. if (--player->mo->movecount < 0 || !Move (cmd)) { NewChaseDir (cmd); } }
// // A_Saw // void A_Saw(player_t *player, pspdef_t *psp) { int damage = 2 * (P_Random() % 10 + 1); angle_t angle = player->mo->angle + ((P_Random() - P_Random()) << 18); int slope = P_AimLineAttack(player->mo, angle, MELEERANGE + 1); // use meleerange + 1 so the puff doesn't skip the flash P_LineAttack(player->mo, angle, MELEERANGE + 1, slope, damage); if (!linetarget) { S_StartSound(player->mo, sfx_sawful); return; } S_StartSound (player->mo, sfx_sawhit); // turn to face target angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); if (angle - player->mo->angle > ANG180) { if (angle - player->mo->angle < -ANG90 / 20) player->mo->angle = angle + ANG90 / 21; else player->mo->angle -= ANG90 / 20; } else { if (angle - player->mo->angle > ANG90 / 20) player->mo->angle = angle - ANG90 / 21; else player->mo->angle += ANG90 / 20; } player->mo->flags |= MF_JUSTATTACKED; }
OVERLAY void A_Punch(player_t *player, pspdef_t *psp) { angle_t angle; int t, slope, damage = (P_Random(pr_punch)%10+1)<<1; if (player->powers[pw_strength]) damage *= 10; angle = player->mo->angle; // killough 5/5/98: remove dependence on order of evaluation: t = P_Random(pr_punchangle); angle += (t - P_Random(pr_punchangle))<<18; slope = P_AimLineAttack(player->mo, angle, MELEERANGE); P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); if (!linetarget) return; S_StartSound(player->mo, sfx_punch); // turn to face target player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); }
bool P_AlignFlat (int linenum, int side, int fc) { line_t *line = lines + linenum; sector_t *sec = side ? line->backsector : line->frontsector; if (!sec) return false; fixed_t x = line->v1->x; fixed_t y = line->v1->y; angle_t angle = R_PointToAngle2 (x, y, line->v2->x, line->v2->y); angle_t norm = (angle-ANGLE_90) >> ANGLETOFINESHIFT; fixed_t dist = -DMulScale16 (finecosine[norm], x, finesine[norm], y); if (side) { angle = angle + ANGLE_180; dist = -dist; } sec->SetBase(fc, dist & ((1<<(FRACBITS+8))-1), 0-angle); return true; }
angle_t DCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd) { fixed_t dist; angle_t ang; AActor *actor; int m; SetBodyAt (bot->x + FixedMul(bot->momx, 5*FRACUNIT), bot->y + FixedMul(bot->momy, 5*FRACUNIT), bot->z + (bot->height / 2), 2); actor = bglobal.body2; dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y); if (dist < SAFE_SELF_MISDIST) return 0; //Predict. m = (((dist+1)/FRACUNIT) / GetDefault<ARocket>()->Speed); SetBodyAt (enemy->x + FixedMul (enemy->momx, (m+2*FRACUNIT)), enemy->y + FixedMul(enemy->momy, (m+2*FRACUNIT)), ONFLOORZ, 1); dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y); //try the predicted location if (P_CheckSight (actor, bglobal.body1, 1)) //See the predicted location, so give a test missile { if (SafeCheckPosition (bot, actor->x, actor->y)) { if (FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST) { ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y); return ang; } } } //Try fire straight. if (P_CheckSight (actor, enemy, 0)) { if (FakeFire (bot, enemy, cmd) >= SAFE_SELF_MISDIST) { ang = R_PointToAngle2(bot->x, bot->y, enemy->x, enemy->y); return ang; } } return 0; }
// // P_WallMomSlide // Adjusts the xmove / ymove // so that the next move will slide along the wall. // static void P_WallMomSlide(line_t *ld) { int side; angle_t lineangle; angle_t moveangle; angle_t deltaangle; fixed_t movelen; fixed_t newlen; // First check the simple cases. if(ld->slopetype == ST_HORIZONTAL) { tmymove = 0; return; } if(ld->slopetype == ST_VERTICAL) { tmxmove = 0; return; } side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); if(side == 1) lineangle += ANG180; moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); deltaangle = moveangle - lineangle; if(deltaangle > ANG180) deltaangle += ANG180; lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT; movelen = P_ApproxDistance(tmxmove, tmymove); newlen = FixedMul(movelen, finecosine[deltaangle]); tmxmove = FixedMul(newlen, finecosine[lineangle]); tmymove = FixedMul(newlen, finesine[lineangle]); }
//doesnt check LOS, checks visibility with a set view angle. //B_Checksight checks LOS (straight line) //---------------------------------------------------------------------- //Check if mo1 has free line to mo2 //and if mo2 is within mo1 viewangle (vangle) given with normal degrees. //if these conditions are true, the function returns true. //GOOD TO KNOW is that the player's view angle //in doom is 90 degrees infront. bool DCajunMaster::Check_LOS (AActor *from, AActor *to, angle_t vangle) { if (!P_CheckSight (from, to, 2)) return false; // out of sight if (vangle == ANGLE_MAX) return true; if (vangle == 0) return false; //Looker seems to be blind. return abs (R_PointToAngle2 (from->x, from->y, to->x, to->y) - from->angle) <= vangle/2; }
void A_FiredChase (AActor *actor) { int weaveindex = actor->special1; AActor *target = actor->target; angle_t ang; fixed_t dist; if (actor->reactiontime) actor->reactiontime--; if (actor->threshold) actor->threshold--; // Float up and down actor->z += FloatBobOffsets[weaveindex]; actor->special1 = (weaveindex+2)&63; // Ensure it stays above certain height if (actor->z < actor->floorz + (64*FRACUNIT)) { actor->z += 2*FRACUNIT; } if(!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { // Invalid target P_LookForPlayers (actor,true); return; } // Strafe if (actor->special2 > 0) { actor->special2--; } else { actor->special2 = 0; actor->momx = actor->momy = 0; dist = P_AproxDistance (actor->x - target->x, actor->y - target->y); if (dist < FIREDEMON_ATTACK_RANGE) { if (pr_firedemonchase() < 30) { ang = R_PointToAngle2 (actor->x, actor->y, target->x, target->y); if (pr_firedemonchase() < 128) ang += ANGLE_90; else ang -= ANGLE_90; ang >>= ANGLETOFINESHIFT; actor->momx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]); actor->momy = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]); actor->special2 = 3; // strafe time } } }
DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) { int weaveindex = self->special1; AActor *target = self->target; angle_t ang; fixed_t dist; if (self->reactiontime) self->reactiontime--; if (self->threshold) self->threshold--; // Float up and down self->z += finesine[weaveindex << BOBTOFINESHIFT] * 8; self->special1 = (weaveindex + 2) & 63; // Ensure it stays above certain height if (self->z < self->floorz + (64*FRACUNIT)) { self->z += 2*FRACUNIT; } if(!self->target || !(self->target->flags&MF_SHOOTABLE)) { // Invalid target P_LookForPlayers (self,true, NULL); return; } // Strafe if (self->special2 > 0) { self->special2--; } else { self->special2 = 0; self->velx = self->vely = 0; dist = P_AproxDistance (self->x - target->x, self->y - target->y); if (dist < FIREDEMON_ATTACK_RANGE) { if (pr_firedemonchase() < 30) { ang = R_PointToAngle2 (self->x, self->y, target->x, target->y); if (pr_firedemonchase() < 128) ang += ANGLE_90; else ang -= ANGLE_90; ang >>= ANGLETOFINESHIFT; self->velx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]); self->vely = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]); self->special2 = 3; // strafe time } } }
void A_Saw(player_t *player, pspdef_t *psp) { int slope, damage; angle_t angle; int t; CHECK_WEAPON_CODEPOINTER("A_Saw", player); damage = 2*(P_Random(pr_saw)%10+1); angle = player->mo->angle; // killough 5/5/98: remove dependence on order of evaluation: t = P_Random(pr_saw); angle += (t - P_Random(pr_saw))<<18; /* Use meleerange + 1 so that the puff doesn't skip the flash * killough 8/2/98: make autoaiming prefer enemies */ if (!mbf_features || (slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, MF_FRIEND), !linetarget)) slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, 0); P_LineAttack(player->mo, angle, MELEERANGE+1, slope, damage); if (!linetarget) { S_StartSound(player->mo, sfx_sawful); return; } S_StartSound(player->mo, sfx_sawhit); // turn to face target angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); if (angle - player->mo->angle > ANG180) { if (angle - player->mo->angle < -ANG90/20) player->mo->angle = angle + ANG90/21; else player->mo->angle -= ANG90/20; } else { if (angle - player->mo->angle > ANG90/20) player->mo->angle = angle - ANG90/21; else player->mo->angle += ANG90/20; } player->mo->flags |= MF_JUSTATTACKED; R_SmoothPlaying_Reset(player); // e6y }
static void ST_DrawDamageMarkers(void) { damagemarker_t *dmgmarker; for (dmgmarker = dmgmarkers.next; dmgmarker != &dmgmarkers; dmgmarker = dmgmarker->next) { static vtx_t v[3]; player_t *p; float angle; byte alpha; GL_SetState(GLSTATE_BLEND, 1); GL_SetOrtho(0); alpha = (dmgmarker->tics << 3); if (alpha < 0) alpha = 0; v[0].x = -8; v[0].a = alpha; v[1].x = 8; v[1].a = alpha; v[2].y = 4; v[2].r = 255; v[2].a = alpha; p = &players[consoleplayer]; angle = (float)TRUEANGLES(p->mo->angle - R_PointToAngle2(dmgmarker->source->x, dmgmarker->source->y, p->mo->x, p->mo->y)); dglPushMatrix(); dglTranslatef(160, 120, 0); dglRotatef(angle, 0.0f, 0.0f, 1.0f); dglTranslatef(0, 16, 0); dglDisable(GL_TEXTURE_2D); dglSetVertex(v); dglTriangle(0, 1, 2); dglDrawGeometry(3, v); dglEnable(GL_TEXTURE_2D); dglPopMatrix(); GL_ResetViewport(); GL_SetState(GLSTATE_BLEND, 0); } }
DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck) { int i; for(i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) { AActor *pmo = players[i].mo; if (P_CheckSight (self, pmo) && (abs (R_PointToAngle2 (pmo->x, pmo->y, self->x, self->y) - pmo->angle) <= ANGLE_45)) { // Previous state (pottery bit waiting state) self->SetState (self->state - 1); return; } } } }
void A_Saw(player_t* player, pspdef_t* psp) { angle_t angle; int damage; int slope = 0; damage = ((P_Random() & 7) + 1) * 3; angle = player->mo->angle; angle += P_RandomShift(18); // use meleerange + 1 se the puff doesn't skip the flash slope = P_AimLineAttack(player->mo, angle, 0, MELEERANGE+1); P_LineAttack(player->mo, angle, MELEERANGE + 1, slope, damage); if(!linetarget) { S_StartSound (player->mo, sfx_saw1); return; } S_StartSound (player->mo, sfx_saw2); // turn to face target angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); if(angle - player->mo->angle > ANG180) { if(angle - player->mo->angle < -ANG90/20) player->mo->angle = angle + ANG90/21; else player->mo->angle -= ANG90/20; } else { if(angle - player->mo->angle > ANG90/20) player->mo->angle = angle - ANG90/21; else player->mo->angle += ANG90/20; } player->mo->flags |= MF_JUSTATTACKED; }
// // A_Punch // void A_Punch(player_t *player, pspdef_t *psp) { int damage = (P_Random() % 10 + 1) << 1; angle_t angle = player->mo->angle + ((P_Random() - P_Random()) << 18); int slope = P_AimLineAttack(player->mo, angle, MELEERANGE); if (player->powers[pw_strength]) damage *= 10; P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); if (!linetarget) return; S_StartSound(player->mo, sfx_punch); // turn to face target player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); }
// // A_Punch // DEFINE_ACTION_FUNCTION(AActor, A_Punch) { angle_t angle; int damage; int pitch; AActor *linetarget; if (self->player != NULL) { AWeapon *weapon = self->player->ReadyWeapon; if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO)) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return; } } damage = (pr_punch()%10+1)<<1; if (self->FindInventory<APowerStrength>()) damage *= 10; angle = self->angle; angle += pr_punch.Random2() << 18; pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &linetarget); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y); } }
OVERLAY void A_Saw(player_t *player, pspdef_t *psp) { int slope, damage = 2*(P_Random(pr_saw)%10+1); angle_t angle = player->mo->angle; // killough 5/5/98: remove dependence on order of evaluation: int t = P_Random(pr_saw); angle += (t - P_Random(pr_saw))<<18; // Use meleerange + 1 so that the puff doesn't skip the flash slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1); P_LineAttack(player->mo, angle, MELEERANGE+1, slope, damage); if (!linetarget) { S_StartSound(player->mo, sfx_sawful); return; } S_StartSound(player->mo, sfx_sawhit); // turn to face target angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); if (angle - player->mo->angle > ANG180) { if (angle - player->mo->angle < -ANG90/20) player->mo->angle = angle + ANG90/21; else player->mo->angle -= ANG90/20; } else { if (angle - player->mo->angle > ANG90/20) player->mo->angle = angle - ANG90/21; else player->mo->angle += ANG90/20; } player->mo->flags |= MF_JUSTATTACKED; }
void AdjustPlayerAngle (AActor *pmo) { angle_t angle; int difference; angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y); difference = (int)angle - (int)pmo->angle; if (abs(difference) > MAX_ANGLE_ADJUST) { if (difference > 0) { pmo->angle += MAX_ANGLE_ADJUST; } else { pmo->angle -= MAX_ANGLE_ADJUST; } } else { pmo->angle = angle; } }
static void MarinePunch(AActor *self, int damagemul) { angle_t angle; int damage; int pitch; AActor *linetarget; // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; damage = ((pr_m_punch()%10+1) << 1) * damagemul; A_FaceTarget (self); angle = self->angle + (pr_m_punch.Random2() << 18); pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget); P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true); // turn to face target if (linetarget) { S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "*fist", 1, ATTN_NORM ); self->angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y); } }
bool APathFollower::Interpolate () { fixed_t dx = 0, dy = 0, dz = 0; if ((args[2] & 8) && Time > 0.f) { dx = x; dy = y; dz = z; } if (CurrNode->Next==NULL) return false; UnlinkFromWorld (); if (args[2] & 1) { // linear x = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->x), FIXED2FLOAT(CurrNode->Next->x))); y = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->y), FIXED2FLOAT(CurrNode->Next->y))); z = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->z), FIXED2FLOAT(CurrNode->Next->z))); } else { // spline if (CurrNode->Next->Next==NULL) return false; x = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->x), FIXED2FLOAT(CurrNode->x), FIXED2FLOAT(CurrNode->Next->x), FIXED2FLOAT(CurrNode->Next->Next->x))); y = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->y), FIXED2FLOAT(CurrNode->y), FIXED2FLOAT(CurrNode->Next->y), FIXED2FLOAT(CurrNode->Next->Next->y))); z = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->z), FIXED2FLOAT(CurrNode->z), FIXED2FLOAT(CurrNode->Next->z), FIXED2FLOAT(CurrNode->Next->Next->z))); } LinkToWorld (); if (args[2] & 6) { if (args[2] & 8) { if (args[2] & 1) { // linear dx = CurrNode->Next->x - CurrNode->x; dy = CurrNode->Next->y - CurrNode->y; dz = CurrNode->Next->z - CurrNode->z; } else if (Time > 0.f) { // spline dx = x - dx; dy = y - dy; dz = z - dz; } else { int realarg = args[2]; args[2] &= ~(2|4|8); Time += 0.1f; dx = x; dy = y; dz = z; Interpolate (); Time -= 0.1f; args[2] = realarg; dx = x - dx; dy = y - dy; dz = z - dz; x -= dx; y -= dy; z -= dz; } if (args[2] & 2) { // adjust yaw angle = R_PointToAngle2 (0, 0, dx, dy); } if (args[2] & 4) { // adjust pitch; use floats for precision float fdx = FIXED2FLOAT(dx); float fdy = FIXED2FLOAT(dy); float fdz = FIXED2FLOAT(-dz); float dist = (float)sqrt (fdx*fdx + fdy*fdy); float ang = dist != 0.f ? (float)atan2 (fdz, dist) : 0; pitch = (angle_t)(ang * 2147483648.f / PI); } } else { if (args[2] & 2) { // interpolate angle float angle1 = (float)CurrNode->angle; float angle2 = (float)CurrNode->Next->angle; if (angle2 - angle1 <= -2147483648.f) { float lerped = Lerp (angle1, angle2 + 4294967296.f); if (lerped >= 4294967296.f) { angle = (angle_t)(lerped - 4294967296.f); } else { angle = (angle_t)lerped; } } else if (angle2 - angle1 >= 2147483648.f) { float lerped = Lerp (angle1, angle2 - 4294967296.f); if (lerped < 0.f) { angle = (angle_t)(lerped + 4294967296.f); } else { angle = (angle_t)lerped; } } else { angle = (angle_t)Lerp (angle1, angle2); } } if (args[2] & 1) { // linear if (args[2] & 4) { // interpolate pitch pitch = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch))); } } else { // spline if (args[2] & 4) { // interpolate pitch pitch = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->pitch), FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch), FIXED2FLOAT(CurrNode->Next->Next->pitch))); } } } } return true; }
// // P_DialogStart // // villsa [STRIFE] New function // void P_DialogStart(player_t *player) { int i = 0; int pic; int rnd = 0; char* byetext; int jumptoconv; if(menuactive || netgame) return; // are we facing towards our NPC? P_AimLineAttack(player->mo, player->mo->angle, (128*FRACUNIT)); if(!linetarget) { P_AimLineAttack(player->mo, player->mo->angle + (ANG90/16), (128*FRACUNIT)); if(!linetarget) P_AimLineAttack(player->mo, player->mo->angle - (ANG90/16), (128*FRACUNIT)); } if(!linetarget) return; // already in combat, can't talk to it if(linetarget->flags & MF_NODIALOG) return; // set pointer to the character talking dialogtalker = linetarget; // play a sound if(player == &players[consoleplayer]) S_StartSound(0, sfx_radio); linetarget->target = player->mo; // target the player dialogtalker->reactiontime = 2; // set reactiontime dialogtalkerangle = dialogtalker->angle; // remember original angle // face talker towards player A_FaceTarget(dialogtalker); // face towards NPC's direction player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, dialogtalker->x, dialogtalker->y); // set pointer to player talking dialogplayer = player; // haleyjd 09/08/10: get any stored dialog state from this object jumptoconv = linetarget->miscdata; // check item requirements while(1) { int i = 0; currentdialog = P_DialogFind(linetarget->type, jumptoconv); // dialog's jumptoconv equal to 0? There's nothing to jump to. if(currentdialog->jumptoconv == 0) break; // villsa 09/08/10: converted into for loop for(i = 0; i < MDLG_MAXITEMS; i++) { // if the item is non-zero, the player must have at least one in his // or her inventory if(currentdialog->checkitem[i] != 0 && P_PlayerHasItem(dialogplayer, currentdialog->checkitem[i]) < 1) break; } if(i < MDLG_MAXITEMS) // didn't find them all? this is our dialog! break; jumptoconv = currentdialog->jumptoconv; } M_DialogDimMsg(20, 28, currentdialog->text, false); dialogtext = P_DialogGetMsg(currentdialog->text); // get states dialogtalkerstates = P_DialogGetStates(linetarget->type); // have talker greet the player if(dialogtalkerstates->greet) P_SetMobjState(dialogtalker, dialogtalkerstates->greet); // get talker's name if(currentdialog->name[0]) dialogname = currentdialog->name; else { // use a fallback: if(mobjinfo[linetarget->type].name) dialogname = DEH_String(mobjinfo[linetarget->type].name); // mobjtype name else dialogname = DEH_String("Person"); // default name - like Joe in Doom 3 :P } // setup number of choices to choose from for(i = 0; i < MDLG_MAXCHOICES; i++) { if(!currentdialog->choices[i].giveitem) break; } // set number of choices to menu dialogmenu.numitems = i + 1; rnd = M_Random() % 3; // setup dialog menu M_StartControlPanel(); menupause = false; menuindialog = true; menupausetime = gametic + 17; currentMenu = &dialogmenu; if(i >= dialogmenu.lastOn) itemOn = dialogmenu.lastOn; else itemOn = 0; // get backdrop pic = W_CheckNumForName(currentdialog->backpic); dialogbgpiclumpnum = pic; if(pic != -1) V_DrawPatchDirect(0, 0, W_CacheLumpNum(pic, PU_CACHE)); // get voice I_StartVoice(currentdialog->voice); // get bye text switch(rnd) { case 2: byetext = DEH_String("BYE!"); break; case 1: byetext = DEH_String("Thanks, Bye!"); break; default: case 0: byetext = DEH_String("See you later!"); break; } DEH_snprintf(dialoglastmsgbuffer, sizeof(dialoglastmsgbuffer), "%d) %s", i + 1, byetext); }
// // P_DialogDrawer // // This function is set as the drawer callback for the dialog menu. // static void P_DialogDrawer(void) { angle_t angle; int y; int i; int height; int finaly; char choicetext[64]; char choicetext2[64]; // Run down bonuscount faster than usual so that flashes from being given // items are less obvious. if(dialogplayer->bonuscount) { dialogplayer->bonuscount -= 3; if(dialogplayer->bonuscount < 0) dialogplayer->bonuscount = 0; } angle = R_PointToAngle2(dialogplayer->mo->x, dialogplayer->mo->y, dialogtalker->x, dialogtalker->y); angle -= dialogplayer->mo->angle; // Dismiss the dialog if the player is out of alignment, or the thing he was // talking to is now engaged in battle. if ((angle > ANG45 && angle < (ANG270+ANG45)) || (dialogtalker->flags & MF_NODIALOG) != 0) { P_DialogDoChoice(dialogmenu.numitems - 1); } dialogtalker->reactiontime = 2; // draw background if(dialogbgpiclumpnum != -1) { patch_t *patch = W_CacheLumpNum(dialogbgpiclumpnum, PU_CACHE); V_DrawPatchDirect(0, 0, patch); } // if there's a valid background pic, delay drawing the rest of the menu // for a while; otherwise, it will appear immediately if(dialogbgpiclumpnum == -1 || menupausetime <= gametic) { if(menuindialog) { // time to pause the game? if(menupausetime + 3 < gametic) menupause = true; } // draw character name M_WriteText(12, 18, dialogname); y = 28; // show text (optional for dialogs with voices) if(dialogshowtext || currentdialog->voice[0] == '\0') y = M_WriteText(20, 28, dialogtext); height = 20 * dialogmenu.numitems; finaly = 175 - height; // preferred height if(y > finaly) finaly = 199 - height; // height it will bump down to if necessary. // draw divider M_WriteText(42, finaly - 6, DEH_String("______________________________")); dialogmenu.y = finaly + 6; y = 0; // draw the menu items for(i = 0; i < dialogmenu.numitems - 1; i++) { DEH_snprintf(choicetext, sizeof(choicetext), "%d) %s", i + 1, currentdialog->choices[i].text); // alternate text for items that need money if(currentdialog->choices[i].needamounts[0] > 0) { // haleyjd 20120401: necessary to avoid undefined behavior: M_StringCopy(choicetext2, choicetext, sizeof(choicetext2)); DEH_snprintf(choicetext, sizeof(choicetext), "%s for %d", choicetext2, currentdialog->choices[i].needamounts[0]); } M_WriteText(dialogmenu.x, dialogmenu.y + 3 + y, choicetext); y += 19; } // draw the final item for dismissing the dialog M_WriteText(dialogmenu.x, 19 * i + dialogmenu.y + 3, dialoglastmsgbuffer); } }
// // This is a not-very-pretty routine which handles // the face states and their timing. // the precedence of expressions is: // dead > evil grin > turned head > straight ahead // void ST_updateFaceWidget(void) { int i; angle_t badguyangle; angle_t diffang; static int lastattackdown = -1; static int priority = 0; boolean doevilgrin; if (priority < 10) { // dead if (!plyr->health) { priority = 9; st_faceindex = ST_DEADFACE; st_facecount = 1; } } if (priority < 9) { if (plyr->bonuscount) { // picking up bonus doevilgrin = false; for (i=0;i<NUMWEAPONS;i++) { if (oldweaponsowned[i] != plyr->weaponowned[i]) { doevilgrin = true; oldweaponsowned[i] = plyr->weaponowned[i]; } } if (doevilgrin) { // evil grin if just picked up weapon priority = 8; st_facecount = ST_EVILGRINCOUNT; st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET; } } } if (priority < 8) { if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo) { // being attacked priority = 7; if (plyr->health - st_oldhealth > ST_MUCHPAIN) { st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { badguyangle = R_PointToAngle2(plyr->mo->x, plyr->mo->y, plyr->attacker->x, plyr->attacker->y); if (badguyangle > plyr->mo->angle) { // whether right or left diffang = badguyangle - plyr->mo->angle; i = diffang > ANG180; } else { // whether left or right diffang = plyr->mo->angle - badguyangle; i = diffang <= ANG180; } // confusing, aint it? st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset(); if (diffang < ANG45) { // head-on st_faceindex += ST_RAMPAGEOFFSET; } else if (i) { // turn face right st_faceindex += ST_TURNOFFSET; } else { // turn face left st_faceindex += ST_TURNOFFSET+1; } } } } if (priority < 7) { // getting hurt because of your own damn stupidity if (plyr->damagecount) { if (plyr->health - st_oldhealth > ST_MUCHPAIN) { priority = 7; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { priority = 6; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; } } } if (priority < 6) { // rapid firing if (plyr->attackdown) { if (lastattackdown==-1) lastattackdown = ST_RAMPAGEDELAY; else if (!--lastattackdown) { priority = 5; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; st_facecount = 1; lastattackdown = 1; } } else lastattackdown = -1; } if (priority < 5) { // invulnerability if ((plyr->cheats & CF_GODMODE) || plyr->powers[pw_invulnerability]) { priority = 4; st_faceindex = ST_GODFACE; st_facecount = 1; } } // look left or look right if the facecount has timed out if (!st_facecount) { st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3); st_facecount = ST_STRAIGHTFACECOUNT; priority = 0; } st_facecount--; }
DEFINE_ACTION_FUNCTION(AActor, A_M_Saw) { // [BC] Don't do this in client mode. if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) || ( CLIENTDEMO_IsPlaying( ))) { return; } if (self->target == NULL) return; A_FaceTarget (self); if (self->CheckMeleeRange ()) { angle_t angle; int damage; AActor *linetarget; damage = 2 * (pr_m_saw()%10+1); angle = self->angle + (pr_m_saw.Random2() << 18); P_LineAttack (self, angle, MELEERANGE+1, P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage, NAME_Melee, NAME_BulletPuff); if (!linetarget) { S_Sound (self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM ); return; } S_Sound (self, CHAN_WEAPON, "weapons/sawhit", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawhit", 1, ATTN_NORM ); // turn to face target angle = R_PointToAngle2 (self->x, self->y, linetarget->x, linetarget->y); if (angle - self->angle > ANG180) { if (angle - self->angle < (angle_t)(-ANG90/20)) self->angle = angle + ANG90/21; else self->angle -= ANG90/20; } else { if (angle - self->angle > ANG90/20) self->angle = angle - ANG90/21; else self->angle += ANG90/20; } } else { S_Sound (self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM); // [BC] If we're the server, tell clients to play this sound. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_SoundActor( self, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM ); } //A_Chase (self); }
void P_StartConversation (AActor *npc, AActor *pc) { FStrifeDialogueReply *reply; menuitem_t item; const char *toSay; int i, j; pc->momx = pc->momy = 0; // Stop moving pc->player->momx = pc->player->momy = 0; if (pc->player - players != consoleplayer) return; ConversationPC = pc; ConversationNPC = npc; CurNode = npc->Conversation; if (pc->player == &players[consoleplayer]) { S_Sound (CHAN_VOICE, "misc/chat", 1, ATTN_NONE); } npc->reactiontime = 2; if (!(npc->flags & MF_FRIENDLY) && !(npc->flags4 & MF4_NOHATEPLAYERS)) { npc->target = pc; } ConversationNPCAngle = npc->angle; A_FaceTarget (npc); pc->angle = R_PointToAngle2 (pc->x, pc->y, npc->x, npc->y); // Check if we should jump to another node while (CurNode->ItemCheck[0] != NULL) { if (CheckStrifeItem (CurNode->ItemCheck[0]) && CheckStrifeItem (CurNode->ItemCheck[1]) && CheckStrifeItem (CurNode->ItemCheck[2])) { int root = FindNode (ConversationNPC->GetDefault()->Conversation); CurNode = StrifeDialogues[root + CurNode->ItemCheckNode - 1]; } else { break; } } if (CurNode->SpeakerVoice != 0) { S_SoundID (npc, CHAN_VOICE, CurNode->SpeakerVoice, 1, ATTN_NORM); } // Set up the menu ConversationMenu.PreDraw = DrawConversationMenu; ConversationMenu.EscapeHandler = CleanupConversationMenu; // Format the speaker's message. toSay = CurNode->Dialogue; if (strncmp (toSay, "RANDOM_", 7) == 0) { for (i = 0; i < NUM_RANDOM_TALKERS; ++i) { if (strcmp (RandomLines[i][0], toSay + 7) == 0) { toSay = RandomLines[i][1 + (pr_randomspeech() % NUM_RANDOM_LINES)]; break; } } } DialogueLines = V_BreakLines (screen->GetWidth()/CleanXfac-24*2, toSay); // Fill out the possible choices ShowGold = false; item.type = numberedmore; item.e.mfunc = PickConversationReply; for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next) { if (reply->Reply == NULL) { continue; } ShowGold |= reply->NeedsGold; reply->ReplyLines = V_BreakLines (320-50-10, reply->Reply); for (j = 0; reply->ReplyLines[j].width != -1; ++j) { item.label = reply->ReplyLines[j].string; item.b.position = j == 0 ? i : 0; item.c.extra = reply; ConversationItems.Push (item); } ++i; } item.label = RandomGoodbyes[pr_randomspeech() % NUM_RANDOM_GOODBYES]; item.b.position = i; item.c.extra = NULL; ConversationItems.Push (item); // Determine where the top of the reply list should be positioned. i = (gameinfo.gametype & GAME_Raven) ? 9 : 8; ConversationMenu.y = MIN<int> (140, 192 - ConversationItems.Size() * i); for (i = 0; DialogueLines[i].width != -1; ++i) { } i = 44 + i * 10; if (ConversationMenu.y - 100 < i - screen->GetHeight() / CleanYfac / 2) { ConversationMenu.y = i - screen->GetHeight() / CleanYfac / 2 + 100; } ConversationMenu.indent = 50; // Finish setting up the menu ConversationMenu.items = &ConversationItems[0]; ConversationMenu.numitems = ConversationItems.Size(); if (CurNode != PrevNode) { // Only reset the selection if showing a different menu. ConversationMenu.lastOn = 0; PrevNode = CurNode; } ConversationMenu.DontDim = true; // And open the menu M_StartControlPanel (false); OptionsActive = true; menuactive = MENU_OnNoPause; ConversationPauseTic = gametic + 20; M_SwitchMenu (&ConversationMenu); }