Permalink
Browse files

Merge pull request #313 from redv/bribescreen

implemented the BribeScreen
  • Loading branch information...
JonnyH committed Dec 22, 2017
2 parents 97fe0d1 + e27b84a commit ae86cc2812876e55f7f52076c5faa9e418c66ae9
View
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<openapoc>
<form id="FORM_SCORE_SCREEN">
<style minwidth="640" minheight="480">
<position x="centre" y="centre"/>
<size width="640" height="480"/>
<graphic>
<image>xcom3/ufodata/dip_rift.pcx</image>
<position x="0" y="0"/>
<size width="640" height="480"/>
</graphic>
<label text="OFFER CASH SETTLEMENT">
<position x="113" y="0"/>
<size width="420" height="32"/>
<alignment horizontal="centre" vertical="centre"/>
<font>bigfont</font>
</label>
<label id="TEXT_FUNDS">
<position x="572" y="11"/>
<size width="60" height="10"/>
<alignment horizontal="left" vertical="centre"/>
<font>smalfont</font>
</label>
<label id="TEXT_DATE">
<position x="27" y="77"/>
<size width="300" height="15"/>
<alignment horizontal="left" vertical="centre"/>
<font>smalfont</font>
</label>
<label id="TEXT_RELATION">
<position x="27" y="102"/>
<size width="300" height="15"/>
<alignment horizontal="left" vertical="centre"/>
<font>smalfont</font>
</label>
<label id="TEXT_OFFER">
<position x="27" y="152"/>
<size width="400" height="30"/>
<alignment horizontal="left" vertical="top"/>
<font>smalfont</font>
</label>
<graphicbutton id="BUTTON_BRIBE">
<position x="602" y="40"/>
<size width="35" height="34"/>
<imagedepressed>PCK:xcom3/ufodata/newbut.pck:xcom3/ufodata/newbut.tab:78:xcom3/ufodata/base.pcx</imagedepressed>
</graphicbutton>
<graphicbutton id="BUTTON_QUIT">
<position x="602" y="443"/>
<size width="35" height="34"/>
<imagedepressed>BUTTON_OK_DEPRESSED</imagedepressed>
</graphicbutton>
</style>
</form>
</openapoc>
@@ -640,23 +640,26 @@ Organisation::Relation Organisation::isRelatedTo(const StateRef<Organisation> &o
{
float x = this->getRelationTo(other);
// FIXME: Make the thresholds read from serialized GameState?
if (x <= -50)
if (x < -50)
{
return Relation::Hostile;
}
else if (x <= -25)
else if (x < -25)
{
return Relation::Unfriendly;
}
else if (x >= 25)
else if (x < 25)
{
return Relation::Neutral;
}
else if (x < 75)
{
return Relation::Friendly;
}
else if (x >= 75)
else
{
return Relation::Allied;
}
return Relation::Neutral;
}
bool Organisation::isPositiveTo(const StateRef<Organisation> &other) const
@@ -671,6 +674,86 @@ bool Organisation::isNegativeTo(const StateRef<Organisation> &other) const
return x < 0;
}
/**
* Calculate the cost of a bribe
* @param other - other organisation
* @return - minimum sum of the bribe
*/
int Organisation::costOfBribeBy(const StateRef<Organisation> &other) const
{
float improvement;
float x = this->getRelationTo(other);
if (x < -50) // Hostile
{
improvement = -50.0f - x;
}
else if (x < -25) // Unfriendly
{
improvement = -25.0f - x;
}
else if (x < 25) // Neutral
{
improvement = 25.0f - x;
}
else if (x < 75) // Friendly
{
improvement = 75.0f - x;
}
else // Allied (relationship cannot be improved)
{
return 0;
}
// The best approximation is 2030 * improvement + 19573
// but vanilla X-Com:
// 1. fond of numbers with 7 (27000, 37000 etc up to 127000)
// 2. often, for unknown reason, reduces the sum
// TODO: implement a more relevant formula
return 2000 * std::max((int)improvement, 1) + 25000;
}
/**
* The organisation is bribed by other org
* @param state - GameState
* @param other - other organisation
* @param bribe - sum of the bribe
* @return - true/false if success/fail
*/
bool Organisation::bribedBy(GameState &state, StateRef<Organisation> other, int bribe)
{
if (bribe <= 0 || other->balance < bribe || bribe < costOfBribeBy(other))
{
return false;
}
float improvement;
float x = this->getRelationTo(other);
if (x < -50) // Hostile
{
improvement = -50.0f - x;
}
else if (x < -25) // Unfriendly
{
improvement = -25.0f - x;
}
else if (x < 25) // Neutral
{
improvement = 25.0f - x;
}
else if (x < 75) // Friendly
{
improvement = 75.0f - x;
}
else // Allied (relationship cannot be improved)
{
return false;
}
other->balance -= bribe;
adjustRelationTo(state, other, improvement);
return true;
}
sp<Organisation> Organisation::get(const GameState &state, const UString &id)
{
auto it = state.organisations.find(id);
@@ -154,6 +154,10 @@ class Organisation : public StateObject
Relation isRelatedTo(const StateRef<Organisation> &other) const;
bool isPositiveTo(const StateRef<Organisation> &other) const;
bool isNegativeTo(const StateRef<Organisation> &other) const;
// Calculate the cost of a bribe.
int costOfBribeBy(const StateRef<Organisation> &other) const;
// The organisation is bribed by other org.
bool bribedBy(GameState &state, StateRef<Organisation> other, int bribe);
float getRelationTo(const StateRef<Organisation> &other) const;
void adjustRelationTo(GameState &state, StateRef<Organisation> other, float value);
std::map<StateRef<Organisation>, float> current_relations;
View
@@ -23,6 +23,7 @@ set (GAMEUI_SOURCE_FILES
city/basebuyscreen.cpp
city/baseselectscreen.cpp
city/bribescreen.cpp
city/buildingscreen.cpp
city/alertscreen.cpp
city/infiltrationscreen.cpp
@@ -86,6 +87,7 @@ set (GAMEUI_HEADER_FILES
city/basebuyscreen.h
city/baseselectscreen.h
city/bribescreen.h
city/buildingscreen.h
city/alertscreen.h
city/infiltrationscreen.h
@@ -0,0 +1,161 @@
#include "game/ui/city/bribescreen.h"
#include "forms/form.h"
#include "forms/label.h"
#include "forms/ui.h"
#include "framework/event.h"
#include "framework/framework.h"
#include "framework/keycodes.h"
#include "game/state/city/city.h"
#include "game/state/gamestate.h"
#include "game/state/shared/organisation.h"
namespace OpenApoc
{
BribeScreen::BribeScreen(sp<GameState> state)
: Stage(), menuform(ui().getForm("city/bribe")), state(state),
organisation(state->current_city->cityViewSelectedOrganisation)
{
}
BribeScreen::~BribeScreen() = default;
/**
* Update info about deal.
*/
void BribeScreen::updateInfo()
{
UString relationship;
UString offer;
bribe = organisation->costOfBribeBy(state->getPlayer());
switch (organisation->isRelatedTo(state->getPlayer()))
{
case Organisation::Relation::Allied:
relationship = ": allied with:";
offer =
tr("X-COM is ALLIED with this organization. The relationship cannot be improved.");
bribe = 0;
break;
case Organisation::Relation::Friendly:
relationship = ": friendly with:";
offer = getOfferString(bribe, tr("ALLIED"));
break;
case Organisation::Relation::Neutral:
relationship = ": neutral towards:";
offer = getOfferString(bribe, tr("FRIENDLY"));
break;
case Organisation::Relation::Unfriendly:
relationship = ": unfriendly towards:";
offer = getOfferString(bribe, tr("NEUTRAL"));
break;
case Organisation::Relation::Hostile:
relationship = ": hostile towards:";
if (organisation->isRelatedTo(state->getAliens()) == Organisation::Relation::Allied)
{
offer = tr("Whilst X-COM continue to oppose our Alien friends we will remain "
"hostile. Negotiations are impossible.");
bribe = 0;
}
else
{
offer = getOfferString(bribe, tr("UNFRIENDLY"));
}
break;
default:
relationship = ": Attitude unknown towards:";
offer = "Unconventional relations";
bribe = 0;
LogError(offer);
}
if (organisation->takenOver)
{
offer = tr("This organization is under Alien control.The Alien race will not enter "
"negotiations with X-COM.");
bribe = 0;
}
labelFunds->setText(state->getPlayerBalance());
labelRelation->setText(format("%s%s X-COM", tr(organisation->name), tr(relationship)));
labelOffer->setText(offer);
}
/**
* Get the offer of a bribe.
* @param itWillCost - the sum of the bribe
* @param newRelation - text of better attitude
* @return - a text of the offer
*/
UString BribeScreen::getOfferString(int itWillCost, const UString &newAttitude) const
{
return format("%s %d %s %s", tr("It will cost: $"), itWillCost,
tr("to improve relations to:"), newAttitude);
}
void BribeScreen::begin()
{
menuform->findControlTyped<Label>("TEXT_DATE")->setText(state->gameTime.getLongDateString());
labelFunds = menuform->findControlTyped<Label>("TEXT_FUNDS");
labelRelation = menuform->findControlTyped<Label>("TEXT_RELATION");
labelOffer = menuform->findControlTyped<Label>("TEXT_OFFER");
updateInfo();
}
void BribeScreen::pause() {}
void BribeScreen::resume() {}
void BribeScreen::finish() {}
void BribeScreen::eventOccurred(Event *e)
{
menuform->eventOccured(e);
if (e->type() == EVENT_KEY_DOWN)
{
switch (e->keyboard().KeyCode)
{
case SDLK_ESCAPE:
case SDLK_RETURN:
fw().stageQueueCommand({StageCmd::Command::POP});
return;
}
}
if (e->type() == EVENT_FORM_INTERACTION && e->forms().EventFlag == FormEventType::ButtonClick)
{
if (e->forms().RaisedBy->Name == "BUTTON_BRIBE")
{
if (bribe > 0)
{
organisation->bribedBy(*state, state->getPlayer(), bribe);
updateInfo();
}
return;
}
if (e->forms().RaisedBy->Name == "BUTTON_QUIT")
{
fw().stageQueueCommand({StageCmd::Command::POP});
return;
}
}
}
void BribeScreen::update() { menuform->update(); }
void BribeScreen::render()
{
fw().stageGetPrevious(this->shared_from_this())->render();
menuform->render();
}
bool BribeScreen::isTransition() { return false; }
}; // namespace OpenApoc
Oops, something went wrong.

0 comments on commit ae86cc2

Please sign in to comment.