bool Utility::AntiHumanRadiusDamage(Entity& entity, float amount, float range, meansOfDeath_t mod) { bool hit = false; ForEntities<HumanClassComponent>([&] (Entity& other, HumanClassComponent& humanClassComponent) { // TODO: Add LocationComponent. float distance = G_Distance(entity.oldEnt, other.oldEnt); float damage = amount * (1.0f - distance / range); if (damage <= 0.0f) return; if (!G_IsVisible(entity.oldEnt, other.oldEnt, MASK_SOLID)) return; if (other.Damage(damage, entity.oldEnt, {}, {}, DAMAGE_NO_LOCDAMAGE, mod)) { hit = true; } }); return hit; }
bool Utility::KnockbackRadiusDamage(Entity& entity, float amount, float range, meansOfDeath_t mod) { bool hit = false; // FIXME: Only considering entities with HealthComponent. // TODO: Allow ForEntities to iterate over all entities. ForEntities<HealthComponent>([&] (Entity& other, HealthComponent& healthComponent) { // TODO: Add LocationComponent. float distance = G_Distance(entity.oldEnt, other.oldEnt); float damage = amount * (1.0f - distance / range); if (damage <= 0.0f) return; if (!G_IsVisible(entity.oldEnt, other.oldEnt, MASK_SOLID)) return; if (other.Damage(damage, entity.oldEnt, {}, {}, DAMAGE_NO_LOCDAMAGE | DAMAGE_KNOCKBACK, mod)) { hit = true; } }); return hit; }
void G_HomingMissile(gentity_t * ent) { gentity_t *target = NULL; gentity_t *blip = NULL; vec3_t dir, blipdir; vec_t angle; qboolean chaff; //qboolean ignorechaff = qfalse; const int HOMING_THINK_TIME = 60; // explode after 15 seconds without a hit if(ent->spawnTime + 15000 <= level.time) { G_ExplodeMissile(ent); return; } /* if(ent->parent->health <= 0) { ent->nextthink = level.time + 15000; ent->think = G_ExplodeMissile; return; } */ /* if(ent->parent && ent->parent->client) { ignorechaff = (ent->parent->client->ps.powerups[PW_ACCURACY] > 0); } */ while((blip = G_FindRadius(blip, ent->r.currentOrigin, 2000)) != NULL) { #if 0 if(blip->s.weapon == WP_CHAFF) { if(ignorechaff) { continue; } chaff = qtrue; } else #endif { chaff = qfalse; if(blip->client == NULL) continue; if(blip == ent->parent) continue; if(blip->health <= 0) continue; if(blip->client->sess.sessionTeam >= TEAM_SPECTATOR) continue; if((g_gametype.integer == GT_TEAM || g_gametype.integer == GT_CTF) && OnSameTeam(blip, ent->parent)) continue; } if(!G_IsVisible(ent, blip->r.currentOrigin)) continue; VectorSubtract(blip->r.currentOrigin, ent->r.currentOrigin, blipdir); if(chaff) { VectorScale(blipdir, 0.5, blipdir); } if((target == NULL) || (VectorLength(blipdir) < VectorLength(dir))) { if(chaff) { VectorScale(blipdir, 2, blipdir); } angle = AngleBetweenVectors(ent->r.currentAngles, blipdir); if(angle < 120.0f) { // We add it as our target target = blip; VectorCopy(blipdir, dir); } } } if(target == NULL) { ent->nextthink = level.time + HOMING_THINK_TIME; // + 10000; ent->think = G_HomingMissile; } else { // for exact trajectory calculation, set current point to base. VectorCopy(ent->r.currentOrigin, ent->s.pos.trBase); VectorNormalize(dir); // 0.5 is swing rate. VectorScale(dir, 0.5, dir); VectorAdd(dir, ent->r.currentAngles, dir); // turn nozzle to target angle VectorNormalize(dir); VectorCopy(dir, ent->r.currentAngles); // scale direction, put into trDelta if(g_rocketAcceleration.integer) { // use acceleration instead of linear velocity ent->s.pos.trType = TR_ACCELERATION; ent->s.pos.trAcceleration = g_rocketAcceleration.value; VectorScale(dir, g_rocketVelocity.value, ent->s.pos.trDelta); } else { ent->s.pos.trType = TR_LINEAR; VectorScale(dir, g_rocketVelocity.value * 0.25, ent->s.pos.trDelta); } ent->s.pos.trTime = level.time; SnapVector(ent->s.pos.trDelta); // save net bandwidth ent->nextthink = level.time + HOMING_THINK_TIME; // decrease this value also makes fast swing ent->think = G_HomingMissile; //G_Printf("targeting %s\n", target->classname); } }
/* ================ G_HomingMissile From XREAL r3036 ================ */ void G_HomingMissile(gentity_t * ent) { gentity_t *target = NULL; gentity_t *blip = NULL; vec3_t dir, blipdir; vec_t angle; const int HOMING_THINK_TIME = 60; #ifdef TA_WEAPSYS // XREAL: spawnTime // explode after 15 seconds without a hit if (bg_projectileinfo[ent->s.weapon].timetolive != -1 && ent->spawnTime + bg_projectileinfo[ent->s.weapon].timetolive <= level.time) { G_ExplodeMissile(ent); return; } #endif /* if(ent->parent->health <= 0) { ent->nextthink = level.time + 15000; ent->think = G_ExplodeMissile; return; } */ while((blip = G_FindRadius(blip, ent->r.currentOrigin, 2000)) != NULL) { if(blip->player == NULL) continue; if(blip == ent->parent) continue; if(blip->health <= 0) continue; if(blip->flags & FL_NOTARGET) continue; if(blip->player->sess.sessionTeam >= TEAM_SPECTATOR) continue; if(OnSameTeam(blip, ent->parent)) continue; if(!G_IsVisible(ent->s.number, ent->r.currentOrigin, blip->r.currentOrigin)) continue; VectorSubtract(blip->r.currentOrigin, ent->r.currentOrigin, blipdir); if((target == NULL) || (VectorLength(blipdir) < VectorLength(dir))) { angle = AngleBetweenVectors(ent->r.currentAngles, blipdir); if(angle < 120.0f) { // We add it as our target target = blip; VectorCopy(blipdir, dir); } } } if (target == NULL) { ent->nextthink = level.time + HOMING_THINK_TIME; // + 10000; ent->think = G_HomingMissile; } else { // for exact trajectory calculation, set current point to base. VectorCopy(ent->r.currentOrigin, ent->s.pos.trBase); VectorNormalize(dir); // 0.5 is swing rate. VectorScale(dir, 0.5, dir); VectorAdd(dir, ent->r.currentAngles, dir); // turn nozzle to target angle VectorNormalize(dir); VectorCopy(dir, ent->r.currentAngles); ent->s.pos.trTime = level.time; G_SetMissileVelocity(ent, dir, ent->s.weapon); ent->nextthink = level.time + HOMING_THINK_TIME; // decrease this value also makes fast swing ent->think = G_HomingMissile; //G_Printf("targeting %s\n", target->classname); } }