void GameStateLoad::readGameSlot(int slot) { stringstream filename; FileParser infile; // abort if not a valid slot number if (slot < 0 || slot >= GAME_SLOT_MAX) return; // save slots are named save#.txt filename << PATH_USER; if (GAME_PREFIX.length() > 0) filename << GAME_PREFIX << "_"; filename << "save" << (slot+1) << ".txt"; if (!infile.open(filename.str(),false, true, "")) return; while (infile.next()) { // load (key=value) pairs if (infile.key == "name") stats[slot].name = infile.val; else if (infile.key == "class") stats[slot].character_class = infile.val; else if (infile.key == "xp") stats[slot].xp = atoi(infile.val.c_str()); else if (infile.key == "build") { stats[slot].physical_character = atoi(infile.nextValue().c_str()); stats[slot].mental_character = atoi(infile.nextValue().c_str()); stats[slot].offense_character = atoi(infile.nextValue().c_str()); stats[slot].defense_character = atoi(infile.nextValue().c_str()); } else if (infile.key == "equipped") { string repeat_val = infile.nextValue(); while (repeat_val != "") { equipped[slot].push_back(toInt(repeat_val)); repeat_val = infile.nextValue(); } } else if (infile.key == "option") { stats[slot].base = infile.nextValue(); stats[slot].head = infile.nextValue(); stats[slot].portrait = infile.nextValue(); } else if (infile.key == "spawn") { current_map[slot] = getMapName(infile.nextValue()); } else if (infile.key == "permadeath") { stats[slot].permadeath = (toInt(infile.val) == 1); } } infile.close(); stats[slot].recalc(); loadPreview(slot); }
void MenuActionBar::update() { // Read data from config file FileParser infile; if (infile.open(mods->locate("menus/actionbar.txt"))) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "slot1") { slots[0].x = window_area.x+eatFirstInt(infile.val, ','); slots[0].y = window_area.y+eatFirstInt(infile.val, ','); slots[0].w = eatFirstInt(infile.val, ','); slots[0].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot2") { slots[1].x = window_area.x+eatFirstInt(infile.val, ','); slots[1].y = window_area.y+eatFirstInt(infile.val, ','); slots[1].w = eatFirstInt(infile.val, ','); slots[1].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot3") { slots[2].x = window_area.x+eatFirstInt(infile.val, ','); slots[2].y = window_area.y+eatFirstInt(infile.val, ','); slots[2].w = eatFirstInt(infile.val, ','); slots[2].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot4") { slots[3].x = window_area.x+eatFirstInt(infile.val, ','); slots[3].y = window_area.y+eatFirstInt(infile.val, ','); slots[3].w = eatFirstInt(infile.val, ','); slots[3].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot5") { slots[4].x = window_area.x+eatFirstInt(infile.val, ','); slots[4].y = window_area.y+eatFirstInt(infile.val, ','); slots[4].w = eatFirstInt(infile.val, ','); slots[4].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot6") { slots[5].x = window_area.x+eatFirstInt(infile.val, ','); slots[5].y = window_area.y+eatFirstInt(infile.val, ','); slots[5].w = eatFirstInt(infile.val, ','); slots[5].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot7") { slots[6].x = window_area.x+eatFirstInt(infile.val, ','); slots[6].y = window_area.y+eatFirstInt(infile.val, ','); slots[6].w = eatFirstInt(infile.val, ','); slots[6].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot8") { slots[7].x = window_area.x+eatFirstInt(infile.val, ','); slots[7].y = window_area.y+eatFirstInt(infile.val, ','); slots[7].w = eatFirstInt(infile.val, ','); slots[7].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot9") { slots[8].x = window_area.x+eatFirstInt(infile.val, ','); slots[8].y = window_area.y+eatFirstInt(infile.val, ','); slots[8].w = eatFirstInt(infile.val, ','); slots[8].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot10") { slots[9].x = window_area.x+eatFirstInt(infile.val, ','); slots[9].y = window_area.y+eatFirstInt(infile.val, ','); slots[9].w = eatFirstInt(infile.val, ','); slots[9].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot_M1") { slots[10].x = window_area.x+eatFirstInt(infile.val, ','); slots[10].y = window_area.y+eatFirstInt(infile.val, ','); slots[10].w = eatFirstInt(infile.val, ','); slots[10].h = eatFirstInt(infile.val, ','); } else if (infile.key == "slot_M2") { slots[11].x = window_area.x+eatFirstInt(infile.val, ','); slots[11].y = window_area.y+eatFirstInt(infile.val, ','); slots[11].w = eatFirstInt(infile.val, ','); slots[11].h = eatFirstInt(infile.val, ','); } else if (infile.key == "char_menu") { menus[0].x = window_area.x+eatFirstInt(infile.val, ','); menus[0].y = window_area.y+eatFirstInt(infile.val, ','); menus[0].w = eatFirstInt(infile.val, ','); menus[0].h = eatFirstInt(infile.val, ','); } else if (infile.key == "inv_menu") { menus[1].x = window_area.x+eatFirstInt(infile.val, ','); menus[1].y = window_area.y+eatFirstInt(infile.val, ','); menus[1].w = eatFirstInt(infile.val, ','); menus[1].h = eatFirstInt(infile.val, ','); } else if (infile.key == "powers_menu") { menus[2].x = window_area.x+eatFirstInt(infile.val, ','); menus[2].y = window_area.y+eatFirstInt(infile.val, ','); menus[2].w = eatFirstInt(infile.val, ','); menus[2].h = eatFirstInt(infile.val, ','); } else if (infile.key == "log_menu") { menus[3].x = window_area.x+eatFirstInt(infile.val, ','); menus[3].y = window_area.y+eatFirstInt(infile.val, ','); menus[3].w = eatFirstInt(infile.val, ','); menus[3].h = eatFirstInt(infile.val, ','); } else if (infile.key == "numberArea") { numberArea.x = window_area.x+eatFirstInt(infile.val, ','); numberArea.w = eatFirstInt(infile.val, ','); numberArea.h = eatFirstInt(infile.val, ','); } else if (infile.key == "mouseArea") { mouseArea.x = window_area.x+eatFirstInt(infile.val, ','); mouseArea.w = eatFirstInt(infile.val, ','); mouseArea.h = eatFirstInt(infile.val, ','); } else if (infile.key == "menuArea") { menuArea.x = window_area.x+eatFirstInt(infile.val, ','); menuArea.w = eatFirstInt(infile.val, ','); menuArea.h = eatFirstInt(infile.val, ','); } } infile.close(); } else fprintf(stderr, "Unable to open menus/actionbar.txt!\n"); // screen areas occupied by the three main sections numberArea.y = mouseArea.y = menuArea.y = window_area.y; // set keybinding labels for (unsigned int i=0; i<10; i++) { if (inpt->binding[i+6] < 8) labels[i]->set(slots[i].x+slots[i].w, slots[i].y+slots[i].h-12, JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+6]-1], font->getColor("menu_normal")); else labels[i]->set(slots[i].x+slots[i].w, slots[i].y+slots[i].h-12, JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+6]), font->getColor("menu_normal")); } for (unsigned int i=0; i<2; i++) { if (inpt->binding[i+20] < 8) labels[i+10]->set(slots[i+10].x+slots[i+10].w, slots[i+10].y+slots[i+10].h-12, JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+20]-1], font->getColor("menu_normal")); else labels[i+10]->set(slots[i+10].x+slots[i+10].w, slots[i+10].y+slots[i+10].h-12, JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+20]), font->getColor("menu_normal")); } for (unsigned int i=0; i<4; i++) { if (inpt->binding[i+16] < 8) labels[i+12]->set(menus[i].x+menus[i].w, menus[i].y+menus[i].h-12, JUSTIFY_RIGHT, VALIGN_TOP, inpt->mouse_button[inpt->binding[i+16]-1], font->getColor("menu_normal")); else labels[i+12]->set(menus[i].x+menus[i].w, menus[i].y+menus[i].h-12, JUSTIFY_RIGHT, VALIGN_TOP, SDL_GetKeyName((SDLKey)inpt->binding[i+16]), font->getColor("menu_normal")); } }
GameStateNew::GameStateNew() : GameState() { game_slot = 0; current_option = 0; option_count = 0; tip_buf.clear(); modified_name = false; // set up buttons button_exit = new WidgetButton("images/menus/buttons/button_default.png"); button_exit->label = msg->get("Cancel"); button_exit->pos.x = VIEW_W_HALF - button_exit->pos.w; button_exit->pos.y = VIEW_H - button_exit->pos.h; button_exit->refresh(); button_create = new WidgetButton("images/menus/buttons/button_default.png"); button_create->label = msg->get("Create"); button_create->pos.x = VIEW_W_HALF; button_create->pos.y = VIEW_H - button_create->pos.h; button_create->enabled = false; button_create->refresh(); button_prev = new WidgetButton("images/menus/buttons/left.png"); button_next = new WidgetButton("images/menus/buttons/right.png"); input_name = new WidgetInput(); button_permadeath = new WidgetCheckBox("images/menus/buttons/checkbox_default.png"); if (DEATH_PENALTY_PERMADEATH) { button_permadeath->enabled = false; button_permadeath->Check(); } class_list = new WidgetListBox (HERO_CLASSES.size(), 12, "images/menus/buttons/listbox_default.png"); class_list->can_deselect = false; class_list->selected[0] = true; show_classlist = true; tip = new WidgetTooltip(); // Read positions from config file FileParser infile; if (infile.open("menus/gamenew.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "button_prev") { button_prev->pos.x = eatFirstInt(infile.val, ','); button_prev->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "button_next") { button_next->pos.x = eatFirstInt(infile.val, ','); button_next->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "button_permadeath") { button_permadeath->pos.x = eatFirstInt(infile.val, ','); button_permadeath->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "name_input") { name_pos.x = eatFirstInt(infile.val, ','); name_pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "portrait_label") { portrait_label = eatLabelInfo(infile.val); } else if (infile.key == "name_label") { name_label = eatLabelInfo(infile.val); } else if (infile.key == "permadeath_label") { permadeath_label = eatLabelInfo(infile.val); } else if (infile.key == "classlist_label") { classlist_label = eatLabelInfo(infile.val); } else if (infile.key == "portrait") { portrait_pos.x = eatFirstInt(infile.val, ','); portrait_pos.y = eatFirstInt(infile.val, ','); portrait_pos.w = eatFirstInt(infile.val, ','); portrait_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "class_list") { class_list->pos.x = eatFirstInt(infile.val, ','); class_list->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "show_classlist") { int show_cl = eatFirstInt(infile.val, ','); if (show_cl == 1) show_classlist = true; else show_classlist = false; } } infile.close(); } button_prev->pos.x += (VIEW_W - FRAME_W)/2; button_prev->pos.y += (VIEW_H - FRAME_H)/2; button_next->pos.x += (VIEW_W - FRAME_W)/2; button_next->pos.y += (VIEW_H - FRAME_H)/2; class_list->pos.x += (VIEW_W - FRAME_W)/2; class_list->pos.y += (VIEW_H - FRAME_H)/2; name_pos.x += (VIEW_W - FRAME_W)/2; name_pos.y += (VIEW_H - FRAME_H)/2; input_name->setPosition(name_pos.x, name_pos.y); button_permadeath->pos.x += (VIEW_W - FRAME_W)/2; button_permadeath->pos.y += (VIEW_H - FRAME_H)/2; portrait_label.x += (VIEW_W - FRAME_W)/2; portrait_label.y += (VIEW_H - FRAME_H)/2; name_label.x += (VIEW_W - FRAME_W)/2; name_label.y += (VIEW_H - FRAME_H)/2; permadeath_label.x += (VIEW_W - FRAME_W)/2; permadeath_label.y += (VIEW_H - FRAME_H)/2; classlist_label.x += (VIEW_W - FRAME_W)/2; classlist_label.y += (VIEW_H - FRAME_H)/2; // set up labels color_normal = font->getColor("menu_normal"); label_portrait = new WidgetLabel(); label_portrait->set(portrait_label.x, portrait_label.y, portrait_label.justify, portrait_label.valign, msg->get("Choose a Portrait"), color_normal, portrait_label.font_style); label_name = new WidgetLabel(); label_name->set(name_label.x, name_label.y, name_label.justify, name_label.valign, msg->get("Choose a Name"), color_normal, name_label.font_style); label_permadeath = new WidgetLabel(); label_permadeath->set(permadeath_label.x, permadeath_label.y, permadeath_label.justify, permadeath_label.valign, msg->get("Permadeath?"), color_normal, permadeath_label.font_style); label_classlist = new WidgetLabel(); label_classlist->set(classlist_label.x, classlist_label.y, classlist_label.justify, classlist_label.valign, msg->get("Choose a Class"), color_normal, classlist_label.font_style); // set up class list for (unsigned i=0; i<HERO_CLASSES.size(); i++) { class_list->append(msg->get(HERO_CLASSES[i].name),getClassTooltip(i)); } loadGraphics(); loadOptions("hero_options.txt"); loadPortrait(portrait[0]); setName(name[0]); // Set up tab list tablist.add(button_exit); tablist.add(button_create); tablist.add(button_permadeath); tablist.add(button_prev); tablist.add(button_next); tablist.add(class_list); }
/** * load a statblock, typically for an enemy definition */ void StatBlock::load(const std::string& filename) { // @CLASS StatBlock: Enemies|Description of enemies in enemies/ FileParser infile; if (!infile.open(filename)) return; bool clear_loot = true; while (infile.next()) { if (infile.new_section) { // APPENDed file clear_loot = true; } int num = toInt(infile.val); float fnum = toFloat(infile.val); bool valid = loadCoreStat(&infile) || loadSfxStat(&infile); // @ATTR name|string|Name if (infile.key == "name") name = msg->get(infile.val); // @ATTR humanoid|boolean|This creature gives human traits when transformed into, such as the ability to talk with NPCs. else if (infile.key == "humanoid") humanoid = toBool(infile.val); // @ATTR level|integer|Level else if (infile.key == "level") level = num; // enemy death rewards and events // @ATTR xp|integer|XP awarded upon death. else if (infile.key == "xp") xp = num; else if (infile.key == "loot") { // @ATTR loot|[currency:item (integer)], chance (integer), min (integer), max (integer)|Possible loot that can be dropped on death. // loot entries format: // loot=[id],[percent_chance] // optionally allow range: // loot=[id],[percent_chance],[count_min],[count_max] if (clear_loot) { loot_table.clear(); clear_loot = false; } loot_table.push_back(Event_Component()); loot->parseLoot(infile, &loot_table.back(), &loot_table); } // @ATTR defeat_status|string|Campaign status to set upon death. else if (infile.key == "defeat_status") defeat_status = infile.val; // @ATTR convert_status|string|Campaign status to set upon being converted to a player ally. else if (infile.key == "convert_status") convert_status = infile.val; // @ATTR first_defeat_loot|integer|Drops this item upon first death. else if (infile.key == "first_defeat_loot") first_defeat_loot = num; // @ATTR quest_loot|[requires status (string), requires not status (string), item (integer)|Drops this item when campaign status is met. else if (infile.key == "quest_loot") { quest_loot_requires_status = infile.nextValue(); quest_loot_requires_not_status = infile.nextValue(); quest_loot_id = toInt(infile.nextValue()); } // combat stats // @ATTR cooldown|integer|Cooldown between attacks in 'ms' or 's'. else if (infile.key == "cooldown") cooldown = parse_duration(infile.val); // behavior stats // @ATTR flying|boolean|Creature can move over gaps/water. else if (infile.key == "flying") flying = toBool(infile.val); // @ATTR intangible|boolean|Creature can move through walls. else if (infile.key == "intangible") intangible = toBool(infile.val); // @ATTR facing|boolean|Creature can turn to face their target. else if (infile.key == "facing") facing = toBool(infile.val); // @ATTR waypoint_pause|duration|Duration to wait at each waypoint in 'ms' or 's'. else if (infile.key == "waypoint_pause") waypoint_pause = parse_duration(infile.val); // @ATTR turn_delay|duration|Duration it takes for this creature to turn and face their target in 'ms' or 's'. else if (infile.key == "turn_delay") turn_delay = parse_duration(infile.val); // @ATTR chance_pursue|integer|Percentage change that the creature will chase their target. else if (infile.key == "chance_pursue") chance_pursue = num; // @ATTR chance_flee|integer|Percentage chance that the creature will run away from their target. else if (infile.key == "chance_flee") chance_flee = num; // @ATTR chance_melee_phys|integer|Percentage chance that the creature will use their physical melee power. else if (infile.key == "chance_melee_phys") power_chance[MELEE_PHYS] = num; // @ATTR chance_melee_ment|integer|Percentage chance that the creature will use their mental melee power. else if (infile.key == "chance_melee_ment") power_chance[MELEE_MENT] = num; // @ATTR chance_ranged_phys|integer|Percentage chance that the creature will use their physical ranged power. else if (infile.key == "chance_ranged_phys") power_chance[RANGED_PHYS] = num; // @ATTR chance_ranged_ment|integer|Percentage chance that the creature will use their mental ranged power. else if (infile.key == "chance_ranged_ment") power_chance[RANGED_MENT] = num; // @ATTR power_melee_phys|integer|Power index for the physical melee power. else if (infile.key == "power_melee_phys") power_index[MELEE_PHYS] = powers->verifyID(num, &infile); // @ATTR power_melee_ment|integer|Power index for the mental melee power. else if (infile.key == "power_melee_ment") power_index[MELEE_MENT] = powers->verifyID(num, &infile); // @ATTR power_ranged_phys|integer|Power index for the physical ranged power. else if (infile.key == "power_ranged_phys") power_index[RANGED_PHYS] = powers->verifyID(num, &infile); // @ATTR power_ranged_ment|integer|Power index for the mental ranged power. else if (infile.key == "power_ranged_ment") power_index[RANGED_MENT] = powers->verifyID(num, &infile); // @ATTR power_beacon|integer|Power index of a "beacon" power used to aggro nearby creatures. else if (infile.key == "power_beacon") power_index[BEACON] = powers->verifyID(num, &infile); // @ATTR power_on_hit|integer|Power index that is triggered when hit. else if (infile.key == "power_on_hit") power_index[ON_HIT] = powers->verifyID(num, &infile); // @ATTR power_on_death|integer|Power index that is triggered when dead. else if (infile.key == "power_on_death") power_index[ON_DEATH] = powers->verifyID(num, &infile); // @ATTR power_on_half_dead|integer|Power index that is triggered when at half health. else if (infile.key == "power_on_half_dead") power_index[ON_HALF_DEAD] = powers->verifyID(num, &infile); // @ATTR power_on_debuff|integer|Power index that is triggered when under a negative status effect. else if (infile.key == "power_on_debuff") power_index[ON_DEBUFF] = powers->verifyID(num, &infile); // @ATTR power_on_join_combat|integer|Power index that is triggered when initiating combat. else if (infile.key == "power_on_join_combat") power_index[ON_JOIN_COMBAT] = powers->verifyID(num, &infile); // @ATTR chance_on_hit|integer|Percentage chance that power_on_hit will be triggered. else if (infile.key == "chance_on_hit") power_chance[ON_HIT] = num; // @ATTR chance_on_death|integer|Percentage chance that power_on_death will be triggered. else if (infile.key == "chance_on_death") power_chance[ON_DEATH] = num; // @ATTR chance_on_half_dead|integer|Percentage chance that power_on_half_dead will be triggered. else if (infile.key == "chance_on_half_dead") power_chance[ON_HALF_DEAD] = num; // @ATTR chance_on_debuff|integer|Percentage chance that power_on_debuff will be triggered. else if (infile.key == "chance_on_debuff") power_chance[ON_DEBUFF] = num; // @ATTR chance_on_join_combat|integer|Percentage chance that power_on_join_combat will be triggered. else if (infile.key == "chance_on_join_combat") power_chance[ON_JOIN_COMBAT] = num; // @ATTR cooldown_hit|duration|Duration of cooldown after being hit in 'ms' or 's'. else if (infile.key == "cooldown_hit") cooldown_hit = parse_duration(infile.val); else if (infile.key == "passive_powers") { // @ATTR passive_powers|power (integer), ...|A list of passive powers this creature has. powers_passive.clear(); std::string p = infile.nextValue(); while (p != "") { powers_passive.push_back(toInt(p)); p = infile.nextValue(); } } // @ATTR melee_range|float|Minimum distance from target required to use melee powers. else if (infile.key == "melee_range") melee_range = fnum; // @ATTR threat_range|float|Radius of the area this creature will be able to start chasing the hero. else if (infile.key == "threat_range") threat_range = fnum; // @ATTR combat_style|[default:aggressive:passive]|How the creature will enter combat. Default is within range of the hero; Aggressive is always in combat; Passive must be attacked to enter combat. else if (infile.key == "combat_style") { if (infile.val == "default") combat_style = COMBAT_DEFAULT; else if (infile.val == "aggressive") combat_style = COMBAT_AGGRESSIVE; else if (infile.val == "passive") combat_style = COMBAT_PASSIVE; else infile.error("StatBlock: Unknown combat style '%s'", infile.val.c_str()); } // @ATTR animations|string|Filename of an animation definition. else if (infile.key == "animations") animations = infile.val; // @ATTR suppress_hp|boolean|Hides the enemy HP bar for this creature. else if (infile.key == "suppress_hp") suppress_hp = toBool(infile.val); else if (infile.key == "categories") { // @ATTR categories|category (string), ...|Categories that this enemy belongs to. categories.clear(); std::string cat; while ((cat = infile.nextValue()) != "") { categories.push_back(cat); } } // this is only used for EnemyGroupManager // we check for them here so that we don't get an error saying they are invalid else if (infile.key == "rarity") ; // but do nothing else if (!valid) { infile.error("StatBlock: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); hp = starting[STAT_HP_MAX]; mp = starting[STAT_MP_MAX]; applyEffects(); }
GameStateConfig::GameStateConfig () : GameState(), child_widget(), ok_button(NULL), defaults_button(NULL), cancel_button(NULL), imgFileName(mods->locate("images/menus/config.png")) { // Load background image SDL_Surface * tmp = IMG_Load(imgFileName.c_str()); if (NULL == tmp) { fprintf(stderr, "Could not load image \"%s\" error \"%s\"\n", imgFileName.c_str(), IMG_GetError()); SDL_Quit(); exit(1); } background = SDL_DisplayFormatAlpha(tmp); SDL_FreeSurface(tmp); // Initialize Widgets tabControl = new WidgetTabControl(5); ok_button = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); defaults_button = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); cancel_button = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); for (unsigned int i = 0; i < 41; i++) { settings_lb[i] = new WidgetLabel(); } for (unsigned int i = 0; i < 3; i++) { settings_sl[i] = new WidgetSlider(mods->locate("images/menus/buttons/slider_default.png")); } for (unsigned int i = 0; i < 6; i++) { settings_cb[i] = new WidgetCheckBox(mods->locate("images/menus/buttons/checkbox_default.png")); } for (unsigned int i = 0; i < 50; i++) { settings_key[i] = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); } keyboard_layout = new WidgetComboBox(2, mods->locate("images/menus/buttons/combobox_default.png")); keyboard_layout->set(0, "QWERTY"); keyboard_layout->set(1, "AZERTY"); input_scrollbox = new WidgetScrollBox(600, 230, 780); input_scrollbox->pos.x = (VIEW_W - 640)/2 + 10; input_scrollbox->pos.y = (VIEW_H - 480)/2 + 150; input_scrollbox->refresh(); settings_btn[0] = new WidgetButton(mods->locate("images/menus/buttons/up.png")); settings_btn[1] = new WidgetButton(mods->locate("images/menus/buttons/down.png")); settings_btn[2] = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); settings_btn[3] = new WidgetButton(mods->locate("images/menus/buttons/button_default.png")); // Allocate Joycticks ComboBox settings_cmb[0] = new WidgetComboBox(SDL_NumJoysticks(), mods->locate("images/menus/buttons/combobox_default.png")); // Allocate Resolution ComboBox int resolutions = getVideoModes(); if (resolutions < 1) fprintf(stderr, "Unable to get resolutions list!\n"); settings_cmb[1] = new WidgetComboBox(resolutions, mods->locate("images/menus/buttons/combobox_default.png")); // Allocate Languages ComboBox int langCount = getLanguagesNumber(); language_ISO = new std::string[langCount]; language_full = new std::string[langCount]; settings_cmb[2] = new WidgetComboBox(langCount, mods->locate("images/menus/buttons/combobox_default.png")); // Allocate Mods ListBoxes vector<string> mod_dirs; getDirList(PATH_DATA + "mods", mod_dirs); settings_lstb[0] = new WidgetListBox(mod_dirs.size(), 5, mods->locate("images/menus/buttons/listbox_default.png")); settings_lstb[1] = new WidgetListBox(mod_dirs.size(), 5, mods->locate("images/menus/buttons/listbox_default.png")); //Load the menu configuration from file int x1; int y1; int x2; int y2; int setting_num; int offset_x; int offset_y; FileParser infile; if (infile.open(mods->locate("menus/config.txt"))) { while (infile.next()) { infile.val = infile.val + ','; x1 = eatFirstInt(infile.val, ','); y1 = eatFirstInt(infile.val, ','); x2 = eatFirstInt(infile.val, ','); y2 = eatFirstInt(infile.val, ','); setting_num = -1; if (infile.key == "fullscreen") setting_num = 1; else if (infile.key == "mouse_move") setting_num = 2; else if (infile.key == "combat_text") setting_num = 3; else if (infile.key == "hwsurface") setting_num = 4; else if (infile.key == "doublebuf") setting_num = 5; else if (infile.key == "enable_joystick") setting_num = 6; else if (infile.key == "music_volume") setting_num = 7; else if (infile.key == "sound_volume") setting_num = 8; else if (infile.key == "gamma") setting_num = 9; else if (infile.key == "joystick_device") setting_num = 10; else if (infile.key == "resolution") setting_num = 11; else if (infile.key == "language")setting_num = 12; else if (infile.key == "cancel") setting_num = 13 + CANCEL; else if (infile.key == "accept") setting_num = 13 + ACCEPT; else if (infile.key == "up") setting_num = 13 + UP; else if (infile.key == "down") setting_num = 13 + DOWN; else if (infile.key == "left") setting_num = 13 + LEFT; else if (infile.key == "right") setting_num = 13 + RIGHT; else if (infile.key == "bar1") setting_num = 13 + BAR_1; else if (infile.key == "bar2") setting_num = 13 + BAR_2; else if (infile.key == "bar3") setting_num = 13 + BAR_3; else if (infile.key == "bar4") setting_num = 13 + BAR_4; else if (infile.key == "bar5") setting_num = 13 + BAR_5; else if (infile.key == "bar6") setting_num = 13 + BAR_6; else if (infile.key == "bar7") setting_num = 13 + BAR_7; else if (infile.key == "bar8") setting_num = 13 + BAR_8; else if (infile.key == "bar9") setting_num = 13 + BAR_9; else if (infile.key == "bar0") setting_num = 13 + BAR_0; else if (infile.key == "main1") setting_num = 13 + MAIN1; else if (infile.key == "main2") setting_num = 13 + MAIN2; else if (infile.key == "character") setting_num = 13 + CHARACTER; else if (infile.key == "inventory") setting_num = 13 + INVENTORY; else if (infile.key == "powers") setting_num = 13 + POWERS; else if (infile.key == "log") setting_num = 13 + LOG; else if (infile.key == "ctrl") setting_num = 13 + CTRL; else if (infile.key == "shift") setting_num = 13 + SHIFT; else if (infile.key == "delete") setting_num = 13 + DEL; else if (infile.key == "hws_note") setting_num = 38; else if (infile.key == "dbuf_note") setting_num = 39; else if (infile.key == "activemods") setting_num = 40; else if (infile.key == "inactivemods") setting_num = 41; else if (infile.key == "activemods_shiftup") setting_num = 42; else if (infile.key == "activemods_shiftdown") setting_num = 43; else if (infile.key == "activemods_deactivate") setting_num = 44; else if (infile.key == "inactivemods_activate") setting_num = 45; else if (infile.key == "secondary_offset") {offset_x = x1; offset_y = y1;} else if (infile.key == "keyboard_layout") setting_num = 46; if (setting_num != -1) { if (setting_num > 12 && setting_num < 38) { settings_lb[setting_num-1]->setX(x1); settings_lb[setting_num-1]->setY(y1); } else if (setting_num < 42) { settings_lb[setting_num-1]->setX((VIEW_W - 640)/2 + x1); settings_lb[setting_num-1]->setY((VIEW_H - 480)/2 + y1); } if (setting_num < 7) { settings_cb[setting_num-1]->pos.x = (VIEW_W - 640)/2 + x2; settings_cb[setting_num-1]->pos.y = (VIEW_H - 480)/2 + y2; } else if ((setting_num > 6) && (setting_num < 10)) { settings_sl[setting_num-7]->pos.x = (VIEW_W - 640)/2 + x2; settings_sl[setting_num-7]->pos.y = (VIEW_H - 480)/2 + y2; } else if ((setting_num > 9) && (setting_num < 13)) { settings_cmb[setting_num-10]->pos.x = (VIEW_W - 640)/2 + x2; settings_cmb[setting_num-10]->pos.y = (VIEW_H - 480)/2 + y2; } else if (setting_num > 12 && setting_num < 39) { settings_key[setting_num-13]->pos.x = x2; settings_key[setting_num-13]->pos.y = y2; } else if (setting_num > 39 && setting_num < 42) { settings_lstb[setting_num-40]->pos.x = (VIEW_W - 640)/2 + x2; settings_lstb[setting_num-40]->pos.y = (VIEW_H - 480)/2 + y2; } else if (setting_num > 41 && setting_num < 46) { settings_btn[setting_num-42]->pos.x = (VIEW_W - 640)/2 + x1; settings_btn[setting_num-42]->pos.y = (VIEW_H - 480)/2 + y1; } else if (setting_num == 46) { keyboard_layout->pos.x = (VIEW_W - 640)/2 + x1; keyboard_layout->pos.y = (VIEW_H - 480)/2 + y1; } } } } else fprintf(stderr, "Unable to open config.txt!\n"); infile.close(); // Initialize the tab control. tabControl->setMainArea((VIEW_W - 640)/2, (VIEW_H - 480)/2, 640, 480); // Set positions of secondary key bindings for (unsigned int i = 25; i < 50; i++) { settings_key[i]->pos.x = settings_key[i-25]->pos.x + offset_x; settings_key[i]->pos.y = settings_key[i-25]->pos.y + offset_y; } // Define the header. tabControl->setTabTitle(0, msg->get("Video")); tabControl->setTabTitle(1, msg->get("Audio")); tabControl->setTabTitle(2, msg->get("Interface")); tabControl->setTabTitle(3, msg->get("Input")); tabControl->setTabTitle(4, msg->get("Mods")); tabControl->updateHeader(); // Define widgets ok_button->label = msg->get("Ok"); ok_button->pos.x = VIEW_W_HALF - ok_button->pos.w/2; ok_button->pos.y = VIEW_H - (cancel_button->pos.h*3); ok_button->refresh(); child_widget.push_back(ok_button); defaults_button->label = msg->get("Defaults"); defaults_button->pos.x = VIEW_W_HALF - defaults_button->pos.w/2; defaults_button->pos.y = VIEW_H - (cancel_button->pos.h*2); defaults_button->refresh(); child_widget.push_back(defaults_button); cancel_button->label = msg->get("Cancel"); cancel_button->pos.x = VIEW_W_HALF - cancel_button->pos.w/2; cancel_button->pos.y = VIEW_H - (cancel_button->pos.h); cancel_button->refresh(); child_widget.push_back(cancel_button); settings_lb[0]->set(msg->get("Full Screen Mode")); child_widget.push_back(settings_lb[0]); optiontab[child_widget.size()-1] = 0; child_widget.push_back(settings_cb[0]); optiontab[child_widget.size()-1] = 0; settings_lb[6]->set(msg->get("Music Volume")); child_widget.push_back(settings_lb[6]); optiontab[child_widget.size()-1] = 1; child_widget.push_back(settings_sl[0]); optiontab[child_widget.size()-1] = 1; settings_lb[7]->set(msg->get("Sound Volume")); child_widget.push_back(settings_lb[7]); optiontab[child_widget.size()-1] = 1; child_widget.push_back(settings_sl[1]); optiontab[child_widget.size()-1] = 1; settings_lb[8]->set(msg->get("Gamma")); child_widget.push_back(settings_lb[8]); optiontab[child_widget.size()-1] = 0; child_widget.push_back(settings_sl[2]); optiontab[child_widget.size()-1] = 0; settings_lb[1]->set(msg->get("Move hero using mouse")); child_widget.push_back(settings_lb[1]); optiontab[child_widget.size()-1] = 3; child_widget.push_back(settings_cb[1]); optiontab[child_widget.size()-1] = 3; settings_lb[2]->set(msg->get("Show combat text")); child_widget.push_back(settings_lb[2]); optiontab[child_widget.size()-1] = 2; child_widget.push_back(settings_cb[2]); optiontab[child_widget.size()-1] = 2; settings_lb[3]->set(msg->get("Hardware surfaces")); child_widget.push_back(settings_lb[3]); optiontab[child_widget.size()-1] = 0; child_widget.push_back(settings_cb[3]); optiontab[child_widget.size()-1] = 0; settings_lb[4]->set(msg->get("Double buffering")); child_widget.push_back(settings_lb[4]); optiontab[child_widget.size()-1] = 0; child_widget.push_back(settings_cb[4]); optiontab[child_widget.size()-1] = 0; settings_lb[5]->set(msg->get("Use joystick")); child_widget.push_back(settings_lb[5]); optiontab[child_widget.size()-1] = 3; child_widget.push_back(settings_cb[5]); optiontab[child_widget.size()-1] = 3; settings_lb[37]->set(msg->get("Try disabling for performance")); child_widget.push_back(settings_lb[37]); optiontab[child_widget.size()-1] = 0; settings_lb[38]->set(msg->get("Try disabling for performance")); child_widget.push_back(settings_lb[38]); optiontab[child_widget.size()-1] = 0; //Define ComboBoxes and their Labels settings_lb[10]->set(msg->get("Resolution")); child_widget.push_back(settings_lb[10]); optiontab[child_widget.size()-1] = 0; child_widget.push_back(settings_cmb[1]); optiontab[child_widget.size()-1] = 0; settings_lb[11]->set(msg->get("Language")); child_widget.push_back(settings_lb[11]); optiontab[child_widget.size()-1] = 2; child_widget.push_back(settings_cmb[2]); optiontab[child_widget.size()-1] = 2; settings_lb[9]->set(msg->get("Joystick")); child_widget.push_back(settings_lb[9]); optiontab[child_widget.size()-1] = 3; for(int i = 0; i < SDL_NumJoysticks(); i++) { settings_cmb[0]->set(i, SDL_JoystickName(i)); } child_widget.push_back(settings_cmb[0]); optiontab[child_widget.size()-1] = 3; // Add Key Binding objects for (unsigned int i = 12; i < 37; i++) { settings_lb[i]->set(binding_name[i-12]); child_widget.push_back(settings_lb[i]); optiontab[child_widget.size()-1] = 3; } for (unsigned int i = 0; i < 50; i++) { child_widget.push_back(settings_key[i]); optiontab[child_widget.size()-1] = 3; } keyboard_layout->refresh(); child_widget.push_back(keyboard_layout); optiontab[child_widget.size()-1] = 3; // Add ListBoxes settings_lb[39]->set(msg->get("Active Mods")); child_widget.push_back(settings_lb[39]); optiontab[child_widget.size()-1] = 4; settings_lstb[0]->multi_select = true; for (unsigned int i = 0; i < mods->mod_list.size() ; i++) { settings_lstb[0]->append(mods->mod_list[i],""); } child_widget.push_back(settings_lstb[0]); optiontab[child_widget.size()-1] = 4; settings_lb[40]->set(msg->get("Avaliable Mods")); child_widget.push_back(settings_lb[40]); optiontab[child_widget.size()-1] = 4; settings_lstb[1]->multi_select = true; for (unsigned int i = 0; i < mod_dirs.size(); i++) { settings_lstb[1]->append(mod_dirs[i],""); } child_widget.push_back(settings_lstb[1]); optiontab[child_widget.size()-1] = 4; // Add Button labels settings_btn[2]->label = msg->get("<< Deactivate"); settings_btn[3]->label = msg->get("Activate >>"); for (unsigned int i=0; i<4; i++) { settings_btn[i]->refresh(); child_widget.push_back(settings_btn[i]); optiontab[child_widget.size()-1] = 4; } update(); }
MenuStatBar::MenuStatBar(short _type) : bar(NULL) , label(new WidgetLabel()) , stat_min(0) , stat_cur(0) , stat_cur_prev(0) , stat_max(0) , orientation(HORIZONTAL) , custom_text_pos(false) // label will be placed in the middle of the bar , custom_string("") , bar_gfx("") , bar_gfx_background("") , type(_type) { std::string type_filename; if (type == TYPE_HP) type_filename = "hp"; else if (type == TYPE_MP) type_filename = "mp"; else if (type == TYPE_XP) type_filename = "xp"; // Load config settings FileParser infile; // @CLASS MenuStatBar|Description of menus/hp.txt, menus/mp.txt, menus/xp.txt if(!type_filename.empty() && infile.open("menus/" + type_filename + ".txt", FileParser::MOD_FILE, FileParser::ERROR_NORMAL)) { while(infile.next()) { if (parseMenuKey(infile.key, infile.val)) continue; // @ATTR bar_pos|rectangle|Position and dimensions of the bar graphics. if(infile.key == "bar_pos") { bar_pos = Parse::toRect(infile.val); } // @ATTR text_pos|label|Position of the text displaying the current value of the relevant stat. else if(infile.key == "text_pos") { custom_text_pos = true; text_pos = Parse::popLabelInfo(infile.val); } // @ATTR orientation|bool|True is vertical orientation; false is horizontal. else if(infile.key == "orientation") { orientation = Parse::toBool(infile.val); } // @ATTR bar_gfx|filename|Filename of the image to use for the "fill" of the bar. else if (infile.key == "bar_gfx") { bar_gfx = infile.val; } // @ATTR bar_gfx_background|filename|Filename of the image to use for the base of the bar. else if (infile.key == "bar_gfx_background") { bar_gfx_background = infile.val; } // @ATTR hide_timeout|duration|Hide HP and MP bar if full mana or health, after given amount of seconds; Hide XP bar if no changes in XP points for given amount of seconds. 0 disable hiding. else if (infile.key == "hide_timeout") { timeout.setDuration(Parse::toDuration(infile.val)); } else { infile.error("MenuStatBar: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); } loadGraphics(); align(); }
void ItemManager::loadSets(const string& filename) { FileParser infile; if (!infile.open(filename)) { fprintf(stderr, "Unable to open %s!\n", filename.c_str()); return; } int id = 0; bool id_line; while (infile.next()) { if (infile.key == "id") { id_line = true; id = toInt(infile.val); if (id > 0 && id >= (int)item_sets.size()) { // *2 to amortize the resizing to O(log(n)). item_sets.resize((2*id) + 1); } } else id_line = false; if (id < 1) { if (id_line) fprintf(stderr, "Item set index out of bounds 1-%d, skipping\n", INT_MAX); continue; } if (id_line) continue; if (infile.key == "name") { item_sets[id].name = msg->get(infile.val); } else if (infile.key == "items") { string item_id = infile.nextValue(); while (item_id != "") { if (toInt(item_id) > 0) { items[toInt(item_id)].set = id; item_sets[id].items.push_back(toInt(item_id)); item_id = infile.nextValue(); } else fprintf(stderr, "Item index inside item set %s definition out of bounds 1-%d, skipping item\n", item_sets[id].name.c_str(), INT_MAX); } } else if (infile.key == "color") { item_sets[id].color.r = toInt(infile.nextValue()); item_sets[id].color.g = toInt(infile.nextValue()); item_sets[id].color.b = toInt(infile.nextValue()); } else if (infile.key == "bonus") { Set_bonus bonus; bonus.requirement = toInt(infile.nextValue()); bonus.bonus_stat = infile.nextValue(); bonus.bonus_val = toInt(infile.nextValue()); item_sets[id].bonus.push_back(bonus); } } infile.close(); }
/** * Load a specific item sets file * * @param filename The (full) path and name of the file to load */ void ItemManager::loadSets(const std::string& filename, bool locateFileName) { FileParser infile; // @CLASS ItemManager: Sets|Definition of a item sets, items/sets.txt... if (!infile.open(filename, locateFileName)) return; bool clear_bonus = true; int id = 0; bool id_line; while (infile.next()) { if (infile.key == "id") { // @ATTR id|integer|A uniq id for the item set. id_line = true; id = toInt(infile.val); if (id > 0) { size_t new_size = id+1; if (item_sets.size() <= new_size) item_sets.resize(new_size); } clear_bonus = true; } else id_line = false; if (id < 1) { if (id_line) infile.error("ItemManager: Item set index out of bounds 1-%d, skipping set.", INT_MAX); continue; } if (id_line) continue; assert(item_sets.size() > std::size_t(id)); if (infile.key == "name") { // @ATTR name|string|Name of the item set. item_sets[id].name = msg->get(infile.val); } else if (infile.key == "items") { // @ATTR items|[item_id,...]|List of item id's that is part of the set. item_sets[id].items.clear(); std::string item_id = infile.nextValue(); while (item_id != "") { int temp_id = toInt(item_id); if (temp_id > 0 && temp_id < static_cast<int>(items.size())) { items[temp_id].set = id; item_sets[id].items.push_back(temp_id); } else { const int maxsize = static_cast<int>(items.size()-1); infile.error("ItemManager: Item index out of bounds 1-%d, skipping item.", maxsize); } item_id = infile.nextValue(); } } else if (infile.key == "color") { // @ATTR color|color|A specific of color for the set. item_sets[id].color = toRGB(infile.val); } else if (infile.key == "bonus") { // @ATTR bonus|[requirements (integer), bonus stat (string), bonus (integer)]|Bonus to append to items in the set. if (clear_bonus) { item_sets[id].bonus.clear(); clear_bonus = false; } Set_bonus bonus; bonus.requirement = toInt(infile.nextValue()); parseBonus(bonus, infile); item_sets[id].bonus.push_back(bonus); } else { infile.error("ItemManager: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); }
/** * Load a specific items file * * @param filename The (full) path and name of the file to load */ void ItemManager::loadItems(const std::string& filename, bool locateFileName) { FileParser infile; // @CLASS ItemManager: Items|Description about the class and it usage, items/items.txt... if (!infile.open(filename, locateFileName)) return; // used to clear vectors when overriding items bool clear_req_stat = true; bool clear_bonus = true; bool clear_loot_anim = true; bool clear_replace_power = true; int id = 0; bool id_line = false; while (infile.next()) { if (infile.key == "id") { // @ATTR id|integer|An uniq id of the item used as reference from other classes. id_line = true; id = toInt(infile.val); addUnknownItem(id); clear_req_stat = true; clear_bonus = true; clear_loot_anim = true; clear_replace_power = true; } else id_line = false; if (id < 1) { if (id_line) infile.error("ItemManager: Item index out of bounds 1-%d, skipping item.", INT_MAX); continue; } if (id_line) continue; assert(items.size() > std::size_t(id)); if (infile.key == "name") { // @ATTR name|string|Item name displayed on long and short tooltips. items[id].name = msg->get(infile.val); items[id].has_name = true; } else if (infile.key == "flavor") // @ATTR flavor|string|A description of the item. items[id].flavor = msg->get(infile.val); else if (infile.key == "level") // @ATTR level|integer|The item's level. Has no gameplay impact. (Deprecated?) items[id].level = toInt(infile.val); else if (infile.key == "icon") { // @ATTR icon|integer|An id for the icon to display for this item. items[id].icon = toInt(infile.nextValue()); } else if (infile.key == "book") { // @ATTR book|string|A book file to open when this item is activated. items[id].book = infile.val; } else if (infile.key == "quality") { // @ATTR quality|string|Item quality matching an id in items/qualities.txt items[id].quality = infile.val; } else if (infile.key == "item_type") { // @ATTR item_type|string|Equipment slot [artifact, head, chest, hands, legs, feets, main, off, ring] or base item type [gem, consumable] items[id].type = infile.val; } else if (infile.key == "equip_flags") { // @ATTR equip_flags|flag (string), ...|A comma separated list of flags to set when this item is equipped. See engine/equip_flags.txt. items[id].equip_flags.clear(); std::string flag = popFirstString(infile.val); while (flag != "") { items[id].equip_flags.push_back(flag); flag = popFirstString(infile.val); } } else if (infile.key == "dmg_melee") { // @ATTR dmg_melee|[min (integer), max (integer)]|Defines the item melee damage, if only min is specified the melee damage is fixed. items[id].dmg_melee_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_melee_max = toInt(infile.nextValue()); else items[id].dmg_melee_max = items[id].dmg_melee_min; } else if (infile.key == "dmg_ranged") { // @ATTR dmg_ranged|[min (integer), max (integer)]|Defines the item ranged damage, if only min is specified the ranged damage is fixed. items[id].dmg_ranged_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ranged_max = toInt(infile.nextValue()); else items[id].dmg_ranged_max = items[id].dmg_ranged_min; } else if (infile.key == "dmg_ment") { // @ATTR dmg_ment|[min (integer), max (integer)]|Defines the item mental damage, if only min is specified the ranged damage is fixed. items[id].dmg_ment_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ment_max = toInt(infile.nextValue()); else items[id].dmg_ment_max = items[id].dmg_ment_min; } else if (infile.key == "abs") { // @ATTR abs|[min (integer), max (integer)]|Defines the item absorb value, if only min is specified the absorb value is fixed. items[id].abs_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].abs_max = toInt(infile.nextValue()); else items[id].abs_max = items[id].abs_min; } else if (infile.key == "requires_level") { // @ATTR requires_level|integer|The hero's level must match or exceed this value in order to equip this item. items[id].requires_level = toInt(infile.val); } else if (infile.key == "requires_stat") { // @ATTR requires_stat|[ [physical:mental:offense:defense], amount (integer) ]|Make item require specific stat level ex. requires_stat=physical,6 will require hero to have level 6 in physical stats if (clear_req_stat) { items[id].req_stat.clear(); items[id].req_val.clear(); clear_req_stat = false; } std::string s = infile.nextValue(); if (s == "physical") items[id].req_stat.push_back(REQUIRES_PHYS); else if (s == "mental") items[id].req_stat.push_back(REQUIRES_MENT); else if (s == "offense") items[id].req_stat.push_back(REQUIRES_OFF); else if (s == "defense") items[id].req_stat.push_back(REQUIRES_DEF); else infile.error("%s unrecognized at; requires_stat must be one of [physical:mental:offense:defense]", s.c_str()); items[id].req_val.push_back(toInt(infile.nextValue())); } else if (infile.key == "requires_class") { // @ATTR requires_class|string|The hero's base class (engine/classes.txt) must match for this item to be equipped. items[id].requires_class = infile.val; } else if (infile.key == "bonus") { // @ATTR bonus|[stat_name (string), amount (integer)]|Adds a bonus to the item power_tag being a uniq tag of a power definition, e.: bonus=HP regen, 50 if (clear_bonus) { items[id].bonus.clear(); clear_bonus = false; } BonusData bdata; parseBonus(bdata, infile); items[id].bonus.push_back(bdata); } else if (infile.key == "soundfx") { // @ATTR soundfx|string|Sound effect filename to play for the specific item. items[id].sfx = infile.val; items[id].sfx_id = snd->load(items[id].sfx, "ItemManager"); } else if (infile.key == "gfx") // @ATTR gfx|string|Filename of an animation set to display when the item is equipped. items[id].gfx = infile.val; else if (infile.key == "loot_animation") { // @ATTR loot_animation|filename (string), min quantity (int), max quantity (int)|Specifies the loot animation file for the item. The max quantity, or both quantity values, may be omitted. if (clear_loot_anim) { items[id].loot_animation.clear(); clear_loot_anim = false; } LootAnimation la; la.name = popFirstString(infile.val); la.low = popFirstInt(infile.val); la.high = popFirstInt(infile.val); items[id].loot_animation.push_back(la); } else if (infile.key == "power") { // @ATTR power|power_id|Adds a specific power to the item which makes it usable as a power and can be placed in action bar. if (toInt(infile.val) > 0) items[id].power = toInt(infile.val); else infile.error("ItemManager: Power index out of bounds 1-%d, skipping power.", INT_MAX); } else if (infile.key == "replace_power") { // @ATTR replace_power|old (integer), new (integer)|Replaces the old power id with the new power id in the action bar when equipped. if (clear_replace_power) { items[id].replace_power.clear(); clear_replace_power = false; } Point power_ids = toPoint(infile.val); items[id].replace_power.push_back(power_ids); } else if (infile.key == "power_desc") // @ATTR power_desc|string|A string describing the additional power. items[id].power_desc = msg->get(infile.val); else if (infile.key == "price") // @ATTR price|integer|The amount of currency the item costs, if set to 0 the item cannot be sold. items[id].price = toInt(infile.val); else if (infile.key == "price_per_level") // @ATTR price_per_level|integer|Additional price for each player level above 1 items[id].price_per_level = toInt(infile.val); else if (infile.key == "price_sell") // @ATTR price_sell|integer|The amount of currency the item is sold for, if set to 0 the sell prices is prices*vendor_ratio. items[id].price_sell = toInt(infile.val); else if (infile.key == "max_quantity") // @ATTR max_quantity|integer|Max item count per stack. items[id].max_quantity = toInt(infile.val); else if (infile.key == "pickup_status") // @ATTR pickup_status|string|Set a campaign status when item is picked up, this is used for quest items. items[id].pickup_status = infile.val; else if (infile.key == "stepfx") // @ATTR stepfx|string|Sound effect when walking, this applies only to armors. items[id].stepfx = infile.val; else if (infile.key == "disable_slots") { // @ATTR disable_slots|type (string), ...|A comma separated list of equip slot types to disable when this item is equipped. items[id].disable_slots.clear(); std::string slot_type = popFirstString(infile.val); while (slot_type != "") { items[id].disable_slots.push_back(slot_type); slot_type = popFirstString(infile.val); } } else if (infile.key == "quest_item") { // @ATTR quest_item|bool|If true, this item is a quest item and can not be dropped, stashed, or sold. items[id].quest_item = toBool(infile.val); } else { infile.error("ItemManager: '%s' is not a valid key.", infile.key.c_str()); } } infile.close(); }
void LootManager::loadLootTables() { std::vector<std::string> filenames = mods->list("loot", false); for (unsigned i=0; i<filenames.size(); i++) { FileParser infile; if (!infile.open(filenames[i])) continue; std::vector<Event_Component> *ec_list = &loot_tables[filenames[i]]; Event_Component *ec = NULL; bool skip_to_next = false; while (infile.next()) { if (infile.section == "") { if (infile.key == "loot") { ec_list->push_back(Event_Component()); ec = &ec_list->back(); parseLoot(infile, ec, ec_list); } } else if (infile.section == "loot") { if (infile.new_section) { ec_list->push_back(Event_Component()); ec = &ec_list->back(); ec->type = "loot"; skip_to_next = false; } if (skip_to_next || ec == NULL) continue; if (infile.key == "id") { ec->s = infile.val; if (ec->s == "currency") ec->c = CURRENCY_ID; else if (toInt(ec->s, -1) != -1) ec->c = toInt(ec->s); else { skip_to_next = true; infile.error("LootManager: Invalid item id for loot."); } } else if (infile.key == "chance") { if (infile.val == "fixed") ec->z = 0; else ec->z = toInt(infile.val); } else if (infile.key == "quantity") { ec->a = toInt(infile.nextValue()); clampFloor(ec->a, 1); ec->b = toInt(infile.nextValue()); clampFloor(ec->b, ec->a); } } } infile.close(); } }
MenuCharacter::MenuCharacter(StatBlock *_stats) { stats = _stats; // Labels for major stats cstat_labels[CSTAT_NAME] = "Name"; cstat_labels[CSTAT_LEVEL] = "Level"; cstat_labels[CSTAT_PHYSICAL] = "Physical"; cstat_labels[CSTAT_MENTAL] = "Mental"; cstat_labels[CSTAT_OFFENSE] = "Offense"; cstat_labels[CSTAT_DEFENSE] = "Defense"; skill_points = 0; visible = false; newPowerNotification = false; for (int i=0; i<CSTAT_COUNT; i++) { cstat[i].label = new WidgetLabel(); cstat[i].value = new WidgetLabel(); cstat[i].hover.x = cstat[i].hover.y = 0; cstat[i].hover.w = cstat[i].hover.h = 0; cstat[i].visible = true; } for (int i=0; i<STATLIST_COUNT; i++) { show_stat[i] = true; } statlist_rows = 10; statlist_scrollbar_offset = 0; closeButton = new WidgetButton("images/menus/buttons/button_x.png"); // Upgrade buttons for (int i=0; i<4; i++) { upgradeButton[i] = new WidgetButton("images/menus/buttons/upgrade.png"); upgradeButton[i]->enabled = false; show_upgrade[i] = true; } physical_up = false; mental_up = false; offense_up = false; defense_up = false; // menu title labelCharacter = new WidgetLabel(); // unspent points labelUnspent = new WidgetLabel(); // Load config settings FileParser infile; // @CLASS MenuCharacter|Description of menus/character.txt if (infile.open("menus/character.txt")) { while(infile.next()) { if (parseMenuKey(infile.key, infile.val)) continue; // @ATTR close|x (integer), y (integer)|Position of the close button. if(infile.key == "close") close_pos = toPoint(infile.val); // @ATTR label_title|label|Position of the "Character" text. else if(infile.key == "label_title") title = eatLabelInfo(infile.val); // @ATTR upgrade_physical|x (integer), y (integer)|Position of the button used to add a stat point to Physical. else if(infile.key == "upgrade_physical") upgrade_pos[0] = toPoint(infile.val); // @ATTR upgrade_mental|x (integer), y (integer)|Position of the button used to add a stat point to Mental. else if(infile.key == "upgrade_mental") upgrade_pos[1] = toPoint(infile.val); // @ATTR upgrade_offense|x (integer), y (integer)|Position of the button used to add a stat point to Offense. else if(infile.key == "upgrade_offense") upgrade_pos[2] = toPoint(infile.val); // @ATTR upgrade_defense|x (integer), y (integer)|Position of the button used to add a stat point to Defense. else if(infile.key == "upgrade_defense") upgrade_pos[3] = toPoint(infile.val); // @ATTR statlist|x (integer), y (integer)|Position of the scrollbox containing non-primary stats. else if(infile.key == "statlist") statlist_pos = toPoint(infile.val); // @ATTR statlist_rows|integer|The height of the statlist in rows. else if (infile.key == "statlist_rows") statlist_rows = toInt(infile.val); // @ATTR statlist_scrollbar_offset|integer|Right margin in pixels for the statlist's scrollbar. else if (infile.key == "statlist_scrollbar_offset") statlist_scrollbar_offset = toInt(infile.val); // @ATTR label_name|label|Position of the "Name" text. else if(infile.key == "label_name") { label_pos[0] = eatLabelInfo(infile.val); cstat[CSTAT_NAME].visible = !label_pos[0].hidden; } // @ATTR label_level|label|Position of the "Level" text. else if(infile.key == "label_level") { label_pos[1] = eatLabelInfo(infile.val); cstat[CSTAT_LEVEL].visible = !label_pos[1].hidden; } // @ATTR label_physical|label|Position of the "Physical" text. else if(infile.key == "label_physical") { label_pos[2] = eatLabelInfo(infile.val); cstat[CSTAT_PHYSICAL].visible = !label_pos[2].hidden; } // @ATTR label_mental|label|Position of the "Mental" text. else if(infile.key == "label_mental") { label_pos[3] = eatLabelInfo(infile.val); cstat[CSTAT_MENTAL].visible = !label_pos[3].hidden; } // @ATTR label_offense|label|Position of the "Offense" text. else if(infile.key == "label_offense") { label_pos[4] = eatLabelInfo(infile.val); cstat[CSTAT_OFFENSE].visible = !label_pos[4].hidden; } // @ATTR label_defense|label|Position of the "Defense" text. else if(infile.key == "label_defense") { label_pos[5] = eatLabelInfo(infile.val); cstat[CSTAT_DEFENSE].visible = !label_pos[5].hidden; } // @ATTR name|x (integer), y (integer), w (integer), h (integer)|Position of the player's name and dimensions of the tooltip hotspot. else if(infile.key == "name") value_pos[0] = toRect(infile.val); // @ATTR level|x (integer), y (integer), w (integer), h (integer)|Position of the player's level and dimensions of the tooltip hotspot. else if(infile.key == "level") value_pos[1] = toRect(infile.val); // @ATTR physical|x (integer), y (integer), w (integer), h (integer)|Position of the player's physical stat and dimensions of the tooltip hotspot. else if(infile.key == "physical") value_pos[2] = toRect(infile.val); // @ATTR mental|x (integer), y (integer), w (integer), h (integer)|Position of the player's mental stat and dimensions of the tooltip hotspot. else if(infile.key == "mental") value_pos[3] = toRect(infile.val); // @ATTR offense|x (integer), y (integer), w (integer), h (integer)|Position of the player's offense stat and dimensions of the tooltip hotspot. else if(infile.key == "offense") value_pos[4] = toRect(infile.val); // @ATTR defense|x (integer), y (integer), w (integer), h (integer)|Position of the player's defense stat and dimensions of the tooltip hotspot. else if(infile.key == "defense") value_pos[5] = toRect(infile.val); // @ATTR upspent|label|Position of the label showing the number of unspent stat points. else if(infile.key == "unspent") unspent_pos = eatLabelInfo(infile.val); // @ATTR show_upgrade_physical|boolean|Hide the Physical upgrade button if set to false. else if (infile.key == "show_upgrade_physical") show_upgrade[0] = toBool(infile.val); // @ATTR show_upgrade_mental|boolean|Hide the Mental upgrade button if set to false. else if (infile.key == "show_upgrade_mental") show_upgrade[1] = toBool(infile.val); // @ATTR show_upgrade_offense|boolean|Hide the Offense upgrade button if set to false. else if (infile.key == "show_upgrade_offense") show_upgrade[2] = toBool(infile.val); // @ATTR show_upgrade_defense|boolean|Hide the Defense upgrade button if set to false. else if (infile.key == "show_upgrade_defense") show_upgrade[3] = toBool(infile.val); // @ATTR show_maxhp|boolean|Hide the "Max HP" stat in the statlist if set to false. else if (infile.key == "show_maxhp") show_stat[0] = toBool(infile.val); // @ATTR show_hpregen|boolean|Hide the "HP Regen" stat in the statlist if set to false. else if (infile.key == "show_hpregen") show_stat[1] = toBool(infile.val); // @ATTR show_maxmp|boolean|Hide the "Max MP" stat in the statlist if set to false. else if (infile.key == "show_maxmp") show_stat[2] = toBool(infile.val); // @ATTR show_mpregen|boolean|Hide the "MP Regen" stat in the statlist if set to false. else if (infile.key == "show_mpregen") show_stat[3] = toBool(infile.val); // @ATTR show_accuracy|boolean|Hide the "Accuracy" stat in the statlist if set to false. else if (infile.key == "show_accuracy") show_stat[4] = toBool(infile.val); // @ATTR show_avoidance|boolean|Hide the "Avoidance" stat in the statlist if set to false. else if (infile.key == "show_avoidance") show_stat[5] = toBool(infile.val); // @ATTR show_melee|boolean|Hide the "Melee Damage" stat in the statlist if set to false. else if (infile.key == "show_melee") show_stat[6] = toBool(infile.val); // @ATTR show_ranged|boolean|Hide the "Ranged Damage" stat in the statlist if set to false. else if (infile.key == "show_ranged") show_stat[7] = toBool(infile.val); // @ATTR show_mental|boolean|Hide the "Mental Damage" stat in the statlist if set to false. else if (infile.key == "show_mental") show_stat[8] = toBool(infile.val); // @ATTR show_crit|boolean|Hide the "Crit" stat in the statlist if set to false. else if (infile.key == "show_crit") show_stat[9] = toBool(infile.val); // @ATTR show_absorb|boolean|Hide the "Absorb" stat in the statlist if set to false. else if (infile.key == "show_absorb") show_stat[10] = toBool(infile.val); // @ATTR show_poise|boolean|Hide the "Poise" stat in the statlist if set to false. else if (infile.key == "show_poise") show_stat[11] = toBool(infile.val); // @ATTR show_bonus_xp|boolean|Hide the "Bonus XP" stat in the statlist if set to false. else if (infile.key == "show_bonus_xp") show_stat[12] = toBool(infile.val); // @ATTR show_bonus_currency|boolean|Hide the "Bonus Gold" stat in the statlist if set to false. else if (infile.key == "show_bonus_currency") show_stat[13] = toBool(infile.val); // @ATTR show_bonus_itemfind|boolean|Hide the "Bonus Item Find" stat in the statlist if set to false. else if (infile.key == "show_bonus_itemfind") show_stat[14] = toBool(infile.val); // @ATTR show_bonus_stealth|boolean|Hide the "Stealth" stat in the statlist if set to false. else if (infile.key == "show_bonus_stealth") show_stat[15] = toBool(infile.val); // @ATTR show_resists|boolean|Hide the elemental "Resistance" stats in the statlist if set to false. else if (infile.key == "show_resists") show_stat[16] = toBool(infile.val); } infile.close(); } // stat list statList = new WidgetListBox(STATLIST_COUNT-1+stats->vulnerable.size(), statlist_rows, "images/menus/buttons/listbox_char.png"); tablist.add(statList); statList->can_select = false; statList->scrollbar_offset = statlist_scrollbar_offset; setBackground("images/menus/character.png"); align(); alignElements(); }
void LootManager::parseLoot(FileParser &infile, Event_Component *e, std::vector<Event_Component> *ec_list) { if (e == NULL) return; std::string chance; bool first_is_filename = false; e->s = infile.nextValue(); if (e->s == "currency") e->c = CURRENCY_ID; else if (toInt(e->s, -1) != -1) e->c = toInt(e->s); else if (ec_list) { // load entire loot table std::string filename = e->s; // remove the last event component, since getLootTable() will create a new one if (e == &ec_list->back()) ec_list->pop_back(); getLootTable(filename, ec_list); first_is_filename = true; } if (!first_is_filename) { // make sure the type is "loot" e->type = "loot"; // drop chance chance = infile.nextValue(); if (chance == "fixed") e->z = 0; else e->z = toInt(chance); // quantity min/max e->a = toInt(infile.nextValue()); clampFloor(e->a, 1); e->b = toInt(infile.nextValue()); clampFloor(e->b, e->a); } // add repeating loot if (ec_list) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { ec_list->push_back(Event_Component()); Event_Component *ec = &ec_list->back(); ec->type = infile.key; ec->s = repeat_val; if (ec->s == "currency") ec->c = CURRENCY_ID; else if (toInt(ec->s, -1) != -1) ec->c = toInt(ec->s); else { // remove the last event component, since getLootTable() will create a new one ec_list->pop_back(); getLootTable(repeat_val, ec_list); repeat_val = infile.nextValue(); continue; } chance = infile.nextValue(); if (chance == "fixed") ec->z = 0; else ec->z = toInt(chance); ec->a = toInt(infile.nextValue()); clampFloor(ec->a, 1); ec->b = toInt(infile.nextValue()); clampFloor(ec->b, ec->a); repeat_val = infile.nextValue(); } } }
/** * Load the entity's animation from animation definition file */ void Entity::loadAnimations(const string& filename) { FileParser parser; if (!parser.open(mods->locate(filename).c_str())) { cout << "Error loading animation definition file: " << filename << endl; SDL_Quit(); exit(1); } string name = ""; int position = 0; int frames = 0; int duration = 0; Point render_size; Point render_offset; string type = ""; string firstAnimation = ""; int active_frame = 0; // Parse the file and on each new section create an animation object from the data parsed previously parser.next(); parser.new_section = false; // do not create the first animation object until parser has parsed first section do { // create the animation if finished parsing a section if (parser.new_section) { animations.push_back(new Animation(name, render_size, render_offset, position, frames, duration, type, active_frame)); } if (parser.key == "position") { if (isInt(parser.val)) { position = atoi(parser.val.c_str()); } } else if (parser.key == "frames") { if (isInt(parser.val)) { frames = atoi(parser.val.c_str()); } } else if (parser.key == "duration") { if (isInt(parser.val)) { int ms_per_frame = atoi(parser.val.c_str()); duration = (int)round((float)ms_per_frame / (1000.0 / (float)FRAMES_PER_SEC)); // adjust duration according to the entity's animation speed duration = (duration * 100) / stats.animationSpeed; // TEMP: if an animation is too fast, display one frame per fps anyway if (duration < 1) duration=1; } } else if (parser.key == "type") { type = parser.val; } else if (parser.key == "render_size_x") { if (isInt(parser.val)) { render_size.x = atoi(parser.val.c_str()); } } else if (parser.key == "render_size_y") { if (isInt(parser.val)) { render_size.y = atoi(parser.val.c_str()); } } else if (parser.key == "render_offset_x") { if (isInt(parser.val)) { render_offset.x = atoi(parser.val.c_str()); } } else if (parser.key == "render_offset_y") { if (isInt(parser.val)) { render_offset.y = atoi(parser.val.c_str()); } } else if (parser.key == "active_frame") { active_frame = atoi(parser.val.c_str()); } if (name == "") { // This is the first animation firstAnimation = parser.section; } name = parser.section; } while (parser.next()); // add final animation animations.push_back(new Animation(name, render_size, render_offset, position, frames, duration, type, active_frame)); // set the default animation if (firstAnimation != "") { setAnimation(firstAnimation); } }
GameStateLoad::GameStateLoad() : GameState() { items = new ItemManager(); portrait = NULL; loading_requested = false; loading = false; loaded = false; label_loading = new WidgetLabel(); for (int i = 0; i < GAME_SLOT_MAX; i++) { label_name[i] = new WidgetLabel(); label_level[i] = new WidgetLabel(); label_map[i] = new WidgetLabel(); } // Confirmation box to confirm deleting confirm = new MenuConfirm(msg->get("Delete Save"), msg->get("Delete this save?")); button_exit = new WidgetButton("images/menus/buttons/button_default.png"); button_exit->label = msg->get("Exit to Title"); button_exit->pos.x = VIEW_W_HALF - button_exit->pos.w/2; button_exit->pos.y = VIEW_H - button_exit->pos.h; button_exit->refresh(); button_action = new WidgetButton("images/menus/buttons/button_default.png"); button_action->label = msg->get("Choose a Slot"); button_action->enabled = false; button_alternate = new WidgetButton("images/menus/buttons/button_default.png"); button_alternate->label = msg->get("Delete Save"); button_alternate->enabled = false; // Set up tab list tablist = TabList(HORIZONTAL); tablist.add(button_exit); // Read positions from config file FileParser infile; if (infile.open("menus/gameload.txt")) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "action_button") { button_action->pos.x = eatFirstInt(infile.val, ','); button_action->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "atlernate_button") { button_alternate->pos.x = eatFirstInt(infile.val, ','); button_alternate->pos.y = eatFirstInt(infile.val, ','); } else if (infile.key == "portrait") { portrait_pos.x = eatFirstInt(infile.val, ','); portrait_pos.y = eatFirstInt(infile.val, ','); portrait_pos.w = eatFirstInt(infile.val, ','); portrait_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "gameslot") { gameslot_pos.x = eatFirstInt(infile.val, ','); gameslot_pos.y = eatFirstInt(infile.val, ','); gameslot_pos.w = eatFirstInt(infile.val, ','); gameslot_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "preview") { preview_pos.x = eatFirstInt(infile.val, ','); preview_pos.y = eatFirstInt(infile.val, ','); preview_pos.w = eatFirstInt(infile.val, ','); preview_pos.h = eatFirstInt(infile.val, ','); // label positions within each slot } else if (infile.key == "name") { name_pos = eatLabelInfo(infile.val); } else if (infile.key == "level") { level_pos = eatLabelInfo(infile.val); } else if (infile.key == "map") { map_pos = eatLabelInfo(infile.val); } else if (infile.key == "loading_label") { loading_pos = eatLabelInfo(infile.val); // Position for the avatar preview image in each slot } else if (infile.key == "sprite") { sprites_pos.x = eatFirstInt(infile.val, ','); sprites_pos.y = eatFirstInt(infile.val, ','); } } infile.close(); } // Load the MenuConfirm positions and alignments from menus/menus.txt if (infile.open("menus/menus.txt")) { int menu_index = -1; while (infile.next()) { if (infile.key == "id") { if (infile.val == "confirm") menu_index = 0; else menu_index = -1; } if (menu_index == -1) continue; if (infile.key == "layout") { infile.val = infile.val + ','; confirm->window_area.x = eatFirstInt(infile.val, ','); confirm->window_area.y = eatFirstInt(infile.val, ','); confirm->window_area.w = eatFirstInt(infile.val, ','); confirm->window_area.h = eatFirstInt(infile.val, ','); } if (infile.key == "align") { confirm->alignment = infile.val; } } infile.close(); } confirm->align(); confirm->update(); // get displayable types list bool found_layer = false; if (infile.open("engine/hero_options.txt")) { while(infile.next()) { infile.val = infile.val + ','; if (infile.key == "layer") { unsigned dir = eatFirstInt(infile.val,','); if (dir != 6) continue; else found_layer = true; string layer = eatFirstString(infile.val,','); while (layer != "") { preview_layer.push_back(layer); layer = eatFirstString(infile.val,','); } } } infile.close(); } if (!found_layer) fprintf(stderr, "Warning: Could not find layers for direction 6\n"); button_action->pos.x += (VIEW_W - FRAME_W)/2; button_action->pos.y += (VIEW_H - FRAME_H)/2; button_action->refresh(); button_alternate->pos.x += (VIEW_W - FRAME_W)/2; button_alternate->pos.y += (VIEW_H - FRAME_H)/2; button_alternate->refresh(); load_game = false; for (int i=0; i<GAME_SLOT_MAX; i++) { current_map[i] = ""; } loadGraphics(); readGameSlots(); for (int i=0; i<GAME_SLOT_MAX; i++) { slot_pos[i].x = gameslot_pos.x + (VIEW_W - FRAME_W)/2; slot_pos[i].h = gameslot_pos.h; slot_pos[i].y = gameslot_pos.y + (VIEW_H - FRAME_H)/2 + (i * gameslot_pos.h); slot_pos[i].w = gameslot_pos.w; } selected_slot = -1; // temp current_frame = 0; frame_ticker = 0; color_normal = font->getColor("menu_normal"); }
void GameStateLoad::readGameSlot(int slot) { stringstream filename; FileParser infile; // abort if not a valid slot number if (slot < 0 || slot >= GAME_SLOT_MAX) return; // save slots are named save#.txt filename << "save" << (slot+1) << ".txt"; if (!infile.open(PATH_USER + filename.str())) return; while (infile.next()) { // load (key=value) pairs if (infile.key == "name") stats[slot].name = infile.val; else if (infile.key == "xp") stats[slot].xp = atoi(infile.val.c_str()); else if (infile.key == "build") { stats[slot].physical_character = atoi(infile.nextValue().c_str()); stats[slot].mental_character = atoi(infile.nextValue().c_str()); stats[slot].offense_character = atoi(infile.nextValue().c_str()); stats[slot].defense_character = atoi(infile.nextValue().c_str()); } else if (infile.key == "equipped") { equipped[slot][0] = atoi(infile.nextValue().c_str()); equipped[slot][1] = atoi(infile.nextValue().c_str()); equipped[slot][2] = atoi(infile.nextValue().c_str()); } else if (infile.key == "option") { stats[slot].base = infile.nextValue(); stats[slot].head = infile.nextValue(); stats[slot].portrait = infile.nextValue(); } else if (infile.key == "spawn") { current_map[slot] = getMapName(infile.nextValue()); } } infile.close(); stats[slot].recalc(); loadPreview(slot); }
/** * All powers are defined in powers/powers.txt */ void PowerManager::loadPowers() { FileParser infile; int input_id = 0; if (infile.open((PATH_DATA + "powers/powers.txt").c_str())) { while (infile.next()) { // id needs to be the first component of each power. That is how we write // data to the correct power. if (infile.key == "id") { input_id = atoi(infile.val.c_str()); } else if (infile.key == "type") { if (infile.val == "single") powers[input_id].type = POWTYPE_SINGLE; else if (infile.val == "effect") powers[input_id].type = POWTYPE_EFFECT; else if (infile.val == "missile") powers[input_id].type = POWTYPE_MISSILE; else if (infile.val == "repeater") powers[input_id].type = POWTYPE_REPEATER; } else if (infile.key == "name") { powers[input_id].name = infile.val; } else if (infile.key == "description") { powers[input_id].description = infile.val; } else if (infile.key == "icon") { powers[input_id].icon = atoi(infile.val.c_str()); } else if (infile.key == "new_state") { if (infile.val == "swing") powers[input_id].new_state = POWSTATE_SWING; else if (infile.val == "shoot") powers[input_id].new_state = POWSTATE_SHOOT; else if (infile.val == "cast") powers[input_id].new_state = POWSTATE_CAST; else if (infile.val == "block") powers[input_id].new_state = POWSTATE_BLOCK; } else if (infile.key == "face") { if (infile.val == "true") powers[input_id].face = true; } else if (infile.key == "source_type") { if (infile.val == "hero") powers[input_id].source_type = SOURCE_TYPE_HERO; else if (infile.val == "neutral") powers[input_id].source_type = SOURCE_TYPE_NEUTRAL; else if (infile.val == "enemy") powers[input_id].source_type = SOURCE_TYPE_ENEMY; } else if (infile.key == "beacon") { if (infile.val == "true") powers[input_id].beacon = true; } // power requirements else if (infile.key == "requires_physical_weapon") { if (infile.val == "true") powers[input_id].requires_physical_weapon = true; } else if (infile.key == "requires_mental_weapon") { if (infile.val == "true") powers[input_id].requires_mental_weapon = true; } else if (infile.key == "requires_offense_weapon") { if (infile.val == "true") powers[input_id].requires_offense_weapon = true; } else if (infile.key == "requires_mp") { powers[input_id].requires_mp = atoi(infile.val.c_str()); } else if (infile.key == "requires_los") { if (infile.val == "true") powers[input_id].requires_los = true; } else if (infile.key == "requires_empty_target") { if (infile.val == "true") powers[input_id].requires_empty_target = true; } else if (infile.key == "requires_item") { powers[input_id].requires_item = atoi(infile.val.c_str()); } else if (infile.key == "requires_targeting") { if (infile.val == "true") powers[input_id].requires_targeting = true; } else if (infile.key == "cooldown") { powers[input_id].cooldown = atoi(infile.val.c_str()); } // animation info else if (infile.key == "gfx") { powers[input_id].gfx_index = loadGFX(infile.val); } else if (infile.key == "sfx") { powers[input_id].sfx_index = loadSFX(infile.val); } else if (infile.key == "rendered") { if (infile.val == "true") powers[input_id].rendered = true; } else if (infile.key == "directional") { if (infile.val == "true") powers[input_id].directional = true; } else if (infile.key == "visual_random") { powers[input_id].visual_random = atoi(infile.val.c_str()); } else if (infile.key == "visual_option") { powers[input_id].visual_option = atoi(infile.val.c_str()); } else if (infile.key == "aim_assist") { powers[input_id].aim_assist = atoi(infile.val.c_str()); } else if (infile.key == "speed") { powers[input_id].speed = atoi(infile.val.c_str()); } else if (infile.key == "lifespan") { powers[input_id].lifespan = atoi(infile.val.c_str()); } else if (infile.key == "frame_loop") { powers[input_id].frame_loop = atoi(infile.val.c_str()); } else if (infile.key == "frame_duration") { powers[input_id].frame_duration = atoi(infile.val.c_str()); } else if (infile.key == "frame_size") { powers[input_id].frame_size.x = atoi(infile.nextValue().c_str()); powers[input_id].frame_size.y = atoi(infile.nextValue().c_str()); } else if (infile.key == "frame_offset") { powers[input_id].frame_offset.x = atoi(infile.nextValue().c_str()); powers[input_id].frame_offset.y = atoi(infile.nextValue().c_str()); } else if (infile.key == "floor") { if (infile.val == "true") powers[input_id].floor = true; } else if (infile.key == "active_frame") { powers[input_id].active_frame = atoi(infile.val.c_str()); } else if (infile.key == "complete_animation") { if (infile.val == "true") powers[input_id].complete_animation = true; } // hazard traits else if (infile.key == "use_hazard") { if (infile.val == "true") powers[input_id].use_hazard = true; } else if (infile.key == "no_attack") { if (infile.val == "true") powers[input_id].no_attack = true; } else if (infile.key == "radius") { powers[input_id].radius = atoi(infile.val.c_str()); } else if (infile.key == "base_damage") { if (infile.val == "none") powers[input_id].base_damage = BASE_DAMAGE_NONE; else if (infile.val == "melee") powers[input_id].base_damage = BASE_DAMAGE_MELEE; else if (infile.val == "ranged") powers[input_id].base_damage = BASE_DAMAGE_RANGED; else if (infile.val == "ment") powers[input_id].base_damage = BASE_DAMAGE_MENT; } else if (infile.key == "damage_multiplier") { powers[input_id].damage_multiplier = atoi(infile.val.c_str()); } else if (infile.key == "starting_pos") { if (infile.val == "source") powers[input_id].starting_pos = STARTING_POS_SOURCE; else if (infile.val == "target") powers[input_id].starting_pos = STARTING_POS_TARGET; else if (infile.val == "melee") powers[input_id].starting_pos = STARTING_POS_MELEE; } else if (infile.key == "multitarget") { if (infile.val == "true") powers[input_id].multitarget = true; } else if (infile.key == "trait_armor_penetration") { if (infile.val == "true") powers[input_id].trait_armor_penetration = true; } else if (infile.key == "trait_crits_impaired") { powers[input_id].trait_crits_impaired = atoi(infile.val.c_str()); } else if (infile.key == "trait_elemental") { if (infile.val == "wood") powers[input_id].trait_elemental = ELEMENT_WOOD; else if (infile.val == "metal") powers[input_id].trait_elemental = ELEMENT_METAL; else if (infile.val == "wind") powers[input_id].trait_elemental = ELEMENT_WIND; else if (infile.val == "water") powers[input_id].trait_elemental = ELEMENT_WATER; else if (infile.val == "earth") powers[input_id].trait_elemental = ELEMENT_EARTH; else if (infile.val == "fire") powers[input_id].trait_elemental = ELEMENT_FIRE; else if (infile.val == "shadow") powers[input_id].trait_elemental = ELEMENT_SHADOW; else if (infile.val == "light") powers[input_id].trait_elemental = ELEMENT_LIGHT; } //steal effects else if (infile.key == "hp_steal") { powers[input_id].hp_steal = atoi(infile.val.c_str()); } else if (infile.key == "mp_steal") { powers[input_id].mp_steal = atoi(infile.val.c_str()); } //missile modifiers else if (infile.key == "missile_num") { powers[input_id].missile_num = atoi(infile.val.c_str()); } else if (infile.key == "missile_angle") { powers[input_id].missile_angle = atoi(infile.val.c_str()); } else if (infile.key == "angle_variance") { powers[input_id].angle_variance = atoi(infile.val.c_str()); } else if (infile.key == "speed_variance") { powers[input_id].speed_variance = atoi(infile.val.c_str()); } //repeater modifiers else if (infile.key == "delay") { powers[input_id].delay = atoi(infile.val.c_str()); } else if (infile.key == "start_frame") { powers[input_id].start_frame = atoi(infile.val.c_str()); } else if (infile.key == "repeater_num") { powers[input_id].repeater_num = atoi(infile.val.c_str()); } // buff/debuff durations else if (infile.key == "bleed_duration") { powers[input_id].bleed_duration = atoi(infile.val.c_str()); } else if (infile.key == "stun_duration") { powers[input_id].stun_duration = atoi(infile.val.c_str()); } else if (infile.key == "slow_duration") { powers[input_id].slow_duration = atoi(infile.val.c_str()); } else if (infile.key == "immobilize_duration") { powers[input_id].immobilize_duration = atoi(infile.val.c_str()); } else if (infile.key == "immunity_duration") { powers[input_id].immunity_duration = atoi(infile.val.c_str()); } else if (infile.key == "haste_duration") { powers[input_id].haste_duration = atoi(infile.val.c_str()); } else if (infile.key == "hot_duration") { powers[input_id].hot_duration = atoi(infile.val.c_str()); } else if (infile.key == "hot_value") { powers[input_id].hot_value = atoi(infile.val.c_str()); } // buffs else if (infile.key == "buff_heal") { if (infile.val == "true") powers[input_id].buff_heal = true; } else if (infile.key == "buff_shield") { if (infile.val == "true") powers[input_id].buff_shield = true; } else if (infile.key == "buff_teleport") { if (infile.val == "true") powers[input_id].buff_teleport = true; } else if (infile.key == "buff_immunity") { if (infile.val == "true") powers[input_id].buff_immunity = true; } else if (infile.key == "buff_restore_hp") { powers[input_id].buff_restore_hp = atoi(infile.val.c_str()); } else if (infile.key == "buff_restore_mp") { powers[input_id].buff_restore_mp = atoi(infile.val.c_str()); } // pre and post power effects else if (infile.key == "post_power") { powers[input_id].post_power = atoi(infile.val.c_str()); } else if (infile.key == "wall_power") { powers[input_id].wall_power = atoi(infile.val.c_str()); } else if (infile.key == "allow_power_mod") { if (infile.val == "true") powers[input_id].allow_power_mod = true; } } infile.close(); } }
void AnimationSet::load() { assert(!loaded); loaded = true; FileParser parser; // @CLASS Animation|Description of animations in animations/ if (!parser.open(name, true, "Error loading animation definition: " + name)) return; string _name = ""; int position = 0; int frames = 0; int duration = 0; Point render_size; Point render_offset; string type = ""; string starting_animation = ""; bool first_section=true; bool compressed_loading=false; // is reset every section to false, set by frame keyword Animation *newanim = NULL; vector<short> active_frames; // Parse the file and on each new section create an animation object from the data parsed previously while (parser.next()) { // create the animation if finished parsing a section if (parser.new_section) { if (!first_section && !compressed_loading) { Animation *a = new Animation(_name, type, sprite); a->setupUncompressed(render_size, render_offset, position, frames, duration); if (!active_frames.empty()) a->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(a); } first_section = false; compressed_loading = false; } if (parser.key == "image") { // @ATTR image|string|Filename of sprite-sheet image. if (sprite != NULL) { printf("multiple images specified in %s, dragons be here!\n", name.c_str()); SDL_Quit(); exit(128); } sprite = render_device->loadImage(parser.val); } else if (parser.key == "position") { // @ATTR position|integer|Number of frames to the right to use as the first frame. Unpacked animations only. position = toInt(parser.val); } else if (parser.key == "frames") { // @ATTR frames|integer|The total number of frames frames = toInt(parser.val); } else if (parser.key == "duration") { // @ATTR duration|integer|The duration of each frame. duration = parse_duration(parser.val); } else if (parser.key == "type") // @ATTR type|[play_once, back_forth, looped]|How to loop (or not loop) this animation. type = parser.val; else if (parser.key == "render_size") { // @ATTR render_size|w (integer), h (integer)|Width and height of animation. render_size.x = toInt(parser.nextValue()); render_size.y = toInt(parser.nextValue()); } else if (parser.key == "render_offset") { // @ATTR render_offset|x (integer), y (integer)|Render x/y offset. render_offset.x = toInt(parser.nextValue()); render_offset.y = toInt(parser.nextValue()); } else if (parser.key == "active_frame") { // @ATTR active_frame|[all:frame (integer), ...]|A list of frames marked as "active". Also, "all" can be used to mark all frames as active. active_frames.clear(); string nv = parser.nextValue(); if (nv == "all") { active_frames.push_back(-1); } else { while (nv != "") { active_frames.push_back(toInt(nv)); nv = parser.nextValue(); } sort(active_frames.begin(), active_frames.end()); active_frames.erase(unique(active_frames.begin(), active_frames.end()), active_frames.end()); } } else if (parser.key == "frame") { // @ATTR frame|index (integer), direction (integer), x (integer), y (integer), w (integer), h (integer), x offset (integer), y offset (integer)|A single frame of a compressed animation. if (compressed_loading == false) { // first frame statement in section newanim = new Animation(_name, type, sprite); newanim->setup(frames, duration); if (!active_frames.empty()) newanim->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(newanim); compressed_loading = true; } // frame = index, direction, x, y, w, h, offsetx, offsety Rect r; Point offset; const int index = toInt(parser.nextValue()); const int direction = toInt(parser.nextValue()); r.x = toInt(parser.nextValue()); r.y = toInt(parser.nextValue()); r.w = toInt(parser.nextValue()); r.h = toInt(parser.nextValue()); offset.x = toInt(parser.nextValue()); offset.y = toInt(parser.nextValue()); newanim->addFrame(index, direction, r, offset); } else { fprintf(stderr, "animations definitions (%s): Key %s not supported!\n", parser.getFileName().c_str(), parser.key.c_str()); } if (_name == "") { // This is the first animation starting_animation = parser.section; } _name = parser.section; } if (!compressed_loading) { // add final animation Animation *a = new Animation(_name, type, sprite); a->setupUncompressed(render_size, render_offset, position, frames, duration); if (!active_frames.empty()) a->setActiveFrames(active_frames); active_frames.clear(); animations.push_back(a); } if (starting_animation != "") { Animation *a = getAnimation(starting_animation); delete defaultAnimation; defaultAnimation = a; } }
MenuInventory::MenuInventory(StatBlock *_stats) { stats = _stats; MAX_EQUIPPED = 4; MAX_CARRIED = 64; visible = false; setBackground("images/menus/inventory.png"); currency = 0; carried_cols = 4; // default to 4 if menus/inventory.txt::carried_cols not set carried_rows = 4; // default to 4 if menus/inventory.txt::carried_rows not set drag_prev_src = -1; changed_equipment = true; inv_ctrl = INV_CTRL_NONE; log_msg = ""; show_book = ""; closeButton = new WidgetButton("images/menus/buttons/button_x.png"); // Load config settings FileParser infile; // @CLASS MenuInventory|Description of menus/inventory.txt if (infile.open("menus/inventory.txt")) { while(infile.next()) { if (parseMenuKey(infile.key, infile.val)) continue; // @ATTR close|x (integer), y (integer)|Position of the close button. if(infile.key == "close") { Point pos = toPoint(infile.val); closeButton->setBasePos(pos.x, pos.y); } // @ATTR equipment_slot|x (integer), y (integer), size (integer), slot_type (string)|Position and item type of an equipment slot. else if(infile.key == "equipment_slot") { Rect area; Point pos; pos.x = area.x = popFirstInt(infile.val); pos.y = area.y = popFirstInt(infile.val); area.w = area.h = popFirstInt(infile.val); equipped_area.push_back(area); equipped_pos.push_back(pos); slot_type.push_back(popFirstString(infile.val)); } // @ATTR slot_name|string|The displayed name of the last defined equipment slot. else if(infile.key == "slot_name") slot_desc.push_back(infile.val); // @ATTR carried_area|x (integer), y (integer)|Position of the first normal inventory slot. else if(infile.key == "carried_area") { Point pos; carried_pos.x = carried_area.x = popFirstInt(infile.val); carried_pos.y = carried_area.y = popFirstInt(infile.val); } // @ATTR carried_cols|integer|The number of columns for the normal inventory. else if (infile.key == "carried_cols") carried_cols = std::max(1, toInt(infile.val)); // @ATTR carried_rows|integer|The number of rows for the normal inventory. else if (infile.key == "carried_rows") carried_rows = std::max(1, toInt(infile.val)); // @ATTR label_title|label|Position of the "Inventory" label. else if (infile.key == "label_title") title = eatLabelInfo(infile.val); // @ATTR currency|label|Position of the label that displays the total currency being carried. else if (infile.key == "currency") currency_lbl = eatLabelInfo(infile.val); // @ATTR help|x (integer), y (integer), w (integer), h (integer)|A mouse-over area that displays some help text for inventory shortcuts. else if (infile.key == "help") help_pos = toRect(infile.val); else infile.error("MenuInventory: '%s' is not a valid key.", infile.key.c_str()); } infile.close(); } MAX_EQUIPPED = static_cast<int>(equipped_area.size()); MAX_CARRIED = carried_cols * carried_rows; carried_area.w = carried_cols*ICON_SIZE; carried_area.h = carried_rows*ICON_SIZE; color_normal = font->getColor("menu_normal"); color_high = font->getColor("menu_bonus"); inventory[EQUIPMENT].init(MAX_EQUIPPED, equipped_area, slot_type); inventory[CARRIED].init(MAX_CARRIED, carried_area, ICON_SIZE, carried_cols); for (int i = 0; i < MAX_EQUIPPED; i++) { tablist.add(inventory[EQUIPMENT].slots[i]); } for (int i = 0; i < MAX_CARRIED; i++) { tablist.add(inventory[CARRIED].slots[i]); } align(); }
LootManager::LootManager(ItemManager *_items, MapRenderer *_map, StatBlock *_hero) { items = _items; map = _map; // we need to be able to read loot that drops from map containers hero = _hero; // we need the player's position for dropping loot in a valid spot tip = new WidgetTooltip(); FileParser infile; // load loot animation settings from engine config file if (infile.open(mods->locate("engine/loot.txt").c_str())) { while (infile.next()) { infile.val = infile.val + ','; if (infile.key == "loot_animation") { animation_pos.x = eatFirstInt(infile.val, ','); animation_pos.y = eatFirstInt(infile.val, ','); animation_pos.w = eatFirstInt(infile.val, ','); animation_pos.h = eatFirstInt(infile.val, ','); } else if (infile.key == "loot_animation_offset") { animation_offset.x = eatFirstInt(infile.val, ','); animation_offset.y = eatFirstInt(infile.val, ','); } else if (infile.key == "tooltip_margin") { tooltip_margin = eatFirstInt(infile.val, ','); } else if (infile.key == "autopickup_range") { AUTOPICKUP_RANGE = eatFirstInt(infile.val, ','); } else if (infile.key == "autopickup_currency") { AUTOPICKUP_CURRENCY = eatFirstInt(infile.val, ','); } else if (infile.key == "currency_name") { CURRENCY = msg->get(eatFirstString(infile.val, ',')); } else if (infile.key == "vendor_ratio") { VENDOR_RATIO = (float)eatFirstInt(infile.val, ',') / 100.0; } else if (infile.key == "currency_range") { CurrencyRange cr; cr.filename = eatFirstString(infile.val, ','); cr.low = eatFirstInt(infile.val, ','); cr.high = eatFirstInt(infile.val, ','); currency_range.push_back(cr); } } infile.close(); } else fprintf(stderr, "Unable to open engine/loot.txt!\n"); animation_count = 0; for (int i=0; i<64; i++) { flying_loot[i] = NULL; animation_id[i] = ""; } loot_flip = NULL; // reset current map loot loot.clear(); // reset loot table for (int lvl=0; lvl<15; lvl++) { loot_table_count[lvl] = 0; for (int num=0; num<256; num++) { loot_table[lvl][num] = 0; } } loadGraphics(); calcTables(); if (audio && SOUND_VOLUME) loot_flip = Mix_LoadWAV(mods->locate("soundfx/flying_loot.ogg").c_str()); full_msg = false; anim_loot_frames = 6; anim_loot_duration = 3; if (!lootManager) lootManager = this; else exit(25); // TODO: make sure only one instance of the lootmanager is created. }
void EventManager::loadEventComponent(FileParser &infile, Event* evnt, Event_Component* ec) { Event_Component *e = NULL; if (evnt) { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); } else if (ec) { e = ec; } if (!e) return; e->type = infile.key; if (infile.key == "tooltip") { // @ATTR event.tooltip|string|Tooltip for event e->s = msg->get(infile.val); } else if (infile.key == "power_path") { // @ATTR event.power_path|[hero:[x,y]]|Event power path // x,y are src, if s=="hero" we target the hero, // else we'll use values in a,b as coordinates e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); std::string dest = infile.nextValue(); if (dest == "hero") { e->s = "hero"; } else { e->a = toInt(dest); e->b = toInt(infile.nextValue()); } } else if (infile.key == "power_damage") { // @ATTR event.power_damage|min(integer), max(integer)|Range of power damage e->a = toInt(infile.nextValue()); e->b = toInt(infile.nextValue()); } else if (infile.key == "intermap") { // @ATTR event.intermap|[map(string),x(integer),y(integer)]|Jump to specific map at location specified. e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "intramap") { // @ATTR event.intramap|[x(integer),y(integer)]|Jump to specific position within current map. e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "mapmod") { // @ATTR event.mapmod|[string,int,int,int],..|Modify map tiles e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); // add repeating mapmods if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); repeat_val = infile.nextValue(); } } } else if (infile.key == "soundfx") { // @ATTR event.soundfx|[soundfile(string),x(integer),y(integer)]|Filename of a sound to play at an optional location e->s = infile.nextValue(); e->x = e->y = -1; std::string s = infile.nextValue(); if (s != "") e->x = toInt(s); s = infile.nextValue(); if (s != "") e->y = toInt(s); } else if (infile.key == "loot") { // @ATTR event.loot|[string,drop_chance([fixed:chance(integer)]),quantity_min(integer),quantity_max(integer)],...|Add loot to the event; either a filename or an inline definition. loot->parseLoot(infile, e, &evnt->components); } else if (infile.key == "msg") { // @ATTR event.msg|string|Adds a message to be displayed for the event. e->s = msg->get(infile.val); } else if (infile.key == "shakycam") { // @ATTR event.shakycam|duration|Makes the camera shake for this duration in 'ms' or 's'. e->x = parse_duration(infile.val); } else if (infile.key == "requires_status") { // @ATTR event.requires_status|string,...|Event requires list of statuses e->s = infile.nextValue(); // add repeating requires_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "requires_not_status") { // @ATTR event.requires_not_status|string,...|Event requires not list of statuses e->s = infile.nextValue(); // add repeating requires_not if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "requires_level") { // @ATTR event.requires_level|integer|Event requires hero level e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_not_level") { // @ATTR event.requires_not_level|integer|Event requires not hero level e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_currency") { // @ATTR event.requires_currency|integer|Event requires atleast this much currency e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_item") { // @ATTR event.requires_item|integer,...|Event requires specific item e->x = toInt(infile.nextValue()); // add repeating requires_item if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } } else if (infile.key == "requires_class") { // @ATTR event.requires_class|string|Event requires this base class e->s = infile.nextValue(); } else if (infile.key == "set_status") { // @ATTR event.set_status|string,...|Sets specified statuses e->s = infile.nextValue(); // add repeating set_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "unset_status") { // @ATTR event.unset_status|string,...|Unsets specified statuses e->s = infile.nextValue(); // add repeating unset_status if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } } else if (infile.key == "remove_currency") { // @ATTR event.remove_currency|integer|Removes specified amount of currency from hero inventory e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "remove_item") { // @ATTR event.remove_item|integer,...|Removes specified item from hero inventory e->x = toInt(infile.nextValue()); // add repeating remove_item if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } } else if (infile.key == "reward_xp") { // @ATTR event.reward_xp|integer|Reward hero with specified amount of experience points. e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "reward_currency") { // @ATTR event.reward_currency|integer|Reward hero with specified amount of currency. e->x = toInt(infile.val); clampFloor(e->x, 0); } else if (infile.key == "reward_item") { // @ATTR event.reward_item|x(integer),y(integer)|Reward hero with y number of item x. e->x = toInt(infile.nextValue()); e->y = toInt(infile.val); clampFloor(e->y, 0); } else if (infile.key == "restore") { // @ATTR event.restore|string|Restore the hero's HP, MP, and/or status. e->s = infile.val; } else if (infile.key == "power") { // @ATTR event.power|power_id|Specify power coupled with event. e->x = toInt(infile.val); } else if (infile.key == "spawn") { // @ATTR event.spawn|[string,x(integer),y(integer)], ...|Spawn an enemy from this category at location e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); // add repeating spawn if (evnt) { std::string repeat_val = infile.nextValue(); while (repeat_val != "") { evnt->components.push_back(Event_Component()); e = &evnt->components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); repeat_val = infile.nextValue(); } } } else if (infile.key == "stash") { // @ATTR event.stash|boolean|Opens the Stash menu. e->s = infile.val; } else if (infile.key == "npc") { // @ATTR event.npc|string|Filename of an NPC to start dialog with. e->s = infile.val; } else if (infile.key == "music") { // @ATTR event.music|string|Change background music to specified file. e->s = infile.val; } else if (infile.key == "cutscene") { // @ATTR event.cutscene|string|Show specified cutscene by filename. e->s = infile.val; } else if (infile.key == "repeat") { // @ATTR event.repeat|boolean|Allows the event to be triggered again. e->s = infile.val; } else if (infile.key == "save_game") { // @ATTR event.save_game|boolean|Saves the game when the event is triggered. The respawn position is set to where the player is standing. e->s = infile.val; } else { infile.error("EventManager: '%s' is not a valid key.", infile.key.c_str()); } }
/** * Load a specific items file * * @param filename The full path and name of the file to load */ void ItemManager::load(const string& filename) { FileParser infile; if (!infile.open(filename)) { fprintf(stderr, "Unable to open %s!\n", filename.c_str()); return; } int id = 0; bool id_line = false; while (infile.next()) { if (infile.key == "id") { id_line = true; id = toInt(infile.val); if (id > 0 && id >= (int)items.size()) { // *2 to amortize the resizing to O(log(n)). items.resize((2*id) + 1); } } else id_line = false; if (id < 1) { if (id_line) fprintf(stderr, "Item index out of bounds 1-%d, skipping\n", INT_MAX); continue; } if (id_line) continue; if (infile.key == "name") items[id].name = msg->get(infile.val); else if (infile.key == "level") items[id].level = toInt(infile.val); else if (infile.key == "icon") { items[id].icon = toInt(infile.nextValue()); } else if (infile.key == "quality") { if (infile.val == "low") items[id].quality = ITEM_QUALITY_LOW; else if (infile.val == "high") items[id].quality = ITEM_QUALITY_HIGH; else if (infile.val == "epic") items[id].quality = ITEM_QUALITY_EPIC; } else if (infile.key == "item_type") { items[id].type = infile.val; } else if (infile.key == "dmg_melee") { items[id].dmg_melee_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_melee_max = toInt(infile.nextValue()); else items[id].dmg_melee_max = items[id].dmg_melee_min; } else if (infile.key == "dmg_ranged") { items[id].dmg_ranged_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ranged_max = toInt(infile.nextValue()); else items[id].dmg_ranged_max = items[id].dmg_ranged_min; } else if (infile.key == "dmg_ment") { items[id].dmg_ment_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].dmg_ment_max = toInt(infile.nextValue()); else items[id].dmg_ment_max = items[id].dmg_ment_min; } else if (infile.key == "abs") { items[id].abs_min = toInt(infile.nextValue()); if (infile.val.length() > 0) items[id].abs_max = toInt(infile.nextValue()); else items[id].abs_max = items[id].abs_min; } else if (infile.key == "req") { string s = infile.nextValue(); if (s == "p") items[id].req_stat = REQUIRES_PHYS; else if (s == "m") items[id].req_stat = REQUIRES_MENT; else if (s == "o") items[id].req_stat = REQUIRES_OFF; else if (s == "d") items[id].req_stat = REQUIRES_DEF; items[id].req_val = toInt(infile.nextValue()); } else if (infile.key == "bonus") { items[id].bonus_stat.push_back(infile.nextValue()); items[id].bonus_val.push_back(toInt(infile.nextValue())); } else if (infile.key == "sfx") { if (infile.val == "book") items[id].sfx = SFX_BOOK; else if (infile.val == "cloth") items[id].sfx = SFX_CLOTH; else if (infile.val == "coins") items[id].sfx = SFX_COINS; else if (infile.val == "gem") items[id].sfx = SFX_GEM; else if (infile.val == "leather") items[id].sfx = SFX_LEATHER; else if (infile.val == "metal") items[id].sfx = SFX_METAL; else if (infile.val == "page") items[id].sfx = SFX_PAGE; else if (infile.val == "maille") items[id].sfx = SFX_MAILLE; else if (infile.val == "object") items[id].sfx = SFX_OBJECT; else if (infile.val == "heavy") items[id].sfx = SFX_HEAVY; else if (infile.val == "wood") items[id].sfx = SFX_WOOD; else if (infile.val == "potion") items[id].sfx = SFX_POTION; } else if (infile.key == "gfx") items[id].gfx = infile.val; else if (infile.key == "loot_animation") items[id].loot_animation = infile.val; else if (infile.key == "power") { if (toInt(infile.val) > 0) { items[id].power = toInt(infile.val); } else fprintf(stderr, "Power index inside item %d definition out of bounds 1-%d, skipping item\n", id, INT_MAX); } else if (infile.key == "power_mod") items[id].power_mod = toInt(infile.val); else if (infile.key == "power_desc") items[id].power_desc = msg->get(infile.val); else if (infile.key == "price") items[id].price = toInt(infile.val); else if (infile.key == "price_sell") items[id].price_sell = toInt(infile.val); else if (infile.key == "max_quantity") items[id].max_quantity = toInt(infile.val); else if (infile.key == "rand_loot") items[id].rand_loot = toInt(infile.val); else if (infile.key == "rand_vendor") items[id].rand_vendor = toInt(infile.val); else if (infile.key == "pickup_status") items[id].pickup_status = infile.val; else if (infile.key == "stepfx") items[id].stepfx = infile.val; else if (infile.key == "class") { string classname = infile.nextValue(); while (classname != "") { unsigned pos; // find the position where this classname is stored: for (pos = 0; pos < item_class_names.size(); pos++) { if (item_class_names[pos] == classname) break; } // if it was not found, add it to the end. // pos is already the correct index. if (pos == item_class_names.size()) { item_class_names.push_back(classname); item_class_items.push_back(vector<unsigned int>()); } // add item id to the item list of that class: item_class_items[pos].push_back(id); classname = infile.nextValue(); } } } infile.close(); }
void EventManager::loadEvent(FileParser &infile, Event* evnt) { if (!evnt) return; // @CLASS EventManager|Description of events in maps/ and npcs/ if (infile.key == "type") { // @ATTR event.type|[on_trigger:on_mapexit:on_leave:on_load:on_clear]|Type of map event. std::string type = infile.val; evnt->type = type; if (type == "on_trigger"); else if (type == "on_mapexit"); // no need to set keep_after_trigger to false correctly, it's ignored anyway else if (type == "on_leave"); else if (type == "on_load") { evnt->keep_after_trigger = false; } else if (type == "on_clear") { evnt->keep_after_trigger = false; } else { infile.error("EventManager: Event type '%s' unknown, change to \"on_trigger\" to suppress this warning.", type.c_str()); } } else if (infile.key == "location") { // @ATTR event.location|[x,y,w,h]|Defines the location area for the event. evnt->location.x = toInt(infile.nextValue()); evnt->location.y = toInt(infile.nextValue()); evnt->location.w = toInt(infile.nextValue()); evnt->location.h = toInt(infile.nextValue()); if (evnt->center.x == -1 && evnt->center.y == -1) { evnt->center.x = static_cast<float>(evnt->location.x) + static_cast<float>(evnt->location.w)/2; evnt->center.y = static_cast<float>(evnt->location.y) + static_cast<float>(evnt->location.h)/2; } } else if (infile.key == "hotspot") { // @ATTR event.hotspot|[ [x, y, w, h] : location ]|Event uses location as hotspot or defined by rect. if (infile.val == "location") { evnt->hotspot.x = evnt->location.x; evnt->hotspot.y = evnt->location.y; evnt->hotspot.w = evnt->location.w; evnt->hotspot.h = evnt->location.h; } else { evnt->hotspot.x = toInt(infile.nextValue()); evnt->hotspot.y = toInt(infile.nextValue()); evnt->hotspot.w = toInt(infile.nextValue()); evnt->hotspot.h = toInt(infile.nextValue()); } evnt->center.x = static_cast<float>(evnt->hotspot.x) + static_cast<float>(evnt->hotspot.w)/2; evnt->center.y = static_cast<float>(evnt->hotspot.y) + static_cast<float>(evnt->hotspot.h)/2; } else if (infile.key == "cooldown") { // @ATTR event.cooldown|duration|Duration for event cooldown in 'ms' or 's'. evnt->cooldown = parse_duration(infile.val); } else if (infile.key == "reachable_from") { // @ATTR event.reachable_from|[x,y,w,h]|If the hero is inside this rectangle, they can activate the event. evnt->reachable_from.x = toInt(infile.nextValue()); evnt->reachable_from.y = toInt(infile.nextValue()); evnt->reachable_from.w = toInt(infile.nextValue()); evnt->reachable_from.h = toInt(infile.nextValue()); } else { loadEventComponent(infile, evnt, NULL); } }
int main(int argc, char* argv[]) #endif { IFXRESULT result = IFX_OK; #ifdef __MINGW32__ wchar_t **argw = NULL; int argc=0; #endif #ifndef WIN32 wchar_t **argw = NULL; int i; #endif result = IFXSetDefaultLocale(); IFXTRACE_GENERIC(L"[Converter] IFXSetDefaultLocale %i\n", result); if( IFXSUCCESS(result) ) { #ifdef __MINGW32__ argw = CommandLineToArgvW(GetCommandLineW(), &argc); #endif #ifndef WIN32 argw = (wchar_t**)malloc(argc*sizeof(wchar_t*)); if (argw == NULL) result = IFX_E_OUT_OF_MEMORY; if( IFXSUCCESS(result) ) { memset(argw, 0, argc*sizeof(wchar_t*)); for (i=0; i<argc; i++) { argw[i] = mbs_to_wcs(argv[i]); if (argw[i] == NULL) { result = IFX_E_OUT_OF_MEMORY; break; } } } #endif } if( IFXSUCCESS(result) && argc > 2 ) { if( 0 == wcscmp(L"-libdir", argw[argc-2]) || 0 == wcscmp(L"-l", argw[argc-2]) ) { size_t size = wcstombs(NULL, argw[argc-1], 0); if (size <= MAXIMUM_FILENAME_LENGTH) { #ifdef WIN32 SetEnvironmentVariable(L"U3D_LIBDIR", argw[argc-1]); #else char libdir[size+1]; wcstombs(libdir, argw[argc-1], size); libdir[size] = 0; setenv("U3D_LIBDIR",libdir,1); #endif argc -=2; } } } if( IFXSUCCESS(result) ) { IFXDEBUG_STARTUP(); result = IFXCOMInitialize(); } IFXTRACE_GENERIC(L"[Converter] IFXCOMInitialize %i\n", result); if( IFXSUCCESS(result) ) { ConverterOptions converterOptions; FileOptions fileOptions; if( IFXSUCCESS(result) ) SetDefaultOptionsX( &converterOptions, &fileOptions ); if( IFXSUCCESS(result) ) { result = ReadAndSetUserOptionsX( argc, argw, &converterOptions, &fileOptions ); } #ifdef STDIO_HACK if( IFXSUCCESS(result) ) { if ( fileOptions.outFile != L"stdout" && fileOptions.outFile != L"-" ) stdmsg = stdout; } #endif if( IFXSUCCESS(result) ) { SceneUtilities sceneUtils; FileParser fileParser; IFXTRACE_GENERIC( L"[Converter] fileParser.Initialize\n" ); result = fileParser.Initialize( fileOptions.inFile.Raw() ); if( IFXSUCCESS(result) ) IFXTRACE_GENERIC( L"[Converter] sceneUtils.InitializeScene\n" ); result = sceneUtils.InitializeScene( fileOptions.profile, fileOptions.scalingFactor ); if( IFXSUCCESS(result) ) { IFXTRACE_GENERIC( L"[Converter] converter.Convert\n" ); SceneConverter converter( &fileParser, &sceneUtils, &converterOptions ); result = converter.Convert(); } //---------------------------------------------- // Scene now built and in the U3D engine. // It is now time to examine the scene and/or // dump it to a debug file or a U3D file. //---------------------------------------------- // Write out the scene to a U3D file if this is enabled. if ( IFXSUCCESS( result ) && ( fileOptions.exportOptions > 0 ) ) { result = sceneUtils.WriteSceneToFile( fileOptions.outFile, fileOptions.exportOptions ); } // If enabled, dump the scene to the debug file. if ( IFXSUCCESS( result ) && ( fileOptions.debugLevel > 0 ) ) { U8 file[MAXIMUM_FILENAME_LENGTH]; result = fileOptions.outFile.ConvertToRawU8( file, MAXIMUM_FILENAME_LENGTH ); if ( IFXSUCCESS( result ) ) result = sceneUtils.WriteDebugInfo( (const char*)file ); } } } fprintf(stdmsg,"Exit code = %x\n", result); IFXRESULT comResult = IFXCOMUninitialize(); IFXTRACE_GENERIC( L"[Converter] IFXCOMUninitialize %i\n", comResult ); IFXDEBUG_SHUTDOWN(); #ifdef __MINGW32__ LocalFree(argw); #endif #ifndef WIN32 if (argw != NULL) { for (i=0; i<argc; i++) { if(argw[i] != NULL) free(argw[i]); } free(argw); } #endif return result; }
void loadMiscSettings() { FileParser infile; // load miscellaneous settings from engine config // misc.txt if (infile.open(mods->locate("engine/misc.txt").c_str())) { while (infile.next()) { if (infile.key == "save_hpmp") { SAVE_HPMP = toInt(infile.val); } else if (infile.key == "default_name") { DEFAULT_NAME = infile.val.c_str(); } else if (infile.key == "corpse_timeout") { CORPSE_TIMEOUT = toInt(infile.val); } } infile.close(); } else fprintf(stderr, "Unable to open engine/misc.txt!\n"); // resolutions.txt if (infile.open(mods->locate("engine/resolutions.txt").c_str())) { while (infile.next()) { if (infile.key == "menu_frame_width") FRAME_W = toInt(infile.val); else if (infile.key == "menu_frame_height") FRAME_H = toInt(infile.val); else if (infile.key == "small_icon_size") ICON_SIZE_SMALL = toInt(infile.val); else if (infile.key == "large_icon_size") ICON_SIZE_LARGE = toInt(infile.val); else if (infile.key == "required_width") { MIN_VIEW_W = toInt(infile.val); if (VIEW_W < MIN_VIEW_W) VIEW_W = MIN_VIEW_W; VIEW_W_HALF = VIEW_W/2; } else if (infile.key == "required_height") { MIN_VIEW_H = toInt(infile.val); if (VIEW_H < MIN_VIEW_H) VIEW_H = MIN_VIEW_H; VIEW_H_HALF = VIEW_H/2; } } infile.close(); } else fprintf(stderr, "Unable to open engine/resolutions.txt!\n"); // gameplay.txt if (infile.open(mods->locate("engine/gameplay.txt").c_str())) { while (infile.next()) { if (infile.key == "enable_playgame") { ENABLE_PLAYGAME = toInt(infile.val); } } infile.close(); } else fprintf(stderr, "Unable to open engine/gameplay.txt!\n"); // combat.txt if (infile.open(mods->locate("engine/combat.txt").c_str())) { while (infile.next()) { if (infile.key == "max_absorb_percent") { MAX_ABSORB = toInt(infile.val); } else if (infile.key == "max_resist_percent") { MAX_RESIST = toInt(infile.val); } else if (infile.key == "max_block_percent") { MAX_BLOCK = toInt(infile.val); } else if (infile.key == "max_avoidance_percent") { MAX_AVOIDANCE = toInt(infile.val); } } infile.close(); } else fprintf(stderr, "Unable to open engine/combat.txt!\n"); // elements.txt if (infile.open(mods->locate("engine/elements.txt").c_str())) { Element e; ELEMENTS.clear(); while (infile.next()) { if (infile.key == "name") e.name = msg->get(infile.val); else if (infile.key == "resist") e.resist = msg->get(infile.val); if (e.name != "" && e.resist != "") { ELEMENTS.push_back(e); e.name = e.resist = ""; } } infile.close(); } else fprintf(stderr, "Unable to open engine/elements.txt!\n"); }
/** * load a statblock, typically for an enemy definition */ void StatBlock::load(const string& filename) { FileParser infile; if (!infile.open(filename)) return; string loot_token; while (infile.next()) { int num = toInt(infile.val); float fnum = toFloat(infile.val); bool valid = loadCoreStat(&infile); if (infile.key == "name") name = msg->get(infile.val); else if (infile.key == "humanoid") humanoid = toBool(infile.val); else if (infile.key == "sfx_prefix") sfx_prefix = infile.val; else if (infile.key == "level") level = num; // enemy death rewards and events else if (infile.key == "xp") xp = num; else if (infile.key == "loot") { // loot entries format: // loot=[id],[percent_chance] // optionally allow range: // loot=[id],[percent_chance],[count_min],[count_max] EnemyLoot el; std::string loot_id = infile.nextValue(); // id 0 means currency. The keyword "currency" can also be used. if (loot_id == "currency") el.id = 0; else el.id = toInt(loot_id); el.chance = toInt(infile.nextValue()); // check for optional range. loot_token = infile.nextValue(); if (loot_token != "") { el.count_min = toInt(loot_token); el.count_max = el.count_min; } loot_token = infile.nextValue(); if (loot_token != "") { el.count_max = toInt(loot_token); } loot.push_back(el); } else if (infile.key == "defeat_status") defeat_status = infile.val; else if (infile.key == "convert_status") convert_status = infile.val; else if (infile.key == "first_defeat_loot") first_defeat_loot = num; else if (infile.key == "quest_loot") { quest_loot_requires_status = infile.nextValue(); quest_loot_requires_not_status = infile.nextValue(); quest_loot_id = toInt(infile.nextValue()); } // combat stats else if (infile.key == "cooldown") cooldown = parse_duration(infile.val); // behavior stats else if (infile.key == "flying") flying = toBool(infile.val); else if (infile.key == "intangible") intangible = toBool(infile.val); else if (infile.key == "facing") facing = toBool(infile.val); else if (infile.key == "waypoint_pause") waypoint_pause = num; else if (infile.key == "turn_delay") turn_delay = num; else if (infile.key == "chance_pursue") chance_pursue = num; else if (infile.key == "chance_flee") chance_flee = num; else if (infile.key == "chance_melee_phys") power_chance[MELEE_PHYS] = num; else if (infile.key == "chance_melee_ment") power_chance[MELEE_MENT] = num; else if (infile.key == "chance_ranged_phys") power_chance[RANGED_PHYS] = num; else if (infile.key == "chance_ranged_ment") power_chance[RANGED_MENT] = num; else if (infile.key == "power_melee_phys") power_index[MELEE_PHYS] = num; else if (infile.key == "power_melee_ment") power_index[MELEE_MENT] = num; else if (infile.key == "power_ranged_phys") power_index[RANGED_PHYS] = num; else if (infile.key == "power_ranged_ment") power_index[RANGED_MENT] = num; else if (infile.key == "power_beacon") power_index[BEACON] = num; else if (infile.key == "cooldown_melee_phys") power_cooldown[MELEE_PHYS] = parse_duration(infile.val); else if (infile.key == "cooldown_melee_ment") power_cooldown[MELEE_MENT] = parse_duration(infile.val); else if (infile.key == "cooldown_ranged_phys") power_cooldown[RANGED_PHYS] = parse_duration(infile.val); else if (infile.key == "cooldown_ranged_ment") power_cooldown[RANGED_MENT] = parse_duration(infile.val); else if (infile.key == "power_on_hit") power_index[ON_HIT] = num; else if (infile.key == "power_on_death") power_index[ON_DEATH] = num; else if (infile.key == "power_on_half_dead") power_index[ON_HALF_DEAD] = num; else if (infile.key == "power_on_debuff") power_index[ON_DEBUFF] = num; else if (infile.key == "power_on_join_combat") power_index[ON_JOIN_COMBAT] = num; else if (infile.key == "chance_on_hit") power_chance[ON_HIT] = num; else if (infile.key == "chance_on_death") power_chance[ON_DEATH] = num; else if (infile.key == "chance_on_half_dead") power_chance[ON_HALF_DEAD] = num; else if (infile.key == "chance_on_debuff") power_chance[ON_DEBUFF] = num; else if (infile.key == "chance_on_join_combat") power_chance[ON_JOIN_COMBAT] = num; else if (infile.key == "cooldown_hit") cooldown_hit = num; else if (infile.key == "passive_powers") { std::string p = infile.nextValue(); while (p != "") { powers_passive.push_back(toInt(p)); p = infile.nextValue(); } } else if (infile.key == "melee_range") melee_range = fnum; else if (infile.key == "threat_range") threat_range = fnum; else if (infile.key == "passive_attacker") passive_attacker = toBool(infile.val); // animation stats else if (infile.key == "melee_weapon_power") melee_weapon_power = num; else if (infile.key == "mental_weapon_power") mental_weapon_power = num; else if (infile.key == "ranged_weapon_power") ranged_weapon_power = num; else if (infile.key == "animations") animations = infile.val; // hide enemy HP bar else if (infile.key == "suppress_hp") suppress_hp = toBool(infile.val); // this is only used for EnemyGroupManager // we check for them here so that we don't get an error saying they are invalid else if (infile.key == "rarity") ; // but do nothing else if (!valid) { fprintf(stderr, "%s=%s not a valid StatBlock parameter\n", infile.key.c_str(), infile.val.c_str()); } } infile.close(); hp = starting[STAT_HP_MAX]; mp = starting[STAT_MP_MAX]; // sort loot table std::sort(loot.begin(), loot.end(), sortLoot); applyEffects(); }
void Map::loadEventComponent(FileParser &infile) { // new event component events.back().components.push_back(Event_Component()); Event_Component *e = &events.back().components.back(); e->type = infile.key; if (infile.key == "tooltip") { e->s = msg->get(infile.val); } else if (infile.key == "power_path") { // x,y are src, if s=="hero" we target the hero, // else we'll use values in a,b as coordinates e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); std::string dest = infile.nextValue(); if (dest == "hero") { e->s = "hero"; } else { e->a = toInt(dest); e->b = toInt(infile.nextValue()); } } else if (infile.key == "power_damage") { e->a = toInt(infile.nextValue()); e->b = toInt(infile.nextValue()); } else if (infile.key == "intermap") { e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "intramap") { e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); } else if (infile.key == "mapmod") { e->s = infile.nextValue(); e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); // add repeating mapmods std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()); e->y = toInt(infile.nextValue()); e->z = toInt(infile.nextValue()); repeat_val = infile.nextValue(); } } else if (infile.key == "soundfx") { e->s = infile.nextValue(); e->x = e->y = -1; std::string s = infile.nextValue(); if (s != "") e->x = toInt(s); s = infile.nextValue(); if (s != "") e->y = toInt(s); } else if (infile.key == "loot") { e->s = infile.nextValue(); e->x = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; e->y = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; // drop chance std::string chance = infile.nextValue(); if (chance == "fixed") e->z = 0; else e->z = toInt(chance); // quantity min/max e->a = toInt(infile.nextValue()); if (e->a < 1) e->a = 1; e->b = toInt(infile.nextValue()); if (e->b < e->a) e->b = e->a; // add repeating loot std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; e->y = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; chance = infile.nextValue(); if (chance == "fixed") e->z = 0; else e->z = toInt(chance); e->a = toInt(infile.nextValue()); if (e->a < 1) e->a = 1; e->b = toInt(infile.nextValue()); if (e->b < e->a) e->b = e->a; repeat_val = infile.nextValue(); } } else if (infile.key == "msg") { e->s = msg->get(infile.val); } else if (infile.key == "shakycam") { e->x = toInt(infile.val); } else if (infile.key == "requires_status") { e->s = infile.nextValue(); // add repeating requires_status std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } else if (infile.key == "requires_not") { e->s = infile.nextValue(); // add repeating requires_not std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } else if (infile.key == "requires_level") { e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_not_level") { e->x = toInt(infile.nextValue()); } else if (infile.key == "requires_item") { e->x = toInt(infile.nextValue()); // add repeating requires_item std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } else if (infile.key == "set_status") { e->s = infile.nextValue(); // add repeating set_status std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } else if (infile.key == "unset_status") { e->s = infile.nextValue(); // add repeating unset_status std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; repeat_val = infile.nextValue(); } } else if (infile.key == "remove_item") { e->x = toInt(infile.nextValue()); // add repeating remove_item std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->x = toInt(repeat_val); repeat_val = infile.nextValue(); } } else if (infile.key == "reward_xp") { e->x = toInt(infile.val); } else if (infile.key == "power") { e->x = toInt(infile.val); } else if (infile.key == "spawn") { e->s = infile.nextValue(); e->x = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; e->y = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; // add repeating spawn std::string repeat_val = infile.nextValue(); while (repeat_val != "") { events.back().components.push_back(Event_Component()); e = &events.back().components.back(); e->type = infile.key; e->s = repeat_val; e->x = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; e->y = toInt(infile.nextValue()) * UNITS_PER_TILE + UNITS_PER_TILE/2; repeat_val = infile.nextValue(); } } else if (infile.key == "stash") { e->s = infile.val; } else if (infile.key == "npc") { e->s = infile.val; } else if (infile.key == "music") { e->s = infile.val; } else if (infile.key == "cutscene") { e->s = infile.val; } else if (infile.key == "repeat") { e->s = infile.val; } else { fprintf(stderr, "Map: Unknown key value: %s in file %s in section %s\n", infile.key.c_str(), infile.getFileName().c_str(), infile.section.c_str()); } }
MenuManager::MenuManager(PowerManager *_powers, StatBlock *_stats, CampaignManager *_camp, ItemManager *_items) { powers = _powers; stats = _stats; camp = _camp; items = _items; loadIcons(); hp = new MenuStatBar("hp"); menus.push_back(hp); // menus[0] mp = new MenuStatBar("mp"); menus.push_back(mp); // menus[1] xp = new MenuStatBar("xp"); menus.push_back(xp); // menus[2] effects = new MenuActiveEffects(icons); menus.push_back(effects); // menus[3] hudlog = new MenuHUDLog(); menus.push_back(hudlog); // menus[4] act = new MenuActionBar(powers, stats, icons); menus.push_back(act); // menus[5] enemy = new MenuEnemy(); menus.push_back(enemy); // menus[6] vendor = new MenuVendor(items, stats); menus.push_back(vendor); // menus[7] talker = new MenuTalker(camp); menus.push_back(talker); // menus[8] exit = new MenuExit(); menus.push_back(exit); // menus[9] mini = new MenuMiniMap(); menus.push_back(mini); // menus[10] chr = new MenuCharacter(stats); menus.push_back(chr); // menus[11] inv = new MenuInventory(items, stats, powers); menus.push_back(inv); // menus[12] pow = new MenuPowers(stats, powers, icons); menus.push_back(pow); // menus[13] log = new MenuLog(); menus.push_back(log); // menus[14] stash = new MenuStash(items, stats); menus.push_back(stash); // menus[15] tip = new WidgetTooltip(); // Load the menu positions and alignments from menus/menus.txt std::string align; FileParser infile; if (infile.open(mods->locate("menus/menus.txt"))) { while (infile.next()) { infile.val = infile.val + ','; int x = eatFirstInt(infile.val, ','); int y = eatFirstInt(infile.val, ','); int w = eatFirstInt(infile.val, ','); int h = eatFirstInt(infile.val, ','); align = eatFirstString(infile.val, ','); int menu_index = -1; if (infile.key == "hp") menu_index = 0; else if (infile.key == "mp") menu_index = 1; else if (infile.key == "xp") menu_index = 2; else if (infile.key == "effects") menu_index = 3; else if (infile.key == "hudlog") menu_index = 4; else if (infile.key == "actionbar") menu_index = 5; else if (infile.key == "enemy") menu_index = 6; else if (infile.key == "vendor") menu_index = 7; else if (infile.key == "talker") menu_index = 8; else if (infile.key == "exit") menu_index = 9; else if (infile.key == "minimap") menu_index = 10; else if (infile.key == "character") menu_index = 11; else if (infile.key == "inventory") menu_index = 12; else if (infile.key == "powers") menu_index = 13; else if (infile.key == "log") menu_index = 14; else if (infile.key == "stash") menu_index = 15; if (menu_index != -1) { menus[menu_index]->window_area.x = x; menus[menu_index]->window_area.y = y; menus[menu_index]->window_area.w = w; menus[menu_index]->window_area.h = h; menus[menu_index]->alignment = align; menus[menu_index]->align(); } } infile.close(); } else fprintf(stderr, "Unable to open menus/menus.txt!\n"); // Some menus need to be updated to apply their new dimensions act->update(); vendor->update(); vendor->buyback_stock.init(NPC_VENDOR_MAX_STOCK, items); talker->update(); exit->update(); chr->update(); inv->update(); pow->update(); log->update(); stash->update(); pause = false; dragging = false; drag_stack.item = 0; drag_stack.quantity = 0; drag_power = 0; drag_src = 0; drop_stack.item = 0; drop_stack.quantity = 0; loadSounds(); done = false; closeAll(false); // make sure all togglable menus start closed }
void TileSet::load(const std::string& filename) { if (current_map == filename) return; reset(); FileParser infile; string img; if (infile.open("tilesetdefs/" + filename)) { while (infile.next()) { if (infile.key == "tile") { infile.val = infile.val + ','; unsigned index = eatFirstInt(infile.val, ','); if (index >= tiles.size()) tiles.resize(index + 1); tiles[index].tile.src.x = eatFirstInt(infile.val, ','); tiles[index].tile.src.y = eatFirstInt(infile.val, ','); tiles[index].tile.src.w = eatFirstInt(infile.val, ','); tiles[index].tile.src.h = eatFirstInt(infile.val, ','); tiles[index].offset.x = eatFirstInt(infile.val, ','); tiles[index].offset.y = eatFirstInt(infile.val, ','); max_size_x = std::max(max_size_x, (tiles[index].tile.src.w / TILE_W) + 1); max_size_y = std::max(max_size_y, (tiles[index].tile.src.h / TILE_H) + 1); } else if (infile.key == "img") { img = infile.val; } else if (infile.key == "transparency") { alpha_background = false; infile.val = infile.val + ','; trans_r = (Uint8)eatFirstInt(infile.val, ','); trans_g = (Uint8)eatFirstInt(infile.val, ','); trans_b = (Uint8)eatFirstInt(infile.val, ','); } else if (infile.key == "animation") { int frame = 0; unsigned TILE_ID = toInt(infile.nextValue()); if (TILE_ID >= anim.size()) anim.resize(TILE_ID + 1); string repeat_val = infile.nextValue(); while (repeat_val != "") { anim[TILE_ID].frames++; anim[TILE_ID].pos.resize(frame + 1); anim[TILE_ID].frame_duration.resize(frame + 1); anim[TILE_ID].pos[frame].x = toInt(repeat_val); anim[TILE_ID].pos[frame].y = toInt(infile.nextValue()); anim[TILE_ID].frame_duration[frame] = toInt(infile.nextValue()); frame++; repeat_val = infile.nextValue(); } } } infile.close(); loadGraphics(img); } current_map = filename; }
void EventManager::loadEventComponent(FileParser &infile, Event* evnt, Event_Component* ec) { if (!loadEventComponentString(infile.key, infile.val, evnt, ec)) { infile.error("EventManager: '%s' is not a valid key.", infile.key.c_str()); } }
/** * When loading the game, load from file if possible */ void GameStatePlay::loadGame() { int saved_hp = 0; int saved_mp = 0; int currency = 0; // game slots are currently 1-4 if (game_slot == 0) return; FileParser infile; int hotkeys[12]; for (int i=0; i<12; i++) { hotkeys[i] = -1; } stringstream ss; ss.str(""); ss << PATH_USER; if (GAME_PREFIX.length() > 0) ss << GAME_PREFIX << "_"; ss << "save" << game_slot << ".txt"; if (infile.open(ss.str(), false)) { while (infile.next()) { if (infile.key == "name") pc->stats.name = infile.val; else if (infile.key == "permadeath") { pc->stats.permadeath = toBool(infile.val); } else if (infile.key == "option") { pc->stats.gfx_base = infile.nextValue(); pc->stats.gfx_head = infile.nextValue(); pc->stats.gfx_portrait = infile.nextValue(); } else if (infile.key == "class") { pc->stats.character_class = infile.nextValue(); } else if (infile.key == "xp") { pc->stats.xp = toUnsignedLong(infile.val); } else if (infile.key == "hpmp") { saved_hp = toInt(infile.nextValue()); saved_mp = toInt(infile.nextValue()); } else if (infile.key == "build") { pc->stats.physical_character = toInt(infile.nextValue()); pc->stats.mental_character = toInt(infile.nextValue()); pc->stats.offense_character = toInt(infile.nextValue()); pc->stats.defense_character = toInt(infile.nextValue()); if (pc->stats.physical_character < 0 || pc->stats.physical_character > pc->stats.max_points_per_stat || pc->stats.mental_character < 0 || pc->stats.mental_character > pc->stats.max_points_per_stat || pc->stats.offense_character < 0 || pc->stats.offense_character > pc->stats.max_points_per_stat || pc->stats.defense_character < 0 || pc->stats.defense_character > pc->stats.max_points_per_stat) { fprintf(stderr, "Some basic stats are out of bounds, setting to zero\n"); pc->stats.physical_character = 0; pc->stats.mental_character = 0; pc->stats.offense_character = 0; pc->stats.defense_character = 0; } } else if (infile.key == "currency") { currency = toInt(infile.val); } else if (infile.key == "equipped") { menu->inv->inventory[EQUIPMENT].setItems(infile.val); } else if (infile.key == "equipped_quantity") { menu->inv->inventory[EQUIPMENT].setQuantities(infile.val); } else if (infile.key == "carried") { menu->inv->inventory[CARRIED].setItems(infile.val); } else if (infile.key == "carried_quantity") { menu->inv->inventory[CARRIED].setQuantities(infile.val); } else if (infile.key == "spawn") { mapr->teleport_mapname = infile.nextValue(); if (fileExists(mods->locate("maps/" + mapr->teleport_mapname))) { mapr->teleport_destination.x = toInt(infile.nextValue()) + 0.5f; mapr->teleport_destination.y = toInt(infile.nextValue()) + 0.5f; mapr->teleportation = true; // prevent spawn.txt from putting us on the starting map mapr->clearEvents(); } else { fprintf(stderr, "Unable to find maps/%s, loading spawn.txt\n", mapr->teleport_mapname.c_str()); mapr->teleport_mapname = "spawn.txt"; mapr->teleport_destination.x = 1; mapr->teleport_destination.y = 1; mapr->teleportation = true; } } else if (infile.key == "actionbar") { for (int i=0; i<12; i++) { hotkeys[i] = toInt(infile.nextValue()); if (hotkeys[i] < 0) { fprintf(stderr, "Hotkey power on position %d has negative id, skipping\n", i); hotkeys[i] = 0; } else if ((unsigned)hotkeys[i] > powers->powers.size()-1) { fprintf(stderr, "Hotkey power id (%d) out of bounds 1-%d, skipping\n", hotkeys[i], (int)powers->powers.size()); hotkeys[i] = 0; } else if (hotkeys[i] != 0 && powers->powers[hotkeys[i]].name == "") { fprintf(stderr, "Hotkey power with id=%d, found on position %d does not exist, skipping\n", hotkeys[i], i); hotkeys[i] = 0; } } menu->act->set(hotkeys); } else if (infile.key == "transformed") { pc->stats.transform_type = infile.nextValue(); if (pc->stats.transform_type != "") { pc->stats.transform_duration = -1; pc->stats.manual_untransform = toBool(infile.nextValue()); } } else if (infile.key == "powers") { string power; while ( (power = infile.nextValue()) != "") { if (toInt(power) > 0) pc->stats.powers_list.push_back(toInt(power)); } } else if (infile.key == "campaign") camp->setAll(infile.val); } infile.close(); } else fprintf(stderr, "Unable to open %s!\n", ss.str().c_str()); menu->inv->inventory[EQUIPMENT].fillEquipmentSlots(); menu->inv->addCurrency(currency); // remove items with zero quantity from inventory menu->inv->inventory[EQUIPMENT].clean(); menu->inv->inventory[CARRIED].clean(); // Load stash loadStash(); // initialize vars pc->stats.recalc(); menu->inv->applyEquipment(menu->inv->inventory[EQUIPMENT].storage); // trigger passive effects here? Saved HP/MP values might depend on passively boosted HP/MP // powers->activatePassives(pc->stats); pc->stats.logic(); // run stat logic once to apply items bonuses if (SAVE_HPMP) { if (saved_hp < 0 || saved_hp > pc->stats.get(STAT_HP_MAX)) { fprintf(stderr, "HP value is out of bounds, setting to maximum\n"); pc->stats.hp = pc->stats.get(STAT_HP_MAX); } else pc->stats.hp = saved_hp; if (saved_mp < 0 || saved_mp > pc->stats.get(STAT_MP_MAX)) { fprintf(stderr, "MP value is out of bounds, setting to maximum\n"); pc->stats.mp = pc->stats.get(STAT_MP_MAX); } else pc->stats.mp = saved_mp; } else { pc->stats.hp = pc->stats.get(STAT_HP_MAX); pc->stats.mp = pc->stats.get(STAT_MP_MAX); } // reset character menu menu->chr->refreshStats(); // just for aesthetics, turn the hero to face the camera pc->stats.direction = 6; // set up MenuTalker for this hero menu->talker->setHero(pc->stats.name, pc->stats.character_class, pc->stats.gfx_portrait); // load sounds (gender specific) pc->loadSounds(); }