Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2009-04-15 17:08:51 +0000
committerStijn Buys <ingar@osirion.org>2009-04-15 17:08:51 +0000
commita95028547981614e06ea7a6d22b853b85418cea3 (patch)
treed4d6998a4118a4d8690ce138d586abfba4893179 /src
parent4f33f59571f10019c1e7a0e3640b2f69c159a8cf (diff)
added info registry, list_info
added network info transfer added info based buy menu and related game changes
Diffstat (limited to 'src')
-rw-r--r--src/client/Makefile.am8
-rw-r--r--src/client/buymenu.cc132
-rw-r--r--src/client/buymenu.h58
-rw-r--r--src/client/client.cc21
-rw-r--r--src/client/client.h4
-rw-r--r--src/client/entitymenu.cc75
-rw-r--r--src/client/entitymenu.h2
-rw-r--r--src/client/input.cc7
-rw-r--r--src/client/playerview.cc79
-rw-r--r--src/client/playerview.h10
-rw-r--r--src/client/targets.cc5
-rw-r--r--src/client/trademenu.cc32
-rw-r--r--src/client/trademenu.h29
-rw-r--r--src/core/Makefile.am3
-rw-r--r--src/core/commandbuffer.cc33
-rw-r--r--src/core/descriptions.cc27
-rw-r--r--src/core/descriptions.h9
-rw-r--r--src/core/gameconnection.cc22
-rw-r--r--src/core/gameconnection.h3
-rw-r--r--src/core/gameinterface.cc4
-rw-r--r--src/core/gameinterface.h8
-rw-r--r--src/core/gameserver.cc5
-rw-r--r--src/core/gameserver.h3
-rw-r--r--src/core/info.cc183
-rw-r--r--src/core/info.h108
-rw-r--r--src/core/net.h2
-rw-r--r--src/core/netconnection.cc33
-rw-r--r--src/core/netconnection.h4
-rw-r--r--src/core/netserver.cc30
-rw-r--r--src/core/netserver.h4
-rw-r--r--src/game/base/collision.cc25
-rw-r--r--src/game/base/game.cc44
-rw-r--r--src/game/base/game.h1
-rw-r--r--src/game/base/shipmodel.cc35
-rw-r--r--src/game/base/shipmodel.h8
-rwxr-xr-xsrc/ui/modelview.cc5
36 files changed, 991 insertions, 70 deletions
diff --git a/src/client/Makefile.am b/src/client/Makefile.am
index 557adc1..2786d80 100644
--- a/src/client/Makefile.am
+++ b/src/client/Makefile.am
@@ -7,9 +7,9 @@ else
noinst_LTLIBRARIES = libclient.la
endif
-libclient_la_SOURCES = action.cc chat.cc client.cc clientext.cc entitymenu.cc \
- hud.cc infowidget.cc input.cc joystick.cc key.cc keyboard.cc map.cc \
- notifications.cc playerview.cc soundext.cc targets.cc video.cc worldview.cc
+libclient_la_SOURCES = action.cc buymenu.cc chat.cc client.cc clientext.cc \
+ entitymenu.cc hud.cc infowidget.cc input.cc joystick.cc key.cc keyboard.cc map.cc \
+ notifications.cc playerview.cc soundext.cc targets.cc trademenu.cc video.cc worldview.cc
libclient_la_CFLAGS = $(LIBSDL_CFLAGS) $(GL_CFLAGS)
libclient_la_LDFLAGS = -avoid-version -no-undefined $(GL_LIBS) $(LIBSDL_LIBS)
@@ -19,3 +19,5 @@ noinst_HEADERS = action.h chat.h client.h clientext.h hud.h entitymenu.h \
libclient_la_LIBADD = $(top_builddir)/src/core/libcore.la $(top_builddir)/src/audio/libaudio.la \
$(top_builddir)/src/render/librender.la $(top_builddir)/src/ui/libui.la
+_SOURCES = trademenu.h
+_SOURCES = buymenu.h
diff --git a/src/client/buymenu.cc b/src/client/buymenu.cc
new file mode 100644
index 0000000..b0a0b48
--- /dev/null
+++ b/src/client/buymenu.cc
@@ -0,0 +1,132 @@
+/*
+ client/buymenu.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "ui/ui.h"
+#include "ui/button.h"
+#include "ui/paint.h"
+#include "client/buymenu.h"
+#include "core/info.h"
+#include "core/application.h"
+namespace client
+{
+
+BuyMenu::BuyMenu(ui::Widget *parent, const char * label) : ui::Window(parent)
+{
+ set_border(false);
+ set_background(true);
+
+ if (label)
+ set_label(label);
+ else
+ set_label("buymenu");
+
+ // model pane (left)
+ menu_modelpane = new ui::Window(this);
+ menu_modelpane->set_label("modelpane");
+ menu_modelpane->set_background(true);
+ menu_modelpane->set_border(true);
+
+ menu_closebutton = new ui::Button(menu_modelpane, "Close","view hide");
+
+ // text pane (right)
+ menu_textpane = new ui::Window(this);
+ menu_textpane->set_label("textpane");
+ menu_textpane->set_background(true);
+ menu_textpane->set_border(true);
+
+ menu_namelabel = new ui::Label(menu_textpane);
+ menu_namelabel->set_label("infolabel");
+ menu_namelabel->set_background(false);
+ menu_namelabel->set_border(false);
+ menu_namelabel->set_font(ui::root()->font_large());
+ menu_namelabel->set_alignment(ui::AlignCenter);
+ menu_buybutton = new ui::Button(menu_textpane, "Buy");
+ menu_scrollpane = new ui::ScrollPane(menu_textpane, menu_infotext);
+ menu_scrollpane->set_background(false);
+ menu_scrollpane->set_border(false);
+ menu_scrollpane->set_alignment(ui::AlignTop);
+
+ menu_infotimestamp = 0;
+ menu_inforecord = 0;
+
+ hide();
+}
+
+BuyMenu::~BuyMenu()
+{
+
+}
+
+void BuyMenu::set_item(std::string const & itemtype, std::string const & itemname)
+{
+ menu_itemtype.assign(itemtype);
+ aux::to_label(menu_itemtype);
+
+ menu_itemname.assign(itemname);
+ aux::to_label(menu_itemname);
+
+ menu_buybutton->set_command("remote buy " + itemtype + ' ' + itemname + "; view hide");
+ menu_buybutton->set_label("buy " + itemname);
+
+ menu_infotext.clear();
+ menu_namelabel->set_text(0);
+
+ core::Info *info = core::game()->info(itemtype+'/'+itemname);
+ if (info) {
+ menu_namelabel->set_text(info->name());
+ for (core::Info::Text::iterator it = info->text().begin(); it != info->text().end(); it++) {
+ menu_infotext.push_back((*it));
+ }
+ menu_infotimestamp = info->timestamp();
+ } else {
+ menu_infotext.push_back("Information is not available");
+ menu_infotimestamp = 0;
+ }
+
+ menu_inforecord = info;
+}
+
+void BuyMenu::resize()
+{
+ const float smallmargin = ui::UI::elementsize.height();
+
+ set_size(parent()->size());
+
+ // reposition model pane (left)
+ menu_modelpane->set_size(ui::UI::elementsize.width() * 1.5f, height() - smallmargin * 4.0f);
+ menu_modelpane->set_location(smallmargin, smallmargin * 2.0f);
+
+ menu_closebutton->set_size(ui::UI::elementsize);
+ menu_closebutton->set_location((menu_modelpane->width() - menu_closebutton->width()) * 0.5f,
+ menu_modelpane->height() - menu_closebutton->height() - ui::UI::elementsize.height() * 0.5f);
+
+ // reposition text pane (right)
+ menu_textpane->set_size(width() - smallmargin * 3.0f - menu_modelpane->width(), height() - smallmargin * 4.0f);
+ menu_textpane->set_location(smallmargin * 2.0f + menu_modelpane->width(), smallmargin * 2.0f);
+
+ menu_buybutton->set_size(ui::UI::elementsize);
+ menu_buybutton->set_location((menu_textpane->width() - menu_buybutton->width()) * 0.5f,
+ menu_textpane->height() - menu_buybutton->height() - ui::UI::elementsize.height() * 0.5f);
+
+ menu_namelabel->set_size(menu_textpane->width(), menu_namelabel->font()->height() * 2.0f);
+ menu_namelabel->set_location(0, 4);
+
+ menu_scrollpane->set_size(menu_textpane->width() - 8, menu_buybutton->top() - menu_namelabel->bottom() - 8 );
+ menu_scrollpane->set_location(4, menu_namelabel->bottom() + 4);
+
+}
+
+void BuyMenu::draw()
+{
+ // update content if necessary
+ if (menu_infotimestamp && (menu_infotimestamp != menu_inforecord->timestamp()))
+ set_item(menu_itemtype, menu_itemname);
+
+ ui::Window::draw();
+}
+
+}
+
diff --git a/src/client/buymenu.h b/src/client/buymenu.h
new file mode 100644
index 0000000..81a87bd
--- /dev/null
+++ b/src/client/buymenu.h
@@ -0,0 +1,58 @@
+/*
+ client/buymenu.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_CLIENT_BUYMENU_H__
+#define __INCLUDED_CLIENT_BUYMENU_H__
+
+#include "core/info.h"
+#include "ui/container.h"
+#include "ui/button.h"
+#include "ui/label.h"
+#include "ui/window.h"
+#include "ui/scrollpane.h"
+
+namespace client
+{
+
+/// The buy menu is used to trade a single item, like a ship or an upgrade
+class BuyMenu : public ui::Window
+{
+public:
+ /// create a new menu
+ BuyMenu(ui::Widget *parent, const char * label = 0);
+ ~BuyMenu();
+
+ void set_item(std::string const & itemtype, std::string const & itemname);
+
+protected:
+ /// resize event
+ virtual void resize();
+
+ /// draw event
+ virtual void draw();
+
+private:
+
+ ui::Window *menu_modelpane;
+ ui::Window *menu_textpane;
+ ui::Label *menu_namelabel;
+ ui::ScrollPane *menu_scrollpane;
+
+ ui::Button *menu_closebutton;
+ ui::Button *menu_buybutton;
+
+ std::string menu_itemtype;
+ std::string menu_itemname;
+
+ core::Info *menu_inforecord;
+ ui::Text menu_infotext;
+ unsigned long menu_infotimestamp;
+};
+
+}
+
+#endif // __INCLUDED_CLIENT_BUYMENU_H__
+
diff --git a/src/client/client.cc b/src/client/client.cc
index dffa1ca..47af682 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -144,6 +144,9 @@ void Client::init(int count, char **arguments)
func = core::Func::add("menu", func_menu);
func->set_info("[command] menu functions");
+ func = core::Func::add("view", func_view);
+ func->set_info("[command] view menu functions");
+
previous_timestamp = 0;
}
@@ -256,6 +259,7 @@ void Client::shutdown()
core::Func::remove("ui_map");
core::Func::remove("ui_menu");
core::Func::remove("menu");
+ core::Func::remove("view");
audio::shutdown();
@@ -495,6 +499,15 @@ void Client::func_ui_menu(std::string const &args)
}
}
+// entity menus
+void Client::func_view(std::string const &args)
+{
+ if (client()->worldview()) {
+ client()->worldview()->playerview()->show_menu(args);
+ }
+}
+
+// global menus
void Client::func_menu(std::string const &args)
{
if (!ui::root()) {
@@ -535,14 +548,6 @@ void Client::func_menu(std::string const &args)
} else if (command.compare("list") == 0) {
ui::root()->list_menus();
- } else if (command.compare("view") == 0) {
- if (client()->worldview()) {
- std::string label;
- if (!(argstr >> label)) {
- label.assign("main");
- }
- client()->worldview()->playerview()->show_menu(label);
- }
} else {
ui::root()->show_menu(command.c_str());
}
diff --git a/src/client/client.h b/src/client/client.h
index 375a9ce..dbb2c44 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -76,13 +76,17 @@ private:
static void func_ui_restart(std::string const &args);
static void func_ui_console(std::string const &args);
static void func_list_menu(std::string const &args);
+
static void func_ui_help();
+
static void func_ui(std::string const &args);
static void func_ui_chat(std::string const &args);
static void func_ui_chatbar(std::string const &args);
static void func_ui_map(std::string const &args);
static void func_ui_menu(std::string const &args);
+
static void func_menu(std::string const &args);
+ static void func_view(std::string const &args);
WorldView *client_worldview;
diff --git a/src/client/entitymenu.cc b/src/client/entitymenu.cc
index f727ff3..f1529e1 100644
--- a/src/client/entitymenu.cc
+++ b/src/client/entitymenu.cc
@@ -16,8 +16,10 @@ EntityMenu::EntityMenu(ui::Widget *parent, const char * label) : ui::Window(pare
{
set_border(false);
set_background(false);
- set_label(label);
- set_label("entitymenu");
+ if (label)
+ set_label(label);
+ else
+ set_label("entitymenu");
menu_container = new ui::Container(this);
hide();
@@ -73,7 +75,74 @@ void EntityMenu::generate(core::Entity *entity, const char *menulabel)
for (core::MenuDescription::Buttons::iterator it = menudescr->buttons().begin(); it != menudescr->buttons().end(); it++) {
core::ButtonDescription *buttondescr = (*it);
- Button *button = new Button(menu_container, buttondescr->text().c_str(), buttondescr->command().c_str());
+
+ // parse the command sequence
+ size_t i = 0;
+ std::string result;
+ std::string current;
+ bool quote = false;
+
+ while (i < buttondescr->command().size()) {
+ const char c = buttondescr->command()[i];
+
+ if (c == '"') {
+ quote = !quote;
+ result += c;
+
+ } else if (c == ';') {
+
+ if (quote) {
+ current += c;
+
+ } else if (current.size()) {
+ if (buttondescr->command_type() == core::ButtonDescription::CommandGame) {
+ if (result.size()) {
+ result += ';';
+ }
+
+ result.append("remote ");
+ result.append(current);
+
+ } else if (buttondescr->command_type() == core::ButtonDescription::CommandMenu) {
+ if (result.size()) {
+ result += ';';
+ }
+
+ result.append("view ");
+ result.append(current);
+ }
+ current.clear();
+ }
+
+ } else {
+ current += c;
+ }
+
+ i++;
+ }
+
+ if (current.size()) {
+ if (buttondescr->command_type() == core::ButtonDescription::CommandGame) {
+ if (result.size()) {
+ result += ';';
+ }
+
+ result.append("remote ");
+ result.append(current);
+
+ } else if (buttondescr->command_type() == core::ButtonDescription::CommandMenu) {
+ if (result.size()) {
+ result += ';';
+ }
+
+ result.append("view ");
+ result.append(current);
+ }
+
+ }
+
+ Button *button = new Button(menu_container, buttondescr->text().c_str(), result.c_str());
+
switch (buttondescr->alignment()) {
case core::ButtonDescription::Center:
button->set_alignment(AlignCenter);
diff --git a/src/client/entitymenu.h b/src/client/entitymenu.h
index ac5a793..adc31a9 100644
--- a/src/client/entitymenu.h
+++ b/src/client/entitymenu.h
@@ -15,7 +15,7 @@
namespace client
{
-/// entity menus
+/// entity menu
class EntityMenu : public ui::Window
{
public:
diff --git a/src/client/input.cc b/src/client/input.cc
index 3ccf15c..943bed1 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -516,6 +516,9 @@ void key_pressed(Key *key)
}
if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) {
+
+ // work-around for the mouse release event FIXME
+ //key->key_pressed = 0;
return;
} else if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) {
@@ -549,12 +552,14 @@ void key_released(Key *key)
if (core::application()->connected() && core::localcontrol()) {
+ // FIXME mouse release selection should be handled inside the hud
if ((key->sym() == 512 + SDL_BUTTON_LEFT) && targets::hover() && (key->waspressed() <= (input_mousedelay->value()/1000.0f) ) ) {
// hovering target selected
targets::select_target(targets::hover());
}
- // the release event still must be processed as usual
+
+ // the release event must still be processed as usual
char c = 0;
c = key->bind(Key::None).c_str()[0];
if (c == '+') {
diff --git a/src/client/playerview.cc b/src/client/playerview.cc
index 54d444d..e4a889a 100644
--- a/src/client/playerview.cc
+++ b/src/client/playerview.cc
@@ -4,6 +4,9 @@
the terms and conditions of the GNU General Public License version 2
*/
+#include <string>
+#include <sstream>
+
#include "audio/audio.h"
#include "client/playerview.h"
#include "ui/ui.h"
@@ -32,10 +35,11 @@ PlayerView::PlayerView(ui::Widget *parent) : ui::Widget(parent)
view_chat = new Chat(this);
view_map = new Map(this);
view_hud = new HUD(this);
- view_menu = new EntityMenu(this);
+ view_entitymenu = new EntityMenu(this);
+ view_buymenu = new BuyMenu(this);
view_hud->lower();
- view_menu->raise();
+ view_entitymenu->raise();
}
PlayerView::~PlayerView()
@@ -49,7 +53,7 @@ void PlayerView::clear()
view_chat->hide();
view_map->hide();
- view_menu->hide();
+ view_entitymenu->hide();
view_lastentity = 0;
}
@@ -67,8 +71,8 @@ void PlayerView::toggle_map()
if(chat()->visible() && !chat()->small_view())
chat()->hide();
- if (view_menu->visible())
- view_menu->hide();
+ if (view_entitymenu->visible())
+ view_entitymenu->hide();
}
map()->toggle();
@@ -85,8 +89,8 @@ void PlayerView::toggle_chat()
if(map()->visible())
map()->hide();
- if (view_menu->visible())
- view_menu->hide();
+ if (view_entitymenu->visible())
+ view_entitymenu->hide();
}
chat()->set_small_view(false);
chat()->toggle();
@@ -99,16 +103,47 @@ void PlayerView::toggle_chatbar()
chat()->toggle();
}
-void PlayerView::show_menu(const std::string & label)
+void PlayerView::show_menu(const std::string & args)
{
+ if (!args.size())
+ return;
+
if (!core::localplayer()->view())
return;
if (!core::localplayer()->view()->menus().size())
return;
- view_menu->generate(core::localplayer()->view(), label.c_str());
- view_menu->show();
+ std::stringstream argstr(args);
+ std::string label;
+ if (!(argstr >> label))
+ return;
+
+ if (label.compare("buy") == 0) {
+ // buy menu, single item
+ std::string itemtype;
+ std::string itemname;
+
+ if ((argstr >> itemtype) && (argstr >> itemname)) {
+ view_buymenu->set_item(itemtype, itemname);
+ view_buymenu->show();
+ view_entitymenu->hide();
+ } else {
+ con_print << "usage: view buy [string] [string] buy menu for item type and name" << std::endl;
+ }
+
+ } else if (label.compare("trade") == 0) {
+ // trade menu, multiple items
+
+ } else if (label.compare("hide") == 0) {
+ view_buymenu->hide();
+ view_entitymenu->hide();
+
+ } else {
+ view_entitymenu->generate(core::localplayer()->view(), label.c_str());
+ view_entitymenu->show();
+ view_buymenu->hide();
+ }
if (chat()->visible() && chat()->small_view())
chat()->raise();
@@ -121,6 +156,9 @@ void PlayerView::resize()
set_size(parent()->size());
+ // reposition buy menu
+ view_buymenu->event_resize();
+
// set hud geometry
view_hud->set_geometry(0,0, width(), height());
view_hud->event_resize();
@@ -142,6 +180,8 @@ void PlayerView::resize()
void PlayerView::draw()
{
+ const float smallmargin = ui::UI::elementsize.height();
+
if (core::localplayer()->view()) {
// hide hide when a view is set
@@ -164,12 +204,17 @@ void PlayerView::draw()
audio::play("ui/menu");
view_lastentity = core::localplayer()->view();
- } else if (!view_menu->visible() && !map()->visible() && (!chat()->visible() || chat()->small_view()) ) {
+ } else if (!view_entitymenu->visible() && !view_buymenu->visible() &&
+ !map()->visible() && (!chat()->visible() || chat()->small_view()) ) {
+
// show the menu if there's no other window open
menu()->show();
audio::play("ui/menu");
}
+ view_notify->set_size(width() - smallmargin * 3.0f - ui::UI::elementsize.width() * 1.5f, height() - smallmargin * 4.0f);
+ view_notify->set_location(smallmargin * 2.0f + ui::UI::elementsize.width() * 1.5f, smallmargin * 2.0f);
+
} else {
// entity without menus, plain view
view_lastentity = 0;
@@ -179,8 +224,13 @@ void PlayerView::draw()
}
} else {
- if (view_menu->visible()) {
- view_menu->hide();
+ view_notify->set_geometry(view_map->location(), view_map->size());
+
+ if (view_entitymenu->visible()) {
+ view_entitymenu->hide();
+ }
+ if (view_buymenu->visible()) {
+ view_buymenu->hide();
}
label_viewname->hide();
@@ -193,9 +243,6 @@ void PlayerView::draw()
label_zonename->set_text(core::localplayer()->zone()->name());
}
- //const float largemargin = ui::UI::elementsize.width() * 0.25;
- const float smallmargin = ui::UI::elementsize.height();
-
// reposition chat widget
if (view_chat->small_view()) {
view_chat->set_size(width() - smallmargin * 2, font()->height() * 2);
diff --git a/src/client/playerview.h b/src/client/playerview.h
index 9cf8a94..a09f5ca 100644
--- a/src/client/playerview.h
+++ b/src/client/playerview.h
@@ -8,7 +8,9 @@
#define __INCLUDED_CLIENT_PLAYERVIEW_H__
#include "client/chat.h"
+#include "client/buymenu.h"
#include "client/entitymenu.h"
+#include "client/trademenu.h"
#include "client/hud.h"
#include "client/map.h"
#include "client/notifications.h"
@@ -40,10 +42,11 @@ public:
/// show entity menus
void show_menu(const std::string & label);
+ inline HUD *hud() { return view_hud; }
inline Map *map() { return view_map; }
inline Chat *chat() { return view_chat; }
inline Notifications *notify() { return view_notify; }
- inline EntityMenu *menu() { return view_menu; }
+ inline EntityMenu *menu() { return view_entitymenu; }
protected:
virtual void draw();
@@ -54,7 +57,10 @@ private:
HUD *view_hud;
Chat *view_chat;
Map *view_map;
- EntityMenu *view_menu;
+
+ EntityMenu *view_entitymenu;
+ BuyMenu *view_buymenu;
+ TradeMenu *view_trademenu;
core::Entity *view_lastentity;
diff --git a/src/client/targets.cc b/src/client/targets.cc
index 8a50510..af8ec17 100644
--- a/src/client/targets.cc
+++ b/src/client/targets.cc
@@ -362,7 +362,7 @@ void frame()
if (entity->id() == current_target_id) {
current_target = entity;
}
-
+
// check if the mouse is hovering the entity
Vector3f v(entity->location() - render::Camera::eye());
v.normalize();
@@ -390,10 +390,11 @@ void frame()
}
}
}
+
}
}
-
+
if (!current_target) {
current_target_id = 0;
} else {
diff --git a/src/client/trademenu.cc b/src/client/trademenu.cc
new file mode 100644
index 0000000..9db1299
--- /dev/null
+++ b/src/client/trademenu.cc
@@ -0,0 +1,32 @@
+/*
+ client/trademenu.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "ui/ui.h"
+#include "ui/button.h"
+#include "ui/paint.h"
+#include "client/trademenu.h"
+
+namespace client
+{
+
+TradeMenu::TradeMenu(ui::Widget *parent, const char * label) : ui::Window(parent)
+{
+ set_border(false);
+ set_background(false);
+ if (label)
+ set_label(label);
+ else
+ set_label("trademenu");
+
+ hide();
+}
+
+TradeMenu::~TradeMenu()
+{
+
+}
+
+}
diff --git a/src/client/trademenu.h b/src/client/trademenu.h
new file mode 100644
index 0000000..feb91f4
--- /dev/null
+++ b/src/client/trademenu.h
@@ -0,0 +1,29 @@
+/*
+ client/trademenu.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_CLIENT_TRADEMENU_H__
+#define __INCLUDED_CLIENT_TRADEMENU_H__
+
+#include "ui/container.h"
+#include "ui/label.h"
+#include "ui/window.h"
+
+namespace client
+{
+
+/// trade menu
+class TradeMenu : public ui::Window
+{
+public:
+ /// create a new menu
+ TradeMenu(ui::Widget *parent, const char * label = 0);
+ ~TradeMenu();
+};
+
+}
+
+#endif // __INCLUDED_CLIENT_TRADEMENU_H__
+
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 317a99e..af59d00 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -3,7 +3,7 @@ INCLUDES = -I$(top_srcdir)/src
libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc \
descriptions.cc entity.cc extension.cc func.cc gameconnection.cc gameinterface.cc \
- gameserver.cc loader.cc module.cc netclient.cc netconnection.cc netplayer.cc \
+ gameserver.cc info.cc loader.cc module.cc netclient.cc netconnection.cc netplayer.cc \
netserver.cc parser.cc player.cc stats.cc timer.cc zone.cc
libcore_la_LDFLAGS = -avoid-version -no-undefined
libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \
@@ -15,3 +15,4 @@ noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \
gameconnection.h gameinterface.h gameserver.h message.h module.h net.h netclient.h \
netconnection.h netserver.h player.h range.h stats.h timer.h parser.h descriptions.h \
extension.h loader.h
+_SOURCES = info.h
diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc
index 21002bd..84b63be 100644
--- a/src/core/commandbuffer.cc
+++ b/src/core/commandbuffer.cc
@@ -16,6 +16,7 @@
#include "core/commandbuffer.h"
#include "core/gameconnection.h"
#include "core/func.h"
+#include "core/info.h"
#include "core/cvar.h"
#include "core/loader.h"
#include "core/zone.h"
@@ -23,6 +24,8 @@
namespace core
{
+std::stringstream CommandBuffer::cmdbuf(std::stringstream::in | std::stringstream::out);
+
void func_print(std::string const &args)
{
con_print << args << "\n";
@@ -38,6 +41,15 @@ void func_print_file(std::string const &args)
CommandBuffer::print_file(filename);
}
+void func_list_info(std::string const &args)
+{
+ Info *info = Info::find(args);
+ if (info)
+ info->print();
+ else
+ Info::list();
+}
+
void func_list_func(std::string const &args)
{
Func::list();
@@ -151,7 +163,19 @@ void func_exec(std::string const &args)
CommandBuffer::exec_file(filename);
}
-std::stringstream CommandBuffer::cmdbuf(std::stringstream::in | std::stringstream::out);
+void func_remote(std::string const &args)
+{
+ if (connection()) {
+ if ((args[0] == '\\') || (args[0] == '/')) {
+ connection()->forward(args.substr(1, args.size()-1));
+ } else {
+ connection()->forward(args);
+ }
+ } else {
+ cmd() << args;
+ CommandBuffer::exec();
+ }
+}
void CommandBuffer::init()
{
@@ -164,6 +188,9 @@ void CommandBuffer::init()
func = Func::add("list_func", (FuncPtr)func_list_func);
func->set_info("list functions");
+ func = Func::add("list_info", (FuncPtr)func_list_info);
+ func->set_info("list infos");
+
func = Func::add("list_var", (FuncPtr)func_list_var);
func->set_info("list variables");
@@ -190,6 +217,9 @@ void CommandBuffer::init()
func = Func::add("exec", (FuncPtr)func_exec);
func->set_info("[filename] execute commands from file");
+
+ func = Func::add("remote", (FuncPtr)func_remote);
+ func->set_info("[command] send a command to the game server");
}
void CommandBuffer::shutdown()
@@ -200,6 +230,7 @@ void CommandBuffer::shutdown()
Func::remove("toggle");
Func::remove("list_var");
Func::remove("list_func");
+ Func::remove("list_info");
Func::remove("list_ent");
Func::remove("list_model");
Func::remove("list_module");
diff --git a/src/core/descriptions.cc b/src/core/descriptions.cc
index fe37d2c..8c0f4ee 100644
--- a/src/core/descriptions.cc
+++ b/src/core/descriptions.cc
@@ -16,6 +16,7 @@ ButtonDescription::ButtonDescription()
{
button_model = 0;
button_align = Center;
+ button_commandtype = CommandNone;
}
ButtonDescription::~ButtonDescription()
@@ -27,8 +28,9 @@ void ButtonDescription::set_text(const std::string &text)
button_text.assign(text);
}
-void ButtonDescription::set_command(const std::string &command)
+void ButtonDescription::set_command(const std::string &command, const CommandType command_type)
{
+ button_commandtype = command_type;
button_command.assign(command);
}
@@ -85,9 +87,10 @@ void Descriptions::serialize(MenuDescription *menu, std::ostream & os)
for (MenuDescription::Buttons::iterator it = menu-> buttons().begin(); it != menu->buttons().end(); it++) {
ButtonDescription *button = (*it);
- os << "\"" << button->text() << "\" "
+ os << "\"" << button->text() << "\" "
<< button->alignment() << " "
- << "\"" << button->command() << "\" "
+ << button->command_type() << " "
+ << "\"" << button->command() << "\" "
<< "\"" << button->modelname() << "\" ";
}
}
@@ -97,6 +100,7 @@ MenuDescription * Descriptions::receive(std::istream &is)
MenuDescription *menu = new MenuDescription();
int a;
+ int t;
std::string n;
size_t nb;
char c;
@@ -135,12 +139,22 @@ MenuDescription * Descriptions::receive(std::istream &is)
else
button->set_alignment(ButtonDescription::Center);
+ // button command type
+ is >> t;
+
// button command
n.clear();
while ( (is.get(c)) && (c != '"'));
while ( (is.get(c)) && (c != '"'))
n += c;
- if (n.size()) button->set_command(n);
+
+ if (n.size()) {
+ if (t == ButtonDescription::CommandGame) {
+ button->set_command(n, ButtonDescription::CommandGame);
+ } else if (t == ButtonDescription::CommandMenu) {
+ button->set_command(n, ButtonDescription::CommandMenu);
+ }
+ }
// button modelname
n.clear();
@@ -213,7 +227,10 @@ bool Descriptions::load_entity_menus(core::Entity *entity, const std::string &me
if (strval[i] == ',') strval[i] = ';';
}
aux::strip_quotes(strval);
- button->set_command(strval);
+
+ // default command is a game command
+ button->set_command(strval, ButtonDescription::CommandGame);
+
} else if (inifile.got_key_string("model", strval)) {
button->set_modelname(strval);
} else if (inifile.got_key_string("align", strval)) {
diff --git a/src/core/descriptions.h b/src/core/descriptions.h
index 345d354..dec7896 100644
--- a/src/core/descriptions.h
+++ b/src/core/descriptions.h
@@ -28,6 +28,8 @@ class ButtonDescription
public:
enum Align {Center=0, Left=1, Right=2};
+ enum CommandType {CommandNone=0, CommandGame=1, CommandMenu=2};
+
ButtonDescription();
~ButtonDescription();
@@ -36,6 +38,9 @@ public:
/// button text
inline const std::string & text() const { return button_text; }
+ /// button command type
+ inline const CommandType command_type() const {return button_commandtype; }
+
/// button command
inline const std::string & command() const { return button_command; }
@@ -54,7 +59,7 @@ public:
void set_text(const std::string &text);
/// set button command
- void set_command(const std::string &command);
+ void set_command(const std::string &command, const CommandType command_type);
/// set button name
void set_modelname(const std::string &modelname);
@@ -64,10 +69,10 @@ public:
private:
std::string button_text;
+ CommandType button_commandtype;
std::string button_command;
std::string button_modelname;
Align button_align;
-
model::Model *button_model;
};
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index c2763ee..2dc0e32 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -74,6 +74,28 @@ GameConnection::~GameConnection()
connection_instance = 0;
}
+Info *GameConnection::info(const std::string &label)
+{
+ // check if we already have the info record
+ Info *info = Info::find(label);
+ if (info)
+ return info;
+
+ // create a new information record and set the label
+ info = new Info(label);
+ Info::add(info);
+
+ info->text().push_back("Requesting information...");
+
+ // send an information request to the server
+ if (connection_network) {
+ connection_network->send_info_request(info);
+ } else {
+ info->text().push_back("^RNot connected.");
+ }
+ return info;
+}
+
void GameConnection::abort()
{
connection_running = false;
diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h
index e1a7008..5880f9b 100644
--- a/src/core/gameconnection.h
+++ b/src/core/gameconnection.h
@@ -51,6 +51,9 @@ public:
/// localplayer sends a private message to another player
void private_message(std::string const &args);
+ /// returns an info record
+ Info *info(const std::string &label);
+
/*----- static ---------------------------------------------------- */
/// return the current game connection
diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc
index f658619..0ade34b 100644
--- a/src/core/gameinterface.cc
+++ b/src/core/gameinterface.cc
@@ -12,6 +12,7 @@
#include "core/application.h"
#include "core/cvar.h"
#include "core/func.h"
+#include "core/info.h"
#include "core/gameinterface.h"
#include "core/player.h"
#include "core/zone.h"
@@ -120,6 +121,9 @@ void GameInterface::clear()
// remove all models
model::Model::clear();
+ // remove infos
+ Info::clear();
+
// clear player list
for (Players::iterator it = game_players.begin(); it != game_players.end(); it++) {
Player *player = (*it);
diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h
index 22b85d5..8dc401b 100644
--- a/src/core/gameinterface.h
+++ b/src/core/gameinterface.h
@@ -8,6 +8,7 @@
#define __INCLUDED_CORE_GAMEINTERFACE_H__
#include "core/player.h"
+#include "core/info.h"
namespace core
{
@@ -38,6 +39,9 @@ public:
/// show a list of connected players
void list_players();
+ /// return the current game time, in seconds
+ float time() const { return ((float)(timestamp()) / 1000.0f); }
+
/*----- virtual inspectors --------------------------------------- */
/// returns true if the game server can run a time frime
@@ -49,8 +53,8 @@ public:
/// return the current game time
virtual unsigned long timestamp() const = 0;
- /// return the current game time, in seconds
- float time() const { return ((float)(timestamp()) / 1000.0f); }
+ /// returns an info record
+ virtual Info *info(const std::string &label) = 0;
/*----- mutators ------------------------------------------------- */
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index fc7a814..b82946b 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -226,6 +226,11 @@ GameServer::~GameServer()
server_instance = 0;
}
+Info *GameServer::info(const std::string &label)
+{
+ return Info::find(label);
+}
+
void GameServer::abort()
{
server_running = false;
diff --git a/src/core/gameserver.h b/src/core/gameserver.h
index 31cfca6..ac5f19e 100644
--- a/src/core/gameserver.h
+++ b/src/core/gameserver.h
@@ -77,6 +77,9 @@ public:
/// time the server was started
inline const unsigned long startup() const { return server_startup; }
+ /// returns an info record
+ Info *info(const std::string &label);
+
/*----- static ---------------------------------------------------- */
/// return the current game server
diff --git a/src/core/info.cc b/src/core/info.cc
new file mode 100644
index 0000000..fc10fe5
--- /dev/null
+++ b/src/core/info.cc
@@ -0,0 +1,183 @@
+/*
+ core/info.xx
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "auxiliary/functions.h"
+#include "core/info.h"
+#include "sys/sys.h"
+
+namespace core
+{
+
+Info::Registry Info::registry;
+
+Info::Info(const std::string & label)
+{
+ info_label.assign(label);
+ aux::to_lowercase(info_label);
+ aux::strip_quotes(info_label);
+ info_timestamp = 0;
+}
+
+void Info::set_name(const std::string & name)
+{
+ info_name.assign(name);
+}
+
+void Info::set_name(const char *name)
+{
+ info_name.assign(name);
+}
+
+void Info::set_modelname(const std::string & modelname)
+{
+ info_modelname.assign(modelname);
+}
+
+void Info::set_modelname(const char *modelname)
+{
+ info_modelname.assign(modelname);
+}
+
+void Info::set_timestamp(const unsigned long timestamp)
+{
+ info_timestamp = timestamp;
+}
+
+void Info::clear_timestamp()
+{
+ info_timestamp = 0;
+}
+
+void Info::add_text(const char *text)
+{
+ std::string str(text);
+ aux::strip_quotes(str);
+ info_text.push_back(str);
+}
+
+void Info::add_text(const std::string & text)
+{
+ add_text(text.c_str());
+}
+
+void Info::clear_text()
+{
+ info_text.clear();
+}
+
+void Info::serialize_server_update(std::ostream & os) const
+{
+ os << '"' << name() << "\" \"" << modelname() << "\" " << info_text.size() << " ";
+
+ for (Text::const_iterator it = info_text.begin(); it != info_text.end(); it++) {
+ if (it != info_text.begin())
+ os << ' ';
+
+ os << '"' << (*it) << '"';
+ }
+}
+
+void Info::receive_server_update(std::istream &is)
+{
+ std::string n;
+ char c;
+
+ // read name
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ info_name.assign(n);
+
+ // read model name
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+
+ info_modelname.assign(n);
+
+ // read info text
+ size_t s;
+ info_text.clear();
+ is >> s;
+ for (size_t i = 0; (i < s) && is.good(); i++) {
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+
+ info_text.push_back(n);
+ }
+}
+
+Info::~Info()
+{
+ info_text.clear();
+ info_modelname.clear();
+ info_text.clear();
+}
+
+void Info::print() const
+{
+ con_print << "label: ^B" << label() << " ^Nname: ^B" << name() << "^N" << std::endl;
+
+ for (Text::const_iterator it = info_text.begin(); it != info_text.end(); it++) {
+ con_print << " " << (*it) << std::endl;
+ }
+}
+
+/* ---- static info registry --------------------------------------- */
+
+void Info::add(Info *info)
+{
+ if (find(info->label()))
+ return;
+
+ registry[info->label()] = info;
+}
+
+Info *Info::find(const char *label)
+{
+ for (Registry::iterator it = registry.begin(); it != registry.end(); it++) {
+ Info *info = (*it).second;
+ if (info->label().compare(label) == 0) {
+ return info;
+ }
+ }
+ return 0;
+}
+
+Info *Info::find(const std::string & label)
+{
+ for (Registry::iterator it = registry.begin(); it != registry.end(); it++) {
+ Info *info = (*it).second;
+ if (info->label().compare(label) == 0) {
+ return info;
+ }
+ }
+ return 0;
+}
+
+void Info::clear()
+{
+ for (Registry::iterator it = registry.begin(); it != registry.end(); it++) {
+ Info *info = (*it).second;;
+ delete info;
+ }
+ registry.clear();
+}
+
+void Info::list()
+{
+ for (Registry::iterator it = registry.begin(); it != registry.end(); it++) {
+ Info *info = (*it).second;;
+ con_print << info->label() << std::endl;
+ }
+ con_print << registry.size() << " registered infos" << std::endl;
+}
+
+}
+
diff --git a/src/core/info.h b/src/core/info.h
new file mode 100644
index 0000000..cc480bf
--- /dev/null
+++ b/src/core/info.h
@@ -0,0 +1,108 @@
+/*
+ core/info.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_CORE_INFO_H__
+#define __INCLUDED_CORE_INFO_H__
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <deque>
+
+#include "model/model.h"
+
+namespace core
+{
+
+/**
+ * an information record
+ */
+class Info
+{
+public:
+ /// create a new labeled information record
+ Info(const std::string & label);
+ /// delete the information record
+ ~Info();
+
+ typedef std::deque<std::string> Text;
+
+ inline const std::string & label() const { return info_label; }
+
+ inline const std::string & name() const { return info_name; }
+
+ inline const std::string & modelname() const { return info_modelname; }
+
+ inline const unsigned long &timestamp() const { return info_timestamp; }
+
+ inline Text & text() { return info_text; }
+
+ void set_name(const std::string & name);
+
+ void set_name(const char *name);
+
+ void set_modelname(const std::string & modelname);
+
+ void set_modelname(const char *modelname);
+
+ /// set the timestamp
+ void set_timestamp(const unsigned long timestamp);
+
+ /// clear the timestamp
+ void clear_timestamp();
+
+ /// add a line of info text
+ void add_text(const char *text);
+
+ /// add a line of info text
+ void add_text(const std::string & text);
+
+ /// clear the info text
+ void clear_text();
+
+ /// print info to sys::con_out
+ void print() const;
+
+ /// serialize a server-to-client update on a stream
+ void serialize_server_update(std::ostream & os) const;
+
+ /// receive a server-to-client update from a stream
+ void receive_server_update(std::istream &is);
+
+/* ---- static info registry --------------------------------------- */
+
+ typedef std::map<std::string, Info*> Registry;
+
+ /// add an item to the info regsitry
+ static void add(Info *info);
+
+ /// search the info registry for a labeled item
+ static Info *find(const char * label);
+
+ /// search the info registry for a labeled item
+ static Info *find(const std::string & label);
+
+ /// clear the info registry
+ static void clear();
+
+ /// list the info registry
+ static void list();
+
+private:
+ std::string info_label;
+ std::string info_name;
+ std::string info_modelname;
+ Text info_text;
+
+ long info_credits;
+ static Registry registry;
+
+ unsigned long info_timestamp;
+};
+
+}
+#endif // __INCLUDED_CORE_INFO_H__
+
diff --git a/src/core/net.h b/src/core/net.h
index 887bf1b..01c15be 100644
--- a/src/core/net.h
+++ b/src/core/net.h
@@ -11,7 +11,7 @@ namespace core
{
/// network protocol version
-const unsigned int PROTOCOLVERSION = 15;
+const unsigned int PROTOCOLVERSION = 16;
/// maximum lenght of a (compressed) network message block
const unsigned int FRAMESIZE = 1152;
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index fc2b6bf..dfb86f7 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -410,6 +410,16 @@ void NetConnection::send_ping_reply(unsigned long timestamp)
this->send_raw(msg.str());
}
+// send an info record request
+void NetConnection::send_info_request(Info *info)
+{
+ std::ostringstream msg;
+ msg << "inf " << '"' << info->label() << '"' << '\n';
+ this->send_raw(msg.str());
+
+ info->set_timestamp(application()->timestamp());
+}
+
// parse incoming client messages
/**
* The following incoming messages are parsed;
@@ -674,7 +684,28 @@ void NetConnection::parse_incoming_message(const std::string & message)
return;
}
}
-
+ } else if (command == "inf") {
+
+ // incoming info record
+ std::string label;
+ char c;
+
+ while ( (msgstream.get(c)) && (c != '"'));
+ while ( (msgstream.get(c)) && (c != '"'))
+ label += c;
+
+ if (label.size()) {
+ Info *info = Info::find(label);
+ if (!info) {
+ info = new Info(label);
+ Info::add(info);
+ }
+
+ info->receive_server_update(msgstream);
+ info->clear_timestamp();
+ } else {
+ con_warn << "Received empty information record!" << std::endl;
+ }
} else if (command == "sup") {
if (connection_state == Connected)
{
diff --git a/src/core/netconnection.h b/src/core/netconnection.h
index a17b35d..7c0b23d 100644
--- a/src/core/netconnection.h
+++ b/src/core/netconnection.h
@@ -30,6 +30,7 @@
#include "core/entity.h"
#include "core/net.h"
+#include "core/info.h"
namespace core
{
@@ -71,6 +72,9 @@ public:
/// send a console command to the remote server
void send_rcon(std::string const &cmdline);
+ /// send an info request
+ void send_info_request(Info *info);
+
/// transmit messages in the send queue to the remote server
void transmit();
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index 62d9b74..5b3a991 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -525,7 +525,7 @@ void NetServer::send_player_update(NetClient *client)
void NetServer::send_player_update(NetClient *client, Player *player)
{
std::ostringstream msg;
- msg << "pif " << player->id() << " ";
+ msg << "pif " << player->id() << ' ';
client->player()->serialize_server_update(msg);
msg << '\n';
client->send_raw(msg.str());
@@ -539,6 +539,16 @@ void NetServer::send_player_disconnect_info(NetClient *client, Player *player)
client->send_raw(msg.str());
}
+// send a "inf" info record
+void NetServer::send_info_update(NetClient *client, Info *info)
+{
+ std::ostringstream msg;
+ msg << "inf " << '"' << info->label() << '"' << ' ';
+ info->serialize_server_update(msg);
+ msg << '\n';
+ client->send_raw(msg.str());
+}
+
// parse incoming client messages
/**
@@ -547,6 +557,7 @@ void NetServer::send_player_disconnect_info(NetClient *client, Player *player)
* disconnect
* cmd <game command>
* cup
+ * inf
* pif
* ping
* say <text>
@@ -641,6 +652,23 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me
return;
}
+ if (command == "inf") {
+ std::string n;
+ char c;
+
+ while ( (msgstream.get(c)) && (c != '"'));
+ while ( (msgstream.get(c)) && (c != '"'))
+ n += c;
+
+ if (n.size()) {
+ Info *info = Info::find(n);
+ if (info) {
+ send_info_update(client, info);
+ client->transmit();
+ }
+ }
+ }
+
if (command == "rcon") {
if ((message.size() > command.size()+1) && Cvar::sv_password->str().size()) {
if ((Cvar::sv_password->str().compare(client->player()->rconpassword()) == 0)) {
diff --git a/src/core/netserver.h b/src/core/netserver.h
index 9ef0f0d..e54ea2e 100644
--- a/src/core/netserver.h
+++ b/src/core/netserver.h
@@ -19,6 +19,7 @@
#include "core/net.h"
#include "core/netclient.h"
#include "core/player.h"
+#include "core/info.h"
namespace core
{
@@ -92,6 +93,9 @@ protected:
/// send player disconnect information message
void send_player_disconnect_info(NetClient *client, Player *player);
+ /// send player an info record
+ void send_info_update(NetClient *client, Info *info);
+
/// set the error state
void abort();
diff --git a/src/game/base/collision.cc b/src/game/base/collision.cc
index 728ad14..215764c 100644
--- a/src/game/base/collision.cc
+++ b/src/game/base/collision.cc
@@ -8,26 +8,27 @@
#include "base/game.h"
#include "core/zone.h"
#include "math/functions.h"
-#include "math/vector3f.h"
+#include "math/vector3f.h"
-namespace game {
+namespace game
+{
void Collision::distance_test(core::EntityControlable *first, core::Entity *second)
{
if (!first->owner())
return;
-
+
if (first->state() == core::Entity::Docked)
return;
-
+
// FIXME - use distancesquared
const float d = math::distance(first->location(), second->location());
const float r = first->radius() + second->radius();
-
+
if (second->type() == core::Entity::Globe) {
// collision with a star or a planet
-
- if ( (d-r) < 0.0f) {
+
+ if ((d-r) < 0.0f) {
// crash zone
if ((first->moduletype() == ship_enttype) && (first->state() != core::Entity::Destroyed)) {
first->owner()->send_warning("^RBOOM!^N");
@@ -36,9 +37,9 @@ void Collision::distance_test(core::EntityControlable *first, core::Entity *seco
}
} else if (first->owner()->last_warning() + 5.0f < core::application()->time()) {
// warning zone: star corona or planet atmosphere
- if ((second->moduletype() == star_enttype) && (d-r < 50.0f)) {
+ if ((second->moduletype() == star_enttype) && (d-r < 50.0f)) {
first->owner()->send_warning("^3Warning: entering star corona!^N");
- } else if ((second->moduletype() == planet_enttype) && (d-r < 15.0f)) {
+ } else if ((second->moduletype() == planet_enttype) && (d-r < 15.0f)) {
first->owner()->send_warning("^3Warning: entering planet gravity well!^N");
}
}
@@ -49,14 +50,14 @@ void Collision::frame_zone(core::Zone *zone)
{
core::Zone::Content::iterator first;
core::Zone::Content::iterator second;
-
+
for (first = zone->content().begin(); first != zone->content().end(); first ++) {
second = first;
for (second++; second != zone->content().end(); second++) {
- if ( (*first)->type() == core::Entity::Controlable) {
+ if ((*first)->type() == core::Entity::Controlable) {
distance_test(static_cast<core::EntityControlable *>((*first)), (*second));
} else if ((*second)->type() == core::Entity::Controlable) {
- distance_test(static_cast<core::EntityControlable *> ((*second)), (*first));
+ distance_test(static_cast<core::EntityControlable *>((*second)), (*first));
}
}
}
diff --git a/src/game/base/game.cc b/src/game/base/game.cc
index b2824f5..da060b9 100644
--- a/src/game/base/game.cc
+++ b/src/game/base/game.cc
@@ -191,6 +191,26 @@ void Game::func_dock(core::Player *player, core::Entity *entity)
}
}
+// buy request from a player
+void Game::func_buy(core::Player *player, const std::string &args)
+{
+ std::istringstream is(args);
+ std::string itemtype;
+ if (!(is >> itemtype)) {
+ player->send("usage: buy [string] [string] buy type of item, name of item");
+ return;
+ }
+
+ aux::to_label(itemtype);
+ if ((args.size() > 5 ) && (itemtype.compare("ship") == 0)) {
+ ShipDealer::func_buy(player, args.substr(5, args.size() - 5));
+ } else {
+ player->send("unkown item type '" + itemtype + "'");
+ }
+
+ return;
+}
+
// launch request
void Game::func_launch(core::Player *player, std::string const &args)
{
@@ -308,8 +328,8 @@ Game::Game() : core::Module("Project::OSiRiON", true)
func = core::Func::add("spectate", Game::func_spectate);
func->set_info("leave the game and spectate");
- func = core::Func::add("buy", ShipDealer::func_buy);
- func->set_info("buy a ship");
+ func = core::Func::add("buy", Game::func_buy);
+ func->set_info("[string] [string] buy type of item, name of item");
func = core::Func::add("jump", Game::func_jump);
func->set_info("[string] activate or deactivate hyperspace jump drive");
@@ -697,7 +717,7 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename)
if (model) {
button = new ButtonDescription();
button->set_text("buy " + model->name());
- button->set_command("buy " + model->label());
+ button->set_command("buy ship " + model->label(), ButtonDescription::CommandMenu);
button->set_modelname(model->modelname());
button->set_alignment(ButtonDescription::Left);
menu_dealer->add_button(button);
@@ -719,14 +739,14 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename)
button = new ButtonDescription();
button->set_text("Launch");
- button->set_command("launch");
+ button->set_command("launch", ButtonDescription::CommandGame);
button->set_alignment(ButtonDescription::Center);
menu_main->add_button(button);
if (menu_dealer) {
button = new ButtonDescription();
button->set_text("Return");
- button->set_command("menu view main");
+ button->set_command("main", ButtonDescription::CommandMenu);
button->set_alignment(ButtonDescription::Center);
menu_dealer->add_button(button);
@@ -734,7 +754,7 @@ bool Game::load_menus(core::Entity *entity, const std::string &menufilename)
button = new ButtonDescription();
button->set_text("Ship dealer");
- button->set_command("menu view dealer");
+ button->set_command("dealer", ButtonDescription::CommandMenu);
button->set_alignment(ButtonDescription::Center);
menu_main->add_button(button);
}
@@ -763,6 +783,7 @@ bool Game::load_ships()
ShipModel *shipmodel = 0;
std::string label;
+ std::string infostr;
long l;
float f;
@@ -776,6 +797,9 @@ bool Game::load_ships()
continue;
} else if (shipsini.got_key_string("name",shipmodel->shipmodel_name)) {
continue;
+ } else if (shipsini.got_key_string("info", infostr)) {
+ shipmodel->shipmodel_infotext.push_back(infostr);
+ continue;
} else if (shipsini.got_key_string("model", shipmodel->shipmodel_modelname)) {
continue;
} else if (shipsini.got_key_long("price", l)) {
@@ -814,6 +838,14 @@ bool Game::load_ships()
if (shipmodel && !ShipModel::find(shipmodel)) delete shipmodel;
+ // add shipmodel infos
+ for (ShipModel::iterator it = ShipModel::registry.begin(); it != ShipModel::registry.end(); it++) {
+ ShipModel *shipmodel = (*it).second;
+ core::Info *info = new core::Info("ship/" + shipmodel->label());
+ shipmodel->generate_info(info);
+ core::Info::add(info);
+ }
+
con_debug << " " << shipsini.name() << " " << ShipModel::registry.size() << " ship models" << std::endl;
return true;
diff --git a/src/game/base/game.h b/src/game/base/game.h
index 36de8dc..1f16a9f 100644
--- a/src/game/base/game.h
+++ b/src/game/base/game.h
@@ -103,6 +103,7 @@ private:
static void func_launch(core::Player *player, std::string const &args);
static void func_respawn(core::Player *player, std::string const &args);
static void func_goto(core::Player *player, const std::string &args);
+ static void func_buy(core::Player *player, std::string const &args);
};
/// factory function
diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc
index 78dc125..fc4781a 100644
--- a/src/game/base/shipmodel.cc
+++ b/src/game/base/shipmodel.cc
@@ -43,11 +43,42 @@ void ShipModel::clear()
void ShipModel::print()
{
con_print << "label: ^B" << label() << " ^Nname: ^B" << name() << std::endl;
+ con_print << " price: ^B" << price() << std::endl;
con_print << " acceleration: ^B" << acceleration() << std::endl;
con_print << " turnspeed: ^B" << turnspeed() << std::endl;
con_print << " max speed: ^B" << maxspeed() << std::endl;
- con_print << " max cargo: ^B" << maxcargo() << std::endl;
- con_print << " price: ^B" << price() << std::endl;
+ con_print << " cargo: ^B" << maxcargo() << std::endl;
+}
+
+void ShipModel::generate_info(core::Info *info)
+{
+ info->clear_text();
+
+ info->set_name(name());
+ info->set_modelname(modelname());
+
+ // info text form ships.ini
+ for (core::Info::Text::iterator it = shipmodel_infotext.begin(); it != shipmodel_infotext.end(); it++) {
+ info->add_text((*it));
+ }
+
+ info->add_text("");
+ info->add_text("^BSpecifications:^N");
+ std::stringstream str;
+ str << "price: ^B" << price() << " ^Ncredits";
+ info->add_text(str.str()); str.str("");
+
+ str << "cargo hold: ^B" << 0.1f * maxcargo() << " ^Nmetric tonnes";
+ info->add_text(str.str()); str.str("");
+
+ str << "top speed: ^B" << 100.0f * maxspeed() << " ^Nmps";
+ info->add_text(str.str()); str.str("");
+
+ str << "response: ^B" << turnspeed() << " ^Ndps";
+ info->add_text(str.str()); str.str("");
+
+ str << "acceleration: ^B" << acceleration() << " ^Nstandard";
+ info->add_text(str.str()); str.str("");
}
void ShipModel::list()
diff --git a/src/game/base/shipmodel.h b/src/game/base/shipmodel.h
index c194dc0..9bdf4f5 100644
--- a/src/game/base/shipmodel.h
+++ b/src/game/base/shipmodel.h
@@ -10,6 +10,8 @@
#include <map>
#include <string>
+#include "core/info.h"
+
namespace game {
/// ship model specifications
@@ -60,6 +62,9 @@ public:
/// set size of the cargo hold
inline void set_maxcargo(const float maxcargo) { shipmodel_maxcargo = maxcargo; }
+ /// generate an info object for this shipmodel
+ void generate_info(core::Info *info);
+
/// indicates of this model can be equiped with a jump drive
bool shipmodel_jumpdrive;
@@ -67,6 +72,9 @@ public:
std::string shipmodel_name;
std::string shipmodel_modelname;
+ /// info text
+ core::Info::Text shipmodel_infotext;
+
/* ---- static registry ------------------------------------ */
typedef std::map<std::string, ShipModel *>::iterator iterator;
diff --git a/src/ui/modelview.cc b/src/ui/modelview.cc
index 4239294..a07922a 100755
--- a/src/ui/modelview.cc
+++ b/src/ui/modelview.cc
@@ -55,6 +55,11 @@ void ModelView::draw()
if (!modelview_modelname.size())
return;
+ math ::Vector2f center(global_location());
+
+ center.x += width() * 0.5f;
+ center.y += height() * 0.5f;
+
//model::Model *model = model::Model::find(modelview_modelname);
// gl 3d mode