Associate reserved pointers directly to their values, rather than referencing magic SDFs

- String buffer referencing is no longer done via a pointer but instead by a magic value separate from the pointer system (it's still -8 though)
- String buffer now stored in universe instead of scenario
This commit is contained in:
2015-06-07 02:46:57 -04:00
parent 01d317b007
commit 543ccdc670
10 changed files with 81 additions and 105 deletions

View File

@@ -71,8 +71,6 @@ special node. In addition, there are a number of reserved pointers that are set
circumstances. Rather than referencing a Stuff Done Flag, these refer to special values of
the encounter itself. The reserved pointers are:</p>
<ol start=''>
<li value='5'>If the special node was called to determine the result of a custom trap
effect, this pointer refers to the trap level.</li>
<li value='8'>This can be used anywhere a scenario message is expected to refer to the
special string buffer. The contents of the special string buffer can be manipulated using
the Clear Buffer special node and various Append To Buffer special nodes.</li>
@@ -80,6 +78,8 @@ the Clear Buffer special node and various Append To Buffer special nodes.</li>
on.</li>
<li>This contains the Y coordinate of the space the special node was triggered on.</li>
<li>This contains the terrain type of the space the special node was triggered on.</li>
<li value='15'>If the special node was called to determine the result of a custom trap
effect, this pointer refers to the trap level.</li>
<li value='20'>When a special node is called during an attack, this contains the number of
the targeted creature, ready to be passed to a Select Target special node.</li>
<li>When a special node is called during an attack, this contains the X coordinate of the

View File

@@ -416,7 +416,10 @@ given in the Transform To What field, it is changed to that terrain type.
<dt>Extra 1a, Extra 1b:</dt><dd>The x and y coordinates of the space to
transform.</dd></dd>
<dt>Type 37: Clear String Buffer</dt><dd>Clears the string buffer.</dd>
<dt>Type 37: Clear String Buffer</dt><dd>Clears the string buffer. It's best to always do
this before you use the buffer. The buffer is never automatically cleared, but it is not
saved, so if the user reloads from a saved game, anything that was in the buffer may be
lost.</dd>
<dt>Type 38: Append String to Buffer</dt><dd>Appends a literal string to the string buffer.
<dl>

View File

@@ -847,12 +847,9 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
}
} else if(weap.ability == eItemAbil::WEAPON_CALL_SPECIAL) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = target.get_loc().x;
PSD[SDF_SPEC_TARGLOC_Y] = target.get_loc().y;
PSD[SDF_SPEC_TARGET] = i_monst;
univ.party.force_ptr(21, target.get_loc().x);
univ.party.force_ptr(22, target.get_loc().y);
univ.party.force_ptr(20, i_monst);
run_special(eSpecCtx::ATTACKING_MELEE, 0, weap.abil_data[0],univ.party[who_att].combat_pos, &s1, &s2, &s3);
}
}
@@ -1826,32 +1823,23 @@ void fire_missile(location target) {
} else if(ammo.ability == eItemAbil::WEAPON_CALL_SPECIAL) {
// TODO: Should this be checked on the missile as well as on the ammo? (Provided they're different.)
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = victim->get_loc().x;
PSD[SDF_SPEC_TARGLOC_Y] = victim->get_loc().y;
PSD[SDF_SPEC_TARGET] = univ.get_target_i(*victim);
univ.party.force_ptr(21, victim->get_loc().x);
univ.party.force_ptr(22, victim->get_loc().y);
univ.party.force_ptr(20, univ.get_target_i(*victim));
run_special(eSpecCtx::ATTACKING_RANGE, 0, missile.abil_data[0], missile_firer.combat_pos, &s1, &s2, &s3);
}
cCreature* monst; cPlayer* pc; int spec_item;
if((monst = dynamic_cast<cCreature*>(victim)) && monst->abil[eMonstAbil::HIT_TRIGGER].active) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = monst->cur_loc.x;
PSD[SDF_SPEC_TARGLOC_Y] = monst->cur_loc.y;
PSD[SDF_SPEC_TARGET] = univ.get_target_i(*monst);
univ.party.force_ptr(21, monst->cur_loc.x);
univ.party.force_ptr(22, monst->cur_loc.y);
univ.party.force_ptr(20, univ.get_target_i(*monst));
run_special(eSpecCtx::ATTACKED_RANGE, 0, monst->abil[eMonstAbil::HIT_TRIGGER].special.extra1, missile_firer.combat_pos, &s1, &s2, &s3);
} else if((pc = dynamic_cast<cPlayer*>(victim)) && (spec_item = pc->has_abil_equip(eItemAbil::HIT_CALL_SPECIAL)) < 24) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = pc->combat_pos.x;
PSD[SDF_SPEC_TARGLOC_Y] = pc->combat_pos.y;
PSD[SDF_SPEC_TARGET] = univ.get_target_i(*pc);
univ.party.force_ptr(21, pc->combat_pos.x);
univ.party.force_ptr(22, pc->combat_pos.y);
univ.party.force_ptr(20, univ.get_target_i(*pc));
run_special(eSpecCtx::ATTACKED_RANGE, 0, pc->items[spec_item].abil_data[0], missile_firer.combat_pos, &s1, &s2, &s3);
}
}
@@ -2444,14 +2432,11 @@ void do_monster_turn() {
uAbility abil = cur_monst->abil[eMonstAbil::SPECIAL];
short s1, s2, s3;
special_called = true;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = targ_space.x;
PSD[SDF_SPEC_TARGLOC_Y] = targ_space.y;
univ.party.force_ptr(21, targ_space.x);
univ.party.force_ptr(22, targ_space.y);
if(target < 6)
PSD[SDF_SPEC_TARGET] = 11 + target; // ready to be passed to SELECT_TARGET node
else PSD[SDF_SPEC_TARGET] = target; // ready to be passed to SELECT_TARGET node
univ.party.force_ptr(20, 11 + target); // ready to be passed to SELECT_TARGET node
else univ.party.force_ptr(20, target); // ready to be passed to SELECT_TARGET node
run_special(eSpecCtx::MONST_SPEC_ABIL,0,abil.special.extra1,cur_monst->cur_loc,&s1,&s2,&s3);
take_m_ap(abil.special.extra2,cur_monst);
}
@@ -2899,21 +2884,15 @@ void monster_attack(short who_att,iLiving* target) {
int spec_item;
if(pc_target != nullptr && (spec_item = pc_target->has_abil_equip(eItemAbil::HIT_CALL_SPECIAL)) < 24) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = target->get_loc().x;
PSD[SDF_SPEC_TARGLOC_Y] = target->get_loc().y;
PSD[SDF_SPEC_TARGET] = i_monst;
univ.party.force_ptr(21, target->get_loc().x);
univ.party.force_ptr(22, target->get_loc().y);
univ.party.force_ptr(20, i_monst);
run_special(eSpecCtx::ATTACKED_MELEE, 0, pc_target->items[spec_item].abil_data[0], attacker->cur_loc, &s1, &s2, &s3);
} else if(m_target != nullptr && m_target->abil[eMonstAbil::HIT_TRIGGER].active) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = target->get_loc().x;
PSD[SDF_SPEC_TARGLOC_Y] = target->get_loc().y;
PSD[SDF_SPEC_TARGET] = i_monst;
univ.party.force_ptr(21, target->get_loc().x);
univ.party.force_ptr(22, target->get_loc().y);
univ.party.force_ptr(20, i_monst);
run_special(eSpecCtx::ATTACKED_MELEE, 0, m_target->abil[eMonstAbil::HIT_TRIGGER].special.extra1, attacker->cur_loc, &s1, &s2, &s3);
}
}
@@ -3043,22 +3022,16 @@ void monst_fire_missile(short m_num,short bless,std::pair<eMonstAbil,uAbility> a
if(spec_item < 24) {
short s1,s2,s3;
// TODO: This force_ptr...run_special code is almost duplicated in several places; maybe make a call_attack_spec subroutine!
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = target->get_loc().x;
PSD[SDF_SPEC_TARGLOC_Y] = target->get_loc().y;
PSD[SDF_SPEC_TARGET] = i_monst;
univ.party.force_ptr(21, target->get_loc().x);
univ.party.force_ptr(22, target->get_loc().y);
univ.party.force_ptr(20, i_monst);
run_special(eSpecCtx::ATTACKED_RANGE, 0, pc_target->items[spec_item].abil_data[0], univ.town.monst[m_num].cur_loc, &s1, &s2, &s3);
}
} else if(m_target != nullptr && m_target->abil[eMonstAbil::HIT_TRIGGER].active) {
short s1,s2,s3;
univ.party.force_ptr(21, 301, 5);
univ.party.force_ptr(22, 301, 6);
univ.party.force_ptr(20, 301, 7);
PSD[SDF_SPEC_TARGLOC_X] = m_target->cur_loc.x;
PSD[SDF_SPEC_TARGLOC_Y] = m_target->cur_loc.y;
PSD[SDF_SPEC_TARGET] = i_monst;
univ.party.force_ptr(21, m_target->cur_loc.x);
univ.party.force_ptr(22, m_target->cur_loc.y);
univ.party.force_ptr(20, i_monst);
run_special(eSpecCtx::ATTACKED_RANGE, 0, m_target->abil[eMonstAbil::HIT_TRIGGER].special.extra1, univ.town.monst[m_num].cur_loc, &s1, &s2, &s3);
}
} else if(abil.first == eMonstAbil::MISSILE_WEB) {

View File

@@ -25,14 +25,6 @@
#define NUM_OF_HORSES 30
/* stuff done flags */
#define SDF_SPEC_LOC_X 301][0 // For special nodes to access the trigger location
#define SDF_SPEC_LOC_Y 301][1
#define SDF_SPEC_TER 301][2
#define SDF_SPEC_STRBUF 301][3
#define SDF_SPEC_TRAPLVL 301][4
#define SDF_SPEC_TARGLOC_X 301][5
#define SDF_SPEC_TARGLOC_Y 301][6
#define SDF_SPEC_TARGET 301][7
#define SDF_SKIP_STARTUP 305][4 // preferably deprecated
#define SDF_LESS_SOUND 305][5
#define SDF_NO_TARGET_LINE 305][6

View File

@@ -2002,22 +2002,10 @@ void run_special(eSpecCtx which_mode,short which_type,short start_spec,location
}
// Store the special's location in reserved pointers
univ.party.force_ptr(10, 301, 0);
univ.party.force_ptr(11, 301, 1);
// And put the location there
PSD[SDF_SPEC_LOC_X] = spec_loc.x;
PSD[SDF_SPEC_LOC_Y] = spec_loc.y;
univ.party.force_ptr(10, spec_loc.x);
univ.party.force_ptr(11, spec_loc.y);
// Also store the terrain type on that location
univ.party.force_ptr(12, 301, 2);
PSD[SDF_SPEC_TER] = coord_to_ter(spec_loc.x, spec_loc.y);
// And a reference to the string buffer
univ.party.force_ptr(8, 301, 3);
PSD[SDF_SPEC_STRBUF] = std::find_if(
univ.scenario.spec_strs.begin(),
univ.scenario.spec_strs.end(),
[](std::string& a) {
return &a == &univ.scenario.get_buf();
}) - univ.scenario.spec_strs.begin();
univ.party.force_ptr(12, coord_to_ter(spec_loc.x, spec_loc.y));
while(next_spec >= 0) {
@@ -2399,35 +2387,35 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
story_dialog(str1, spec.m2, spec.m3, cur_spec_type, spec.pic, ePicType(spec.pictype));
break;
case eSpecType::CLEAR_BUF:
univ.scenario.get_buf().clear();
univ.get_buf().clear();
break;
case eSpecType::APPEND_STRING:
get_strs(str1,str1,cur_spec_type,spec.ex1a,-1);
univ.scenario.get_buf() += str1;
univ.get_buf() += str1;
break;
case eSpecType::APPEND_NUM:
univ.scenario.get_buf() += std::to_string(spec.ex1a);
univ.get_buf() += std::to_string(spec.ex1a);
break;
case eSpecType::APPEND_MONST:
if(spec.ex1a == 0) {
int pc = univ.get_target_i(*current_pc_picked_in_spec_enc);
if(pc == 6)
univ.scenario.get_buf() += "Your party";
univ.get_buf() += "Your party";
else if(pc < 100)
univ.scenario.get_buf() += univ.party[pc].name;
univ.get_buf() += univ.party[pc].name;
else if(!is_out())
univ.scenario.get_buf() += univ.town.monst[pc - 100].m_name;
} else univ.scenario.get_buf() += univ.scenario.scen_monsters[spec.ex1a].m_name;
univ.get_buf() += univ.town.monst[pc - 100].m_name;
} else univ.get_buf() += univ.scenario.scen_monsters[spec.ex1a].m_name;
break;
case eSpecType::APPEND_ITEM:
if(spec.ex1b == 1)
univ.scenario.get_buf() += univ.scenario.scen_items[spec.ex1a].full_name;
univ.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;
univ.get_buf() += get_item_interesting_string(univ.scenario.scen_items[spec.ex1a]);
else univ.get_buf() += univ.scenario.scen_items[spec.ex1a].name;
break;
case eSpecType::APPEND_TER:
univ.scenario.get_buf() += univ.scenario.ter_types[spec.ex1a].name;
univ.get_buf() += univ.scenario.ter_types[spec.ex1a].name;
break;
case eSpecType::PAUSE:
if(spec.ex1a < 0) break;
@@ -2659,7 +2647,7 @@ void oneshot_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
bool disarmed = run_trap(j,eTrapType(spec.ex1a),spec.ex1b,spec.ex2a);
if(!disarmed && spec.ex1a == TRAP_CUSTOM) {
if(spec.jumpto >= 0)
queue_special(which_mode, cur_spec_type, spec.jumpto, loc(PSD[SDF_SPEC_LOC_X], PSD[SDF_SPEC_LOC_Y]));
queue_special(which_mode, cur_spec_type, spec.jumpto, loc(univ.party.get_ptr(10), univ.party.get_ptr(11)));
*next_spec = spec.ex2b;
*next_spec_type = 0;
}
@@ -3840,7 +3828,7 @@ void townmode_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
*next_spec = -1;
}
else {
if(handle_lever(loc(PSD[SDF_SPEC_LOC_X], PSD[SDF_SPEC_LOC_Y])))
if(handle_lever(loc(univ.party.get_ptr(10), univ.party.get_ptr(11))))
*next_spec = spec.ex1b;
}
break;
@@ -3929,8 +3917,9 @@ void townmode_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
i = custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons);
if(i == 1) {*next_spec = -1;}
else {
ter = coord_to_ter(PSD[SDF_SPEC_LOC_X], PSD[SDF_SPEC_LOC_Y]);
alter_space(PSD[SDF_SPEC_LOC_X], PSD[SDF_SPEC_LOC_Y],univ.scenario.ter_types[ter].trans_to_what);
int x = univ.party.get_ptr(10), y = univ.party.get_ptr(11);
ter = coord_to_ter(x, y);
alter_space(x,y,univ.scenario.ter_types[ter].trans_to_what);
*next_spec = spec.ex1b;
}
}
@@ -4560,6 +4549,10 @@ void get_strs(std::string& str1,std::string& str2,short cur_type,short which_str
break;
}
if(which_str1 == -8)
str1 = univ.get_buf();
if(which_str2 == -8)
str2 = univ.get_buf();
}
// This function sets/retrieves values to/from campaign flags

View File

@@ -147,8 +147,7 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) {
break;
case TRAP_CUSTOM:
univ.party.force_ptr(5, 301, 4);
PSD[SDF_SPEC_TRAPLVL] = trap_level;
univ.party.force_ptr(15, trap_level);
break;
default:

View File

@@ -36,6 +36,7 @@ cParty::cParty(cUniverse& univ, long party_preset) : univ(univ) {
p_loc.y = 84;
in_boat = -1;
in_horse = -1;
std::fill(magic_ptrs.begin(), magic_ptrs.end(), 0);
for(int i = 0; i < 5; i++)
for(int j = 0; j < 10; j++)
magic_store_items[i][j].variety = eItemType::NO_ITEM;
@@ -529,6 +530,8 @@ void cParty::writeTo(std::ostream& file) const {
file << "SDF " << i << ' ' << j << ' ' << unsigned(stuff_done[i][j]) << '\n';
for(auto iter = pointers.begin(); iter != pointers.end(); iter++)
file << "POINTER " << iter->first << ' ' << iter->second.first << ' ' << iter->second.second << '\n';
for(int i = 0; i < magic_ptrs.size(); i++)
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) {
@@ -731,8 +734,13 @@ void cParty::readFrom(std::istream& file){
}
} else if(cur == "POINTER") {
int i,j,k;
sin >> i >> j >> k;
pointers[i] = std::make_pair(j,k);
sin >> i >> j;
if(i >= 10 && i < 100) {
magic_ptrs[i-10] = j;
} else if(i >= 100 && i < 200) {
sin >> k;
pointers[i] = std::make_pair(j,k);
}
} else if(cur == "STATUS") {
ePartyStatus stat;
int n;
@@ -983,11 +991,17 @@ void cParty::clear_ptr(unsigned short p) {
} else throw std::range_error("Attempted to assign a pointer out of range (100 to 199)");
}
void cParty::force_ptr(unsigned short p, unsigned short sdfx, unsigned short sdfy){
pointers[p] = std::make_pair(sdfx,sdfy);
void cParty::force_ptr(unsigned short p, unsigned short val){
if(p < 10 || p >= 100)
throw std::range_error("Magic pointer out of range (10..99)");
magic_ptrs[p-10] = val;
}
unsigned char cParty::get_ptr(unsigned short p){
if(p < 10 || p >= 200)
throw std::range_error("Attempted to access a nonexistent pointer (10..199)");
if(p < 100)
return magic_ptrs[p-10];
auto iter = pointers.find(p);
if(iter == pointers.end()) return 0;
return stuff_done[iter->second.first][iter->second.second];

View File

@@ -74,6 +74,7 @@ public:
unsigned short gold;
unsigned short food;
unsigned char stuff_done[310][50];
std::array<unsigned char,90> magic_ptrs;
unsigned char item_taken[200][8];
short light_level;
location outdoor_corner;
@@ -129,7 +130,7 @@ private:
public:
void set_ptr(unsigned short p, unsigned short sdfx, unsigned short sdfy);
void force_ptr(unsigned short p, unsigned short sdfx, unsigned short sdfy);
void force_ptr(unsigned short p, unsigned short val);
void clear_ptr(unsigned short p);
unsigned char get_ptr(unsigned short p);

View File

@@ -101,7 +101,6 @@ public:
vector2d<cOutdoors*> outdoors;
std::vector<cTown*> towns;
template<typename Town> void addTown() {towns.push_back(new Town(*this, true));}
std::string& get_buf() {return spec_strs[100];}
void append(legacy::scenario_data_type& old);
void append(legacy::scen_item_data_type& old);

View File

@@ -157,6 +157,7 @@ class cUniverse{
pic_num_t addGraphic(pic_num_t pic, ePicType type);
void check_monst(cMonster& monst);
void check_item(cItem& item);
std::string strbuf;
public:
void exportSummons();
void exportGraphics();
@@ -164,7 +165,8 @@ public:
iLiving& get_target(size_t which);
iLiving* target_there(location pos, eTargetType type = TARG_ANY);
size_t get_target_i(iLiving& who);
std::string get_buf() {return strbuf;}
cScenario scenario;
cParty party;
std::map<long,cPlayer*> stored_pcs;