Several more tweaks/fixes

- Missing special node opcodes
- Pass the party's (or in combat, the active character's) current location to special nodes triggered by timers
- Fix the set pointer node
- Fix terrain palette not correctly registering clicks while scrolled down
- Fix sheets not correctly being copied from the temporary files folder
- Fix monster abilities not being loaded from new scenarios
- Fix custom sheets not being reloaded if they have changed
- Documentation tweaks
This commit is contained in:
2015-06-02 22:01:03 -04:00
parent 322e3b9e21
commit 1b754619dc
7 changed files with 39 additions and 23 deletions

View File

@@ -211,7 +211,11 @@ flag. Put the two parts of the required stuff done flag in these two text areas.
<p><b>Message 1-3, Pict, Pict type -</b> Some special nodes display a piece of text on the
screen. Other special nodes display a dialog box, with text in the middle and a picture in
the upper left corner. The numbers for these messages and the number of the picture to
display can be put in these text fields.</p>
display can be put in these text fields. When attaching a simple text message (two
strings) to some other type of node, keep in mind that the text will display <i>after</i>
the main action of the node. For example, a Missile Animation node with attached text
messages will show the missile, then display the text. Similarly, a Pause special node will
display the text after the delay is complete.</p>
<p>Each picture and each text message has a number associated with it (for example, every
town has 100 text messages, numbered from 0 to 99). Most of the time, you really dont want
to have to worry about these. Fortunately, there is an easier way to deal with this. Press

View File

@@ -1689,7 +1689,8 @@ both in town and outdoors, but the first few only work in town. For these nodes,
values have slightly different meanings than before:</p>
<dt>Extra 1a, Extra 1b, Extra 2a, Extra 2b:</dt><dd>For each of these specials, Extra 1a
and Extra 1b are the top and left of the rectangle. Extra 2a and Extra 2b are the bottom
and right of the rectangle.
and right of the rectangle. Note that this is the reverse of standard coordinate order -
Y coordinate first, then X coordinate.
<p>The default values of Extra 2a and Extra 2b are -1. If you want the effect to only
apply to one space (and not a whole rectangle), leave Extra 2a and Extra 2b at -1. In this
case, the node only affects the space specified by Extra 1a and Extra 1b.</dd>

View File

@@ -88,13 +88,13 @@ status
traits
ap
name
level
morale
soul-crystal
monst-attack
monst-statistic
statistic
spell-mage
spell-priest

View File

@@ -1789,11 +1789,20 @@ void special_increase_age(long length, bool queue) {
unsigned short i;
short s1,s2,s3;
bool redraw = false,stat_area = false;
location null_loc; // TODO: Should we pass the party's location here? It doesn't quite make sense to me though...
location trigger_loc;
unsigned long age_before = univ.party.age - length;
unsigned long current_age = univ.party.age;
bool failed_job = false;
if(is_combat()) {
extern short combat_active_pc;
trigger_loc = univ.party[combat_active_pc].combat_pos;
} else if(is_town()) {
trigger_loc = univ.town.p_loc;
} else if(is_out()) {
trigger_loc = univ.party.p_loc;
}
for(auto& p : univ.party.quest_status) {
if(p.second != eQuestStatus::STARTED)
continue;
@@ -1844,8 +1853,8 @@ void special_increase_age(long length, bool queue) {
if(j % time == 0) {
if(queue) {
univ.party.age = j;
queue_special(eSpecCtx::TOWN_TIMER, 2, univ.town->timers[i].node, null_loc);
} else run_special(eSpecCtx::TOWN_TIMER,2,univ.town->timers[i].node,null_loc,&s1,&s2,&s3);
queue_special(eSpecCtx::TOWN_TIMER, 2, univ.town->timers[i].node, trigger_loc);
} else run_special(eSpecCtx::TOWN_TIMER,2,univ.town->timers[i].node,trigger_loc,&s1,&s2,&s3);
}
stat_area = true;
if(s3 > 0)
@@ -1860,8 +1869,8 @@ void special_increase_age(long length, bool queue) {
if(j % time == 0) {
if(queue) {
univ.party.age = j;
queue_special(eSpecCtx::SCEN_TIMER, 0, univ.scenario.scenario_timers[i].node, null_loc);
} else run_special(eSpecCtx::SCEN_TIMER,0,univ.scenario.scenario_timers[i].node,null_loc,&s1,&s2,&s3);
queue_special(eSpecCtx::SCEN_TIMER, 0, univ.scenario.scenario_timers[i].node, trigger_loc);
} else run_special(eSpecCtx::SCEN_TIMER,0,univ.scenario.scenario_timers[i].node,trigger_loc,&s1,&s2,&s3);
}
stat_area = true;
if(s3 > 0)
@@ -1873,8 +1882,8 @@ void special_increase_age(long length, bool queue) {
univ.party.age = age_before + univ.party.party_event_timers[i].time;
short which_type = univ.party.party_event_timers[i].node_type;
if(queue)
queue_special(eSpecCtx::PARTY_TIMER, which_type, univ.party.party_event_timers[i].node, null_loc);
else run_special(eSpecCtx::PARTY_TIMER,which_type,univ.party.party_event_timers[i].node,null_loc,&s1,&s2,&s3);
queue_special(eSpecCtx::PARTY_TIMER, which_type, univ.party.party_event_timers[i].node, trigger_loc);
else run_special(eSpecCtx::PARTY_TIMER,which_type,univ.party.party_event_timers[i].node,trigger_loc,&s1,&s2,&s3);
univ.party.party_event_timers[i].time = 0;
univ.party.party_event_timers[i].node = -1;
stat_area = true;
@@ -2248,7 +2257,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
else try {
if(spec.sd1 < 0 && spec.sd2 < 0)
univ.party.clear_ptr(spec.ex1a);
else univ.party.set_ptr(spec.sd1,spec.sd2,spec.ex1a);
else univ.party.set_ptr(spec.ex1a,spec.sd1,spec.sd2);
} catch(std::range_error x) {
giveError(x.what());
}

View File

@@ -996,7 +996,7 @@ bool handle_action(location the_point,sf::Event /*event*/) {
if(overall_mode < MODE_MAIN_SCREEN) {
switch(draw_mode) {
case DRAW_TERRAIN:
set_new_terrain(i);
set_new_terrain(pal_sbar->getPosition() * 16 + i);
break;
case DRAW_ITEM:
if(scenario.scen_items[mode_count].variety == eItemType::NO_ITEM) {
@@ -1004,12 +1004,12 @@ bool handle_action(location the_point,sf::Event /*event*/) {
break;
}
overall_mode = MODE_PLACE_ITEM;
mode_count = i;
mode_count = pal_sbar->getPosition() * 16 + i;
set_string("Place the item:",scenario.scen_items[mode_count].full_name.c_str());
break;
case DRAW_MONST:
overall_mode = MODE_PLACE_CREATURE;
mode_count = i + 1;
mode_count = pal_sbar->getPosition() * 16 + i + 1;
set_string("Place the monster:",scenario.scen_monsters[mode_count].m_name.c_str());
break;
}

View File

@@ -1003,25 +1003,26 @@ void save_scenario(fs::path toFile) {
pic_out << fin.rdbuf();
fin.close();
}
} else if(spec_scen_g) {
} else {
fs::path picPath = tempDir/"scenario"/"graphics";
if(fs::exists(picPath) && fs::is_directory(picPath)) {
// First build a list of overridable sheets
std::set<std::string> sheet_names;
fs::directory_iterator sheet_iter(progDir/"Scenario Editor"/"graphics.exd"/"mac");
while(sheet_iter != fs::directory_iterator()) {
for(; sheet_iter != fs::directory_iterator(); sheet_iter++) {
std::string fname = sheet_iter->path().filename().string();
size_t dot = fname.find_last_of('.');
if(dot == std::string::npos) continue;
if(fname.substr(dot) == ".png")
sheet_names.insert(fname);
sheet_iter++;
}
fs::directory_iterator dir_iter(picPath);
while(dir_iter != fs::directory_iterator()) {
for(; dir_iter != fs::directory_iterator(); dir_iter++) {
std::string fname = dir_iter->path().filename().string();
bool is_sheet = false;
if(fname.substr(0,5) == "sheet") {
size_t dot = fname.find_last_of('.');
if(dot == std::string::npos) continue;
if(fname.substr(dot) == ".png" && std::all_of(fname.begin() + 5, fname.begin() + dot, isdigit)) {
// Looks like a valid sheet!
is_sheet = true;
@@ -1036,7 +1037,6 @@ void save_scenario(fs::path toFile) {
pic_out << fin.rdbuf();
fin.close();
}
dir_iter++;
}
}
}

View File

@@ -1049,6 +1049,7 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) {
if(abil_type == eMonstAbil::NO_ABIL)
throw xMissingAttr(type, "type", data.Row(), data.Column(), fname);
uAbility& abil = monst.abil[abil_type];
abil.active = true;
Iterator<Element> elem;
if(type == "general") {
auto& general = abil.gen;
@@ -2134,6 +2135,7 @@ void load_spec_graphics_v2(int num_sheets) {
}
while(num_sheets-- > 0) {
std::string name = "sheet" + std::to_string(num_sheets);
ResMgr::free<ImageRsrc>(name);
spec_scen_g.sheets[num_sheets].loadFromImage(*ResMgr::get<ImageRsrc>(name));
}
reload_core_graphics();