void walkmonster_start_go(edict_t *self) { if (!(self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) && (level.time < 1)) { M_droptofloor(self); if (self->groundentity) { if (!M_walkmove(self, 0, 0)) { gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin)); } } } if (!self->yaw_speed) { self->yaw_speed = 20; } self->viewheight = 25; monster_start_go(self); if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) { monster_triggered_start(self); } }
/* ============= ai_run_slide Strafe sideways, but stay at aproximately the same range ============= */ void ai_run_slide(edict_t *self, float distance) { float ofs; self->ideal_yaw = enemy_yaw; M_ChangeYaw (self); if (self->monsterinfo.lefty) ofs = 90; else ofs = -90; if (M_walkmove (self, self->ideal_yaw + ofs, distance)) return; self->monsterinfo.lefty = 1 - self->monsterinfo.lefty; M_walkmove (self, self->ideal_yaw - ofs, distance); }
/* ============= ai_turn don't move, but turn towards ideal_yaw Distance is for slight position adjustments needed by the animations ============= */ void ai_turn (edict_t *self, float dist) { if (dist) M_walkmove (self, self->s.angles[YAW], dist); if (FindTarget (self)) return; M_ChangeYaw (self); }
void ai_move2 (edict_t *self, float dist) { vec3_t v; if (dist) M_walkmove (self, self->s.angles[YAW], dist); VectorSubtract (self->goalentity->s.origin, self->s.origin, v); self->ideal_yaw = vectoyaw(v); M_ChangeYaw (self); };
/* ============= ai_charge Turns towards target and advances Use this call with a distnace of 0 to replace ai_face ============== */ void ai_charge (edict_t *self, float dist) { vec3_t v; VectorSubtract (self->enemy->s.origin, self->s.origin, v); self->ideal_yaw = vectoyaw(v); M_ChangeYaw (self); if (dist) M_walkmove (self, self->s.angles[YAW], dist); }
void barrel_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { float ratio; vec3_t v; if ((!other->groundentity) || (other->groundentity == self)) return; ratio = (float)other->mass / (float)self->mass; VectorSubtract (self->s.origin, other->s.origin, v); M_walkmove (self, vectoyaw(v), 20 * ratio * FRAMETIME); }
void flymonster_start_go(edict_t *self){ if(!M_walkmove(self, 0, 0)) gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin)); if(!self->yaw_speed) self->yaw_speed = 10; self->viewheight = 25; monster_start_go(self); if(self->spawnflags & 2) monster_triggered_start(self); }
/* ============= ai_stand Used for standing around and looking for players Distance is for slight position adjustments needed by the animations ============== */ void ai_stand (edict_t *self, float dist) { vec3_t v; if (dist) M_walkmove (self, self->s.angles[YAW], dist); if (self->monsterinfo.aiflags & AI_STAND_GROUND) { if (self->enemy) { VectorSubtract (self->enemy->s.origin, self->s.origin, v); self->ideal_yaw = vectoyaw(v); if (self->s.angles[YAW] != self->ideal_yaw && self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND) { self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); self->monsterinfo.run (self); } M_ChangeYaw (self); ai_checkattack (self, 0); } else FindTarget (self); return; } if (FindTarget (self)) return; if (level.time > self->monsterinfo.pausetime) { self->monsterinfo.walk (self); return; } if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time)) { if (self->monsterinfo.idle_time) { self->monsterinfo.idle (self); self->monsterinfo.idle_time = level.time + 15000 + random() * 15000; } else { self->monsterinfo.idle_time = level.time + random() * 15000; } } }
void flymonster_start_go (edict_t *self) { if (!M_walkmove (self, 0, 0)) gi.dprintf ("%s in solid at %s\n", self->classname, vtos(self->s.origin)); if (!self->yaw_speed) self->yaw_speed = 10; self->viewheight = 25; self->monsterinfo.flies = 0.0; monster_start_go (self); if (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) monster_triggered_start (self); }
void walkmonster_start_go(edict_t *self){ if(!(self->spawnflags & 2) && level.time < 1){ M_droptofloor(self); if(self->groundentity) if(!M_walkmove(self, 0, 0)) gi.dprintf("%s in solid at %s\n", self->classname, vtos(self->s.origin)); } if(!self->yaw_speed) self->yaw_speed = 20; self->viewheight = 25; monster_start_go(self); if(self->spawnflags & 2) monster_triggered_start(self); }
/* ============= ai_schoolStand Used for standing around and looking for players / schooling monsters of the same type. Distance is for slight position adjustments needed by the animations ============== */ void ai_schoolStand (edict_t *self, float dist) { float speed; if(!(self->monsterinfo.aiflags & AI_SCHOOLING)) { ai_stand(self, dist); return; } // init school var's for this frame self->zRaduisList = NULL; if(self->enemy || FindTarget(self)) { ai_stand(self, dist); return; } else { // run schooling routines switch(zSchoolMonsters(self, dist, 0, &speed)) { case 1: self->monsterinfo.walk (self); break; case 2: self->monsterinfo.run (self); break; } } // do the normal stand stuff if (dist) M_walkmove (self, self->ideal_yaw, dist); }
void boss_update (edict_t *ent, usercmd_t *ucmd) { int div=15, forwardspeed, sidespeed, maxspeed; int frames=0; vec3_t forward, right, angles; edict_t *boss; boss = ent->owner; // make sure this is a valid boss entity if (!G_EntIsAlive(boss)) return; if (!IsABoss(boss) && (boss->mtype != P_TANK)) return; VectorCopy(ent->s.origin, ent->s.old_origin); // update player state //ent->client->ps.pmove.pm_type = PM_FREEZE; ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; //ent->client->ability_delay = level.time + FRAMETIME; // copy player angles to boss boss->s.angles[YAW] = ent->s.angles[YAW]; boss->s.angles[PITCH] = 0; boss->s.angles[ROLL] = 0; AngleVectors(boss->s.angles, forward, right, NULL); vectoangles(right, angles); // move player into position boss_position_player(ent, boss); // speed divider, lower is faster (ucmd is 400) if (boss->mtype == BOSS_TANK) div = 20; else if (boss->mtype == BOSS_MAKRON) div = 10; else div = 26; // speed limiter, dont allow client to speed cheat using higher cl_speeds maxspeed = 400; forwardspeed = ucmd->forwardmove; sidespeed = ucmd->sidemove; //gi.dprintf("%d %d\n", forwardspeed, sidespeed); if ((forwardspeed > 0) && forwardspeed > maxspeed) forwardspeed = maxspeed; else if (forwardspeed < -maxspeed) forwardspeed = -maxspeed; if ((sidespeed > 0) && sidespeed > maxspeed) sidespeed = maxspeed; else if (sidespeed < -maxspeed) sidespeed = -maxspeed; //4.2 allow superspeed if (ent->superspeed && (level.time > ent->lasthurt + DAMAGE_ESCAPE_DELAY)) { forwardspeed *= 3; sidespeed *= 3; maxspeed = 3*BOSS_MAXVELOCITY; } else if (boss->monsterinfo.air_frames)// used for boost maxspeed = 9999; else maxspeed = BOSS_MAXVELOCITY; if (level.framenum >= boss->count) { if (!(ent->client->buttons & BUTTON_ATTACK)) { if (forwardspeed > 0) { M_walkmove(boss, boss->s.angles[YAW], forwardspeed/div); frames = FRAMES_RUN_FORWARD; } else if (forwardspeed < 0) { M_walkmove(boss, boss->s.angles[YAW], forwardspeed/div); frames = FRAMES_RUN_BACKWARD; } if (sidespeed > 0) { M_walkmove(boss, angles[YAW], sidespeed/div); frames = FRAMES_RUN_FORWARD; } else if (sidespeed < 0) { M_walkmove(boss, angles[YAW], sidespeed/div); frames = FRAMES_RUN_FORWARD; } } else { frames = FRAMES_ATTACK; } if (boss->groundentity) { boss->monsterinfo.air_frames = 0;//we're done boosting VectorClear(boss->velocity); if (ucmd->upmove > 0 && !ent->client->jump) { //gi.sound (ent, CHAN_WEAPON, gi.soundindex ("tank/sight1.wav"), 1, ATTN_NORM, 0); // jump in the direction we are trying to move boss->velocity[0] = 0.1*((forwardspeed*forward[0])+(sidespeed*right[0])); boss->velocity[1] = 0.1*((forwardspeed*forward[1])+(sidespeed*right[1])); boss->velocity[2] = 350; ent->client->jump = true; } boss->v_flags &= ~SFLG_DOUBLEJUMP; } else { if (ucmd->upmove < 1) ent->client->jump = false; if (CanDoubleJump(boss, ucmd)) { boss->velocity[2] += 350; boss->v_flags |= SFLG_DOUBLEJUMP; } // steer in the direction we are trying to move boss->velocity[0] += 0.1*((forwardspeed*forward[0])+(sidespeed*right[0])); boss->velocity[1] += 0.1*((forwardspeed*forward[1])+(sidespeed*right[1])); if (ucmd->upmove && (boss->waterlevel > 1)) { if (ucmd->upmove > 0) { if (boss->waterlevel == 2) boss->velocity[2] = 200; else if (boss->velocity[2] < 50) boss->velocity[2] = 50; } else { if (boss->velocity[2] > -50) boss->velocity[2] = -50; } } // don't move too fast if (boss->velocity[0] > maxspeed) boss->velocity[0] = maxspeed; if (boss->velocity[0] < -maxspeed) boss->velocity[0] = -maxspeed; if (boss->velocity[1] > maxspeed) boss->velocity[1] = maxspeed; if (boss->velocity[1] < -maxspeed) boss->velocity[1] = -maxspeed; } boss->style = frames; // set frame set boss should use gi.linkentity(boss); boss->count = level.framenum+1; } // move player into position //boss_position_player(ent, boss); // if we are standing on a live entity, call its touch function // this prevents player-bosses from being invulnerable to obstacles //FIXME: it may be dangerous to call a touch function without a NULL plane or surf /* if (boss->groundentity && G_EntIsAlive(boss->groundentity) && boss->groundentity->touch) boss->groundentity->touch(boss->groundentity, boss, NULL, NULL); */ }
/* ============= ai_move Move the specified distance at current facing. This replaces the QC functions: ai_forward, ai_back, ai_pain, and ai_painforward ============== */ void ai_move (edict_t *self, float dist) { M_walkmove (self, self->s.angles[YAW], dist); }