Various special node fixes/tweaks

- Fix secret passage nodes (CANT_ENTER with ex1a = 0, ex2a = 1) not working
- Set many flags now sets the entire row of 50 flags
- Division node now accepts either SDF to be null
- New mode for append item to buffer - adds the item's "interesting string" rather than its name
- Affect mage/priest spell inverted the meaning of ex1b relative to other affect nodes; this has been fixed
- Fix affect party status being confused about which fields mean what (the implementation had one idea, and the porting of old scenarios had a different idea, and the scenario editor had yet a different idea). In addition, it now allows removing the statuses.
- Fix some typos in special node information for the editor
This commit is contained in:
2015-01-29 21:16:44 -05:00
parent 28a630d9e7
commit 7a59776189
8 changed files with 67 additions and 48 deletions

View File

@@ -199,6 +199,8 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
if(!is_blocked(where_check)) runSpecial = true;
if(ter_special == eTerSpec::CHANGE_WHEN_STEP_ON) runSpecial = true;
if(ter_special == eTerSpec::CALL_SPECIAL) runSpecial = true;
if(univ.town->specials[*spec_num].type == eSpecType::CANT_ENTER)
runSpecial = true;
if(!PSD[SDF_NO_BOAT_SPECIALS] && univ.party.in_boat >= 0 && univ.scenario.ter_types[ter].boat_over)
runSpecial = true;
if(runSpecial) {
@@ -2202,7 +2204,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
case eSpecType::SET_SDF_ROW:
if(spec.sd1 != minmax(0,299,spec.sd1))
giveError("Stuff Done flag out of range.");
else for(i = 0; i < 10; i++) PSD[spec.sd1][i] = spec.ex1a;
else for(i = 0; i < 50; i++) PSD[spec.sd1][i] = spec.ex1a;
break;
case eSpecType::COPY_SDF:
if(!univ.party.sd_legit(spec.sd1,spec.sd2) || !univ.party.sd_legit(spec.ex1a,spec.ex1b))
@@ -2286,8 +2288,10 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
case eSpecType::SDF_DIFF: setsd(spec.sd1, spec.sd2, i - j); break;
case eSpecType::SDF_TIMES: setsd(spec.sd1, spec.sd2, i * j); break;
case eSpecType::SDF_DIVIDE:
setsd(spec.sd1, spec.sd2, i / j);
setsd(spec.ex1c, spec.ex2c, i % j);
if(univ.party.sd_legit(spec.sd1, spec.sd2))
setsd(spec.sd1, spec.sd2, i / j);
if(univ.party.sd_legit(spec.ex1c, spec.ex2c))
setsd(spec.ex1c, spec.ex2c, i % j);
break;
case eSpecType::SDF_POWER:
if(i == 2) setsd(spec.sd1, spec.sd2, 1 << j);
@@ -2374,8 +2378,10 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
} else univ.scenario.get_buf() += univ.scenario.scen_monsters[spec.ex1a].m_name;
break;
case eSpecType::APPEND_ITEM:
if(spec.ex1b)
if(spec.ex1b == 1)
univ.scenario.get_buf() += univ.scenario.scen_items[spec.ex1a].full_name;
else if(spec.ex1b == 2)
univ.scenario.get_buf() += get_item_interesting_string(univ.scenario.scen_items[spec.ex1a]);
else univ.scenario.get_buf() += univ.scenario.scen_items[spec.ex1a].name;
break;
case eSpecType::APPEND_TER:
@@ -2922,7 +2928,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
}
for(i = 0; i < 6; i++)
if(pc_num == 6 || pc_num == i)
univ.party[i].mage_spells[spec.ex1a] = spec.ex1b;
univ.party[i].mage_spells[spec.ex1a] = !spec.ex1b;
break;
case eSpecType::AFFECT_PRIEST_SPELL:
if(pc_num >= 100) break;
@@ -2932,7 +2938,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
}
for(i = 0; i < 6; i++)
if(pc_num == 6 || pc_num == i)
univ.party[i].priest_spells[spec.ex1a] = spec.ex1b;
univ.party[i].priest_spells[spec.ex1a] = !spec.ex1b;
break;
case eSpecType::AFFECT_GOLD:
if(spec.ex1b == 0)
@@ -2957,12 +2963,14 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
break;
case eSpecType::AFFECT_PARTY_STATUS:
if(spec.ex2a < 0 || spec.ex2a > 3) break;
if(spec.ex2a == 1 && univ.party.in_boat >= 0)
if(spec.ex1b == 0 && spec.ex2a == 1 && univ.party.in_boat >= 0)
add_string_to_buf(" Can't fly when on a boat.");
else if(spec.ex2a == 1 && univ.party.in_horse >= 0)
else if(spec.ex1b == 0 && spec.ex2a == 1 && univ.party.in_horse >= 0)
add_string_to_buf(" Can't fly when on a horse.");
r1 = univ.party.status[ePartyStatus(spec.ex2a)];
r1 = minmax(0,250,r1 + spec.ex1a);
if(spec.ex1b == 0)
r1 = minmax(0,250,r1 + spec.ex1a);
else r1 = minmax(0,250,r1 - spec.ex1a);
univ.party.status[ePartyStatus::STEALTH] = r1;
break;
case eSpecType::AFFECT_TRAITS:

View File

@@ -45,7 +45,7 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) {
num_hits += trap_level;
if(trap_type == TRAP_RANDOM)
trap_type = (eTrapType) get_ran(1,0,4);
trap_type = (eTrapType) get_ran(1,1,4);
if(trap_type == TRAP_FALSE_ALARM)
return true;

View File

@@ -12,6 +12,8 @@
#include "mathutil.hpp"
void iLiving::apply_status(eStatus which, int how_much) {
if(!is_alive()) return;
static const std::set<eStatus> allow_negative = {
// The obvious ones:
eStatus::BLESS_CURSE, eStatus::HASTE_SLOW,
@@ -22,12 +24,17 @@ void iLiving::apply_status(eStatus which, int how_much) {
eStatus::MAGIC_RESISTANCE, eStatus::DUMB,
};
// TODO: Martyr's Shield range seems to be 0..10; Paralyzed seems to range something like 0..1000
int lo = 0, hi = 8;
if(!is_alive()) return;
status[which] = minmax(-8,8,status[which] + how_much);
if(!allow_negative.count(which))
status[which] = max(status[which],0);
if(which == eStatus::MARTYRS_SHIELD)
hi = 10;
else if(which == eStatus::PARALYZED)
hi = 5000;
if(allow_negative.count(which))
lo = -hi;
status[which] = minmax(lo,hi,status[which] + how_much);
}
void iLiving::clear_bad_status() {

View File

@@ -104,7 +104,7 @@ void cSpecial::append(legacy::special_node_type& old){
break;
case 99: case 100: // Add mage/priest spell TODO: Merge these by adding 100 if it's a priest spell
ex1a += 30;
ex1b = 1; // Meaning give spell, not take
ex1b = 0; // Meaning give spell, not take
break;
case 148: case 149: // if barrels or crates
type = eSpecType::IF_FIELDS;
@@ -201,15 +201,18 @@ void cSpecial::append(legacy::special_node_type& old){
// Party statuses (three nodes collapsed into one)
case 104:
type = eSpecType::AFFECT_STATUS;
ex1c = int(ePartyStatus::STEALTH);
ex1b = 0;
ex2a = int(ePartyStatus::STEALTH);
break;
case 105:
type = eSpecType::AFFECT_STATUS;
ex1c = int(ePartyStatus::FIREWALK);
ex1b = 0;
ex2a = int(ePartyStatus::FIREWALK);
break;
case 106:
type = eSpecType::AFFECT_STATUS;
ex1c = int(ePartyStatus::FLIGHT);
ex1b = 0;
ex2a = int(ePartyStatus::FLIGHT);
break;
// Place fields (twelve individual node types were collapsed into one)
case 200:
@@ -422,9 +425,9 @@ static const char*const button_dict[7][11] = {
" 5", // pic
" s", // pictype
" w q AP a ", // ex1a
" E ", // ex1b
" ", // ex1b
" e Q", // ex1c
" K ", // ex2a
" K E ", // ex2a
" D ", // ex2b
" x ", // ex2c
}, { // if-then nodes