/////////////////////////////////////////////////////////////////////// // Set bot to move to it's movetarget. (following node path) /////////////////////////////////////////////////////////////////////// void ACEMV_MoveToGoal(edict_t *self, usercmd_t *ucmd) { // If a rocket or grenade is around deal with it // Simple, but effective (could be rewritten to be more accurate) if(strcmp(self->movetarget->classname,"rocket")==0 || strcmp(self->movetarget->classname,"grenade")==0) { VectorSubtract (self->movetarget->s.origin, self->s.origin, self->move_vector); ACEMV_ChangeBotAngle(self); if(debug_mode) debug_printf("%s: Oh crap a rocket!\n",self->client->pers.netname); // strafe left/right if(rand()%1 && ACEMV_CanMove(self, MOVE_LEFT)) ucmd->sidemove = -400; else if(ACEMV_CanMove(self, MOVE_RIGHT)) ucmd->sidemove = 400; return; } else { // Set bot's movement direction VectorSubtract (self->movetarget->s.origin, self->s.origin, self->move_vector); ACEMV_ChangeBotAngle(self); ucmd->forwardmove = 400; return; } }
// Set bot to move to it's moveTarget. (following node path) void ACEMV_MoveToGoal(gentity_t * self) { // if a rocket or grenade is around deal with it // simple, but effective (could be rewritten to be more accurate) if((strcmp(self->bs.moveTarget->classname, "rocket") == 0 || strcmp(self->bs.moveTarget->classname, "grenade") == 0)) { VectorSubtract(self->bs.moveTarget->s.origin, self->client->ps.origin, self->bs.moveVector); ACEMV_ChangeBotAngle(self); if(ace_debug.integer) trap_SendServerCommand(-1, va("print \"%s: Oh crap a rocket!\n\"", self->client->pers.netname)); //trap_SendServerCommand(-1, va("%s \"%s%c%c%s\"", mode == SAY_TEAM ? "tchat" : "chat", name, Q_COLOR_ESCAPE, color, message)); // strafe left/right if(rand() % 1 && ACEMV_CanMove(self, MOVE_LEFT)) { self->client->pers.cmd.rightmove = -127; } else if(ACEMV_CanMove(self, MOVE_RIGHT)) { self->client->pers.cmd.rightmove = 127; } return; } else { // set bot's movement direction VectorSubtract(self->bs.moveTarget->s.origin, self->client->ps.origin, self->bs.moveVector); ACEMV_ChangeBotAngle(self); if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; return; } }
/////////////////////////////////////////////////////////////////////// // Main movement code. (following node path) /////////////////////////////////////////////////////////////////////// void ACEMV_Move(edict_t *self, usercmd_t *ucmd) { vec3_t dist; int current_node_type=-1; int next_node_type=-1; int i; // Get current and next node back from nav code. if(!ACEND_FollowPath(self)) { self->state = STATE_WANDER; self->wander_timeout = level.time + 1.0; return; } current_node_type = nodes[self->current_node].type; next_node_type = nodes[self->next_node].type; /////////////////////////// // Move To Goal /////////////////////////// if (self->movetarget) ACEMV_MoveToGoal(self,ucmd); //////////////////////////////////////////////////////// // Platforms /////////////////////////////////////////////////////// if(current_node_type != NODE_PLATFORM && next_node_type == NODE_PLATFORM) { // check to see if lift is down? for(i=0;i<num_items;i++) if(item_table[i].node == self->next_node) if(item_table[i].ent->moveinfo.state != STATE_BOTTOM) return; // Wait for elevator } if(current_node_type == NODE_PLATFORM && next_node_type == NODE_PLATFORM) { // Move to the center self->move_vector[2] = 0; // kill z movement if(VectorLength(self->move_vector) > 10) ucmd->forwardmove = 200; // walk to center ACEMV_ChangeBotAngle(self); return; // No move, riding elevator } //////////////////////////////////////////////////////// // Jumpto Nodes /////////////////////////////////////////////////////// if(next_node_type == NODE_JUMP || (current_node_type == NODE_JUMP && next_node_type != NODE_ITEM && nodes[self->next_node].origin[2] > self->s.origin[2])) { // Set up a jump move ucmd->forwardmove = 300; ucmd->upmove = 300; ACEMV_ChangeBotAngle(self); VectorCopy(self->move_vector,dist); VectorScale(dist,440,self->velocity); return; } //////////////////////////////////////////////////////// // Ladder Nodes /////////////////////////////////////////////////////// if(next_node_type == NODE_LADDER && nodes[self->next_node].origin[2] > self->s.origin[2]) { // Otherwise move as fast as we can ucmd->forwardmove = 300; self->velocity[2] = 320; ACEMV_ChangeBotAngle(self); return; } // If getting off the ladder if(current_node_type == NODE_LADDER && next_node_type != NODE_LADDER && nodes[self->next_node].origin[2] > self->s.origin[2]) { ucmd->forwardmove = 300; ucmd->upmove = 200; self->velocity[2] = 200; ACEMV_ChangeBotAngle(self); return; } //////////////////////////////////////////////////////// // Water Nodes /////////////////////////////////////////////////////// if(current_node_type == NODE_WATER) { // We need to be pointed up/down ACEMV_ChangeBotAngle(self); // If the next node is not in the water, then move up to get out. if(next_node_type != NODE_WATER && !(gi.pointcontents(nodes[self->next_node].origin) & MASK_WATER)) // Exit water ucmd->upmove = 300; ucmd->forwardmove = 300; return; } // Falling off ledge? if(!self->groundentity) { ACEMV_ChangeBotAngle(self); self->velocity[0] = self->move_vector[0] * 360; self->velocity[1] = self->move_vector[1] * 360; return; } // Check to see if stuck, and if so try to free us // Also handles crouching if(VectorLength(self->velocity) < 37) { // Keep a random factor just in case.... if(random() > 0.1 && ACEMV_SpecialMove(self, ucmd)) return; self->s.angles[YAW] += random() * 180 - 90; ucmd->forwardmove = 300; return; } // Otherwise move as fast as we can ucmd->forwardmove = 300; ACEMV_ChangeBotAngle(self); }
// Wandering code (based on old ACE movement code) void ACEMV_Wander(gentity_t * self) { vec3_t tmp; // do not move if(self->bs.next_move_time > level.time) return; // Special check for elevators, stand still until the ride comes to a complete stop. /* * FIXME if(self->groundentity != NULL && self->groundentity->use == Use_Plat) if(self->groundentity->moveinfo.state == STATE_UP || self->groundentity->moveinfo.state == STATE_DOWN) // only move when platform not { self->velocity[0] = 0; self->velocity[1] = 0; self->velocity[2] = 0; self->next_move_time = level.time + 500; return; } */ // touched jumppad last Frame? if(self->s.groundEntityNum == ENTITYNUM_NONE) { if(VectorLength(self->client->ps.velocity) > 120) { VectorNormalize2(self->client->ps.velocity, tmp); if(AngleBetweenVectors(self->bs.moveVector, tmp) >= 120) { // we might have been knocked back by someone or something .. if(!self->bs.moveTarget) { VectorCopy(tmp, self->bs.moveVector); ACEMV_ChangeBotAngle(self); } } } //ACEMV_ChangeBotAngle(self); //self->client->ps.velocity[0] = self->bs.moveVector[0] * 360; //self->client->ps.velocity[1] = self->bs.moveVector[1] * 360; //return; } // is there a target to move to if(self->bs.moveTarget) { ACEMV_MoveToGoal(self); } // swimming? VectorCopy(self->client->ps.origin, tmp); tmp[2] += 24; if(trap_PointContents(tmp, self->s.number) & MASK_WATER) { // if drowning and no node, move up if(self->client->airOutTime > 0) { self->client->pers.cmd.upmove = 1; self->bs.viewAngles[PITCH] = -45; } else self->client->pers.cmd.upmove = 15; self->client->pers.cmd.forwardmove = 100; } else { //self->client->airOutTime = 0; // probably shound not be messing with this, but } // lava? tmp[2] -= 48; if(trap_PointContents(tmp, self->s.number) & (CONTENTS_LAVA | CONTENTS_SLIME)) { // safe_bprintf(PRINT_MEDIUM,"lava jump\n"); self->bs.viewAngles[YAW] += random() * 360 - 180; self->client->pers.cmd.forwardmove = 127; self->client->pers.cmd.upmove = 127; return; } // check for special movement if we have a normal move (have to test) if(VectorLength(self->client->ps.velocity) < 37) { //if(random() > 0.1 && ACEMV_SpecialMove(self)) // return; //removed this because when wandering, the last thing you want is bots jumping //over things and going off ledges. It's better for them to just bounce around the map. self->bs.viewAngles[YAW] += random() * 180 - 90; if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; else if(ACEMV_CanMove(self, MOVE_BACK)) self->client->pers.cmd.forwardmove = -127; // if there is ground continue otherwise wait for next move if( /*!M_CheckBottom || */ self->s.groundEntityNum != ENTITYNUM_NONE) { if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; } return; } if(ACEMV_CheckEyes(self)) return; if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; }
// Main movement code. (following node path) void ACEMV_Move(gentity_t * self) { int currentNodeType = -1; int nextNodeType = -1; // get current and next node back from nav code. if(!ACEND_FollowPath(self)) { self->bs.state = STATE_WANDER; self->bs.wander_timeout = level.time + 1000; // center view //self->bs.viewAngles[PITCH] = 0; //-self->client->ps.delta_angles[PITCH]; return; } currentNodeType = nodes[self->bs.currentNode].type; nextNodeType = nodes[self->bs.nextNode].type; // move to a selected goal, if any if(self->bs.moveTarget) { ACEMV_MoveToGoal(self); } // grapple /* if(nextNodeType == NODE_GRAPPLE) { ACEMV_ChangeBotAngle(self); ACEIT_ChangeWeapon(self, FindItem("grapple")); self->client->pers.cmd.buttons = BUTTON_ATTACK; return; } // Reset the grapple if hangin on a graple node if(currentNodeType == NODE_GRAPPLE) { CTFPlayerResetGrapple(self); return; } */ #if 0 // check for platforms if(currentNodeType != NODE_PLATFORM && nextNodeType == NODE_PLATFORM) { // check to see if lift is down? for(i = 0; i < num_items; i++) if(item_table[i].node == self->bs.nextNode) if(item_table[i].ent->moverState != MOVER_POS1) return; // Wait for elevator } #endif if(currentNodeType == NODE_PLATFORM && nextNodeType == NODE_PLATFORM) { // move to the center self->bs.moveVector[2] = 0; // kill z movement if(VectorLength(self->bs.moveVector) > 10) self->client->pers.cmd.forwardmove = 200; // walk to center ACEMV_ChangeBotAngle(self); return; // No move, riding elevator } // jumpto nodes if(nextNodeType == NODE_JUMP || (currentNodeType == NODE_JUMP && nextNodeType != NODE_ITEM && nodes[self->bs.nextNode].origin[2] > self->client->ps.origin[2])) { // set up a jump move if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; self->client->pers.cmd.upmove = 127; ACEMV_ChangeBotAngle(self); //VectorCopy(self->bs.moveVector, dist); //VectorScale(dist, 127, self->client->ps.velocity); return; } // ladder nodes /* if(nextNodeType == NODE_LADDER && nodes[self->nextNode].origin[2] > self->s.origin[2]) { // Otherwise move as fast as we can self->client->pers.cmd.forwardmove = 400; self->velocity[2] = 320; ACEMV_ChangeBotAngle(self); return; } // If getting off the ladder if(currentNodeType == NODE_LADDER && nextNodeType != NODE_LADDER && nodes[self->nextNode].origin[2] > self->s.origin[2]) { self->client->pers.cmd.forwardmove = 400; self->client->pers.cmd.upmove = 200; self->velocity[2] = 200; ACEMV_ChangeBotAngle(self); return; } */ // water nodes if(currentNodeType == NODE_WATER) { // we need to be pointed up/down ACEMV_ChangeBotAngle(self); // ff the next node is not in the water, then move up to get out. if(nextNodeType != NODE_WATER && !(trap_PointContents(nodes[self->bs.nextNode].origin, self->s.number) & MASK_WATER)) { // exit water self->client->pers.cmd.upmove = 127; } self->client->pers.cmd.forwardmove = 100; return; } // falling off ledge? if(self->s.groundEntityNum == ENTITYNUM_NONE) { ACEMV_ChangeBotAngle(self); //self->client->ps.velocity[0] = self->bs.moveVector[0] * 360; //self->client->ps.velocity[1] = self->bs.moveVector[1] * 360; return; } // check to see if stuck, and if so try to free us // also handles crouching if(VectorLength(self->client->ps.velocity) < 37) { // keep a random factor just in case.... if(random() > 0.1 && ACEMV_SpecialMove(self)) return; self->bs.viewAngles[YAW] += random() * 180 - 90; if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; else if(ACEMV_CanMove(self, MOVE_BACK)) self->client->pers.cmd.forwardmove = -127; return; } // otherwise move as fast as we can if(ACEMV_CanMove(self, MOVE_FORWARD)) self->client->pers.cmd.forwardmove = 127; ACEMV_ChangeBotAngle(self); }