bool UnitBase::isInAttackRange(const ObjectBase* pObject) const { int checkRange; switch(attackMode) { case GUARD: { checkRange = getWeaponRange(); } break; case AREAGUARD: { checkRange = getAreaGuardRange() + getWeaponRange() + 1; } break; case AMBUSH: { checkRange = getViewRange() + 1; } break; case HUNT: { return true; } break; case STOP: default: { return false; } break; } if(getItemID() == Unit_Sandworm) { checkRange = getViewRange() + 1; } return (blockDistance(guardPoint*TILESIZE + Coord(TILESIZE/2, TILESIZE/2), pObject->getCenterPoint()) <= checkRange*TILESIZE); }
virtual void calculate(const float dt) { if (!_reaction.tick(dt)) return; float range = getWeaponRange(_object); //LOG_DEBUG(("range = %g", range)); _state.fire = false; const Object * result = NULL; float dist = -1; std::set<const Object *> objects; enumerate_objects(objects, range, &ai::Targets->troops ); for(std::set<const Object *>::const_iterator i = objects.begin(); i != objects.end(); ++i) { const Object *target = *i; if (has_same_owner(target) || target->ai_disabled() || target->pierceable || target->impassability == 0 || target->hp <= 0) continue; v2<float> dpos = get_relative_position(target); if (check_distance(get_center_position(), target->get_center_position(), get_z(), true)) { if (result == NULL || dpos.quick_length() < dist) { result = target; dist = dpos.quick_length(); } } } if (result != NULL) { _state.fire = true; _direction = get_relative_position(result); _direction.normalize(); //set_direction(_direction.get_direction(get_directions_number()) - 1); } }
bool UnitBase::isInWeaponRange(const ObjectBase* object) const { if(object == NULL) { return false; } Coord targetLocation = target.getObjPointer()->getClosestPoint(location); return (blockDistance(location, targetLocation) <= getWeaponRange()); }
void Cannon::calculate(const float dt) { if (!_reaction.tick(dt)) return; static float range = getWeaponRange("cannon-bullet"); v2<float> pos, vel; if (get_nearest(_variants.has("trainophobic")? ai::Targets->infantry_and_train: ai::Targets->infantry, range, pos, vel, true)) { pos.normalize(); set_direction(pos.get_direction(get_directions_number()) - 1); _direction = pos; _state.fire = true; } else _state.fire = false; }
void calculate(const float dt) { if (!_reaction.tick(dt)) return; if (_parent == NULL) throw_ex(("turret is only operable attached to shilka ")); if (_parent->disable_ai && PlayerManager->get_slot_by_id(_parent->get_id()) == NULL) { Object::calculate(dt); return; } v2<float> pos, vel; std::set<const Object *> objects; _parent->enumerate_objects(objects, getWeaponRange("shilka-bullet"), &ai::Targets->troops); int dirs = get_directions_number(); //int parent_dir = _parent->get_direction(); //(_parent->get_direction() - _parent->get_directions_number() / 2) * get_directions_number() / _parent->get_directions_number(); const Object *target = NULL; v2<float> target_pos; for(std::set<const Object *>::iterator i = objects.begin(); i != objects.end(); ++i) { const Object *o = *i; if (o->get_id() == _parent->get_id() || o->impassability == 0 || o->hp <= 0 || PIERCEABLE_PAIR(_parent, o) || !ZBox::sameBox(_parent->get_z(), o->get_z()) || _parent->has_same_owner(o) || o->has_effect("invulnerability") ) continue; pos = get_relative_position(o); if (target == NULL || pos.quick_length() < target_pos.quick_length()) { target = o; target_pos = pos; } //LOG_DEBUG(("%s <- dir: %d, parent_dir: %d (%g, %g)", o->animation.c_str(), dir, parent_dir, pos.x, pos.y)); } target_pos.normalize(); int dir = target_pos.get_direction(dirs) - 1; if (target == NULL || dir < 0) { Object::calculate(dt); return; } _direction = target_pos; set_direction(dir); }
void UnitBase::engageTarget() { if(target && (target.getObjPointer() == NULL)) { // the target does not exist anymore releaseTarget(); return; } if(target && (target.getObjPointer()->isActive() == false)) { // the target changed its state to inactive releaseTarget(); return; } if(target && !targetFriendly && !canAttack(target.getObjPointer())) { // the (non-friendly) target cannot be attacked anymore releaseTarget(); return; } if(target && !targetFriendly && !forced && !isInAttackRange(target.getObjPointer())) { // the (non-friendly) target left the attack mode range (and we were not forced to attack it) releaseTarget(); return; } if(target) { // we have a target unit or structure Coord targetLocation = target.getObjPointer()->getClosestPoint(location); if(destination != targetLocation) { // the location of the target has moved // => recalculate path clearPath(); } targetDistance = blockDistance(location, targetLocation); Sint8 newTargetAngle = lround(8.0f/256.0f*destinationAngle(location, targetLocation)); if(newTargetAngle == 8) { newTargetAngle = 0; } if(bFollow) { // we are following someone setDestination(targetLocation); return; } if(targetDistance > getWeaponRange()) { // we are not in attack range // => follow the target setDestination(targetLocation); return; } // we are in attack range if(targetFriendly && !forced) { // the target is friendly and we only attack these if were forced to do so return; } if(goingToRepairYard) { // we are going to the repair yard // => we do not need to change the destination targetAngle = INVALID; } else if(attackMode == CAPTURE) { // we want to capture the target building setDestination(targetLocation); targetAngle = INVALID; } else if(isTracked() && target.getObjPointer()->isInfantry() && currentGameMap->tileExists(targetLocation) && !currentGameMap->getTile(targetLocation)->isMountain() && forced) { // we squash the infantry unit because we are forced to setDestination(targetLocation); targetAngle = INVALID; } else { // we decide to fire on the target thus we can stop moving setDestination(location); targetAngle = newTargetAngle; } if(getCurrentAttackAngle() == newTargetAngle) { attack(); } } else if(attackPos) { // we attack a position targetDistance = blockDistance(location, attackPos); Sint8 newTargetAngle = lround(8.0f/256.0f*destinationAngle(location, attackPos)); if(newTargetAngle == 8) { newTargetAngle = 0; } if(targetDistance <= getWeaponRange()) { // we are in weapon range thus we can stop moving setDestination(location); targetAngle = newTargetAngle; if(getCurrentAttackAngle() == newTargetAngle) { attack(); } } else { targetAngle = INVALID; } } }