00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sstream>
00023 #include <pgimage.h>
00024 #include <pglistboxbaseitem.h>
00025 #include <pgtooltiphelp.h>
00026
00027 #include "../iconrepository.h"
00028 #include "../gamemap.h"
00029 #include "../paradialog.h"
00030 #include "playersetup.h"
00031 #include "alliancesetup.h"
00032 #include "../actions/diplomacycommand.h"
00033 #include "../dialog.h"
00034
00035 const int diplomaticStateIconSize = 20;
00036 const int diplomaticStateIconSpace = 2;
00037
00038
00039 template<typename SelectionType>
00040 int getItemNum() { return 0; };
00041
00042 template<typename SelectionType>
00043 const char* getStateName(int s) { return NULL; };
00044
00045
00046 template<>
00047 int getItemNum<DiplomaticStates>() { return diplomaticStateNum; };
00048
00049 template<>
00050 const char* getStateName<DiplomaticStates>(int s) { return diplomaticStateNames[s]; };
00051
00052
00053 template<>
00054 int getItemNum<AllianceSetupWidget::DiplomaticTransitions>() { return diplomaticStateNum+1; };
00055
00056 template<>
00057 const char* getStateName<AllianceSetupWidget::DiplomaticTransitions>(int s)
00058 {
00059 if ( s == 0 )
00060 return "Sneak Attack";
00061 else
00062 return diplomaticStateNames[s-1];
00063 };
00064
00065
00066 ASCString getDiplomaticStateImage( DiplomaticStates s )
00067 {
00068 ASCString filename = "diplo-" + ASCString::toString(s) + ".png";
00069 return filename;
00070 };
00071
00072 ASCString getDiplomaticStateImage( AllianceSetupWidget::DiplomaticTransitions s )
00073 {
00074 if ( s == AllianceSetupWidget::SNEAK_ATTACK ) {
00075 ASCString filename = "diplo-sneak.png";
00076 return filename;
00077 } else
00078 return getDiplomaticStateImage( DiplomaticStates( s-1 ));
00079 };
00080
00081
00082 template <typename SelectionType>
00083 class ListBoxImageItem : public PG_ListBoxBaseItem {
00084 SelectionType state;
00085 public:
00086 ListBoxImageItem( PG_ListBox *parent, PG_Point pos, SelectionType s ) : PG_ListBoxBaseItem( parent, diplomaticStateIconSize + 2*diplomaticStateIconSpace ), state(s)
00087 {
00088 new PG_Image( this, PG_Point(diplomaticStateIconSpace,diplomaticStateIconSpace), IconRepository::getIcon( getDiplomaticStateImage(s)).getBaseSurface() , false );
00089 new PG_Label( this, PG_Rect(diplomaticStateIconSize + 5, diplomaticStateIconSpace, 200,diplomaticStateIconSize), getStateName<SelectionType>(s));
00090 }
00091
00092 SigC::Signal1<void,SelectionType> sigSet;
00093
00094 bool eventMouseButtonUp(const SDL_MouseButtonEvent* button)
00095 {
00096 if(button->button != 1) {
00097 return false;
00098 }
00099
00100 PG_ListBox* listbox = dynamic_cast<PG_ListBox*>(GetParent());
00101
00102 if(listbox == NULL || !listbox->IsVisible()) {
00103 return true;
00104 }
00105
00106 listbox->SelectItem(this);
00107 listbox->QuitModal();
00108 sigSet(state);
00109
00110 return true;
00111 }
00112 };
00113
00114
00115
00116
00117
00118 template <typename SelectionType>
00119 class DiplomaticModeChooser : public PG_Widget {
00120 SelectionType& mode;
00121 bool writePossible;
00122
00123 protected:
00124
00125 void selectMode()
00126 {
00127 PG_ListBox listBox( NULL, PG_Rect( x, y + Height(), 250, getItemNum<SelectionType>() * ( diplomaticStateIconSpace * 2 + diplomaticStateIconSize ) + 4 ));
00128 for ( int i = 0; i < getItemNum<SelectionType>(); ++i) {
00129 ListBoxImageItem<SelectionType>* item = new ListBoxImageItem<SelectionType>( NULL, PG_Point(0,0), SelectionType(i));
00130 item->sigSet.connect( SigC::slot( *this, &DiplomaticModeChooser::SetState));
00131 listBox.AddChild( item );
00132 }
00133 listBox.Show();
00134 listBox.RunModal();
00135 }
00136
00137 public:
00138 DiplomaticModeChooser ( PG_Widget *parent, const PG_Rect& pos, SelectionType& dm, bool writeable ) : PG_Widget( parent, pos, true ), mode(dm), writePossible( writeable )
00139 {
00140 };
00141
00142 SigC::Signal1<void,SelectionType> sigStateChange;
00143
00144 void eventDraw (SDL_Surface *surface, const PG_Rect &rect)
00145 {
00146 Surface s = Surface::Wrap( surface );
00147 s.Blit( IconRepository::getIcon( getDiplomaticStateImage(mode) ) );
00148 }
00149
00150 void SetState( SelectionType state )
00151 {
00152 mode = state;
00153 Redraw();
00154 Update(true);
00155 sigStateChange(state);
00156 }
00157
00158 bool eventMouseButtonUp(const SDL_MouseButtonEvent* button)
00159 {
00160 if (button->button != 1) {
00161 return false;
00162 }
00163
00164 if ( writePossible )
00165 selectMode();
00166 return true;
00167 }
00168 };
00169
00170
00171 AllianceSetupWidget::AllianceSetupWidget( GameMap* gamemap, ApplyStrategy* applyStrategy, bool allEditable, PG_Widget *parent, const PG_Rect &r, const std::string &style )
00172 : PG_ScrollWidget( parent, r, style ) , actmap ( gamemap ), strategy( applyStrategy )
00173
00174 {
00175 this->allEditable = allEditable;
00176 int playerNum = 0;
00177
00178 for ( int i = 0; i < actmap->getPlayerCount(); ++i ) {
00179 vector<DiplomaticTransitions> t;
00180 vector< DiplomaticStates > s;
00181
00182 const DiplomaticStateVector& diplo = actmap->player[i].diplomacy;
00183
00184 for ( int j = 0; j < actmap->getPlayerCount(); ++j ) {
00185 DiplomaticStateVector::QueuedStateChanges::const_iterator change = diplo.queuedStateChanges.find(j);
00186 if ( change != diplo.queuedStateChanges.end() )
00187 t.push_back( DiplomaticTransitions( change->second + 1 ));
00188 else
00189 t.push_back( DiplomaticTransitions( diplo.getState(j) + 1 ));
00190 s.push_back( diplo.getState(j));
00191 }
00192
00193 stateChanges.push_back ( t );
00194 states.push_back ( s );
00195
00196 if ( actmap->player[i].exist() )
00197 ++playerNum;
00198 }
00199
00200
00201 const int colWidth = 40;
00202 const int lineHeight = 30;
00203 const int barSpace = 5;
00204 const int spacing = 10;
00205 const int nameLength = 200;
00206 const int barOverhang = 20;
00207 const int sqaureWidth = lineHeight;
00208 const int lineLength = sqaureWidth + nameLength + playerNum * (colWidth + spacing) + barOverhang;
00209 const int colHeight = barOverhang + playerNum * (lineHeight + spacing) - spacing + barOverhang;
00210
00211 #define calcx(counter) (sqaureWidth + nameLength + spacing + counter * (colWidth + spacing) )
00212 #define calcy(counter) (barOverhang + counter * (lineHeight + spacing))
00213
00214 int counter = 0;
00215 for ( int i = 0; i < actmap->getPlayerCount(); ++i )
00216 if ( actmap->player[i].exist() ) {
00217 int x = calcx(counter);
00218
00219 ColoredBar* verticalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( x, 0, colWidth, colHeight ));
00220 verticalBar->SetTransparency( 128 );
00221
00222 ++counter;
00223 }
00224
00225
00226 counter = 0;
00227 for ( int i = 0; i < actmap->getPlayerCount(); ++i )
00228 if ( actmap->player[i].exist() ) {
00229
00230 PlayerWidgets pw;
00231 pw.pos = i;
00232
00233 int y = calcy(counter);
00234
00235 ColoredBar* horizontalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( 0, y, lineLength, lineHeight ));
00236 horizontalBar->SetTransparency( 128 );
00237
00238 pw.name = new PG_LineEdit( horizontalBar, PG_Rect( sqaureWidth, barSpace, nameLength, lineHeight-2*barSpace ));
00239 pw.name->SetText( actmap->player[i].getName());
00240 pw.name->SetEditable( false );
00241
00242 new PG_ToolTipHelp( pw.name, "Position: " + ASCString::toString(i) );
00243
00244 PG_ThemeWidget* col = new PG_ThemeWidget( horizontalBar, PG_Rect( barSpace, barSpace, sqaureWidth - 2*barSpace, lineHeight - 2*barSpace ));
00245 col->SetSimpleBackground(true);
00246 col->SetBackgroundColor ( actmap->player[i].getColor());
00247 col->SetBorderSize(0);
00248
00249 int cnt2 = 0;
00250 for ( int j = 0; j < actmap->getPlayerCount(); ++j )
00251 if ( actmap->player[j].exist() ) {
00252 if ( i != j ) {
00253 int x = calcx(cnt2) - barSpace;
00254 PG_Rect rect ( x + (colWidth - diplomaticStateIconSize)/2 , (lineHeight - diplomaticStateIconSize)/2,diplomaticStateIconSize,diplomaticStateIconSize);
00255 if ( allEditable ) {
00256 DiplomaticModeChooser<DiplomaticStates>* dmc = new DiplomaticModeChooser<DiplomaticStates>( horizontalBar, rect, getState(i,j), true );
00257 dmc->sigStateChange.connect( SigC::bind( SigC::slot( *this, &AllianceSetupWidget::setState ), j, i));
00258 diplomaticWidgets[ linearize( i,j) ] = dmc;
00259 } else {
00260 DiplomaticTransitions& s = stateChanges[i][j];
00261 DiplomaticModeChooser<DiplomaticTransitions>* dmc = new DiplomaticModeChooser<DiplomaticTransitions>( horizontalBar, rect, s, i == gamemap->actplayer );
00262
00263 diplomaticWidgets[ linearize( i,j) ] = dmc;
00264 }
00265
00266 }
00267 ++cnt2;
00268 }
00269
00270 playerWidgets.push_back( pw );
00271
00272 ++counter;
00273 }
00274
00275 SetTransparency(255);
00276 };
00277
00278
00279 void AllianceSetupWidget::setState( DiplomaticStates s, int actingPlayer, int secondPlayer )
00280 {
00281 getState( actingPlayer, secondPlayer) = s;
00282
00283 DiplomaticWidgets::iterator i = diplomaticWidgets.find( linearize( actingPlayer, secondPlayer) );
00284 if ( i != diplomaticWidgets.end() )
00285 i->second->Redraw(true);
00286 }
00287
00288 DiplomaticStates& AllianceSetupWidget::getState( int actingPlayer, int secondPlayer )
00289 {
00290 return states.at(actingPlayer).at(secondPlayer);
00291 }
00292
00293 int AllianceSetupWidget::linearize( int actingPlayer, int secondPlayer )
00294 {
00295 return actingPlayer * actmap->getPlayerCount() + secondPlayer;
00296 }
00297
00298
00299 void AllianceSetupWidget::Apply()
00300 {
00301 for ( int acting = 0; acting < actmap->getPlayerCount(); ++acting )
00302 for ( int second = 0; second < actmap->getPlayerCount(); ++second ) {
00303
00304 if ( allEditable ) {
00305 if ( getState( acting, second ) != actmap->player[acting].diplomacy.getState( second ))
00306 actmap->player[acting].diplomacy.setState( second, getState( acting, second ));
00307 } else {
00308 if ( acting == actmap->actplayer ) {
00309 if ( stateChanges[acting][second] == SNEAK_ATTACK ) {
00310 strategy->sneakAttack( actmap, acting, second );
00311 } else {
00312 DiplomaticStates s = DiplomaticStates( stateChanges[acting][second] - 1);
00313 DiplomaticStates t;
00314 DiplomaticStateVector::QueuedStateChanges::iterator q = actmap->player[acting].diplomacy.queuedStateChanges.find( second );
00315 if ( q == actmap->player[acting].diplomacy.queuedStateChanges.end() )
00316 t = getState( acting, second );
00317 else
00318 t = q->second;
00319
00320 if ( t != s ) {
00321 strategy->setState( actmap, acting, second, s );
00322 }
00323 }
00324 }
00325 }
00326 }
00327 };
00328
00329
00330 AllianceSetupWidget::~AllianceSetupWidget()
00331 {
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 class AllianceSetupWindow : public ASC_PG_Dialog {
00344 AllianceSetupWidget* asw;
00345 bool changed;
00346 public:
00347 AllianceSetupWindow( GameMap* actmap, AllianceSetupWidget::ApplyStrategy* strategy, bool allEditable, PG_Widget *parent, const PG_Rect &r ) : ASC_PG_Dialog( parent, r, "Diplomacy" ), changed(false)
00348 {
00349 asw = new AllianceSetupWidget( actmap, strategy, allEditable, this, PG_Rect( 5, 30, r.Width() - 10, r.Height() - 60 ));
00350 PG_Button* ok = new PG_Button( this, PG_Rect( Width() - 200, Height() - 30, 90, 20 ), "OK" );
00351 ok->sigClick.connect( SigC::slot( *this, &AllianceSetupWindow::Apply ));
00352 PG_Button* cancel = new PG_Button( this, PG_Rect( Width() - 100, Height() - 30, 90, 20 ), "Cancel" );
00353 cancel->sigClick.connect( SigC::slot( *this, &AllianceSetupWindow::QuitModal ));
00354 }
00355
00356 bool Apply()
00357 {
00358 asw->Apply();
00359 QuitModal();
00360 changed = true;
00361 return true;
00362 }
00363
00364 bool isSomethingChanged() { return changed; };
00365
00366 };
00367
00368 bool setupalliances( GameMap* actmap, AllianceSetupWidget::ApplyStrategy* strategy, bool supervisor )
00369 {
00370 AllianceSetupWindow asw ( actmap, strategy, supervisor, NULL, PG_Rect( 100, 100, 700, 500 ));
00371 asw.Show();
00372 asw.RunModal();
00373 return asw.isSomethingChanged();
00374 }
00375
00376 void DirectAllianceSetupStrategy::sneakAttack ( GameMap* map, int actingPlayer, int towardsPlayer )
00377 {
00378 map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, WAR );
00379 }
00380
00381
00382 void DirectAllianceSetupStrategy::setState ( GameMap* map, int actingPlayer, int towardsPlayer, DiplomaticStates newState )
00383 {
00384 map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, newState );
00385 }