bool
FighterTacticalAI::IsStrikeComplete(Instruction* instr)
{
	// wingmen can not call a halt to a strike:
	if (!ship || element_index > 1)
	return false;

	// if there's nothing to shoot at, we must be done:
	if (!instr || !instr->GetTarget() || instr->GetTarget()->Life() == 0 ||
			instr->GetTarget()->Type() != SimObject::SIM_SHIP)
	return true;

	// break off strike only when ALL weapons are expended:
	// (remember to check all relevant wingmen)
	Element*    element = ship->GetElement();
	Ship*       target  = (Ship*) instr->GetTarget();

	if (!element)
	return true;

	for (int i = 0; i < element->NumShips(); i++) {
		Ship* s = element->GetShip(i+1);

		if (!s || s->Integrity() < 25) // || (s->Location() - target->Location()).length() > 250e3)
		continue;

		ListIter<WeaponGroup> g_iter = s->Weapons();
		while (++g_iter) {
			WeaponGroup* w = g_iter.value();

			if (w->Ammo() && w->CanTarget(target->Class())) {
				ListIter<Weapon> w_iter = w->GetWeapons();

				while (++w_iter) {
					Weapon* weapon = w_iter.value();

					if (weapon->Status() > System::CRITICAL)
					return false;
				}
			}
		}
	}

	// still here?  we must be done!
	return true;
}
int
FighterTacticalAI::ListSecondariesForTarget(Ship* tgt, List<WeaponGroup>& weps)
{
	weps.clear();

	if (tgt) {
		ListIter<WeaponGroup> iter = ship->Weapons();
		while (++iter) {
			WeaponGroup* w = iter.value();

			if (w->Ammo() && w->CanTarget(tgt->Class()))
			weps.append(w);
		}
	}

	return weps.size();
}
Ejemplo n.º 3
0
void
NetPlayer::SetShip(Ship* s)
{
	if (ship != s) {
		if (ship) {
			ship->EnableRepair(true);
			Ignore(ship);
		}

		ship = s;

		if (ship) {
			Observe(ship);
			ship->SetNetworkControl(this);
			ship->SetObjID(objid);

			iff = ship->GetIFF();

			// Turn off auto-repair.  All repair data should
			// come in over the network from the remote player:

			ship->EnableRepair(false);

			// Set all ship weapons back to manual fire control.
			// All trigger events should come over the network,
			// not from weapon auto aiming ai:

			ListIter<WeaponGroup> iter = ship->Weapons();
			while (++iter) {
				WeaponGroup* group = iter.value();

				ListIter<Weapon> w_iter = group->GetWeapons();
				while (++w_iter) {
					Weapon* weapon = w_iter.value();

					weapon->SetFiringOrders(Weapon::MANUAL);
				}
			}
		}
	}
}
Ejemplo n.º 4
0
void
GroundAI::ExecFrame(double secs)
{
    const int exec_period = 1000;

    if ((int) Game::GameTime() - exec_time > exec_period) {
        exec_time = (int) Game::GameTime();
        SelectTarget();
    }

    if (ship) {
        Shield* shield = ship->GetShield();

        if (shield)
        shield->SetPowerLevel(100);

        ListIter<WeaponGroup> iter = ship->Weapons();
        while (++iter) {
            WeaponGroup* group = (WeaponGroup*) iter.value();

            if (group->NumWeapons() > 1 && group->CanTarget(Ship::DROPSHIPS))
            group->SetFiringOrders(Weapon::POINT_DEFENSE);
            else
            group->SetFiringOrders(Weapon::AUTO);

            group->SetTarget((Ship*) target, 0);
        }

        if (carrier_ai)
        carrier_ai->ExecFrame(secs);
    }
}
bool
StarshipAI::AssessTargetPointDefense()
{
	if (Game::GameTime() - point_defense_time < 3500)
	return tgt_point_defense;

	tgt_point_defense = false;

	if (!target || target->Type() != SimObject::SIM_SHIP || GetAILevel() < 2)
	return tgt_point_defense;

	Ship* tgt_ship = (Ship*) target;

	if (!tgt_ship->IsStarship())
	return tgt_point_defense;

	Weapon*  subtgt = 0;
	Point    svec   = ship->Location() - tgt_ship->Location();

	point_defense_time = Game::GameTime();

	// first pass: turrets
	ListIter<WeaponGroup> g_iter = tgt_ship->Weapons();
	while (++g_iter && !tgt_point_defense) {
		WeaponGroup* g = g_iter.value();

		if (g->CanTarget(1)) {
			ListIter<Weapon> w_iter = g->GetWeapons();
			while (++w_iter && !tgt_point_defense) {
				Weapon* w = w_iter.value();

				if (w->Availability() > 35 && w->GetAimVector() * svec > 0)
				tgt_point_defense = true;
			}
		}
	}

	return tgt_point_defense;
}
Ejemplo n.º 6
0
bool Model::Read()
{
    int chunk;
    FILE *f;
    ImgString ist;

    if (filename.Length() == 0)
    {
        ErrorMsg("Project has no filename.");
        return false;
    }
    f = fopen(filename.c_str(), "rb");
    if (f == NULL)
    {
        ErrorMsg("Could not open %s for binary reading.", filename.c_str());
        return false;
    }

    int nmeshes;
    Mesh *m;

    // Header
    fread(&nmeshes, sizeof nmeshes, 1, f);
    if (nmeshes != GEO_MAGIC)
    {
        ErrorMsg("This is not a Segeltuch Project file");
        return false;
    }
    fread(&nmeshes, sizeof nmeshes, 1, f);
    fread(&nlods, sizeof nlods, 1, f);

    // Info
    meshes.insert(meshes.end(), nmeshes, Mesh());
    for (m=meshes.begin(); m != meshes.end(); m++)
    {
        m->Read(f);
    }

    // Additional resources
    int ntexts, i;
    char str[128];
    int nt, ng;
    Thruster *trstr;
    Glow *glow;
    // Process them
    while (fread(&chunk, 4, 1, f))
    {
        switch (chunk)
        {
        case TEXT_ID:
            fread(&ntexts, 4, 1, f);
            //InfoMsg("%d Textures found", ntexts);
            while (ntexts)
            {
                fread(&i, 4, 1, f);
                fread(str, i+1, 1, f);
                ist.s = str; ist.image = 0;
                mats.push_back(ist);
                ntexts--;
            }
            break;
        case SHLD_ID:
            shields.Read(f);
            break;
        case OLD_WEAP_ID:  /////// REMOVE AS SOON AS POSSIBLE ////////
            {
            fread(&i, 4, 1, f);
            WeaponGroup wg;
            int group_gun = 0, group_mis = 0, group;
            while (i > 0)
            {
                wg.Read(f); i--;
                if (wg.type == WT_GUN)
                    group = group_gun++;
                else
                    group = group_mis++;
                size_t wi = weapons.size();
                weapons.insert(weapons.end(), wg.weapons.size(), Weapon());
                for (size_t w=0; w < wg.weapons.size(); w++, wi++)
                {
                    weapons[wi].Type  = wg.type;
                    weapons[wi].ID    = w;
                    weapons[wi].Group = group;
                    weapons[wi].Pos   = wg.weapons[w].Pos;
                    weapons[wi].Normal= wg.weapons[w].Normal;
                }
            }
            }                           ///////////////
            break;
        case NEW_WEAP_ID:
            fread(&i, 4, 1, f);
            weapons.clear();
            weapons.insert(weapons.end(), i, Weapon());
            for (int w=0; w < i; w++)
            {
                weapons[w].Read(f);
            }
            break;
        case THRUST_ID:
            fread(&i, 4, 1, f);
            thrusters.clear();
            thrusters.insert(thrusters.begin(), i, Thruster());
            for (int t=0; t < i; t++)
            {
                thrusters[t].Read(f);
            }
            break;
        case SPCL_ID:
            fread(&i, 4, 1, f);
            Specials.clear();
            Specials.insert(Specials.begin(), i, Special());
            for (int s=0; s < i; s++)
            {
                Specials[s].Read(f);
            }
            break;
        default:
            ErrorMsg("Unrecognized chunk (ID=0x%X) in project file", chunk);
            fclose(f);
            return false;
        }
    }

    fclose(f);
    return true;
}
System*
StarshipAI::SelectSubtarget()
{
	if (Game::GameTime() - sub_select_time < 2345)
	return subtarget;

	subtarget = 0;

	if (!target || target->Type() != SimObject::SIM_SHIP || GetAILevel() < 1)
	return subtarget;

	Ship* tgt_ship = (Ship*) target;

	if (!tgt_ship->IsStarship())
	return subtarget;

	Weapon*  subtgt = 0;
	double   dist   = 50e3;
	Point    svec   = ship->Location() - tgt_ship->Location();

	sub_select_time = Game::GameTime();

	// first pass: turrets
	ListIter<WeaponGroup> g_iter = tgt_ship->Weapons();
	while (++g_iter) {
		WeaponGroup* g = g_iter.value();

		if (g->GetDesign() && g->GetDesign()->turret_model) {
			ListIter<Weapon> w_iter = g->GetWeapons();
			while (++w_iter) {
				Weapon*  w     = w_iter.value();

				if (w->Availability() < 35)
				continue;

				if (w->GetAimVector() * svec < 0)
				continue;

				if (w->GetTurret()) {
					Point    tloc  = w->GetTurret()->Location();
					Point    delta = tloc - ship->Location();
					double   dlen  = delta.length();

					if (dlen < dist) {
						subtgt = w;
						dist   = dlen;
					}
				}
			}
		}
	}

	// second pass: major weapons
	if (!subtgt) {
		g_iter.reset();
		while (++g_iter) {
			WeaponGroup* g = g_iter.value();

			if (g->GetDesign() && !g->GetDesign()->turret_model) {
				ListIter<Weapon> w_iter = g->GetWeapons();
				while (++w_iter) {
					Weapon*  w     = w_iter.value();

					if (w->Availability() < 35)
					continue;

					if (w->GetAimVector() * svec < 0)
					continue;

					Point    tloc  = w->MountLocation();
					Point    delta = tloc - ship->Location();
					double   dlen  = delta.length();

					if (dlen < dist) {
						subtgt = w;
						dist   = dlen;
					}
				}
			}
		}
	}

	subtarget = subtgt;
	return subtarget;
}
void
StarshipAI::FireControl()
{
	// identify unknown contacts:
	if (identify) {
		if (fabs(ship->GetHelmHeading() - ship->CompassHeading()) < 10*DEGREES) {
			Contact* contact = ship->FindContact(target);

			if (contact && !contact->ActLock()) {
				if (!ship->GetProbe()) {
					ship->LaunchProbe();
				}
			}
		}

		return;
	}

	// investigate last known location of enemy ship:
	if (rumor && !target && ship->GetProbeLauncher() && !ship->GetProbe()) {
		// is rumor in basket?
		Point rmr = Transform(rumor->Location());
		rmr.Normalize();

		double dx = fabs(rmr.x);
		double dy = fabs(rmr.y);

		if (dx < 10*DEGREES && dy < 10*DEGREES && rmr.z > 0) {
			ship->LaunchProbe();
		}
	}

	// Corvettes and Frigates are anti-air platforms.  They need to
	// target missile threats even when the threat is aimed at another
	// friendly ship.  Forward facing weapons must be on auto fire,
	// while lateral and aft facing weapons are set to point defense.

	if (ship->Class() == Ship::CORVETTE || ship->Class() == Ship::FRIGATE) {
		ListIter<WeaponGroup> iter = ship->Weapons();
		while (++iter) {
			WeaponGroup* group = iter.value();

			ListIter<Weapon> w_iter = group->GetWeapons();
			while (++w_iter) {
				Weapon* weapon = w_iter.value();

				double az = weapon->GetAzimuth();
				if (fabs(az) < 45*DEGREES) {
					weapon->SetFiringOrders(Weapon::AUTO);
					weapon->SetTarget(target, 0);
				}

				else {
					weapon->SetFiringOrders(Weapon::POINT_DEFENSE);
				}
			}
		}
	}

	// All other starships are free to engage ship targets.  Weapon
	// fire control is managed by the type of weapon.

	else {
		System* subtgt = SelectSubtarget();

		ListIter<WeaponGroup> iter = ship->Weapons();
		while (++iter) {
			WeaponGroup* weapon = iter.value();

			if (weapon->GetDesign()->target_type & Ship::DROPSHIPS) {   // anti-air weapon?
				weapon->SetFiringOrders(Weapon::POINT_DEFENSE);
			}
			else if (weapon->IsDrone()) {                               // torpedoes
				weapon->SetFiringOrders(Weapon::MANUAL);
				weapon->SetTarget(target, 0);

				if (target && target->GetRegion() == ship->GetRegion()) {
					Point  delta = target->Location() - ship->Location();
					double range = delta.length();

					if (range < weapon->GetDesign()->max_range * 0.9 && 
							!AssessTargetPointDefense())
					weapon->SetFiringOrders(Weapon::AUTO);

					else if (range < weapon->GetDesign()->max_range * 0.5)
					weapon->SetFiringOrders(Weapon::AUTO);
				}
			}
			else {                                                      // anti-ship weapon
				weapon->SetFiringOrders(Weapon::AUTO);
				weapon->SetTarget(target, subtgt);
				weapon->SetSweep(subtgt ? Weapon::SWEEP_NONE : Weapon::SWEEP_TIGHT);
			}
		}
	}
}
void
FighterTacticalAI::SelectSecondaryForTarget(Ship* tgt)
{
	if (tgt) {
		int wix = WINCHESTER_FIGHTER;

		if (tgt->IsGroundUnit())      wix = WINCHESTER_STRIKE;
		else if (tgt->IsStatic())     wix = WINCHESTER_STATIC;
		else if (tgt->IsStarship())   wix = WINCHESTER_ASSAULT;

		WeaponGroup*      best = 0;
		List<WeaponGroup> weps;
		
		if (ListSecondariesForTarget(tgt, weps)) {
			winchester[wix] = false;

			// select best weapon for the job:
			double range       = (ship->Location() - tgt->Location()).length();
			double best_range  = 0;
			double best_damage = 0;

			ListIter<WeaponGroup> iter  = weps;
			while (++iter) {
				WeaponGroup* w = iter.value();

				if (!best) {
					best = w;

					WeaponDesign* d = best->GetDesign();
					best_range  = d->max_range;
					best_damage = d->damage * d->ripple_count;

					if (best_range < range)
					best = 0;
				}

				else {
					WeaponDesign* d = w->GetDesign();
					double w_range  = d->max_range;
					double w_damage = d->damage * d->ripple_count;

					if (w_range > range) {
						if (w_range < best_range || w_damage > best_damage)
						best = w;
					}
				}
			}

			// now cycle weapons until you pick the best one:
			WeaponGroup* current_missile = ship->GetSecondaryGroup();

			if (current_missile && best && current_missile != best) {
				ship->CycleSecondary();
				WeaponGroup* m = ship->GetSecondaryGroup();

				while (m != current_missile && m != best) {
					ship->CycleSecondary();
					m = ship->GetSecondaryGroup();
				}
			}
		}
		
		else {
			winchester[wix] = true;

			// if we have NO weapons that can hit this target,
			// just drop it:

			Weapon* primary = ship->GetPrimary();
			if (!primary || !primary->CanTarget(tgt->Class())) {
				ship_ai->DropTarget(3);
				ship->DropTarget();
			}
		}

		if (tgt->IsGroundUnit())
		ship->SetSensorMode(Sensor::GM);

		else if (ship->GetSensorMode() == Sensor::GM)
		ship->SetSensorMode(Sensor::STD);
	}
}