From: Mario Date: Tue, 26 Jul 2016 16:27:17 +0000 (+1000) Subject: Replace most cases of findchain* with the FOREACH_ENTITY_* macros X-Git-Tag: xonotic-v0.8.2~700^2~27 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=90f4259bf39b41bb370dbc2efc6017ad0aa596e7;p=xonotic%2Fxonotic-data.pk3dir.git Replace most cases of findchain* with the FOREACH_ENTITY_* macros --- diff --git a/qcsrc/common/effects/qc/rubble.qh b/qcsrc/common/effects/qc/rubble.qh index 7848b7b1f..1665e4cce 100644 --- a/qcsrc/common/effects/qc/rubble.qh +++ b/qcsrc/common/effects/qc/rubble.qh @@ -8,34 +8,25 @@ class(Rubble).float creationtime; void RubbleLimit(string cname, float limit, void(entity) deleteproc) { - entity e; - entity oldest; - float c; - float oldesttime; - // remove rubble of the same type if it's at the limit // remove multiple rubble if the limit has been decreased while (1) { - e = findchain(classname, cname); - if (e == NULL) break; // walk the list and count the entities, find the oldest // initialize our search with the first entity - c = 1; - oldest = e; - oldesttime = e.creationtime; - e = e.chain; + int c = 0; + entity oldest = NULL; + float oldesttime = 0; // compare to all other matching entities - while (e) + FOREACH_ENTITY_CLASS(cname, true, { - c = c + 1; - if (oldesttime > e.creationtime) + ++c; + if(!oldest || oldesttime > it.creationtime) { - oldesttime = e.creationtime; - oldest = e; + oldest = it; + oldesttime = it.creationtime; } - e = e.chain; - } + }); // stop if there are less than the limit already if (c <= limit) break; diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc index 6242414ae..d0c575a48 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc +++ b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc @@ -358,13 +358,11 @@ void onslaught_updatelinks() } ons_ControlPoint_UpdateSprite(l); } - l = findchain(classname, "ons_captureshield"); - while(l) + FOREACH_ENTITY_CLASS("ons_captureshield", true, { - l.team = l.enemy.team; - l.colormap = l.enemy.colormap; - l = l.chain; - } + it.team = it.enemy.team; + it.colormap = it.enemy.colormap; + }); } @@ -1289,8 +1287,6 @@ void Onslaught_RoundStart() void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector org, float sradius) { - entity head; - float t, c; bool needarmor = false, needweapons = false; // Needs armor/health? @@ -1298,7 +1294,7 @@ void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector needarmor = true; // Needs weapons? - c = 0; + int c = 0; FOREACH(Weapons, it != WEP_Null, { if(this.weapons & (it.m_wepset)) if(++c >= 4) @@ -1315,20 +1311,18 @@ void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector LOG_DEBUG(strcat(this.netname, " needs armor ", ftos(needarmor) , "\n")); // See what is around - head = findchainfloat(bot_pickup, true); - while (head) + FOREACH_ENTITY_FLOAT(bot_pickup, true, { // gather health and armor only - if (head.solid) - if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) ) - if (vdist(head.origin - org, <, sradius)) + if (it.solid) + if ( ((it.health || it.armorvalue) && needarmor) || (it.weapons && needweapons ) ) + if (vdist(it.origin - org, <, sradius)) { - t = head.bot_pickupevalfunc(this, head); + int t = it.bot_pickupevalfunc(this, it); if (t > 0) - navigation_routerating(this, head, t * ratingscale, 500); + navigation_routerating(this, it, t * ratingscale, 500); } - head = head.chain; - } + }); } void havocbot_role_ons_setrole(entity this, int role) @@ -1597,26 +1591,22 @@ void havocbot_ons_reset_role(entity this) */ entity ons_Nearest_ControlPoint(entity this, vector pos, float max_dist) { - entity tmp_entity, closest_target = NULL; - tmp_entity = findchain(classname, "onslaught_controlpoint"); - while(tmp_entity) + entity closest_target = NULL; + FOREACH_ENTITY_CLASS("onslaught_controlpoint", true, { - if(SAME_TEAM(tmp_entity, this)) - if(tmp_entity.iscaptured) - if(max_dist <= 0 || vdist(tmp_entity.origin - pos, <=, max_dist)) - if(vlen2(tmp_entity.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL) - closest_target = tmp_entity; - tmp_entity = tmp_entity.chain; - } - tmp_entity = findchain(classname, "onslaught_generator"); - while(tmp_entity) + if(SAME_TEAM(it, this)) + if(it.iscaptured) + if(max_dist <= 0 || vdist(it.origin - pos, <=, max_dist)) + if(vlen2(it.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL) + closest_target = it; + }); + FOREACH_ENTITY_CLASS("onslaught_generator", true, { - if(SAME_TEAM(tmp_entity, this)) - if(max_dist <= 0 || vdist(tmp_entity.origin - pos, <, max_dist)) - if(vlen2(tmp_entity.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL) - closest_target = tmp_entity; - tmp_entity = tmp_entity.chain; - } + if(SAME_TEAM(it, this)) + if(max_dist <= 0 || vdist(it.origin - pos, <, max_dist)) + if(vlen2(it.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL) + closest_target = it; + }); return closest_target; } @@ -1628,45 +1618,39 @@ entity ons_Nearest_ControlPoint(entity this, vector pos, float max_dist) */ entity ons_Nearest_ControlPoint_2D(entity this, vector pos, float max_dist) { - entity tmp_entity, closest_target = NULL; + entity closest_target = NULL; vector delta; float smallest_distance = 0, distance; - tmp_entity = findchain(classname, "onslaught_controlpoint"); - while(tmp_entity) + FOREACH_ENTITY_CLASS("onslaught_controlpoint", true, { - delta = tmp_entity.origin - pos; + delta = it.origin - pos; delta_z = 0; distance = vlen(delta); - if(SAME_TEAM(tmp_entity, this)) - if(tmp_entity.iscaptured) + if(SAME_TEAM(it, this)) + if(it.iscaptured) if(max_dist <= 0 || distance <= max_dist) if(closest_target == NULL || distance <= smallest_distance ) { - closest_target = tmp_entity; + closest_target = it; smallest_distance = distance; } - - tmp_entity = tmp_entity.chain; - } - tmp_entity = findchain(classname, "onslaught_generator"); - while(tmp_entity) + }); + FOREACH_ENTITY_CLASS("onslaught_generator", true, { - delta = tmp_entity.origin - pos; + delta = it.origin - pos; delta_z = 0; distance = vlen(delta); - if(SAME_TEAM(tmp_entity, this)) + if(SAME_TEAM(it, this)) if(max_dist <= 0 || distance <= max_dist) if(closest_target == NULL || distance <= smallest_distance ) { - closest_target = tmp_entity; + closest_target = it; smallest_distance = distance; } - - tmp_entity = tmp_entity.chain; - } + }); return closest_target; } @@ -1675,23 +1659,18 @@ entity ons_Nearest_ControlPoint_2D(entity this, vector pos, float max_dist) */ int ons_Count_SelfControlPoints(entity this) { - entity tmp_entity; - tmp_entity = findchain(classname, "onslaught_controlpoint"); int n = 0; - while(tmp_entity) + FOREACH_ENTITY_CLASS("onslaught_controlpoint", true, { - if(SAME_TEAM(tmp_entity, this)) - if(tmp_entity.iscaptured) + if(SAME_TEAM(it, this)) + if(it.iscaptured) n++; - tmp_entity = tmp_entity.chain; - } - tmp_entity = findchain(classname, "onslaught_generator"); - while(tmp_entity) + }); + FOREACH_ENTITY_CLASS("onslaught_generator", true, { - if(SAME_TEAM(tmp_entity, this)) + if(SAME_TEAM(it, this)) n++; - tmp_entity = tmp_entity.chain; - } + }); return n; } diff --git a/qcsrc/common/turrets/turret/tesla_weapon.qc b/qcsrc/common/turrets/turret/tesla_weapon.qc index e21cd498f..38a9335f7 100644 --- a/qcsrc/common/turrets/turret/tesla_weapon.qc +++ b/qcsrc/common/turrets/turret/tesla_weapon.qc @@ -42,12 +42,10 @@ METHOD(TeslaCoilTurretAttack, wr_think, void(entity thiswep, entity actor, .enti } - e = findchainfloat(railgunhit, 1); - while (e) { - e.railgunhit = 0; - e = e.chain; - } - + FOREACH_ENTITY_FLOAT(railgunhit, 1, + { + it.railgunhit = 0; + }); } } diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc index 14405460e..e743a7771 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc @@ -201,15 +201,13 @@ void raptor_flare_damage(entity this, entity inflictor, entity attacker, float d void raptor_flare_think(entity this) { this.nextthink = time + 0.1; - entity _missile = findchainentity(enemy, this.owner); - while(_missile) + FOREACH_ENTITY_ENT(enemy, this.owner, { - if(_missile.flags & FL_PROJECTILE) - if(vdist(this.origin - _missile.origin, <, autocvar_g_vehicle_raptor_flare_range)) + if(it.flags & FL_PROJECTILE) + if(vdist(this.origin - it.origin, <, autocvar_g_vehicle_raptor_flare_range)) if(random() > autocvar_g_vehicle_raptor_flare_chase) - _missile.enemy = this; - _missile = _missile.chain; - } + it.enemy = this; + }); if(this.tur_impacttime < time) remove(this); diff --git a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc index fbe82436c..dc1f6ba60 100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc @@ -48,21 +48,17 @@ void spiderbot_rocket_guided(entity this) void spiderbot_guide_release(entity this) { - entity rkt; - rkt = findchainentity(realowner, this.owner); - if(!rkt) - return; - - crosshair_trace(this.owner); - while(rkt) + FOREACH_ENTITY_ENT(realowner, this.owner, { - if(getthink(rkt) == spiderbot_rocket_guided) + if(i == 0) // something exists, let's trace! + crosshair_trace(this.owner); + + if(getthink(it) == spiderbot_rocket_guided) { - rkt.pos1 = trace_endpos; - setthink(rkt, spiderbot_rocket_unguided); + it.pos1 = trace_endpos; + setthink(it, spiderbot_rocket_unguided); } - rkt = rkt.chain; - } + }); } float spiberbot_calcartillery_flighttime; diff --git a/qcsrc/common/weapons/weapon/devastator.qc b/qcsrc/common/weapons/weapon/devastator.qc index bcc81c82e..3049225c4 100644 --- a/qcsrc/common/weapons/weapon/devastator.qc +++ b/qcsrc/common/weapons/weapon/devastator.qc @@ -441,8 +441,7 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor)) if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! { // decide whether to detonate rockets - entity targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; + float edgedamage, coredamage, edgeradius, recipricoledgeradius; float selfdamage, teamdamage, enemydamage; edgedamage = WEP_CVAR(devastator, edgedamage); coredamage = WEP_CVAR(devastator, damage); @@ -451,25 +450,23 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor)) selfdamage = 0; teamdamage = 0; enemydamage = 0; - targetlist = findchainfloat(bot_attack, true); FOREACH_ENTITY_ENT(realowner, actor, { if(it.classname != "rocket") continue; - targ = targetlist; - while(targ) + entity rocket = it; + FOREACH_ENTITY_FLOAT(bot_attack, true, { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - it.origin); - d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); - // count potential damage according to type of target - if(targ == actor) - selfdamage = selfdamage + d; - else if(targ.team == actor.team && teamplay) - teamdamage = teamdamage + d; - else if(bot_shouldattack(actor, targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } + float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - rocket.origin); + d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); + // count potential damage according to type of target + if(it == actor) + selfdamage = selfdamage + d; + else if(SAME_TEAM(it, actor)) + teamdamage = teamdamage + d; + else if(bot_shouldattack(actor, it)) + enemydamage = enemydamage + d; + }); }); float desirabledamage; desirabledamage = enemydamage; @@ -478,36 +475,35 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor)) if(teamplay && actor.team) desirabledamage = desirabledamage - teamdamage; + makevectors(actor.v_angle); FOREACH_ENTITY_ENT(realowner, actor, { if(it.classname != "rocket") continue; - makevectors(it.v_angle); - targ = targetlist; if(skill > 9) // normal players only do this for the target they are tracking { - targ = targetlist; - while(targ) - { - if( - (v_forward * normalize(it.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - ) PHYS_INPUT_BUTTON_ATCK2(actor) = true; - targ = targ.chain; - } - } - else - { - float distance; distance= bound(300,vlen(actor.origin-actor.enemy.origin),30000); + entity rocket = it; + FOREACH_ENTITY_FLOAT(bot_attack, true, + { + if((v_forward * normalize(rocket.origin - it.origin) < 0.1) + && desirabledamage > 0.1 * coredamage + ) PHYS_INPUT_BUTTON_ATCK2(actor) = true; + }); + } + else + { //As the distance gets larger, a correct detonation gets near imposible //Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player - if(v_forward * normalize(it.origin - actor.enemy.origin)< 0.1) - if(IS_PLAYER(actor.enemy)) - if(desirabledamage >= 0.1*coredamage) - if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1)) - PHYS_INPUT_BUTTON_ATCK2(actor) = true; - // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n"); - } + if((v_forward * normalize(it.origin - actor.enemy.origin) < 0.1) + && IS_PLAYER(actor.enemy) + && (desirabledamage >= 0.1 * coredamage) + ) + { + float distance = bound(300, vlen(actor.origin - actor.enemy.origin), 30000); + if(random() / distance * 300 > frametime * bound(0, (10 - skill) * 0.2, 1)) + PHYS_INPUT_BUTTON_ATCK2(actor) = true; + } + } }); // if we would be doing at X percent of the core damage, detonate it // but don't fire a new shot at the same time! diff --git a/qcsrc/common/weapons/weapon/minelayer.qc b/qcsrc/common/weapons/weapon/minelayer.qc index ffa9793e8..8b1e0cd2e 100644 --- a/qcsrc/common/weapons/weapon/minelayer.qc +++ b/qcsrc/common/weapons/weapon/minelayer.qc @@ -415,8 +415,7 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor)) if(skill >= 2) // skill 0 and 1 bots won't detonate mines! { // decide whether to detonate mines - entity targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; + float edgedamage, coredamage, edgeradius, recipricoledgeradius; float selfdamage, teamdamage, enemydamage; edgedamage = WEP_CVAR(minelayer, edgedamage); coredamage = WEP_CVAR(minelayer, damage); @@ -425,31 +424,26 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor)) selfdamage = 0; teamdamage = 0; enemydamage = 0; - targetlist = findchainfloat(bot_attack, true); - entity mine = find(NULL, classname, "mine"); - while(mine) + + FOREACH_ENTITY_ENT(realowner, actor, { - if(mine.realowner != actor) - { - mine = find(mine, classname, "mine"); - continue; - } - targ = targetlist; - while(targ) - { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.origin); - d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); + if(it.classname != "mine") continue; + + entity mine = it; + FOREACH_ENTITY_FLOAT(bot_attack, true, + { + float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - mine.origin); + d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); // count potential damage according to type of target - if(targ == actor) + if(it == actor) selfdamage = selfdamage + d; - else if(targ.team == actor.team && teamplay) + else if(SAME_TEAM(it, actor)) teamdamage = teamdamage + d; - else if(bot_shouldattack(actor, targ)) + else if(bot_shouldattack(actor, it)) enemydamage = enemydamage + d; - targ = targ.chain; - } - mine = find(mine, classname, "mine"); - } + }); + }); + float desirabledamage; desirabledamage = enemydamage; if(time > actor.invincible_finished && time > actor.spawnshieldtime) @@ -457,41 +451,37 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor)) if(teamplay && actor.team) desirabledamage = desirabledamage - teamdamage; - mine = find(NULL, classname, "mine"); - while(mine) + makevectors(actor.v_angle); + FOREACH_ENTITY_ENT(realowner, actor, { - if(mine.realowner != actor) - { - mine = find(mine, classname, "mine"); - continue; - } - makevectors(mine.v_angle); - targ = targetlist; + if(it.classname != "mine") continue; + if(skill > 9) // normal players only do this for the target they are tracking { - targ = targetlist; - while(targ) - { - if( - (v_forward * normalize(mine.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - ) PHYS_INPUT_BUTTON_ATCK2(actor) = true; - targ = targ.chain; - } - }else{ - float distance; distance= bound(300,vlen(actor.origin-actor.enemy.origin),30000); + entity mine = it; + FOREACH_ENTITY_FLOAT(bot_attack, true, + { + if((v_forward * normalize(mine.origin - it.origin) < 0.1) + && desirabledamage > 0.1 * coredamage + ) PHYS_INPUT_BUTTON_ATCK2(actor) = true; + }); + } + else + { //As the distance gets larger, a correct detonation gets near imposible //Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player - if(v_forward * normalize(mine.origin - actor.enemy.origin)< 0.1) - if(IS_PLAYER(actor.enemy)) - if(desirabledamage >= 0.1*coredamage) - if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1)) - PHYS_INPUT_BUTTON_ATCK2(actor) = true; - // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n"); - } - - mine = find(mine, classname, "mine"); - } + if((v_forward * normalize(it.origin - actor.enemy.origin) < 0.1) + && IS_PLAYER(actor.enemy) + && (desirabledamage >= 0.1 * coredamage) + ) + { + float distance = bound(300, vlen(actor.origin - actor.enemy.origin), 30000); + if(random() / distance * 300 > frametime * bound(0, (10 - skill) * 0.2, 1)) + PHYS_INPUT_BUTTON_ATCK2(actor) = true; + } + } + }); + // if we would be doing at X percent of the core damage, detonate it // but don't fire a new shot at the same time! if(desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events diff --git a/qcsrc/server/bot/bot.qc b/qcsrc/server/bot/bot.qc index 8707a03bd..5fff8361f 100644 --- a/qcsrc/server/bot/bot.qc +++ b/qcsrc/server/bot/bot.qc @@ -346,31 +346,28 @@ void bot_endgame() void bot_relinkplayerlist() { - entity e; - entity prevbot; player_count = 0; currentbots = 0; - player_list = e = findchainflags(flags, FL_CLIENT); bot_list = NULL; - prevbot = NULL; - while (e) + + entity prevbot = NULL; + FOREACH_CLIENT(true, { - player_count = player_count + 1; - e.nextplayer = e.chain; - if (IS_BOT_CLIENT(e)) + ++player_count; + + if(IS_BOT_CLIENT(it)) { - if (prevbot) - prevbot.nextbot = e; + if(prevbot) + prevbot.nextbot = it; else { - bot_list = e; + bot_list = it; bot_list.nextbot = NULL; } - prevbot = e; - currentbots = currentbots + 1; + prevbot = it; + ++currentbots; } - e = e.chain; - } + }); LOG_TRACE(strcat("relink: ", ftos(currentbots), " bots seen.\n")); bot_strategytoken = bot_list; bot_strategytoken_taken = true; @@ -427,70 +424,84 @@ void bot_clientconnect(entity this) void bot_removefromlargestteam() { - float besttime, bestcount, thiscount; - entity best, head; CheckAllowedTeams(NULL); GetTeamCounts(NULL); - head = findchainfloat(isbot, true); - if (!head) - return; - best = head; - besttime = head.createdtime; - bestcount = 0; - while (head) + + entity best = NULL; + float besttime = 0; + int bestcount = 0; + + int bcount = 0; + FOREACH_ENTITY_FLOAT(isbot, true, { - if(head.team == NUM_TEAM_1) - thiscount = c1; - else if(head.team == NUM_TEAM_2) - thiscount = c2; - else if(head.team == NUM_TEAM_3) - thiscount = c3; - else if(head.team == NUM_TEAM_4) - thiscount = c4; - else - thiscount = 0; - if (thiscount > bestcount) + ++bcount; + + if(!best) + { + best = it; + besttime = it.createdtime; + } + + int thiscount = 0; + + switch(it.team) + { + case NUM_TEAM_1: thiscount = c1; break; + case NUM_TEAM_2: thiscount = c2; break; + case NUM_TEAM_3: thiscount = c3; break; + case NUM_TEAM_4: thiscount = c4; break; + } + + if(thiscount > bestcount) { bestcount = thiscount; - besttime = head.createdtime; - best = head; + besttime = it.createdtime; + best = it; } - else if (thiscount == bestcount && besttime < head.createdtime) + else if(thiscount == bestcount && besttime < it.createdtime) { - besttime = head.createdtime; - best = head; + besttime = it.createdtime; + best = it; } - head = head.chain; - } + }); + if(!bcount) + return; // no bots to remove currentbots = currentbots - 1; dropclient(best); } void bot_removenewest() { - float besttime; - entity best, head; - if(teamplay) { bot_removefromlargestteam(); return; } - head = findchainfloat(isbot, true); - if (!head) - return; - best = head; - besttime = head.createdtime; - while (head) + float besttime = 0; + entity best = NULL; + int bcount = 0; + + FOREACH_ENTITY_FLOAT(isbot, true, { - if (besttime < head.createdtime) + ++bcount; + + if(!best) { - besttime = head.createdtime; - best = head; + best = it; + besttime = it.createdtime; } - head = head.chain; - } + + if(besttime < it.createdtime) + { + besttime = it.createdtime; + best = it; + } + }); + + if(!bcount) + return; // no bots to remove + currentbots = currentbots - 1; dropclient(best); } @@ -659,9 +670,10 @@ void bot_serverframe() else { // TODO: Make this check cleaner - entity wp = findchain(classname, "waypoint"); - if(time - wp.nextthink > 10) + FOREACH_ENTITY_CLASS("waypoint", time - it.nextthink > 10, + { waypoint_save_links(); + }); } } else diff --git a/qcsrc/server/bot/bot.qh b/qcsrc/server/bot/bot.qh index a28c94b7f..e9dd92668 100644 --- a/qcsrc/server/bot/bot.qh +++ b/qcsrc/server/bot/bot.qh @@ -52,9 +52,7 @@ float bot_weapons_mid[Weapons_MAX]; float bot_weapons_close[Weapons_MAX]; entity bot_list; -entity player_list; .entity nextbot; -.entity nextplayer; .string cleanname; .string netname_freeme; .string playermodel_freeme; diff --git a/qcsrc/server/bot/havocbot/havocbot.qc b/qcsrc/server/bot/havocbot/havocbot.qc index c3603e9ff..f1b1f65f9 100644 --- a/qcsrc/server/bot/havocbot/havocbot.qc +++ b/qcsrc/server/bot/havocbot/havocbot.qc @@ -41,41 +41,30 @@ void havocbot_ai(entity this) // TODO: tracewalk() should take care of this job (better path finding under water) // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it if(IS_DEAD(this)) - if(this.goalcurrent==NULL) - if(this.waterlevel==WATERLEVEL_SWIMMING || (this.aistatus & AI_STATUS_OUT_WATER)) + if(!this.goalcurrent) + if(this.waterlevel == WATERLEVEL_SWIMMING || (this.aistatus & AI_STATUS_OUT_WATER)) { // Look for the closest waypoint out of water - entity newgoal, head; - float bestdistance, distance; - - newgoal = NULL; - bestdistance = 10000; - for (head = findchain(classname, "waypoint"); head; head = head.chain) + entity newgoal = NULL; + FOREACH_ENTITY_CLASS("waypoint", vdist(it.origin - this.origin, <, 10000), { - distance = vlen(head.origin - this.origin); - if(distance>10000) - continue; - - if(head.origin.z < this.origin.z) + if(it.origin.z < this.origin.z) continue; - if(head.origin.z - this.origin.z - this.view_ofs.z > 100) + if(it.origin.z - this.origin.z - this.view_ofs.z > 100) continue; - if (pointcontents(head.origin + head.maxs + '0 0 1') != CONTENT_EMPTY) + if (pointcontents(it.origin + it.maxs + '0 0 1') != CONTENT_EMPTY) continue; - traceline(this.origin + this.view_ofs , head.origin, true, head); + traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this); - if(trace_fraction<1) + if(trace_fraction < 1) continue; - if(distance1000) + if(trace_fraction < 1) continue; - traceline(this.origin + this.view_ofs , ( ( head.absmin + head.absmax ) * 0.5 ), true, NULL); - - if(trace_fraction<1) - continue; - - if(distance>bestdistance) - { - newgoal = head; - bestdistance = distance; - } - } + if(!newgoal || vlen2(it.origin - this.origin) > vlen2(newgoal.origin - this.origin)) + newgoal = it; + }); if(newgoal) { diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc index 034e29fab..9ea6a3d90 100644 --- a/qcsrc/server/bot/havocbot/roles.qc +++ b/qcsrc/server/bot/havocbot/roles.qc @@ -13,58 +13,45 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius) { - entity head; - float rating, d, discard, distance, friend_distance, enemy_distance; + float rating, d, discard, friend_distance, enemy_distance; vector o; ratingscale = ratingscale * 0.0001; // items are rated around 10000 already - head = findchainfloat(bot_pickup, true); - while (head) + FOREACH_ENTITY_FLOAT(bot_pickup, true, { - o = (head.absmin + head.absmax) * 0.5; - distance = vlen(o - org); + o = (it.absmin + it.absmax) * 0.5; friend_distance = 10000; enemy_distance = 10000; rating = 0; - if(!head.solid || distance > sradius || (head == this.ignoregoal && time < this.ignoregoaltime) ) - { - head = head.chain; + if(!it.solid || vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) ) continue; - } // Check if the item can be picked up safely - if(head.classname == "droppedweapon") + if(it.classname == "droppedweapon") { traceline(o, o + '0 0 -1500', true, NULL); d = pointcontents(trace_endpos + '0 0 1'); if(d & CONTENT_WATER || d & CONTENT_SLIME || d & CONTENT_LAVA) - { - head = head.chain; continue; - } - if(tracebox_hits_trigger_hurt(head.origin, head.mins, head.maxs, trace_endpos)) - { - head = head.chain; + if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos)) continue; - } } else { // Ignore items under water - traceline(head.origin + head.maxs, head.origin + head.maxs, MOVE_NORMAL, head); + traceline(it.origin + it.maxs, it.origin + it.maxs, MOVE_NORMAL, it); if(trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK) - { - head = head.chain; continue; - } } if(teamplay) { discard = false; - FOREACH_CLIENT(IS_PLAYER(it) && it != this && !IS_DEAD(it), LAMBDA( + entity picker = it; + FOREACH_CLIENT(IS_PLAYER(it) && it != this && !IS_DEAD(it), + { d = vlen(it.origin - o); // distance between player and item if ( it.team == this.team ) @@ -79,29 +66,29 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float discard = true; - if( head.health && it.health > this.health ) + if( picker.health && it.health > this.health ) continue; - if( head.armorvalue && it.armorvalue > this.armorvalue) + if( picker.armorvalue && it.armorvalue > this.armorvalue) continue; - if( head.weapons ) - if( head.weapons & ~it.weapons ) + if( picker.weapons ) + if( picker.weapons & ~it.weapons ) continue; - if (head.ammo_shells && it.ammo_shells > this.ammo_shells) + if (picker.ammo_shells && it.ammo_shells > this.ammo_shells) continue; - if (head.ammo_nails && it.ammo_nails > this.ammo_nails) + if (picker.ammo_nails && it.ammo_nails > this.ammo_nails) continue; - if (head.ammo_rockets && it.ammo_rockets > this.ammo_rockets) + if (picker.ammo_rockets && it.ammo_rockets > this.ammo_rockets) continue; - if (head.ammo_cells && it.ammo_cells > this.ammo_cells) + if (picker.ammo_cells && it.ammo_cells > this.ammo_cells) continue; - if (head.ammo_plasma && it.ammo_plasma > this.ammo_plasma) + if (picker.ammo_plasma && it.ammo_plasma > this.ammo_plasma) continue; discard = false; @@ -113,40 +100,33 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float if( d < enemy_distance ) enemy_distance = d; } - )); + }); // Rate the item only if no one needs it, or if an enemy is closer to it - if ( (enemy_distance < friend_distance && distance < enemy_distance) || + if ( (enemy_distance < friend_distance && vdist(o - org, <, enemy_distance)) || (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ) || !discard ) - rating = head.bot_pickupevalfunc(this, head); + rating = it.bot_pickupevalfunc(this, it); } else - rating = head.bot_pickupevalfunc(this, head); + rating = it.bot_pickupevalfunc(this, it); if(rating > 0) - navigation_routerating(this, head, rating * ratingscale, 2000); - head = head.chain; - } + navigation_routerating(this, it, rating * ratingscale, 2000); + }); } void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius) { - entity head; - head = findchain(classname, "dom_controlpoint"); - while (head) + FOREACH_ENTITY_CLASS("dom_controlpoint", vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius), { - if(vdist((((head.absmin + head.absmax) * 0.5) - org), <, sradius)) - { - if(head.cnt > -1) // this is just being fought for - navigation_routerating(this, head, ratingscale, 5000); - else if(head.goalentity.cnt == 0) // unclaimed point - navigation_routerating(this, head, ratingscale * 0.5, 5000); - else if(head.goalentity.team != this.team) // other team's point - navigation_routerating(this, head, ratingscale * 0.2, 5000); - } - head = head.chain; - } + if(it.cnt > -1) // this is just being fought + navigation_routerating(this, it, ratingscale, 5000); + else if(it.goalentity.cnt == 0) // unclaimed + navigation_routerating(this, it, ratingscale * 0.5, 5000); + else if(it.goalentity.team != this.team) // other team's point + navigation_routerating(this, it, ratingscale * 0.2, 5000); + }); } void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius) diff --git a/qcsrc/server/bot/navigation.qc b/qcsrc/server/bot/navigation.qc index 8deefdb39..21e5342c0 100644 --- a/qcsrc/server/bot/navigation.qc +++ b/qcsrc/server/bot/navigation.qc @@ -614,7 +614,7 @@ void navigation_markroutes_inverted(entity fixed_source_waypoint) entity w, wp, waylist; float searching, cost, cost2; vector p; - w = waylist = findchain(classname, "waypoint"); + w = waylist = findchain(classname, "waypoint"); // TODO while (w) { w.wpconsidered = false; @@ -1024,40 +1024,34 @@ void navigation_goalrating_end(entity this) void botframe_updatedangerousobjects(float maxupdate) { - entity head, bot_dodgelist; vector m1, m2, v, o; float c, d, danger; c = 0; - bot_dodgelist = findchainfloat(bot_dodge, true); - botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint"); - while (botframe_dangerwaypoint != NULL) + FOREACH_ENTITY_CLASS("waypoint", true, { danger = 0; - m1 = botframe_dangerwaypoint.mins; - m2 = botframe_dangerwaypoint.maxs; - head = bot_dodgelist; - while (head) + m1 = it.mins; + m2 = it.maxs; + FOREACH_ENTITY_FLOAT(bot_dodge, true, { - v = head.origin; + v = it.origin; v.x = bound(m1_x, v.x, m2_x); v.y = bound(m1_y, v.y, m2_y); v.z = bound(m1_z, v.z, m2_z); - o = (head.absmin + head.absmax) * 0.5; - d = head.bot_dodgerating - vlen(o - v); + o = (it.absmin + it.absmax) * 0.5; + d = it.bot_dodgerating - vlen(o - v); if (d > 0) { traceline(o, v, true, NULL); if (trace_fraction == 1) danger = danger + d; } - head = head.chain; - } - botframe_dangerwaypoint.dmg = danger; + }); + it.dmg = danger; c = c + 1; if (c >= maxupdate) break; - botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint"); - } + }); } void navigation_unstuck(entity this) diff --git a/qcsrc/server/bot/navigation.qh b/qcsrc/server/bot/navigation.qh index 7fef6afef..cf793068b 100644 --- a/qcsrc/server/bot/navigation.qh +++ b/qcsrc/server/bot/navigation.qh @@ -10,7 +10,6 @@ float navigation_testtracewalk; vector jumpstepheightvec; vector stepheightvec; -entity botframe_dangerwaypoint; entity navigation_bestgoal; // stack of current goals (the last one of which may be an item or other diff --git a/qcsrc/server/bot/scripting.qc b/qcsrc/server/bot/scripting.qc index 01a1117c9..291b22f5f 100644 --- a/qcsrc/server/bot/scripting.qc +++ b/qcsrc/server/bot/scripting.qc @@ -252,7 +252,7 @@ entity find_bot_by_number(float number) if(!number) return NULL; - bot = findchainflags(flags, FL_CLIENT); + bot = findchainflags(flags, FL_CLIENT); // TODO: doesn't findchainflags loop backwards through entities? while (bot) { if(IS_BOT_CLIENT(bot)) diff --git a/qcsrc/server/bot/waypoints.qc b/qcsrc/server/bot/waypoints.qc index 58bb0b46b..1a9b4784f 100644 --- a/qcsrc/server/bot/waypoints.qc +++ b/qcsrc/server/bot/waypoints.qc @@ -19,14 +19,11 @@ entity waypoint_spawn(vector m1, vector m2, float f) { if(!(f & WAYPOINTFLAG_PERSONAL)) { - for(entity wp = findchain(classname, "waypoint"); wp; wp = wp.chain) + FOREACH_ENTITY_CLASS("waypoint", boxesoverlap(m1, m2, it.absmin, it.absmax), { - // if a matching spawnfunc_waypoint already exists, don't add a duplicate - if(boxesoverlap(m1, m2, wp.absmin, wp.absmax)) - return wp; - } + return it; + }); } - entity w = new(waypoint); w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; @@ -344,28 +341,21 @@ void waypoint_remove(entity e) // empties the map of waypoints void waypoint_removeall() { - entity head, next; - head = findchain(classname, "waypoint"); - while (head) + FOREACH_ENTITY_CLASS("waypoint", true, { - next = head.chain; - remove(head); - head = next; - } + remove(it); + }); } // tell all waypoints to relink // (is this useful at all?) void waypoint_schedulerelinkall() { - entity head; relink_total = relink_walkculled = relink_pvsculled = relink_lengthculled = 0; - head = findchain(classname, "waypoint"); - while (head) + FOREACH_ENTITY_CLASS("waypoint", true, { - waypoint_schedulerelink(head); - head = head.chain; - } + waypoint_schedulerelink(it); + }); } // Load waypoint links from file @@ -588,87 +578,71 @@ entity waypoint_get_link(entity w, float i) // Save all waypoint links to a file void waypoint_save_links() { - string filename, s; - float file, c, i; - entity w, link; - filename = strcat("maps/", mapname); - filename = strcat(filename, ".waypoints.cache"); - file = fopen(filename, FILE_WRITE); + string filename = sprintf("maps/%s.waypoints.cache", mapname); + int file = fopen(filename, FILE_WRITE); if (file < 0) { - LOG_INFO("waypoint links save to "); - LOG_INFO(filename); - LOG_INFO(" failed\n"); + LOG_INFOF("waypoint link save to %s failed\n", filename); + return; } - c = 0; - w = findchain(classname, "waypoint"); - while (w) + + int c = 0; + FOREACH_ENTITY_CLASS("waypoint", true, { - for(i=0;i<32;++i) + for(int j = 0; j < 32; ++j) { - // :S - link = waypoint_get_link(w, i); - if(link==NULL) - continue; - - s = strcat(vtos(w.origin), "*", vtos(link.origin), "\n"); - fputs(file, s); - ++c; + entity link = waypoint_get_link(it, j); + if(link) + { + string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n"); + fputs(file, s); + ++c; + } } - w = w.chain; - } + }); fclose(file); botframe_cachedwaypointlinks = true; - LOG_INFO("saved "); - LOG_INFO(ftos(c)); - LOG_INFO(" waypoints links to maps/"); - LOG_INFO(mapname); - LOG_INFO(".waypoints.cache\n"); + LOG_INFOF("saved %d waypoint links to maps/%s.waypoints.cache\n", c, mapname); } // save waypoints to gamedir/data/maps/mapname.waypoints void waypoint_saveall() { - string filename, s; - float file, c; - entity w; - filename = strcat("maps/", mapname); - filename = strcat(filename, ".waypoints"); - file = fopen(filename, FILE_WRITE); - if (file >= 0) + string filename = sprintf("maps/%s.waypoints", mapname); + int file = fopen(filename, FILE_WRITE); + if (file < 0) { - c = 0; - w = findchain(classname, "waypoint"); - while (w) - { - if (!(w.wpflags & WAYPOINTFLAG_GENERATED)) - { - s = strcat(vtos(w.origin + w.mins), "\n"); - s = strcat(s, vtos(w.origin + w.maxs)); - s = strcat(s, "\n"); - s = strcat(s, ftos(w.wpflags)); - s = strcat(s, "\n"); - fputs(file, s); - c = c + 1; - } - w = w.chain; - } - fclose(file); - bprint("saved "); - bprint(ftos(c)); - bprint(" waypoints to maps/"); - bprint(mapname); - bprint(".waypoints\n"); + waypoint_save_links(); // save anyway? + botframe_loadedforcedlinks = false; + + LOG_INFOF("waypoint links: save to %s failed\n", filename); + return; } - else + + int c = 0; + FOREACH_ENTITY_CLASS("waypoint", true, { - bprint("waypoint save to "); - bprint(filename); - bprint(" failed\n"); - } + if(it.wpflags & WAYPOINTFLAG_GENERATED) + continue; + + for(int j = 0; j < 32; ++j) + { + string s; + s = strcat(vtos(it.origin + it.mins), "\n"); + s = strcat(s, vtos(it.origin + it.maxs)); + s = strcat(s, "\n"); + s = strcat(s, ftos(it.wpflags)); + s = strcat(s, "\n"); + fputs(file, s); + ++c; + } + }); + fclose(file); waypoint_save_links(); botframe_loadedforcedlinks = false; + + LOG_INFOF("saved %d waypoints to maps/%s.waypoints\n", c, mapname); } // load waypoints from file @@ -723,33 +697,30 @@ vector waypoint_fixorigin(vector position) void waypoint_spawnforitem_force(entity e, vector org) { - entity w; - // Fix the waypoint altitude if necessary org = waypoint_fixorigin(org); // don't spawn an item spawnfunc_waypoint if it already exists - w = findchain(classname, "waypoint"); - while (w) + FOREACH_ENTITY_CLASS("waypoint", true, { - if (w.wpisbox) + if(it.wpisbox) { - if (boxesoverlap(org, org, w.absmin, w.absmax)) + if(boxesoverlap(org, org, it.absmin, it.absmax)) { - e.nearestwaypoint = w; + e.nearestwaypoint = it; return; } } else { - if (vlen(w.origin - org) < 16) + if(vdist(it.origin - org, <, 16)) { - e.nearestwaypoint = w; + e.nearestwaypoint = it; return; } } - w = w.chain; - } + }); + e.nearestwaypoint = waypoint_spawn(org, org, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_ITEM); } diff --git a/qcsrc/server/cl_impulse.qc b/qcsrc/server/cl_impulse.qc index 517ee3796..f3fedf5f1 100644 --- a/qcsrc/server/cl_impulse.qc +++ b/qcsrc/server/cl_impulse.qc @@ -512,96 +512,93 @@ IMPULSE(navwaypoint_save) IMPULSE(navwaypoint_unreachable) { if (!autocvar_g_waypointeditor) return; - for (entity e = findchain(classname, "waypoint"); e; e = e.chain) + FOREACH_ENTITY_CLASS("waypoint", true, { - e.colormod = '0.5 0.5 0.5'; - e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE); - } + it.colormod = '0.5 0.5 0.5'; + it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE); + }); entity e2 = navigation_findnearestwaypoint(this, false); navigation_markroutes(this, e2); - int i, m; + int j, m; - i = 0; + j = 0; m = 0; - for (entity e = findchain(classname, "waypoint"); e; e = e.chain) + FOREACH_ENTITY_CLASS("waypoint", it.wpcost >= 10000000, { - if (e.wpcost < 10000000) continue; - LOG_INFO("unreachable: ", etos(e), " ", vtos(e.origin), "\n"); - e.colormod_z = 8; - e.effects |= EF_NODEPTHTEST | EF_BLUE; - ++i; + LOG_INFO("unreachable: ", etos(it), " ", vtos(it.origin), "\n"); + it.colormod_z = 8; + it.effects |= EF_NODEPTHTEST | EF_BLUE; + ++j; ++m; - } - if (i) LOG_INFOF("%d waypoints cannot be reached from here in any way (marked with blue light)\n", i); + }); + if (j) LOG_INFOF("%d waypoints cannot be reached from here in any way (marked with blue light)\n", j); navigation_markroutes_inverted(e2); - i = 0; - for (entity e = findchain(classname, "waypoint"); e; e = e.chain) + j = 0; + FOREACH_ENTITY_CLASS("waypoint", it.wpcost >= 10000000, { - if (e.wpcost < 10000000) continue; - LOG_INFO("cannot reach me: ", etos(e), " ", vtos(e.origin), "\n"); - e.colormod_x = 8; - if (!(e.effects & EF_NODEPTHTEST)) // not already reported before + LOG_INFO("cannot reach me: ", etos(it), " ", vtos(it.origin), "\n"); + it.colormod_x = 8; + if (!(it.effects & EF_NODEPTHTEST)) // not already reported before ++m; - e.effects |= EF_NODEPTHTEST | EF_RED; - ++i; - } - if (i) LOG_INFOF("%d waypoints cannot walk to here in any way (marked with red light)\n", i); + it.effects |= EF_NODEPTHTEST | EF_RED; + ++j; + }); + if (j) LOG_INFOF("%d waypoints cannot walk to here in any way (marked with red light)\n", j); if (m) LOG_INFOF("%d waypoints have been marked total\n", m); - i = 0; - for (entity e = findchain(classname, "info_player_deathmatch"); e; e = e.chain) + j = 0; + FOREACH_ENTITY_CLASS("info_player_deathmatch", true, { - vector org = e.origin; - tracebox(e.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), e.origin - '0 0 512', MOVE_NOMONSTERS, NULL); - setorigin(e, trace_endpos); - if (navigation_findnearestwaypoint(e, false)) + vector org = it.origin; + tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - '0 0 512', MOVE_NOMONSTERS, NULL); + setorigin(it, trace_endpos); + if (navigation_findnearestwaypoint(it, false)) { - setorigin(e, org); - e.effects &= ~EF_NODEPTHTEST; - e.model = ""; + setorigin(it, org); + it.effects &= ~EF_NODEPTHTEST; + it.model = ""; } else { - setorigin(e, org); - LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n"); - e.effects |= EF_NODEPTHTEST; - _setmodel(e, this.model); - e.frame = this.frame; - e.skin = this.skin; - e.colormod = '8 0.5 8'; - setsize(e, '0 0 0', '0 0 0'); - ++i; + setorigin(it, org); + LOG_INFO("spawn without waypoint: ", etos(it), " ", vtos(it.origin), "\n"); + it.effects |= EF_NODEPTHTEST; + _setmodel(it, this.model); + it.frame = this.frame; + it.skin = this.skin; + it.colormod = '8 0.5 8'; + setsize(it, '0 0 0', '0 0 0'); + ++j; } - } - if (i) LOG_INFOF("%d spawnpoints have no nearest waypoint (marked by player model)\n", i); + }); + if (j) LOG_INFOF("%d spawnpoints have no nearest waypoint (marked by player model)\n", j); - i = 0; - entity start = findchainflags(flags, FL_ITEM); - for (entity e = start; e; e = e.chain) + j = 0; + FOREACH_ENTITY_FLAGS(flags, FL_ITEM, { - e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE); - e.colormod = '0.5 0.5 0.5'; - } - for (entity e = start; e; e = e.chain) + it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE); + it.colormod = '0.5 0.5 0.5'; + }); + FOREACH_ENTITY_FLAGS(flags, FL_ITEM, { - if (navigation_findnearestwaypoint(e, false)) continue; - LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n"); - e.effects |= EF_NODEPTHTEST | EF_RED; - e.colormod_x = 8; - ++i; - } - if (i) LOG_INFOF("%d items have no nearest waypoint and cannot be walked away from (marked with red light)\n", i); + if (navigation_findnearestwaypoint(it, false)) continue; + LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n"); + it.effects |= EF_NODEPTHTEST | EF_RED; + it.colormod_x = 8; + ++j; + }); + if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked away from (marked with red light)\n", j); - i = 0; - for (entity e = start; e; e = e.chain) + j = 0; + FOREACH_ENTITY_FLAGS(flags, FL_ITEM, { - if (navigation_findnearestwaypoint(e, true)) continue; - LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n"); - e.effects |= EF_NODEPTHTEST | EF_BLUE; - e.colormod_z = 8; - ++i; - } - if (i) LOG_INFOF("%d items have no nearest waypoint and cannot be walked to (marked with blue light)\n", i); + if (navigation_findnearestwaypoint(it, true)) continue; + LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n"); + it.effects |= EF_NODEPTHTEST | EF_BLUE; + it.colormod_z = 8; + ++j; + }); + if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked to (marked with blue light)\n", j); } diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 2686e0553..93cbab001 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -33,20 +33,25 @@ void crosshair_trace(entity pl) { traceline_antilag(pl, pl.cursor_trace_start, pl.cursor_trace_start + normalize(pl.cursor_trace_endpos - pl.cursor_trace_start) * MAX_SHOT_DISTANCE, MOVE_NORMAL, pl, ANTILAG_LATENCY(pl)); } +.bool ctrace_solidchanged; void crosshair_trace_plusvisibletriggers(entity pl) { - entity first; - entity e; - first = findchainfloat(solid, SOLID_TRIGGER); - - for (e = first; e; e = e.chain) - if (e.model != "") - e.solid = SOLID_BSP; + FOREACH_ENTITY_FLOAT(solid, SOLID_TRIGGER, + { + if(it.model != "") + { + it.solid = SOLID_BSP; + it.ctrace_solidchanged = true; + } + }); crosshair_trace(pl); - for (e = first; e; e = e.chain) - e.solid = SOLID_TRIGGER; + FOREACH_ENTITY_FLOAT(ctrace_solidchanged, true, + { + it.solid = SOLID_TRIGGER; + it.ctrace_solidchanged = false; + }); } void WarpZone_crosshair_trace(entity pl) { diff --git a/qcsrc/server/mutators/mutator/gamemode_assault.qc b/qcsrc/server/mutators/mutator/gamemode_assault.qc index cab30262a..6ce572437 100644 --- a/qcsrc/server/mutators/mutator/gamemode_assault.qc +++ b/qcsrc/server/mutators/mutator/gamemode_assault.qc @@ -429,68 +429,48 @@ spawnfunc(target_assault_roundstart) // legacy bot code void havocbot_goalrating_ast_targets(entity this, float ratingscale) { - entity ad, best, wp; - float radius, bestvalue; - bool found; - vector p; - - ad = findchain(classname, "func_assault_destructible"); - - for (; ad; ad = ad.chain) + FOREACH_ENTITY_CLASS("func_assault_destructible", it.bot_attack, { - if (ad.target == "") - continue; - - if (!ad.bot_attack) + if (it.target == "") continue; - found = false; - FOREACH_ENTITY_STRING(targetname, ad.target, + bool found = false; + FOREACH_ENTITY_STRING(targetname, it.target, { - if(it.classname == "target_objective_decrease") + if(it.classname != "target_objective_decrease") + continue; + + if(it.enemy.health > 0 && it.enemy.health < ASSAULT_VALUE_INACTIVE) { - if(it.enemy.health > 0 && it.enemy.health < ASSAULT_VALUE_INACTIVE) - { - // dprint(etos(ad),"\n"); - found = true; - break; - } + found = true; + break; } }); if(!found) - { - /// dprint("target not found\n"); continue; - } - /// dprint("target #", etos(ad), " found\n"); - - p = 0.5 * (ad.absmin + ad.absmax); - // dprint(vtos(ad.origin), " ", vtos(ad.absmin), " ", vtos(ad.absmax),"\n"); - // te_knightspike(p); - // te_lightning2(NULL, '0 0 0', p); + vector p = 0.5 * (it.absmin + it.absmax); // Find and rate waypoints around it found = false; - best = NULL; - bestvalue = 99999999999; - for(radius=0; radius<1500 && !found; radius+=500) + entity best = NULL; + float bestvalue = 99999999999; + entity des = it; + for(float radius = 0; radius < 1500 && !found; radius += 500) { - for(wp=findradius(p, radius); wp; wp=wp.chain) + FOREACH_ENTITY_RADIUS(p, radius, it.classname == "waypoint" && !(it.wpflags & WAYPOINTFLAG_GENERATED), { - if(!(wp.wpflags & WAYPOINTFLAG_GENERATED)) - if(wp.classname=="waypoint") - if(checkpvs(wp.origin, ad)) + if(checkpvs(it.origin, des)) { found = true; - if(wp.cnt 0) - navigation_routerating(this, head, t * ratingscale, 500); + navigation_routerating(this, it, t * ratingscale, 500); } - head = head.chain; - } + }); } void havocbot_ctf_reset_role(entity this) diff --git a/qcsrc/server/pathlib/main.qc b/qcsrc/server/pathlib/main.qc index b6e135078..0a28f206d 100644 --- a/qcsrc/server/pathlib/main.qc +++ b/qcsrc/server/pathlib/main.qc @@ -6,15 +6,11 @@ void pathlib_deletepath(entity start) { - entity e; - - e = findchainentity(owner, start); - while(e) + FOREACH_ENTITY_ENT(owner, start, { - setthink(e, SUB_Remove); - e.nextthink = time; - e = e.chain; - } + setthink(it, SUB_Remove); + it.nextthink = time; + }); } //#define PATHLIB_NODEEXPIRE 0.05 @@ -218,9 +214,6 @@ float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector go entity pathlib_getbestopen() { - entity node; - entity bestnode; - if(best_open_node) { ++pathlib_bestcash_hits; @@ -229,19 +222,14 @@ entity pathlib_getbestopen() return best_open_node; } - node = findchainentity(owner,openlist); - if(!node) - return NULL; - - bestnode = node; - while(node) + entity bestnode = NULL; + FOREACH_ENTITY_ENT(owner, openlist, { - ++pathlib_bestopen_seached; - if(node.pathlib_node_f < bestnode.pathlib_node_f) - bestnode = node; + ++pathlib_bestopen_searched; - node = node.chain; - } + if(!bestnode || it.pathlib_node_f < bestnode.pathlib_node_f) + bestnode = it; + }); return bestnode; } @@ -432,7 +420,7 @@ entity pathlib_astar(entity this, vector from,vector to) pathlib_made_cnt = 0; pathlib_merge_cnt = 0; pathlib_searched_cnt = 0; - pathlib_bestopen_seached = 0; + pathlib_bestopen_searched = 0; pathlib_bestcash_hits = 0; pathlib_bestcash_saved = 0; @@ -561,7 +549,7 @@ entity pathlib_astar(entity this, vector from,vector to) LOG_TRACE("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n"); LOG_TRACE("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n"); LOG_TRACE("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n"); - LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n"); + LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_searched),"\n"); LOG_TRACE("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n"); LOG_TRACE("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n"); LOG_TRACE("AStar done.\n"); diff --git a/qcsrc/server/pathlib/path_waypoint.qc b/qcsrc/server/pathlib/path_waypoint.qc index 35dcce5b2..01a6e2c74 100644 --- a/qcsrc/server/pathlib/path_waypoint.qc +++ b/qcsrc/server/pathlib/path_waypoint.qc @@ -114,20 +114,16 @@ float pathlib_wpp_expand(entity wp) entity pathlib_wpp_bestopen() { - entity n, best; - if(best_open_node) return best_open_node; - n = findchainentity(pathlib_list, openlist); - best = n; - while(n) - { - if(n.pathlib_node_f < best.pathlib_node_f) - best = n; + entity best = NULL; - n = n.chain; - } + FOREACH_ENTITY_ENT(pathlib_list, openlist, + { + if(!best || it.pathlib_node_f < best.pathlib_node_f) + best = it; + }); return best; @@ -135,7 +131,6 @@ entity pathlib_wpp_bestopen() entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback) { - entity n; float ptime; ptime = gettime(GETTIME_REALTIME); @@ -168,19 +163,18 @@ entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback) // Initialize waypoint grid // FIXME! presisted chain for better preformance - for(n = findchain(classname, "waypoint"); n; n = n.chain) + FOREACH_ENTITY_CLASS("waypoint", true, { - n.pathlib_list = NULL; - n.pathlib_node_g = 0; - n.pathlib_node_f = 0; - n.pathlib_node_h = 0; - - //setmodel(n, "models/runematch/rune.mdl"); - //n.effects = EF_LOWPRECISION; - //n.colormod = '0 0 0'; - //n.scale = 1; - - } + it.pathlib_list = NULL; + it.pathlib_node_g = 0; + it.pathlib_node_f = 0; + it.pathlib_node_h = 0; + + //setmodel(it, "models/runematch/rune.mdl"); + //it.effects = EF_LOWPRECISION; + //it.colormod = '0 0 0'; + //it.scale = 1; + }); goal_node = wp_to; start_node = wp_from; diff --git a/qcsrc/server/pathlib/pathlib.qh b/qcsrc/server/pathlib/pathlib.qh index a5f36da4a..339a2e7e0 100644 --- a/qcsrc/server/pathlib/pathlib.qh +++ b/qcsrc/server/pathlib/pathlib.qh @@ -46,7 +46,7 @@ float pathlib_closed_cnt; float pathlib_made_cnt; float pathlib_merge_cnt; float pathlib_searched_cnt; -float pathlib_bestopen_seached; +float pathlib_bestopen_searched; float pathlib_bestcash_hits; float pathlib_bestcash_saved; float pathlib_gridsize; diff --git a/qcsrc/server/steerlib.qc b/qcsrc/server/steerlib.qc index ef95e7b64..fce976851 100644 --- a/qcsrc/server/steerlib.qc +++ b/qcsrc/server/steerlib.qc @@ -597,20 +597,14 @@ void flocker_hunter_think(entity this) if(!this.enemy) { - e = findchainfloat(flock_id,this.flock_id); - while(e) + FOREACH_ENTITY_FLOAT(flock_id, this.flock_id, { - d = vlen(this.origin - e.origin); - - if(e != this.owner) - if(e != ee) - if(d > bd) - { - this.enemy = e; - bd = d; - } - e = e.chain; - } + if(it == this.owner || it == ee) + continue; + + if(!this.enemy || vlen2(this.origin - it.origin) < vlen2(this.origin - this.enemy.origin)) + this.enemy = it; + }); } if(this.enemy) @@ -624,7 +618,6 @@ void flocker_hunter_think(entity this) this.velocity = movelib_inertmove_byspeed(this, newmove,1250,0.3,0.7); this.velocity = movelib_dragvec(this, 0.01,0.5); - this.angles = vectoangles(this.velocity); this.nextthink = time + 0.1; }