/*
 * Copyright 2010-2016 OpenXcom Developers.
 *
 * This file is part of OpenXcom.
 *
 * OpenXcom is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * OpenXcom is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "Craft.h"
#include "../fmath.h"
#include "../Engine/Language.h"
#include "../Engine/RNG.h"
#include "../Mod/RuleCraft.h"
#include "CraftWeapon.h"
#include "../Mod/RuleCraftWeapon.h"
#include "../Mod/Mod.h"
#include "SavedGame.h"
#include "ItemContainer.h"
#include "Soldier.h"
#include "Base.h"
#include "Ufo.h"
#include "Waypoint.h"
#include "MissionSite.h"
#include "AlienBase.h"
#include "Vehicle.h"
#include "../Mod/RuleItem.h"
#include "../Mod/AlienDeployment.h"
#include "../Engine/Logger.h"
 
namespace OpenXcom
{
 
/**
 * Initializes a craft of the specified type and
 * assigns it the latest craft ID available.
 * @param rules Pointer to ruleset.
 * @param base Pointer to base of origin.
 * @param id ID to assign to the craft (0 to not assign).
 */
Craft::Craft(RuleCraft *rules, Base *base, int id) : MovingTarget(), _rules(rules), _base(base), _fuel(0), _damage(0), _interceptionOrder(0), _takeoff(0), _status("STR_READY"), _lowFuel(false), _mission(false), _inBattlescape(false), _inDogfight(false)
{
	_items = new ItemContainer();
	if (id != 0)
	{
		_id = id;
	}
	for (unsigned int i = 0; i < _rules->getWeapons(); ++i)
	{
		_weapons.push_back(0);
	}
	if (base != 0)
	{
		setBase(base);
	}
	_speedMaxRadian = calculateRadianSpeed(_rules->getMaxSpeed()) * 120;
}
 
/**
 * Delete the contents of the craft from memory.
 */
Craft::~Craft()
{
	for (std::vector<CraftWeapon*>::iterator i = _weapons.begin(); i != _weapons.end(); ++i)
	{
		delete *i;
	}
	delete _items;
	for (std::vector<Vehicle*>::iterator i = _vehicles.begin(); i != _vehicles.end(); ++i)
	{
		delete *i;
	}
}
 
/**
 * Loads the craft from a YAML file.
 * @param node YAML node.
 * @param mod Mod for the saved game.
 * @param save Pointer to the saved game.
 */
void Craft::load(const YAML::Node &node, const Mod *mod, SavedGame *save)
{
	MovingTarget::load(node);
	_fuel = node["fuel"].as<int>(_fuel);
	_damage = node["damage"].as<int>(_damage);
 
	size_t j = 0;
	for (YAML::const_iterator i = node["weapons"].begin(); i != node["weapons"].end(); ++i)
	{
		if (_rules->getWeapons() > j)
		{
			std::string type = (*i)["type"].as<std::string>();
			if (type != "0" && mod->getCraftWeapon(type))
			{
				CraftWeapon *w = new CraftWeapon(mod->getCraftWeapon(type), 0);
				w->load(*i);
				_weapons[j] = w;
			}
			else
			{
				_weapons[j] = 0;
				if (type != "0")
				{
					Log(LOG_ERROR) << "Failed to load craft weapon " << type;
				}
			}
			j++;
		}
	}
 
	_items->load(node["items"]);
	// Some old saves have bad items, better get rid of them to avoid further bugs
	for (std::map<std::string, int>::iterator i = _items->getContents()->begin(); i != _items->getContents()->end();)
	{
		if (mod->getItem(i->first) == 0)
		{
			Log(LOG_ERROR) << "Failed to load item " << i->first;
			_items->getContents()->erase(i++);
		}
		else
		{
			++i;
		}
	}
	for (YAML::const_iterator i = node["vehicles"].begin(); i != node["vehicles"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		if (mod->getItem(type))
		{
			Vehicle *v = new Vehicle(mod->getItem(type), 0, 4);
			v->load(*i);
			_vehicles.push_back(v);
		}
		else
		{
			Log(LOG_ERROR) << "Failed to load item " << type;
		}
	}
	_status = node["status"].as<std::string>(_status);
	_lowFuel = node["lowFuel"].as<bool>(_lowFuel);
	_mission = node["mission"].as<bool>(_mission);
	_interceptionOrder = node["interceptionOrder"].as<int>(_interceptionOrder);
	if (const YAML::Node &dest = node["dest"])
	{
		std::string type = dest["type"].as<std::string>();
		int id = dest["id"].as<int>();
		if (type == "STR_BASE")
		{
			returnToBase();
		}
		else if (type == "STR_UFO")
		{
			for (std::vector<Ufo*>::iterator i = save->getUfos()->begin(); i != save->getUfos()->end(); ++i)
			{
				if ((*i)->getId() == id)
				{
					setDestination(*i);
					break;
				}
			}
		}
		else if (type == "STR_WAY_POINT")
		{
			for (std::vector<Waypoint*>::iterator i = save->getWaypoints()->begin(); i != save->getWaypoints()->end(); ++i)
			{
				if ((*i)->getId() == id)
				{
					setDestination(*i);
					break;
				}
			}
		}
		else
		{
			// Backwards compatibility
			if (type == "STR_ALIEN_TERROR")
				type = "STR_TERROR_SITE";
			bool found = false;
			for (std::vector<MissionSite*>::iterator i = save->getMissionSites()->begin(); i != save->getMissionSites()->end() && !found; ++i)
			{
				if ((*i)->getId() == id && (*i)->getDeployment()->getMarkerName() == type)
				{
					setDestination(*i);
					found = true;
				}
			}
			for (std::vector<AlienBase*>::iterator i = save->getAlienBases()->begin(); i != save->getAlienBases()->end() && !found; ++i)
			{
				if ((*i)->getId() == id && (*i)->getDeployment()->getMarkerName() == type)
				{
					setDestination(*i);
					found = true;
				}
			}
		}
	}
	_takeoff = node["takeoff"].as<int>(_takeoff);
	_inBattlescape = node["inBattlescape"].as<bool>(_inBattlescape);
	if (_inBattlescape)
		setSpeed(0);
}
 
/**
 * Saves the craft to a YAML file.
 * @return YAML node.
 */
YAML::Node Craft::save() const
{
	YAML::Node node = MovingTarget::save();
	node["type"] = _rules->getType();
	node["fuel"] = _fuel;
	node["damage"] = _damage;
	for (std::vector<CraftWeapon*>::const_iterator i = _weapons.begin(); i != _weapons.end(); ++i)
	{
		YAML::Node subnode;
		if (*i != 0)
		{
			subnode = (*i)->save();
		}
		else
		{
			subnode["type"] = "0";
		}
		node["weapons"].push_back(subnode);
	}
	node["items"] = _items->save();
	for (std::vector<Vehicle*>::const_iterator i = _vehicles.begin(); i != _vehicles.end(); ++i)
	{
		node["vehicles"].push_back((*i)->save());
	}
	node["status"] = _status;
	if (_lowFuel)
		node["lowFuel"] = _lowFuel;
	if (_mission)
		node["mission"] = _mission;
	if (_inBattlescape)
		node["inBattlescape"] = _inBattlescape;
	if (_interceptionOrder != 0)
		node["interceptionOrder"] = _interceptionOrder;
	if (_takeoff != 0)
		node["takeoff"] = _takeoff;
	return node;
}
 
/**
 * Loads a craft unique identifier from a YAML file.
 * @param node YAML node.
 * @return Unique craft id.
 */
CraftId Craft::loadId(const YAML::Node &node)
{
	return std::make_pair(node["type"].as<std::string>(), node["id"].as<int>());
}
 
/**
 * Returns the craft's unique type used for
 * savegame purposes.
 * @return ID.
 */
std::string Craft::getType() const
{
	return _rules->getType();
}
 
/**
 * Returns the ruleset for the craft's type.
 * @return Pointer to ruleset.
 */
RuleCraft *Craft::getRules() const
{
	return _rules;
}
 
/**
 * Changes the ruleset for the craft's type.
 * @param rules Pointer to ruleset.
 * @warning ONLY FOR NEW BATTLE USE!
 */
void Craft::changeRules(RuleCraft *rules)
{
	_rules = rules;
	_weapons.clear();
	for (unsigned int i = 0; i < _rules->getWeapons(); ++i)
	{
		_weapons.push_back(0);
	}
}
 
/**
 * Returns the craft's unique default name.
 * @param lang Language to get strings from.
 * @return Full name.
 */
std::string Craft::getDefaultName(Language *lang) const
{
	return lang->getString("STR_CRAFTNAME").arg(lang->getString(getType())).arg(_id);
}
 
/**
 * Returns the globe marker for the craft.
 * @return Marker sprite, -1 if none.
 */
int Craft::getMarker() const
{
	if (_status != "STR_OUT")
		return -1;
	else if (_rules->getMarker() == -1)
		return 1;
	return _rules->getMarker();
}
 
/**
 * Returns the base the craft belongs to.
 * @return Pointer to base.
 */
Base *Craft::getBase() const
{
	return _base;
}
 
/**
 * Changes the base the craft belongs to.
 * @param base Pointer to base.
 * @param move Move the craft to the base coordinates.
 */
void Craft::setBase(Base *base, bool move)
{
	_base = base;
	if (move)
	{
		_lon = base->getLongitude();
		_lat = base->getLatitude();
	}
}
 
/**
 * Returns the current status of the craft.
 * @return Status string.
 */
std::string Craft::getStatus() const
{
	return _status;
}
 
/**
 * Changes the current status of the craft.
 * @param status Status string.
 */
void Craft::setStatus(const std::string &status)
{
	_status = status;
}
 
/**
 * Returns the current altitude of the craft.
 * @return Altitude.
 */
std::string Craft::getAltitude() const
{
	Ufo *u = dynamic_cast<Ufo*>(_dest);
	if (u && u->getAltitude() != "STR_GROUND")
	{
		return u->getAltitude();
	}
	else
	{
		return "STR_VERY_LOW";
	}
}
 
 
/**
 * Changes the destination the craft is heading to.
 * @param dest Pointer to new destination.
 */
void Craft::setDestination(Target *dest)
{
	if (_status != "STR_OUT")
	{
		_takeoff = 60;
	}
	if (dest == 0)
		setSpeed(_rules->getMaxSpeed()/2);
	else
		setSpeed(_rules->getMaxSpeed());
	MovingTarget::setDestination(dest);
}
 
/**
 * Returns the amount of weapons currently
 * equipped on this craft.
 * @return Number of weapons.
 */
int Craft::getNumWeapons() const
{
	if (_rules->getWeapons() == 0)
	{
		return 0;
	}
 
	int total = 0;
 
	for (std::vector<CraftWeapon*>::const_iterator i = _weapons.begin(); i != _weapons.end(); ++i)
	{
		if ((*i) != 0)
		{
			total++;
		}
	}
 
	return total;
}
 
/**
 * Returns the amount of soldiers from a list
 * that are currently attached to this craft.
 * @return Number of soldiers.
 */
int Craft::getNumSoldiers() const
{
	if (_rules->getSoldiers() == 0)
		return 0;
 
	int total = 0;
 
	for (std::vector<Soldier*>::iterator i = _base->getSoldiers()->begin(); i != _base->getSoldiers()->end(); ++i)
	{
		if ((*i)->getCraft() == this)
			total++;
	}
 
	return total;
}
 
/**
 * Returns the amount of equipment currently
 * equipped on this craft.
 * @return Number of items.
 */
int Craft::getNumEquipment() const
{
	return _items->getTotalQuantity();
}
 
/**
 * Returns the amount of vehicles currently
 * contained in this craft.
 * @return Number of vehicles.
 */
int Craft::getNumVehicles() const
{
	return _vehicles.size();
}
 
/**
 * Returns the list of weapons currently equipped
 * in the craft.
 * @return Pointer to weapon list.
 */
std::vector<CraftWeapon*> *Craft::getWeapons()
{
	return &_weapons;
}
 
/**
 * Returns the list of items in the craft.
 * @return Pointer to the item list.
 */
ItemContainer *Craft::getItems()
{
	return _items;
}
 
/**
 * Returns the list of vehicles currently equipped
 * in the craft.
 * @return Pointer to vehicle list.
 */
std::vector<Vehicle*> *Craft::getVehicles()
{
	return &_vehicles;
}
 
/**
 * Returns the amount of fuel currently contained
 * in this craft.
 * @return Amount of fuel.
 */
int Craft::getFuel() const
{
	return _fuel;
}
 
/**
 * Changes the amount of fuel currently contained
 * in this craft.
 * @param fuel Amount of fuel.
 */
void Craft::setFuel(int fuel)
{
	_fuel = fuel;
	if (_fuel > _rules->getMaxFuel())
	{
		_fuel = _rules->getMaxFuel();
	}
	else if (_fuel < 0)
	{
		_fuel = 0;
	}
}
 
/**
 * Returns the ratio between the amount of fuel currently
 * contained in this craft and the total it can carry.
 * @return Percentage of fuel.
 */
int Craft::getFuelPercentage() const
{
	return (int)floor((double)_fuel / _rules->getMaxFuel() * 100.0);
}
 
/**
 * Returns the amount of damage this craft has taken.
 * @return Amount of damage.
 */
int Craft::getDamage() const
{
	return _damage;
}
 
/**
 * Changes the amount of damage this craft has taken.
 * @param damage Amount of damage.
 */
void Craft::setDamage(int damage)
{
	_damage = damage;
	if (_damage < 0)
	{
		_damage = 0;
	}
}
 
/**
 * Returns the ratio between the amount of damage this
 * craft can take and the total it can take before it's
 * destroyed.
 * @return Percentage of damage.
 */
int Craft::getDamagePercentage() const
{
	return (int)floor((double)_damage / _rules->getMaxDamage() * 100);
}
 
/**
 * Returns whether the craft is currently low on fuel
 * (only has enough to head back to base).
 * @return True if it's low, false otherwise.
 */
bool Craft::getLowFuel() const
{
	return _lowFuel;
}
 
/**
 * Changes whether the craft is currently low on fuel
 * (only has enough to head back to base).
 * @param low True if it's low, false otherwise.
 */
void Craft::setLowFuel(bool low)
{
	_lowFuel = low;
}
 
/**
 * Returns whether the craft has just done a ground mission,
 * and is forced to return to base.
 * @return True if it's returning, false otherwise.
 */
bool Craft::getMissionComplete() const
{
	return _mission;
}
 
/**
 * Changes whether the craft has just done a ground mission,
 * and is forced to return to base.
 * @param mission True if it's returning, false otherwise.
 */
void Craft::setMissionComplete(bool mission)
{
	_mission = mission;
}
 
/**
 * Returns the current distance between the craft
 * and the base it belongs to.
 * @return Distance in radian.
 */
double Craft::getDistanceFromBase() const
{
	return getDistance(_base);
}
 
/**
 * Returns the amount of fuel the craft uses up
 * while it's on the air, based on its current speed.
 * @return Fuel amount.
 */
int Craft::getFuelConsumption() const
{
	return getFuelConsumption(_speed);
}
 
/**
 * Returns the amount of fuel the craft uses up
 * while it's on the air.
 * @param speed Craft speed for estimation.
 * @return Fuel amount.
 */
int Craft::getFuelConsumption(int speed) const
{
	if (!_rules->getRefuelItem().empty())
		return 1;
	return (int)floor(speed / 100.0);
}
 
/**
 * Returns the minimum required fuel for the
 * craft to make it back to base.
 * @return Fuel amount.
 */
int Craft::getFuelLimit() const
{
	return getFuelLimit(_base);
}
 
/**
 * Returns the minimum required fuel for the
 * craft to go to a base.
 * @param base Pointer to target base.
 * @return Fuel amount.
 */
int Craft::getFuelLimit(Base *base) const
{
	return (int)floor(getFuelConsumption(_rules->getMaxSpeed()) * getDistance(base) / _speedMaxRadian);
}
 
/**
 * Returns the maximum range the craft can travel
 * from its origin base on its current fuel.
 * @return Range in radians.
 */
double Craft::getBaseRange() const
{
	return _fuel / 2.0 / getFuelConsumption(_rules->getMaxSpeed()) * _speedMaxRadian;
}
 
/**
 * Sends the craft back to its origin base.
 */
void Craft::returnToBase()
{
	setDestination(_base);
}
 
/**
 * Moves the craft to its destination.
 */
void Craft::think()
{
	if (_takeoff == 0)
	{
		move();
	}
	else
	{
		_takeoff--;
		resetMeetPoint();
	}
	if (reachedDestination() && _dest == (Target*)_base)
	{
		setInterceptionOrder(0); // just to be sure
		checkup();
		setDestination(0);
		setSpeed(0);
		_lowFuel = false;
		_mission = false;
		_takeoff = 0;
	}
}
 
/**
 * Checks the condition of all the craft's systems
 * to define its new status (eg. when arriving at base).
 */
void Craft::checkup()
{
	int available = 0, full = 0;
	for (std::vector<CraftWeapon*>::iterator i = _weapons.begin(); i != _weapons.end(); ++i)
	{
		if ((*i) == 0)
			continue;
		available++;
		if ((*i)->getAmmo() >= (*i)->getRules()->getAmmoMax())
		{
			full++;
		}
		else
		{
			(*i)->setRearming(true);
		}
	}
 
	if (_damage > 0)
	{
		_status = "STR_REPAIRS";
	}
	else if (available != full)
	{
		_status = "STR_REARMING";
	}
	else
	{
		_status = "STR_REFUELLING";
	}
}
 
/**
 * Returns if a certain target is detected by the craft's
 * radar, taking in account the range and chance.
 * @param target Pointer to target to compare.
 * @return True if it's detected, False otherwise.
 */
bool Craft::detect(Target *target) const
{
	if (_rules->getRadarRange() == 0 || !insideRadarRange(target))
		return false;
 
	// backward compatibility with vanilla
	if (_rules->getRadarChance() == 100)
		return true;
 
	Ufo *u = dynamic_cast<Ufo*>(target);
	int chance = _rules->getRadarChance() * (100 + u->getVisibility()) / 100;
	return RNG::percent(chance);
}
 
/**
 * Returns if a certain target is inside the craft's
 * radar range, taking in account the positions of both.
 * @param target Pointer to target to compare.
 * @return True if inside radar range.
 */
bool Craft::insideRadarRange(Target *target) const
{
	double range = Nautical(_rules->getRadarRange());
	return (getDistance(target) <= range);
}
 
/**
 * Consumes the craft's fuel every 10 minutes
 * while it's on the air.
 */
void Craft::consumeFuel()
{
	setFuel(_fuel - getFuelConsumption());
}
 
/**
 * Repairs the craft's damage every hour
 * while it's docked in the base.
 */
void Craft::repair()
{
	setDamage(_damage - _rules->getRepairRate());
	if (_damage <= 0)
	{
		_status = "STR_REARMING";
	}
}
 
/**
 * Refuels the craft every 30 minutes
 * while it's docked in the base.
 * @return The item ID missing for refuelling, or "" if none.
 */
std::string Craft::refuel()
{
	std::string fuel;
	if (_fuel < _rules->getMaxFuel())
	{
		std::string item = _rules->getRefuelItem();
		if (item.empty())
		{
			setFuel(_fuel + _rules->getRefuelRate());
		}
		else
		{
			if (_base->getStorageItems()->getItem(item) > 0)
			{
				_base->getStorageItems()->removeItem(item);
				setFuel(_fuel + _rules->getRefuelRate());
				_lowFuel = false;
			}
			else if (!_lowFuel)
			{
				fuel = item;
				if (_fuel > 0)
				{
					_status = "STR_READY";
				}
				else
				{
					_lowFuel = true;
				}
			}
		}
	}
	if (_fuel >= _rules->getMaxFuel())
	{
		_status = "STR_READY";
		for (std::vector<CraftWeapon*>::iterator i = _weapons.begin(); i != _weapons.end(); ++i)
		{
			if (*i && (*i)->isRearming())
			{
				_status = "STR_REARMING";
				break;
			}
		}
	}
	return fuel;
}
 
/**
 * Rearms the craft's weapons by adding ammo every hour
 * while it's docked in the base.
 * @param mod Pointer to mod.
 * @return The ammo ID missing for rearming, or "" if none.
 */
std::string Craft::rearm(const Mod *mod)
{
	std::string ammo;
	for (std::vector<CraftWeapon*>::iterator i = _weapons.begin(); ; ++i)
	{
		if (i == _weapons.end())
		{
			_status = "STR_REFUELLING";
			break;
		}
		if (*i != 0 && (*i)->isRearming())
		{
			std::string clip = (*i)->getRules()->getClipItem();
			int available = _base->getStorageItems()->getItem(clip);
			if (clip.empty())
			{
				(*i)->rearm(0, 0);
			}
			else if (available > 0)
			{
				int used = (*i)->rearm(available, mod->getItem(clip)->getClipSize());
 
				if (used == available && (*i)->isRearming())
				{
					ammo = clip;
					(*i)->setRearming(false);
				}
 
				_base->getStorageItems()->removeItem(clip, used);
			}
			else
			{
				ammo = clip;
				(*i)->setRearming(false);
			}
			break;
		}
	}
	return ammo;
}
 
/**
 * Returns the craft's battlescape status.
 * @return Is the craft currently in battle?
 */
bool Craft::isInBattlescape() const
{
	return _inBattlescape;
}
 
/**
 * Changes the craft's battlescape status.
 * @param inbattle True if it's in battle, False otherwise.
 */
void Craft::setInBattlescape(bool inbattle)
{
	if (inbattle)
		setSpeed(0);
	_inBattlescape = inbattle;
}
 
/// Returns the craft destroyed status.
/**
 * If the amount of damage the craft take
 * is more than it's health it will be
 * destroyed.
 * @return Is the craft destroyed?
 */
bool Craft::isDestroyed() const
{
	return (_damage >= _rules->getMaxDamage());
}
 
/**
 * Returns the amount of space available for
 * soldiers and vehicles.
 * @return Space available.
 */
int Craft::getSpaceAvailable() const
{
	return _rules->getSoldiers() - getSpaceUsed();
}
 
/**
 * Returns the amount of space in use by
 * soldiers and vehicles.
 * @return Space used.
 */
int Craft::getSpaceUsed() const
{
	int vehicleSpaceUsed = 0;
	for (std::vector<Vehicle*>::const_iterator i = _vehicles.begin(); i != _vehicles.end(); ++i)
	{
		vehicleSpaceUsed += (*i)->getSize();
	}
	return getNumSoldiers() + vehicleSpaceUsed;
}
 
/**
 * Returns the total amount of vehicles of
 * a certain type stored in the craft.
 * @param vehicle Vehicle type.
 * @return Number of vehicles.
 */
int Craft::getVehicleCount(const std::string &vehicle) const
{
	int total = 0;
	for (std::vector<Vehicle*>::const_iterator i = _vehicles.begin(); i != _vehicles.end(); ++i)
	{
		if ((*i)->getRules()->getType() == vehicle)
		{
			total++;
		}
	}
	return total;
}
 
/**
 * Returns the craft's dogfight status.
 * @return Is the craft ion a dogfight?
 */
bool Craft::isInDogfight() const
{
	return _inDogfight;
}
 
/**
 * Changes the craft's dogfight status.
 * @param inDogfight True if it's in dogfight, False otherwise.
 */
void Craft::setInDogfight(bool inDogfight)
{
	_inDogfight = inDogfight;
}
 
/**
 * Sets interception order (first craft to leave the base gets 1, second 2, etc.).
 * @param order Interception order.
 */
void Craft::setInterceptionOrder(const int order)
{
	_interceptionOrder = order;
}
 
/**
 * Gets interception order.
 * @return Interception order.
 */
int Craft::getInterceptionOrder() const
{
	return _interceptionOrder;
}
 
/**
 * Gets the craft's unique id.
 * @return A tuple of the craft's type and per-type id.
 */
CraftId Craft::getUniqueId() const
{
	return std::make_pair(_rules->getType(), _id);
}
 
/**
 * Unloads all the craft contents to the base.
 * @param mod Pointer to mod.
 */
void Craft::unload(const Mod *mod)
{
	// Remove weapons
	for (std::vector<CraftWeapon*>::iterator w = _weapons.begin(); w != _weapons.end(); ++w)
	{
		if ((*w) != 0)
		{
			_base->getStorageItems()->addItem((*w)->getRules()->getLauncherItem());
			_base->getStorageItems()->addItem((*w)->getRules()->getClipItem(), (*w)->getClipsLoaded(mod));
			delete (*w);
			(*w) = 0;
		}
	}
 
	// Remove items
	for (std::map<std::string, int>::iterator it = _items->getContents()->begin(); it != _items->getContents()->end(); ++it)
	{
		_base->getStorageItems()->addItem(it->first, it->second);
	}
 
	// Remove vehicles
	for (std::vector<Vehicle*>::iterator v = _vehicles.begin(); v != _vehicles.end(); ++v)
	{
		_base->getStorageItems()->addItem((*v)->getRules()->getType());
		if (!(*v)->getRules()->getCompatibleAmmo()->empty())
		{
			_base->getStorageItems()->addItem((*v)->getRules()->getCompatibleAmmo()->front(), (*v)->getAmmo());
		}
		delete (*v);
		(*v) = 0;
	}
	_vehicles.clear();
 
	// Remove soldiers
	for (std::vector<Soldier*>::iterator s = _base->getSoldiers()->begin(); s != _base->getSoldiers()->end(); ++s)
	{
		if ((*s)->getCraft() == this)
		{
			(*s)->setCraft(0);
		}
	}
}
 
/**
 * Checks if an item can be reused by the craft and
 * updates its status appropriately.
 * @param item Item ID.
 */
void Craft::reuseItem(const std::string& item)
{
	if (_status != "STR_READY")
		return;
	// Check if it's ammo to reload the craft
	for (std::vector<CraftWeapon*>::iterator w = _weapons.begin(); w != _weapons.end(); ++w)
	{
		if ((*w) != 0 && item == (*w)->getRules()->getClipItem() && (*w)->getAmmo() < (*w)->getRules()->getAmmoMax())
		{
			(*w)->setRearming(true);
			_status = "STR_REARMING";
		}
	}
	// Check if it's fuel to refuel the craft
	if (item == _rules->getRefuelItem() && _fuel < _rules->getMaxFuel())
		_status = "STR_REFUELLING";
}
 
}

V522 There might be dereferencing of a potential null pointer 'u'.

V601 The bool type is implicitly cast to the class type.

V601 The bool type is implicitly cast to the class type.

V601 The bool type is implicitly cast to the class type.