void CurseEffects (edict_t *self, int num, int color) { vec3_t start, up, angle; if ((level.framenum % 5) != 0) return; if (!G_EntIsAlive(self)) return; VectorCopy(self->s.angles, angle); angle[ROLL] = GetRandom(0, 20) - 10; angle[PITCH] = GetRandom(0, 20) - 10; AngleCheck(&angle[ROLL]); AngleCheck(&angle[PITCH]); AngleVectors(angle, NULL, NULL, up); // upside-down minisentry if (self->owner && (self->mtype == M_MINISENTRY) && (self->owner->style == SENTRY_FLIPPED)) VectorMA(self->s.origin, self->mins[2]-16, up, start); else VectorMA(self->s.origin, self->maxs[2]+16, up, start); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_LASER_SPARKS); gi.WriteByte(num); // number of sparks gi.WritePosition(start); gi.WriteDir(up); gi.WriteByte(color); // 242 = red, 210 = green, 2 = black gi.multicast(start, MULTICAST_PVS); }
bool IImpostorable::CheckToUpdateImpostor(bool &bRenderImpostor, const D3DXVECTOR3* pWorldUp, D3DXVECTOR3* pViewpointDif, float fDistanceScale, bool bForce) { if( (m_bUpdateImpostor && m_bUseImpostor) || bForce) { // Refresh impostor on LostDevice() etc. m_bUpdateImpostor = false; bRenderImpostor = m_bUseImpostor; return true; } float distance = fabs(pViewpointDif->x) + fabs(pViewpointDif->y) + fabs(pViewpointDif->z); if(distance < IMPOSTOR_DISTANCE_FACTOR * fDistanceScale) { // render actual object m_bUseImpostor = bRenderImpostor = false; return false; } m_bUseImpostor = bRenderImpostor = true; float diffUp, diffAt; AngleCheck(pWorldUp, &m_vecPrevWorldUp, pViewpointDif, &m_vecPrevLookAt, diffUp, diffAt); if(diffUp < IMPOSTOR_DELTA_UP_ANGLE_THRESH || diffAt < IMPOSTOR_DELTA_AT_ANGLE_THRESH || fabs(m_PrevDistance - distance) > IMPOSTOR_DELTA_DISTANCE_THRESH) { m_PrevDistance = distance; m_vecPrevWorldUp = *pWorldUp; m_vecPrevLookAt = *pViewpointDif; // already normalized return true; // Update Impostor } else // Render Old Impostor return false; }
qboolean CheckYawStep (edict_t *self, float minyaw, float maxyaw, float dist) { int i, max; float yaw; AngleCheck(&minyaw); AngleCheck(&maxyaw); // calculate the maximum yaw variance max = 360 - fabs(minyaw - maxyaw); // we will start at the minimum yaw angle and move towards maxyaw yaw = minyaw; for (i = 0; i < max; i += 30) { // if we changed course a while ago, then try a partial step 50% of the time if (level.time - self->monsterinfo.bump_delay > 1.0 || random() < 0.5) { yaw += i; AngleCheck(&yaw); if (SV_StepDirection(self, yaw, dist, true)) { //gi.dprintf("attempt small step\n"); return true; } } // otherwise, we might be stuck, so try a full step else { if (SV_StepDirection(self, i, dist, false)) { //gi.dprintf("attempt full step\n"); return true; } } } return false; }
void allymarker_think (edict_t *self) { vec3_t start, right; // must have an owner if (!self->owner || !self->owner->inuse || !self->owner->teamnum) { G_FreeEdict(self); return; } // beam diameter goes to 0 if we're dead or cloaked (to hide it) if ((self->owner->health < 1) || (self->owner->client->cloaking && self->owner->svflags & SVF_NOCLIENT) || (self->owner->flags & FL_WORMHOLE)) self->s.frame = 0; else self->s.frame = 4; self->s.skinnum = GetTeamColor(self->owner->teamnum); self->s.angles[YAW]+=18; AngleCheck(&self->s.angles[YAW]); AngleVectors(self->s.angles, NULL, right, NULL); if (PM_PlayerHasMonster(self->owner)) { VectorCopy(self->owner->owner->s.origin, start); start[2] = self->owner->owner->absmax[2]+16; } else { VectorCopy(self->owner->s.origin, start); start[2] = self->owner->absmax[2]+16; } VectorMA(start, 12, right, self->s.origin); VectorMA(start, -12, right, self->s.old_origin); gi.linkentity(self); self->nextthink = level.time + FRAMETIME; }
qboolean CanJumpUp (edict_t *self, vec3_t neworg, vec3_t end) { int jumpdist; vec3_t angles, start; trace_t tr; if (self->monsterinfo.jumpup < 1) return false; // we can't jump up! VectorCopy(neworg, start); jumpdist = 8;//STEPSIZE; for ( ; ; jumpdist += 8) { // we can't jump any higher if (jumpdist > self->monsterinfo.jumpup) return false; // each loop increments start position 1 step higher start[2] = neworg[2] + jumpdist; // trace to the floor (end position is always 1 step below floor) tr = gi.trace(start, self->mins, self->maxs, end, self, MASK_MONSTERSOLID); // we have cleared the obstacle! if (!tr.startsolid && !tr.allsolid) break; } // make sure we land on a flat plane vectoangles(tr.plane.normal, angles); AngleCheck(&angles[PITCH]); if (angles[PITCH] != 270) return false; VectorCopy(tr.endpos, self->s.origin); //gi.dprintf("allowed monster to jump up\n"); return true; }
/* =============== M_walkmove =============== */ qboolean M_walkmove (edict_t *ent, float yaw, float dist) { float original_yaw=yaw;//GHz vec3_t move; if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM))) return false; yaw = yaw*M_PI*2 / 360; move[0] = cos(yaw)*dist; move[1] = sin(yaw)*dist; move[2] = 0; if (IsABoss(ent) || ent->mtype == P_TANK) { //return M_Move(ent, move, true); if (!M_Move(ent, move, true)) { float angle1, angle2, delta1, delta2, cl_yaw, ideal_yaw, mult; vec3_t start, end, angles, right; trace_t tr; // get monster angles AngleVectors(ent->s.angles, NULL, right, NULL); //vectoangles(forward, forward); vectoangles(right, right); // get client yaw (FIXME: use mons yaw instead?) cl_yaw = ent->s.angles[YAW]; AngleCheck(&cl_yaw); // trace from monster to wall VectorCopy(ent->s.origin, start); VectorMA(start, 64, move, end); tr = gi.trace(start, ent->mins, ent->maxs, end, ent, MASK_SHOT); // get monster angles in relation to wall VectorCopy(tr.plane.normal, angles); vectoangles(angles, angles); // monster is moving sideways, so use sideways vector instead if ((int)original_yaw==(int)right[YAW]) { cl_yaw = right[YAW]; AngleCheck(&cl_yaw); } // delta between monster yaw and wall yaw should be no more than 90 degrees // else, turn wall angles around 180 degrees if (fabs(cl_yaw-angles[YAW]) > 90) angles[YAW]+=180; ValidateAngles(angles); // possible escape angle 1 angle1 = angles[YAW]+90; AngleCheck(&angle1); delta1 = fabs(angle1-cl_yaw); // possible escape angle 2 angle2 = angles[YAW]-90; AngleCheck(&angle2); delta2 = fabs(angle2-cl_yaw); // take the shorter route if (delta1 > delta2) { ideal_yaw = angle2; mult = 1.0-delta2/90.0; } else { ideal_yaw = angle1; mult = 1.0-delta1/90.0; } // go full speed if we are turned at least half way towards ideal yaw if (mult >= 0.5) mult = 1.0; // modify speed dist*=mult; // recalculate with new heading yaw = ideal_yaw*M_PI*2 / 360; move[0] = cos(yaw)*dist; move[1] = sin(yaw)*dist; move[2] = 0; //gi.dprintf("can't walk wall@%.1f you@%.1f ideal@%.1f\n", angles[YAW], cl_yaw, ideal_yaw); return M_Move(ent, move, true); } return true; } else if (level.time > ent->holdtime) // stay in-place for medic healing return SV_movestep(ent, move, true); else return false; }
void p_berserk_attack (edict_t *ent, int move_state) { int punch_dmg = BERSERK_PUNCH_INITIAL_DAMAGE + BERSERK_PUNCH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level; int slash_dmg = BERSERK_SLASH_INITIAL_DAMAGE + BERSERK_SLASH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level; int crush_dmg = BERSERK_CRUSH_INITIAL_DAMAGE + BERSERK_CRUSH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level; vec3_t forward, right, up, angles; ent->client->idle_frames = 0; AngleVectors(ent->s.angles, NULL, right, up); AngleVectors(ent->client->v_angle, forward, NULL, NULL); VectorCopy(ent->client->v_angle, angles); if (move_state == BERSERK_RUN_FORWARD) { G_RunFrames(ent, BERSERK_FRAMES_RUNATTACK1_START, BERSERK_FRAMES_RUNATTACK1_END, false); // swing left-right if (ent->s.frame == 124) { angles[YAW] += 20; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 125) { p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 126) { angles[YAW] -= 20; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } } else if (move_state == BERSERK_RUN_BACKWARD) { G_RunFrames(ent, BERSERK_FRAMES_RUNATTACK1_START, BERSERK_FRAMES_RUNATTACK1_END, true); // swing left-right if (ent->s.frame == 124) { angles[YAW] += 20; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 125) { p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 126) { angles[YAW] -= 20; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } } else if (ent->client->weapon_mode == 1) // slash { G_RunFrames(ent, BERSERK_FRAMES_SLASH_START, BERSERK_FRAMES_SLASH_END, false); if ((ent->s.frame == 79) || (ent->s.frame == 80)) p_berserk_melee(ent, forward, up, slash_dmg, BERSERK_SLASH_KNOCKBACK, BERSERK_SLASH_RANGE, MOD_BERSERK_SLASH); } else if (ent->client->weapon_mode == 2) // crush { G_RunFrames(ent, BERSERK_FRAMES_SLAM_START, BERSERK_FRAMES_SLAM_END, false); if (ent->s.frame == 154) p_berserk_crush(ent, crush_dmg, BERSERK_CRUSH_RANGE, MOD_BERSERK_CRUSH); } else // punch { G_RunFrames(ent, BERSERK_FRAMES_PUNCH_START, BERSERK_FRAMES_PUNCH_END, false); // swing left-right if (ent->s.frame == 66) { angles[YAW] += 20;//45; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 67) { p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } else if (ent->s.frame == 68) { angles[YAW] -= 20;//45; AngleCheck(&angles[YAW]); AngleVectors(angles, forward, NULL, NULL); p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH); } } p_berserk_swing(ent); }