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:
@@ -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:
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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() {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user