00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "fack.hpp"
00020 #include <boost/filesystem/operations.hpp>
00021 #include <boost/filesystem/fstream.hpp>
00022
00023 #include <SDL/SDL_gfxPrimitives.h>
00024
00025 #include <stdio.h>
00026 #include <algorithm>
00027
00028
00029
00030 #include <assert.h>
00031
00032
00033 cfsurf::cfsurf(int apparent_wt_, int apparent_ht_,
00034 int real_wt_, int real_ht_, int offset_x_, int offset_y_)
00035 {
00036 apparent_wt = apparent_wt_;
00037 apparent_ht = apparent_ht_;
00038 real_wt = real_wt_;
00039 real_ht = real_ht_;
00040 offs_y = offset_y_;
00041 offs_x = offset_x_;
00042 pixels.resize(real_wt_ * real_ht_);
00043 }
00044
00045
00046
00047
00048 string string_of_int(int i){
00049 std::ostringstream temp;
00050 temp << i;
00051 return temp.str();
00052 }
00053
00054
00055
00056 void raise_exception(string s){
00057 cerr << s << endl;
00058 throw s;
00059 }
00060
00061
00062 bool
00063 point_in_rect(int_pair p, SDL_Rect r)
00064 {
00065 return (r.x <= p.x && p.x<r.x+r.w
00066 &&
00067 r.y <=p.y && p.y <r.y + r.h);
00068 }
00069
00071 Uint32
00072 get_raw_pixel_32bitpp(SDL_Surface * s, int x, int y)
00073 {
00074
00075 int bpp;
00076 Uint32 * ptr;
00077 SDL_PixelFormat * f;
00078
00079
00080
00081 if(x >= s->w)
00082 raise_exception("x out of range");
00083 if(y >= s->h){
00084 cerr << " y = " << y << ", ht = " << s->h;
00085 raise_exception(string("get_raw_pixel_32bitpp: y out of range "));}
00086 f = s->format;
00087 bpp = f->BytesPerPixel;
00088 if (bpp != 4){
00089 raise_exception("Only 32 bitpp surfaces supported");}
00090
00091
00092 ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00093 return * ptr;
00094
00095 }
00096
00097 void put_raw_pixel_32bitpp(SDL_Surface * s, int x, int y, Uint32 pixel)
00098 {
00099
00100 int bpp;
00101 Uint32 *p;
00102
00103
00104
00105 if(x <= s->w && y <=s->h){
00106
00107 bpp = s->format->BytesPerPixel;
00108
00109 if (bpp != 4){
00110 raise_exception("Only 32 bitpp surfaces supported");
00111 }
00112
00113 p = (Uint32 *)(s->pixels) + x + y * s->w;
00114 *(Uint32 *)p = pixel;
00115 }
00116 }
00117
00118
00119
00120
00121 inline
00122 void
00123 anim_frame::set_pixel(
00124 int x,
00125 int y,
00126 rgbaf pix)
00127 {
00128
00129
00130
00131 assert(0<= x && x < w);
00132 assert(0<= y && y < h);
00133
00134 pixels[ y * w + x] = pix;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 pt<anim_frame>
00145 anim_frame::from_sdl_surface(
00146 SDL_Surface * s,
00147 int_pair hot_spot,
00148 float duration)
00149 {
00150
00151 pt<anim_frame> ret;
00152 int x, y;
00153 rgbaf pix;
00154 Uint32 raw_pixel;
00155 Uint32 * ptr;
00156 Uint8 r, g,b, a;
00157
00158
00159
00160 assert(s != NULL);
00161 assert(s->format->BytesPerPixel == 4);
00162
00163
00164
00165 ret = NEW( anim_frame(s->w, s->h, hot_spot, duration));
00166 SDL_LockSurface(s);
00167 for(x = 0; x< s->w ; x++){
00168 for ( y = 0 ; y< s->h ; y++){
00169 ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00170 raw_pixel = * ptr;
00171 SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00172 ret->set_pixel( x, y, rgbaf_of_rgbai(r, g,b, a));}}
00173 SDL_UnlockSurface(s);
00174 return ret;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 bool surf_and_weight::operator< (const surf_and_weight& s) const{
00184 return this->surf < s.surf;
00185 }
00186
00187
00188
00189
00190 pt<cfsurf>
00191 cfsurf::from_sdl_surface(SDL_Surface * s)
00192 {
00193
00194 pt<cfsurf> surf;
00195 int x, y;
00196 Uint32 raw_pixel;
00197 Uint32 * ptr;
00198 Uint8 r, g, b, a;
00199 rgbaf pix2;
00200 int real_wt, real_ht, offs_x, offs_y, apparent_wt, apparent_ht;
00201 int lowest_nontransparent_x_found_so_far;
00202 int lowest_nontransparent_y_found_so_far;
00203 int highest_nontransparent_x_found_so_far;
00204 int highest_nontransparent_y_found_so_far;
00205
00206
00207
00208 assert(s != NULL);
00209 assert(s->format->BytesPerPixel == 4);
00210
00211
00212 lowest_nontransparent_y_found_so_far = INT_MAX;
00213 highest_nontransparent_y_found_so_far = INT_MIN;
00214 lowest_nontransparent_x_found_so_far = INT_MAX;
00215 highest_nontransparent_x_found_so_far = INT_MIN;
00216
00217 SDL_LockSurface(s);
00218 for ( x = 0; x < s->w; x++)
00219 {
00220 for (y = 0; y < s->h; y++)
00221 {
00222 ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00223 raw_pixel = * ptr;
00224 SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00225 if (a != 0)
00226 {
00227 if (x < lowest_nontransparent_x_found_so_far){
00228 lowest_nontransparent_x_found_so_far = x;}
00229 if (x > highest_nontransparent_x_found_so_far){
00230 highest_nontransparent_x_found_so_far = x;}
00231 if (y < lowest_nontransparent_y_found_so_far){
00232 lowest_nontransparent_y_found_so_far = y;}
00233 if (y > highest_nontransparent_y_found_so_far){
00234 highest_nontransparent_y_found_so_far = y;}
00235 }
00236 }
00237 }
00238
00239 assert(lowest_nontransparent_y_found_so_far
00240 < highest_nontransparent_y_found_so_far);
00241 assert(lowest_nontransparent_x_found_so_far
00242 < highest_nontransparent_x_found_so_far);
00243
00244 real_wt = highest_nontransparent_x_found_so_far
00245 - lowest_nontransparent_x_found_so_far;
00246 real_ht = highest_nontransparent_y_found_so_far
00247 - lowest_nontransparent_y_found_so_far;
00248 offs_x = lowest_nontransparent_x_found_so_far;
00249 offs_y = lowest_nontransparent_y_found_so_far;
00250 apparent_ht = s->h;
00251 apparent_wt = s->w;
00252
00253 surf = NEW( cfsurf(apparent_wt, apparent_ht
00254 , real_wt, real_ht
00255 , offs_x, offs_y));
00256 for(x = offs_x; x< offs_x + real_wt; x++){
00257 for ( y = offs_y; y< offs_y + real_ht; y++){
00258 ptr = (Uint32 *) (s->pixels) + x + y * s->w;
00259 raw_pixel = * ptr;
00260 SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
00261 pix2 = rgbaf_of_rgbai(r, g, b, a);
00262 surf->set_pixel( x, y, pix2);}}
00263 SDL_UnlockSurface(s);
00264 return surf;
00265 }
00266
00267
00268
00269
00270
00272 int
00273 pow(int base, int exp){
00274
00275 int p;
00276 int count;
00277
00278
00279 p = 1;
00280 for (count = 0; count< exp; count ++){
00281 p *= base;}
00282 return p;
00283 }
00284
00285
00286 template<class S>
00287 set<typename S::key_type>
00288 subset(S s, vector<bool> must_be_included)
00289 {
00290
00291 set<typename S::key_type> ret;
00292 typename S::key_type el;
00293 int i;
00294 typename S::const_iterator i2;
00295
00296
00297
00298 assert(must_be_included.size() >= s.size());
00299
00300
00301 for ( i = 0 , i2 = s.begin() ; i2 != s.end() ; i++, i2++){
00302 if (must_be_included[i]){
00303 el = *i2;
00304 ret.insert(el);}}
00305 return ret;
00306 }
00307
00308 vector<bool>
00309 boolean_representation(int integer)
00310 {
00311
00312 vector<bool> ret;
00313 int num_bits;
00314 int mask, i;
00315
00316
00317 num_bits = sizeof(integer) * 8;
00318 ret.resize(num_bits);
00319 for (i = 0; i < num_bits; i++){
00320 mask = 1 << i;
00321 ret[i] = ((integer & mask) != 0 ); }
00322 return ret;
00323 }
00324
00325
00326 string string_of_boolRepr(vector<bool> v){
00327
00328 string ret;
00329 int i;
00330
00331
00332 ret = "";
00333 for (i = 0; i < v.size(); i++){
00334 if (v[i]){
00335 ret += "1";}
00336 else{
00337 ret += "0";}}
00338 return ret;}
00339
00340
00341
00342
00343 float
00344 scaling_of_char(float char_y,
00345 const room_scaling_data & d)
00346 {
00347
00348 float a, b, tg_alpha;
00349
00350 tg_alpha = (d.scaling_at_y2 - d.scaling_at_y1) / (d.y2 - d.y1);
00351 a = d.scaling_at_y1 - tg_alpha * d.y1;
00352 b = a / tg_alpha;
00353 return (b+ char_y ) * tg_alpha;
00354 }
00355
00356
00357
00358 bool
00359 surf_must_be_printed_before(
00360 const pt<anim_frame_and_pos> c1,
00361 const pt<anim_frame_and_pos> c2)
00362 {
00363
00364
00365 return (c1->position_y < c2->position_y);
00366
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 bool
00580 hot_zone_square::point_in_zone(
00581 int_pair point) const
00582 {
00583 return (this->x1 <= point.x && point.x <this->x2 &&
00584 this->y1 <= point.y && point.y < this->y2);
00585 }
00586
00587 bool
00588 hot_zone_pixel_perfect::point_in_zone(
00589 int_pair point) const
00590 {
00591
00592 rgbaf p;
00593
00594
00595 if ( 0<= point.x && point.x < surf->apparent_wt &&
00596 0<= point.y && point.y < surf->apparent_ht)
00597 {
00598 p = surf->get_pixel( point.x, point.y);
00599 return ( p.a != 0.0f );
00600 }
00601 else
00602 {
00603 return false;
00604 }
00605 }
00606
00607 bool
00608 player_is_closer_to_the_screen(
00609 const pt<PC> c1,
00610 const pt<PC> c2)
00611 {
00612 return (c1->pos.y > c2->pos.y);
00613 }
00614
00615
00616 void
00617 FACK::drop_item(
00618 pt<dragging_state_maybe_dragging_obj> st,
00619 int_pair mouse)
00620 {
00621
00622 list<pt<popup> >::reverse_iterator zo;
00623 int_pair mouse_in_cont_coords, top_left_of_obj_in_cont_coords;
00624 pt<container> cont, co, real_co;
00625 int_pair top_left_of_obj, bottom_right_of_obj;
00626 list<pt<popup> > popups;
00627 int_pair pos;
00628
00629
00630 popups = act_pl->open_popups;
00631 popups.push_front(act_pl->cache);
00632
00633 for(zo = popups.rbegin();
00634 zo != popups.rend();
00635 zo ++)
00636 {
00637 if (pt_cast( *zo, co))
00638 {
00639 mouse_in_cont_coords = mouse - co->position_in_screen;
00640
00641 top_left_of_obj = mouse_in_cont_coords - st->offset_of_mouse_in_obj;
00642 bottom_right_of_obj = top_left_of_obj + int_pair(
00643 st->obj_and_pos.o->get_inv_surf()->w,
00644 st->obj_and_pos.o->get_inv_surf()->h);
00645
00646 if( point_in_rect(top_left_of_obj, co->drop_in_area) &&
00647 point_in_rect(bottom_right_of_obj, co->drop_in_area ))
00648 {
00649 if ( co->can_contain_this_obj(st->obj_and_pos.o)
00650 &&
00651 ( !pt_cast(st->obj_and_pos.o, cont)
00652 ||
00653 ( cont != co
00654 &&
00655 !contains_recursively(cont, co, real_co , pos ) )))
00656 {
00657 if ( st->orig_container == co
00658 ||
00659 st->obj_and_pos.o->can_be_moved_across_containers())
00660 {
00661 co->add_item_in_pos(pos_and<pt<obj_or_concept> >(st->obj_and_pos.o,
00662 top_left_of_obj));
00663 return;
00664 }
00665 else
00666 {
00667 quick_msg = NEW(quick_message("This item cannot be moved across containers."));
00668 break;
00669 }
00670 }
00671 else
00672 {
00673 quick_msg = NEW(quick_message("Item and container incompatible."));
00674 break;
00675 }
00676 }
00677 }
00678 }
00679
00680
00681 st->orig_container->add_item_in_pos(st->obj_and_pos);
00682
00683 }
00684
00685
00686
00687 pt<container_pick_result>
00688 container::item_at_screen_pos(
00689 int_pair screen_pos,
00690 pt<popup> myself_as_a_smart_ptr) const
00691 {
00692
00693 SDL_Rect rect;
00694 list<pos_and<pt<obj_or_concept> > >::const_reverse_iterator i;
00695 int_pair pos_in_item_coords, pos_in_container_coords;
00696 SDL_Surface* surf;
00697 SDL_Surface* surf2;
00698 Uint32 * addr;
00699 Uint32 raw_pix;
00700 Uint8 r, g, b, a;
00701
00702
00703
00704 pos_in_container_coords = screen_pos - this->position_in_screen;
00705
00706 for( i = this->sorted_items.rbegin();
00707 i != this->sorted_items.rend();
00708 i ++)
00709 {
00710 surf = i->o->get_inv_surf();
00711
00712 pos_in_item_coords = pos_in_container_coords - i->pos;
00713
00714 if (0 <= pos_in_item_coords.x && pos_in_item_coords.x < surf->w &&
00715 0 <= pos_in_item_coords.y && pos_in_item_coords.y < surf->h)
00716 {
00717 SDL_LockSurface(surf);
00718 addr = (Uint32 *)(surf->pixels) + pos_in_item_coords.y * surf->w + pos_in_item_coords.x;
00719 raw_pix = * addr;
00720 SDL_GetRGBA(raw_pix, surf->format, &r, &g, &b, &a);
00721 SDL_UnlockSurface(surf);
00722 if (a != 0)
00723 {
00724 return NEW(container_pick_result_obj_and_pos(pos_and<pt<obj_or_concept> >
00725 (i->o, i->pos),
00726 myself_as_a_smart_ptr));
00727 }
00728 }
00729
00730 }
00731
00732
00733 if(var_cast(this->closing_area, rect) && point_in_rect(pos_in_container_coords, rect))
00734 {
00735 return NEW(container_pick_result_closing_area(myself_as_a_smart_ptr));
00736 }
00737 else if(this->can_be_dragged)
00738 {
00739 if (point_in_rect(pos_in_container_coords, this->drop_in_area))
00740 {
00741 return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00742 }
00743 else
00744 {
00745 surf2 = this->picture;
00746
00747 if (0 <= pos_in_container_coords.x && pos_in_container_coords.x < surf2->w &&
00748 0 <= pos_in_container_coords.y && pos_in_container_coords.y < surf2->h)
00749 {
00750 SDL_LockSurface(surf2);
00751 addr = (Uint32 *)(surf2->pixels) + pos_in_container_coords.y * surf2->w +
00752 pos_in_container_coords.x;
00753 raw_pix = * addr;
00754 SDL_GetRGBA(raw_pix, surf2->format, &r, &g, &b, &a);
00755 SDL_UnlockSurface(surf2);
00756 if (a != 0)
00757 {
00758 return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00759 }
00760 }
00761 }
00762 }
00763
00764
00765 return NEW(container_pick_result_void());
00766 }
00767
00769 pt<container_pick_result>
00770 zoomable::item_at_screen_pos(
00771 int_pair screen_pos,
00772 pt<popup> myself_as_a_smart_ptr ) const
00773 {
00774
00775 SDL_Rect rect;
00776 list<pt<zoomable_zone> >::const_reverse_iterator z;
00777 int_pair pos_in_container_coords;
00778 SDL_Surface* surf2;
00779 Uint32 * addr;
00780 Uint32 raw_pix;
00781 SDL_Rect surf_rect;
00782 Uint8 r, g, b, a;
00783
00784
00785 pos_in_container_coords = screen_pos - this->position_in_screen;
00786
00787
00788 surf2 = this->picture;
00789
00790 surf_rect = create_rect(0, 0, surf2->w, surf2->h);
00791
00792 if (point_in_rect(pos_in_container_coords, surf_rect))
00793 {
00794 SDL_LockSurface(surf2);
00795 addr = (Uint32 *)(surf2->pixels) + pos_in_container_coords.y * surf2->w +
00796 pos_in_container_coords.x;
00797 raw_pix = * addr;
00798 SDL_GetRGBA(raw_pix, surf2->format, &r, &g, &b, &a);
00799 SDL_UnlockSurface(surf2);
00800 }
00801
00802
00803
00804
00805 for( z = this->sorted_zones.rbegin();
00806 z != this->sorted_zones.rend();
00807 z ++)
00808 {
00809
00810 if ( (*z)->point_in_zone(pos_in_container_coords)
00811 &&
00812 ( a != 0
00813 ||
00814 !(*z)->intersect_rect_and_picture))
00815 {
00816 return NEW(container_pick_result_obj(
00817 (*z)->obj,
00818 myself_as_a_smart_ptr));
00819 }
00820
00821 }
00822
00823
00824 if(var_cast(this->closing_area, rect) && point_in_rect(pos_in_container_coords, rect))
00825 {
00826 return NEW(container_pick_result_closing_area(myself_as_a_smart_ptr));
00827 }
00828 else
00829 {
00830 if (point_in_rect(pos_in_container_coords, surf_rect)
00831 &&
00832 a != 0)
00833 {
00834 return NEW(container_pick_result_container_drag_area(myself_as_a_smart_ptr));
00835 }
00836
00837 }
00838
00839 return NEW(container_pick_result_void());
00840 }
00841
00842
00843 pt<container_pick_result>
00844 FACK::item_in_popup_at_screen_pos(
00845 int_pair screen_pos) const
00846 {
00847
00848 list<pt<popup> >::reverse_iterator po;
00849 list<pt<popup> > popups;
00850 pt<container> co;
00851 pt<zoomable> zo;
00852 pt<container_pick_result> pick_res;
00853 pt<container_pick_result_void> void_res;
00854
00855
00856 popups = act_pl->open_popups;
00857 popups.push_front(act_pl->cache);
00858
00859 for(po = popups.rbegin();
00860 po != popups.rend();
00861 po++)
00862 {
00863 pick_res = (*po)->item_at_screen_pos(screen_pos, *po);
00864
00865 if(!pt_cast(pick_res, void_res))
00866 {
00867 return pick_res;
00868 }
00869 }
00870 return NEW(container_pick_result_void());
00871
00872 }
00873
00874
00875 variant<no_item, pt<obj_or_concept> >
00876 item_in_room_at_position(
00877 int_pair pos,
00878 list<pt<PC> > players,
00879 const pt<PC> act_pl,
00880 const map<pt<PC>, pt<anim_frame> > & cur_frame_of_player)
00881 {
00882
00883 list<pt<bg_hot_zone> >::const_iterator z;
00884 list<pt<PC> >::const_iterator pl;
00885 pt<PC> item2;
00886 pt<bg_hot_zone> item1;
00887 pt<still_situation_sitting> sitting;
00888 bool must_be_scaled;
00889 float scal;
00890
00891
00892 foreach(z, act_pl->loc->sorted_hot_zones){
00893 if( (*z)->visible && (*z)->point_in_zone(pos))
00894 {
00895 item1 = *z;
00896 break;
00897 }
00898 }
00899
00900 players.sort(player_is_closer_to_the_screen);
00901
00902 foreach(pl, players){
00903
00904 must_be_scaled = !pt_cast((*pl)->still_situat, sitting);
00905
00906 scal = (must_be_scaled?
00907 scaling_of_char( (*pl)->pos.y, act_pl->loc->scaling_data):
00908 1.0f);
00909
00910 if( (*pl) != act_pl
00911 &&
00912 (*pl)->loc == act_pl->loc
00913 &&
00914 map_get(
00915 cur_frame_of_player,
00916 (*pl)) -> point_in_surf( pos,
00917 (*pl)->pos,
00918 scal))
00919 {
00920 item2 = *pl;
00921 break;
00922 }
00923 }
00924
00925 if (item1 && !item2)
00926 {
00927 return item1->obj;
00928 }
00929 else if (item2 && !item1)
00930 {
00931 return item2->obj;
00932 }
00933 else if (item1 && item2)
00934 {
00935 if (item1->y_walkbehind > item2->pos.y)
00936 {
00937
00938 return item1->obj;
00939 }
00940 else
00941 {
00942
00943 return item2->obj;
00944 }
00945 }
00946 else
00947 {
00948 return no_item();
00949 }
00950 }
00951
00952
00953 bool
00954 printable_must_be_printed_before(
00955 const pt<printable> p1,
00956 const pt<printable> p2 )
00957 {
00958 return p1->y() < p2->y();
00959 }
00960
00961
00962 void
00963 render_layers_and_chars_in_correct_order(
00964 list< pt<printable> >& layers_and_chars_except_bg,
00965 cfsurf & bg_surf,
00966 SDL_Surface * screen,
00967 const room_scaling_data& d,
00968 SDL_Rect visible_rect_in_src_surf,
00969 set<pt<light> > active_lights)
00970 {
00971
00972 list<pt<printable> >::const_iterator l;
00973
00974
00975 layers_and_chars_except_bg.sort(printable_must_be_printed_before);
00976
00977 foreach(l, layers_and_chars_except_bg){
00978 (*l)->print_with_transparency(bg_surf, d, active_lights);
00979 }
00980 bg_surf.opaque_blit_to_sdl_surface( screen, visible_rect_in_src_surf);
00981
00982 }
00983
00984
00985
00986 Uint32 choose_some_video_flags(){
00987
00988 const SDL_VideoInfo *videoInfo;
00989 Uint32 videoflags;
00990
00991
00992
00993 videoflags = SDL_DOUBLEBUF;
00994 videoInfo = SDL_GetVideoInfo( );
00995
00996 if ( !videoInfo ){
00997 raise_exception( "Video query failed: " + string(SDL_GetError()));
00998 }
00999 else{
01000 if ( videoInfo->hw_available ){
01001 videoflags |= SDL_HWSURFACE;
01002 cout << "HW Surface available" << endl;
01003 }
01004 else{
01005 videoflags |= SDL_SWSURFACE;
01006 cout << "SW Surface available" << endl;
01007 }
01008 if ( videoInfo->blit_hw ){
01009 videoflags |= SDL_HWACCEL;
01010 cout << "HW ACCEL available" << endl;
01011 }
01012
01013 }
01014
01015 return videoflags;
01016 }
01017
01018
01019
01020 pt<vector2<bool> >
01021 walking_map_from_sdl_surface(SDL_Surface * s)
01022 {
01023
01024 pt<vector2<bool> > m;
01025 int x, y;
01026 rgbaf pix;
01027 Uint32 raw_pixel;
01028 Uint32 * ptr;
01029 Uint8 r, g,b, a;
01030
01031
01032
01033 m = NEW( vector2<bool>(s->w, s->h));
01034 SDL_LockSurface(s);
01035 for (x = 0; x< s->w; x++){
01036 for (y = 0; y< s->h; y++){
01037 ptr = (Uint32 *) (s->pixels) + x + y * s->w;
01038 raw_pixel = * ptr;
01039 SDL_GetRGBA(raw_pixel, s->format, &r, &g, &b, &a);
01040 m->set( x , y, a != 0);
01041 }
01042 }
01043 SDL_UnlockSurface(s);
01044 return m;}
01045
01046
01047 bool
01048 is_walkable
01049 ( const vector2<bool>& walking_map, int x, int y)
01050 {
01051 if ( 0 <= x && x < walking_map.w
01052 &&
01053 0 <= y && y < walking_map.h)
01054 {
01055 return walking_map.get( x , y);
01056 }
01057 else
01058 {
01059 return false;
01060 }
01061
01062 }
01063
01064 namespace path_finding{
01065
01066
01067 bool int_pair::operator==(const int_pair& p) const{
01068 return ( x == p.x && y == p.y);
01069 }
01070 bool int_pair::operator<(const int_pair& p) const{
01071 if(x < p.x)
01072 return true;
01073 else if (x > p.x){
01074 return false;}
01075 else{
01076 if ( y < p.y){
01077 return true;}
01078 else if (y > p.y){
01079 return false;}
01080 else{
01081 return false;}}}
01082
01083 struct frontier_node{
01084 int_pair position;
01085 int cost_g;
01086 float cost_h;
01087
01088 frontier_node(int_pair position, int cost_g, float cost_h){
01089 this->position = position;
01090 this->cost_h = cost_h;
01091 this->cost_g = cost_g;}
01092 frontier_node(){}
01093 };
01094
01095
01096 struct int_pair_and_cost{
01097 int_pair pair;
01098 int cost;
01099 int_pair_and_cost(int_pair pair, int cost){
01100 this->pair = pair;
01101 this->cost = cost;}
01102 };
01103
01104 list<int_pair_and_cost>
01105 neighbours( int_pair node)
01106 {
01107
01108 list<int_pair_and_cost> ret;
01109
01110
01111 ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y), 10));
01112 ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y), 10));
01113 ret.push_back(int_pair_and_cost(int_pair(node.x, node.y-1), 10));
01114 ret.push_back(int_pair_and_cost(int_pair(node.x, node.y+1), 10));
01115 ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y-1), 11));
01116 ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y+1), 11));
01117 ret.push_back(int_pair_and_cost(int_pair(node.x+1, node.y-1), 11));
01118 ret.push_back(int_pair_and_cost(int_pair(node.x-1, node.y+1), 11));
01119 return ret;
01120 }
01121
01122 float
01123 distance( int_pair p1, int_pair p2){
01124
01125 float x, y;
01126
01127
01128 x = float(p1.x - p2.x);
01129 y = float(p1.y - p2.y);
01130 return sqrt( x * x + y * y);
01131 }
01132
01133
01134 bool
01135 compare_frontier_nodes(const frontier_node& f1,
01136 const frontier_node& f2){
01137 return f1.cost_g + f1.cost_h < f2.cost_g + f2.cost_h;
01138
01139 }
01140
01141 bool
01142 int_pair__equal(int_pair p1, int_pair p2){
01143 return p1.x == p2.x && p1.y == p2.y;}
01144
01145 string
01146 string_of_int_pair(int_pair p){
01147 string ret;
01148 ret = string_of_int(p.x);
01149 ret += ", " + string_of_int(p.y);
01150 return ret;
01151 }
01152
01153 struct no_route_found{};
01154
01157 variant<no_route_found, pt<list<int_pair> > >
01158 best_route(
01159 int_pair from,
01160 int_pair to,
01161 const vector2<bool>& walkable)
01162 {
01163
01164 pt<list<int_pair> > route;
01165 list<int_pair>::const_iterator it;
01166
01167 vector<int_pair> route2;
01168 list<frontier_node> frontier, nei3;
01169 frontier_node chosen_node;
01170 vector2<bool> visited;
01171 list<int_pair_and_cost> nei;
01172 list<int_pair_and_cost> nei2;
01173 list<int_pair_and_cost>::const_iterator n;
01174 int_pair nn;
01175 map<int_pair, int_pair> parent_of;
01176 map<int_pair, int_pair>::const_iterator parent_it;
01177
01178
01179
01180 assert( walkable.get(from.x, from.y));
01181 assert( walkable.get(to.x, to.y));
01182
01183
01184 if (from == to)
01185 {
01186 return pt<list<int_pair> >();
01187 }
01188 else
01189 {
01190
01191 visited = vector2<bool>(walkable.w, walkable.h);
01192 visited.fill_with(false);
01193 frontier.push_back(frontier_node(
01194 from, 0,
01195 100 ));
01196 visited.set(from.x, from.y, true);
01197
01198 while(true)
01199 {
01200 if (frontier.empty())
01201 {
01202 return no_route_found();
01203 }
01204 else
01205 {
01206 chosen_node = frontier.front();
01207 frontier.pop_front();
01208
01209 if (int_pair__equal(chosen_node.position, to))
01210 {
01211 nn = to;
01212 route = NEW( list<int_pair>());
01213 route->push_front(nn);
01214 while(! int_pair__equal( nn,from))
01215 {
01216 parent_it = parent_of.find(nn);
01217 assert(parent_it != parent_of.end());
01218 nn = parent_it->second;
01219 route->push_front(nn);
01220 }
01221 assert(route->front() == from);
01222 route->pop_front();
01223 return route;
01224 }
01225 else
01226 {
01227 nei = neighbours(chosen_node.position);
01228
01229 setof( n,
01230 nei,
01231 ( n->pair.x >= 0 && n->pair.x <walkable.w
01232 &&
01233 n->pair.y >= 0 && n->pair.y <walkable.h
01234 &&
01235 ! visited.get( n->pair.x, n->pair.y)
01236 &&
01237 walkable.get( n->pair.x, n->pair.y) ),
01238 nei2);
01239
01240 foreach(n, nei2){
01241 assert(!visited.get( n->pair.x, n->pair.y));
01242 visited.set(n->pair.x, n->pair.y, true);
01243 parent_of[n->pair] = chosen_node.position;
01244 }
01245
01246 setof_( frontier_node(n->pair ,
01247 chosen_node.cost_g + n->cost ,
01248 distance(n->pair, to) ),
01249 n,
01250 nei2,
01251 true,
01252 nei3);
01253
01254 nei3.sort(compare_frontier_nodes);
01255 frontier.merge(nei3, compare_frontier_nodes);
01256 }
01257 }
01258 }
01259 assert(false);
01260 }
01261 }
01262 };
01263
01264
01265
01266 using path_finding::best_route;
01267 using path_finding::no_route_found;
01268
01269
01270
01271
01272 bool
01273 walk_frame_id::operator< (
01274 const walk_frame_id& w)const
01275 {
01276 if (dir < w.dir)
01277 {
01278 return true;
01279 }
01280 else if (dir > w.dir)
01281 {
01282 return false;
01283 }
01284 else
01285 {
01286 if (foot < w.foot)
01287 {
01288 return true;
01289 }
01290 else if (foot > w.foot)
01291 {
01292 return false;
01293 }
01294 else
01295 {
01296 if (phase < w.phase)
01297 {
01298 return true;
01299 }
01300 else
01301 {
01302 return false;
01303 }
01304 }
01305 }
01306 }
01307
01308
01309
01310
01311 pt<list<int_pair> >
01312 compute_feet_positions(
01313 int_pair start_position,
01314 const list<int_pair>& route,
01315 const room_scaling_data& scaling_data,
01316 float walk_step_horiz,
01317 float walk_step_vert)
01318 {
01319
01320 pt<list<int_pair> > route2;
01321 int_pair new_candidate, latest_certain_foot_pos;
01322 list<int_pair>::const_iterator route_it;
01323 float scal_of_cur_step, delta_x, delta_y;
01324
01325
01326
01327 assert(route.size()>0);
01328 assert(! (route.front() == start_position));
01329
01330
01331 route2 = NEW( list<int_pair>());
01332
01333 latest_certain_foot_pos = start_position;
01334 route_it = route.begin();
01335
01336 scal_of_cur_step = scaling_of_char(float(latest_certain_foot_pos.y), scaling_data);
01337
01338 do
01339 {
01340 new_candidate = *route_it;
01341
01342
01343 delta_x = float(std::abs(new_candidate.x - latest_certain_foot_pos.x));
01344 delta_y = float(std::abs(new_candidate.y - latest_certain_foot_pos.y));
01345
01346 if(delta_x > scal_of_cur_step * walk_step_horiz ||
01347 delta_y > scal_of_cur_step * walk_step_vert)
01348 {
01349 latest_certain_foot_pos = new_candidate;
01350 route2->push_back(latest_certain_foot_pos);
01351 scal_of_cur_step = scaling_of_char(float(latest_certain_foot_pos.y), scaling_data);
01352 }
01353
01354 route_it ++;
01355 if(route_it == route.end())
01356 {
01357 break;
01358 }
01359
01360 }while(true);
01361
01362 if(!(latest_certain_foot_pos == route.back()))
01363 {
01364 route2->push_back(route.back());
01365 }
01366 return route2;
01367 }
01368
01369
01370
01371
01372
01373 direction
01374 compute_dir(int_pair p1, int_pair p2, float walk_step_horiz)
01375 {
01376
01377
01378 if(p2.x - p1.x >= walk_step_horiz * 0.8f ){
01379 return d_right;}
01380 else if (p1.x - p2.x >= walk_step_horiz * 0.8f){
01381 return d_left;}
01382 else{
01383 if(p2.y < p1.y){
01384 return d_up;}
01385 else if (p2.y > p1.y){
01386 return d_down;}
01387 else{
01388 if(p2.x < p1.x){
01389 return d_left;}
01390 else if (p2.x > p1.x){
01391 return d_right;}
01392
01393 }
01394
01395
01396 }
01397
01398 }
01399
01400
01401
01402 struct walking_finished{};
01403
01404 variant<walking_finished, pair<int_pair, direction> >
01405 update_walking_animation(
01406 float frame_change_interval,
01407 pt<AI_substate_walk> state_walk,
01408 int_pair player_pos,
01409 float walk_step_horiz,
01410 float dt,
01411 direction cur_dir)
01412 {
01413
01414 int_pair new_pos;
01415
01416
01417 state_walk->timer += dt;
01418
01419 if (state_walk->timer <= frame_change_interval)
01420 {
01421 return make_pair(player_pos, cur_dir);
01422 }
01423 else{
01424 state_walk->timer -= frame_change_interval;
01425
01426
01427
01428
01429
01430 if (state_walk->cur_phase == RECOIL)
01431 {
01432 state_walk->cur_phase = PASSING;
01433 return make_pair(player_pos, cur_dir);
01434 }
01435 else if (state_walk->cur_phase == PASSING)
01436 {
01437
01438 state_walk->cur_phase = CONTACT;
01439 return make_pair(player_pos, cur_dir);
01440 }
01441 else if (state_walk->cur_phase == CONTACT){
01442
01443 state_walk->cur_phase = RECOIL;
01444
01445
01446
01447 if(state_walk->cur_foot == hd_right){
01448 state_walk->cur_foot = hd_left;}
01449 else{
01450 state_walk->cur_foot = hd_right;}
01451
01452
01453 if (state_walk->cur_pos >= state_walk->route.size()){
01454 return walking_finished();
01455 }
01456 else{
01457 new_pos = state_walk->route[state_walk->cur_pos];
01458
01459 state_walk->cur_pos ++;
01460
01461 return make_pair(new_pos,
01462 compute_dir(player_pos, new_pos, walk_step_horiz));
01463 }
01464
01465 }
01466
01467 }
01468
01469
01470 }
01471
01472 list<SDL_Event>
01473 get_sdl_events()
01474 {
01475
01476 list<SDL_Event> ret;
01477 SDL_Event ev;
01478
01479
01480 while(SDL_PollEvent(&ev)){
01481 ret.push_back(ev);}
01482
01483 return ret;
01484
01485 }
01486
01487
01488
01489
01490
01491
01492
01493 namespace text{
01494
01495 bool
01496 is_alnum(char c)
01497 {
01498 return ( 65 <= c && c <=90
01499 ||
01500 97 <= c && c <= 122);
01501 }
01502
01503 list<string>
01504 tokenize(string t)
01505 {
01506
01507 list<string> ret;
01508 int i;
01509 char c;
01510 string cur_word;
01511 bool previous_was_alnum;
01512
01513
01514 cur_word = "";
01515 previous_was_alnum = true;
01516 for (i = 0; i < t.size(); i++){
01517 c = t[i];
01518 if (is_alnum(c)){
01519 if (previous_was_alnum){
01520 cur_word += c;}
01521 else{
01522 ret.push_back(cur_word);
01523 cur_word = "";
01524 cur_word += c;
01525 previous_was_alnum = true;}}
01526 else{
01527 cur_word += c;
01528 ret.push_back(cur_word);
01529 cur_word = "";
01530 previous_was_alnum = false;
01531 }
01532 }
01533 if (cur_word != ""){
01534 ret.push_back(cur_word);}
01535 return ret;
01536 }
01537
01538 int
01539 text_wt_in_pixels(string s,
01540 const surf_of_letter_t & surf_of_letter)
01541 {
01542
01543 int wt; int i;
01544
01545
01546 wt = 0;
01547 for (i = 0; i<s.size(); i++){
01548 wt += map_get(surf_of_letter, s[i])->w;
01549 }
01550 return wt;
01551 }
01552
01553 void
01554 print_letter(
01555 SDL_Surface * l,
01556 SDL_Surface * screen,
01557 int_pair dest_pos,
01558 rgb col)
01559 {
01560
01561 int x, y;
01562 Uint32* dest_addr, *src_addr;
01563 Uint32 raw_pix;
01564 Uint8 r, g, b, a;
01565
01566
01567
01568 assert(screen->format->BytesPerPixel == 4);
01569 assert(l->format->BytesPerPixel == 4);
01570
01571
01572 SDL_LockSurface(screen);
01573 SDL_LockSurface(l);
01574 for (x = 0; x < l->w ; x++)
01575 {
01576 for (y = 0; y < l->h ; y++)
01577 {
01578 src_addr = (Uint32 *) (l->pixels) + x + y * l->w;
01579 raw_pix = *src_addr;
01580
01581 SDL_GetRGBA(raw_pix, l->format, &r, &g, &b, &a);
01582
01583 dest_addr = (Uint32 *) (screen->pixels) + (dest_pos.x + x) + (dest_pos.y + y) * screen->w;
01584 if(a == 0)
01585 {
01586 }
01587 else if (r==0)
01588 {
01589 * dest_addr = SDL_MapRGB(screen->format , r, g, b);
01590 }
01591 else
01592 {
01593 * dest_addr = SDL_MapRGB(screen->format , col.r, col.g, col.b);
01594 }
01595 }
01596 }
01597 SDL_UnlockSurface(screen);
01598 SDL_UnlockSurface(l);
01599 }
01600
01602 int
01603 print_line_of_text(string t, int x, int y,
01604 const surf_of_letter_t & surf_of_letter,
01605 SDL_Surface * screen,
01606 bool calc_wt_only,
01607 rgb col)
01608 {
01609
01610 int i, cur_x;
01611 SDL_Rect dest_rect;
01612 char c;
01613
01614
01615 cur_x = x;
01616
01617 for (i = 0; i< t.size(); i++)
01618 {
01619 dest_rect.y = y;
01620 dest_rect.x = cur_x;
01621
01622 c = t[i];
01623
01624 if (!calc_wt_only)
01625 {
01626
01627
01628
01629
01630 print_letter(
01631 map_get(surf_of_letter, c),
01632 screen,
01633 int_pair(cur_x, y),
01634 col);
01635 }
01636
01637 cur_x += map_get(surf_of_letter, c)->w;
01638 }
01639 return cur_x - x;
01640 }
01641
01642 void
01643 print_x_centered_line_of_text(string t, int x_min, int x_max, int y,
01644 const surf_of_letter_t & surf_of_letter,
01645 SDL_Surface * screen, rgb col)
01646 {
01647
01648 int avail_wt, wt, final_x;
01649
01650 avail_wt = x_max - x_min;
01651 wt = print_line_of_text(t, x_min, y, surf_of_letter, screen, true, col);
01652 assert(wt < avail_wt);
01653
01654 final_x = x_min + (avail_wt - wt)/2;
01655 print_line_of_text(t, final_x, y, surf_of_letter, screen, false, col);
01656
01657 }
01658
01659 int
01660 draw_text_multiline_variable_ht(string text,
01661 SDL_Surface* surf,
01662 int x_left,
01663 int y_top,
01664 int x_right,
01665 const surf_of_letter_t & surf_of_letter,
01666 bool calc_ht_only,
01667 rgb col)
01668 {
01669
01670 int cur_line_wt;
01671 list<string>::const_iterator t;
01672 int w;
01673 int avail_wt;
01674 list<string> tokens;
01675 string cur_line;
01676 int ht;
01677 char random_letter;
01678
01679
01680 tokens = tokenize(text);
01681 avail_wt = x_right - x_left;
01682 assert(avail_wt > 0);
01683 random_letter = text[0];
01684 cur_line_wt = 0;
01685 cur_line = "";
01686 ht = 0;
01687 foreach( t, tokens){
01688 w = text_wt_in_pixels(*t, surf_of_letter);
01689 assert(w < avail_wt );
01690 if (cur_line_wt + w < avail_wt){
01691 cur_line_wt +=w;
01692 cur_line += *t;
01693 }
01694 else{
01695
01696 if (!calc_ht_only)
01697 {
01698 print_x_centered_line_of_text(cur_line, x_left, x_right, y_top + ht, surf_of_letter, surf, col);
01699 }
01700 ht += map_get(surf_of_letter, random_letter)->h;
01701
01702
01703 cur_line = "";
01704 cur_line += *t;
01705 cur_line_wt = w;
01706 }
01707 }
01708
01709 if (cur_line != ""){
01710
01711 if (!calc_ht_only){
01712 print_x_centered_line_of_text(cur_line, x_left, x_right, y_top + ht, surf_of_letter, surf, col);}
01713 ht += map_get(surf_of_letter, random_letter)->h;
01714
01715
01716 }
01717 return ht;
01718 }
01719 };
01720
01721 using text::draw_text_multiline_variable_ht;
01722 using text::print_line_of_text;
01723 using text::print_x_centered_line_of_text;
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743 void
01744 FACK::render_command_bar(
01745 int_pair mouse_screen,
01746 int_pair mouse_bg,
01747 const map<pt<PC>, pt<anim_frame> > & cur_frame_of_player) const
01748 {
01749
01750 SDL_Rect dest_rect;
01751 pt<PS_missing_one_item> missing_one;
01752 pt<PS_missing_two_items> missing_two;
01753 variant<no_item, pt<obj_or_concept> > ret2;
01754 pt<obj_or_concept> item;
01755 string selected_item_text;
01756 rgb text_color_of_command_bar(120, 140, 200);
01757 Uint32 bg_color_of_command_bar;
01758 pt<game_state_flashing_inv_t> flashing;
01759 pt<container_pick_result> pick_res;
01760 pt<container_pick_result_obj_and_pos> obj_and_pos;
01761 pt<container_pick_result_obj> obj;
01762 pt<container_pick_result_container_drag_area> container_drag_area;
01763 pt<container_pick_result_closing_area> closing_area;
01764 special_button_pick_result special_but;
01765
01766
01767 bg_color_of_command_bar = SDL_MapRGB(screen->format, 10,10,15);
01768
01769
01770 dest_rect.x = 0;
01771 dest_rect.y = screen->h - act_pl->cache->picture->h - calc_command_bar_ht();
01772 dest_rect.w = screen->w;
01773 dest_rect.h = calc_command_bar_ht();
01774 SDL_FillRect(screen, &dest_rect, bg_color_of_command_bar);
01775
01776 if(!pt_cast(game_state, flashing))
01777 {
01778
01779 special_but = special_button_at_pos(mouse_screen);
01780 if(special_but == SBPR_STAY_FOLLOW)
01781 {
01782 selected_item_text = "stay/follow";
01783
01784 print_x_centered_line_of_text(
01785 selected_item_text,
01786 0, screen->w,
01787 screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01788 surf_of_letter,
01789 screen,
01790 text_color_of_command_bar);
01791 }
01792 else if (special_but == SBPR_CYCLE_PLAYER)
01793 {
01794 selected_item_text = "switch active player";
01795
01796 print_x_centered_line_of_text(
01797 selected_item_text,
01798 0, screen->w,
01799 screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01800 surf_of_letter,
01801 screen,
01802 text_color_of_command_bar);
01803
01804 }
01805 else if (special_but == SBPR_SAVE_LOAD)
01806 {
01807 selected_item_text = "Options";
01808
01809 print_x_centered_line_of_text(
01810 selected_item_text,
01811 0, screen->w,
01812 screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01813 surf_of_letter,
01814 screen,
01815 text_color_of_command_bar);
01816
01817 }
01818 else
01819 {
01820 pick_res = item_in_popup_at_screen_pos(mouse_screen);
01821
01822 ret2 = item_in_room_at_position(
01823 mouse_bg,
01824 players, act_pl, cur_frame_of_player);
01825
01826 if( pt_cast(act_pl->state, missing_one))
01827 {
01828 if( pt_cast(pick_res, obj_and_pos) &&
01829 obj_and_pos->obj_and_pos.o != missing_one->obj_already_chosen)
01830 {
01831 selected_item_text = obj_and_pos->obj_and_pos.o->readable_name;
01832 }
01833 else if( pt_cast(pick_res, obj) &&
01834 obj->obj != missing_one->obj_already_chosen)
01835 {
01836 selected_item_text = obj->obj->readable_name;
01837 }
01838 else if(pt_cast(pick_res, container_drag_area) ||
01839 pt_cast(pick_res, closing_area))
01840 {
01841 selected_item_text = "";
01842 }
01843 else if ( var_cast(ret2, item)
01844 &&
01845 item != missing_one->obj_already_chosen)
01846 {
01847 selected_item_text = item->readable_name;
01848 }
01849 else{
01850 selected_item_text = "...";
01851 }
01852
01853 print_x_centered_line_of_text(
01854 missing_one->obj_already_chosen->readable_name + " + " + selected_item_text,
01855 0, screen->w,
01856 screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01857 surf_of_letter,
01858 screen,
01859 text_color_of_command_bar);
01860 }
01861 else if (pt_cast(act_pl->state, missing_two))
01862 {
01863 if(pt_cast(pick_res, obj_and_pos))
01864 {
01865 selected_item_text = obj_and_pos->obj_and_pos.o->readable_name;
01866 }
01867 else if(pt_cast(pick_res, obj))
01868 {
01869 selected_item_text = obj->obj->readable_name;
01870 }
01871 else if(pt_cast(pick_res, container_drag_area) ||
01872 pt_cast(pick_res, closing_area))
01873 {
01874 selected_item_text = "";
01875 }
01876 else if ( var_cast(ret2, item) )
01877 {
01878 selected_item_text = item->readable_name;
01879 }
01880 else
01881 {
01882 selected_item_text = "";
01883 }
01884 print_x_centered_line_of_text(
01885 selected_item_text,
01886 0, screen->w,
01887 screen->h - calc_command_bar_ht() - act_pl->cache->picture->h +1,
01888 surf_of_letter,
01889 screen,
01890 text_color_of_command_bar);
01891 }
01892 }
01893 }
01894 }
01895
01896
01897 void
01898 draw_verb_dialog(
01899 pt<phys_obj> item1,
01900 pt<phys_obj> item2,
01901 const surf_of_letter_t & surf_of_letter,
01902 SDL_Surface * screen,
01903 bool calc_rect_only,
01904 int_pair mouse,
01906 SDL_Rect & cancel_rect,
01908 list<pt<dialog_choice> > & choices)
01909 {
01910
01911 int ht_label, avail_ht;
01912 int y_top, y_bottom;
01913 int ht_per_verb, ht;
01914 int left_border, right_border;
01915 SDL_Rect rect;
01916 string text;
01917 int ht_of_letter, centered_y;
01918 vector<pt<verb> >::const_iterator v;
01919 pt<verb> cur_verb;
01920
01921
01922 rgb color_of_less_important_text(80,120,120);
01923 rgb color_of_none_of_the_above(250,250,150);
01924 rgb col;
01925 list<pt<token_of_verb_text> >::const_iterator tok;
01926 pt<phys_obj_with_verbs> obj_with_verbs;
01927 vector<pt<phys_obj> > items;
01928 vector<pt<phys_obj> >::const_iterator i;
01929 pt<phys_obj> active_it, passive_it;
01930 int c;
01931 int num_choices;
01932
01933
01934
01935 if (! calc_rect_only)
01936 SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 10, 10, 10));
01937
01938
01939
01940
01941 ht_of_letter = map_get(surf_of_letter, 'a')->h;
01942
01943 left_border = 10;
01944 right_border = screen->w - 10;
01945
01946 ht_label = draw_text_multiline_variable_ht( ( "Please specify what you want to do."),
01947 screen,
01948 left_border,
01949 0,
01950 right_border,
01951 surf_of_letter,
01952 calc_rect_only,
01953 color_of_less_important_text);
01954
01955
01956
01957
01958 avail_ht = screen->h - ht_label;
01959
01960 items = *vector_of(ulist(item1) << item2);
01961
01962
01963
01964
01965 num_choices = 1 ;
01966
01967 foreach(i, items){
01968
01969 if(pt_cast(*i, obj_with_verbs))
01970 {
01971 num_choices += obj_with_verbs->verbs.size();
01972 }
01973
01974 }
01975 if ( (pt_cast(item1, obj_with_verbs) && obj_with_verbs->none_of_the_above)
01976 ||
01977 (pt_cast(item2, obj_with_verbs) && obj_with_verbs->none_of_the_above))
01978 {
01979 num_choices ++ ;
01980 }
01981
01982 ht_per_verb = avail_ht / num_choices;
01983
01984
01985
01986
01987
01988 choices.clear();
01989
01990 for(c = 0; c < 2; c++)
01991 {
01992 active_it = items[c];
01993 passive_it = items[1-c];
01994
01995
01996 if(pt_cast(active_it, obj_with_verbs))
01997 {
01998 foreach(v, obj_with_verbs->verbs)
01999 {
02000 y_top = ht_label + choices.size() * ht_per_verb;
02001 y_bottom = ht_label + (choices.size() +1)* ht_per_verb;
02002
02003 centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02004
02005 cur_verb = *v;
02006
02007 text = "";
02008 foreach(tok, cur_verb->tokens){
02009 text += (*tok)->to_string(obj_with_verbs, passive_it);
02010 }
02011
02012 col = cur_verb->color;
02013
02015
02016 print_x_centered_line_of_text(text,
02017 left_border,right_border,
02018 centered_y,
02019 surf_of_letter, screen,
02020 col);
02021
02022 rect = create_rect(left_border, y_top, right_border, y_top + ht_per_verb);
02023
02024 choices.push_back(NEW(dialog_choice_verb_object(cur_verb, obj_with_verbs, passive_it, rect)));
02025
02026
02027
02028 if ( left_border <= mouse.x && mouse.x < right_border
02029 &&
02030 y_top <= mouse.y && mouse.y < y_bottom)
02031 {
02032
02033 rectangleRGBA(screen,
02034 left_border, y_top, right_border, y_bottom,
02035 200, 100, 100, 200);
02036 }
02037
02038 }
02039 }
02040 }
02041
02042
02043
02044
02045 if ( (pt_cast(item1, obj_with_verbs) && obj_with_verbs->none_of_the_above)
02046 ||
02047 (pt_cast(item2, obj_with_verbs) && obj_with_verbs->none_of_the_above))
02048 {
02049 y_top = ht_label + (num_choices -2) * ht_per_verb;
02050 y_bottom = ht_label + ( num_choices -1)* ht_per_verb;
02051
02052 centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02053
02054 text = "Other";
02055
02056 col = color_of_none_of_the_above;
02057
02059
02060 print_x_centered_line_of_text(text,
02061 left_border,right_border,
02062 centered_y,
02063 surf_of_letter, screen,
02064 col);
02065 rect = create_rect(left_border, y_top, right_border, y_top + ht_per_verb);
02066
02067 choices.push_back(NEW(dialog_choice_double_other(rect)));
02068
02069
02070 if ( left_border <= mouse.x && mouse.x < right_border
02071 &&
02072 y_top <= mouse.y && mouse.y < y_bottom)
02073 {
02074
02075 rectangleRGBA(screen,
02076 left_border, y_top, right_border, y_bottom,
02077 200, 100, 100, 200);
02078 }
02079
02080
02081 }
02082
02083
02084
02085
02086
02087
02088 y_top = ht_label + (num_choices-1) * ht_per_verb;
02089
02090 centered_y = y_top + (ht_per_verb - ht_of_letter)/2;
02091
02092 ht = draw_text_multiline_variable_ht( "Cancel",
02093 screen,
02094 left_border,
02095 centered_y,
02096 right_border,
02097 surf_of_letter,
02098 calc_rect_only,
02099 color_of_less_important_text);
02100 rect = create_rect( left_border, y_top, right_border, y_top + ht_per_verb);
02101
02102 cancel_rect = rect;
02103
02104 if ( point_in_rect(mouse, cancel_rect))
02105 {
02106 rectangleRGBA(screen,
02107 left_border, y_top, right_border, y_top + ht_per_verb,
02108 200, 100, 100, 200);
02109 }
02110
02111
02112
02113 }
02114
02115
02116 pt<anim_frame>
02117 update_still_anim(
02118 pt<PS_still_and_parsing> st,
02119 float dt)
02120 {
02121
02122 pt<anim_frame> cur_fr;
02123
02124
02125 if(st->cur_frame >= st->anim->frames.size())
02126 {
02127 return st->anim->frames.back();
02128 }
02129 else
02130 {
02131 cur_fr = st->anim->frames[st->cur_frame];
02132
02133 st->timer += dt;
02134 if (st->timer <= cur_fr->duration)
02135 {
02136 return cur_fr;
02137 }
02138 else
02139 {
02140 st->timer -= cur_fr->duration;
02141 st->cur_frame ++;
02142
02143 if(st->cur_frame >= st->anim->frames.size())
02144 {
02145 return st->anim->frames.back();
02146 }
02147 else
02148 {
02149 return st->anim->frames[st->cur_frame];
02150 }
02151
02152 }
02153 }
02154 }
02155
02156
02157 void
02158 FACK::execute_commands(
02159 pt<PC> pl,
02160 const list<pt<script_cmd> > & commands)
02161 {
02162
02163 pt<PS_still_and_parsing> still;
02164 pt<anim_frame> cur_frame;
02165 result_exec_next_scr_cmd res;
02166 bool cast_ok;
02167
02168
02169 cast_ok = pt_cast(pl->state, still);
02170 assert(cast_ok);
02171
02172
02173 if(still->cur_frame >= still->anim->frames.size())
02174 {
02175 assert(still->anim->frames.size()>0);
02176 cur_frame = still->anim->frames.back();
02177 }
02178 else
02179 {
02180 cur_frame = still->anim->frames[still->cur_frame];
02181 }
02182
02183
02184 res = exec_next_scr_cmd(*vector_of(commands),
02185 0,
02186 pl,
02187 cur_frame,
02188 false,
02189 true
02190
02191
02192 );
02193
02194 pl->state = res.new_pl_state;
02195 pl->pos = res.new_pl_pos;
02196 pl->cur_dir = res.new_pl_dir;
02197
02198 }
02199
02200
02201
02202 struct speech_finished{};
02203
02204 void
02205 decide_position_for_text(
02206 string text,
02207 int_pair player_head,
02208 int & x_left,
02209 int & y_top,
02210 int & x_right,
02211 const surf_of_letter_t & surf_of_letter,
02212 SDL_Surface * screen)
02213 {
02214
02215 int ideal_wt, ht;
02216 int ideal_x_left, ideal_x_right;
02217 int real_x_left, real_x_right;
02218 int vert_gap_head_text;
02219 rgb col(0,0,0);
02220
02221
02222 vert_gap_head_text = 10;
02223 ideal_wt = screen->w * 2 / 3;
02224
02225 ideal_x_left = player_head.x - ideal_wt/2;
02226 ideal_x_right = player_head.x + ideal_wt/2;
02227
02228 if(ideal_x_left < 0)
02229 {
02230 real_x_left = 0;
02231 real_x_right = ideal_wt;
02232 }
02233 else if (ideal_x_right >= screen->w)
02234 {
02235 real_x_right = screen->w;
02236 real_x_left = real_x_right - ideal_wt;
02237 }
02238 else
02239 {
02240 real_x_right = ideal_x_right;
02241 real_x_left = ideal_x_left;
02242 }
02243
02244 ht = draw_text_multiline_variable_ht(
02245 text, screen, real_x_left, 0, real_x_right, surf_of_letter, true, col);
02246
02247 if (ht < player_head.y - vert_gap_head_text)
02248 {
02249 y_top = player_head.y - vert_gap_head_text -ht;
02250 x_left = real_x_left;
02251 x_right = real_x_right;
02252 }
02253 else
02254 {
02255 ht = draw_text_multiline_variable_ht(
02256 text, screen, 0, 0, screen->w, surf_of_letter, true, col);
02257
02258 y_top = std::max(0, player_head.y - ht - vert_gap_head_text);
02259 x_left = 0;
02260 x_right = screen->w;
02261 }
02262
02263 }
02264
02265
02266 variant<speech_finished, sentence_with_location>
02267 update_speech(
02268 AI_substate_speaking_while_standing & state,
02269 float dt,
02270 const surf_of_letter_t & surf_of_letter,
02271 SDL_Surface * screen,
02272 pt<anim_frame> & new_frame ,
02273 rgb text_color,
02274 bool time_frozen,
02275 const pt<PC> player,
02276 const room_scaling_data & scaling_data,
02277 int_pair top_left_of_screen_in_bg)
02278 {
02279
02280 variant<speech_finished, sentence_with_location> ret;
02281 float change_seconds;
02282 string cur_txt;
02283 int x_left, y_top, x_right;
02284 pt<anim_frame> cur_frame;
02285 int_pair player_head_bg_coord;
02286 int_pair player_head_screen_coord;
02287
02288
02289
02290
02291 if(state.cur_frame_it >= state.current_phrase->anim->frames.size())
02292 {
02293
02294 new_frame = state.current_phrase->anim->frames.back();
02295 }
02296 else
02297 {
02298 if (time_frozen)
02299 {
02300 new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02301 }
02302 else
02303 {
02304
02305
02306
02307 cur_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02308
02309 state.anim_timer += dt;
02310
02311 if (state.anim_timer <= cur_frame->duration)
02312 {
02313
02314 new_frame = cur_frame;
02315 }
02316 else
02317 {
02318
02319
02320 state.anim_timer -= cur_frame->duration;
02321 state.cur_frame_it ++;
02322 if (state.cur_frame_it >= state.current_phrase->anim->frames.size())
02323 {
02324
02325 new_frame = state.current_phrase->anim->frames.back();
02326 }
02327 else
02328 {
02329 new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02330 }
02331 }
02332 }
02333 }
02334
02335
02336 player_head_bg_coord.x = player->pos.x;
02337 player_head_bg_coord.y = player->pos.y -
02338 int(float( new_frame->h ) *
02339 scaling_of_char(float(player->pos.y), scaling_data));
02340
02341 player_head_screen_coord = player_head_bg_coord - top_left_of_screen_in_bg;
02342
02343 cur_txt = state.current_phrase->str;
02344 if(time_frozen)
02345 {
02346 decide_position_for_text(cur_txt, player_head_screen_coord,
02347 x_left ,
02348 y_top , x_right,
02349 surf_of_letter, screen);
02350 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02351 }
02352 else
02353 {
02354 change_seconds = cur_txt.size() * 0.04f + 0.5f;
02355
02356 state.speech_timer += dt;
02357
02358 if (state.speech_timer <= change_seconds)
02359 {
02360 decide_position_for_text(cur_txt, player_head_screen_coord,
02361 x_left ,
02362 y_top , x_right, surf_of_letter, screen);
02363
02364 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02365 }
02366 else
02367 {
02368 state.speech_timer -= change_seconds;
02369 state.current_phrase ++;
02370
02371
02372 if (state.current_phrase == state.speech.end())
02373 {
02374
02375
02376
02377 return speech_finished();
02378 }
02379 else
02380 {
02381
02382
02383
02384
02385
02386 state.cur_frame_it = 0;
02387 assert(state.current_phrase->anim->frames.size()>0);
02388 new_frame = state.current_phrase->anim->frames[state.cur_frame_it];
02389
02390
02391 decide_position_for_text(cur_txt, player_head_screen_coord, x_left ,
02392 y_top , x_right, surf_of_letter, screen);
02393 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02394 }
02395 }
02396
02397 }
02398 assert(false);
02399
02400 }
02401
02402
02403 variant<speech_finished, sentence_with_location>
02404 update_speech(
02405 AI_substate_speaking_while_sitting & state,
02406 float dt,
02407 const surf_of_letter_t & surf_of_letter,
02408 SDL_Surface * screen,
02409 const pt<anim_frame> const_frame,
02410 rgb text_color,
02411 bool time_frozen,
02412 const pt<PC> player,
02413 const room_scaling_data & scaling_data,
02414 int_pair top_left_of_screen_in_bg)
02415 {
02416
02417 variant<speech_finished, sentence_with_location> ret;
02418 float change_seconds;
02419 string cur_txt;
02420 int x_left, y_top, x_right;
02421 pt<anim_frame> cur_frame;
02422 int_pair player_head_screen_coord;
02423 int_pair player_head_bg_coord;
02424
02425
02426
02427
02428 player_head_bg_coord.x = player->pos.x;
02429
02430 player_head_bg_coord.y = player->pos.y - int(float( const_frame->h ) );
02431
02432 player_head_screen_coord = player_head_bg_coord - top_left_of_screen_in_bg;
02433
02434 cur_txt = *state.current_phrase;
02435 if(time_frozen)
02436 {
02437 decide_position_for_text(cur_txt, player_head_screen_coord, x_left ,
02438 y_top , x_right, surf_of_letter, screen);
02439 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02440 }
02441 else
02442 {
02443 change_seconds = cur_txt.size() * 0.04f + 0.5f;
02444
02445 state.speech_timer += dt;
02446
02447 if (state.speech_timer <= change_seconds)
02448 {
02449 decide_position_for_text(cur_txt, player_head_screen_coord, x_left ,
02450 y_top , x_right, surf_of_letter, screen);
02451
02452 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02453 }
02454 else
02455 {
02456 state.speech_timer -= change_seconds;
02457 state.current_phrase ++;
02458
02459
02460 if (state.current_phrase == state.speech.end())
02461 {
02462
02463
02464
02465 return speech_finished();
02466 }
02467 else
02468 {
02469 decide_position_for_text(cur_txt, player_head_screen_coord, x_left ,
02470 y_top , x_right, surf_of_letter, screen);
02471 return sentence_with_location(cur_txt, x_left, y_top, x_right, text_color);
02472 }
02473 }
02474
02475 }
02476 assert(false);
02477
02478 }
02479
02480 template<class T>
02481 void
02482 list_remove_one( T & l, typename T::value_type el)
02483 {
02484
02485 typename T::iterator i;
02486 bool done;
02487
02488 done = false;
02489 for(i = l.begin() ; i != l.end(); i++)
02490 {
02491 if (*i == el)
02492 {
02493 i = l.erase(i);
02494 done = true;
02495 break;
02496 }
02497 }
02498 assert(done);
02499 }
02500
02501
02502 result_exec_next_scr_cmd
02503 end_commands(
02504 pt<PC> pl,
02505 int cur_cmd_it,
02506 bool must_set_player_left_or_right)
02507 {
02508
02509 direction dir2;
02510 pt<still_situation_normal> normal;
02511 pt<still_situation_sitting> sitting;
02512 bool ok;
02513
02514
02515
02516 if (must_set_player_left_or_right)
02517 {
02518 if(pl->cur_dir == d_left)
02519 dir2 = d_left;
02520 else
02521 dir2 = d_right;
02522 }
02523 else
02524 {
02525 dir2 = pl->cur_dir;
02526 }
02527
02528
02529 if(pt_cast(pl->still_situat, normal))
02530 {
02531 return result_exec_next_scr_cmd(
02532 NEW( PS_missing_two_items(
02533 map_get(pl->anim_of_norm_still_sit,
02534 dir2),
02535 0,
02536 0)),
02537 cur_cmd_it,
02538 pl->pos,
02539 dir2);
02540 }
02541 else
02542 {
02543 ok = pt_cast(pl->still_situat, sitting);
02544 assert(ok);
02545
02546 return result_exec_next_scr_cmd(
02547 NEW( PS_missing_two_items(
02548 map_get(pl->anim_of_sitting_still_sit,
02549 sitting->situation_name),
02550 0,
02551 0)),
02552 cur_cmd_it,
02553 pl->pos,
02554 dir2);
02555 }
02556
02557 }
02558
02559
02560
02561 void
02562 FACK::stand_up_if_sitting(
02563 pt<PC> pl)
02564 {
02565
02566
02567 pt<still_situation_sitting> sitting;
02568
02569
02570
02571
02572 if (pt_cast(pl->still_situat, sitting))
02573 {
02574 pl->loc->occupied_sitting_places.erase(sitting->occupied_place);
02575 pl->still_situat = NEW(still_situation_normal());
02576 }
02577
02578
02579 }
02580
02581 void
02582 FACK::close_all_open_popups(
02583 const pt<PC> pl)
02584 {
02585
02586 list<pt<popup> >::iterator co;
02587
02588
02589
02590 pl->open_popups.clear();
02591 }
02592
02593
02594 result_exec_next_scr_cmd
02595 FACK::exec_next_scr_cmd(
02596 const vector<pt<script_cmd> > commands,
02597 int cur_cmd_it,
02598 const pt<PC> pl,
02599 pt<anim_frame> last_frame,
02600 bool increm_cmd_at_start,
02601 bool must_set_player_left_or_right)
02602 {
02603
02604 direction dir2;
02605 still_situation still_sit;
02606 pt<PS_governed_by_AI> gov_ai;
02607 variant < no_route_found, pt<list<int_pair> > > maybe_route;
02608 pt<list<int_pair> > route;
02609 pt<list<int_pair> > route2;
02610 pt<scr_cmd_walk> cmd_walk;
02611 pt<scr_cmd_speak> cmd_speak;
02612 pt<scr_cmd_set_sitting_state> set_sitting_still_stat;
02613 pt<scr_cmd_passive_anim> cmd_passive_anim;
02614 pt<scr_cmd_light_transition> cmd_light_transit;
02615 pt<scr_cmd_wait_for_person_to_stop_talking> cmd_wait_stop_talk;
02616 pt<scr_cmd_change_light> cmd_change_light;
02617 pt<scr_cmd_change_loc> cmd_change_loc;
02618 pt<scr_cmd_modify_zone> cmd_modify_zone;
02619 pt<scr_cmd_add_to_container> cmd_add_to_cont;
02620 pt<scr_cmd_add_to_container_in_pos> cmd_add_to_cont_in_pos;
02621 pt<scr_cmd_remove_from_container> cmd_remove_from_cont;
02622 pt<scr_cmd_modify_layer> cmd_modify_layer;
02623 pt<scr_cmd_quick_message> quick_mess;
02624 pt<scr_cmd_look_at_fixed_direction> cmd_look_at_dir;
02625 speech_t::const_iterator i;
02626 speech2_t sp2;
02627 horizontal_dir d;
02628 pt<script_cmd> cur_cmd;
02629 pt<still_situation_normal> normal;
02630 pt<still_situation_sitting> sitting;
02631 list<string> strings;
02632 pt<scr_cmd_open_popup> open_popup;
02633 bool ok;
02634 pt<container> real_co;
02635 int_pair pos;
02636
02637
02638 if(increm_cmd_at_start)
02639 cur_cmd_it ++;
02640
02641 if(cur_cmd_it >= commands.size())
02642 {
02643 return end_commands(pl, cur_cmd_it, must_set_player_left_or_right);
02644 }
02645 else
02646 {
02647 cur_cmd = commands[cur_cmd_it];
02648
02649
02650 if(pt_cast(cur_cmd, cmd_walk))
02651 {
02652 if(!( pl->pos == cmd_walk->dest))
02653 {
02654 maybe_route = best_route(
02655 pl->pos, cmd_walk->dest, *pl->loc->walking_map);
02656
02657 ok = var_cast(maybe_route, route);
02658 assert(ok);
02659
02660 route2 = compute_feet_positions(
02661 pl->pos, *route, pl->loc->scaling_data,
02662 pl->walk_step_horiz, pl->walk_step_vert);
02663 assert(route2->size()>0);
02664 dir2 = compute_dir(pl->pos,
02665 route2->front(), pl->walk_step_horiz);
02666
02667 stand_up_if_sitting(pl);
02668 close_all_open_popups(pl);
02669
02670 return result_exec_next_scr_cmd(
02671 NEW(PS_governed_by_AI(
02672 commands,
02673 cur_cmd_it,
02674 NEW(AI_substate_walk(*vector_of(*route2))))),
02675 cur_cmd_it,
02676 pl->pos,
02677 dir2);
02678 }
02679 else
02680 {
02681 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02682 }
02683 }
02684 else if(pt_cast(cur_cmd, cmd_speak))
02685 {
02686 if(cmd_speak->close_containers == close_any_open_container)
02687 {
02688 close_all_open_popups(pl);
02689 }
02690
02691 if (pt_cast(pl->still_situat, sitting))
02692 {
02693 setof_(
02694 i->str,
02695 i,
02696 cmd_speak->speech,
02697 true,
02698 strings);
02699
02700 return result_exec_next_scr_cmd(
02701 NEW(PS_governed_by_AI(
02702 commands,
02703 cur_cmd_it,
02704 NEW(AI_substate_speaking_while_sitting(strings, last_frame)))),
02705 cur_cmd_it,
02706 pl->pos,
02707 pl->cur_dir);
02708 }
02709 else
02710 {
02711 if(pl->cur_dir == d_left)
02712 {
02713 d = hd_left;
02714 }
02715 else
02716 {
02717 pl->cur_dir = d_right;
02718 d = hd_right;
02719 }
02720
02721 setof_(
02722 anim_and_string(
02723 map_get(pl->anim_of_mood,
02724 i->mood).get_anim(d), i->str),
02725 i,
02726 cmd_speak->speech,
02727 true,
02728 sp2);
02729
02730 return result_exec_next_scr_cmd(
02731 NEW(PS_governed_by_AI(
02732 commands,
02733 cur_cmd_it,
02734 NEW(AI_substate_speaking_while_standing(sp2)))),
02735 cur_cmd_it,
02736 pl->pos,
02737 pl->cur_dir);
02738 }
02739
02740 }
02741 else if(pt_cast(cur_cmd, cmd_passive_anim))
02742 {
02743 close_all_open_popups(pl);
02744
02745 return result_exec_next_scr_cmd(
02746 NEW(PS_governed_by_AI(
02747 commands,
02748 cur_cmd_it,
02749 NEW(AI_substate_passive_anim(cmd_passive_anim->anim)))),
02750 cur_cmd_it,
02751 pl->pos,
02752 pl->cur_dir);
02753 }
02754 else if(pt_cast(cur_cmd, cmd_wait_stop_talk))
02755 {
02756 return result_exec_next_scr_cmd(
02757 NEW(PS_governed_by_AI(
02758 commands,
02759 cur_cmd_it,
02760 NEW(AI_substate_waiting_for_person_to_stop_talking(cmd_wait_stop_talk->person,
02761 last_frame)))),
02762 cur_cmd_it,
02763 pl->pos,
02764 pl->cur_dir);
02765 }
02766 else if(pt_cast(cur_cmd, cmd_change_light))
02767 {
02768 if (cmd_change_light->turn_on)
02769 {
02770
02771
02772 cmd_change_light->loc->active_lights.insert(cmd_change_light->ligh);
02773 }
02774 else
02775 {
02776
02777 cmd_change_light->loc->active_lights.erase(cmd_change_light->ligh);
02778 }
02779 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02780 }
02781 else if(pt_cast(cur_cmd, open_popup))
02782 {
02783 pl->open_popups.push_back(open_popup->dr);
02784
02785 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02786 }
02787 else if(pt_cast(cur_cmd, quick_mess))
02788 {
02789 quick_msg = NEW(quick_message(quick_mess->text));
02790
02791 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02792 }
02793 else if(pt_cast(cur_cmd, set_sitting_still_stat))
02794 {
02795 if (! in( set_sitting_still_stat->occupied_place, pl->loc->occupied_sitting_places))
02796 {
02797 pl->still_situat = NEW(still_situation_sitting(
02798 set_sitting_still_stat->situation_name,
02799 set_sitting_still_stat->occupied_place));
02800 pl->loc->occupied_sitting_places.insert(set_sitting_still_stat->occupied_place);
02801 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02802 }
02803 else
02804 {
02805
02806 cout << "The place is occupied" << endl;
02807 return end_commands(pl, cur_cmd_it, must_set_player_left_or_right);
02808 }
02809 }
02810 else if(pt_cast(cur_cmd, cmd_change_loc))
02811 {
02812 pl->loc = cmd_change_loc->new_loc;
02813 pl->pos = cmd_change_loc->position;
02814
02815 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02816 }
02817 else if(pt_cast(cur_cmd, cmd_light_transit))
02818 {
02819
02820 this->transitions_of_fixed_light.push_back(
02821 NEW(transition_of_fixed_light( cmd_light_transit->ligh,
02822 cmd_light_transit->time_delta,
02823 cmd_light_transit->start_intensity,
02824 cmd_light_transit->dest_intensity,
02825 cmd_light_transit->switch_off_light_at_the_end)));
02826 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02827 }
02828 else if(pt_cast(cur_cmd, cmd_add_to_cont))
02829 {
02830 if(contains_recursively(cmd_add_to_cont->cont,
02831 cmd_add_to_cont->object,
02832 real_co ,
02833 pos ))
02834 {
02835 raise_exception("Error in game logic: the item was already in the inventory.");
02836 }
02837 else
02838 {
02839 cmd_add_to_cont->cont->add_item(cmd_add_to_cont->object);
02840
02841 if (cmd_add_to_cont->cont == act_pl->cache)
02842 {
02843 game_state = NEW(game_state_flashing_inv_t(cmd_add_to_cont->object));
02844 }
02845 }
02846
02847 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02848
02849 }
02850 else if(pt_cast(cur_cmd, cmd_add_to_cont_in_pos))
02851 {
02852 if(contains_recursively(cmd_add_to_cont_in_pos->cont,
02853 cmd_add_to_cont_in_pos->object,
02854 real_co ,
02855 pos ))
02856 {
02857 raise_exception("Error in game logic: the item was already in the inventory.");
02858 }
02859 else
02860 {
02861 cmd_add_to_cont_in_pos->cont->add_item_in_pos(
02862 pos_and<pt<obj_or_concept> > (cmd_add_to_cont_in_pos->object,
02863 cmd_add_to_cont_in_pos->pos));
02864
02865 if (cmd_add_to_cont_in_pos->cont == act_pl->cache)
02866 {
02867 game_state = NEW(game_state_flashing_inv_t(cmd_add_to_cont_in_pos->object));
02868 }
02869 }
02870
02871 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02872
02873 }
02874 else if(pt_cast(cur_cmd, cmd_remove_from_cont))
02875 {
02876 cmd_remove_from_cont->cont->remove_item_recursively(cmd_remove_from_cont->object);
02877
02878 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02879
02880 }
02881 else if(pt_cast(cur_cmd, cmd_modify_zone))
02882 {
02883 if(cmd_modify_zone->show == HIDE)
02884 cmd_modify_zone->zone->visible = false;
02885 else
02886 cmd_modify_zone->zone->visible = true;
02887
02888 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02889
02890 }
02891 else if(pt_cast(cur_cmd, cmd_modify_layer))
02892 {
02893 if(cmd_modify_layer->show == HIDE)
02894 cmd_modify_layer->layer->visible = false;
02895 else
02896 cmd_modify_layer->layer->visible = true;
02897
02898
02899 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true, must_set_player_left_or_right);
02900
02901 }
02902 else if(pt_cast(cur_cmd, cmd_look_at_dir))
02903 {
02904 pl->cur_dir = cmd_look_at_dir->dir;
02905
02906 return exec_next_scr_cmd(commands, cur_cmd_it, pl, last_frame, true,
02907 false );
02908 }
02909 else
02910 {
02911 assert(false);
02912 }
02913
02914 }
02915 }
02916
02917
02918
02919
02920
02921 update_AI_result
02922 FACK::update_AI_state(
02923 pt<PC> pl,
02924 float dt,
02925 int_pair top_left_of_screen_in_bg)
02926 {
02927
02928
02929 pt<script_cmd> cur_cmd;
02930 pt<script_cmd> cur_cmd_other;
02931
02932 pt<scr_cmd_walk> cmd_walk;
02933
02934 pt<AI_substate_walk> walk;
02935 pt<AI_substate_waiting_for_person_to_stop_talking> wait_stop_talk;
02936 pt<AI_substate_speaking_while_standing> speaking_standing;
02937 pt<AI_substate_speaking_while_sitting> speaking_sitting;
02938
02939 pt<AI_substate_passive_anim> passive_anim;
02940 pair<int_pair, direction> new_pos;
02941 pt<PS_governed_by_AI> gov_ai;
02942 pt<PS_governed_by_AI> gov_ai_other;
02943
02944 seq_list<pt<bg_hot_zone> >::const_iterator x;
02945 pt<anim_frame> cur_frame;
02946 variant<walking_finished, pair<int_pair, direction> > maybe_new_pos;
02947 variant<speech_finished, sentence_with_location> maybe_sentence;
02948 pt<game_state_flashing_inv_t> flashing_inv;
02949 bool ok;
02950 result_exec_next_scr_cmd res;
02951
02952
02953
02954 ok = pt_cast(pl->state, gov_ai);
02955 assert(ok);
02956
02957 if (pt_cast(gov_ai->substate, walk))
02958 {
02959 cur_frame = map_get( pl->walk_frame_when,
02960 walk_frame_id( walk->cur_foot,
02961 walk->cur_phase, pl->cur_dir));
02962
02963 if(pt_cast(game_state, flashing_inv))
02964 {
02965
02966 return update_AI_result( cur_frame, pl->pos, pl->cur_dir,
02967 no_sentence(), pl->state);
02968 }
02969 else
02970 {
02971 maybe_new_pos = update_walking_animation(
02972 cur_frame->duration,
02973 walk , pl->pos, pl->walk_step_horiz, dt, pl->cur_dir);
02974
02975
02976
02977 cur_frame = map_get( pl->walk_frame_when,
02978 walk_frame_id( walk->cur_foot,
02979 walk->cur_phase, pl->cur_dir));
02980
02981 if (var_cast(maybe_new_pos, new_pos))
02982 {
02983 return update_AI_result( cur_frame, new_pos.first,
02984 new_pos.second, no_sentence(), pl->state);
02985 }
02986 else
02987 {
02988 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl, cur_frame, true,
02989 true );
02990
02991 return update_AI_result( cur_frame, res.new_pl_pos, res.new_pl_dir,
02992 no_sentence(), res.new_pl_state);
02993 }
02994 }
02995
02996
02997 }
02998 else if (pt_cast(gov_ai->substate, passive_anim))
02999 {
03000 assert (passive_anim->cur_frame < passive_anim->anim->frames.size());
03001
03002 cur_frame = passive_anim->anim->frames[passive_anim->cur_frame];
03003
03004 if (pt_cast(game_state, flashing_inv))
03005 {
03006
03007 return update_AI_result(
03008 cur_frame, pl->pos,
03009 pl->cur_dir, no_sentence(), pl->state);
03010 }
03011 else
03012 {
03013 passive_anim->timer += dt;
03014
03015 if(passive_anim->timer <= cur_frame->duration)
03016 {
03017 return update_AI_result( cur_frame,
03018 pl->pos, pl->cur_dir, no_sentence(), pl->state);
03019 }
03020 else
03021 {
03022 passive_anim->timer -= cur_frame->duration;
03023 passive_anim->cur_frame ++;
03024 if (passive_anim->cur_frame >= passive_anim->anim->frames.size())
03025 {
03026 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl,
03027 cur_frame, true, true );
03028
03029 return update_AI_result( cur_frame ,
03030 res.new_pl_pos, res.new_pl_dir,
03031 no_sentence(), res.new_pl_state);
03032 }
03033 else
03034 {
03035 cur_frame = passive_anim->anim->frames[passive_anim->cur_frame];
03036
03037 return update_AI_result( cur_frame, pl->pos,
03038 pl->cur_dir, no_sentence(), pl->state);
03039 }
03040 }
03041 }
03042 }
03043 else if (pt_cast(gov_ai->substate, speaking_standing))
03044 {
03045
03046 maybe_sentence = update_speech(*speaking_standing, dt,
03047 surf_of_letter, screen, cur_frame , pl->text_color,
03048 pt_cast(game_state, flashing_inv) ,
03049 pl, pl->loc->scaling_data,
03050 top_left_of_screen_in_bg);
03051
03052 sentence_with_location sentenc;
03053 if(var_cast(maybe_sentence, sentenc))
03054 {
03055
03056 return update_AI_result( cur_frame, pl->pos,
03057 pl->cur_dir, sentenc, pl->state);
03058 }
03059 else
03060 {
03061 if (pt_cast(game_state, flashing_inv))
03062 {
03063
03064 return update_AI_result( cur_frame, pl->pos,
03065 pl->cur_dir, no_sentence(), pl->state);
03066 }
03067 else
03068 {
03069 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl,
03070 cur_frame, true, true );
03071
03072 return update_AI_result( cur_frame,
03073 res.new_pl_pos, res.new_pl_dir,
03074 no_sentence(), res.new_pl_state);
03075 }
03076 }
03077
03078
03079 }
03080 else if (pt_cast(gov_ai->substate, speaking_sitting))
03081 {
03082
03083 maybe_sentence = update_speech(*speaking_sitting, dt,
03084 surf_of_letter, screen, speaking_sitting->frame,
03085 pl->text_color,
03086 pt_cast(game_state, flashing_inv) ,
03087 pl, pl->loc->scaling_data,
03088 top_left_of_screen_in_bg);
03089
03090 sentence_with_location sentenc;
03091 if(var_cast(maybe_sentence, sentenc))
03092 {
03093
03094 return update_AI_result( speaking_sitting->frame, pl->pos,
03095 pl->cur_dir, sentenc, pl->state);
03096 }
03097 else
03098 {
03099 if (pt_cast(game_state, flashing_inv))
03100 {
03101
03102 return update_AI_result( speaking_sitting->frame, pl->pos,
03103 pl->cur_dir, no_sentence(), pl->state);
03104 }
03105 else
03106 {
03107 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl,
03108 speaking_sitting->frame, true,
03109 true );
03110
03111 return update_AI_result( speaking_sitting->frame,
03112 res.new_pl_pos, res.new_pl_dir,
03113 no_sentence(), res.new_pl_state);
03114 }
03115 }
03116
03117
03118 }
03119 else if (pt_cast(gov_ai->substate, wait_stop_talk))
03120 {
03121 if(pt_cast(wait_stop_talk->person->state, gov_ai_other))
03122 {
03123 if( pt_cast(gov_ai_other->substate, speaking_sitting)
03124 ||
03125 pt_cast(gov_ai_other->substate, speaking_standing))
03126 {
03127
03128
03129 return update_AI_result( wait_stop_talk->frame, pl->pos,
03130 pl->cur_dir, no_sentence(), pl->state);
03131 }
03132 else
03133 {
03134 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it, pl,
03135 wait_stop_talk->frame, true,
03136 true );
03137
03138 return update_AI_result( wait_stop_talk->frame,
03139 res.new_pl_pos, res.new_pl_dir,
03140 no_sentence(), res.new_pl_state);
03141 }
03142 }
03143 else
03144 {
03145
03146
03147 res = exec_next_scr_cmd(gov_ai->commands, gov_ai->cur_cmd_it,
03148 pl, wait_stop_talk->frame, true,
03149 true );
03150
03151 return update_AI_result( wait_stop_talk->frame,
03152 res.new_pl_pos, res.new_pl_dir,
03153 no_sentence(), res.new_pl_state);
03154 }
03155
03156
03157 }
03158 else
03159 {
03160 if(!gov_ai->substate)
03161 assert(false);
03162 else
03163 assert(false);
03164 }
03165
03166 }
03167
03168
03169
03170
03171
03172 void
03173 FACK::manage_button_up(
03174 list<SDL_Event>::const_iterator ev)
03175 {
03176
03177
03178
03179
03180 }
03181
03182 void
03183 zoomable::render(
03184 SDL_Surface * screen,
03185 const pt<game_state_t> game_state) const
03186 {
03187
03188 SDL_Rect r;
03189 int ret;
03190
03191
03192
03193 r.x = this->position_in_screen.x;
03194 r.y = this->position_in_screen.y;
03195
03196 ret = SDL_BlitSurface(this->picture, NULL, screen, &r);
03197 assert(ret == 0);
03198 }
03199
03200
03201 void
03202 container::render(
03203 SDL_Surface * screen,
03204 const pt<game_state_t> game_state) const
03205 {
03206
03207 SDL_Rect r;
03208 int ret;
03209 list<pos_and<pt<obj_or_concept> > >::const_iterator i;
03210 pt<game_state_flashing_inv_t> flashing;
03211
03212
03213
03214 r.x = this->position_in_screen.x;
03215 r.y = this->position_in_screen.y;
03216
03217 ret = SDL_BlitSurface(this->picture, NULL, screen, &r);
03218 assert(ret == 0);
03219
03220 foreach(i, this->sorted_items){
03221
03222 r.x = this->position_in_screen.x + i->pos.x;
03223 r.y = this->position_in_screen.y + i->pos.y;
03224
03225 ret = SDL_BlitSurface(i->o->get_inv_surf(),
03226 NULL,
03227 screen,
03228 &r);
03229 assert (ret == 0);
03230
03231
03232
03233 if ( pt_cast(game_state, flashing) &&
03234 flashing->item_that_is_flashing == i->o &&
03235 int(floor(flashing->timer / 0.3f)) % 2 == 0)
03236 {
03237 rectangleRGBA(screen,
03238
03239 this->position_in_screen.x + i->pos.x,
03240 this->position_in_screen.y + i->pos.y,
03241
03242 this->position_in_screen.x + i->pos.x + i->o->get_inv_surf()->w,
03243 this->position_in_screen.y + i->pos.y + i->o->get_inv_surf()->h,
03244
03245
03246 200, 100, 100, 200);
03247
03248 }
03249
03250
03251 }
03252
03253 }
03254
03255 struct result_is_there_only_one_option{
03256 virtual ~result_is_there_only_one_option(){}
03257 };
03258
03259 struct result_is_there_only_one_option_yes : public result_is_there_only_one_option
03260 {
03261 pt<verb> v;
03262 pt<phys_obj_with_verbs> obj_with_verb;
03263 pt<phys_obj> obj_without_verb;
03264
03265 result_is_there_only_one_option_yes(
03266 pt<verb> v,
03267 pt<phys_obj_with_verbs> obj_with_verb,
03268 pt<phys_obj> obj_without_verb)
03269 {
03270 this->v = v;
03271 this->obj_with_verb = obj_with_verb;
03272 this->obj_without_verb = obj_without_verb;
03273 }
03274
03275 };
03276
03277 struct result_is_there_only_one_option_no : public result_is_there_only_one_option {};
03278
03279 pt<result_is_there_only_one_option>
03280 is_there_only_one_option_overall(
03281 pt<phys_obj> o1,
03282 pt<phys_obj> o2)
03283 {
03284
03285 pt<phys_obj_with_verbs> obj_with_verbs;
03286 int count;
03287 vector<pt<phys_obj> > objs;
03288 int c;
03289 pt<phys_obj> active_obj, passive_obj;
03290 pt<result_is_there_only_one_option> last_option;
03291
03292
03293 objs = *vector_of(ulist(o1) << o2);
03294
03295
03296 count = 0;
03297 last_option = NEW(result_is_there_only_one_option_no());
03298
03299 for(c = 0; c < 2; c++)
03300 {
03301 active_obj = objs[c];
03302 passive_obj = objs[1-c];
03303
03304 if(pt_cast(active_obj, obj_with_verbs))
03305 {
03306 count += obj_with_verbs->verbs.size();
03307
03308 if (obj_with_verbs->none_of_the_above)
03309 {
03310 count ++;
03311 }
03312 last_option = NEW(result_is_there_only_one_option_yes(
03313 obj_with_verbs->verbs.front(),
03314 obj_with_verbs,
03315 passive_obj));
03316 }
03317 }
03318
03319
03320 assert(count >0);
03321
03322 if(count == 1)
03323 {
03324 return last_option;
03325 }
03326 else
03327 {
03328 return NEW(result_is_there_only_one_option_no());
03329 }
03330
03331 }
03332
03333
03334 void
03335 FACK::the_obj_was_clicked(
03336 pt<obj_or_concept> item_chosen,
03337 int_pair mouse)
03338 {
03339
03340 list<pt<dialog_choice> > choices;
03341 list<pt<dialog_choice> >::const_iterator cho;
03342
03343 SDL_Rect cancel_rect;
03344 pt<PS_missing_two_items> missing_two_items;
03345 pt<PS_missing_one_item> missing_one_item;
03346 list<pt<phys_obj_with_verbs> >ambig;
03347 pt<popup> zoomab;
03348 list<pt<obj_or_concept> >::const_iterator am;
03349
03350
03351
03352
03353 if(pt_cast(item_chosen, zoomab))
03354 {
03355 if(!in_list(zoomab, act_pl->open_popups))
03356 act_pl->open_popups.push_back(zoomab);
03357 else
03358 list_remove_one(act_pl->open_popups, zoomab);
03359 }
03360 else
03361 {
03362
03363
03364
03365 if (pt_cast(act_pl->state, missing_one_item))
03366 {
03367
03368 pt<concept> conc;
03369 pt<phys_obj> phys1, phys2;
03370 pt<phys_obj_with_verbs> obj_with_verbs;
03371 pt<result_is_there_only_one_option> ret;
03372 pt<result_is_there_only_one_option_yes> only_one;
03373
03374
03375 if (pt_cast(item_chosen, conc) || pt_cast(missing_one_item->obj_already_chosen, conc))
03376 {
03377 execute_action_object_object( item_chosen, missing_one_item->obj_already_chosen);
03378 }
03379 else
03380 {
03381 phys1 = dynamic_pointer_cast<phys_obj> (item_chosen);
03382 phys2 = dynamic_pointer_cast<phys_obj> (missing_one_item->obj_already_chosen);
03383 assert(phys1);
03384 assert(phys2);
03385
03386
03387 if(pt_cast(phys1, obj_with_verbs) || pt_cast(phys2, obj_with_verbs))
03388 {
03389 ret = is_there_only_one_option_overall(phys1, phys2);
03390
03391 if (pt_cast(ret, only_one))
03392 {
03393 execute_action_verb_object(only_one->v,
03394 only_one->obj_without_verb ,
03395 only_one->obj_with_verb );
03396 }
03397 else
03398 {
03399 draw_verb_dialog(
03400 phys1,
03401 phys2,
03402 surf_of_letter,
03403 screen,
03404 true ,
03405 mouse,
03406 cancel_rect ,
03407 choices );
03408
03409 act_pl->state = NEW( PS_choosing_verb(
03410 phys1,
03411 phys2 ,
03412 choices,
03413 cancel_rect,
03414 missing_one_item->anim,
03415 missing_one_item->timer,
03416 missing_one_item->cur_frame));
03417 }
03418 }
03419 else
03420 {
03421 execute_action_object_object( phys1, phys2);
03422 }
03423 }
03424 }
03425 else if (pt_cast(act_pl->state, missing_two_items))
03426 {
03427 act_pl->state = NEW( PS_missing_one_item(
03428 item_chosen, missing_two_items->anim,
03429 missing_two_items->timer,
03430 missing_two_items->cur_frame));
03431 }
03432 }
03433
03434 }
03435
03436 void
03437 FACK::cycle_active_player()
03438 {
03439
03440 list<pt<PC> >::const_iterator ch;
03441 list< list<pt<PC> >::const_iterator > qwe;
03442
03443
03444 setof_( ch, ch, players, *ch == act_pl, qwe);
03445 assert(qwe.size() == 1);
03446 ch = qwe.front();
03447 ch ++;
03448
03449 if (ch == players.end())
03450 {
03451 act_pl = players.front();
03452 }
03453 else
03454 {
03455 act_pl = *ch;
03456 }
03457
03458 active_player_changed(act_pl);
03459
03460 }
03461
03462
03463 SDL_Rect
03464 FACK::find_scrolling_rect(
03465 int_pair size_of_bg_surf)
03466 {
03467
03468 int ht_of_graphic_window, wt_of_graphic_window;
03469 int ideal_top, ideal_bottom, ideal_left, ideal_right;
03470 int final_top, final_bottom, final_left, final_right;
03471
03472
03473
03474 ht_of_graphic_window = std::min( size_of_bg_surf.y,
03475 screen->h - act_pl->cache->picture->h - calc_command_bar_ht());
03476 wt_of_graphic_window = std::min( size_of_bg_surf.x,
03477 screen->w);
03478
03479 ideal_top = act_pl->pos.y - ht_of_graphic_window * 3/4;
03480 ideal_bottom = act_pl->pos.y + ht_of_graphic_window / 4;
03481 ideal_left = act_pl->pos.x - wt_of_graphic_window /2;
03482 ideal_right = act_pl->pos.x + wt_of_graphic_window /2;
03483
03484 if (ideal_left <0)
03485 {
03486 final_left = 0;
03487 final_right = wt_of_graphic_window;
03488 }
03489 else if (ideal_right > size_of_bg_surf.x)
03490 {
03491 final_right = size_of_bg_surf.x;
03492 final_left = final_right - wt_of_graphic_window;
03493 }
03494 else
03495 {
03496 final_left = ideal_left;
03497 final_right = ideal_right;
03498 }
03499
03500 if (ideal_top <0)
03501 {
03502 final_top = 0;
03503 final_bottom = ht_of_graphic_window;
03504 }
03505 else if (ideal_bottom > size_of_bg_surf.y)
03506 {
03507 final_bottom = size_of_bg_surf.y;
03508 final_top = final_bottom - ht_of_graphic_window;
03509 }
03510 else
03511 {
03512 final_top = ideal_top;
03513 final_bottom = ideal_bottom;
03514 }
03515
03516 return create_rect( final_left, final_top, final_right, final_bottom);
03517
03518
03519 }
03520
03521 void
03522 FACK::recompute_on_lights(
03523 set<pt<light> > & on_lights ) const
03524 {
03525
03526 set<pt<light_across_loc> >::const_iterator lia;
03527 set<pt<light_fixed_in_loc> >::const_iterator lif;
03528 list<pt<PC> >::const_iterator pl;
03529 pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
03530 list<pos_and<pt<obj_or_concept> > >::const_iterator ob;
03531
03532
03533 on_lights.clear();
03534 foreach(lif, act_pl->loc->active_lights){
03535 on_lights.insert(*lif);
03536 }
03537
03538 foreach(lia, lights_across_loc){
03539 if( pt_cast(act_pl->drag_st, maybe_drag_obj)
03540 &&
03541 (*lia)->obj_which_emits_the_light == maybe_drag_obj->obj_and_pos.o )
03542 {
03543 on_lights.insert( *lia );
03544 }
03545 else
03546 {
03547 foreach(pl, players){
03548 if ( (*pl)->loc == act_pl->loc)
03549 {
03550 foreach(ob, (*pl)->cache->sorted_items){
03551 if (ob->o == (*lia)->obj_which_emits_the_light )
03552 {
03553 on_lights.insert( *lia );
03554 }
03555 }
03556 }
03557 }
03558 }
03559 }
03560 }
03561
03562
03563
03564 void
03565 FACK::start()
03566 {
03567
03568 pt<container_pick_result> itc;
03569 pt<PS_missing_two_items> missing_two_items;
03570 pt<PS_missing_one_item> missing_one_item;
03571 set<pt<light> > on_lights;
03572
03573 bool ok;
03574 pt<sentence_with_location> sen;
03575
03576
03577
03578 bool must_be_scaled;
03579 pt<still_situation_sitting> sitting;
03580 pt<AI_substate_speaking_while_sitting> sitting_talking;
03581 list<pt<layer_unlit_before_anim> >::const_iterator ql;
03582 list<pt<layer_unlit_after_anim> > unlit_layers_after_anim;
03583 list<pt<layer_unlit_after_anim> >::const_iterator l;
03584
03585
03586 pt<layer_lit> bg_layer_lit;
03587 list<pt<layer_lit> >::const_iterator xx;
03588 list<pt<anim_frame_and_pos> >::const_iterator xxc;
03589 list<pt<printable> > lit_layers_and_chars;
03590
03591
03592 update_AI_result update_AI_res;
03593 pt<anim_frame_and_pos> frame_and_pos;
03594 variant<no_sentence, sentence_with_location> maybe_sentence;
03595 sentence_with_location sentenc;
03596 float timer, dt;
03597 int timer_int, dt_int, previous_timer;
03598 list<SDL_Event> pending_events;
03599 list<SDL_Event>::const_iterator event;
03600 int_pair mouse_screen_coords;
03601 int_pair mouse_bg_coords;
03602
03603 pt<obj_or_concept> other_item, item_to_disamb;
03604 pt<phys_obj_with_verbs> just_disambig, still_to_disamb;
03605
03606
03607
03608 list<SDL_Surface*> inv_surfs;
03609 list<SDL_Surface*>::const_iterator sit;
03610 pt<vector<SDL_Surface *> >inv_surfs_2;
03611 pt<phys_obj> item_ph;
03612 variant<no_item, pt<obj_or_concept> > it, it2;
03613 pt<cfsurf> background;
03614 list<pt<layer_lit> > lit_layers;
03615 list<pt<anim_frame_and_pos> > characters;
03616 variant < no_route_found, pt<list<int_pair> > > maybe_route;
03617 pt<list<int_pair> > route2;
03618 pt<vector<int_pair> > route3;
03619 pt<PS_governed_by_AI> governed_by_AI;
03620 pt<anim_frame> cur_frame;
03621 list<int_pair>::const_iterator r;
03622 vector<int_pair>::const_iterator r3;
03623 list<int_pair>::const_iterator r4;
03624 pt<list<int_pair> > route4;
03625 vector<int_pair>::const_iterator r5;
03626 pt<vector<int_pair> > route5;
03627 variant<walking_finished, int_pair> res;
03628
03629 SDL_Rect cancel_rect;
03630 pt<PS_choosing_verb> choosing_verb;
03631
03632
03633 list<pt<dialog_choice> > clicked_choices;
03634 list<pt<dialog_choice> >::const_iterator cho;
03635
03636 list<sentence_with_location> sentences_to_display;
03637 list<sentence_with_location>::const_iterator sent;
03638
03639 speech_t speech;
03640 script_cmds_t commands;
03641
03642
03643 pt<game_state_normal_t> normal;
03644 pt<game_state_flashing_inv_t> flashing_inv;
03645
03646 map<pt<PC>, pt<anim_frame> > cur_frame_of_player;
03647 pt<anim_frame> stil;
03648 pt<PS_still_and_parsing> still;
03649 special_button_pick_result special_but;
03650
03651 SDL_Rect scrolling_rect;
03652 int_pair top_left, bottom_right;
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668 must_exit = false;
03669 previous_timer = SDL_GetTicks();
03670
03671 scrolling_rect = create_rect(0,0, 10,10);
03672
03673 while( !must_exit)
03674 {
03675
03676
03677 timer_int = SDL_GetTicks();
03678 timer = float(timer_int);
03679 dt_int = timer_int - previous_timer ;
03680 dt = float (dt_int / 1000.f);
03681 previous_timer = timer_int;
03682
03683
03684
03685
03686
03687
03688 if (!pt_cast(game_state, flashing_inv))
03689 {
03690 pending_events = get_sdl_events();
03691
03692 SDL_GetMouseState(&mouse_screen_coords.x, &mouse_screen_coords.y);
03693 mouse_bg_coords = mouse_screen_coords +
03694 int_pair(scrolling_rect.x, scrolling_rect.y);
03695
03696 foreach(event, pending_events){
03697
03698 gcn_input->pushInput(*event);
03699
03700 if (event->type == SDL_MOUSEBUTTONUP)
03701 {
03702
03703 pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
03704 pt<dragging_state_dragging_open_popup> drag_open_popup;
03705
03706 mouse_screen_coords = int_pair(event->button.x, event->button.y);
03707 mouse_bg_coords = mouse_screen_coords +
03708 int_pair(scrolling_rect.x, scrolling_rect.y);
03709
03710 if(pt_cast(act_pl->drag_st, maybe_drag_obj))
03711 {
03712 if(mouse_screen_coords == maybe_drag_obj->orig_mouse_pos)
03713 {
03714 maybe_drag_obj->orig_container->add_item_in_pos(
03715 maybe_drag_obj->obj_and_pos);
03716
03717 the_obj_was_clicked(maybe_drag_obj->obj_and_pos.o, mouse_screen_coords);
03718 }
03719 else
03720 {
03721 drop_item(maybe_drag_obj, mouse_screen_coords);
03722 }
03723
03724
03725 }
03726 else if(pt_cast(act_pl->drag_st, drag_open_popup))
03727 {
03728 drag_open_popup->pop->position_in_screen = mouse_screen_coords -
03729 drag_open_popup->offset_of_mouse_in_obj;
03730
03731 act_pl->open_popups.push_back(drag_open_popup->pop);
03732
03733 }
03734 act_pl->drag_st = NEW(dragging_state_not_dragging());
03735 }
03736 else if ( event->type == SDL_MOUSEBUTTONDOWN )
03737 {
03738 mouse_screen_coords = int_pair(event->button.x, event->button.y);
03739 mouse_bg_coords = mouse_screen_coords +
03740 int_pair(scrolling_rect.x, scrolling_rect.y);
03741
03742 if (event->button.button == SDL_BUTTON_LEFT)
03743 {
03744 special_but = special_button_at_pos(mouse_screen_coords);
03745 if(special_but == SBPR_CYCLE_PLAYER)
03746 {
03747 cycle_active_player();
03748 }
03749 else if (special_but == SBPR_STAY_FOLLOW)
03750 {
03751 quick_msg = NEW(quick_message("Not yet implemented."));
03752 }
03753 else if(special_but == SBPR_SAVE_LOAD)
03754 {
03755 if(gcn_options_window->isVisible())
03756 {
03757 gcn_options_window->setVisible( false);
03758 gcn_save_window->setVisible( false);
03759 gcn_load_window->setVisible( false);
03760 }
03761 else
03762 {
03763 gcn_options_window->setVisible( true);
03764 gcn_top_container->moveToTop(gcn_options_window.get());
03765 }
03766 }
03767 else
03768 {
03769 if (pt_cast(act_pl->state, missing_one_item)
03770 || pt_cast(act_pl->state, missing_two_items))
03771 {
03772
03773 pt<container_pick_result_obj_and_pos> obj_and_pos_clicked;
03774 pt<container_pick_result_obj> obj_clicked;
03775 pt<container_pick_result_container_drag_area> drag_cont;
03776 pt<container_pick_result_closing_area> close_cont;
03777 pt<container> cont;
03778
03779
03780 itc = item_in_popup_at_screen_pos(mouse_screen_coords);
03781
03782
03783 if(pt_cast(itc, obj_and_pos_clicked))
03784 {
03785 cont = dynamic_pointer_cast<container>(obj_and_pos_clicked->pop);
03786 assert(cont);
03787
03788 act_pl->drag_st =
03789 NEW(dragging_state_maybe_dragging_obj(
03790 obj_and_pos_clicked->obj_and_pos,
03791 ( (mouse_screen_coords - obj_and_pos_clicked->pop->position_in_screen) -
03792 obj_and_pos_clicked->obj_and_pos.pos) ,
03793 cont,
03794 mouse_screen_coords ));
03795
03796 cont->remove_item_not_recursively(obj_and_pos_clicked->obj_and_pos.o);
03797
03798 }
03799 else if (pt_cast(itc, obj_clicked))
03800 {
03801 the_obj_was_clicked(obj_clicked->obj, mouse_screen_coords);
03802 }
03803 else if (pt_cast(itc, close_cont))
03804 {
03805 list_remove_one(act_pl->open_popups, close_cont->pop);
03806 }
03807 else if(pt_cast(itc, drag_cont))
03808 {
03809 act_pl->drag_st =
03810 NEW(dragging_state_dragging_open_popup(
03811 mouse_screen_coords - drag_cont->pop->position_in_screen ,
03812 drag_cont->pop));
03813
03814 list_remove_one(act_pl->open_popups, drag_cont->pop);
03815 }
03816 else
03817 {
03818
03819 pt<obj_or_concept> obj_or_conc;
03820
03821
03822 it2 = item_in_room_at_position( mouse_bg_coords,
03823 players,
03824 act_pl,
03825 cur_frame_of_player);
03826
03827 if(var_cast(it2, obj_or_conc))
03828 {
03829 the_obj_was_clicked(obj_or_conc, mouse_screen_coords);
03830 }
03831 else
03832 {
03833
03834
03835 }
03836 }
03837 }
03838 else if (pt_cast(act_pl->state, choosing_verb))
03839 {
03840 if (point_in_rect( int_pair(event->button.x,
03841 event->button.y),
03842 choosing_verb->cancel_rect))
03843 {
03844 act_pl->state = NEW( PS_missing_two_items(
03845 choosing_verb->anim,
03846 choosing_verb->timer,
03847 choosing_verb->cur_frame));
03848 }
03849 else
03850 {
03851 setof( cho,
03852 choosing_verb->choices,
03853 point_in_rect( int_pair(event->button.x,
03854 event->button.y),
03855 (*cho)->rect),
03856 clicked_choices);
03857
03858 if(clicked_choices.size() >0)
03859 {
03860
03861 pt<dialog_choice_verb_object> choice_verb_obj;
03862
03863
03864
03865 if(pt_cast(clicked_choices.front(), choice_verb_obj))
03866 {
03867
03868 execute_action_verb_object(
03869 choice_verb_obj->v,
03870 choice_verb_obj->passive_obj ,
03871 choice_verb_obj->obj_for_which_the_verb_was_chosen );
03872 }
03873 else
03874 {
03875 assert(dynamic_pointer_cast<dialog_choice_double_other>(clicked_choices.front()));
03876 execute_action_double_none_of_the_above(
03877 choosing_verb->obj_one,
03878 choosing_verb->obj_two);
03879
03880 }
03881 }
03882 }
03883 }
03884 else if (pt_cast(act_pl->state, governed_by_AI))
03885 {
03886
03887 }
03888 else{
03889 assert(false);
03890 }
03891 }
03892 }
03893 else
03894 {
03895
03896
03897 mouse_screen_coords = int_pair(event->button.x, event->button.y);
03898 mouse_bg_coords = mouse_screen_coords +
03899 int_pair(scrolling_rect.x, scrolling_rect.y);
03900
03901
03902
03903 if(!pt_cast(act_pl->state, governed_by_AI))
03904 {
03905
03906 if(is_walkable(*act_pl->loc->walking_map,
03907 mouse_bg_coords.x,
03908 mouse_bg_coords.y))
03909 {
03910 commands.clear();
03911 commands << NEW(scr_cmd_walk(mouse_bg_coords));
03912 execute_commands(act_pl, commands);
03913 }
03914
03915 }
03916 }
03917 }
03918
03919 }
03920 }
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935 gcn_gui->logic();
03936
03937 recompute_on_lights(on_lights );
03938
03939 characters.clear();
03940 sentences_to_display.clear();
03941 cur_frame_of_player.clear();
03942
03943 if( pt_cast(act_pl->state, missing_one_item) ||
03944 pt_cast(act_pl->state, missing_two_items ) ||
03945 pt_cast(act_pl->state, governed_by_AI))
03946 {
03947
03948 list<pt<PC> >::const_iterator ch;
03949
03950
03951 foreach(ch, players){
03952
03953 if (pt_cast((*ch)->state, still))
03954 {
03955 cur_frame_of_player[*ch] = update_still_anim(still, dt);
03956
03957 if (act_pl->loc == (*ch)->loc)
03958 {
03959 must_be_scaled = !pt_cast((*ch)->still_situat, sitting );
03960
03961 characters.push_back(NEW( anim_frame_and_pos(
03962 map_get(cur_frame_of_player, *ch),
03963 (*ch)->pos.x,
03964 (*ch)->pos.y,
03965 must_be_scaled)));
03966 }
03967 }
03968 else
03969 {
03970 ok = pt_cast((*ch)->state, governed_by_AI);
03971 assert(ok);
03972
03973
03974 update_AI_res = update_AI_state( *ch, dt,
03975 int_pair(scrolling_rect.x,
03976 scrolling_rect.y));
03977
03978
03979
03980 recompute_on_lights(on_lights );
03981
03982
03983 cur_frame_of_player[*ch] = update_AI_res.frame;
03984 (*ch)->state = update_AI_res.new_player_state;
03985 (*ch)->cur_dir = update_AI_res.dir;
03986 (*ch)->pos = update_AI_res.pos;
03987
03988 if((*ch)->loc == act_pl->loc && update_AI_res.frame)
03989 {
03990 must_be_scaled = !pt_cast((*ch)->still_situat, sitting );
03991
03992 characters.push_back(NEW(anim_frame_and_pos(
03993 update_AI_res.frame,
03994 update_AI_res.pos.x,
03995 update_AI_res.pos.y,
03996 must_be_scaled)));
03997
03998 }
03999
04000 if ((*ch)->loc == act_pl->loc && var_cast(update_AI_res.maybe_sentence, sentenc))
04001 {
04002 sentences_to_display.push_back(sentenc);
04003 }
04004 }
04005 }
04006
04007
04008 setof_(
04009 (*ql)->get_cur_frame(dt),
04010 ql,
04011 act_pl->loc->sorted_unlit_layers_before_anim ,
04012 (*ql)->visible,
04013 unlit_layers_after_anim);
04014
04015
04016 scrolling_rect = find_scrolling_rect( int_pair(
04017 unlit_layers_after_anim.front()->lit_versions.front().surf->apparent_wt,
04018 unlit_layers_after_anim.front()->lit_versions.front().surf->apparent_ht));
04019
04020
04021 setof_ (
04022 lit_layer_of_unlit_layer(**l,
04023 on_lights,
04024 timer,
04025 scrolling_rect),
04026 l,
04027 unlit_layers_after_anim,
04028 true,
04029 lit_layers);
04030
04031
04032 bg_layer_lit = lit_layers.front();
04033 lit_layers.pop_front();
04034
04035 lit_layers_and_chars.clear();
04036 foreach(xx, lit_layers){
04037 lit_layers_and_chars.push_back(*xx);
04038 }
04039 foreach(xxc, characters){
04040 lit_layers_and_chars.push_back(*xxc);
04041 }
04042
04043
04044 if(quick_msg)
04045 {
04046 quick_msg->timer -= dt;
04047 if(quick_msg->timer <0)
04048 {
04049 quick_msg = pt<quick_message>();
04050 }
04051 }
04052
04053
04054
04055 update_light_transitions(dt);
04056 }
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069 if (pt_cast(act_pl->state, missing_one_item) ||
04070 pt_cast(act_pl->state, missing_two_items ) ||
04071 pt_cast(act_pl->state, governed_by_AI))
04072 {
04073
04074
04075 pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
04076 pt<dragging_state_dragging_open_popup> drag_open_popup;
04077 list<pt<popup> >::const_iterator zo;
04078
04079
04080
04081
04082
04083
04084
04085 render_layers_and_chars_in_correct_order(
04086 lit_layers_and_chars, *bg_layer_lit->surf, screen,
04087 act_pl->loc->scaling_data,
04088 scrolling_rect,
04089 on_lights);
04090
04091
04092
04093 {
04094
04095 SDL_Rect r;
04096 bool ret;
04097
04098
04099 r.x = special_buttons_icon_pos.x;
04100 r.y = special_buttons_icon_pos.y;
04101 ret = SDL_BlitSurface(special_buttons_icon,
04102 NULL,
04103 screen,
04104 &r);
04105 assert (ret == 0);
04106 }
04107
04108
04109 render_command_bar( mouse_screen_coords,
04110 mouse_bg_coords,
04111 cur_frame_of_player);
04112
04113 act_pl->cache->render(screen, game_state);
04114
04115 foreach(zo, act_pl->open_popups){
04116 (*zo)->render(screen, game_state);
04117 }
04118
04119 if(pt_cast(act_pl->drag_st, maybe_drag_obj))
04120 {
04121
04122 SDL_Rect r;
04123 int_pair cur_obj_pos;
04124 bool ret;
04125
04126
04127 cur_obj_pos = mouse_screen_coords - maybe_drag_obj->offset_of_mouse_in_obj;
04128 r.x = cur_obj_pos.x;
04129 r.y = cur_obj_pos.y;
04130 ret = SDL_BlitSurface(maybe_drag_obj->obj_and_pos.o->get_inv_surf(),
04131 NULL,
04132 screen,
04133 &r);
04134 assert (ret == 0);
04135
04136 }
04137 else if (pt_cast(act_pl->drag_st, drag_open_popup))
04138 {
04139 drag_open_popup->pop->position_in_screen =
04140 mouse_screen_coords - drag_open_popup->offset_of_mouse_in_obj;
04141
04142 drag_open_popup->pop->render(screen, game_state);
04143 }
04144
04145 foreach(sent, sentences_to_display){
04146
04147 draw_text_multiline_variable_ht(
04148 sent->text, screen, sent->x_left, sent->y_top,
04149 sent->x_right, surf_of_letter,
04150 false ,
04151 sent->color);
04152 }
04153
04154
04155 if(quick_msg)
04156 {
04157 print_x_centered_line_of_text(
04158 quick_msg->text,
04159 0, screen->w,
04160 screen->h - act_pl->cache->picture->h - calc_command_bar_ht() * 2 ,
04161 surf_of_letter, screen,
04162 rgb(150, 150, 210));
04163 }
04164
04165
04166 }
04167 else if(pt_cast(act_pl->state, choosing_verb))
04168 {
04169
04170 list<pt<dialog_choice> > choices;
04171
04172
04173
04174 draw_verb_dialog( choosing_verb->obj_one,
04175 choosing_verb->obj_two,
04176 surf_of_letter,
04177 screen,
04178 false ,
04179 mouse_screen_coords,
04180 cancel_rect ,
04181 choices );
04182 }
04183 gcn_gui->draw();
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199 if(pt_cast(game_state, flashing_inv))
04200 {
04201 flashing_inv->timer -= dt;
04202 if(flashing_inv->timer <= 0)
04203 {
04204 game_state = NEW(game_state_normal_t());
04205 }
04206 }
04207
04208
04209
04210
04211
04212
04213 SDL_Flip(screen);
04214 }
04215
04216 SDL_Quit();
04217 }
04218
04219 FACK::FACK(int argc, char ** argv)
04220 {
04221
04222
04223 Uint32 videoflags;
04224 int button_ht;
04225 seq_list<pt<gcn::Widget> > options_widgets;
04226 seq_list<pt<gcn::Widget> >::const_iterator x, w;
04227 list<int> widths;
04228 int maxw;
04229
04230
04231 if((SDL_Init(SDL_INIT_VIDEO)==-1)) {
04232 raise_exception("Could not initialize SDL." );
04233 }
04234
04235
04236 videoflags = choose_some_video_flags();
04237
04238
04239 if ( (argc > 1) && (strcmp(argv[1], "-full") == 0) ) {
04240 videoflags |= SDL_FULLSCREEN;}
04241
04242 this->screen = SDL_SetVideoMode(320, 240, 32, videoflags);
04243 if (!screen) {
04244 raise_exception("Couldn't set 320x200x32 video mode. " );
04245 }
04246
04247
04248
04249
04250
04251 list_model = NEW(dir_watcher_list_model());
04252 gcn_gui = NEW(gcn::Gui());
04253 button_ht = 20;
04254
04255 SDL_EnableUNICODE(1);
04256
04257 gcn_save_cont = NEW(gcn::Container());
04258 gcn_save_cont->setSize(300,150);
04259 gcn_save_cont->setOpaque(false);
04260
04261 gcn_load_cont = NEW(gcn::Container());
04262 gcn_load_cont->setSize(screen->w - 20,
04263 screen->h * 3 /4 );
04264 gcn_load_cont->setOpaque(false);
04265
04266 gcn_options_cont = NEW(gcn::Container());
04267 gcn_options_cont->setOpaque(false);
04268
04269 gcn_save_window = NEW(gcn::Window("Save"));
04270 gcn_save_window->setContent(gcn_save_cont.get());
04271
04272
04273
04274 gcn_options_window = NEW(gcn::Window("Options"));
04275 gcn_options_window->setContent(gcn_options_cont.get());
04276 gcn_options_window->setPosition(100, 20);
04277
04278
04279 gcn_load_window = NEW(gcn::Window("Load"));
04280 gcn_load_window->setContent(gcn_load_cont.get());
04281 gcn_load_window->resizeToContent();
04282
04283 gcn_top_container = NEW(gcn::Container());
04284 gcn_top_container->setDimension(gcn::Rectangle(0, 0, screen->w, screen->h));
04285 gcn_top_container->setOpaque(false);
04286 gcn_top_container->add(gcn_save_window.get());
04287 gcn_top_container->add(gcn_load_window.get());
04288 gcn_top_container->add(gcn_options_window.get());
04289
04290
04291
04292
04293 gcn_save_text_field = NEW(gcn::TextField("quick save"));
04294 gcn_save_text_field->setSize(200, 20);
04295 gcn_save_cont->add(gcn_save_text_field.get());
04296
04297 gcn_save_button = NEW(gcn::Button("Save"));
04298 gcn_save_button->setEventId("save_button_event");
04299 gcn_save_button->setPosition(0, button_ht );
04300 gcn_save_button->addActionListener(this);
04301 gcn_save_cont->add(gcn_save_button.get());
04302
04303 gcn_cancel_save_button = NEW(gcn::Button("Cancel"));
04304 gcn_cancel_save_button->setEventId("cancel_save_button_event");
04305 gcn_cancel_save_button->setPosition(0, 2 * button_ht );
04306 gcn_cancel_save_button->addActionListener(this);
04307 gcn_save_cont->add(gcn_cancel_save_button.get());
04308
04309
04310
04311 gcn_options_save_button = NEW(gcn::Button("Save"));
04312 gcn_options_save_button->setEventId("gcn_options_save_button");
04313 gcn_options_save_button->addActionListener(this);
04314 gcn_options_cont->add(gcn_options_save_button.get());
04315
04316
04317 gcn_options_load_button = NEW(gcn::Button("Load"));
04318 gcn_options_load_button->setPosition(0, button_ht );
04319 gcn_options_load_button->setEventId("gcn_options_load_button");
04320 gcn_options_load_button->addActionListener(this);
04321 gcn_options_cont->add(gcn_options_load_button.get());
04322
04323 gcn_options_fullscreen_button = NEW(gcn::Button("Toggle full screen"));
04324 gcn_options_fullscreen_button->setPosition(0, 2 * button_ht );
04325 gcn_options_fullscreen_button->setEventId("gcn_options_fullscreen_button");
04326 gcn_options_fullscreen_button->addActionListener(this);
04327 gcn_options_cont->add(gcn_options_fullscreen_button.get());
04328
04329 gcn_options_cancel_button = NEW(gcn::Button("Cancel"));
04330 gcn_options_cancel_button->setPosition(0, 3 * button_ht);
04331 gcn_options_cancel_button->setEventId("gcn_options_cancel_button");
04332 gcn_options_cancel_button->addActionListener(this);
04333 gcn_options_cont->add(gcn_options_cancel_button.get());
04334
04335
04336 gcn_options_quit_button = NEW(gcn::Button("Quit game"));
04337 gcn_options_quit_button->setPosition(0, 4 * button_ht);
04338 gcn_options_quit_button->setEventId("gcn_options_quit_button");
04339 gcn_options_quit_button->addActionListener(this);
04340 gcn_options_cont->add(gcn_options_quit_button.get());
04341
04342
04343 options_widgets = seq_list<pt<gcn::Widget> > () <<
04344 gcn_options_quit_button <<
04345 gcn_options_cancel_button << gcn_options_fullscreen_button <<
04346 gcn_options_load_button << gcn_options_save_button;
04347
04348 setof_ ( (*w)->getWidth(),
04349 w,
04350 options_widgets,
04351 true,
04352 widths);
04353
04354 maxw = max( widths);
04355
04356 gcn_options_cont->setSize(maxw, 120);
04357
04358 foreach( x, options_widgets){
04359
04360 (*x)->setWidth(maxw);
04361 }
04362
04363
04364 gcn_load_listbox = NEW(gcn::ListBox( list_model.get() ));
04365
04366 gcn_load_scroll_area = NEW(gcn::ScrollArea(gcn_load_listbox.get()));
04367 gcn_load_scroll_area->setSize(gcn_load_cont->getWidth(),
04368 gcn_load_cont->getHeight() - 32);
04369 gcn_load_listbox->setSize(gcn_load_cont->getWidth() - gcn_load_scroll_area->getScrollbarWidth() -2,
04370 gcn_load_cont->getHeight() - 32);
04371
04372
04373 gcn_cancel_load_button = NEW(gcn::Button("Cancel"));
04374 gcn_cancel_load_button->setEventId("gcn_cancel_load_button");
04375 gcn_cancel_load_button->addActionListener(this);
04376 gcn_cancel_load_button->setPosition(0, gcn_load_cont->getHeight() - 30);
04377
04378 gcn_load_cont->add(gcn_load_scroll_area.get());
04379 gcn_load_cont->add(gcn_cancel_load_button.get());
04380
04381
04382
04383
04384 gcn_load_window->resizeToContent();
04385 gcn_save_window->resizeToContent();
04386 gcn_options_window->resizeToContent();
04387
04388 gcn_load_window->setVisible(false);
04389 gcn_save_window->setVisible(false);
04390 gcn_options_window->setVisible(false);
04391
04392
04393
04394
04395 gcn_graphics = NEW(gcn::SDLGraphics());
04396 gcn_graphics->setTarget(screen);
04397
04398 gcn_image_loader = NEW(gcn::SDLImageLoader());
04399 gcn::Image::setImageLoader(gcn_image_loader.get());
04400
04401 gcn_input = NEW(gcn::SDLInput());
04402
04403 gcn_gui->setGraphics(gcn_graphics.get());
04404 gcn_gui->setInput(gcn_input.get());
04405 gcn_gui->setTop(gcn_top_container.get());
04406
04407
04408 gcn_font = NEW(gcn::ImageFont("data/fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.;:"));
04409
04410 gcn::Widget::setGlobalFont(gcn_font.get());
04411
04412
04413
04414 this->game_state = NEW(game_state_normal_t());
04415
04416 printf ("screen: pitch %d bytespp %d\n", screen->pitch, screen->format->BytesPerPixel);
04417 }
04418
04419
04420
04421 SDL_Surface * can_appear_closed_in_inv_no::get_inv_surf()
04422 {
04423 assert(false);
04424 }
04425
04426 SDL_Surface * can_appear_closed_in_inv_yes::get_inv_surf()
04427 {
04428 return inv_surf;
04429 }
04430
04431
04432
04433
04434
04436 bool
04437 anim_frame::point_in_surf(
04438 int_pair p ,
04439 int_pair pl ,
04440 float scaling ) const
04441 {
04442
04443 int_pair r, l, j;
04444 rgbaf pix;
04445
04446
04447 r = p - pl;
04448
04449 l = int_pair( int( float(r.x)/scaling ), int( float(r.y)/scaling) );
04450
04451 j = l + this->hot_spot;
04452
04453
04454 if ( 0 <= j.x && j.x < this->w
04455 &&
04456 0 <= j.y && j.y < this->h)
04457 {
04458 pix = get_pixel( j.x, j.y);
04459
04460 return (pix.a != 0.0f );
04461 }
04462 else
04463 {
04464 return false;
04465 }
04466
04467 }
04468
04469
04470 void
04471 layer_lit::print_with_transparency(
04472 cfsurf & background,
04473 const room_scaling_data& d,
04474 set<pt<light> > active_lights)
04475 {
04476 surf->blit_with_src_alpha( background);
04477
04478 }
04479
04480 void
04481 anim_frame_and_pos::print_with_transparency(
04482 cfsurf & background,
04483 const room_scaling_data& d,
04484 const set<pt<light> > active_lights)
04485 {
04486
04487 float scal;
04488 float light_fact;
04489 float sum;
04490 set<pt<light> >::const_iterator l;
04491 map<pt<light>, float> normalized_weight_of_light;
04492
04493
04494 if (this->must_be_scaled)
04495 {
04496 scal = scaling_of_char( this->position_y, d);
04497 }
04498 else
04499 {
04500 scal = 1.0f;
04501 }
04502
04503
04504 sum = 0.0f;
04505 foreach(l, active_lights){
04506 sum += (*l)->weight;
04507 }
04508
04509 foreach(l, active_lights){
04510 normalized_weight_of_light[*l] = (*l)->weight / sum;
04511 }
04512
04513
04514
04515 light_fact = 0.0f;
04516 foreach(l, active_lights){
04517 light_fact +=
04518 (*l)->pl_illum->get_illum_factor_at( this->position_x, this->position_y)
04519 *
04520 map_get( normalized_weight_of_light, *l);
04521 }
04522
04523 blit_char(*this, scal, light_fact, background);
04524
04525 }
04526
04527
04528 pt<layer_unlit_after_anim>
04529 layer_unlit_anim::get_cur_frame(float dt)
04530 {
04531 timer += dt;
04532 if (timer >= frame_change_interval)
04533 {
04534 timer -= frame_change_interval;
04535 cur_frame ++;
04536 if(cur_frame == anim.end())
04537 {
04538 cur_frame = anim.begin();
04539 }
04540
04541 }
04542 return NEW(layer_unlit_after_anim(*cur_frame, y_walkbehind));
04543
04544 }
04545
04546
04547 void
04548 FACK::define_dialog_aux(
04549 const dialog_t & dialog,
04550 pt<PC> first_player,
04551 pt<PC> second_player,
04552 script_cmds_t & steps_first,
04553 script_cmds_t & steps_second) const
04554 {
04555
04556 dialog_t::const_iterator i;
04557 pt<PC> who_speaks_next;
04558
04559
04560 who_speaks_next = first_player;
04561 foreach(i, dialog){
04562 if(who_speaks_next == first_player)
04563 {
04564 steps_first << NEW(scr_cmd_speak( *i, close_any_open_container));
04565 steps_second << NEW(scr_cmd_wait_for_person_to_stop_talking(first_player));
04566
04567 who_speaks_next = second_player;
04568 }
04569 else
04570 {
04571 steps_second << NEW(scr_cmd_speak(*i, close_any_open_container ));
04572 steps_first << NEW(scr_cmd_wait_for_person_to_stop_talking(second_player));
04573
04574 who_speaks_next = first_player;
04575
04576 }
04577 }
04578 }
04579
04580
04581
04582
04583 pt<animation>
04584 anim_right_left::get_anim(horizontal_dir dir) const
04585 {
04586 if (dir == hd_right)
04587 {
04588 return this->right;
04589 }
04590 else
04591 {
04592 return this->left;
04593 }
04594
04595 }
04596
04597
04598
04599
04600
04601
04602 void
04603 write_string(
04604 ostream& o, string s)
04605 {
04606
04607 o << s.length() << ":" << s;
04608 }
04609
04610
04611 string
04612 read_string(
04613 istream & i)
04614 {
04615
04616 size_t len;
04617 string ret;
04618 int c;
04619 char colon;
04620 char ch;
04621
04622
04623
04624 i >> len;
04625 i >> colon;
04626 assert(colon == ':');
04627
04628 ret = "";
04629 for (c = 0; c < len; c++)
04630 {
04631 i >> ch;
04632 ret += ch;
04633 }
04634
04635 return ret;
04636
04637 }
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852
04853
04854
04855 int_pair
04856 int_pair::operator-(
04857 const int_pair& p) const
04858 {
04859 return int_pair(x - p.x, y-p.y);
04860 }
04861 int_pair
04862 int_pair::operator+(
04863 const int_pair& p) const
04864 {
04865 return int_pair(x + p.x, y + p.y);
04866 }
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885 template<class T>
04886 void
04887 vector2<T>::fill_with(
04888 const T& val)
04889 {
04890
04891 int i;
04892
04893 for( i= 0; i < w * h ; i++)
04894 {
04895 v[i] = val;
04896 }
04897 }
04898
04899
04900 void
04901 container::add_item(
04902 const pt<obj_or_concept> i)
04903 {
04904 sorted_items.push_back(pos_and<pt<obj_or_concept> >(
04905 i, int_pair(drop_in_area.x + drop_in_area.w/3,
04906 drop_in_area.y + drop_in_area.h /3)));
04907 }
04908
04909
04910 void
04911 container::remove_item_not_recursively(
04912 const pt<obj_or_concept> item)
04913 {
04914
04915 list<pos_and<pt<obj_or_concept> > >::iterator i;
04916
04917
04918 foreach(i, sorted_items)
04919 {
04920 if (i->o == item)
04921 {
04922 i = sorted_items.erase(i);
04923 return;
04924 }
04925 }
04926
04927 assert(false);
04928 }
04929
04930
04931 bool
04932 container::remove_item_aux(
04933 const pt<obj_or_concept> item)
04934 {
04935
04936 list<pos_and<pt<obj_or_concept> > >::iterator i;
04937
04938
04939 foreach(i, sorted_items)
04940 {
04941 if (i->o == item)
04942 {
04943 i = sorted_items.erase(i);
04944 return true;
04945 }
04946 }
04947 return false;
04948
04949 }
04950
04951 bool
04952 container::remove_item_rec_aux(
04953 const pt<obj_or_concept> item)
04954 {
04955
04956 list<pos_and<pt<obj_or_concept> > >::const_iterator i;
04957 pt<container> container;
04958 bool ret, found;
04959
04960
04961 ret = remove_item_aux(item);
04962
04963 if(ret)
04964 {
04965 return true;
04966 }
04967 else
04968 {
04969 found = false;
04970 foreach(i, sorted_items){
04971 if (pt_cast(i->o, container))
04972 {
04973 ret = container->remove_item_rec_aux(item);
04974
04975 if(ret)
04976 found = true;
04977 }
04978 }
04979 return found;
04980 }
04981
04982 }
04983
04984
04985 void
04986 container::remove_item_recursively(
04987 const pt<obj_or_concept> item)
04988 {
04989 bool found;
04990
04991 found = remove_item_rec_aux(item);
04992
04993 if(!found)
04994 assert(false);
04995
04996 }
04997 void
04998 container::add_item_in_pos(
04999 pos_and<pt<obj_or_concept> > obj_and_pos)
05000 {
05001 sorted_items.push_back(obj_and_pos);
05002 }
05003
05004 bool
05005 FACK::contains_recursively(
05006 pt<container> cont,
05007 pt<obj_or_concept> o,
05008 pt<container> & real_cont,
05009 int_pair & pos )
05010 {
05011
05012 list<pos_and<pt<obj_or_concept> > >::const_iterator i;
05013 pt<container> container, con;
05014 int_pair po;
05015
05016
05017 if(contains_not_recursively(cont, o, po ))
05018 {
05019 real_cont = cont;
05020 pos = po;
05021 return true;
05022 }
05023 else
05024 {
05025 foreach(i, cont->sorted_items){
05026 if (pt_cast(i->o, container))
05027 {
05028 if(contains_recursively(container,
05029 o,
05030 con ,
05031 po ))
05032 {
05033 real_cont = con;
05034 pos = po;
05035 return true;
05036 }
05037 }
05038 }
05039
05040
05041
05042 return false;
05043 }
05044 }
05045
05046 bool
05047 FACK::contains_not_recursively(
05048 pt<container> cont,
05049 pt<obj_or_concept> o,
05050 int_pair & pos)
05051 {
05052
05053 list<pos_and<pt<obj_or_concept> > >::const_iterator i;
05054
05055
05056 foreach(i, cont->sorted_items){
05057 if (i->o == o )
05058 {
05059 pos = i->pos;
05060 return true;
05061 }
05062 }
05063
05064 pos = int_pair(-1, -1);
05065 return false;
05066 }
05067
05068
05069 bool
05070 container::can_contain_this_obj(pt<obj_or_concept> o)const
05071 {
05072
05073 pt<phys_obj> phys;
05074 pt<concept> conc;
05075 pt<container> cont;
05076 pt<zoomable> zoomab;
05077
05078
05079 if(type == CAN_CONTAIN_ANYTHING)
05080 return true;
05081 else if (pt_cast(o, zoomab))
05082 {
05083 return true;
05084 }
05085 else
05086 {
05087 if(pt_cast(o, cont))
05088 {
05089 return cont->type == type;
05090 }
05091 else
05092 {
05093 return ( (type == PHYS_OBJECTS && pt_cast(o, phys))
05094 ||
05095 (type == CONCEPTS && pt_cast(o, conc)));
05096 }
05097 }
05098
05099 }
05100
05101 bool
05102 container::can_be_moved_across_containers()const
05103 {
05104 return pick_up_info->can_be_moved_across_containers();
05105 }
05106 bool
05107 phys_obj::can_be_moved_across_containers()const
05108 {
05109 return pick_up_info->can_be_moved_across_containers();
05110 }
05111
05112 SDL_Rect
05113 create_rect(
05114 int x1, int y1, int x2, int y2)
05115 {
05116
05117 SDL_Rect r;
05118
05119
05120
05121 assert(x2 >= x1);
05122 assert(y2 >= y1);
05123
05124
05125 r.x = x1; r.y = y1;
05126 r.w = x2 - x1;
05127 r.h = y2 - y1;
05128 return r;
05129 }
05130
05131 special_button_pick_result
05132 FACK::special_button_at_pos(
05133 int_pair pos) const
05134 {
05135 if(point_in_rect(pos, this->zone_save_load_game))
05136 {
05137 return SBPR_SAVE_LOAD;
05138 }
05139 else if (point_in_rect(pos, this->zone_cycle_active_player))
05140 {
05141 return SBPR_CYCLE_PLAYER;
05142 }
05143 else if (point_in_rect(pos, this->zone_toggle_stay_follow))
05144 {
05145 return SBPR_STAY_FOLLOW;
05146 }
05147 else
05148 {
05149 return SBPR_NOTHING;
05150 }
05151 }
05152
05153 bool
05154 zoomable_zone::point_in_zone(int_pair point) const
05155 {
05156 return point_in_rect(point, rect);
05157
05158 }
05159
05160
05161 void
05162 FACK::update_light_transitions( float dt )
05163 {
05164
05165 list<pt<transition_of_fixed_light> > ::iterator t;
05166 pt<transition_of_fixed_light> tr;
05167 float m;
05168 set<pt<location> >::iterator lo;
05169
05170
05171
05172 for(t = transitions_of_fixed_light.begin();
05173 t != transitions_of_fixed_light.end();
05174 t++)
05175 {
05176 tr = *t;
05177 assert( tr->cur_timer < tr->end_timer);
05178
05179 tr->cur_timer += dt;
05180
05181 if (tr->cur_timer >= tr->end_timer)
05182 {
05183 tr->ligh->weight = tr->end_intensity;
05184
05185 t = transitions_of_fixed_light.erase(t);
05186
05187 if(tr->switch_off_light_at_the_end)
05188 {
05189 foreach( lo, locations){
05190 if(in( tr->ligh, (*lo)->active_lights))
05191 {
05192 (*lo)->active_lights.erase(tr->ligh);
05193 cout << "Erased light from loc" << endl;
05194 }
05195 }
05196 }
05197 }
05198 else
05199 {
05200 m = (tr->end_intensity - tr->start_intensity)/ tr->end_timer;
05201
05202 tr->ligh->weight =
05203 tr->start_intensity + m * tr->cur_timer;
05204
05205 }
05206
05207 }
05208 }
05209
05210
05211 pt<circle_t>
05212 FACK::circle_of_light(pt<light> l) const
05213 {
05214
05215 list<pt<PC> >::const_iterator p;
05216 pt<PC> pl;
05217 int_pair center, pos;
05218 pt<light_across_loc> torch;
05219 pt<dragging_state_maybe_dragging_obj> maybe_drag_obj;
05220
05221
05222 if(!pt_cast(l, torch))
05223 {
05224 return pt<circle_t>();
05225 }
05226 else
05227 {
05228 pl = pt<PC>();
05229
05230 foreach(p, players){
05231
05232 if( contains_not_recursively( (*p)->cache,
05233 torch->obj_which_emits_the_light,
05234 pos ))
05235 {
05236 pl = *p;
05237 break;
05238 }
05239 else if (pt_cast( (*p)->drag_st, maybe_drag_obj))
05240 {
05241 if (maybe_drag_obj->obj_and_pos.o == torch->obj_which_emits_the_light )
05242 {
05243 pl = *p;
05244 break;
05245 }
05246 }
05247 }
05248 assert(pl);
05249
05250 center = pl->pos;
05251
05252 return NEW(circle_t( torch->light_radius, center));
05253 }
05254 }
05255
05256
05257 void
05258 FACK::action(const string& eventId)
05259 {
05260
05261 if (eventId == "cancel_save_button_event")
05262 {
05263 gcn_save_window->setVisible(false);
05264 }
05265 else if (eventId == "gcn_options_quit_button")
05266 {
05267 must_exit = true;
05268 }
05269 else if (eventId == "gcn_options_save_button")
05270 {
05271 gcn_save_window->setVisible(true);
05272 gcn_top_container->moveToTop(gcn_save_window.get());
05273 gcn_options_window->setVisible(false);
05274 }
05275 else if (eventId == "gcn_options_load_button")
05276 {
05277 list_model->rescan_dir();
05278 gcn_load_window->setVisible(true);
05279 gcn_top_container->moveToTop(gcn_load_window.get());
05280 gcn_options_window->setVisible(false);
05281 }
05282 else if (eventId == "gcn_options_fullscreen_button")
05283 {
05284 SDL_WM_ToggleFullScreen(screen);
05285
05286 }
05287 else if (eventId == "gcn_cancel_load_button")
05288 {
05289 gcn_load_window->setVisible(false);
05290 }
05291 else if (eventId == "gcn_options_cancel_button")
05292 {
05293 gcn_options_window->setVisible(false);
05294 }
05295
05296
05297
05298 }
05299
05300
05301 dir_watcher_list_model::dir_watcher_list_model()
05302 {
05303 rescan_dir();
05304 }
05305
05306 int
05307 dir_watcher_list_model::getNumberOfElements()
05308 {
05309 return strings.size();
05310 }
05311
05312 string
05313 dir_watcher_list_model::getElementAt(int i)
05314 {
05315 return strings[i];
05316 }
05317
05318
05319 void
05320 dir_watcher_list_model::rescan_dir()
05321 {
05322
05323 boost::filesystem::directory_iterator itr;
05324 string::size_type q;
05325
05326
05327 strings.clear();
05328
05329 boost::filesystem::directory_iterator end_itr;
05330
05331 for ( itr = boost::filesystem::directory_iterator( boost::filesystem::current_path() );
05332 itr != end_itr;
05333 ++itr )
05334 {
05335 if (boost::filesystem::is_directory(*itr))
05336 {
05337
05338 }
05339 else
05340 {
05341 q = itr->leaf().find(".savegame");
05342 if (q != string::npos)
05343 {
05344 strings.push_back(itr->leaf());
05345 }
05346 }
05347 }
05348 }