示例#1
0
// Demand tribute, and get the planet's response.
string Planet::DemandTribute(PlayerInfo &player) const
{
	if(player.GetCondition("tribute: " + name))
		return "We are already paying you as much as we can afford.";
	if(!tribute || defenseFleets.empty())
		return "Please don't joke about that sort of thing.";
	if(player.GetCondition("combat rating") < defenseThreshold)
		return "You're not worthy of our time.";
	
	// The player is scary enough for this planet to take notice. Check whether
	// this is the first demand for tribute, or not.
	if(!isDefending)
	{
		isDefending = true;
		set<const Government *> toProvoke;
		for(const auto &fleet : defenseFleets)
			toProvoke.insert(fleet->GetGovernment());
		for(const auto &gov : toProvoke)
			gov->Offend(ShipEvent::PROVOKE);
		// Terrorizing a planet is not taken lightly by it or its allies.
		GetGovernment()->Offend(ShipEvent::ATROCITY);
		return "Our defense fleet will make short work of you.";
	}
	
	// The player has already demanded tribute. Have they defeated the entire defense fleet?
	bool isDefeated = (defenseDeployed == defenseFleets.size());
	for(const shared_ptr<Ship> &ship : defenders)
		if(!ship->IsDisabled() && !ship->IsYours())
		{
			isDefeated = false;
			break;
		}
	
	if(!isDefeated)
		return "We're not ready to surrender yet.";
	
	player.Conditions()["tribute: " + name] = tribute;
	GameData::GetPolitics().DominatePlanet(this);
	return "We surrender. We will pay you " + Format::Credits(tribute) + " credits per day to leave us alone.";
}
MissionPanel::MissionPanel(PlayerInfo &player)
	: MapPanel(player),
	available(player.AvailableJobs()),
	accepted(player.Missions()),
	availableIt(player.AvailableJobs().begin()),
	acceptedIt(player.AvailableJobs().empty() ? accepted.begin() : accepted.end())
{
	while(acceptedIt != accepted.end() && !acceptedIt->IsVisible())
		++acceptedIt;
	
	wrap.SetWrapWidth(380);
	wrap.SetFont(FontSet::Get(14));
	wrap.SetAlignment(WrappedText::JUSTIFIED);

	// Select the first available or accepted mission in the currently selected
	// system, or along the travel plan.
	if(!FindMissionForSystem(selectedSystem) && player.HasTravelPlan())
	{
		const auto &tp = player.TravelPlan();
		for(auto it = tp.crbegin(); it != tp.crend(); ++it)
			if(FindMissionForSystem(*it))
				break;
	}

	// Auto select the destination system for the current mission.
	if(availableIt != available.end())
		selectedSystem = availableIt->Destination()->GetSystem();
	else if(acceptedIt != accepted.end())
		selectedSystem = acceptedIt->Destination()->GetSystem();

	// Center the system slightly above the center of the screen because the
	// lower panel is taking up more space than the upper one.
	center = Point(0., -80.) - selectedSystem->Position();
}
示例#3
0
void GameEvent::Apply(PlayerInfo &player)
{
	for(const auto &it : GameData::Governments())
	{
		int rep = it.second.Reputation();
		player.Conditions()["reputation: " + it.first] = rep;
	}
	
	conditionsToApply.Apply(player.Conditions());
	player.AddChanges(changes);
	
	for(const auto &it : GameData::Governments())
	{
		int rep = it.second.Reputation();
		int newRep = player.Conditions()["reputation: " + it.first];
		if(rep != newRep)
			it.second.AddReputation(newRep - rep);
	}
	
	for(const System *system : systemsToUnvisit)
		player.Unvisit(system);
}
示例#4
0
BoardingPanel::BoardingPanel(PlayerInfo &player, const shared_ptr<Ship> &victim)
	: player(player), you(player.FlagshipPtr()), victim(victim),
	attackOdds(&*you, &*victim), defenseOdds(&*victim, &*you),
	initialCrew(you->Crew())
{
	SetInterruptible(false);
	
	const System &system = *player.GetSystem();
	for(const auto &it : victim->Cargo().Commodities())
		plunder.emplace_back(it.first, it.second, system.Trade(it.first));
	
	// You cannot plunder hand to hand weapons, because they are kept in the
	// crew's quarters, not mounted on the exterior of the ship.
	for(const auto &it : victim->Outfits())
		if(!it.first->Get("unplunderable"))
			plunder.emplace_back(it.first, it.second);
	
	if(!victim->IsCapturable())
		messages.emplace_back("This is not a ship that you can capture.");
	
	sort(plunder.begin(), plunder.end());
}
示例#5
0
bool Mission::HasSpace(const PlayerInfo &player) const
{
	int extraCrew = 0;
	if(player.Flagship())
		extraCrew = player.Flagship()->Crew() - player.Flagship()->RequiredCrew();
	return (cargoSize <= player.Cargo().Free() + player.Cargo().CommoditiesSize()
		&& passengers <= player.Cargo().Bunks() + extraCrew);
}
示例#6
0
    static int MannedTurrets(IshipIGC* pshipParent)
    {
        // loop through all of the ships on that side and count the ones 
        // that are turrets of this.
        int cMannedTurrets = 0;
        
        const ShipListIGC* shipList = pshipParent->GetSide()->GetShips();
        for (const ShipLinkIGC* lShip = shipList->first(); lShip; lShip = lShip->next())
        {
            IshipIGC* pship = lShip->data();
            PlayerInfo* pplayer = (PlayerInfo*)pship->GetPrivateData();

            if (pplayer->LastSeenState() == c_ssTurret)                
            {
                PlayerInfo* pplayerParent = trekClient.FindPlayer(pplayer->LastSeenParent());

                if (pplayerParent && pplayerParent->GetShip() == pshipParent)
                    cMannedTurrets++;
            }
        }

        return cMannedTurrets;
    }
示例#7
0
    static bool CanBoard(IshipIGC* pship)
    {
        PlayerInfo* pPlayer = (PlayerInfo*)pship->GetPrivateData();

        if (pship != trekClient.GetShip() 
            && pship->GetSide() == trekClient.GetSide()
            && pPlayer->LastSeenState() == c_ssDocked 
            && pship->GetPilotType() >= c_ptPlayer)
        {
            HullID          hid = pPlayer->LastSeenShipType();
            assert (hid != NA);
            IhullTypeIGC*   pht = trekClient.m_pCoreIGC->GetHullType(hid);
            assert (pht);

            if ((trekClient.GetShip()->GetPilotType() == c_ptCheatPlayer) ||
                (pht->GetMaxFixedWeapons() != pht->GetMaxWeapons()))
            {
                return true;
            }
        }

        return false;
    }
示例#8
0
// Check if this action can be completed right now. It cannot be completed
// if it takes away money or outfits that the player does not have.
bool MissionAction::CanBeDone(const PlayerInfo &player) const
{
	if(player.Accounts().Credits() < -payment)
		return false;
	
	const Ship *flagship = player.Flagship();
	for(const auto &it : gifts)
	{
		if(it.second >= 0)
			continue;
		
		// The outfit can be taken from the player's cargo or from the flagship.
		int available = player.Cargo().Get(it.first);
		for(const auto &ship : player.Ships())
			available += ship->Cargo().Get(it.first);
		if(flagship)
			available += flagship->OutfitCount(it.first);
		
		if(available < -it.second)
			return false;
	}
	return true;
}
bool AllianceApplylistCommand::handleRecieve(cocos2d::CCDictionary *dict)
{
    if (dict->valueForKey("cmd")->compare(AL_APPLY_LIST) != 0)
        return false;
    
    CCDictionary *params=_dict(dict->objectForKey("params"));
    
    if (!params) {
        return false;
    }
    const CCString *pStr = params->valueForKey("errorCode");
    if (pStr->compare("")!=0) {
        CCCommonUtils::flyText(_lang(pStr->getCString()));
        callFail(NetResult::create());
    }else{
        map<std::string, PlayerInfo*>::iterator it;
        AllianceManager::getInstance()->applyUserList.clear();
        CCArray* arr =  (CCArray*)params->objectForKey("list");
        int num = arr->count();
        for (int i=0; i<num; i++) {
            CCDictionary* dicPlayer = (CCDictionary*)arr->objectAtIndex(i);
            PlayerInfo* player = new PlayerInfo();
            player->updateInfo(dicPlayer);
            AllianceManager::getInstance()->applyUserList[player->uid] = player;
            if(player->uid==GlobalData::shared()->playerInfo.uid){
                if(dicPlayer->objectForKey("relinquishEndTime")){
                    GlobalData::shared()->playerInfo.relinquishEndTime = dicPlayer->valueForKey("relinquishEndTime")->doubleValue();
                }
                if(dicPlayer->objectForKey("officer")){
                    GlobalData::shared()->playerInfo.officer = dicPlayer->valueForKey("officer")->getCString();
                }
            }
        }
        callSuccess(NetResult::create(Error_OK, params));
    }
    return true;
}
Engine::Engine(PlayerInfo &player)
	: player(player)
{
	// Start the thread for doing calculations.
	calcThread = thread(&Engine::ThreadEntryPoint, this);
	
	if(!player.IsLoaded() || !player.GetSystem())
		return;
	
	// Preload any landscapes for this system.
	for(const StellarObject &object : player.GetSystem()->Objects())
		if(object.GetPlanet())
			GameData::Preload(object.GetPlanet()->Landscape());
	
	// Figure out what planet the player is landed on, if any.
	const StellarObject *object = player.GetStellarObject();
	if(object)
		center = object->Position();
	
	// Now we know the player's current position. Draw the planets.
	draw[calcTickTock].SetCenter(center);
	radar[calcTickTock].SetCenter(center);
	for(const StellarObject &object : player.GetSystem()->Objects())
		if(object.HasSprite())
		{
			draw[calcTickTock].Add(object);
			
			double r = max(2., object.Radius() * .03 + .5);
			radar[calcTickTock].Add(RadarType(object), object.Position(), r, r - 1.);
		}
	
	// Add all neighboring systems to the radar.
	const Ship *flagship = player.Flagship();
	const System *targetSystem = flagship ? flagship->GetTargetSystem() : nullptr;
	const vector<const System *> &links = (flagship && flagship->Attributes().Get("jump drive")) ?
		player.GetSystem()->Neighbors() : player.GetSystem()->Links();
	for(const System *system : links)
		radar[calcTickTock].AddPointer(
			(system == targetSystem) ? Radar::SPECIAL : Radar::INACTIVE,
			system->Position() - player.GetSystem()->Position());
}
示例#11
0
// Check if it's possible to offer or complete this mission right now.
bool Mission::CanOffer(const PlayerInfo &player) const
{
	if(location == BOARDING || location == ASSISTING)
	{
		if(!player.BoardingShip())
			return false;
		
		if(!sourceFilter.Matches(*player.BoardingShip()))
			return false;
	}
	else
	{
		if(source && source != player.GetPlanet())
			return false;
	
		if(!sourceFilter.Matches(player.GetPlanet()))
			return false;
	}
	
	if(!toOffer.Test(player.Conditions()))
		return false;
	
	if(!toFail.IsEmpty() && toFail.Test(player.Conditions()))
		return false;
	
	if(repeat)
	{
		auto cit = player.Conditions().find(name + ": offered");
		if(cit != player.Conditions().end() && cit->second >= repeat)
			return false;
	}
	
	auto it = actions.find(OFFER);
	if(it != actions.end() && !it->second.CanBeDone(player))
		return false;
	
	it = actions.find(ACCEPT);
	if(it != actions.end() && !it->second.CanBeDone(player))
		return false;
	
	it = actions.find(DECLINE);
	if(it != actions.end() && !it->second.CanBeDone(player))
		return false;
	
	return true;
}
示例#12
0
bool Mission::CanComplete(const PlayerInfo &player) const
{
	if(player.GetPlanet() != destination || !waypoints.empty())
		return false;
	
	if(!toComplete.Test(player.Conditions()))
		return false;
	
	auto it = actions.find(COMPLETE);
	if(it != actions.end() && !it->second.CanBeDone(player))
		return false;
	
	for(const NPC &npc : npcs)
		if(!npc.HasSucceeded(player.GetSystem()))
			return false;
	
	// If any of the cargo for this mission is being carried by a ship that is
	// not in this system, the mission cannot be completed right now.
	for(const auto &ship : player.Ships())
		if(ship->GetSystem() != player.GetSystem() && ship->Cargo().Get(this))
			return false;
	
	return true;
}
示例#13
0
void* handle(void* par) {

	signal(SIGPIPE, SIG_IGN);

	HandleThreadParameter* parameter = (HandleThreadParameter*) par;
	int clientSocket = parameter->clientID;
	Server* server = parameter->server;

	std::vector<std::string> withBase = server->listFilesInDirectoryWithBase(
			"sendFiles");
	std::vector<std::string> withoutBase = server->listFilesInDirectory(
			"sendFiles");

	// Manda las imagenes y sonidos necesarios que se utilizaran.
	server->sendFiles(withBase, withoutBase, clientSocket);

	PlayerInfo* info = server->recieveNewPlayer(clientSocket);
	if (!info){
		Logs::logErrorMessage("No se ha recibido la informacion del jugador");
		return NULL;
	}
	string playerName = info->getPlayer()->getName();

	int result = server->isNameAbilivable(playerName);
	server->sendAproval(clientSocket, result);
	if (result != OK) {
		playerName = server->getAbilivableName(playerName);
		server->sendNewName(clientSocket, playerName);
		info->setName(playerName);
		info->getPlayer()->setName(playerName);
	}
	cont++;
	info->getPlayer()->setTeam(cont%2 +1);

	bool playing = true;
	cout << playerName << " has conected and joined team: " << info->getPlayer()->getTeam() <<endl;
	// Antes de agregarlo al juego creo el thread para chequear el estado en el que se encuentra.
	TimerThreadParameter param = {server,clientSocket,playerName, &playing};
	pthread_t timerThread;

	server->addPlayerToGame(clientSocket, info);

	pthread_create(&timerThread,NULL,timerChecker,(void*)&param);

	server->runMainLoop(clientSocket,playerName);

	pthread_cancel(timerThread);
	server->disconectPlayer(clientSocket,playerName);
	close(clientSocket);

	return NULL;

}
示例#14
0
ShipInfoPanel::ShipInfoPanel(PlayerInfo &player, int index)
	: player(player), shipIt(player.Ships().begin()), canEdit(player.GetPlanet())
{
	SetInterruptible(false);
	
	// If a valid ship index was given, show that ship.
	if(static_cast<unsigned>(index) < player.Ships().size())
		shipIt += index;
	else if(player.Flagship())
	{
		// Find the player's flagship. It may not be first in the list, if the
		// first item in the list cannot be a flagship.
		while(shipIt != player.Ships().end() && shipIt->get() != player.Flagship())
			++shipIt;
	}
	
	UpdateInfo();
}
示例#15
0
// Check to see if the player has done anything they should be fined for.
string Politics::Fine(PlayerInfo &player, const Government *gov, int scan, const Ship *target, double security)
{
	// Do nothing if you have already been fined today, or if you evade
	// detection.
	auto it = fined.find(gov);
	if(it != fined.end() || Random::Real() > security || !gov->GetFineFraction())
		return "";
	
	string reason;
	int64_t maxFine = 0;
	for(const shared_ptr<Ship> &ship : player.Ships())
	{
		// Check if the ship evades being scanned due to interference plating.
		if(Random::Real() > 1. / (1. + ship->Attributes().Get("scan interference")))
			continue;
		if(target && target != &*ship)
			continue;
		if(ship->GetSystem() != player.GetSystem())
			continue;
		
		if(!scan || (scan & ShipEvent::SCAN_CARGO))
		{
			int64_t fine = ship->Cargo().IllegalCargoFine();
			if((fine > maxFine && maxFine >= 0) || fine < 0)
			{
				maxFine = fine;
				reason = "carrying illegal cargo.";
			}
		}
		if(!scan || (scan & ShipEvent::SCAN_OUTFITS))
		{
			for(const auto &it : ship->Outfits())
				if(it.second)
				{
					int64_t fine = it.first->Get("illegal");
					if((fine > maxFine && maxFine >= 0) || fine < 0)
					{
						maxFine = fine;
						reason = "having illegal outfits installed on your ship.";
					}
				}
		}
	}
	
	if(maxFine < 0)
	{
		gov->Offend(ShipEvent::ATROCITY);
		if(!scan)
			reason = "atrocity";
		else
			reason = "After scanning your ship, the " + gov->GetName()
				+ " captain hails you with a grim expression on his face. He says, \"You are guilty of "
				+ reason + " The penalty for your actions is death. Goodbye.\"";
	}
	else if(maxFine > 0)
	{
		// Scale the fine based on how lenient this government is.
		maxFine = maxFine * gov->GetFineFraction() + .5;
		reason = "The " + gov->GetName() + " fines you "
			+ Format::Number(maxFine) + " credits for " + reason;
		player.Accounts().AddFine(maxFine);
		fined.insert(gov);
	}
	return reason;
}
示例#16
0
void AI::UpdateKeys(PlayerInfo &player, bool isActive)
{
	shift = (SDL_GetModState() & KMOD_SHIFT);
	
	Command oldHeld = keyHeld;
	keyHeld.ReadKeyboard();
	keyDown = keyHeld.AndNot(oldHeld);
	if(keyHeld.Has(AutopilotCancelKeys()))
		keyStuck.Clear();
	if(keyStuck.Has(Command::JUMP) && !player.HasTravelPlan())
		keyStuck.Clear(Command::JUMP);
	
	const Ship *flagship = player.Flagship();
	if(!isActive || !flagship || flagship->IsDestroyed())
		return;
	
	// Only toggle the "cloak" command if one of your ships has a cloaking device.
	if(keyDown.Has(Command::CLOAK))
		for(const auto &it : player.Ships())
			if(it->Attributes().Get("cloak"))
			{
				isCloaking = !isCloaking;
				Messages::Add(isCloaking ? "Engaging cloaking device." : "Disengaging cloaking device.");
				break;
			}
	
	// Toggle your secondary weapon.
	if(keyDown.Has(Command::SELECT))
		player.SelectNext();
	
	// The commands below here only apply if you have escorts or fighters.
	if(player.Ships().size() < 2)
		return;
	
	// Only toggle the "deploy" command if one of your ships has fighter bays.
	if(keyDown.Has(Command::DEPLOY))
		for(const auto &it : player.Ships())
			if(it->HasBays())
			{
				isLaunching = !isLaunching;
				Messages::Add(isLaunching ? "Deploying fighters" : "Recalling fighters.");
				break;
			}
	
	shared_ptr<Ship> target = flagship->GetTargetShip();
	if(keyDown.Has(Command::FIGHT) && target)
	{
		sharedTarget = target;
		holdPosition = false;
		moveToMe = false;
		Messages::Add("All your ships are focusing their fire on \"" + target->Name() + "\".");
	}
	if(keyDown.Has(Command::HOLD))
	{
		sharedTarget.reset();
		holdPosition = !holdPosition;
		moveToMe = false;
		Messages::Add(holdPosition ? "Your fleet is holding position."
			: "Your fleet is no longer holding position.");
	}
	if(keyDown.Has(Command::GATHER))
	{
		sharedTarget.reset();
		holdPosition = false;
		moveToMe = !moveToMe;
		Messages::Add(moveToMe ? "Your fleet is gathering around your flagship."
			: "Your fleet is no longer gathering around your flagship.");
	}
	if(sharedTarget.lock() && sharedTarget.lock()->IsDisabled())
		sharedTarget.reset();
}
示例#17
0
// "Instantiate" a mission by replacing randomly selected values and places
// with a single choice, and then replacing any wildcard text as well.
Mission Mission::Instantiate(const PlayerInfo &player) const
{
	Mission result;
	// If anything goes wrong below, this mission should not be offered.
	result.hasFailed = true;
	result.isVisible = isVisible;
	result.hasPriority = hasPriority;
	result.isMinor = isMinor;
	result.autosave = autosave;
	result.location = location;
	result.repeat = repeat;
	result.name = name;
	result.waypoints = waypoints;
	// If one of the waypoints is the current system, it is already visited.
	auto it = result.waypoints.find(player.GetSystem());
	if(it != result.waypoints.end())
		result.waypoints.erase(it);
	
	// First, pick values for all the variables.
	
	// If a specific destination is not specified in the mission, pick a random
	// one out of all the destinations that satisfy the mission requirements.
	result.destination = destination;
	if(!result.destination && !destinationFilter.IsEmpty())
	{
		// Find a destination that satisfies the filter.
		vector<const Planet *> options;
		for(const auto &it : GameData::Planets())
		{
			// Skip entries with incomplete data.
			if(it.second.Name().empty() || (clearance.empty() && !it.second.CanLand()))
				continue;
			if(it.second.IsWormhole() || !it.second.HasSpaceport())
				continue;
			if(destinationFilter.Matches(&it.second, player.GetSystem()))
				options.push_back(&it.second);
		}
		if(!options.empty())
			result.destination = options[Random::Int(options.size())];
		else
			return result;
	}
	// If no destination is specified, it is the same as the source planet. Also
	// use the source planet if the given destination is not a valid planet name.
	if(!result.destination || !result.destination->GetSystem())
	{
		if(player.GetPlanet())
			result.destination = player.GetPlanet();
		else
			return result;
	}
	
	// If cargo is being carried, see if we are supposed to replace a generic
	// cargo name with something more specific.
	if(!cargo.empty())
	{
		const Trade::Commodity *commodity = nullptr;
		if(cargo == "random")
			commodity = PickCommodity(*player.GetSystem(), *result.destination->GetSystem());
		else
		{
			for(const Trade::Commodity &option : GameData::Commodities())
				if(option.name == cargo)
				{
					commodity = &option;
					break;
				}
		}
		if(commodity)
			result.cargo = commodity->items[Random::Int(commodity->items.size())];
		else
			result.cargo = cargo;
	}
	// Pick a random cargo amount, if requested.
	if(cargoSize || cargoLimit)
	{
		if(cargoProb)
			result.cargoSize = Random::Polya(cargoLimit, cargoProb) + cargoSize;
		else if(cargoLimit > cargoSize)
			result.cargoSize = cargoSize + Random::Int(cargoLimit - cargoSize + 1);
		else
			result.cargoSize = cargoSize;
	}
	// Pick a random passenger count, if requested.
	if(passengers | passengerLimit)
	{
		if(passengerProb)
			result.passengers = Random::Polya(passengerLimit, passengerProb) + passengers;
		else if(passengerLimit > passengers)
			result.passengers = passengers + Random::Int(passengerLimit - passengers + 1);
		else
			result.passengers = passengers;
	}
	result.illegalCargoFine = illegalCargoFine;
	
	// How far is it to the destination?
	DistanceMap distance(player.GetSystem());
	int jumps = distance.Distance(result.destination->GetSystem());
	int defaultPayment = (jumps + 1) * (150 * result.cargoSize + 1500 * result.passengers);
	int defaultDeadline = doDefaultDeadline ? (2 * jumps) : 0;
	
	// Set the deadline, if requested.
	if(daysToDeadline || defaultDeadline)
	{
		result.hasDeadline = true;
		result.deadline = player.GetDate() + (defaultDeadline + daysToDeadline);
	}
	
	// Copy the completion conditions. No need to copy the offer conditions,
	// because they have already been checked.
	result.toComplete = toComplete;
	result.toFail = toFail;
	
	// Generate the substitutions map.
	map<string, string> subs;
	subs["<commodity>"] = result.cargo;
	subs["<tons>"] = to_string(result.cargoSize) + (result.cargoSize == 1 ? " ton" : " tons");
	subs["<cargo>"] = subs["<tons>"] + " of " + subs["<commodity>"];
	subs["<bunks>"] = to_string(result.passengers);
	subs["<passengers>"] = (result.passengers == 1) ? "passenger" : "passengers";
	subs["<fare>"] = (result.passengers == 1) ? "a passenger" : (subs["<bunks>"] + " passengers");
	if(player.GetPlanet())
		subs["<origin>"] = player.GetPlanet()->Name();
	else if(player.BoardingShip())
		subs["<origin>"] = player.BoardingShip()->Name();
	subs["<planet>"] = result.destination ? result.destination->Name() : "";
	subs["<system>"] = result.destination ? result.destination->GetSystem()->Name() : "";
	subs["<destination>"] = subs["<planet>"] + " in the " + subs["<system>"] + " system";
	subs["<date>"] = result.deadline.ToString();
	subs["<day>"] = result.deadline.LongString();
	
	// Instantiate the NPCs. This also fills in the "<npc>" substitution.
	for(const NPC &npc : npcs)
		result.npcs.push_back(npc.Instantiate(subs, player.GetSystem()));
	
	// Instantiate the actions. The "complete" action is always first so that
	// the "<payment>" substitution can be filled in.
	for(const auto &it : actions)
		result.actions[it.first] = it.second.Instantiate(subs, defaultPayment);
	for(const auto &it : onEnter)
		result.onEnter[it.first] = it.second.Instantiate(subs, defaultPayment);
	
	// Perform substitution in the name and description.
	result.displayName = Format::Replace(displayName, subs);
	result.description = Format::Replace(description, subs);
	result.clearance = Format::Replace(clearance, subs);
	result.blocked = Format::Replace(blocked, subs);
	result.clearanceFilter = clearanceFilter;
	result.hasFullClearance = hasFullClearance;
	
	result.hasFailed = false;
	return result;
}
示例#18
0
MapDetailPanel::MapDetailPanel(PlayerInfo &player, const System *system)
	: MapPanel(player, system ? MapPanel::SHOW_REPUTATION : player.MapColoring(), system),
	governmentY(0), tradeY(0), selectedPlanet(nullptr)
{
}
void ServerPacketHandlerSystem::handleLobby()
{
	while( m_server->hasNewPackets() )
	{
		Packet packet = m_server->popNewPacket();

		char packetType;
		packetType = packet.getPacketType();

		if(packetType == (char)PacketType::ChangeStatePacket){
			ChangeStatePacket statePacket;
			statePacket.unpack(packet);

			if(statePacket.m_gameState == GameStates::INITGAME){

				ChangeStatePacket newState;
				newState.m_serverState = ServerStates::LOADING;
				m_stateSystem->setQueuedState(ServerStates::LOADING);
				m_server->broadcastPacket(newState.pack());
			}
		}
		else if(packetType == (char)PacketType::PlayerInfo){
			PlayerInfo playerInfo;
			playerInfo.unpack(packet);

			PlayerSystem* playerSystem = static_cast<PlayerSystem*>
				(m_world->getSystem(SystemType::PlayerSystem));

			vector<Entity*> connectedPlayers = playerSystem->getActiveEntities();

			//Add the entity here to be used by other systems
			Entity* newPlayer = m_world->createEntity();
			PlayerComponent* newComp = new PlayerComponent();
			if( playerInfo.playerName == "brightestmind" && playerInfo.playerID == 0){
				newComp->setAbsoluteScore(9001);
			}
			else if(playerInfo.playerName=="judas"){
				newComp->setAbsoluteScore(-9001);
			}
			newComp->m_playerName	= playerInfo.playerName;
			newComp->m_playerID		= playerInfo.playerID; //connectedPlayers.size();
			newComp->m_networkID	= packet.getSenderId();
			newPlayer->addComponent(newComp);
			m_world->addEntity(newPlayer);

			NewlyConnectedPlayerPacket connectedPlayer;
			connectedPlayer.playerName	= newComp->m_playerName;
			connectedPlayer.playerID	= newComp->m_playerID;
			connectedPlayer.score		= newComp->getScore();
			connectedPlayer.networkID	= newComp->m_networkID;
			// Broadcast the player to all clients.
			m_server->broadcastPacket(connectedPlayer.pack());

			for (unsigned int i = 0; i < connectedPlayers.size(); i++){
				NewlyConnectedPlayerPacket alreadyConnectedPlayers;
				PlayerComponent* playerComp;
				playerComp = static_cast<PlayerComponent*>
					(connectedPlayers[i]->getComponent(ComponentType::PlayerComponent));
				alreadyConnectedPlayers.playerID	= playerComp->m_playerID;
				alreadyConnectedPlayers.playerName	= playerComp->m_playerName;
				alreadyConnectedPlayers.networkID	= playerComp->m_networkID;

				// Send all the existing players to the new client.
				m_server->unicastPacket(alreadyConnectedPlayers.pack(), newComp->m_networkID);
				
				//m_server->broadcastPacket(alreadyConnectedPlayers.pack());
			}

			// Force all players to be set unready.
			memset(&m_lobbyPlayerReadyStates, 0, sizeof(m_lobbyPlayerReadyStates));
		}
		else if(packetType == (char)PacketType::ClientDisconnect){
			DisconnectPacket dcPacket;
			dcPacket.unpack(packet);

			// Remove client!
			PlayerSystem* playerSystem = static_cast<PlayerSystem*>
				(m_world->getSystem(SystemType::PlayerSystem));
			playerSystem->deletePlayerEntity(dcPacket.playerID);

			// Broadcast the dc packet back to all clients, including the one who sent it.
			m_server->broadcastPacket(packet);
			// Force all players to be set unready.
			memset(&m_lobbyPlayerReadyStates, 0, sizeof(m_lobbyPlayerReadyStates));

			m_world->getOutputLogger()->write(("Server detected a disconnect packet for player: " + toString(dcPacket.playerID) + "\n").c_str());
		}
		else if(packetType == (char)PacketType::PlayerReadyPacket){
			// Broadcast the ready packet back to all clients, including the one who sent it.
			m_server->broadcastPacket(packet);

			PlayerReadyPacket readyPacket;
			readyPacket.unpack(packet);

			m_lobbyPlayerReadyStates[readyPacket.playerId] = readyPacket.ready;
			// Check so that all players are ready!
			m_readyLobbyPlayers = 0;
			for (int i = 0; i < MAXPLAYERS; i++)
			{
				if (m_lobbyPlayerReadyStates[i])
					m_readyLobbyPlayers++;
			}

			m_world->getOutputLogger()->write( ("Players ready: " + toString(m_readyLobbyPlayers) + "\n").c_str() );
			PlayerSystem* playerSystem = static_cast<PlayerSystem*>
				(m_world->getSystem(SystemType::PlayerSystem));
			if (m_readyLobbyPlayers >= playerSystem->getActiveEntities().size())
			{
				ChangeStatePacket newState;
				newState.m_serverState = ServerStates::LOADING;
				m_stateSystem->setQueuedState(ServerStates::LOADING);
				m_server->broadcastPacket(newState.pack());
			}
		}
		else if( packetType == (char)PacketType::Ping )
		{
			// =========================================
			// PINGPACKET
			// =========================================
			PingPacket pingPacket;
			pingPacket.unpack( packet );

			Packet response((char)PacketType::Pong);
			response << pingPacket.timeStamp;

			m_server->unicastPacket( response, packet.getSenderId() );
		}
		else if( packetType == (char)PacketType::Pong)
		{
			// =========================================
			// PONGPACKET
			// =========================================
			//auto clientInfo = static_cast<ClientInfo*>(m_world->getEntityManager()->get)


			float totalElapsedTime = m_world->getElapsedTime();
			float timeWhenSent;

			PongPacket pongPacket;
			pongPacket.unpack( packet );
			timeWhenSent = pongPacket.timeStamp;

			/************************************************************************/
			/* Convert from seconds to milliseconds.								*/
			/************************************************************************/
			float ping = (totalElapsedTime - timeWhenSent)*1000.0f;
			//m_clients[packet.getSenderId()] = info;

			auto playerSys = static_cast<PlayerSystem*>(
				m_world->getSystem(SystemType::PlayerSystem));
			PlayerComponent* playerComp = playerSys->findPlayerComponentFromNetworkID(packet.getSenderId());
			if (playerComp)
				playerComp->m_ping = ping;
		}
		else
		{
			printPacketTypeNotHandled("Lobby", (int)packetType);
		}
	}
}
示例#20
0
// When the state of this mission changes, it may make changes to the player
// information or show new UI panels. PlayerInfo::MissionCallback() will be
// used as the callback for any UI panel that returns a value.
bool Mission::Do(Trigger trigger, PlayerInfo &player, UI *ui)
{
	if(trigger == STOPOVER)
	{
		// If this is not one of this mission's stopover planets, or if it is
		// not the very last one that must be visited, do nothing.
		auto it = stopovers.find(player.GetPlanet());
		if(it == stopovers.end())
			return false;
		
		for(const NPC &npc : npcs)
			if(npc.IsLeftBehind(player.GetSystem()))
			{
				ui->Push(new Dialog("This is a stop for one of your missions, but you have left a ship behind."));
				return false;
			}
		
		stopovers.erase(it);
		if(!stopovers.empty())
			return false;
	}
	if(trigger == ACCEPT)
	{
		++player.Conditions()[name + ": offered"];
		++player.Conditions()[name + ": active"];
	}
	else if(trigger == DECLINE)
		++player.Conditions()[name + ": offered"];
	else if(trigger == FAIL)
		--player.Conditions()[name + ": active"];
	else if(trigger == COMPLETE)
	{
		--player.Conditions()[name + ": active"];
		++player.Conditions()[name + ": done"];
	}
	
	// "Jobs" should never show dialogs when offered, nor should they call the
	// player's mission callback.
	if(trigger == OFFER && location == JOB)
		ui = nullptr;
	
	auto it = actions.find(trigger);
	if(it == actions.end())
	{
		// If a mission has no "on offer" field, it is automatically accepted.
		if(trigger == OFFER && location != JOB)
			player.MissionCallback(Conversation::ACCEPT);
		return true;
	}
	
	if(!it->second.CanBeDone(player))
		return false;
	
	// Set the "reputation" conditions so we can check if this action changed
	// any of them.
	for(const auto &it : GameData::Governments())
	{
		int rep = it.second.Reputation();
		player.Conditions()["reputation: " + it.first] = rep;
	}
	it->second.Do(player, ui, destination ? destination->GetSystem() : nullptr);
	
	// Check if any reputation conditions were updated.
	for(const auto &it : GameData::Governments())
	{
		int rep = it.second.Reputation();
		int newRep = player.Conditions()["reputation: " + it.first];
		if(newRep != rep)
			it.second.AddReputation(newRep - rep);
	}
	return true;
}
示例#21
0
// "Instantiate" a mission by replacing randomly selected values and places
// with a single choice, and then replacing any wildcard text as well.
Mission Mission::Instantiate(const PlayerInfo &player) const
{
	Mission result;
	// If anything goes wrong below, this mission should not be offered.
	result.hasFailed = true;
	result.isVisible = isVisible;
	result.hasPriority = hasPriority;
	result.isMinor = isMinor;
	result.autosave = autosave;
	result.location = location;
	result.repeat = repeat;
	result.name = name;
	result.waypoints = waypoints;
	// If one of the waypoints is the current system, it is already visited.
	auto it = result.waypoints.find(player.GetSystem());
	if(it != result.waypoints.end())
		result.waypoints.erase(it);
	
	// Copy the stopover planet list, and populate the list based on the filters
	// that were given.
	result.stopovers = stopovers;
	// Make sure they all exist in a valid system.
	for(auto it = result.stopovers.begin(); it != result.stopovers.end(); )
	{
		if((*it)->GetSystem())
			++it;
		else
			it = result.stopovers.erase(it);
	}
	for(const LocationFilter &filter : stopoverFilters)
	{
		const Planet *planet = PickPlanet(filter, player);
		if(!planet)
			return result;
		result.stopovers.insert(planet);
	}
	
	// First, pick values for all the variables.
	
	// If a specific destination is not specified in the mission, pick a random
	// one out of all the destinations that satisfy the mission requirements.
	result.destination = destination;
	if(!result.destination && !destinationFilter.IsEmpty())
	{
		result.destination = PickPlanet(destinationFilter, player);
		if(!result.destination)
			return result;
	}
	// If no destination is specified, it is the same as the source planet. Also
	// use the source planet if the given destination is not a valid planet name.
	if(!result.destination || !result.destination->GetSystem())
	{
		if(player.GetPlanet())
			result.destination = player.GetPlanet();
		else
			return result;
	}
	
	// If cargo is being carried, see if we are supposed to replace a generic
	// cargo name with something more specific.
	if(!cargo.empty())
	{
		const Trade::Commodity *commodity = nullptr;
		if(cargo == "random")
			commodity = PickCommodity(*player.GetSystem(), *result.destination->GetSystem());
		else
		{
			for(const Trade::Commodity &option : GameData::Commodities())
				if(option.name == cargo)
				{
					commodity = &option;
					break;
				}
			for(const Trade::Commodity &option : GameData::SpecialCommodities())
				if(option.name == cargo)
				{
					commodity = &option;
					break;
				}
		}
		if(commodity)
			result.cargo = commodity->items[Random::Int(commodity->items.size())];
		else
			result.cargo = cargo;
	}
	// Pick a random cargo amount, if requested.
	if(cargoSize || cargoLimit)
	{
		if(cargoProb)
			result.cargoSize = Random::Polya(cargoLimit, cargoProb) + cargoSize;
		else if(cargoLimit > cargoSize)
			result.cargoSize = cargoSize + Random::Int(cargoLimit - cargoSize + 1);
		else
			result.cargoSize = cargoSize;
	}
	// Pick a random passenger count, if requested.
	if(passengers | passengerLimit)
	{
		if(passengerProb)
			result.passengers = Random::Polya(passengerLimit, passengerProb) + passengers;
		else if(passengerLimit > passengers)
			result.passengers = passengers + Random::Int(passengerLimit - passengers + 1);
		else
			result.passengers = passengers;
	}
	result.illegalCargoFine = illegalCargoFine;
	
	// How far is it to the destination?
	DistanceMap distance(player.GetSystem());
	int jumps = distance.Distance(result.destination->GetSystem());
	int payload = result.cargoSize + 10 * result.passengers;
	
	// Set the deadline, if requested.
	if(deadlineBase || deadlineMultiplier)
		result.deadline = player.GetDate() + deadlineBase + deadlineMultiplier * jumps;
	
	// Copy the conditions. The offer conditions must be copied too, because they
	// may depend on a condition that other mission offers might change.
	result.toOffer = toOffer;
	result.toComplete = toComplete;
	result.toFail = toFail;
	
	// Generate the substitutions map.
	map<string, string> subs;
	subs["<commodity>"] = result.cargo;
	subs["<tons>"] = to_string(result.cargoSize) + (result.cargoSize == 1 ? " ton" : " tons");
	subs["<cargo>"] = subs["<tons>"] + " of " + subs["<commodity>"];
	subs["<bunks>"] = to_string(result.passengers);
	subs["<passengers>"] = (result.passengers == 1) ? "passenger" : "passengers";
	subs["<fare>"] = (result.passengers == 1) ? "a passenger" : (subs["<bunks>"] + " passengers");
	if(player.GetPlanet())
		subs["<origin>"] = player.GetPlanet()->Name();
	else if(player.BoardingShip())
		subs["<origin>"] = player.BoardingShip()->Name();
	subs["<planet>"] = result.destination ? result.destination->Name() : "";
	subs["<system>"] = result.destination ? result.destination->GetSystem()->Name() : "";
	subs["<destination>"] = subs["<planet>"] + " in the " + subs["<system>"] + " system";
	subs["<date>"] = result.deadline.ToString();
	subs["<day>"] = result.deadline.LongString();
	if(!result.stopovers.empty())
	{
		string planets;
		const Planet * const *last = &*--result.stopovers.end();
		int count = 0;
		// Iterate by reference to the pointers so we can check when we're at
		// the very last one in the set.
		for(const Planet * const &planet : result.stopovers)
		{
			if(count++)
				planets += (&planet != last) ? ", " : (count > 2 ? ", and " : " and ");
			planets += planet->Name() + " in the " + planet->GetSystem()->Name() + " system";
		}
		subs["<stopovers>"] = planets;
	}
	
	// Instantiate the NPCs. This also fills in the "<npc>" substitution.
	for(const NPC &npc : npcs)
		result.npcs.push_back(npc.Instantiate(subs, player.GetSystem()));
	
	// Instantiate the actions. The "complete" action is always first so that
	// the "<payment>" substitution can be filled in.
	for(const auto &it : actions)
		result.actions[it.first] = it.second.Instantiate(subs, jumps, payload);
	for(const auto &it : onEnter)
		result.onEnter[it.first] = it.second.Instantiate(subs, jumps, payload);
	
	// Perform substitution in the name and description.
	result.displayName = Format::Replace(displayName, subs);
	result.description = Format::Replace(description, subs);
	result.clearance = Format::Replace(clearance, subs);
	result.blocked = Format::Replace(blocked, subs);
	result.clearanceFilter = clearanceFilter;
	result.hasFullClearance = hasFullClearance;
	
	result.hasFailed = false;
	return result;
}
示例#22
0
void GSTitle::OnActive()
{
  static bool first = true;
  if (first)
  {
    first = false;

    TheAvatarManager::Instance()->Load();

    // Set default keyboard layout
    KbSetLayout(KB_LAYOUT_REGULAR);

    TheGSOptions::Instance()->LoadFromConfig();
  }

  // Kill off any dummy player object
  TheGame::Instance()->ClearGameObjects();

#ifdef SHOW_FRAME_TIME
  Font* font = (Font*)TheResourceManager::Instance()->GetRes("font2d/arial-font.font");
  TheGame::Instance()->SetFrameTimeFont(font);
#endif

  GSGui::OnActive();

  if (!m_titleImage.OpenAndLoad("title-bgimage.txt"))
  {
std::cout << "Failed to load GUI title bg image!\n";
    Assert(0);
  }

  m_gui = LoadGui("gui-title.txt");
  Assert(m_gui);

  GuiButton* start = (GuiButton*)GetElementByName(m_gui, "start-button");
  start->SetCommand(Amju::OnStartButton);
  start->SetHasFocus(true); 

  GuiButton* options = (GuiButton*)GetElementByName(m_gui, "options-button");
  options->SetCommand(Amju::OnOptionsButton);

  GuiButton* quick = (GuiButton*)GetElementByName(m_gui, "quick-start-button");
  static PlayerInfoManager* pim = ThePlayerInfoManager::Instance();
  if (pim->GetNumPlayerNames() > 0)
  {
    quick->SetVisible(true);
    quick->SetCommand(Amju::OnQuickStartButton);
    quick->SetHasFocus(true);

    // Change button text to player name
    Strings names = pim->GetPlayerNames();
    Assert(!names.empty());
    pim->SetCurrentPlayer(names[0]);
    PlayerInfo* pi = pim->GetPI();
    Assert(pi);
    std::string playername = pi->PIGetString(PI_KEY("playername"));
    quick->SetText(playername);
  }
  else
  {
    quick->SetVisible(false);
  }

  GuiButton* quit = (GuiButton*)GetElementByName(m_gui, "quit-button");
  quit->SetCommand(Amju::OnQuitButton);
  quit->SetIsCancelButton(true);

#ifdef SHOW_VERSION
  GuiText* ver = (GuiText*)GetElementByName(m_gui, "version");
  std::string s = "v." + ToString(VersionMajor) + "." + ToString(VersionMinor);
#ifdef _DEBUG
  s += " DEBUG";
#endif
  ver->SetText(s);
#endif

  //CreateText("my game");

#ifdef PLAY_MUSIC
  TheSoundManager::Instance()->PlaySong(ROConfig()->GetValue("music-title", "Sound/hammers.it"));
#endif
}
示例#23
0
// ticks the game forward in time
void GameInfo::Ticker()
{
  tic++;

  // TODO read/write demo ticcmd's here

  // do main actions
  switch (state)
    {
    case GS_INTRO:
      if (--pagetic <= 0)
	AdvanceIntro();
      break;

    case GS_LEVEL:
      if (!paused && currentcluster)
	currentcluster->Ticker();

      if (!dedicated)
	{
	  hud.Ticker();
	  automap.Ticker();
	}
      break;

    case GS_INTERMISSION:
      wi.Ticker();
      break;

    case GS_FINALE:
      F_Ticker();
      break;

    case GS_NULL:
    default:
      // do nothing
      break;
    }


  MapInfo *m;
  PlayerInfo *p;

  if (state != GS_LEVEL)
    return;

  // manage players
  for (player_iter_t t = Players.begin(); t != Players.end(); )
    {
      p = t->second;
      t++; // because "old t" may be invalidated

      if (p->playerstate == PST_REMOVE)
	{
	  // the player is removed from the game (invalidates "old t")
	  if (!p->mp)
	    RemovePlayer(p->number); // first the maps throw out the removed player, then the game proper.

	  // TODO purge the removed players from the frag maps of other players?
	}
      else
	p->Ticker();
    }

  if (!server)
    return;

  //
  for (player_iter_t t = Players.begin(); t != Players.end(); t++)
    {
      p = t->second;

      if (p->playerstate == PST_NEEDMAP)
	{
	  LConnection *conn = p->connection;
	  if (conn && !conn->isGhostAvailable(p))
	    {
	      // remote player, is it already being ghosted? if not, wait.
	      CONS_Printf(" server waiting for client ghost\n");
	      continue;
	    }

	  // assign the player to a map
	  CONS_Printf("Map request..");

	  if (p->requestmap == 0)
	    {
	      m = initial_map; // first map in game
	      p->entrypoint = initial_ep;
	    }
	  else
	    m = FindMapInfo(p->requestmap);

	  if (!m)
	    {
	      // game ends
	      currentcluster->Finish(p->requestmap, p->entrypoint);
	      StartFinale(NULL);
	      break;
	    }
	  else if (!m->found)
	    m = currentcluster->maps[0]; // TODO or give an error?

	  // cluster change?
	  if (currentcluster->number != m->cluster)
	    {
	      // TODO minor thing: if several players exit maps on the same tick,
	      // and someone besides the first one causes a cluster change, some
	      // maps could be loaded in vain...

	      // cluster change!
	      currentcluster->Finish(p->requestmap, p->entrypoint);

	      MapCluster *next = FindCluster(m->cluster);
	      StartFinale(next);
	      currentcluster = next;

	      break; // this is important! no need to check the other players.
	    }

	  p->Reset(!currentcluster->keepstuff, true);

	  // normal individual mapchange
	  if (!m->Activate(p))
	    I_Error("Darn!\n");

	  if (conn)
	    {
	      CONS_Printf(" server sending rpc\n");
	      // nonlocal player enters a new map, notify client
	      // send the EnterMap rpc only to the owning connection
	      NetEvent *e = TNL_RPC_CONSTRUCT_NETEVENT(p, s2cEnterMap, (m->mapnumber));
	      conn->postNetEvent(e);
	    }
	}
    }
}
示例#24
0
void MissionAction::Do(PlayerInfo &player, UI *ui, const System *destination) const
{
	bool isOffer = (trigger == "offer");
	if(!conversation.IsEmpty())
	{
		ConversationPanel *panel = new ConversationPanel(player, conversation, destination);
		if(isOffer)
			panel->SetCallback(&player, &PlayerInfo::MissionCallback);
		ui->Push(panel);
	}
	else if(!dialogText.empty())
	{
		map<string, string> subs;
		subs["<first>"] = player.FirstName();
		subs["<last>"] = player.LastName();
		if(player.Flagship())
			subs["<ship>"] = player.Flagship()->Name();
		string text = Format::Replace(dialogText, subs);
		
		if(isOffer)
			ui->Push(new Dialog(text, player, destination));
		else
			ui->Push(new Dialog(text));
	}
	else if(isOffer && ui)
		player.MissionCallback(Conversation::ACCEPT);
	
	Ship *flagship = player.Flagship();
	for(const auto &it : gifts)
	{
		int count = it.second;
		string name = it.first->Name();
		if(!count || name.empty())
			continue;
		
		string message;
		if(abs(count) == 1)
		{
			char c = tolower(name.front());
			bool isVowel = (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
			message = (isVowel ? "An " : "A ") + name + " was ";
		}
		else
			message = to_string(abs(count)) + " " + name + "s were ";
		
		if(count > 0)
			message += "added to your ";
		else
			message += "removed from your ";
		
		bool didCargo = false;
		bool didShip = false;
		int cargoCount = player.Cargo().Get(it.first);
		if(count < 0 && cargoCount)
		{
			int moved = min(cargoCount, -count);
			count += moved;
			player.Cargo().Transfer(it.first, moved);
			didCargo = true;
		}
		while(flagship && count)
		{
			int moved = (count > 0) ? 1 : -1;
			if(flagship->Attributes().CanAdd(*it.first, moved))
			{
				flagship->AddOutfit(it.first, moved);
				didShip = true;
			}
			else
				break;
			count -= moved;
		}
		if(count > 0)
		{
			player.Cargo().Transfer(it.first, -count);
			didCargo = true;
			if(count > 0)
			{
				string special = "The " + name + (count == 1 ? " was" : "s were");
				special += " put in your cargo hold because there is not enough space to install ";
				special += (count == 1) ? "it" : "them";
				special += " in your ship.";
				ui->Push(new Dialog(special));
			}
		}
		if(didCargo && didShip)
			message += "cargo hold and your flagship.";
		else if(didCargo)
			message += "cargo hold.";
		else
			message += "flagship.";
		Messages::Add(message);
	}
	
	if(payment)
		player.Accounts().AddCredits(payment);
	
	for(const auto &it : events)
		player.AddEvent(*GameData::Events().Get(it.first), player.GetDate() + it.second);
	
	conditions.Apply(player.Conditions());
}
示例#25
0
BankPanel::BankPanel(PlayerInfo &player)
	: player(player), qualify(player.Accounts().Prequalify()), selectedRow(0)
{
	SetTrapAllEvents(false);
}
示例#26
0
Engine::Engine(PlayerInfo &player)
	: player(player),
	calcTickTock(false), drawTickTock(false), terminate(false), step(0),
	flash(0.), doFlash(false), wasLeavingHyperspace(false),
	load(0.), loadCount(0), loadSum(0.)
{
	// Start the thread for doing calculations.
	calcThread = thread(&Engine::ThreadEntryPoint, this);
	
	if(!player.IsLoaded() || !player.GetSystem())
		return;
	
	// Preload any landscapes for this system.
	for(const StellarObject &object : player.GetSystem()->Objects())
		if(object.GetPlanet())
			GameData::Preload(object.GetPlanet()->Landscape());
	
	// Now we know the player's current position. Draw the planets.
	Point center;
	if(player.GetPlanet())
	{
		for(const StellarObject &object : player.GetSystem()->Objects())
			if(object.GetPlanet() == player.GetPlanet())
				center = object.Position();
	}
	for(const StellarObject &object : player.GetSystem()->Objects())
		if(!object.GetSprite().IsEmpty())
		{
			Point position = object.Position();
			Point unit = object.Unit();
			position -= center;
			
			int type = object.IsStar() ? Radar::SPECIAL :
				!object.GetPlanet() ? Radar::INACTIVE :
				object.GetPlanet()->IsWormhole() ? Radar::ANOMALOUS :
				GameData::GetPolitics().HasDominated(object.GetPlanet()) ? Radar::PLAYER :
				object.GetPlanet()->CanLand() ? Radar::FRIENDLY : Radar::HOSTILE;
			double r = max(2., object.Radius() * .03 + .5);
			
			draw[calcTickTock].Add(object.GetSprite(), position, unit);
			radar[calcTickTock].Add(type, position, r, r - 1.);
		}
	
	// Add all neighboring systems to the radar.
	const Ship *flagship = player.Flagship();
	const System *targetSystem = flagship ? flagship->GetTargetSystem() : nullptr;
	const vector<const System *> &links = (flagship && flagship->Attributes().Get("jump drive")) ?
		player.GetSystem()->Neighbors() : player.GetSystem()->Links();
	for(const System *system : links)
		radar[calcTickTock].AddPointer(
			(system == targetSystem) ? Radar::SPECIAL : Radar::INACTIVE,
			system->Position() - player.GetSystem()->Position());
}
示例#27
0
int main()
{

	network::InitializeNetwork();

	initMemoryCheck();
	//Init Timer
	GlobalTimer *gt = GlobalTimer::getInstance();
	//Init EventManager
	EventManager *test;
	test = myNew EventManager("test", true);
	//Init ActorHandler
	Actor::init();
	ActorHandler *actorHandler = ActorHandler::getInstance();

	network::Peer mPeer("hej2", 5002);

	network::MessageHandler *msgServer, *msgClient;
	
	
	msgClient = myNew network::MsgH_GameClient(&mPeer);
	mPeer.getServerManager()->addMessageHandler(msgClient);


	msgServer = myNew network::MsgH_GameServer("tja", mPeer.getPeerManager());
	mPeer.getPeerManager()->addMessageHandler(msgServer);
	
	mPeer.joinNetwork("localhost", 5001);


	network::EventMsgHandler netEventHandler(mPeer.getIdManager());
	mPeer.getPeerManager()->addMessageHandler(&netEventHandler);
	
	//Init Listeners
	EventListenerPtr snoop;
	snoop = boost::shared_ptr<EventSnooper>(myNew EventSnooper());
	safeAddListener(snoop, EventType(gWildcardEventType));

	EventListenerPtr stats;
	stats = boost::shared_ptr<Statistics>(myNew Statistics());
	safeAddListener(stats, EvtData_From_ActorDestroyed::mEventType);
	safeAddListener(stats, EvtData_System_EndGame::mEventType);

	EventListenerPtr epActorHandler;
	epActorHandler = boost::shared_ptr<ActorHandler>(actorHandler);
	safeAddListener(epActorHandler,EvtData_To_EnemyUpdateHp::mEventType);
	safeAddListener(epActorHandler, EvtData_From_ActorCollision::mEventType);
	safeAddListener(epActorHandler, EvtData_To_TankStartFire::mEventType);
	safeAddListener(epActorHandler, EvtData_To_TankStopFire::mEventType);
	safeAddListener(epActorHandler, EvtData_From_ActorDestroyed::mEventType);
	safeAddListener(epActorHandler, EvtData_To_ActorStartMove::mEventType);
	safeAddListener(epActorHandler, EvtData_To_ActorStopMove::mEventType);
	safeAddListener(epActorHandler, EvtData_To_ActorStartRotate::mEventType);
	safeAddListener(epActorHandler, EvtData_To_ActorStopRotate::mEventType);

	EventListenerPtr logiclol;
	logiclol = boost::shared_ptr<LogicListener>(myNew LogicListener());
	safeAddListener(logiclol,EvtData_From_EnemyHit::mEventType);
	safeAddListener(logiclol, EvtData_System_EndGame::mEventType);

	EventListenerPtr networkForwarder;
	networkForwarder = boost::shared_ptr<network::EventForwarder>(myNew network::EventForwarder(&mPeer));
	//safeAddListener(networkForwarder, EvtData_To_ActorStartMove::mEventType);
	safeAddListener(networkForwarder, EvtData_To_ActorStopMove::mEventType);

	EventListenerPtr sound;
	sound = boost::shared_ptr<sound::SoundListener>(myNew sound::SoundListener());
	logic::safeAddListener(sound, logic::EvtData_To_ActorStartMove::mEventType);
	logic::safeAddListener(sound, logic::EvtData_To_ActorStopMove::mEventType);
	logic::safeAddListener(sound, logic::EvtData_From_ActorCreated::mEventType);
	logic::safeAddListener(sound, logic::EvtData_From_ActorDestroyed::mEventType);
	logic::safeAddListener(sound, logic::EvtData_From_WeaponFired::mEventType);
	//Init PLayerInfo
	PlayerInfo *pi = PlayerInfo::getInstance();


	//Init Dx
	gfx::DX10Module *module = gfx::DX10Module::getInstance();
	pthread_t th = module->create();
	while(!module->getRunFlag())
	{
		Sleep(10);
	}
	//Init Input
	logic::InputStates *input = myNew logic::InputStates(module->getHInstancePointer(), module->getHWNDPointer());	
	input->setState(logic::InputStates::GameState_Game_Inside_Tank);

	
	//testing dxmodule
	module->lock(0);

	gfx::Camera *camera = module->getCamera();
	camera->setTarget(D3DXVECTOR3(0.0f, 0.0f, 0.0f));
	camera->setPosition(D3DXVECTOR3(-100.0f, 50.0f, -100.0f));

	module->loadObjectShapeInstance(gfx::ShapeTypes::CUBE, 1, "Cube", 5000);

	srand(time(0));
	int colorCounter;
	gfx::TransformObject *tempObj;
	for(int i = 0; i < 10; i++)
	{

		colorCounter = i;
		for(int j = 0; j < 10; j++)
		{
			int rnd = rand()%10;
			tempObj = module->createObjectInstanced(1);

			
			if(rnd == 0)
			{
				tempObj->setPosition(D3DXVECTOR3(-30.0f * j,0.0f,-30.0f * i));
				tempObj->setScale(D3DXVECTOR3(15.0f, 15.0f, 15.0f));
				tempObj->setID(-1);
			}
			else
			{
				tempObj->setPosition(D3DXVECTOR3(-30.0f * j, -10.0f,-30.0f * i));
				tempObj->setScale(D3DXVECTOR3(15.0f, 0.1f, 15.0f));
				tempObj->setID(-2);
			}
			int color = colorCounter % 4;
			if(color == 0)
				tempObj->setColor(D3DXCOLOR(0.0f,0.0f,0.0f,1.0f));
			else if(color == 1)
				tempObj->setColor(D3DXCOLOR(1.0f,0.0f,0.0f,1.0f));
			else if(color == 2)
				tempObj->setColor(D3DXCOLOR(1.0f,1.0f,0.0f,1.0f));
			else if(color == 3)
				tempObj->setColor(D3DXCOLOR(0.0f,1.0f,1.0f,1.0f));
			colorCounter++;
		}
	}

	//module->loadObjectShapeInstance(gfx::ShapeTypes::CUBE, 1, "Cube", 5000);
	
	module->loadMeshInstance("../../ModelFiles/TankGround/TankGeometry.txt", 2, "LongRangeTank", 5000);
	//module->loadMeshInstance("../../ModelFiles/TankGround/TankGeometry.txt", 1, "Tank3", 5000);
	module->loadMeshInstance("../../ModelFiles/TankAir/TankAirGeometry.txt", 3, "CloseRangeTank", 5000);
	/*gfx::InstanceMesh *mesh1 = module->createMeshInstanced("Tank");
	mesh1->setTextureID(0);
	mesh1->setFlagUpdateAbsolute(false);
	mesh1->setID(lolAnt->getKey());
	mesh1->setName("enemy");
	mesh1->setPosition(D3DXVECTOR3(lolAnt->getPosition().x, lolAnt->getPosition().y, lolAnt->getPosition().z));
	mesh1->setScale(D3DXVECTOR3(2.5f, 1.5f, 2.5f));
	mesh1->setColor(D3DXCOLOR(0.0f, 0.25f, 1.0f, 1.0f));
	
	mesh1 = module->createMeshInstanced("Tank3");	
	mesh1->setTextureID(0);
	mesh1->setFlagUpdateAbsolute(false);
	mesh1->setID(spindelFan->getKey());
	mesh1->setName("enemy2");
	mesh1->setPosition(D3DXVECTOR3(spindelFan->getPosition().x, spindelFan->getPosition().y, spindelFan->getPosition().z));
	mesh1->setScale(D3DXVECTOR3(2.5f, 1.5f, 2.5f));
	mesh1->setColor(D3DXCOLOR(0.0f, 0.25f, 1.0f, 1.0f));

	mesh1 = module->createMeshInstanced("Tank2");
	mesh1->setTextureID(1);
	mesh1->setFlagUpdateAbsolute(false);
	mesh1->setID(pt->getKey());
	mesh1->setName("player");
	mesh1->setPosition(D3DXVECTOR3(pt->getPosition().x, pt->getPosition().y, pt->getPosition().z));
	mesh1->setScale(D3DXVECTOR3(2.5f, 1.5f, 2.5f));
	mesh1->setColor(D3DXCOLOR(1.0f, 0.0f, 1.0f, 1.0f));*/

	//Create actors
	Tank *pt = myNew Tank(200, 15, Tank::TankType_CloseCombat);
	pi->setTankActorId(pt->getKey());
	//safeQueueEvent(EventDataPtr(myNew EvtData_From_ActorCreated(pt->getKey())));

	FireAnt *lolAnt = myNew FireAnt(100,20,Enemy::Size_Small,1,150.0f);
	//safeQueueEvent(EventDataPtr(myNew EvtData_From_ActorCreated(lolAnt->getKey())));
	actorHandler->insertActor(lolAnt);
	lolAnt->setPosition(-120.0f,0.0f,0.0f);
	lolAnt->setDirection(1.0f,0.0f,0.0f);
	
	BlackWidow *spindelFan = myNew BlackWidow(100,20,Enemy::Size_Medium,1,150.0f);
	actorHandler->insertActor(spindelFan);
	spindelFan->setPosition(-50.0f,0.0f,0.0f);
	spindelFan->setDirection(1.0f,0.0f,0.0f);

	actorHandler->insertActor(pt);	
	pt->setPosition(-10.0f, 3.0f, 0.0f);
	pt->setDirection(1.0f, 0.0f, 0.0f);
	pt->setSubsetDirection(1.0f,0.0f,0.0f);
	
	
	actorHandler->setDXModule();

	module->unlock(0);

	

	sound::SoundSystem *ss = sound::SoundSystem::getInstance();
	ss->setActor();
	LogicQuadTree *pQuadTree = LogicQuadTree::getInstance();
	float dt;  
	while(!module->getQuit())
	{
		test->tick(EventManager::KINFINITE);
		pQuadTree->updateQuadTree();
		//camera->setTarget(mesh1->getPositionX(), mesh1->getPositionY(), mesh1->getPositionZ());
		//camera->setPosition(D3DXVECTOR3(mesh1->getPositionX()-100.0f, 50.0f, mesh1->getPositionZ()-100.0f));
		dt = gt->tick();
		actorHandler->update(dt);
		ss->Update();
		input->update();
		
		Sleep(10);
	}
	logic::safeTriggerEvent(logic::EvtData_System_EndGame());
	KeyHandler *tmp = KeyHandler::getInstance();
	
	
	network::ShutdownNetwork();
	SAFE_DELETE(ss);
	SAFE_DELETE(pQuadTree);
	SAFE_DELETE(tmp);
	SAFE_DELETE(input);
	SAFE_DELETE(gt);
	SAFE_DELETE(test);
	SAFE_DELETE(pi);
	SAFE_DELETE(module);
	return 0;
}
示例#28
0
int main(int argc, char *argv[])
{
	Conversation conversation;
	bool debugMode = false;
	for(const char *const *it = argv + 1; *it; ++it)
	{
		string arg = *it;
		if(arg == "-h" || arg == "--help")
		{
			PrintHelp();
			return 0;
		}
		else if(arg == "-v" || arg == "--version")
		{
			PrintVersion();
			return 0;
		}
		else if(arg == "-t" || arg == "--talk")
			conversation = LoadConversation();
		else if(arg == "-d" || arg == "--debug")
			debugMode = true;
	}
	PlayerInfo player;
	
	try {
		SDL_Init(SDL_INIT_VIDEO);
		
		// Begin loading the game data.
		GameData::BeginLoad(argv);
		Audio::Init(GameData::Sources());
		
		// On Windows, make sure that the sleep timer has at least 1 ms resolution
		// to avoid irregular frame rates.
#ifdef _WIN32
		timeBeginPeriod(1);
#endif
		
		player.LoadRecent();
		player.ApplyChanges();
		
		// Check how big the window can be.
		SDL_DisplayMode mode;
		if(SDL_GetCurrentDisplayMode(0, &mode))
			return DoError("Unable to query monitor resolution!");
		
		Preferences::Load();
		Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
		if(Preferences::Has("fullscreen"))
			flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
		
		// Make the window just slightly smaller than the monitor resolution.
		int maxWidth = mode.w;
		int maxHeight = mode.h;
		// Restore this after toggling fullscreen.
		int restoreWidth = 0;
		int restoreHeight = 0;
		if(maxWidth < 640 || maxHeight < 480)
			return DoError("Monitor resolution is too small!");
		
		if(Screen::RawWidth() && Screen::RawHeight())
		{
			// Never allow the saved screen width to be leaving less than 100
			// pixels free around the window. This avoids the problem where you
			// maximize without going full-screen, and next time the window pops
			// up you can't access the resize control because it is offscreen.
			Screen::SetRaw(
				min(Screen::RawWidth(), (maxWidth - 100)),
				min(Screen::RawHeight(), (maxHeight - 100)));
			if(flags & SDL_WINDOW_FULLSCREEN_DESKTOP)
			{
				restoreWidth = Screen::RawWidth();
				restoreHeight = Screen::RawHeight();
				Screen::SetRaw(maxWidth, maxHeight);
			}
		}
		else
			Screen::SetRaw(maxWidth - 100, maxHeight - 100);
		// Make sure the zoom factor is not set too high for the full UI to fit.
		if(Screen::Height() < 700)
			Screen::SetZoom(100);
		
		// Create the window.
		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#ifdef _WIN32
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
		
		SDL_Window *window = SDL_CreateWindow("Endless Sky",
			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			Screen::RawWidth(), Screen::RawHeight(), flags);
		if(!window)
			return DoError("Unable to create window!");
		
		SDL_GLContext context = SDL_GL_CreateContext(window);
		if(!context)
			return DoError("Unable to create OpenGL context! Check if your system supports OpenGL 3.0.", window);
		
		if(SDL_GL_MakeCurrent(window, context))
			return DoError("Unable to set the current OpenGL context!", window, context);
		
		SDL_GL_SetSwapInterval(1);
		
		// Initialize GLEW.
#ifndef __APPLE__
		glewExperimental = GL_TRUE;
		if(glewInit() != GLEW_OK)
			return DoError("Unable to initialize GLEW!", window, context);
#endif
		
		// Check that the OpenGL version is high enough.
		const char *glVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
		if(!glVersion || !*glVersion)
			return DoError("Unable to query the OpenGL version!", window, context);
		
		const char *glslVersion = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
		if(!glslVersion || !*glslVersion)
		{
			ostringstream out;
			out << "Unable to query the GLSL version. OpenGL version is " << glVersion << ".";
			return DoError(out.str(), window, context);
		}
		
		if(*glVersion < '3')
		{
			ostringstream out;
			out << "Endless Sky requires OpenGL version 3.0 or higher." << endl;
			out << "Your OpenGL version is " << glVersion << ", GLSL version " << glslVersion << "." << endl;
			out << "Please update your graphics drivers.";
			return DoError(out.str(), window, context);
		}
		
		glClearColor(0.f, 0.f, 0.0f, 1.f);
		glEnable(GL_BLEND);
		glDisable(GL_DEPTH_TEST);
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		
		GameData::LoadShaders();
		
		{
			// Check whether this is a high-DPI window.
			int width = 0;
			int height = 0;
			SDL_GL_GetDrawableSize(window, &width, &height);
			Screen::SetHighDPI(width > Screen::RawWidth() && height > Screen::RawHeight());
			
			// Fix a possible race condition leading to the wrong window dimensions.
			glViewport(0, 0, width, height);
		}
		
		
		UI gamePanels;
		UI menuPanels;
		menuPanels.Push(new MenuPanel(player, gamePanels));
		if(!conversation.IsEmpty())
			menuPanels.Push(new ConversationPanel(player, conversation));
		
		string swizzleName = "_texture_swizzle";
#ifndef __APPLE__
		const char *extensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
		if(!strstr(extensions, swizzleName.c_str()))
#else
		bool hasSwizzle = false;
		GLint extensionCount;
		glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
		for(GLint i = 0; i < extensionCount && !hasSwizzle; ++i)
		{
			const char *extension = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
			hasSwizzle = (extension && strstr(extension, swizzleName.c_str()));
		}
		if(!hasSwizzle)
#endif
			menuPanels.Push(new Dialog(
				"Note: your computer does not support the \"texture swizzling\" OpenGL feature, "
				"which Endless Sky uses to draw ships in different colors depending on which "
				"government they belong to. So, all human ships will be the same color, which "
				"may be confusing. Consider upgrading your graphics driver (or your OS)."));
		
		FrameTimer timer(60);
		bool isPaused = false;
		while(!menuPanels.IsDone())
		{
			// Handle any events that occurred in this frame.
			SDL_Event event;
			while(SDL_PollEvent(&event))
			{
				UI &activeUI = (menuPanels.IsEmpty() ? gamePanels : menuPanels);
				
				// The caps lock key slows the game down (to make it easier to
				// see and debug things that are happening quickly).
				if(debugMode && (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
						&& event.key.keysym.sym == SDLK_CAPSLOCK)
				{
					timer.SetFrameRate((event.key.keysym.mod & KMOD_CAPS) ? 10 : 60);
				}
				else if(debugMode && event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_BACKQUOTE)
				{
					isPaused = !isPaused;
				}
				else if(event.type == SDL_KEYDOWN && menuPanels.IsEmpty()
						&& Command(event.key.keysym.sym).Has(Command::MENU)
						&& !gamePanels.IsEmpty() && gamePanels.Top()->IsInterruptible())
				{
					menuPanels.Push(shared_ptr<Panel>(
						new MenuPanel(player, gamePanels)));
				}
				else if(event.type == SDL_QUIT)
				{
					menuPanels.Quit();
				}
				else if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
				{
					int width = event.window.data1 & ~1;
					int height = event.window.data2 & ~1;
					if(width != Screen::RawWidth() || height != Screen::RawHeight())
					{
						Screen::SetRaw(width, height);
						if((event.window.data1 | event.window.data2) & 1)
							SDL_SetWindowSize(window, Screen::RawWidth(), Screen::RawHeight());
						SDL_GL_GetDrawableSize(window, &width, &height);
						glViewport(0, 0, width, height);
					}
				}
				else if(event.type == SDL_KEYDOWN
						&& (Command(event.key.keysym.sym).Has(Command::FULLSCREEN)
						|| (event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_ALT)))
				{
					if(restoreWidth)
					{
						SDL_SetWindowFullscreen(window, 0);
						Screen::SetRaw(restoreWidth, restoreHeight);
						SDL_SetWindowSize(window, Screen::RawWidth(), Screen::RawHeight());
						restoreWidth = 0;
						restoreHeight = 0;
					}
					else
					{
						restoreWidth = Screen::RawWidth();
						restoreHeight = Screen::RawHeight();
						Screen::SetRaw(maxWidth, maxHeight);
						SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
					}
					int width, height;
					SDL_GL_GetDrawableSize(window, &width, &height);
					glViewport(0, 0, width, height);
				}
				else if(activeUI.Handle(event))
				{
					// No need to do anything more!
				}
			}
			Font::ShowUnderlines(SDL_GetModState() & KMOD_ALT);
			
			// Tell all the panels to step forward, then draw them.
			((!isPaused && menuPanels.IsEmpty()) ? gamePanels : menuPanels).StepAll();
			Audio::Step();
			// That may have cleared out the menu, in which case we should draw
			// the game panels instead:
			(menuPanels.IsEmpty() ? gamePanels : menuPanels).DrawAll();
			
			SDL_GL_SwapWindow(window);
			timer.Wait();
		}
		
		// If you quit while landed on a planet, save the game.
		if(player.GetPlanet())
			player.Save();
		
		// The Preferences class reads the screen dimensions, so update them if
		// the window is full screen:
		bool isFullscreen = (restoreWidth != 0);
		Preferences::Set("fullscreen", isFullscreen);
		if(isFullscreen)
			Screen::SetRaw(restoreWidth, restoreHeight);
		Preferences::Save();
		
		Cleanup(window, context);
	}
	catch(const runtime_error &error)
	{
		DoError(error.what());
	}
	
	return 0;
}
示例#29
0
OutfitterPanel::OutfitterPanel(PlayerInfo &player)
    : ShopPanel(player, CATEGORIES), available(player.SoldOutfits())
{
    for(const pair<string, Outfit> &it : GameData::Outfits())
        catalog[it.second.Category()].insert(it.first);
}
示例#30
0
HailPanel::HailPanel(PlayerInfo &player, const shared_ptr<Ship> &ship)
	: player(player), ship(ship),
	sprite(ship->GetSprite().GetSprite()), unit(2. * ship->Unit())
{
	SetInterruptible(false);
	
	const Government *gov = ship->GetGovernment();
	header = gov->GetName() + " ship \"" + ship->Name() + "\":";
	
	if(gov->GetName() == "Derelict")
	{
		message = "There is no response to your hail.";
	}
	else if(gov->IsEnemy())
	{
		if(ship->IsDisabled())
			message = GameData::Phrases().Get("hostile disabled")->Get();
		else
		{
			SetBribe(gov->GetBribeFraction());
			if(bribe)
				message = "If you want us to leave you alone, it'll cost you "
					+ Format::Number(bribe) + " credits.";
		}
	}
	else if(ship->IsDisabled())
	{
		const Ship *flagship = player.Flagship();
		if(!flagship->JumpsRemaining() || flagship->IsDisabled())
			message = "Sorry, we can't help you, because our ship is disabled.";
		else
			message = "Our ship has been disabled! Please come board our ship and patch us up!";
	}
	else
	{
		// Is the player in any need of assistance?
		const Ship *flagship = player.Flagship();
		// Check if the player is out of fuel.
		if(!flagship->JumpsRemaining())
		{
			playerNeedsHelp = true;
			canGiveFuel = ship->CanRefuel(*flagship);
		}
		// Check if the player is disabled.
		if(flagship->IsDisabled())
		{
			playerNeedsHelp = true;
			canRepair = true;
		}
		
		if(canGiveFuel || canRepair)
			message = "Looks like you've gotten yourself into a bit of trouble. "
				"Would you like us to ";
		if(canGiveFuel && canRepair)
			message += "patch you up and give you some fuel?";
		else if(canGiveFuel)
			message += "give you some fuel?";
		else if(canRepair)
			message += "patch you up?";
	}
	
	if(message.empty())
		message = ship->GetHail();
}