diff options
Diffstat (limited to 'src/game/base')
| -rw-r--r-- | src/game/base/Makefile.am | 8 | ||||
| -rw-r--r-- | src/game/base/base.cc | 661 | ||||
| -rw-r--r-- | src/game/base/base.h | 77 | ||||
| -rw-r--r-- | src/game/base/game.cc | 661 | ||||
| -rw-r--r-- | src/game/base/jumppoint.cc | 29 | ||||
| -rw-r--r-- | src/game/base/jumppoint.h | 40 | ||||
| -rw-r--r-- | src/game/base/navpoint.cc | 27 | ||||
| -rw-r--r-- | src/game/base/navpoint.h | 27 | ||||
| -rw-r--r-- | src/game/base/planet.cc | 27 | ||||
| -rw-r--r-- | src/game/base/planet.h | 27 | ||||
| -rw-r--r-- | src/game/base/racetrack.cc | 195 | ||||
| -rw-r--r-- | src/game/base/racetrack.h | 63 | ||||
| -rw-r--r-- | src/game/base/ship.cc | 464 | ||||
| -rw-r--r-- | src/game/base/ship.h | 60 | ||||
| -rw-r--r-- | src/game/base/shipmodel.cc | 72 | ||||
| -rw-r--r-- | src/game/base/shipmodel.h | 70 | ||||
| -rw-r--r-- | src/game/base/star.cc | 25 | ||||
| -rw-r--r-- | src/game/base/star.h | 29 | 
18 files changed, 2562 insertions, 0 deletions
| diff --git a/src/game/base/Makefile.am b/src/game/base/Makefile.am new file mode 100644 index 0000000..a8258b2 --- /dev/null +++ b/src/game/base/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/game +METASOURCES = AUTO +libbase_la_LDFLAGS = -avoid-version +noinst_LTLIBRARIES = libbase.la +libbase_la_SOURCES = base.cc jumppoint.cc navpoint.cc planet.cc racetrack.cc \ +		     ship.cc shipmodel.cc star.cc +noinst_HEADERS = base.h jumppoint.h navpoint.h planet.h racetrack.h ship.h \ +	shipmodel.h star.h diff --git a/src/game/base/base.cc b/src/game/base/base.cc new file mode 100644 index 0000000..70d9335 --- /dev/null +++ b/src/game/base/base.cc @@ -0,0 +1,661 @@ +/* +   base/base.cc +   This file is part of the Osirion project and is distributed under +   the terms of the GNU General Public License version 2 +*/ + +#include <vector> +#include <string> + +#include "auxiliary/functions.h" +#include "core/gameserver.h" +#include "filesystem/filesystem.h" +#include "filesystem/inifile.h" +#include "base/base.h" +#include "base/navpoint.h" +#include "base/jumppoint.h" +#include "base/planet.h" +#include "base/racetrack.h" +#include "base/ship.h" +#include "base/star.h" +#include "math/mathlib.h" +#include "sys/sys.h" + +namespace base +{ + +ShipModel		*default_shipmodel = 0; +core::Zone		*default_zone = 0; + +/*----- engine game functions ------------------------------------- */ + +/// list the ship model registry +void func_list_ship(std::string const &args) +{ +	ShipModel::list(); +} + +/// a player joins the game +void func_join(core::Player *player, std::string const &args) +{ +	if (player->control()) +		return; + +	player->set_zone(default_zone); +	Ship *ship = new Ship(player, default_shipmodel); +	ship->set_zone(default_zone); +	player->set_control(ship); + +	core::server()->send_sound(player, "game/buy-ship"); +	 +	std::string message("^B"); +	message.append(player->name()); +	message.append("^B joins the game."); +	core::server()->broadcast(message); + +	player->player_dirty = true; +} + +/// a player joins the spectators +void func_spectate(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; + +	std::string message("^B"); +	message.append(player->name()); +	message.append("^B spectates."); +	core::server()->broadcast(message); + +	if (player->control()) { +		player->remove_asset(player->control()); +	} +} + +/// a player buys a ship +void func_buy(core::Player *player, std::string const &args) +{ +	 +	std::string shipname; +	std::string helpstr; +	std::istringstream is(args); +	is >> shipname; +	aux::to_lowercase(shipname); + +	ShipModel *shipmodel = 0; +	for (ShipModel::iterator smit = ShipModel::registry.begin(); smit != ShipModel::registry.end(); smit++) { +		if (shipname == (*smit).first) { +			shipmodel = (*smit).second; +			break; +		} + +		if (helpstr.size()) +			helpstr.append("^N|^B"); +		helpstr.append((*smit).second->label()); +	} + +	if (shipmodel) { +		// player has only ship for now +		if (player->control()) { +			player->remove_asset(player->control()); +		} + +		Ship * ship = new Ship(player, shipmodel); +		if (player->zone()) { +			ship->set_zone(player->zone()); +		} else { +			ship->set_zone(default_zone); +		} +		player->set_control(ship); +		 +		core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name())); +		core::server()->send_sound(player, "game/buy-ship"); + +	} else { +		core::server()->send(player, "Usage: buy [^B" + helpstr + "^N]"); +	} +} + +/// a player sends standard hails +void func_hail(core::Player *player, std::string const &args) +{ +	std::string  target; +	std::istringstream is(args); +	if (!(is >> target)) { +		core::server()->send(player, "Usage: hail [player]"); +		return; +	} + +	core::Player *targetplayer = core::server()->find_player(target); +	if (!targetplayer) { +		core::server()->send(player, "^BPlayer " + target + "^B not found."); +		return; +	} + +	core::server()->send(player, "^BYou hail " + targetplayer->name() + "^B."); +	core::server()->send_sound(player, "com/hail"); + +	core::server()->send(targetplayer, "^B" + player->name() + "^B hails you!"); +	core::server()->send_sound(targetplayer, "com/hail"); +} + +/// a player actives the hyperspace jump drive on his ship +void func_jump(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; +	if (!player->control()->moduletype() == ship_enttype) +		return; +	Ship * ship = static_cast<Ship *>(player->control()); +	ship->jump(args); +} + +/// a player actives the kinetic impulse drive on his ship +void func_impulse(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; +	if (!player->control()->moduletype() == ship_enttype) +		return; +	Ship * ship = static_cast<Ship *>(player->control()); +	ship->impulse(); +} + +/* ---- The Game class --------------------------------------------- */ + +Base 			*Base::game_instance = 0; + +Base::Base() : core::Module("Project::OSiRiON") +{ +	game_instance = this; +	g_impulsespeed = 0; +} + +Base::~Base() +{ +	game_instance = 0; +} + +void Base::init() +{ +	module_running = false; + +	ShipModel::clear(); + +	if (!load_world()) { +		abort(); +		return; +	} +		 +	if (!load_ships()) { +		abort(); +		return; +	} + +	// add engine game functions +	core::Func *func = 0; +	 +	func = core::Func::add("join", (core::GameFuncPtr) func_join); +	func->set_info("join the game"); +	func = core::Func::add("hail", (core::GameFuncPtr) func_hail); +	func->set_info("send a standard hail"); +	func = core::Func::add("spectate", (core::GameFuncPtr) func_spectate); +	func->set_info("leave the game and spectate"); + +	func = core::Func::add("buy", (core::GameFuncPtr) func_buy); +	func->set_info("buy a ship"); + +	func = core::Func::add("jump", (core::GameFuncPtr) func_jump); +	func->set_info("[string] activate or deactivate hyperspace jump drive"); + +	func = core::Func::add("impulse", (core::GameFuncPtr) func_impulse); +	func->set_info("activate are deactive kinetic impulse drive"); + +	// add engine core functions +	func = core::Func::add("list_ship", (core::FuncPtr) func_list_ship); +	func->set_info("list ship statistics"); + +	g_impulsespeed = core::Cvar::get("g_impulsespeed", "15", core::Cvar::Game | core::Cvar::Archive); +	g_impulsespeed->set_info("[float] speed of the impulse drive"); + +	g_impulseacceleration = core::Cvar::get("g_impulseacceleration", "5", core::Cvar::Game | core::Cvar::Archive); +	g_impulseacceleration->set_info("[float] acceleration of the impulse drive"); + +	g_strafespeed = core::Cvar::get("g_strafespeed", "0.003", core::Cvar::Game | core::Cvar::Archive); +	g_strafespeed->set_info("[float] strafe speed"); + +	g_jumppointrange = core::Cvar::get("g_jumppointrange", "512", core::Cvar::Game | core::Cvar::Archive); +	g_jumppointrange->set_info("[float] jumppoint range"); + +	g_devel = core::Cvar::get("g_devel", "0", core::Cvar::Archive); +	g_devel->set_info("[bool] enable or disable developer mode"); + +	// indicate the module is ready to run frames +	module_running = true; +} + +void Base::shutdown() +{ +	g_impulsespeed = 0; +	// game functions are automaticly removed + +	// remove engine core functions +	core::Func::remove("list_ship"); + +	ShipModel::clear(); +	module_running = false; +} + +bool Base::load_world() +{ +	std::string inifilename("world"); + +	filesystem::IniFile worldini; +	worldini.open(inifilename); + +	if (!worldini.is_open()) { +		con_error << "Could not open " << worldini.name() << std::endl; +		return false; +	} + +	core::Zone *zone = 0; +	std::string label; + +	while (worldini.getline()) { + +		if (worldini.got_section()) { + +			if (worldini.got_section("world")) { +				continue; +			} else { +				con_warn << worldini.name() << "  unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; +			} + +		} else if (worldini.section().compare("world") == 0 ) { +			if (worldini.got_key_string("zone", label)) { +				aux::to_label(label); +				zone = new core::Zone(label); +				core::Zone::add(zone); +			} +		} +	} +	worldini.close(); + +	if (!core::Zone::registry().size()) { +		con_error << "No zones found!" << std::endl; +		return false; +	} + +	con_debug << "  " << worldini.name() << " " << core::Zone::registry().size() << " zones" << std::endl; + +	for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { +		if (!load_zone((*it).second)) { +			return false; +		} +	} + +	for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { +		if (!validate_zone((*it).second)) { +			return false; +		} +	} + +	if (!default_zone) { +		con_error << "No default zone found!" << std::endl; +		return false; +	} + +	return true; +} + +bool Base::got_entity_key(filesystem::IniFile &inifile, core::Entity *entity) +{ +	std::string shapename; +	std::string strval; +	float direction; +	float pitch; +	float roll; + +	if (inifile.got_key_string("shape", shapename)) { + +		if (shapename.compare("axis") == 0) { +			entity->entity_shape = core::Entity::Axis; +			return true; +		} else if (shapename.compare("cube") == 0) { +			entity->entity_shape = core::Entity::Cube; +			return true; +		} else if (shapename.compare("diamond") == 0) { +			entity->entity_shape = core::Entity::Diamond; +			return true; +		} else if (shapename.compare("sphere") == 0) { +			entity->entity_shape = core::Entity::Sphere; +			return true; +		} else { +			con_warn << inifile.name() << " unknown shape '" << shapename << "' at line " << inifile.line() << std::endl; +			return false; +		} + +	} else if (inifile.got_key_string("label", strval)) { +		aux::to_label(strval); +		entity->entity_label.assign(strval);		 +		return true; +	} else if (inifile.got_key_string("name", strval)) { +		aux::strip_quotes(strval); +		entity->entity_name.assign(strval); +		return true; +	} else if (inifile.got_key_string("model", entity->entity_modelname)) { +		return true; +	} else if (inifile.got_key_angle("direction", direction)) { +		entity->axis().change_direction(direction); +		return true; +	} else if (inifile.got_key_angle("pitch", pitch)) { +		entity->axis().change_pitch(pitch); +		return true; +	} else if (inifile.got_key_angle("roll", roll)) { +		entity->axis().change_roll(roll); +		return true; +	} else if (inifile.got_key_angle("radius", entity->entity_radius)) { +		return true; +	} else if (inifile.got_key_vector3f("location", entity->entity_location)) { +		return true; +	} else if (inifile.got_key_color("color", entity->entity_color)) { +		return true; +	} else if (inifile.got_key_color("colorsecond", entity->entity_color_second)) { +		return true; +	} + +	return false; +} + +bool Base::load_zone(core::Zone *zone) +{ +	using math::Vector3f; +	using math::Color; + +	std::string inifilename("zones/"); +	inifilename.append(zone->label()); + +	filesystem::IniFile zoneini; +	zoneini.open(inifilename); + +	if (!zoneini.is_open()) { +		con_error << "Could not open " << zoneini.name() << std::endl; +		return false; +	} + +	size_t count = 0; + +	Planet *planet = 0; +	Star *star = 0; +	NavPoint *navpoint = 0; +	JumpPoint *jumppoint = 0; +	RaceTrack *racetrack = 0; +	CheckPoint *checkpoint = 0; +	core::Entity *entity = 0; + +	bool b; + +	std::string strval; + +	// set th default sky +	zone->set_sky("sky"); + +	while (zoneini.getline()) { +		if (zoneini.got_key()) { +			if (zoneini.section().compare("zone") == 0) { +				if (zoneini.got_key_string("name", strval)) { +					aux::strip_quotes(strval); +					zone->set_name(strval); +					continue; +				} else if (zoneini.got_key_string("sky", strval)) { +					zone->set_sky(strval); +					continue; +				} else if (zoneini.got_key_bool("default", b)) { +					if (b) default_zone = zone; +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("star") == 0) { +				if (got_entity_key(zoneini, star)) { +					continue; +				} else if (zoneini.got_key_string("texture", star->entity_texture)) { +					 continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("navpoint") == 0) { +				if (got_entity_key(zoneini, navpoint)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("jumppoint") == 0) { +				if (got_entity_key(zoneini, jumppoint)) { +					continue; +				} else if (zoneini.got_key_string("target", jumppoint->jumppoint_targetlabel)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("planet") == 0) { +				if (got_entity_key(zoneini, planet)) { +					continue; +				} else if (zoneini.got_key_string("texture", planet->entity_texture)) { +					 continue; +				} else if (zoneini.got_key_float("rotationspeed", planet->entity_rotationspeed)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("racetrack") == 0) { +				if (got_entity_key(zoneini, racetrack)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("checkpoint") == 0) { +				if (got_entity_key(zoneini, checkpoint)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("entity") == 0) { +				if (got_entity_key(zoneini, entity)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} +		} else if (zoneini.got_section("zone")) { +			continue; + +		} else if (zoneini.got_section("star")) { +			star = new Star(); +			star->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section("navpoint")) { +			navpoint = new NavPoint(); +			navpoint->set_zone(zone); +			count ++; +		 +		} else if (zoneini.got_section("jumppoint")) { +			jumppoint = new JumpPoint(); +			jumppoint->set_zone(zone); +			count ++; + +		} else if(zoneini.got_section("racetrack")) { +			racetrack = new RaceTrack(); +			racetrack->set_zone(zone); + +		} else if(zoneini.got_section("checkpoint")) { +			checkpoint = new CheckPoint(racetrack); +			if (!racetrack) { +				con_warn << zoneini.name() << " checkpoint without racetrack at line " << zoneini.line() << std::endl; +			} + +		} else if (zoneini.got_section("planet")) { +			planet = new Planet(); +			planet->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section("entity")) { +			entity = new core::Entity(); +			entity->entity_flags += core::Entity::Static; +			entity->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section()) { +			con_warn << zoneini.name() << " unknown section '" << zoneini.section() << "' at line " << zoneini.line() << std::endl; +		} +	} +	zoneini.close(); + +	con_debug << "  " << zoneini.name() << " " << zone->content().size() << " entities" << std::endl; + + +	return true; +} + +bool Base::validate_zone(core::Zone *zone) +{ +	con_debug << "  validating " << zone->name() << std::endl; + +	for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { +		core::Entity *entity = (*it); + +		if (entity->entity_moduletypeid == jumppoint_enttype) { +			JumpPoint *jumppoint = static_cast<JumpPoint *>(entity); +			 +			if (jumppoint->targetlabel().size() < 3) { +				con_warn << "  Jumppoint with invalid target label '" << jumppoint->targetlabel() << "'\n"; +				continue; +			} +			size_t pos = jumppoint->targetlabel().find(':'); +			if ((pos < 1 ) || (pos >= (jumppoint->targetlabel().size()-1))) { +				con_warn << "  Jumppoint with invalid target label '" << jumppoint->targetlabel() << "'\n"; +				continue; +			} + +			std::string zonelabel(jumppoint->targetlabel().substr(0, pos)); +			std::string entitylabel(jumppoint->targetlabel().substr(pos+1, jumppoint->targetlabel().size()-pos)); + +			core::Zone *targetzone = core::Zone::find(zonelabel); +			if (!targetzone) { +				con_warn << "  Jumppoint with invalid target zone '" << zonelabel << "'\n"; +				continue; +			} + +			core::Entity *targetentity = targetzone->find_entity(entitylabel); +			if (!targetentity) { +				con_warn << "  Could not find target jumppoint '" << entitylabel << "'\n"; +				continue; +			} + +			if (targetentity->moduletype() != jumppoint_enttype) { +				con_warn << "  Jumppoint with invalid target jumppoint '" << entitylabel << "'\n"; +				continue; +			} + +			jumppoint->jumppoint_target = static_cast<JumpPoint *>(targetentity); + +			//con_debug << "  Jumppoint " << zone->label() << ":" << jumppoint->label() << " with target " << jumppoint->targetlabel() << std::endl; +		} +	} + +	return true; +} + +// read ship model specifications +bool Base::load_ships() +{ +	using math::Vector3f; +	using math::Color; + +	default_shipmodel = 0; + +	filesystem::IniFile shipsini; +	shipsini.open("ships"); +	if (!shipsini.is_open()) { +		con_error << "Could not open ini/ships.ini!" << std::endl; +		return false; +	} + +	ShipModel *shipmodel = 0; +	std::string label; +	bool b; + +	while (shipsini.getline()) { +		if (shipsini.got_key()) { +			if (shipsini.section().compare("ship") == 0) { +				if (shipsini.got_key_string("label", label)) { +					aux::to_label(label); +					shipmodel->shipmodel_label.assign(label); +					ShipModel::add(shipmodel); +					continue; +				} else if (shipsini.got_key_string("name",shipmodel->shipmodel_name)) { +					 continue; +				} else if (shipsini.got_key_string("model", shipmodel->shipmodel_modelname)) { +					continue; +				} else if (shipsini.got_key_bool("default", b)) { +					if (b) default_shipmodel = shipmodel; +					continue; +				} else if (shipsini.got_key_bool("jumpdrive", shipmodel->shipmodel_jumpdrive)) { +					continue; +				} else if (shipsini.got_key_float("acceleration", shipmodel->shipmodel_acceleration)) { +					continue; +				} else if (shipsini.got_key_float("maxspeed", shipmodel->shipmodel_maxspeed)) { +					continue; +				} else if (shipsini.got_key_float("turnspeed", shipmodel->shipmodel_turnspeed)) { +					math::clamp(shipmodel->shipmodel_turnspeed, 0.0f, 90.0f); +					continue; +				} else { +					con_warn << shipsini.name() << " unknown key '" << shipsini.key() << "' at line " << shipsini.line() << std::endl; +				} +			} +		} else if (shipsini.got_section("ship")) { +			shipmodel = new ShipModel(); + +			if (!default_shipmodel) +				default_shipmodel = shipmodel;  + +		} else if (shipsini.got_section()) { +			con_warn << shipsini.name() << " unknown section '" << shipsini.section() << "' at line " << shipsini.line() << std::endl; +		} +	} +	shipsini.close(); + +	con_debug << "  " << shipsini.name() << " " << ShipModel::registry.size() << " ship models" << std::endl; + +	if (!default_shipmodel) { +		con_error << "No default ship model found!\n"; +		return false; +	} + +	return true; +} + +void Base::frame(float seconds) +{ +	if (!running()) +		return; +} + +void Base::player_connect(core::Player *player) +{ +	std::string args; +	player->set_zone(default_zone); +	func_spectate(player, args); +} + +void Base::player_disconnect(core::Player *player) +{ +	player->remove_asset(player->control()); +} + +} // namespace game + diff --git a/src/game/base/base.h b/src/game/base/base.h new file mode 100644 index 0000000..fea1919 --- /dev/null +++ b/src/game/base/base.h @@ -0,0 +1,77 @@ +/* +   game/game.h +   This file is part of the Osirion project and is distributed under  +   the terms of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_H__ +#define __INCLUDED_BASE_H__ + +#include <vector> +#include <string> + +#include "base/ship.h" +#include "base/star.h" +#include "core/core.h" +#include "filesystem/inifile.h" +#include "sys/sys.h" + +/// the base game module +/** the base game module containis the game-specific code for Project::Osirion + */ +namespace base +{ + +// entity type constants +const unsigned int ship_enttype = 256; +const unsigned int star_enttype = 257; +const unsigned int planet_enttype = 258; +const unsigned int navpoint_enttype = 259; +const unsigned int jumppoint_enttype = 260; + +class Base : public core::Module { +public: +	Base(); +	~Base(); + +	/// initialize the game +	void init(); + +	/// shutdown the game +	void shutdown(); + +	/// run one time frame +	void frame(float seconds); + +	/// is called when a player connects +	void player_connect(core::Player *player); + +	/// is called when a player disconnects +	void player_disconnect(core::Player *player); + +	static inline Base *instance() { return game_instance; } + +	core::Cvar *g_impulsespeed; +	core::Cvar *g_impulseacceleration; +	core::Cvar *g_strafespeed; +	core::Cvar *g_jumppointrange; +	core::Cvar *g_devel; + +private: +	bool got_entity_key(filesystem::IniFile &inifile, core::Entity *entity); + +	bool load_world(); + +	bool load_zone(core::Zone *zone); + +	bool validate_zone(core::Zone *zone); + +	bool load_ships(); + +	static Base *game_instance; +}; + +} + +#endif // __INCLUDED_BASE_H__ + diff --git a/src/game/base/game.cc b/src/game/base/game.cc new file mode 100644 index 0000000..4d66cbe --- /dev/null +++ b/src/game/base/game.cc @@ -0,0 +1,661 @@ +/* +   game/game.cc +   This file is part of the Osirion project and is distributed under +   the terms of the GNU General Public License version 2 +*/ + +#include <vector> +#include <string> + +#include "auxiliary/functions.h" +#include "core/gameserver.h" +#include "filesystem/filesystem.h" +#include "filesystem/inifile.h" +#include "game/game.h" +#include "game/navpoint.h" +#include "game/jumppoint.h" +#include "game/planet.h" +#include "game/racetrack.h" +#include "game/ship.h" +#include "game/star.h" +#include "math/mathlib.h" +#include "sys/sys.h" + +namespace game +{ + +ShipModel		*default_shipmodel = 0; +core::Zone		*default_zone = 0; + +/*----- engine game functions ------------------------------------- */ + +/// list the ship model registry +void func_list_ship(std::string const &args) +{ +	ShipModel::list(); +} + +/// a player joins the game +void func_join(core::Player *player, std::string const &args) +{ +	if (player->control()) +		return; + +	player->set_zone(default_zone); +	Ship *ship = new Ship(player, default_shipmodel); +	ship->set_zone(default_zone); +	player->set_control(ship); + +	core::server()->send_sound(player, "game/buy-ship"); +	 +	std::string message("^B"); +	message.append(player->name()); +	message.append("^B joins the game."); +	core::server()->broadcast(message); + +	player->player_dirty = true; +} + +/// a player joins the spectators +void func_spectate(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; + +	std::string message("^B"); +	message.append(player->name()); +	message.append("^B spectates."); +	core::server()->broadcast(message); + +	if (player->control()) { +		player->remove_asset(player->control()); +	} +} + +/// a player buys a ship +void func_buy(core::Player *player, std::string const &args) +{ +	 +	std::string shipname; +	std::string helpstr; +	std::istringstream is(args); +	is >> shipname; +	aux::to_lowercase(shipname); + +	ShipModel *shipmodel = 0; +	for (ShipModel::iterator smit = ShipModel::registry.begin(); smit != ShipModel::registry.end(); smit++) { +		if (shipname == (*smit).first) { +			shipmodel = (*smit).second; +			break; +		} + +		if (helpstr.size()) +			helpstr.append("^N|^B"); +		helpstr.append((*smit).second->label()); +	} + +	if (shipmodel) { +		// player has only ship for now +		if (player->control()) { +			player->remove_asset(player->control()); +		} + +		Ship * ship = new Ship(player, shipmodel); +		if (player->zone()) { +			ship->set_zone(player->zone()); +		} else { +			ship->set_zone(default_zone); +		} +		player->set_control(ship); +		 +		core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name())); +		core::server()->send_sound(player, "game/buy-ship"); + +	} else { +		core::server()->send(player, "Usage: buy [^B" + helpstr + "^N]"); +	} +} + +/// a player sends standard hails +void func_hail(core::Player *player, std::string const &args) +{ +	std::string  target; +	std::istringstream is(args); +	if (!(is >> target)) { +		core::server()->send(player, "Usage: hail [player]"); +		return; +	} + +	core::Player *targetplayer = core::server()->find_player(target); +	if (!targetplayer) { +		core::server()->send(player, "^BPlayer " + target + "^B not found."); +		return; +	} + +	core::server()->send(player, "^BYou hail " + targetplayer->name() + "^B."); +	core::server()->send_sound(player, "com/hail"); + +	core::server()->send(targetplayer, "^B" + player->name() + "^B hails you!"); +	core::server()->send_sound(targetplayer, "com/hail"); +} + +/// a player actives the hyperspace jump drive on his ship +void func_jump(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; +	if (!player->control()->moduletype() == ship_enttype) +		return; +	Ship * ship = static_cast<Ship *>(player->control()); +	ship->jump(args); +} + +/// a player actives the kinetic impulse drive on his ship +void func_impulse(core::Player *player, std::string const &args) +{ +	if (!player->control()) +		return; +	if (!player->control()->moduletype() == ship_enttype) +		return; +	Ship * ship = static_cast<Ship *>(player->control()); +	ship->impulse(); +} + +/* ---- The Game class --------------------------------------------- */ + +Game 			*Game::game_instance = 0; + +Game::Game() : core::Module("Project::OSiRiON") +{ +	game_instance = this; +	g_impulsespeed = 0; +} + +Game::~Game() +{ +	game_instance = 0; +} + +void Game::init() +{ +	module_running = false; + +	ShipModel::clear(); + +	if (!load_world()) { +		abort(); +		return; +	} +		 +	if (!load_ships()) { +		abort(); +		return; +	} + +	// add engine game functions +	core::Func *func = 0; +	 +	func = core::Func::add("join", (core::GameFuncPtr) func_join); +	func->set_info("join the game"); +	func = core::Func::add("hail", (core::GameFuncPtr) func_hail); +	func->set_info("send a standard hail"); +	func = core::Func::add("spectate", (core::GameFuncPtr) func_spectate); +	func->set_info("leave the game and spectate"); + +	func = core::Func::add("buy", (core::GameFuncPtr) func_buy); +	func->set_info("buy a ship"); + +	func = core::Func::add("jump", (core::GameFuncPtr) func_jump); +	func->set_info("[string] activate or deactivate hyperspace jump drive"); + +	func = core::Func::add("impulse", (core::GameFuncPtr) func_impulse); +	func->set_info("activate are deactive kinetic impulse drive"); + +	// add engine core functions +	func = core::Func::add("list_ship", (core::FuncPtr) func_list_ship); +	func->set_info("list ship statistics"); + +	g_impulsespeed = core::Cvar::get("g_impulsespeed", "15", core::Cvar::Game | core::Cvar::Archive); +	g_impulsespeed->set_info("[float] speed of the impulse drive"); + +	g_impulseacceleration = core::Cvar::get("g_impulseacceleration", "5", core::Cvar::Game | core::Cvar::Archive); +	g_impulseacceleration->set_info("[float] acceleration of the impulse drive"); + +	g_strafespeed = core::Cvar::get("g_strafespeed", "0.003", core::Cvar::Game | core::Cvar::Archive); +	g_strafespeed->set_info("[float] strafe speed"); + +	g_jumppointrange = core::Cvar::get("g_jumppointrange", "512", core::Cvar::Game | core::Cvar::Archive); +	g_jumppointrange->set_info("[float] jumppoint range"); + +	g_devel = core::Cvar::get("g_devel", "0", core::Cvar::Archive); +	g_devel->set_info("[bool] enable or disable developer mode"); + +	// indicate the module is ready to run frames +	module_running = true; +} + +void Game::shutdown() +{ +	g_impulsespeed = 0; +	// game functions are automaticly removed + +	// remove engine core functions +	core::Func::remove("list_ship"); + +	ShipModel::clear(); +	module_running = false; +} + +bool Game::load_world() +{ +	std::string inifilename("world"); + +	filesystem::IniFile worldini; +	worldini.open(inifilename); + +	if (!worldini.is_open()) { +		con_error << "Could not open " << worldini.name() << std::endl; +		return false; +	} + +	core::Zone *zone = 0; +	std::string label; + +	while (worldini.getline()) { + +		if (worldini.got_section()) { + +			if (worldini.got_section("world")) { +				continue; +			} else { +				con_warn << worldini.name() << "  unknown section '" << worldini.section() << "' at line " << worldini.line() << std::endl; +			} + +		} else if (worldini.section().compare("world") == 0 ) { +			if (worldini.got_key_string("zone", label)) { +				aux::to_label(label); +				zone = new core::Zone(label); +				core::Zone::add(zone); +			} +		} +	} +	worldini.close(); + +	if (!core::Zone::registry().size()) { +		con_error << "No zones found!" << std::endl; +		return false; +	} + +	con_debug << "  " << worldini.name() << " " << core::Zone::registry().size() << " zones" << std::endl; + +	for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { +		if (!load_zone((*it).second)) { +			return false; +		} +	} + +	for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { +		if (!validate_zone((*it).second)) { +			return false; +		} +	} + +	if (!default_zone) { +		con_error << "No default zone found!" << std::endl; +		return false; +	} + +	return true; +} + +bool Game::got_entity_key(filesystem::IniFile &inifile, core::Entity *entity) +{ +	std::string shapename; +	std::string strval; +	float direction; +	float pitch; +	float roll; + +	if (inifile.got_key_string("shape", shapename)) { + +		if (shapename.compare("axis") == 0) { +			entity->entity_shape = core::Entity::Axis; +			return true; +		} else if (shapename.compare("cube") == 0) { +			entity->entity_shape = core::Entity::Cube; +			return true; +		} else if (shapename.compare("diamond") == 0) { +			entity->entity_shape = core::Entity::Diamond; +			return true; +		} else if (shapename.compare("sphere") == 0) { +			entity->entity_shape = core::Entity::Sphere; +			return true; +		} else { +			con_warn << inifile.name() << " unknown shape '" << shapename << "' at line " << inifile.line() << std::endl; +			return false; +		} + +	} else if (inifile.got_key_string("label", strval)) { +		aux::to_label(strval); +		entity->entity_label.assign(strval);		 +		return true; +	} else if (inifile.got_key_string("name", strval)) { +		aux::strip_quotes(strval); +		entity->entity_name.assign(strval); +		return true; +	} else if (inifile.got_key_string("model", entity->entity_modelname)) { +		return true; +	} else if (inifile.got_key_angle("direction", direction)) { +		entity->axis().change_direction(direction); +		return true; +	} else if (inifile.got_key_angle("pitch", pitch)) { +		entity->axis().change_pitch(pitch); +		return true; +	} else if (inifile.got_key_angle("roll", roll)) { +		entity->axis().change_roll(roll); +		return true; +	} else if (inifile.got_key_angle("radius", entity->entity_radius)) { +		return true; +	} else if (inifile.got_key_vector3f("location", entity->entity_location)) { +		return true; +	} else if (inifile.got_key_color("color", entity->entity_color)) { +		return true; +	} else if (inifile.got_key_color("colorsecond", entity->entity_color_second)) { +		return true; +	} + +	return false; +} + +bool Game::load_zone(core::Zone *zone) +{ +	using math::Vector3f; +	using math::Color; + +	std::string inifilename("zones/"); +	inifilename.append(zone->label()); + +	filesystem::IniFile zoneini; +	zoneini.open(inifilename); + +	if (!zoneini.is_open()) { +		con_error << "Could not open " << zoneini.name() << std::endl; +		return false; +	} + +	size_t count = 0; + +	Planet *planet = 0; +	Star *star = 0; +	NavPoint *navpoint = 0; +	JumpPoint *jumppoint = 0; +	RaceTrack *racetrack = 0; +	CheckPoint *checkpoint = 0; +	core::Entity *entity = 0; + +	bool b; + +	std::string strval; + +	// set th default sky +	zone->set_sky("sky"); + +	while (zoneini.getline()) { +		if (zoneini.got_key()) { +			if (zoneini.section().compare("zone") == 0) { +				if (zoneini.got_key_string("name", strval)) { +					aux::strip_quotes(strval); +					zone->set_name(strval); +					continue; +				} else if (zoneini.got_key_string("sky", strval)) { +					zone->set_sky(strval); +					continue; +				} else if (zoneini.got_key_bool("default", b)) { +					if (b) default_zone = zone; +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("star") == 0) { +				if (got_entity_key(zoneini, star)) { +					continue; +				} else if (zoneini.got_key_string("texture", star->entity_texture)) { +					 continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("navpoint") == 0) { +				if (got_entity_key(zoneini, navpoint)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("jumppoint") == 0) { +				if (got_entity_key(zoneini, jumppoint)) { +					continue; +				} else if (zoneini.got_key_string("target", jumppoint->jumppoint_targetlabel)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} else if (zoneini.section().compare("planet") == 0) { +				if (got_entity_key(zoneini, planet)) { +					continue; +				} else if (zoneini.got_key_string("texture", planet->entity_texture)) { +					 continue; +				} else if (zoneini.got_key_float("rotationspeed", planet->entity_rotationspeed)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("racetrack") == 0) { +				if (got_entity_key(zoneini, racetrack)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("checkpoint") == 0) { +				if (got_entity_key(zoneini, checkpoint)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} + +			} else if (zoneini.section().compare("entity") == 0) { +				if (got_entity_key(zoneini, entity)) { +					continue; +				} else { +					con_warn << zoneini.name() << " unknown key '" << zoneini.key() << "' at line " << zoneini.line() << std::endl; +				} +			} +		} else if (zoneini.got_section("zone")) { +			continue; + +		} else if (zoneini.got_section("star")) { +			star = new Star(); +			star->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section("navpoint")) { +			navpoint = new NavPoint(); +			navpoint->set_zone(zone); +			count ++; +		 +		} else if (zoneini.got_section("jumppoint")) { +			jumppoint = new JumpPoint(); +			jumppoint->set_zone(zone); +			count ++; + +		} else if(zoneini.got_section("racetrack")) { +			racetrack = new RaceTrack(); +			racetrack->set_zone(zone); + +		} else if(zoneini.got_section("checkpoint")) { +			checkpoint = new CheckPoint(racetrack); +			if (!racetrack) { +				con_warn << zoneini.name() << " checkpoint without racetrack at line " << zoneini.line() << std::endl; +			} + +		} else if (zoneini.got_section("planet")) { +			planet = new Planet(); +			planet->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section("entity")) { +			entity = new core::Entity(); +			entity->entity_flags += core::Entity::Static; +			entity->set_zone(zone); +			count ++; + +		} else if (zoneini.got_section()) { +			con_warn << zoneini.name() << " unknown section '" << zoneini.section() << "' at line " << zoneini.line() << std::endl; +		} +	} +	zoneini.close(); + +	con_debug << "  " << zoneini.name() << " " << zone->content().size() << " entities" << std::endl; + + +	return true; +} + +bool Game::validate_zone(core::Zone *zone) +{ +	con_debug << "  validating " << zone->name() << std::endl; + +	for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { +		core::Entity *entity = (*it); + +		if (entity->entity_moduletypeid == jumppoint_enttype) { +			JumpPoint *jumppoint = static_cast<JumpPoint *>(entity); +			 +			if (jumppoint->targetlabel().size() < 3) { +				con_warn << "  Jumppoint with invalid target label '" << jumppoint->targetlabel() << "'\n"; +				continue; +			} +			size_t pos = jumppoint->targetlabel().find(':'); +			if ((pos < 1 ) || (pos >= (jumppoint->targetlabel().size()-1))) { +				con_warn << "  Jumppoint with invalid target label '" << jumppoint->targetlabel() << "'\n"; +				continue; +			} + +			std::string zonelabel(jumppoint->targetlabel().substr(0, pos)); +			std::string entitylabel(jumppoint->targetlabel().substr(pos+1, jumppoint->targetlabel().size()-pos)); + +			core::Zone *targetzone = core::Zone::find(zonelabel); +			if (!targetzone) { +				con_warn << "  Jumppoint with invalid target zone '" << zonelabel << "'\n"; +				continue; +			} + +			core::Entity *targetentity = targetzone->find_entity(entitylabel); +			if (!targetentity) { +				con_warn << "  Could not find target jumppoint '" << entitylabel << "'\n"; +				continue; +			} + +			if (targetentity->moduletype() != jumppoint_enttype) { +				con_warn << "  Jumppoint with invalid target jumppoint '" << entitylabel << "'\n"; +				continue; +			} + +			jumppoint->jumppoint_target = static_cast<JumpPoint *>(targetentity); + +			//con_debug << "  Jumppoint " << zone->label() << ":" << jumppoint->label() << " with target " << jumppoint->targetlabel() << std::endl; +		} +	} + +	return true; +} + +// read ship model specifications +bool Game::load_ships() +{ +	using math::Vector3f; +	using math::Color; + +	default_shipmodel = 0; + +	filesystem::IniFile shipsini; +	shipsini.open("ships"); +	if (!shipsini.is_open()) { +		con_error << "Could not open ini/ships.ini!" << std::endl; +		return false; +	} + +	ShipModel *shipmodel = 0; +	std::string label; +	bool b; + +	while (shipsini.getline()) { +		if (shipsini.got_key()) { +			if (shipsini.section().compare("ship") == 0) { +				if (shipsini.got_key_string("label", label)) { +					aux::to_label(label); +					shipmodel->shipmodel_label.assign(label); +					ShipModel::add(shipmodel); +					continue; +				} else if (shipsini.got_key_string("name",shipmodel->shipmodel_name)) { +					 continue; +				} else if (shipsini.got_key_string("model", shipmodel->shipmodel_modelname)) { +					continue; +				} else if (shipsini.got_key_bool("default", b)) { +					if (b) default_shipmodel = shipmodel; +					continue; +				} else if (shipsini.got_key_bool("jumpdrive", shipmodel->shipmodel_jumpdrive)) { +					continue; +				} else if (shipsini.got_key_float("acceleration", shipmodel->shipmodel_acceleration)) { +					continue; +				} else if (shipsini.got_key_float("maxspeed", shipmodel->shipmodel_maxspeed)) { +					continue; +				} else if (shipsini.got_key_float("turnspeed", shipmodel->shipmodel_turnspeed)) { +					math::clamp(shipmodel->shipmodel_turnspeed, 0.0f, 90.0f); +					continue; +				} else { +					con_warn << shipsini.name() << " unknown key '" << shipsini.key() << "' at line " << shipsini.line() << std::endl; +				} +			} +		} else if (shipsini.got_section("ship")) { +			shipmodel = new ShipModel(); + +			if (!default_shipmodel) +				default_shipmodel = shipmodel;  + +		} else if (shipsini.got_section()) { +			con_warn << shipsini.name() << " unknown section '" << shipsini.section() << "' at line " << shipsini.line() << std::endl; +		} +	} +	shipsini.close(); + +	con_debug << "  " << shipsini.name() << " " << ShipModel::registry.size() << " ship models" << std::endl; + +	if (!default_shipmodel) { +		con_error << "No default ship model found!\n"; +		return false; +	} + +	return true; +} + +void Game::frame(float seconds) +{ +	if (!running()) +		return; +} + +void Game::player_connect(core::Player *player) +{ +	std::string args; +	player->set_zone(default_zone); +	func_spectate(player, args); +} + +void Game::player_disconnect(core::Player *player) +{ +	player->remove_asset(player->control()); +} + +} // namespace game + diff --git a/src/game/base/jumppoint.cc b/src/game/base/jumppoint.cc new file mode 100644 index 0000000..bcaf8c5 --- /dev/null +++ b/src/game/base/jumppoint.cc @@ -0,0 +1,29 @@ +/* +   base/jumppoint.cc +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#include "base/base.h" +#include "base/jumppoint.h" + +namespace base +{ + +JumpPoint::JumpPoint() : core::Entity(core::Entity::Static) +{ +	entity_shape = core::Entity::Diamond; +	entity_color.assign(0.0f, 0.8f, 0.8f, 1.0f); +	entity_color_second.assign(0.6f, 1.0f); +	entity_radius = 0.25f; + +	entity_moduletypeid = jumppoint_enttype; +	jumppoint_target = 0; +	entity_serverside = false; +} + +JumpPoint::~JumpPoint() +{ +} + +} diff --git a/src/game/base/jumppoint.h b/src/game/base/jumppoint.h new file mode 100644 index 0000000..4680832 --- /dev/null +++ b/src/game/base/jumppoint.h @@ -0,0 +1,40 @@ +/* +   base/jumppoint.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_JUMPPOINT_H__ +#define __INCLUDED_BASE_JUMPPOINT_H__ + +#include "core/entity.h" +#include "math/mathlib.h" + +#include <string> + +namespace base { + +/// a jump point +/** + * jumppoints are used to define hyperspace routes between systems + * when a ship actives the jump drive, a jump point will be opened + * between the current system and the target of the nearest jumppoint. + * + */ +class JumpPoint : public core::Entity { +public: +	JumpPoint(); +	~JumpPoint(); + +	inline std::string const & targetlabel() { return jumppoint_targetlabel; } +	inline JumpPoint *target() { return jumppoint_target; } + +	std::string	jumppoint_targetlabel; + +	JumpPoint	*jumppoint_target; +}; + +} + +#endif // __INCLUDED_BASE_JUMPPOINT_H__ + diff --git a/src/game/base/navpoint.cc b/src/game/base/navpoint.cc new file mode 100644 index 0000000..560962c --- /dev/null +++ b/src/game/base/navpoint.cc @@ -0,0 +1,27 @@ +/* +   base/navpoint.cc +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#include "base/navpoint.h" +#include "base/base.h" + +namespace base +{ + +NavPoint::NavPoint() : core::Entity(core::Entity::Static | core::Entity::Bright) +{ +	entity_shape = core::Entity::Diamond; +	entity_color.assign(1.0f, 1.0f); +	entity_color_second.assign(0.6f, 1.0f); +	entity_radius = 0.25f; + +	entity_moduletypeid = navpoint_enttype; +} + +NavPoint::~NavPoint() +{ +} + +} diff --git a/src/game/base/navpoint.h b/src/game/base/navpoint.h new file mode 100644 index 0000000..7ea505d --- /dev/null +++ b/src/game/base/navpoint.h @@ -0,0 +1,27 @@ +/* +   base/navpoint.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_NAVPOINT_H__ +#define __INCLUDED_BASE_NAVPOINT_H__ + +#include "core/entity.h" +#include "math/mathlib.h" + +#include <string> + +namespace base { + +/// a navigation point +class NavPoint : public core::Entity { +public: +	NavPoint(); +	~NavPoint(); +}; + +} + +#endif // __INCLUDED_BASE_NAVPOINT_H__ + diff --git a/src/game/base/planet.cc b/src/game/base/planet.cc new file mode 100644 index 0000000..83f3d65 --- /dev/null +++ b/src/game/base/planet.cc @@ -0,0 +1,27 @@ +/* +   base/planet.cc +   This file is part of the Osirion project and is distributed under +   the terms of the GNU General Public License version 2. +*/ + +#include "base/base.h" +#include "base/planet.h" + + +namespace base { + +Planet::Planet() : core::EntityGlobe(core::Entity::Static | core::Entity::Solid) +{ +	entity_color = math::Color(1,1,1,1);	// white +	entity_radius = 64;			// 64 game units + +	entity_moduletypeid = planet_enttype; + +	entity_rotationspeed = 1.0f; +} + +Planet::~Planet() +{ +} + +} // namespace game diff --git a/src/game/base/planet.h b/src/game/base/planet.h new file mode 100644 index 0000000..005157d --- /dev/null +++ b/src/game/base/planet.h @@ -0,0 +1,27 @@ +/* +   base/planet.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_PLANET_H__ +#define __INCLUDED_BASE_PLANET_H__ + +#include "core/entity.h" +#include "math/mathlib.h" + +#include <string> + +namespace base { + +/// a planet +class Planet : public core::EntityGlobe { +public: +	Planet(); +	~Planet(); +}; + +} + +#endif // __INCLUDED_BASE_PLANET_H__ + diff --git a/src/game/base/racetrack.cc b/src/game/base/racetrack.cc new file mode 100644 index 0000000..ee2ecc7 --- /dev/null +++ b/src/game/base/racetrack.cc @@ -0,0 +1,195 @@ +/* +   base/racetrack.cc +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#include <string> +#include <sstream> + +#include "base/racetrack.h" +#include "core/gameserver.h" + +namespace base { + +/* ---- class CheckPoint ------------------------------------------- */ + +CheckPoint::CheckPoint(RaceTrack *parent) +{ +	entity_eventstate = core::Entity::NoPower; +	parent_track = parent; +	if (parent) { +		entity_color = parent->color(); +		entity_color_second = parent->color_second(); +		set_zone(parent->zone()); +		parent->add_checkpoint(this); +	} else { +		die(); +	} +} + +CheckPoint::~CheckPoint() +{ +	 +} + +/* ---- class RaceTrack -------------------------------------------- */ + +RaceTrack::RaceTrack() +{ +	track_player = 0; +	track_racestart = 0; +	track_checkpointtime = 0; + +	entity_eventstate = core::Entity::NoPower; +} + +RaceTrack::~RaceTrack() +{ +	track_checkpoints.clear(); +} + +void RaceTrack::add_checkpoint(CheckPoint *checkpoint) +{ +	track_checkpoints.push_back(checkpoint); +} + +void RaceTrack::reset() +{ +	if (track_player) { +		track_player->set_mission_target(0); +	} +	track_player = 0; +	track_racestart = 0; +	track_checkpointtime = 0; +	 +	for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { +		(*cpit)->set_eventstate(core::Entity::NoPower); +	} + +	set_eventstate(core::Entity::NoPower); +} + +void RaceTrack::frame(float seconds) +{ +	if (!track_checkpoints.size()) +		return; + +	if (!track_player) { + +		// FIXME this should go through proper collision detection +		for (core::GameServer::Players::iterator it = core::server()->players().begin(); it != core::server()->players().end(); ++it) { +			if ((*it)->control() && (*it)->control()->zone() == zone()) { +				if (math::distance((*it)->control()->location(), location()) <= 1) { +					track_player = (*it); + +					track_racestart = core::server()->time(); +					set_eventstate(core::Entity::Normal); + +					for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { +						set_eventstate(core::Entity::Normal); +					} +					 +					entity_timer = 5.0f; +					std::string message("^B"); +					message.append(track_player->name()); +					message.append(" ^Bactivated the race! Race starts in 5..."); +					core::server()->broadcast(message); +					track_player->set_mission_target(this); +					return; +				} +			} +		} + +		return; +	} + +	// FIXME this should go into a proper general function +	// validate current player +	core::Player *player = 0; +	for (core::GameServer::Players::iterator pit = core::server()->players().begin(); (!player) && (pit != core::server()->players().end()); ++pit) { +		if ((*pit) == track_player) { +			player = (*pit); +		} +	} + +	if (!player) { +		reset(); +		return; +	} + +	if (!player->control() || (player->control()->zone() != zone())) { +		reset(); +		return; +	} + +	if (entity_timer) { + +		if (math::distance(player->control()->location(), location()) > 1) { +			std::string message("^BNo cheating!"); +			core::server()->broadcast(message); +			reset(); +			return; +		} + +		if (track_racestart + 1.0f <= core::server()->time()) { +			entity_timer -= 1.0f; +			entity_dirty = true; + +			if (entity_timer > 0) { +				std::stringstream msgstr; +				msgstr << "^B" << entity_timer << "..."; +				core::server()->broadcast(msgstr.str()); +				track_racestart = core::server()->time(); +			} else { +				for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { +					(*cpit)->set_eventstate(core::Entity::NoPower); +				} +				std::string message("^BGo!"); +				core::server()->broadcast(message); + +				track_racestart = core::server()->time(); +				track_checkpointtime = core::server()->time() + 15.0f; +				track_checkpoint = track_checkpoints.begin(); +				(*track_checkpoint)->set_eventstate(core::Entity::Normal); +				track_player->set_mission_target((*track_checkpoint)); +			} +		} +		 + +	} else { + +		if (core::server()->time() > track_checkpointtime) { +			std::string message("^BToo slow, race lost!"); +			core::server()->broadcast(message); + +			reset(); +			return; +		} + +		if (math::distance(track_player->control()->location(), (*track_checkpoint)->location()) <= 1) { +			CheckPoints::iterator next_checkpoint = track_checkpoint; +			next_checkpoint++; + +			if (next_checkpoint != track_checkpoints.end()) { + +				std::string message("^BCheckpoint!"); +				core::server()->broadcast(message); +				track_checkpointtime = core::server()->time() + 15.0f; +				(*track_checkpoint)->set_eventstate(core::Entity::NoPower); +				track_checkpoint++; +				(*track_checkpoint)->set_eventstate(core::Entity::Normal); +				track_player->set_mission_target((*track_checkpoint)); + +			} else { + +				std::stringstream msgstr; +				msgstr << "^BRace completed in " << core::server()->time() - track_racestart << " seconds!"; +				core::server()->broadcast(msgstr.str()); +				reset(); +			} +		} +	} +} + +} diff --git a/src/game/base/racetrack.h b/src/game/base/racetrack.h new file mode 100644 index 0000000..b5b5dad --- /dev/null +++ b/src/game/base/racetrack.h @@ -0,0 +1,63 @@ +/* +   base/racetrack.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_RACETRACK_H__ +#define __INCLUDED_BASE_RACETRACK_H__ + +#include "core/entity.h" +#include "core/player.h" +#include "math/mathlib.h" + +#include <string> + +namespace base { + +class CheckPoint; + +/* ---- class RaceTrack -------------------------------------------- */ + +class RaceTrack : public core::EntityDynamic { + +public: +	typedef std::list<CheckPoint *>  CheckPoints ; + +	RaceTrack(); +	~RaceTrack(); + +	void add_checkpoint(CheckPoint *checkpoint); + +	/// reset the race track +	void reset(); + +	virtual void frame(float seconds); + +	inline core::Player *player() { return track_player; } + +private: +	CheckPoints 		track_checkpoints; +	core::Player		*track_player; +	float			track_racestart; +	float			track_checkpointtime; +	CheckPoints::iterator	track_checkpoint; +	 +}; + +/* ---- class CheckPoint ------------------------------------------- */ + +class CheckPoint : public core::EntityDynamic  { +public: +	CheckPoint(RaceTrack *parent); +	~CheckPoint(); + +private: +	RaceTrack		*parent_track; +}; + + +} + +#endif // __INCLUDED_BASE_NAVPOINT_H__ + diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc new file mode 100644 index 0000000..0fdfd3f --- /dev/null +++ b/src/game/base/ship.cc @@ -0,0 +1,464 @@ +/* +   base/ship.cc +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#include <cmath> +#include <iostream> + +#include "auxiliary/functions.h" +#include "core/gameserver.h" +#include "core/entity.h" +#include "base/base.h" +#include "base/ship.h" +#include "math/functions.h" + + + +using math::degrees360f; +using math::degrees180f; + +namespace base { + +const float 		MIN_DELTA = 0.000001f; + +Ship::Ship(core::Player *owner, ShipModel *shipmodel) : +	core::EntityControlable(owner, ship_enttype) +{ +	entity_modelname = "ships/" + shipmodel->modelname(); +	entity_name = shipmodel->name() + ": <^B" + owner->name() + "^N>"; +	entity_label = shipmodel->label(); + +	entity_moduletypeid = ship_enttype; + +	entity_color = owner->color(); +	entity_color_second = owner->color_second(); + +	ship_shipmodel = shipmodel; +	ship_jumpdrive = shipmodel->shipmodel_jumpdrive; +	 +	ship_impulsedrive_timer = 0; +	ship_jumpdrive_timer = 0; + +	reset(); +} + +Ship::~Ship()  +{ + +} + +void Ship::reset() +{ +	current_target_direction = 0.0f; +	current_target_pitch = 0.0f;; +	current_target_roll = 0.0f; +	current_target_strafe = 0.0f; +	current_target_afterburner = 0.0f; +} +void Ship::impulse() +{ +	if (entity_eventstate == core::Entity::Jump) { +		return; + +	} else if ((entity_eventstate == core::Entity::Impulse) || (entity_eventstate == core::Entity::ImpulseInitiate)) { +		entity_eventstate = core::Entity::Normal; +		 +	} else {  + +		if (entity_eventstate == core::Entity::JumpInitiate) { +			ship_jumpdrive_timer = 0; +			entity_timer = 0; +		} +	 +		entity_eventstate = core::Entity::ImpulseInitiate; +		if (Base::instance()->g_devel->value()) { +			entity_timer = 0; +		} else { +			entity_timer = 3; +		} +		ship_impulsedrive_timer = core::server()->time(); +		entity_dirty = true; +	} + +	entity_dirty = true; +} + +void Ship::jump(std::string const &args) +{ +	// devel mode provides instant jump access to arbitrary systems +	if (Base::instance()->g_devel->value() && (args.size())) { + +		core::Zone *jumptargetzone = 0; +		std::string target; +		std::istringstream is(args); +		if (!(is >> target)) { +			std::string helpstr; +			for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { +				core::Zone *zone = (*it).second; +				if (helpstr.size()) +					helpstr.append("^N|^B"); +				helpstr.append(zone->label()); +			} +	 +			core::server()->send(owner(), "Usage: jump [^B" + helpstr + "^N]"); +			return; +		} +	 +		aux::to_lowercase(target); +		jumptargetzone = core::Zone::find_zone(target); +		if (!jumptargetzone) { +			core::server()->send(owner(), "Unknown system '" + target + '\''); +			return; +		} +	 +		if (jumptargetzone == zone()) { +			core::server()->send(owner(), "Already in the " + jumptargetzone->name() + '.'); +			return; +		} +		 +		core::server()->send(owner(), "Jumping to the " + jumptargetzone->name()); +		set_zone(jumptargetzone); +		if (owner()->control() == (EntityControlable*) this) +			owner()->set_zone(jumptargetzone); + +		ship_jumpdrive_timer = 0; +		entity_timer = 0; +		entity_eventstate = core::Entity::Jump; +		entity_dirty = true; +		return; + +	} else { +		if (!jumpdrive() && !Base::instance()->g_devel->value()) { +			core::server()->send(owner(), "This ship is not equiped with a hyperspace drive!"); +			return; + +		} else 	if (entity_eventstate == core::Entity::Jump) { +			return; + +		} else if (entity_eventstate == core::Entity::JumpInitiate) { +			core::server()->send(owner(), "Jump aborted, hyperspace drive deactivated."); +			ship_jumpdrive_timer = 0; +			entity_timer = 0; +			entity_eventstate = core::Entity::Normal; +			return; +		} +	 +		if (!find_closest_jumppoint()) { +			return; +		} + +		entity_eventstate = core::Entity::JumpInitiate; +		if (Base::instance()->g_devel->value()) { +			entity_timer = 0; +		} else { +			entity_timer = 8; +		} + +		ship_jumpdrive_timer = core::server()->time(); +		entity_dirty = true; +	} +} + +JumpPoint * Ship::find_closest_jumppoint() +{ +	// find closest jumppoint +	float d = -1; +	JumpPoint *jumppoint = 0; +	for (core::Zone::Content::iterator it = zone()->content().begin(); it != zone()->content().end(); it++) { +		core::Entity *entity = (*it); +		if (entity->moduletype() == jumppoint_enttype) { +			JumpPoint *te = static_cast<JumpPoint *>(entity); +			float d1 = math::distance(location(), te->location()); +			if ((d < 0) || (d1 < d)) { +				d = d1; +				jumppoint = te; +			} +		} +	} +	 +	if (jumppoint && jumppoint->target()) { +		if (Base::instance()->g_jumppointrange->value() < d) { +			core::server()->send(owner(), "Jumppoint out of range!"); +			return 0; +		} else { +			core::server()->send(owner(), "Jumping to the " + jumppoint->target()->zone()->name()); +			return jumppoint; +		} +	} else { +		core::server()->send(owner(), "No jumppoints found!"); +		return 0; +	} +	 +	return 0; +} + +void Ship::frame(float seconds)  +{ +	const float direction_change_speed = 2; +	float cosangle;		// cosine of an angle +	float angle;		// angle in radians	 +	math::Vector3f n;	// normal of a plane + +	float actual_maxspeed = ship_shipmodel->maxspeed(); +	float actual_turnspeed = ship_shipmodel->turnspeed(); +	float actual_acceleration = ship_shipmodel->acceleration(); + +	entity_movement = 0; + +	// speed might get set to 0 on this update +	if (entity_speed != 0.0f) +		entity_dirty = true; + +	// jumpdrive +	// target axis +	math::Axis target_axis(entity_axis); + +	if (entity_eventstate == core::Entity::JumpInitiate) { + +		if (ship_jumpdrive_timer + 1.0f <= core::server()->time()) { +			entity_timer -= 1.0f; + +			if (entity_timer <= 0) { +				JumpPoint *jumppoint = find_closest_jumppoint(); + +				if (jumppoint) { +					set_zone(jumppoint->target()->zone()); +					if (owner()->control() == (EntityControlable*) this) +						owner()->set_zone(jumppoint->target()->zone()); +					entity_eventstate = core::Entity::Jump; +					entity_location.assign(jumppoint->target()->location() + location() - jumppoint->location()); +				} else { +					entity_eventstate = core::Entity::Normal; +				} +				ship_jumpdrive_timer = 0; +				entity_timer = 0; +				 +				entity_dirty = true; +				return; +			} else { +				ship_jumpdrive_timer = core::server()->time(); +				entity_dirty = true; +			} +		} + +		// control is disabled while the jumpdrive is activated +		target_thrust = 0; +		target_pitch = 0; +		target_roll = 0; +		target_direction = 0; +		target_afterburner = 0.0f; +		target_thrust = 0; + +	} else if (entity_eventstate == core::Entity::Jump) { +		// control is disabled while the jumpdrive is activated +		target_thrust = 0; +		target_pitch = 0; +		target_roll = 0; +		target_direction = 0; +		target_afterburner = 0.0f; +		target_thrust = 0; + +		// FIXME jump location and axis		 +		math::Axis default_axis; +		entity_axis.assign(default_axis); +		entity_dirty = true; + +		// FIXME 5 second cooldown +		entity_eventstate =  core::Entity::Normal; + +	} else if (entity_eventstate == core::Entity::ImpulseInitiate) { + +		if (ship_impulsedrive_timer + 1.0f <= core::server()->time()) { +			entity_timer -= 1.0f; + +			if (entity_timer <= 0) { +				actual_maxspeed = Base::instance()->g_impulsespeed->value(); +				actual_acceleration = Base::instance()->g_impulseacceleration->value(); +				entity_eventstate = core::Entity::Impulse; +				entity_timer = 0; +				entity_dirty = true; +			} else { +				ship_impulsedrive_timer = core::server()->time(); +				entity_dirty = true; +			} +		} + +		// clamp input values +		target_thrust = 0.0f; +		math::clamp(target_pitch, -1.0f, 1.0f); +		math::clamp(target_roll, -1.0f, 1.0f); +		math::clamp(target_direction, -1.0f, 1.0f); +		math::clamp(target_afterburner, -1.0f, 1.0f); +		actual_turnspeed *= 0.5; + +	} else if (entity_eventstate == core::Entity::Impulse) { + +		// clamp input values +		target_thrust = 0.0f; +		math::clamp(target_pitch, -1.0f, 1.0f); +		math::clamp(target_roll, -1.0f, 1.0f); +		math::clamp(target_direction, -1.0f, 1.0f); +		target_afterburner = 0.0f; +		actual_maxspeed = Base::instance()->g_impulsespeed->value(); +		actual_acceleration = Base::instance()->g_impulseacceleration->value(); +		actual_turnspeed *= 0.5; + +	} else if (entity_eventstate == core::Entity::Normal) { + +		// clamp input values +		math::clamp(target_thrust, 0.0f, 1.0f); +		math::clamp(target_pitch, -1.0f, 1.0f); +		math::clamp(target_roll, -1.0f, 1.0f); +		math::clamp(target_direction, -1.0f, 1.0f); +		math::clamp(target_afterburner, -1.0f, 1.0f); + +		if (speed() > actual_maxspeed * 1.15f) { +			actual_acceleration = Base::instance()->g_impulseacceleration->value(); +			actual_turnspeed *= 0.5; +		} + +	} + +	// update roll +	if (current_target_roll < target_roll) { +		current_target_roll += direction_change_speed * seconds; +		if (current_target_roll > target_roll) +			current_target_roll = target_roll; +	} else if (current_target_roll > target_roll) { +		current_target_roll -= direction_change_speed * seconds; +		if (current_target_roll < target_roll) +			current_target_roll = target_roll; +	} +	math::clamp(current_target_roll, -1.0f, 1.0f); + +	if (fabs(current_target_roll) > MIN_DELTA) {	 +		float roll_offset = seconds * current_target_roll; +		entity_axis.change_roll(actual_turnspeed * roll_offset); +	} else { +		current_target_roll = 0.0f; +	} + +	// update target_axis direction	 +	if (current_target_direction < target_direction) { +		current_target_direction += direction_change_speed * seconds; +		if (current_target_direction > target_direction) { +			current_target_direction = target_direction; +		} +	} else if (current_target_direction > target_direction) { +		current_target_direction -= direction_change_speed * seconds; +		if (current_target_direction < target_direction) { +			current_target_direction = target_direction; +		} +	} + +	if (fabs(current_target_direction) > MIN_DELTA ) { +		math::clamp(current_target_direction, -1.0f, 1.0f); +		target_axis.change_direction(actual_turnspeed * current_target_direction); +	} else { +		current_target_direction = 0.0f; +	} + +	if (current_target_pitch < target_pitch) { +		current_target_pitch += direction_change_speed * seconds; +		if (current_target_pitch > target_pitch) +			current_target_pitch = target_pitch; +	} else if (current_target_pitch > target_pitch) { +		current_target_pitch -= direction_change_speed * seconds; +		if (current_target_pitch < target_pitch) +			current_target_pitch = target_pitch; +	} +	 +	if (fabs(current_target_pitch) > MIN_DELTA) { +		math::clamp(current_target_pitch, -1.0f, 1.0f); +		target_axis.change_pitch(actual_turnspeed * current_target_pitch); +	} else { +		current_target_pitch = 0.0f; +	} + +	n.assign(math::crossproduct(entity_axis.forward(), target_axis.forward())); +	if (!(n.length() < MIN_DELTA)) { +		n.normalize(); +		cosangle = math::dotproduct(entity_axis.forward(), target_axis.forward()); +		angle = acos(cosangle) * seconds; // * 180.0f / M_PI; +		if (angle > MIN_DELTA) +			entity_axis.rotate(n, -angle); +	} + +	// update afterburner +	if (current_target_afterburner < target_afterburner) { +		current_target_afterburner += 2.0f * seconds; +		if (current_target_afterburner > target_afterburner) +			current_target_afterburner = target_afterburner; +	} else if (current_target_afterburner > target_afterburner) { +		current_target_afterburner -= 2.0f * seconds; +		if (current_target_afterburner < target_afterburner) +			current_target_afterburner = target_afterburner; +	} + +	// update thrust +	if (current_target_afterburner < 0.0f) { +		target_thrust = 0; +	} + +	if (entity_thrust < target_thrust) { +		entity_thrust += seconds  * 0.5f; +		if (entity_thrust > target_thrust) +			entity_thrust = target_thrust; +	} else if (entity_thrust > target_thrust) { +		entity_thrust -= seconds * 0.5f; +		if (entity_thrust < target_thrust) +			entity_thrust = target_thrust; +	} +	math::clamp(entity_thrust, 0.0f, 1.0f); +	float actual_thrust = entity_thrust + current_target_afterburner * 0.15f; + +	if ((entity_eventstate == core::Entity::ImpulseInitiate) || (entity_eventstate == core::Entity::Impulse)) { +		actual_thrust = 1.0f; +	} + +	// update speed +	if (entity_speed < actual_thrust * actual_maxspeed) { +		entity_speed += actual_acceleration * seconds; +		if (entity_speed > actual_thrust * actual_maxspeed) { +			entity_speed = actual_thrust * actual_maxspeed; +		} +	} else if(entity_speed > actual_thrust * actual_maxspeed) { +		entity_speed -= actual_acceleration * seconds; +		if (entity_speed < actual_thrust * actual_maxspeed) { +			entity_speed = actual_thrust * actual_maxspeed; +		} +	} + +	// update strafe +	if (current_target_strafe < target_strafe) { +		current_target_strafe += 2.0f * seconds; +		if (current_target_strafe > target_strafe) +			current_target_strafe = target_strafe; +	} else if (current_target_strafe > target_strafe) { +		current_target_strafe -= 2.0f * seconds; +		if (current_target_strafe < target_strafe) +			current_target_strafe = target_strafe; +	} + +	if (fabs(current_target_strafe) > MIN_DELTA) { +		entity_location += entity_axis.left() * (current_target_strafe * Base::instance()->g_strafespeed->value()); +	} + +	entity_movement = target_thrust; +	entity_movement = math::max(entity_movement, fabs(current_target_pitch)); +	entity_movement = math::max(entity_movement, fabs(current_target_direction)); +	entity_movement = math::max(entity_movement, fabs(current_target_roll)); +	entity_movement = math::max(entity_movement, fabs(current_target_afterburner)); +	entity_movement = math::max(entity_movement, fabs(current_target_strafe)); + +	if (entity_speed) { +		entity_location += entity_axis.forward() * entity_speed * seconds; +		entity_dirty = true; +	} else if (entity_movement > 0.0f) { +		entity_dirty = true; +	} +} + +} // namespace game diff --git a/src/game/base/ship.h b/src/game/base/ship.h new file mode 100644 index 0000000..d3c8bbf --- /dev/null +++ b/src/game/base/ship.h @@ -0,0 +1,60 @@ +/* +   base/ship.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_SHIP_H__ +#define __INCLUDED_BASE_SHIP_H__ + +#include "core/player.h" +#include "core/entity.h" +#include "base/shipmodel.h" +#include "base/jumppoint.h" +#include "math/vector3f.h" + +namespace base { + +/// A ship in the game, controled by a player +class Ship : public core::EntityControlable +{ +public: +	Ship(core::Player *owner, ShipModel *shipmodel); +	~Ship(); + +	/// update the ship state +	virtual void frame(float seconds); + +	/// true if the ship is equiped with a jumpdrive +	inline bool jumpdrive() const { return ship_jumpdrive; } + +	/// toggle jump drive activation +	void jump(std::string const & args); + +	/// toggle impulse drive activation +	void impulse(); + +	/// void reset drive controls +	void reset(); + +private: +	ShipModel		*ship_shipmodel; + +	float 			current_target_direction; +	float 			current_target_pitch; +	float 			current_target_roll; +	float			current_target_strafe; +	float			current_target_afterburner; + +	bool			ship_jumpdrive; +	float			ship_jumpdrive_timer; + +	float			ship_impulsedrive_timer; + +	JumpPoint * 		find_closest_jumppoint(); +}; + +} + +#endif // __INCLUDED_BASE_SHIP_H__ + diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc new file mode 100644 index 0000000..6018414 --- /dev/null +++ b/src/game/base/shipmodel.cc @@ -0,0 +1,72 @@ +/* +   base/shipmodel.cc +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#include "sys/sys.h" +#include "base/shipmodel.h" + +namespace base { + +// the ship model registry +std::map<std::string, ShipModel *>	ShipModel::registry; + +ShipModel::ShipModel() +{ +	//default specifications +	shipmodel_acceleration = 1.0f;	// thruster acceleration in game untits/second^2 +	shipmodel_maxspeed = 3.0f;	// maximum thruster speed in game units/second +	shipmodel_turnspeed = 45.0f;	// 45 degrees per second + +	shipmodel_jumpdrive = false; +} + +ShipModel::~ShipModel() +{} + + +// clear the ship model registry +void ShipModel::clear() +{ +	for (iterator smit = registry.begin(); smit != registry.end(); smit++) { +		delete (*smit).second; +	} +	registry.clear(); +} + +void ShipModel::list() +{ +	for (iterator smit = registry.begin(); smit != registry.end(); smit++) { +		con_print <<  +			"  " << (*smit).second->label() <<  +			" " << (*smit).second->name() <<  +			" accel " << (*smit).second->acceleration() <<  +			" max " << (*smit).second->maxspeed() << +			" turn " << (*smit).second->turnspeed() << "\n"; +	} +	con_print << registry.size() << " registered ship models\n"; +} + +ShipModel *ShipModel::find(const std::string label) +{ +	std::map<std::string, ShipModel *>::iterator it = registry.find(label); +	if (it == registry.end()) +		return 0; +	else +		return (*it).second; +} + +// add a new ship model +void ShipModel::add(ShipModel *shipmodel) +{ +	ShipModel *m = find(shipmodel->label()); +	if (m) { +		con_warn << "Duplicate ship model " << shipmodel->label() << "!\n"; +		delete m; +	} +	 +	registry[shipmodel->label()] = shipmodel; +} + +} diff --git a/src/game/base/shipmodel.h b/src/game/base/shipmodel.h new file mode 100644 index 0000000..d92b840 --- /dev/null +++ b/src/game/base/shipmodel.h @@ -0,0 +1,70 @@ +/* +   base/shipmodel.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_SHIPMODEL_H__ +#define __INCLUDED_BASE_SHIPMODEL_H__ + +#include <map> +#include <string> + +namespace base { + +/// ship model specifications +class ShipModel +{ +public: +	ShipModel(); +	~ShipModel(); + +	/// acceleration +	inline float acceleration() const { return shipmodel_acceleration; } + +	/// maximum speed +	inline float maxspeed() const { return shipmodel_maxspeed; } +	 +	/// turn speed in rotations per second +	inline float turnspeed() const { return shipmodel_turnspeed; } + +	/// label of the ship model +	inline std::string const &label() const { return shipmodel_label; } + +	/// name of the ship model +	inline std::string const & name() const { return shipmodel_name; } + +	/// name of the model of the ship +	inline std::string const & modelname() const { return shipmodel_modelname; } + +	float 			shipmodel_acceleration; +	float 			shipmodel_maxspeed; +	float 			shipmodel_turnspeed; +	std::string 		shipmodel_label; +	std::string 		shipmodel_name; +	std::string 		shipmodel_modelname; + +	/// indicates of this model can be equiped with a jump drive +	bool			shipmodel_jumpdrive; + +	static ShipModel *find(const std::string label); + +	/// the ship model registry +	static std::map<std::string, ShipModel *>	registry; + +	typedef std::map<std::string, ShipModel *>::iterator iterator; + +	/// clear the ship model registry +	static void clear(); + +	/// list the ship model registry +	static void list(); + +	/// add a new ship model +	static void add(ShipModel *shipmodel); +}; + +} + +#endif // __INCLUDED_BASE_SHIPMODEL_H__ + diff --git a/src/game/base/star.cc b/src/game/base/star.cc new file mode 100644 index 0000000..cacd542 --- /dev/null +++ b/src/game/base/star.cc @@ -0,0 +1,25 @@ +/* +   base/star.cc +   This file is part of the Osirion project and is distributed under +   the terms of the GNU General Public License version 2. +*/ + +#include "base/base.h" +#include "base/star.h" + + +namespace base { + +Star::Star() : core::EntityGlobe(core::Entity::Static | core::Entity::Solid | core::Entity::Bright) +{ +	entity_color = math::Color(1,1,1,1);	// white +	entity_radius = 96;			// 96 game units + +	entity_moduletypeid = star_enttype; +} + +Star::~Star() +{ +} + +} // namespace game diff --git a/src/game/base/star.h b/src/game/base/star.h new file mode 100644 index 0000000..5a78fc8 --- /dev/null +++ b/src/game/base/star.h @@ -0,0 +1,29 @@ +/* +   base/star.h +   This file is part of the Osirion project and is distributed under  +   the terms and conditions of the GNU General Public License version 2  +*/ + +#ifndef __INCLUDED_BASE_STAR_H__ +#define __INCLUDED_BASE_STAR_H__ + +// project headers +#include "core/entity.h" +#include "math/mathlib.h" + +// C++ headers +#include <string> + +namespace base { + +/// a star, that shines so bright +class Star : public core::EntityGlobe { +public: +	Star(); +	~Star(); +}; + +} + +#endif // __INCLUDED_BASE_STAR_H__ + | 
