Move town-specific daved game data into the town record

Als, use bitsets for item_taken and maps.
This commit is contained in:
2016-08-21 16:09:58 -04:00
parent 9363ab2fcf
commit e9bf63afc7
18 changed files with 133 additions and 207 deletions

View File

@@ -163,16 +163,6 @@ void init_screen_locs() {
startup_top.left = 5; startup_top.left = 5;
startup_top.right = startup_button[STARTBTN_JOIN].right; startup_top.right = startup_button[STARTBTN_JOIN].right;
for(short i = 0; i < 200; i++)
for(short j = 0; j < 8; j++)
for(short k = 0; k < 64; k++)
univ.town_maps[i][j][k] = 0;
for(short i = 0; i < 100; i++)
for(short k = 0; k < 6; k++)
for(short l = 0; l < 48; l++)
univ.out_maps[i][k][l] = 0;
// name, use, give, drip, info, sell/id each one 13 down // name, use, give, drip, info, sell/id each one 13 down
item_buttons[0][ITEMBTN_NAME].top = 17; item_buttons[0][ITEMBTN_NAME].top = 17;
item_buttons[0][ITEMBTN_NAME].bottom = item_buttons[0][ITEMBTN_NAME].top + 12; item_buttons[0][ITEMBTN_NAME].bottom = item_buttons[0][ITEMBTN_NAME].top + 12;

View File

@@ -999,7 +999,7 @@ void handle_talk_event(location p) {
save_talk_str2 = ""; save_talk_str2 = "";
break; break;
case eTalkNode::BUY_TOWN_LOC: case eTalkNode::BUY_TOWN_LOC:
if(univ.party.can_find_town[b]) { if(univ.scenario.towns[b]->can_find) {
// TODO: Uh, is something supposed to happen here? // TODO: Uh, is something supposed to happen here?
} }
else if(univ.party.gold < a) { else if(univ.party.gold < a) {
@@ -1008,7 +1008,7 @@ void handle_talk_event(location p) {
else { else {
univ.party.gold -= a; univ.party.gold -= a;
put_pc_screen(); put_pc_screen();
univ.party.can_find_town[b] = true; univ.scenario.towns[b]->can_find = true;
} }
save_talk_str2 = ""; save_talk_str2 = "";
break; break;

View File

@@ -291,71 +291,33 @@ void build_outdoors() {
} }
short onm(char x_sector,char y_sector) {
short i;
i = y_sector * univ.scenario.outdoors.width() + x_sector;
return i;
}
// This adds the current outdoor map info to the saved outdoor map info // This adds the current outdoor map info to the saved outdoor map info
void save_outdoor_maps() { void save_outdoor_maps() {
location corner = univ.party.outdoor_corner;
for(short i = 0; i < 48; i++) for(short i = 0; i < 48; i++)
for(short j = 0; j < 48; j++) { for(short j = 0; j < 48; j++) {
if(univ.out.out_e[i][j] > 0) univ.scenario.outdoors[corner.x][corner.y]->maps[j][i] = univ.out.out_e[i][j];
univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y)][i / 8][j] = if(corner.x + 1 < univ.scenario.outdoors.width())
univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y)][i / 8][j] | univ.scenario.outdoors[corner.x + 1][corner.y]->maps[j][i] = univ.out.out_e[i + 48][j];
(char) (1 << i % 8); if(corner.y + 1 < univ.scenario.outdoors.height())
if(univ.party.outdoor_corner.x + 1 < univ.scenario.outdoors.width()) { univ.scenario.outdoors[corner.x][corner.y + 1]->maps[j][i] = univ.out.out_e[i][j + 48];
if(univ.out.out_e[i + 48][j] > 0) if(corner.y + 1 < univ.scenario.outdoors.height() && corner.x + 1 < univ.scenario.outdoors.width())
univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y)][i / 8][j] = univ.scenario.outdoors[corner.x + 1][corner.y + 1]->maps[j][i] = univ.out.out_e[i + 48][j + 48];
univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y)][i / 8][j] |
(char) (1 << i % 8);
}
if(univ.party.outdoor_corner.y + 1 < univ.scenario.outdoors.height()) {
if(univ.out.out_e[i][j + 48] > 0)
univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y + 1)][i / 8][j] =
univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y + 1)][i / 8][j] |
(char) (1 << i % 8);
}
if((univ.party.outdoor_corner.y + 1 < univ.scenario.outdoors.height()) &&
(univ.party.outdoor_corner.x + 1 < univ.scenario.outdoors.width())) {
if(univ.out.out_e[i + 48][j + 48] > 0)
univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y + 1)][i / 8][j] =
univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y + 1)][i / 8][j] |
(char) (1 << i % 8);
}
} }
} }
void add_outdoor_maps() { // This takes the existing outdoor map info and supplements it with the saved map info // This takes the existing outdoor map info and supplements it with the saved map info
void add_outdoor_maps() {
location corner = univ.party.outdoor_corner;
for(short i = 0; i < 48; i++) for(short i = 0; i < 48; i++)
for(short j = 0; j < 48; j++) { for(short j = 0; j < 48; j++) {
if((univ.out.out_e[i][j] == 0) && univ.out.out_e[i][j] = univ.scenario.outdoors[corner.x][corner.y]->maps[j][i];
((univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y)][i / 8][j] & if(corner.x + 1 < univ.scenario.outdoors.width())
(char) (1 << i % 8)) != 0)) univ.out.out_e[i + 48][j] = univ.scenario.outdoors[corner.x + 1][corner.y]->maps[j][i];
univ.out.out_e[i][j] = 1; if(corner.y + 1 < univ.scenario.outdoors.height())
if(univ.party.outdoor_corner.x + 1 < univ.scenario.outdoors.width()) { univ.out.out_e[i][j + 48] = univ.scenario.outdoors[corner.x][corner.y + 1]->maps[j][i];
if((univ.out.out_e[i + 48][j] == 0) && if(corner.y + 1 < univ.scenario.outdoors.height() && corner.x + 1 < univ.scenario.outdoors.width())
((univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y)][i / 8][j] & univ.out.out_e[i + 48][j + 48] = univ.scenario.outdoors[corner.x + 1][corner.y + 1]->maps[j][i];
(char) (1 << i % 8)) != 0))
univ.out.out_e[i + 48][j] = 1;
}
if(univ.party.outdoor_corner.y + 1 < univ.scenario.outdoors.height()) {
if((univ.out.out_e[i][j + 48] == 0) &&
((univ.out_maps[onm(univ.party.outdoor_corner.x,univ.party.outdoor_corner.y + 1)][i / 8][j] &
(char) (1 << i % 8)) != 0))
univ.out.out_e[i][j + 48] = 1;
}
if((univ.party.outdoor_corner.y + 1 < univ.scenario.outdoors.height()) &&
(univ.party.outdoor_corner.x + 1 < univ.scenario.outdoors.width())) {
if((univ.out.out_e[i + 48][j + 48] == 0) &&
((univ.out_maps[onm(univ.party.outdoor_corner.x + 1,univ.party.outdoor_corner.y + 1)][i / 8][j] &
(char) (1 << i % 8)) != 0))
univ.out.out_e[i + 48][j + 48] = 1;
}
} }
} }

View File

@@ -251,12 +251,11 @@ short dist_from_party(location where) {
return store; return store;
} }
// TODO: I have no idea what is going on here, other than that it seems to have something to do items being picked up in town // This marks the item as taken so that it won't show up again when the party returns to this town
void set_item_flag(cItem* item) { void set_item_flag(cItem* item) {
if((item->is_special > 0) && (item->is_special < 65)) { if((item->is_special > 0) && (item->is_special < 65)) {
item->is_special--; item->is_special--;
univ.party.item_taken[univ.party.town_num][item->is_special / 8] = univ.town->item_taken.set(item->is_special);
univ.party.item_taken[univ.party.town_num][item->is_special / 8] | (1 << item->is_special % 8);
item->is_special = 0; item->is_special = 0;
} }
} }

View File

@@ -54,7 +54,7 @@ void create_wand_monst() {
place_outd_wand_monst(univ.out->wandering_locs[r2], univ.out->wandering[r1],0); place_outd_wand_monst(univ.out->wandering_locs[r2], univ.out->wandering[r1],0);
} }
} else if(!univ.town->wandering[r1].isNull() && univ.town.countMonsters() <= 50 } else if(!univ.town->wandering[r1].isNull() && univ.town.countMonsters() <= 50
&& !univ.town->is_cleaned_out(univ.party.m_killed[univ.party.town_num])) { && !univ.town->is_cleaned_out()) {
// won't place wandering if more than 50 monsters // won't place wandering if more than 50 monsters
r2 = get_ran(1,0,univ.town->wandering.size() - 1); r2 = get_ran(1,0,univ.town->wandering.size() - 1);
while(point_onscreen(univ.town->wandering_locs[r2],univ.party.town_loc) && while(point_onscreen(univ.town->wandering_locs[r2],univ.party.town_loc) &&

View File

@@ -144,6 +144,13 @@ static void init_party_scen_data() {
} }
} }
} }
for(short j = 0; j < 6; j++) {
univ.party[j].status.clear();
if(isSplit(univ.party[j].main_status))
univ.party[j].main_status -= eMainStatus::SPLIT;
univ.party[j].cur_health = univ.party[j].max_health;
univ.party[j].cur_sp = univ.party[j].max_sp;
}
univ.party.in_boat = -1; univ.party.in_boat = -1;
univ.party.in_horse = -1; univ.party.in_horse = -1;
for(auto& pop : univ.party.creature_save) for(auto& pop : univ.party.creature_save)
@@ -153,22 +160,20 @@ static void init_party_scen_data() {
for(short i = 0; i < 5; i++) for(short i = 0; i < 5; i++)
for(short j = 0; j < 10; j++) for(short j = 0; j < 10; j++)
univ.party.magic_store_items[i][j].variety = eItemType::NO_ITEM; univ.party.magic_store_items[i][j].variety = eItemType::NO_ITEM;
// for(short i = 0; i < 50; i++) // TODO: Now uncertain if the journal should really persist
// univ.party.journal_str[i] = -1; // univ.party.journal.clear();
// for(short i = 0; i < 140; i++)
// for(short j = 0; j < 2; j++)
// univ.party.special_notes_str[i][j] = 0;
// for(short i = 0; i < 120; i++)
// univ.party.talk_save[i].personality = -1;
// TODO: The journal at least should persist across scenarios; the special and talk notes, maybe, maybe not
univ.party.special_notes.clear(); univ.party.special_notes.clear();
univ.party.talk_save.clear(); univ.party.talk_save.clear();
univ.party.direction = DIR_N; univ.party.direction = DIR_N;
univ.party.at_which_save_slot = 0; univ.party.at_which_save_slot = 0;
univ.party.can_find_town.resize(univ.scenario.towns.size()); for(auto town : univ.scenario.towns) {
for(short i = 0; i < univ.scenario.towns.size(); i++) town->can_find = !town->is_hidden;
univ.party.can_find_town[i] = !univ.scenario.towns[i]->is_hidden; town->m_killed = 0;
town->item_taken.reset();
for(auto& m : town->maps)
m.reset();
}
for(short i = 0; i < 20; i++) for(short i = 0; i < 20; i++)
univ.party.key_times[i] = 30000; univ.party.key_times[i] = 30000;
univ.party.party_event_timers.clear(); univ.party.party_event_timers.clear();
@@ -184,13 +189,6 @@ static void init_party_scen_data() {
} }
} }
univ.party.m_killed.clear();
univ.party.m_killed.resize(univ.scenario.towns.size());
for(short i = 0; i < 200; i++)
for(short j = 0; j < 8; j++)
univ.party.item_taken[i][j] = 0;
refresh_store_items(); refresh_store_items();
@@ -216,10 +214,9 @@ static void init_party_scen_data() {
for(short i = 0; i < 3;i++) for(short i = 0; i < 3;i++)
univ.party.stored_items[i].clear(); univ.party.stored_items[i].clear();
for(short i = 0; i < 100; i++) for(auto sector : univ.scenario.outdoors)
for(short k = 0; k < 6; k++) for(auto& m : sector->maps)
for(short l = 0; l < 48; l++) m.reset();
univ.out_maps[i][k][l] = 0;
} }
@@ -234,14 +231,6 @@ void put_party_in_scen(std::string scen_name) {
univ.ghost_mode = false; univ.ghost_mode = false;
univ.node_step_through = false; univ.node_step_through = false;
for(short j = 0; j < 6; j++) {
univ.party[j].status.clear();
if(isSplit(univ.party[j].main_status))
univ.party[j].main_status -= eMainStatus::SPLIT;
univ.party[j].cur_health = univ.party[j].max_health;
univ.party[j].cur_sp = univ.party[j].max_sp;
}
// TODO: The above probably belongs in init_party_scen_data
for(short j = 0; j < 6; j++) for(short j = 0; j < 6; j++)
for(short i = 23; i >= 0; i--) { for(short i = 23; i >= 0; i--) {
cItem& thisItem = univ.party[j].items[i]; cItem& thisItem = univ.party[j].items[i];
@@ -268,10 +257,6 @@ void put_party_in_scen(std::string scen_name) {
} }
if(item_took) if(item_took)
cChoiceDlog("removed-special-items").show(); cChoiceDlog("removed-special-items").show();
univ.party.age = 0;
univ.party.m_killed.clear();
univ.party.m_killed.resize(univ.scenario.towns.size());
univ.party.party_event_timers.clear();
fs::path path = locate_scenario(scen_name); fs::path path = locate_scenario(scen_name);
if(path.empty()) { if(path.empty()) {

View File

@@ -1652,7 +1652,7 @@ void kill_monst(cCreature& which_m,short who_killed,eMainStatus type) {
} }
if((is_town() || which_combat_type == 1) && which_m.summon_time == 0) { if((is_town() || which_combat_type == 1) && which_m.summon_time == 0) {
univ.party.m_killed[univ.party.town_num]++; univ.town->m_killed++;
} }
which_m.spec1 = 0; // make sure, if this is a spec. activated monster, it won't come back which_m.spec1 = 0; // make sure, if this is a spec. activated monster, it won't come back
@@ -2227,7 +2227,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
check_mess = true; check_mess = true;
if(spec.ex1a != minmax(0,univ.scenario.towns.size() - 1,spec.ex1a)) if(spec.ex1a != minmax(0,univ.scenario.towns.size() - 1,spec.ex1a))
showError("Town out of range."); showError("Town out of range.");
else univ.party.can_find_town[spec.ex1a] = spec.ex2a; else univ.scenario.towns[spec.ex1a]->can_find = spec.ex2a;
*redraw = true; *redraw = true;
break; break;
case eSpecType::MAJOR_EVENT_OCCURRED: case eSpecType::MAJOR_EVENT_OCCURRED:

View File

@@ -679,7 +679,7 @@ void print_party_stats() {
add_string_to_buf("PARTY STATS:"); add_string_to_buf("PARTY STATS:");
add_string_to_buf(" Number of kills: " + std::to_string(univ.party.total_m_killed)); add_string_to_buf(" Number of kills: " + std::to_string(univ.party.total_m_killed));
if((is_town()) || ((is_combat()) && (which_combat_type == 1))) { if((is_town()) || ((is_combat()) && (which_combat_type == 1))) {
add_string_to_buf(" Kills in this town: " + std::to_string(univ.party.m_killed[univ.party.town_num])); add_string_to_buf(" Kills in this town: " + std::to_string(univ.town->m_killed));
} }
add_string_to_buf(" Total experience: " + std::to_string(univ.party.total_xp_gained)); add_string_to_buf(" Total experience: " + std::to_string(univ.party.total_xp_gained));
add_string_to_buf(" Total damage done: " + std::to_string(univ.party.total_dam_done)); add_string_to_buf(" Total damage done: " + std::to_string(univ.party.total_dam_done));

View File

@@ -127,7 +127,7 @@ void start_town_mode(short which_town, short entry_dir) {
// Set up map, using stored map // Set up map, using stored map
for(short i = 0; i < univ.town->max_dim(); i++) for(short i = 0; i < univ.town->max_dim(); i++)
for(short j = 0; j < univ.town->max_dim(); j++) { for(short j = 0; j < univ.town->max_dim(); j++) {
if(univ.town_maps[univ.party.town_num][i / 8][j] & (char)(1 << i % 8)) if(univ.town->maps[j][i])
make_explored(i,j); make_explored(i,j);
if(univ.town->terrain(i,j) == 0) if(univ.town->terrain(i,j) == 0)
@@ -218,7 +218,7 @@ void start_town_mode(short which_town, short entry_dir) {
// TODO: Should these two cases be separated? // TODO: Should these two cases be separated?
if(univ.town->town_chop_time > 0 && day_reached(univ.town->town_chop_time,univ.town->town_chop_key)) if(univ.town->town_chop_time > 0 && day_reached(univ.town->town_chop_time,univ.town->town_chop_key))
univ.town.monst[j].active += 10; univ.town.monst[j].active += 10;
else if(univ.town->is_cleaned_out(univ.party.m_killed[univ.party.town_num])) else if(univ.town->is_cleaned_out())
univ.town.monst[j].active += 10; univ.town.monst[j].active += 10;
else univ.town.monst[j].active = 0; else univ.town.monst[j].active = 0;
if(univ.town.monst[j].active >= 10) if(univ.town.monst[j].active >= 10)
@@ -290,7 +290,7 @@ void start_town_mode(short which_town, short entry_dir) {
// TODO: Should these two cases be separated? // TODO: Should these two cases be separated?
if(univ.town->town_chop_time > 0 && day_reached(univ.town->town_chop_time,univ.town->town_chop_key)) if(univ.town->town_chop_time > 0 && day_reached(univ.town->town_chop_time,univ.town->town_chop_key))
univ.town.monst[i].active += 10; univ.town.monst[i].active += 10;
else if(univ.town->is_cleaned_out(univ.party.m_killed[univ.party.town_num])) else if(univ.town->is_cleaned_out())
univ.town.monst[i].active += 10; univ.town.monst[i].active += 10;
else univ.town.monst[i].active = 0; else univ.town.monst[i].active = 0;
break; break;
@@ -319,7 +319,7 @@ void start_town_mode(short which_town, short entry_dir) {
// Thrash town? // Thrash town?
if(univ.town->is_cleaned_out(univ.party.m_killed[univ.party.town_num])) { if(univ.town->is_cleaned_out()) {
town_toast = true; town_toast = true;
add_string_to_buf("Area has been cleaned out."); add_string_to_buf("Area has been cleaned out.");
} }
@@ -373,7 +373,7 @@ void start_town_mode(short which_town, short entry_dir) {
for(short i = 0; i < univ.town->preset_items.size(); i++) for(short i = 0; i < univ.town->preset_items.size(); i++)
if((univ.town->preset_items[i].code >= 0) if((univ.town->preset_items[i].code >= 0)
&& (((univ.party.item_taken[univ.party.town_num][i / 8] & (1 << i % 8)) == 0) || && (!univ.town->item_taken[i] ||
(univ.town->preset_items[i].always_there))) { (univ.town->preset_items[i].always_there))) {
// place the preset item, if party hasn't gotten it already // place the preset item, if party hasn't gotten it already
univ.town.items.push_back(get_stored_item(univ.town->preset_items[i].code)); univ.town.items.push_back(get_stored_item(univ.town->preset_items[i].code));
@@ -571,8 +571,7 @@ location end_town_mode(short switching_level,location destination) { // returns
for(short i = 0; i < univ.town->max_dim(); i++) for(short i = 0; i < univ.town->max_dim(); i++)
for(short j = 0; j < univ.town->max_dim(); j++) for(short j = 0; j < univ.town->max_dim(); j++)
if(is_explored(i,j)) { if(is_explored(i,j)) {
univ.town_maps[univ.party.town_num][i / 8][j] = univ.town_maps[univ.party.town_num][i / 8][j] | univ.town->maps[j].set(i);
(char) (1 << i % 8);
} }
to_return = univ.party.out_loc; to_return = univ.party.out_loc;
@@ -1268,11 +1267,11 @@ void erase_out_specials() {
(sector.city_locs[k].y == minmax(0,47,sector.city_locs[k].y))) { (sector.city_locs[k].y == minmax(0,47,sector.city_locs[k].y))) {
if(sector.city_locs[k].spec < 0 || sector.city_locs[k].spec >= univ.scenario.towns.size()) if(sector.city_locs[k].spec < 0 || sector.city_locs[k].spec >= univ.scenario.towns.size())
continue; continue;
if(!univ.party.can_find_town[sector.city_locs[k].spec]) { if(!univ.scenario.towns[sector.city_locs[k].spec]->can_find) {
univ.out[48 * i + sector.city_locs[k].x][48 * j + sector.city_locs[k].y] = univ.out[48 * i + sector.city_locs[k].x][48 * j + sector.city_locs[k].y] =
univ.scenario.ter_types[sector.terrain[sector.city_locs[k].x][sector.city_locs[k].y]].flag1; univ.scenario.ter_types[sector.terrain[sector.city_locs[k].x][sector.city_locs[k].y]].flag1;
} }
else if(univ.party.can_find_town[sector.city_locs[k].spec]) { else if(univ.scenario.towns[sector.city_locs[k].spec]->can_find) {
univ.out[48 * i + sector.city_locs[k].x][48 * j + sector.city_locs[k].y] = univ.out[48 * i + sector.city_locs[k].x][48 * j + sector.city_locs[k].y] =
sector.terrain[sector.city_locs[k].x][sector.city_locs[k].y]; sector.terrain[sector.city_locs[k].x][sector.city_locs[k].y];

View File

@@ -78,6 +78,8 @@ public:
eAmbientSound ambient_sound; eAmbientSound ambient_sound;
snd_num_t out_sound; snd_num_t out_sound;
int bg_out, bg_fight, bg_town, bg_dungeon; int bg_out, bg_fight, bg_town, bg_dungeon;
// Persistent data for saved games
std::array<std::bitset<48>, 48> maps;
explicit cOutdoors(cScenario& scenario); explicit cOutdoors(cScenario& scenario);
void append(legacy::outdoor_record_type& old); void append(legacy::outdoor_record_type& old);

View File

@@ -53,16 +53,13 @@ cParty::~cParty() {
} }
} }
void cParty::append(legacy::party_record_type& old, const cScenario& scen){ void cParty::append(legacy::party_record_type& old, cUniverse& univ){
age = old.age; age = old.age;
gold = old.gold; gold = old.gold;
food = old.food; food = old.food;
for(short i = 0; i < 310; i++) for(short i = 0; i < 310; i++)
for(short j = 0; j < 10; j++) for(short j = 0; j < 10; j++)
stuff_done[i][j] = old.stuff_done[i][j]; stuff_done[i][j] = old.stuff_done[i][j];
for(short i = 0; i < 200; i++)
for(short j = 0; j < 8; j++)
item_taken[i][j] = old.item_taken[i][j];
light_level = old.light_level; light_level = old.light_level;
if(stuff_done[305][0] > 0) if(stuff_done[305][0] > 0)
status[ePartyStatus::STEALTH] = stuff_done[305][0]; status[ePartyStatus::STEALTH] = stuff_done[305][0];
@@ -108,26 +105,18 @@ void cParty::append(legacy::party_record_type& old, const cScenario& scen){
for(short i = 0; i < 256; i++) for(short i = 0; i < 256; i++)
if(old.m_seen[i]) if(old.m_seen[i])
m_noted.insert(i); m_noted.insert(i);
journal.reserve(50);
// The journal wasn't used before, so let's not bother converting it
// for(short i = 0; i < 50; i++){
// cJournal j;
// j.day = old.journal_day[i];
// journal.push_back(j);
// spec_items[i] = old.spec_items[i];
// }
if(!scen_name.empty()) { if(!scen_name.empty()) {
special_notes.reserve(140); special_notes.reserve(140);
for(short i = 0; i < 140; i++){ for(short i = 0; i < 140; i++){
if(old.special_notes_str[i][0] <= 0) continue; if(old.special_notes_str[i][0] <= 0) continue;
cEncNote n; cEncNote n;
n.append(old.special_notes_str[i], scen); n.append(old.special_notes_str[i], univ.scenario);
special_notes.push_back(n); special_notes.push_back(n);
} }
talk_save.reserve(120); talk_save.reserve(120);
for(short i = 0; i < 120; i++){ for(short i = 0; i < 120; i++){
cConvers t; cConvers t;
t.append(old.talk_save[i], scen); t.append(old.talk_save[i], univ.scenario);
talk_save.push_back(t); talk_save.push_back(t);
} }
} }
@@ -135,11 +124,11 @@ void cParty::append(legacy::party_record_type& old, const cScenario& scen){
at_which_save_slot = old.at_which_save_slot; at_which_save_slot = old.at_which_save_slot;
for(short i = 0; i < 20 ; i++) for(short i = 0; i < 20 ; i++)
alchemy[i] = old.alchemy[i]; alchemy[i] = old.alchemy[i];
can_find_town.resize(200); for(short i = 0; i < univ.scenario.towns.size(); i++){
m_killed.resize(200); univ.scenario.towns[i]->can_find = old.can_find_town[i];
for(short i = 0; i < 200; i++){ univ.scenario.towns[i]->m_killed = old.m_killed[i];
can_find_town[i] = old.can_find_town[i]; for(short j = 0; j < 64; j++)
m_killed[i] = old.m_killed[i]; univ.scenario.towns[i]->item_taken[j] = old.item_taken[i][j / 8] & (1 << j % 8);
} }
for(short i = 0; i < 100; i++) for(short i = 0; i < 100; i++)
key_times[i] = old.key_times[i]; key_times[i] = old.key_times[i];
@@ -538,7 +527,7 @@ bool cParty::start_timer(short time, short node, short type){
return(true); return(true);
} }
void cParty::writeTo(std::ostream& file) const { void cParty::writeTo(std::ostream& file, const cScenario& scen) const {
file << "CREATEVERSION " << std::hex << OBOE_CURRENT_VERSION << std::dec << '\n'; file << "CREATEVERSION " << std::hex << OBOE_CURRENT_VERSION << std::dec << '\n';
file << "AGE " << age << '\n'; file << "AGE " << age << '\n';
file << "GOLD " << gold << '\n'; file << "GOLD " << gold << '\n';
@@ -555,14 +544,6 @@ void cParty::writeTo(std::ostream& file) const {
file << "POINTER " << iter->first << ' ' << iter->second.first << ' ' << iter->second.second << '\n'; file << "POINTER " << iter->first << ' ' << iter->second.first << ' ' << iter->second.second << '\n';
for(int i = 0; i < magic_ptrs.size(); i++) for(int i = 0; i < magic_ptrs.size(); i++)
file << "POINTER " << i << ' ' << int(magic_ptrs[i]) << '\n'; file << "POINTER " << i << ' ' << int(magic_ptrs[i]) << '\n';
for(int i = 0; i < 200; i++)
if(item_taken[i][0] > 0 || item_taken[i][1] > 0 || item_taken[i][2] > 0 || item_taken[i][3] > 0 ||
item_taken[i][4] > 0 || item_taken[i][5] > 0 || item_taken[i][6] > 0 || item_taken[i][7] > 0) {
file << "ITEMTAKEN " << i;
for(int j = 0; j < 8; j++)
file << ' ' << unsigned(item_taken[i][j]);
file << '\n';
}
file << "LIGHT " << light_level << '\n'; file << "LIGHT " << light_level << '\n';
file << "OUTCORNER " << outdoor_corner.x << ' ' << outdoor_corner.y << '\n'; file << "OUTCORNER " << outdoor_corner.x << ' ' << outdoor_corner.y << '\n';
file << "INWHICHCORNER " << i_w_c.x << ' ' << i_w_c.y << '\n'; file << "INWHICHCORNER " << i_w_c.x << ' ' << i_w_c.y << '\n';
@@ -594,16 +575,18 @@ void cParty::writeTo(std::ostream& file) const {
for(int i = 0; i < alchemy.size(); i++) for(int i = 0; i < alchemy.size(); i++)
if(alchemy[i]) if(alchemy[i])
file << "ALCHEMY " << i << '\n'; file << "ALCHEMY " << i << '\n';
for(int i = 0; i < can_find_town.size(); i++) for(int i = 0; i < scen.towns.size(); i++) {
if(can_find_town[i]) if(scen.towns[i]->item_taken.any())
file << "TOWNVISIBLE " << i << '\n'; file << "ITEMTAKEN " << i << ' ' << scen.towns[i]->item_taken << '\n';
if(scen.towns[i]->can_find == scen.towns[i]->is_hidden)
file << (scen.towns[i]->can_find ? "TOWNVISIBLE " : "TOWNHIDDEN ") << i << '\n';
if(scen.towns[i]->m_killed > 0)
file << "TOWNSLAUGHTER " << i << ' ' << scen.towns[i]->m_killed << '\n';
}
for(auto key : key_times) for(auto key : key_times)
file << "EVENT " << key.first << ' ' << key.second << '\n'; file << "EVENT " << key.first << ' ' << key.second << '\n';
for(int i : spec_items) for(int i : spec_items)
file << "ITEM " << i << '\n'; file << "ITEM " << i << '\n';
for(int i = 0; i < m_killed.size(); i++)
if(m_killed[i] > 0)
file << "TOWNSLAUGHTER " << i << ' ' << m_killed[i] << '\n';
file << "KILLS " << total_m_killed << '\n'; file << "KILLS " << total_m_killed << '\n';
file << "DAMAGE " << total_dam_done << '\n'; file << "DAMAGE " << total_dam_done << '\n';
file << "WOUNDS " << total_dam_taken << '\n'; file << "WOUNDS " << total_dam_taken << '\n';
@@ -728,7 +711,7 @@ void cParty::writeTo(std::ostream& file) const {
} }
} }
void cParty::readFrom(std::istream& file){ void cParty::readFrom(std::istream& file, cScenario& scen){
// TODO: Error-check input // TODO: Error-check input
// TODO: Don't call this sin, it's a trig function // TODO: Don't call this sin, it's a trig function
std::istringstream bin; std::istringstream bin;
@@ -787,11 +770,8 @@ void cParty::readFrom(std::istream& file){
}else if(cur == "ITEMTAKEN"){ }else if(cur == "ITEMTAKEN"){
int i; int i;
sin >> i; sin >> i;
for(int j = 0; j < 8; j++) { if(i >= 0 && i < scen.towns.size())
unsigned int n; sin >> scen.towns[i]->item_taken;
sin >> n;
item_taken[i][j] = n;
}
}else if(cur == "LIGHT") }else if(cur == "LIGHT")
sin >> light_level; sin >> light_level;
else if(cur == "OUTCORNER") else if(cur == "OUTCORNER")
@@ -840,9 +820,13 @@ void cParty::readFrom(std::istream& file){
} else if(cur == "TOWNVISIBLE") { } else if(cur == "TOWNVISIBLE") {
int i; int i;
sin >> i; sin >> i;
if(i >= can_find_town.size()) if(i >= 0 && i < scen.towns.size())
can_find_town.resize(i + 1); scen.towns[i]->can_find = true;
can_find_town[i] = true; } else if(cur == "TOWNHIDDEN") {
int i;
sin >> i;
if(i >= 0 && i < scen.towns.size())
scen.towns[i]->can_find = false;
}else if(cur == "EVENT"){ }else if(cur == "EVENT"){
int i; int i;
sin >> i; sin >> i;
@@ -854,9 +838,8 @@ void cParty::readFrom(std::istream& file){
}else if(cur == "TOWNSLAUGHTER"){ }else if(cur == "TOWNSLAUGHTER"){
int i; int i;
sin >> i; sin >> i;
if(i >= m_killed.size()) if(i >= 0 && i < scen.towns.size())
m_killed.resize(i + 1); sin >> scen.towns[i]->m_killed;
sin >> m_killed[i];
} else if(cur == "QUEST") { } else if(cur == "QUEST") {
int i; int i;
sin >> i; sin >> i;

View File

@@ -45,6 +45,7 @@ struct job_bank_t {
bool inited = false; bool inited = false;
}; };
class cUniverse;
class cItem; class cItem;
class cParty : public iLiving { class cParty : public iLiving {
@@ -80,7 +81,6 @@ public:
bool easy_mode = false, less_wm = false; bool easy_mode = false, less_wm = false;
// End former magic SDFs // End former magic SDFs
std::array<unsigned char,90> magic_ptrs; std::array<unsigned char,90> magic_ptrs;
unsigned char item_taken[200][8];
short light_level; short light_level;
location outdoor_corner; location outdoor_corner;
location i_w_c; location i_w_c;
@@ -113,11 +113,9 @@ public:
eDirection direction; eDirection direction;
short at_which_save_slot; short at_which_save_slot;
std::bitset<20> alchemy; std::bitset<20> alchemy;
std::vector<bool> can_find_town;
std::map<int,int> key_times; std::map<int,int> key_times;
std::vector<cTimer> party_event_timers; std::vector<cTimer> party_event_timers;
std::set<int> spec_items; std::set<int> spec_items;
std::vector<long> m_killed;
long long total_m_killed, total_dam_done, total_xp_gained, total_dam_taken; long long total_m_killed, total_dam_done, total_xp_gained, total_dam_taken;
std::string scen_name; std::string scen_name;
private: private:
@@ -138,7 +136,7 @@ public:
void clear_ptr(unsigned short p); void clear_ptr(unsigned short p);
unsigned char get_ptr(unsigned short p); unsigned char get_ptr(unsigned short p);
void append(legacy::party_record_type& old, const cScenario& scen); void append(legacy::party_record_type& old, cUniverse& univ);
void append(legacy::big_tr_type& old); void append(legacy::big_tr_type& old);
void append(legacy::stored_items_list_type& old,short which_list); void append(legacy::stored_items_list_type& old,short which_list);
void append(legacy::setup_save_type& old); void append(legacy::setup_save_type& old);
@@ -184,8 +182,8 @@ public:
bool start_timer(short time, short node, short type); bool start_timer(short time, short node, short type);
cPlayer& operator[](unsigned short n); cPlayer& operator[](unsigned short n);
const cPlayer& operator[](unsigned short n) const; const cPlayer& operator[](unsigned short n) const;
void writeTo(std::ostream& file) const; void writeTo(std::ostream& file, const cScenario& scen) const;
void readFrom(std::istream& file); void readFrom(std::istream& file, cScenario& scen);
bool give_item(cItem item,int flags); bool give_item(cItem item,int flags);
bool forced_give(cItem item,eItemAbil abil,short dat = -1); bool forced_give(cItem item,eItemAbil abil,short dat = -1);

View File

@@ -173,7 +173,7 @@ bool cTown::cWandering::isNull(){
return true; return true;
} }
bool cTown::is_cleaned_out(long m_killed) { bool cTown::is_cleaned_out() {
if(max_num_monst < 0) return false; if(max_num_monst < 0) return false;
return m_killed >= max_num_monst; return m_killed >= max_num_monst;
} }

View File

@@ -91,6 +91,11 @@ public:
std::array<std::string,3> comment; std::array<std::string,3> comment;
std::vector<std::string> spec_strs; std::vector<std::string> spec_strs;
cSpeech talking; cSpeech talking;
// Persistent data for saved games
std::array<std::bitset<64>, 64> maps;
std::bitset<64> item_taken;
bool can_find;
long m_killed;
virtual ~cTown(){} virtual ~cTown(){}
virtual void append(legacy::big_tr_type& old, int town_num); virtual void append(legacy::big_tr_type& old, int town_num);
@@ -103,7 +108,7 @@ public:
void init_start(); void init_start();
void set_up_lights(); void set_up_lights();
short light_obscurity(short x,short y); // Obscurity function used for calculating lighting short light_obscurity(short x,short y); // Obscurity function used for calculating lighting
bool is_cleaned_out(long m_killed); bool is_cleaned_out();
explicit cTown(cScenario& scenario); explicit cTown(cScenario& scenario);
void append(legacy::town_record_type& old); void append(legacy::town_record_type& old);

View File

@@ -64,16 +64,21 @@ void cCurTown::append(legacy::town_item_list& old){
void cUniverse::append(legacy::stored_town_maps_type& old){ void cUniverse::append(legacy::stored_town_maps_type& old){
for(int n = 0; n < 200; n++) for(int n = 0; n < 200; n++)
for(int i = 0; i < 8; i++) for(int i = 0; i < 64; i++)
for(int j = 0; j < 64; j++) for(int j = 0; j < 64; j++)
town_maps[n][i][j] = old.town_maps[n][i][j]; scenario.towns[n]->maps[j][i] = old.town_maps[n][i / 8][j] & (1 << (i % 8));
}
static short onm(char x_sector,char y_sector, char w) {
return y_sector * w + x_sector;
} }
void cUniverse::append(legacy::stored_outdoor_maps_type& old){ void cUniverse::append(legacy::stored_outdoor_maps_type& old){
for(int n = 0; n < 100; n++) for(int x = 0; x < scenario.outdoors.width(); x++)
for(int i = 0; i < 6; i++) for(int y = 0; y < scenario.outdoors.height(); y++)
for(int j = 0; j < 48; j++) for(int i = 0; i < 48; i++)
out_maps[n][i][j] = old.outdoor_maps[n][i][j]; for(int j = 0; j < 48; j++)
scenario.outdoors[x][y]->maps[i][j] = old.outdoor_maps[onm(x,y,scenario.outdoors.width())][i / 8][j] & (1 << i % 8);
} }
void cCurTown::append(unsigned char(& old_sfx)[64][64], unsigned char(& old_misc_i)[64][64]){ void cCurTown::append(unsigned char(& old_sfx)[64][64], unsigned char(& old_misc_i)[64][64]){

View File

@@ -176,9 +176,7 @@ public:
cParty party; cParty party;
std::map<long,cPlayer*> stored_pcs; std::map<long,cPlayer*> stored_pcs;
cCurTown town; cCurTown town;
unsigned char town_maps[200][8][64]; // formerly stored_town_maps_type
cCurOut out; cCurOut out;
unsigned char out_maps[100][6][48]; // formerly stored_outdoor_maps_type
fs::path file; fs::path file;
bool debug_mode, ghost_mode, node_step_through; bool debug_mode, ghost_mode, node_step_through;

View File

@@ -285,17 +285,15 @@ void handle_menu_choice(eMenu item_hit) {
break; break;
case eMenu::ADD_OUT_MAPS: case eMenu::ADD_OUT_MAPS:
display_strings(13,15); display_strings(13,15);
for(short i = 0; i < 100; i++) for(auto sector : univ.scenario.outdoors)
for(short j = 0; j < 6; j++) for(auto& m : sector->maps)
for(short k = 0; k < 48; k++) m.set();
univ.out_maps[i][j][k] = 255;
break; break;
case eMenu::ADD_TOWN_MAPS: case eMenu::ADD_TOWN_MAPS:
display_strings(14,15); display_strings(14,15);
for(short i = 0; i < 200; i++) for(auto town : univ.scenario.towns)
for(short j = 0; j < 8; j++) for(auto& m : town->maps)
for(short k = 0; k < 64; k++) m.set();
univ.town_maps[i][j][k] = 255;
break; break;
case eMenu::EDIT_MAGE: case eMenu::EDIT_MAGE:
display_pc(current_active_pc,10,0); display_pc(current_active_pc,10,0);

View File

@@ -233,7 +233,7 @@ bool load_party_v1(fs::path file_to_load, cUniverse& univ, bool town_restore, bo
univ.party.scen_name = ""; univ.party.scen_name = "";
} }
univ.party.append(store_party, univ.scenario); univ.party.append(store_party, univ);
univ.party.append(store_setup); univ.party.append(store_setup);
univ.party.append(store_pc); univ.party.append(store_pc);
if(in_scen){ if(in_scen){
@@ -280,7 +280,7 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ){
showError("Loading Blades of Exile save file failed."); showError("Loading Blades of Exile save file failed.");
return false; return false;
} }
univ.party.readFrom(fin); univ.party.readFrom(fin, univ.scenario);
} }
{ // Then the "setup" array { // Then the "setup" array
@@ -343,10 +343,9 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ){
// Read town maps // Read town maps
std::istream& fin2 = partyIn.getFile("save/townmaps.dat"); std::istream& fin2 = partyIn.getFile("save/townmaps.dat");
for(int i = 0; i < 200; i++) for(int i = 0; i < univ.scenario.towns.size(); i++)
for(int j = 0; j < 8; j++) for(int j = 0; j < 64; j++)
for(int k = 0; k < 64; k++) fin2 >> univ.scenario.towns[i]->maps[j];
univ.town_maps[i][j][k] = fin2.get();
} else univ.party.town_num = 200; } else univ.party.town_num = 200;
// Load outdoors data // Load outdoors data
@@ -359,10 +358,10 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ){
// Read outdoor maps // Read outdoor maps
std::istream& fin2 = partyIn.getFile("save/outmaps.dat"); std::istream& fin2 = partyIn.getFile("save/outmaps.dat");
for(int i = 0; i < 100; i++) for(int i = 0; i < univ.scenario.outdoors.height(); i++)
for(int j = 0; j < 6; j++) for(int j = 0; j < 48; j++)
for(int k = 0; k < 48; k++) for(int k = 0; k < univ.scenario.outdoors.width(); k++)
univ.out_maps[i][j][k] = fin2.get(); fin2 >> univ.scenario.outdoors[k][i]->maps[j];
} else univ.party.scen_name = ""; } else univ.party.scen_name = "";
if(partyIn.hasFile("save/export.png")) { if(partyIn.hasFile("save/export.png")) {
@@ -391,7 +390,7 @@ bool save_party(fs::path dest_file, const cUniverse& univ) {
tarball partyOut; tarball partyOut;
// First, write the main party data // First, write the main party data
univ.party.writeTo(partyOut.newFile("save/party.txt")); univ.party.writeTo(partyOut.newFile("save/party.txt"), univ.scenario);
{ {
std::ostream& fout = partyOut.newFile("save/setup.dat"); std::ostream& fout = partyOut.newFile("save/setup.dat");
static uint16_t magic = 0x0B0E; static uint16_t magic = 0x0B0E;
@@ -423,10 +422,9 @@ bool save_party(fs::path dest_file, const cUniverse& univ) {
// Write the town map data // Write the town map data
std::ostream& fout = partyOut.newFile("save/townmaps.dat"); std::ostream& fout = partyOut.newFile("save/townmaps.dat");
for(int i = 0; i < 200; i++) for(int i = 0; i < univ.scenario.towns.size(); i++)
for(int j = 0; j < 8; j++) for(int j = 0; j < 64; j++)
for(int k = 0; k < 64; k++) fout << univ.scenario.towns[i]->maps[j] << '\n';
fout.put(univ.town_maps[i][j][k]);
} }
// Write the current outdoors data // Write the current outdoors data
@@ -434,10 +432,14 @@ bool save_party(fs::path dest_file, const cUniverse& univ) {
// Write the outdoors map data // Write the outdoors map data
std::ostream& fout = partyOut.newFile("save/outmaps.dat"); std::ostream& fout = partyOut.newFile("save/outmaps.dat");
for(int i = 0; i < 100; i++) for(int i = 0; i < univ.scenario.outdoors.height(); i++) {
for(int j = 0; j < 6; j++) for(int j = 0; j < 48; j++) {
for(int k = 0; k < 48; k++) for(int k = 0; k < univ.scenario.outdoors.width(); k++)
fout.put(univ.out_maps[i][j][k]); fout << univ.scenario.outdoors[k][i]->maps[j] << ' ';
fout << '\n';
}
fout << '\n';
}
} }
if(spec_scen_g.party_sheet) { if(spec_scen_g.party_sheet) {