From 5f0958c121a246d445507313984358ff8a6df3fa Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 10 Nov 2013 17:13:41 +0000 Subject: Adjust reputation on NPC kills, refresh reputation window if required. --- src/client/reputationwindow.cc | 47 +++++++++++++++++++++++++++++++----------- src/client/reputationwindow.h | 3 ++- src/core/netconnection.cc | 1 + src/core/reputation.cc | 13 ++++++++++++ src/core/reputation.h | 24 +++++++++++++++++---- src/game/base/faction.cc | 45 ++++++++++++++++++++++++++++++++++++++-- src/game/base/faction.h | 11 ++++++++++ src/game/base/ship.cc | 15 +++++++++++++- 8 files changed, 139 insertions(+), 20 deletions(-) diff --git a/src/client/reputationwindow.cc b/src/client/reputationwindow.cc index 804ab50..3566458 100644 --- a/src/client/reputationwindow.cc +++ b/src/client/reputationwindow.cc @@ -11,6 +11,7 @@ #include "client/client.h" #include "client/reputationwindow.h" #include "core/reputation.h" +#include "core/range.h" namespace client { @@ -86,7 +87,8 @@ private: ReputationWindow::ReputationWindow(ui::Widget *parent) : ui::Window(parent) { reputationwindow_info = 0; - reputationwindow_timestamp = 0; + reputationwindow_info_timestamp = 0; + reputationwindow_reputation_timestamp = 0; // window title reputationwindow_titlelabel = new ui::Label(this); @@ -133,6 +135,7 @@ ReputationWindow::~ReputationWindow() void ReputationWindow::show() { if (hidden()) { + reputationwindow_info = 0; refresh(); } @@ -144,14 +147,15 @@ void ReputationWindow::refresh() reputationwindow_listview->clear(); const float padding = ui::root()->font_large()->height(); + ui::ListItem *selected_listitem = 0; for (core::Reputation::FactionReps::const_iterator it = core::localplayer()->reputation().factionreps().begin(); it != core::localplayer()->reputation().factionreps().end(); ++it) { if ((*it)->faction()) { std::string strdescription; - if (roundf((*it)->reputation()) < -50.0f) { + if (roundf((*it)->reputation()) <= core::range::reputation_hostile) { strdescription.append("^1"); - } else if (roundf((*it)->reputation()) > 50.0f) { + } else if (roundf((*it)->reputation()) >= core::range::reputation_friendly) { strdescription.append("^2"); } else { strdescription.append("^B"); @@ -172,12 +176,26 @@ void ReputationWindow::refresh() bar->set_reputation((*it)->reputation()); bar->set_size(reputationwindow_listview->width() - padding, bar->font()->height()); bar->set_location( padding * 0.5f, listitem->height() - bar->height() - padding * 0.5f); + + if ((*it)->faction() == reputationwindow_info) { + selected_listitem = listitem; + } } } reputationwindow_listview->sort(); + reputationwindow_listview->event_resize(); + + reputationwindow_reputation_timestamp = core::localplayer()->reputation().timestamp(); + + if (selected_listitem) { + reputationwindow_listview->select(selected_listitem); + reputationwindow_info = selected_listitem->info(); + } else { + reputationwindow_info = 0; + } - set_info(); + set_info(reputationwindow_info); } void ReputationWindow::set_info(const core::Info *info) @@ -187,8 +205,6 @@ void ReputationWindow::set_info(const core::Info *info) reputationwindow_info = info; if (!info) { - reputationwindow_timestamp = 0; - // player name reputationwindow_targetlabel->set_text(core::localplayer()->name()); @@ -250,27 +266,34 @@ void ReputationWindow::set_info(const core::Info *info) strinfotext << std::setfill('0') << std::setw(2) << time_wasted_seconds; reputationwindow_infotext.push_back(strinfotext.str()); + reputationwindow_info_timestamp = 0; + } else { core::game()->request_info(info->id()); - reputationwindow_targetlabel->set_text(info->name()); - reputationwindow_timestamp = info->timestamp(); - + reputationwindow_targetlabel->set_text(info->name()); for (core::Info::Text::const_iterator it = info->text().begin(); it != info->text().end(); it++) { reputationwindow_infotext.push_back((*it)); } + + reputationwindow_info_timestamp = info->timestamp(); } } void ReputationWindow::draw() { - if (!reputationwindow_info) { + if (reputationwindow_reputation_timestamp != core::localplayer()->reputation().timestamp()) { + con_debug << " ^2ReputationWindow::draw() forced refresh" << std::endl; + refresh(); + + } else if (!reputationwindow_info) { // update player info set_info(0); - - } else if (reputationwindow_timestamp != reputationwindow_info->timestamp()) { + + } else if (reputationwindow_info_timestamp != reputationwindow_info->timestamp()) { // update faction info if we received updates from the server set_info(reputationwindow_info); + } ui::Window::draw(); diff --git a/src/client/reputationwindow.h b/src/client/reputationwindow.h index b6c95c7..7b91cf3 100644 --- a/src/client/reputationwindow.h +++ b/src/client/reputationwindow.h @@ -80,7 +80,8 @@ private: const core::Info *reputationwindow_info; - unsigned long reputationwindow_timestamp; + unsigned long reputationwindow_info_timestamp; + unsigned long reputationwindow_reputation_timestamp; }; // class ReputationWindow diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index b1a4e77..f87f66e 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -817,6 +817,7 @@ void NetConnection::parse_incoming_message(const std::string & message) } else if (command.compare("rep") == 0) { connection()->localplayer()->reputation().receive_server_update(msgstream); + connection()->localplayer()->reputation().set_timestamp(game()->timestamp()); } else if (command.compare("inf") == 0) { diff --git a/src/core/reputation.cc b/src/core/reputation.cc index b3eee43..ea276a7 100644 --- a/src/core/reputation.cc +++ b/src/core/reputation.cc @@ -43,6 +43,19 @@ void Reputation::assign(const Reputation &other) } +void Reputation::set_dirty(const bool dirty) +{ + reputation_dirty = dirty; + if (reputation_dirty) { + reputation_timestamp = game()->timestamp(); + } +} + +void Reputation::set_timestamp(const unsigned long timestamp) +{ + reputation_timestamp = timestamp; +} + const Info *Reputation::find(const Info *faction) const { for (FactionReps::const_iterator it = reputation_factionreps.begin(); it != reputation_factionreps.end(); ++it) { diff --git a/src/core/reputation.h b/src/core/reputation.h index d20a210..af6b426 100644 --- a/src/core/reputation.h +++ b/src/core/reputation.h @@ -87,15 +87,24 @@ public: void set_reputation(const Info *faction, const float reputation); - inline void set_dirty(const bool dirty = true) - { - reputation_dirty = dirty; - } + void set_dirty(const bool dirty = true); + + void set_timestamp(const unsigned long timestamp); void clear(); void assign(const Reputation &other); + inline FactionReps::const_iterator factionreps_begin() const + { + return reputation_factionreps.begin(); + } + + inline FactionReps::const_iterator factionreps_end() const + { + return reputation_factionreps.end(); + } + inline FactionReps & factionreps() { return reputation_factionreps; @@ -106,6 +115,11 @@ public: return reputation_dirty; } + inline const unsigned long timestamp() const + { + return reputation_timestamp; + } + /* ---- deserializers -------------------------------------- */ /// receive a server-to-client update from a stream @@ -120,6 +134,8 @@ private: FactionReps reputation_factionreps; bool reputation_dirty; + + unsigned long reputation_timestamp; }; } // namespace core diff --git a/src/game/base/faction.cc b/src/game/base/faction.cc index ef0a7b6..2dd8a1a 100644 --- a/src/game/base/faction.cc +++ b/src/game/base/faction.cc @@ -6,6 +6,7 @@ #include "core/func.h" #include "core/parser.h" +#include "core/range.h" #include "base/faction.h" namespace game { @@ -193,6 +194,8 @@ Faction::~Faction() void Faction::apply(core::Entity *entity) const { + assert(entity); + // set primary color entity->set_color(color()); @@ -203,10 +206,48 @@ void Faction::apply(core::Entity *entity) const entity->set_faction(this); } + +void Faction::apply_kill(core::Player *player) const +{ + assert(player); + + // a kill will cost the player 5 reputation points with this faction + const float points = 5.0f; + + // a kill will cost the player 1 reputation point with this faction's friends and allies + const float points_ally = 1.0f; + + // adjust current player reputation for this faction + player->reputation().set_reputation(this, player->reputation(this) - points); + + // adjust player reputation for this factions's allies and enemies + for (core::Reputation::FactionReps::const_iterator rip = faction_reputation.factionreps_begin(); rip != faction_reputation.factionreps_end(); ++rip) { + assert((*rip)->faction()); + + if ((*rip)->faction() != faction_default) { + const float other_faction_reputation = faction_reputation.reputation((*rip)->faction()); + if (other_faction_reputation >= core::range::reputation_friendly) { + // allied faction + player->reputation().set_reputation((*rip)->faction(), player->reputation((*rip)->faction()) - points_ally); + } else if (other_faction_reputation <= core::range::reputation_hostile) { + //enemy faction + player->reputation().set_reputation((*rip)->faction(), player->reputation((*rip)->faction()) + points_ally); + } + } + } + + player->reputation().set_dirty(); +} + +void Faction::apply_sale(core::Player *player, const float amount) const +{ + assert(player); +} + + void Faction::apply_default(core::Reputation & reputation) { - // apply default reputation - Faction *faction_default = find("default"); + // apply default reputation if (faction_default) { for (core::Reputation::FactionReps::const_iterator rip = faction_default->reputation().factionreps().begin(); rip != faction_default->reputation().factionreps().end(); ++rip) { // only add defaults the reputation doesn't have yet diff --git a/src/game/base/faction.h b/src/game/base/faction.h index b459899..3f6a1e5 100644 --- a/src/game/base/faction.h +++ b/src/game/base/faction.h @@ -67,6 +67,16 @@ public: faction_color_second.assign(color_second); } + /** + * @brief adjust player reputation for a kill of a member of this faction + */ + void apply_kill(core::Player *player) const; + + /** + * @brief adjust player reputation for buying from/selling to this faction + */ + void apply_sale(core::Player *player, const float amount) const; + /* --- static ----------------------------------------------------- */ /** @@ -87,6 +97,7 @@ public: * @brief apply default reputation * */ static void apply_default(core::Reputation & reputation); + static inline const core::InfoType *infotype() { return faction_infotype; diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 2a5d68f..338bc04 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -22,6 +22,7 @@ #include "base/racetrack.h" #include "base/cargo.h" #include "base/cargopod.h" +#include "base/faction.h" using math::degrees360f; using math::degrees180f; @@ -663,13 +664,16 @@ void Ship::hit(core::Entity *other) message.append(" ^Bwent boom."); } core::server()->broadcast(message); - } else { if (assassin) { // assissin killed an NPC assassin->set_npckills(assassin->npckills() + 1); assassin->set_dirty(); + + // faction ship got killed + assert (faction()->type() == Faction::infotype()); + static_cast(faction())->apply_kill(assassin); } } } @@ -711,6 +715,15 @@ void Ship::hit(core::Entity *other) message.append(" ^Bwas blown to bits."); } core::server()->broadcast(message); + + } else if (faction()) { + + if (assassin) { + // faction ship got killed + assert (faction()->type() == Faction::infotype()); + static_cast(faction())->apply_kill(assassin); + } + } if (assassin) { -- cgit v1.2.3