void selectitem() { if (selected_items.size() < ents.length()) selected_items.resize(ents.length()); if (!select_multiple) fill(selected_items.begin(), selected_items.end(), false); vec selv = { worldpos.x, worldpos.y, worldpos.z }; loopv(ents) { entity &e = ents[i]; if(e.type < I_SHELLS || e.type > I_QUAD) continue; if (!e.spawned) continue; if(OUTBORD(e.x, e.y)) continue; vec v = { e.x, e.y, S(e.x, e.y)->floor }; vdist(dist, t, selv, v); if(dist<2.0) { selset = false; selected_items[i] = true; } } }
void correctsel() // ensures above invariant { selset = !OUTBORD(sel.x, sel.y); int bsize = ssize-MINBORD; if(sel.xs+sel.x>bsize) sel.xs = bsize-sel.x; if(sel.ys+sel.y>bsize) sel.ys = bsize-sel.y; if(sel.xs<=0 || sel.ys<=0) selset = false; };
void computeraytable(float vx, float vy) { if(!ocull) return; odist = getvar("fog")*1.5f; float apitch = (float)fabs(player1->pitch); float af = getvar("fov")/2+apitch/1.5f+3; float byaw = (player1->yaw-90+af)/360*PI2; float syaw = (player1->yaw-90-af)/360*PI2; loopi(NUMRAYS) { float angle = i*PI2/NUMRAYS; if((apitch>45 // must be bigger if fov>120 || (angle<byaw && angle>syaw) || (angle<byaw-PI2 && angle>syaw-PI2) || (angle<byaw+PI2 && angle>syaw+PI2)) && !OUTBORD(vx, vy) && !SOLID(S(fast_f2nat(vx), fast_f2nat(vy)))) // try to avoid tracing ray if outside of frustrum { float ray = i*8/(float)NUMRAYS; float dx, dy; if(ray>1 && ray<3) { dx = -(ray-2); dy = 1; } else if(ray>=3 && ray<5) { dx = -1; dy = -(ray-4); } else if(ray>=5 && ray<7) { dx = ray-6; dy = -1; } else { dx = 1; dy = ray>4 ? ray-8 : ray; }; float sx = vx; float sy = vy; for(;;) { sx += dx; sy += dy; if(SOLID(S(fast_f2nat(sx), fast_f2nat(sy)))) // 90% of time spend in this function is on this line { rdist[i] = (float)(fabs(sx-vx)+fabs(sy-vy)); break; }; }; } else { rdist[i] = 2; }; }; };
void rendermodel(const char *mdl, int frame, int range, int tex, float rad, float x, float y, float z, float yaw, float pitch, bool teammate, float scale, float speed, int snap, int basetime) { md2 *m = loadmodel(mdl); if (world::isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; delayedload(m); int xs, ys; ogl::bindtexture(GL_TEXTURE_2D, tex ? ogl::lookuptex(tex, xs, ys) : FIRSTMDL+m->mdlnum); const int ix = (int)x; const int iy = (int)z; vec light(1.0f, 1.0f, 1.0f); if (!OUTBORD(ix, iy)) { sqr *s = S(ix,iy); const float ll = 256.0f; // 0.96f; const float of = 0.0f; // 0.1f; light.x = s->r/ll+of; light.y = s->g/ll+of; light.z = s->b/ll+of; } if (teammate) { light.x *= 0.6f; light.y *= 0.7f; light.z *= 1.2f; } m->render(light, frame, range, x, y, z, yaw, pitch, scale, speed, snap, basetime); }
void cursorupdate() // called every frame from hud { flrceil = ((int)(player1->pitch>=0))*2; volatile float x = worldpos.x; // volatile needed to prevent msvc7 optimizer bug? volatile float y = worldpos.y; volatile float z = worldpos.z; cx = (int)x; cy = (int)y; if(OUTBORD(cx, cy)) return; sqr *s = S(cx,cy); if(fabs(sheight(s,s,z)-z)>1) // selected wall { x += x>player1->o.x ? 0.5f : -0.5f; // find right wall cube y += y>player1->o.y ? 0.5f : -0.5f; cx = (int)x; cy = (int)y; if(OUTBORD(cx, cy)) return; }; if(dragging) makesel(); const int GRIDSIZE = 5; const float GRIDW = 0.5f; const float GRID8 = 2.0f; const float GRIDS = 2.0f; const int GRIDM = 0x7; // render editing grid /* for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++) { if(OUTBORD(ix, iy)) continue; sqr *s = S(ix,iy); if(SOLID(s)) continue; float h1 = sheight(s, s, z); float h2 = sheight(s, SWS(s,1,0,ssize), z); float h3 = sheight(s, SWS(s,1,1,ssize), z); float h4 = sheight(s, SWS(s,0,1,ssize), z); if(s->tag) linestyle(GRIDW, 0xFF, 0x40, 0x40); else if(s->type==FHF || s->type==CHF) linestyle(GRIDW, 0x80, 0xFF, 0x80); else linestyle(GRIDW, 0x80, 0x80, 0x80); block b = { ix, iy, 1, 1 }; box(b, h1, h2, h3, h4); linestyle(GRID8, 0x40, 0x40, 0xFF); if(!(ix&GRIDM)) line(ix, iy, h1, ix, iy+1, h4); if(!(ix+1&GRIDM)) line(ix+1, iy, h2, ix+1, iy+1, h3); if(!(iy&GRIDM)) line(ix, iy, h1, ix+1, iy, h2); if(!(iy+1&GRIDM)) line(ix, iy+1, h4, ix+1, iy+1, h3); }; */ if(!SOLID(s)) { float ih = sheight(s, s, z); linestyle(GRIDS, 0xFF, 0xFF, 0xFF); block b = { cx, cy, 1, 1 }; box(b, ih, sheight(s, SWS(s,1,0,ssize), z), sheight(s, SWS(s,1,1,ssize), z), sheight(s, SWS(s,0,1,ssize), z)); linestyle(GRIDS, 0xFF, 0x00, 0x00); dot(cx, cy, ih); ch = (int)ih; }; if(selset) { linestyle(GRIDS, 0xFF, 0x40, 0x40); box(sel, (float)selh, (float)selh, (float)selh, (float)selh); std::vector< std::pair<block, int> >::iterator sel_it = secondary_sel.begin(); std::vector< std::pair<block, int> >::iterator sel_end = secondary_sel.end(); for (; sel_it != sel_end; ++sel_it) box(sel_it->first, (float)sel_it->second, (float)sel_it->second, (float)sel_it->second, (float)sel_it->second); }; };
entity *CACBot::SearchForFlags(bool bUseWPs, float flRange, float flMaxHeight) { /* Flags are scored on the following: - Distance */ float flDist; entity *pNewTargetFlag = NULL; waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL; short sScore, sHighestScore = 0; vec vNewGoal = g_vecZero; if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs) pWptNearBot = GetNearestWaypoint(200.0f); #ifdef WP_FLOOD if (!pWptNearBot && bUseWPs) pWptNearBot = GetNearestFloodWP(64.0f); #endif loopv(ents) { sScore = 0; entity &e = ents[i]; if(!CanTakeFlag(e)) continue; //vec o = g_vecZero; vec o = vec(e.x, e.y, S(e.x, e.y)->floor + PLAYERHEIGHT + PLAYERABOVEEYE); if(!m_secure(gamemode) && e.attr2 >= 0 && e.attr2 < 2) { flaginfo &f = flaginfos[e.attr2]; // flaginfo &of = flaginfos[team_opposite(i)]; if(f.state == CTFF_DROPPED) { o = f.pos; o.z += PLAYERHEIGHT + PLAYERABOVEEYE; } } if(OUTBORD((int)o.x, (int)o.y)) continue; flDist = GetDistance(o); if (flDist > flRange) continue; // Score on distance float ff = flDist; if (ff > 100.0f) ff = 100.0f; sScore += ((100 - short(ff)) / 2); waypoint_s *pWptNearEnt = NULL; // If this flag entity isn't visible check if there is a nearby waypoint if (!IsReachable(o, flMaxHeight))//(!IsVisible(o)) { if (!pWptNearBot) continue; #ifdef WP_FLOOD if (pWptNearBot->pNode->iFlags & W_FL_FLOOD) pWptNearEnt = GetNearestFloodWP(o, 100.0f); else #endif pWptNearEnt = GetNearestWaypoint(o, 200.f); if (!pWptNearEnt) continue; } // Score on visibility if (pWptNearEnt == NULL) // Ent is visible sScore += 6; else sScore += 3; if(sScore > sHighestScore) { if (pWptNearEnt) pBestWpt = pWptNearEnt; else pBestWpt = NULL; // best flag doesn't need any waypoints vNewGoal = o; pNewTargetFlag = &e; } } if (pNewTargetFlag) { // Need waypoints to reach it? if (pBestWpt) { ResetWaypointVars(); SetCurrentWaypoint(pWptNearBot); SetCurrentGoalWaypoint(pBestWpt); } m_vGoal = vNewGoal; } return pNewTargetFlag; }
entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight) { /* Entities are scored on the following things: - Visibility - For ammo: Need(ie has this bot much of this type or not) - distance */ float flDist; entity *pNewTargetEnt = NULL; waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL; short sScore, sHighestScore = 0; if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs) pWptNearBot = GetNearestWaypoint(15.0f); #ifdef WP_FLOOD if (!pWptNearBot && bUseWPs) pWptNearBot = GetNearestFloodWP(5.0f); #endif loopv(ents) { sScore = 0; entity &e = ents[i]; vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); if (!ents[i].spawned) continue; if (OUTBORD(e.x, e.y)) continue; bool bInteresting = false; short sAmmo = 0, sMaxAmmo = 0; switch(e.type) { case I_CLIPS: sMaxAmmo = ammostats[m_pMyEnt->secondary].max; bInteresting = (m_pMyEnt->ammo[m_pMyEnt->secondary]<sMaxAmmo); sAmmo = m_pMyEnt->ammo[m_pMyEnt->secondary]; break; case I_AMMO: sMaxAmmo = ammostats[m_pMyEnt->primary].max; bInteresting = (m_pMyEnt->ammo[m_pMyEnt->primary]<sMaxAmmo); sAmmo = m_pMyEnt->ammo[m_pMyEnt->primary]; break; case I_GRENADE: sMaxAmmo = ammostats[GUN_GRENADE].max; bInteresting = (m_pMyEnt->mag[GUN_GRENADE]<sMaxAmmo); sAmmo = -1; break; case I_HEALTH: sMaxAmmo = MAXHEALTH; bInteresting = (m_pMyEnt->health < sMaxAmmo); sAmmo = m_pMyEnt->health; break; case I_HELMET: case I_ARMOUR: sMaxAmmo = MAXARMOUR; bInteresting = (m_pMyEnt->armour < sMaxAmmo); sAmmo = m_pMyEnt->armour; break; case I_AKIMBO: bInteresting = !m_pMyEnt->akimbo; sAmmo = -1; break; }; if (!bInteresting) continue; // Not an interesting item, skip // Score on ammo and need // Akimbo & nade if (sAmmo == -1) { sScore += 75; // Bonus } else { // Calculate current percentage of max ammo float percent = ((float)sAmmo / (float)sMaxAmmo) * 100.0f; if (percent > 100.0f) percent = 100.0f; sScore += ((100 - short(percent))/2); } flDist = GetDistance(o); if (flDist > flRange) continue; // Score on distance float f = flDist; if (f > 100.0f) f = 100.0f; sScore += ((100 - short(f)) / 2); waypoint_s *pWptNearEnt = NULL; // If this entity isn't visible check if there is a nearby waypoint if (!IsReachable(o, flMaxHeight))//(!IsVisible(o)) { if (!pWptNearBot) continue; #ifdef WP_FLOOD if (pWptNearBot->pNode->iFlags & W_FL_FLOOD) pWptNearEnt = GetNearestFloodWP(o, 8.0f); else #endif pWptNearEnt = GetNearestWaypoint(o, 15.0f); if (!pWptNearEnt) continue; } // Score on visibility if (pWptNearEnt == NULL) // Ent is visible sScore += 30; else sScore += 15; if (sScore > sHighestScore) { // Found a valid wp near the bot and the ent,so...lets store it :) if (pWptNearEnt) pBestWpt = pWptNearEnt; else pBestWpt = NULL; // Best ent so far doesn't need any waypoints sHighestScore = sScore; pNewTargetEnt = &ents[i]; } } if (pNewTargetEnt) { // Need waypoints to reach it? if (pBestWpt) { ResetWaypointVars(); SetCurrentWaypoint(pWptNearBot); SetCurrentGoalWaypoint(pBestWpt); } m_vGoal.x = pNewTargetEnt->x; m_vGoal.y = pNewTargetEnt->y; m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->eyeheight; } return pNewTargetEnt; }