source: trunk/UnitDetails.mm @ 26

Revision 26, 15.7 KB checked in by kpoole, 2 years ago (diff)

Episode 5

Line 
1//
2//  UnitDetails.m
3//  wesnoth
4//
5//  Created by Kyle Poole on 5/16/10.
6//  Copyright 2010 __MyCompanyName__. All rights reserved.
7//
8
9#import "UnitDetails.h"
10
11#include "unit_types.hpp"
12#include "game_preferences.hpp"
13#include "game_display.hpp"
14#include "map.hpp"
15#include "filesystem.hpp"
16
17@implementation UnitDetails
18
19@synthesize webView;
20
21extern UIView *gLandscapeView;
22extern bool gPauseForOpenFeint;
23
24extern const unit_type* gUnitType;
25
26
27
28/*
29 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
30- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
31    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
32        // Custom initialization
33    }
34    return self;
35}
36*/
37
38#define HTML_SPACER "     "
39
40
41// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
42- (void)viewDidLoad {
43    [super viewDidLoad];
44   
45//  [scrollView setContentSize:
46//    CGSizeMake(470, 768)
47//   ];
48   
49    // this will force the lazy loading to build this unit
50    unit_type_data::types().find_unit_type(gUnitType->id(), unit_type::WITHOUT_ANIMATIONS);
51   
52    std::stringstream ss;
53    std::string clear_stringstream;
54    const std::string detailed_description = gUnitType->unit_description();
55    const unit_type& female_type = gUnitType->get_gender_unit_type(unit_race::FEMALE);
56    const unit_type& male_type = gUnitType->get_gender_unit_type(unit_race::MALE);
57   
58    ss << "<html><body text='white' style='background-color: transparent; -webkit-user-select: none;'>";
59   
60    ss << "<h2>" << gUnitType->type_name() << "</h2>";
61   
62    // Show the unit's image and its level.
63    std::string filename = get_binary_file_location("images", male_type.image());
64    //SDL_SaveBMP(map_screenshot_surf_, filename.c_str());
65    ss << HTML_SPACER << "<img src='" << filename << "' style='border: 2px black solid;'></img> ";
66   
67    if (&female_type != &male_type)
68    {
69        filename = get_binary_file_location("images", female_type.image());
70        ss << "<img src='" << filename << "' style='border: 1px black solid;'></img> ";
71    }
72   
73   
74    ss << "<br>Level " << gUnitType->level();
75    /*
76     const std::string& male_portrait = male_type.image_profile();
77     const std::string& female_portrait = female_type.image_profile();
78     
79     if (male_portrait.empty() == false && male_portrait != male_type.image()) {
80     ss << "<img>src='" << male_portrait << "' align='right'</img> ";
81     }
82     
83     if (female_portrait.empty() == false && female_portrait != male_portrait && female_portrait != female_type.image()) {
84     ss << "<img>src='" << female_portrait << "' align='right'</img> ";
85     }
86     */
87    ss << "<br>";
88   
89    // Print cross-references to units that this unit advances from.
90    std::vector<shared_string> from_units = gUnitType->advances_from();
91    if (!from_units.empty())
92    {
93        ss << ("Advances from: ");
94        for (std::vector<shared_string>::const_iterator from_iter = from_units.begin();
95             from_iter != from_units.end();
96             ++from_iter)
97        {
98            std::string unit_id = *from_iter;
99            std::map<std::string,unit_type>::const_iterator type = unit_type_data::types().find_unit_type(unit_id);
100            if (type != unit_type_data::types().end() && !type->second.hide_help())
101            {
102                if (from_iter != from_units.begin()) ss << ", ";
103                std::string lang_unit = type->second.type_name();
104//              std::string ref_id;
105//              if (description_type(type->second) == FULL_DESCRIPTION) {
106//                  ref_id = unit_prefix + type->second.id();
107//              } else {
108//                  ref_id = unknown_unit_topic;
109//                  lang_unit += " (?)";
110//              }
111//              ss << "<ref>dst='" << escape(ref_id) << "' text='" << escape(lang_unit) << "'</ref>";
112                ss << lang_unit;
113            }
114        }
115        ss << "<br>";
116    }
117   
118    // Print the units this unit can advance to. Cross reference
119    // to the topics containing information about those units.
120    std::vector<shared_string> next_units = gUnitType->advances_to();
121    if (!next_units.empty()) {
122        ss << ("Advances to: ");
123        for (std::vector<shared_string>::const_iterator advance_it = next_units.begin(),
124             advance_end = next_units.end();
125             advance_it != advance_end; ++advance_it) {
126            std::string unit_id = *advance_it;
127            std::map<std::string,unit_type>::const_iterator type = unit_type_data::types().find_unit_type(unit_id);
128            if(type != unit_type_data::types().end() && !type->second.hide_help()) {
129                if (advance_it != next_units.begin()) ss << ", ";
130                std::string lang_unit = type->second.type_name();
131//              std::string ref_id;
132//              if (description_type(type->second) == FULL_DESCRIPTION) {
133//                  ref_id = unit_prefix + type->second.id();
134//              } else {
135//                  ref_id = unknown_unit_topic;
136//                  lang_unit += " (?)";
137//              }
138//              ss << "<ref>dst='" << escape(ref_id) << "' text='" << escape(lang_unit) << "'</ref>";
139                ss << lang_unit;
140            }
141        }
142        ss << "<br>";
143    }
144    if (gUnitType->can_advance())
145        ss << ("Required XP: ") << gUnitType->experience_needed() << "<br>";
146
147   
148    // Print the race of the unit, cross-reference it to the
149    // respective topic.
150/*  const std::string race_id = gUnitType->race();
151    std::string race_name;
152    const race_map::const_iterator race_it = unit_type_data::types().races().find(race_id);
153    if (race_it != unit_type_data::types().races().end()) {
154        race_name = race_it->second.plural_name().c_str();
155    } else {
156        race_name = ("Miscellaneous");
157    }
158    ss << ("Race: ");
159    ss << race_name;
160    ss << "<br>";
161*/ 
162    // Print some basic information such as HP and movement points.
163    ss << ("HP: ") << gUnitType->hitpoints() << HTML_SPACER
164    << ("Moves: ") << gUnitType->movement() << HTML_SPACER
165    << ("Cost: ") << gUnitType->cost() << HTML_SPACER
166    << ("<br>Alignment: ")
167    //<< "<ref>dst='time_of_day' text='"
168    << gUnitType->alignment_description(gUnitType->alignment(), gUnitType->genders().front())
169    //<< "'</ref>"
170    << "<br>";
171   
172    // Print the abilities the units has, cross-reference them
173    // to their respective topics.
174    if (!gUnitType->abilities().empty()) {
175        ss << ("<br>Abilities: ");
176        for(std::vector<shared_string>::const_iterator ability_it = gUnitType->abilities().begin(),
177            ability_end = gUnitType->abilities().end();
178            ability_it != ability_end; ++ability_it) {
179            const std::string ref_id = "ability_" + *ability_it;
180            std::string lang_ability = ability_it->c_str();
181            ss << lang_ability;
182            if (ability_it + 1 != ability_end)
183                ss << ", ";
184        }
185        ss << "<br>";
186    }
187   
188    // Print the extra AMLA upgrage abilities, cross-reference them
189    // to their respective topics.
190    if (!gUnitType->adv_abilities().empty()) {
191        ss << ("Ability Upgrades: ");
192        for(std::vector<shared_string>::const_iterator ability_it = gUnitType->adv_abilities().begin(),
193            ability_end = gUnitType->adv_abilities().end();
194            ability_it != ability_end; ++ability_it) {
195            const std::string ref_id = "ability_" + *ability_it;
196            std::string lang_ability = ability_it->c_str();
197            ss << lang_ability;
198            if (ability_it + 1 != ability_end)
199                ss << ", ";
200        }
201        ss << "<br>";
202    }
203    ss << "<br>";
204   
205   
206    // Print the detailed description about the unit.
207    ss << detailed_description;
208   
209    // Print the different attacks a unit has, if it has any.
210    std::vector<attack_type> attacks = gUnitType->attacks();
211    if (!attacks.empty()) {
212        // Print headers for the table.
213        //ss << "\n\n<header>text='" << escape(_("unit help^Attacks"))
214        //<< "'</header>\n\n";
215        ss << "<h2>Attacks</h2>";
216        //table_spec table;
217       
218        //std::vector<item> first_row;
219        // Dummy element, icons are below.
220        //first_row.push_back(item("", 0));
221        //push_header(first_row, _("unit help^Name"));
222        //push_header(first_row, _("Type"));
223        //push_header(first_row, _("Dmg"));
224        //push_header(first_row, _("Range"));
225        //push_header(first_row, _("Special"));
226        ss << "<table><tr><td></td><td><b>Name</b></td><td><b>Dmg</b></td><td><b>Range</b></td><td><b>Special</b></td></tr>";
227        //table.push_back(first_row);
228        // Print information about every attack.
229        for(std::vector<attack_type>::const_iterator attack_it = attacks.begin(),
230            attack_end = attacks.end();
231            attack_it != attack_end; ++attack_it) {
232            std::string lang_weapon = attack_it->name();
233            std::string lang_type = attack_it->type().c_str();
234            //std::vector<item> row;
235            //std::stringstream attack_ss;
236            //attack_ss << "<img src='" << (*attack_it).icon() << "'</img>";
237            ss << "<tr><td><img src='" << get_binary_file_location("images", (*attack_it).icon()) << "'</img></td><td>";
238            //row.push_back(std::make_pair(attack_ss.str(),
239            //                           image_width(attack_it->icon())));
240            ss << lang_weapon << HTML_SPACER << "</td>";
241            //push_tab_pair(row, lang_weapon);
242            //push_tab_pair(row, lang_type);
243            //attack_ss.str(clear_stringstream);
244            ss << "<td>" << attack_it->damage() << '-' << attack_it->num_attacks() << " " << attack_it->accuracy_parry_description();
245            ss << HTML_SPACER << "</td>";
246            //push_tab_pair(row, attack_ss.str());
247            //attack_ss.str(clear_stringstream);
248            //push_tab_pair(row, _((*attack_it).range().c_str()));
249            ss << "<td>" << (*attack_it).range() << HTML_SPACER << "</td>";
250            // Show this attack's special, if it has any. Cross
251            // reference it to the section describing the
252            // special.
253            std::vector<t_string> specials = attack_it->special_tooltips(true);
254            ss << "<td>";
255            if(!specials.empty())
256            {
257                std::string lang_special = "";
258                std::vector<t_string>::iterator sp_it;
259                for (sp_it = specials.begin(); sp_it != specials.end(); sp_it++) {
260                    const std::string ref_id = std::string("weaponspecial_")
261                    + *sp_it;
262                    lang_special = (*sp_it);
263                    //attack_ss << "<ref>dst='" << escape(ref_id)
264                    // << "' text='" << escape(lang_special) << "'</ref>";
265                    ss << lang_special;
266                   
267                    if((sp_it + 1) != specials.end() && (sp_it + 2) != specials.end())
268                    {
269                        //attack_ss << ", "; //comma placed before next special
270                        ss << ", ";
271                    }
272                    sp_it++; //skip description
273                }
274                //row.push_back(std::make_pair(attack_ss.str(),
275                //                           font::line_width(lang_special, normal_font_size)));
276               
277            }
278            ss << "</td>";
279            //table.push_back(row);
280            ss << "</tr>";
281        }
282        //ss << generate_table(table);
283        ss << "</table>";
284    }
285   
286    // Print the resistance table of the unit.
287    ss << "<h2>" << "Resistances"
288    << "</h2>";
289    //table_spec resistance_table;
290    //std::vector<item> first_res_row;
291    ss << "<table><tr><td><b>Attack Type</b>" << HTML_SPACER << "</td><td><b>Resistance</b></td></tr>";
292    //push_header(first_res_row, _("Attack Type"));
293    //push_header(first_res_row, _("Resistance"));
294    //resistance_table.push_back(first_res_row);
295    const unit_movement_type &movement_type = gUnitType->movement_type();
296    string_map dam_tab = movement_type.damage_table();
297    for(string_map::const_iterator dam_it = dam_tab.begin(), dam_end = dam_tab.end();
298        dam_it != dam_end; ++dam_it) {
299        //std::vector<item> row;
300        int resistance = 100 - atoi((*dam_it).second.c_str());
301        char resi[16];
302        snprintf(resi,sizeof(resi),"% 4d%%",resistance);    // range: -100% .. +70%
303        //FIXME: "white" is currently not a supported color key
304        //so the default grey-white will be used
305        std::string color;
306        if (resistance < 0)
307            color = "red";
308        else if (resistance <= 20)
309            color = "yellow";
310        else if (resistance <= 40)
311            color = "white";
312        else
313            color = "green";
314       
315        std::string lang_weapon = dam_it->first;
316        //push_tab_pair(row, lang_weapon);
317       
318        //std::stringstream str;
319        //str << "<format>color=" << color << " text='"<< resi << "'</format>";
320        //const std::string markup = str.str();
321        //str.str(clear_stringstream);
322        ss << "<tr><td>" << lang_weapon << "</td>";
323        ss << "<td><font color='" << color << "'>" << resi << "</font></td>";
324        //str << resi;
325        //row.push_back(std::make_pair(markup,
326        //                           font::line_width(str.str(), normal_font_size)));
327        //resistance_table.push_back(row);
328        ss << "</tr>";
329    }
330    //ss << generate_table(resistance_table);
331    ss << "</table>";
332   
333    const gamemap *map = &game_display::get_singleton()->get_map();
334    if (map != NULL) {
335        // Print the terrain modifier table of the unit.
336        ss << "<h2>" << "Terrain Modifiers"
337        << "</h2>";
338        //std::vector<item> first_row;
339        //table_spec table;
340        ss << "<table><tr><td><b>Terrain</b></td><td><b>Defense</b>" << HTML_SPACER << "</td><td><b>Move Cost</b></td></tr>";
341        //push_header(first_row, _("Terrain"));
342        //push_header(first_row, _("Defense"));
343        //push_header(first_row, _("Movement Cost"));
344       
345        //table.push_back(first_row);
346        std::set<t_translation::t_terrain>::const_iterator terrain_it =
347        preferences::encountered_terrains().begin();
348       
349        for (; terrain_it != preferences::encountered_terrains().end();
350             terrain_it++) {
351            const t_translation::t_terrain terrain = *terrain_it;
352            if (terrain == t_translation::FOGGED || terrain == t_translation::VOID_TERRAIN || terrain == t_translation::OFF_MAP_USER)
353                continue;
354            const terrain_type& info = map->get_terrain_info(terrain);
355           
356            if (info.union_type().size() == 1 && info.union_type()[0] == info.number() && info.is_nonnull()) {
357                //std::vector<item> row;
358                const std::string& name = info.name();
359                const std::string id = info.id();
360                const int moves = movement_type.movement_cost(*map,terrain);
361                std::stringstream str;
362                //str << "<ref>text='" << escape(name) << "' dst='"
363                //<< escape(std::string("terrain_") + id) << "'</ref>";
364                //row.push_back(std::make_pair(str.str(),
365                //                           font::line_width(name, normal_font_size)));
366                ss << "<tr><td>" << name << HTML_SPACER << "</td>";
367               
368                //defense  -  range: +10 % .. +70 %
369                //str.str(clear_stringstream);
370                const int defense =
371                100 - movement_type.defense_modifier(*map,terrain);
372                std::string color;
373                if (defense <= 10)
374                    color = "red";
375                else if (defense <= 30)
376                    color = "yellow";
377                else if (defense <= 50)
378                    color = "white";
379                else
380                    color = "green";
381               
382                //str << "<format>color=" << color << " text='"<< defense << "%'</format>";
383                ss << "<td><font color='" << color << "'>" << defense << "%</font></td>";
384               
385                //const std::string markup = str.str();
386                //str.str(clear_stringstream);
387                //str << defense << "%";
388                //row.push_back(std::make_pair(markup,
389                //                           font::line_width(str.str(), normal_font_size)));
390               
391                //movement  -  range: 1 .. 5, unit_movement_type::UNREACHABLE=impassable
392                //str.str(clear_stringstream);
393                const bool cannot_move = moves > gUnitType->movement();
394                if (cannot_move)        // cannot move in this terrain
395                    color = "red";
396                else if (moves > 1)
397                    color = "yellow";
398                else
399                    color = "white";
400               
401                //str << "<format>color=" << color << " text='";
402                ss << "<td><font color='" << color << "'>";
403               
404                // A 5 MP margin; if the movement costs go above
405                // the unit's max moves + 5, we replace it with dashes.
406                if(cannot_move && (moves > gUnitType->movement() + 5)) {
407                    ss << "-";
408                } else {
409                    ss << moves;
410                }
411                //str << "'</format>";
412                //push_tab_pair(row, str.str());
413                ss << "</font></td>";
414               
415                //table.push_back(row);
416                ss << "</tr>";
417            }
418        }
419        //ss << generate_table(table);
420        ss << "</table>";
421    }
422    //return ss.str();
423   
424    ss << "</body></html>";
425   
426    NSString *html = [NSString stringWithUTF8String:ss.str().c_str()];
427    webView.opaque = NO;
428    webView.backgroundColor = [UIColor clearColor];
429    [webView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
430   
431}
432
433/*
434// Override to allow orientations other than the default portrait orientation.
435- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
436    // Return YES for supported orientations
437    return (interfaceOrientation == UIInterfaceOrientationPortrait);
438}
439*/
440
441- (void)didReceiveMemoryWarning {
442    // Releases the view if it doesn't have a superview.
443    [super didReceiveMemoryWarning];
444   
445    // Release any cached data, images, etc that aren't in use.
446}
447
448- (void)viewDidUnload {
449    [super viewDidUnload];
450    // Release any retained subviews of the main view.
451    // e.g. self.myOutlet = nil;
452}
453
454
455- (void)dealloc {
456    [super dealloc];
457}
458
459-(IBAction)onOK:(id)sender
460{
461    [self.view removeFromSuperview];
462    gLandscapeView.hidden = YES;
463    gPauseForOpenFeint = false;
464}
465
466@end
Note: See TracBrowser for help on using the repository browser.