Changes to split party implementation
- Supports playing arbitrary sound along with the split (rather than just teleport sound or no sound) - Correctly imported from older save files - Support for splitting off an arbitrary subgroup of the party rather than just a single PC (though the special node doesn't yet allow this) - Support for leaving town while split - if you leave town, the absent PC's items are not dropped on the ground when later entering a town - Option to not change location when reuniting - If you reunite in a different town than you started, you are returned to the town you split from
This commit is contained in:
@@ -896,7 +896,12 @@ static void handle_party_death() {for(int i = 0; i < 6; i++)
|
||||
}
|
||||
}
|
||||
if(univ.party.is_split()) {
|
||||
ASB(univ.party.end_split(0));
|
||||
univ.party.end_split(0);
|
||||
if(univ.party.left_in == size_t(-1) || univ.town.num == univ.party.left_in) {
|
||||
univ.town.p_loc = univ.party.left_at;
|
||||
update_explored(univ.town.p_loc);
|
||||
center = univ.town.p_loc;
|
||||
} else change_level(univ.party.left_in, univ.party.left_at.x, univ.party.left_at.y);
|
||||
update_explored(univ.town.p_loc);
|
||||
center = univ.town.p_loc;
|
||||
if(is_combat()) overall_mode = MODE_TOWN;
|
||||
|
@@ -25,11 +25,6 @@
|
||||
/* 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_IS_PARTY_SPLIT 304][0
|
||||
//#define SDF_PARTY_SPLIT_X 304][1
|
||||
//#define SDF_PARTY_SPLIT_Y 304][2
|
||||
//#define SDF_PARTY_SPLIT_PC 304][3
|
||||
//#define SDF_PARTY_SPLIT_TOWN 304][4 // for future use, hopefully
|
||||
#define SDF_SKIP_STARTUP 305][4 // preferably deprecated
|
||||
#define SDF_LESS_SOUND 305][5
|
||||
#define SDF_NO_TARGET_LINE 305][6
|
||||
|
@@ -3713,7 +3713,8 @@ void townmode_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
|
||||
if(r1 != 6) {
|
||||
current_pc = r1;
|
||||
*next_spec = -1;
|
||||
ASB(univ.party.start_split(spec.ex1a,spec.ex1b,spec.ex2a,r1));
|
||||
if(!univ.party.start_split(spec.ex1a,spec.ex1b,spec.ex2a,r1))
|
||||
ASB("Party already split!");
|
||||
update_explored(univ.town.p_loc);
|
||||
center = univ.town.p_loc;
|
||||
}
|
||||
@@ -3728,9 +3729,15 @@ void townmode_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
|
||||
*a = 1;
|
||||
*next_spec = -1;
|
||||
check_mess = false;
|
||||
ASB(univ.party.end_split(spec.ex1a));
|
||||
update_explored(univ.town.p_loc);
|
||||
center = univ.town.p_loc;
|
||||
if(univ.party.end_split(spec.ex1a))
|
||||
ASB("Party already together!");
|
||||
else ASB("You are reunited.");
|
||||
if(spec.ex2a); // This means reunite the party by bringing the others to the current location rather than the reverse.
|
||||
else if(univ.party.left_in == size_t(-1) || univ.town.num == univ.party.left_in) {
|
||||
univ.town.p_loc = univ.party.left_at;
|
||||
update_explored(univ.town.p_loc);
|
||||
center = univ.town.p_loc;
|
||||
} else change_level(univ.party.left_in, univ.party.left_at.x, univ.party.left_at.y);
|
||||
break;
|
||||
case eSpecType::TOWN_TIMER_START:
|
||||
univ.party.start_timer(spec.ex1a, spec.ex1b, 1);
|
||||
|
@@ -481,12 +481,15 @@ void start_town_mode(short which_town, short entry_dir) {
|
||||
update_explored(univ.town.p_loc);
|
||||
|
||||
// If a PC dead, drop his items
|
||||
for(m = 0; m < 6; m++)
|
||||
for(m = 0; m < 6; m++) {
|
||||
if(univ.party[m].main_status == eMainStatus::ALIVE || isSplit(univ.party[m].main_status))
|
||||
continue;
|
||||
for(n = 0; n < 24; n++)
|
||||
if(univ.party[m].main_status != eMainStatus::ALIVE && univ.party[m].items[n].variety != eItemType::NO_ITEM) {
|
||||
if(univ.party[m].items[n].variety != eItemType::NO_ITEM) {
|
||||
place_item(univ.party[m].items[n],univ.town.p_loc,true);
|
||||
univ.party[m].items[n].variety = eItemType::NO_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < univ.town->max_monst(); i++) {
|
||||
univ.town.monst[i].targ_loc.x = 0;
|
||||
|
@@ -70,6 +70,10 @@ void cParty::append(legacy::party_record_type& old){
|
||||
p_loc.y = old.p_loc.y;
|
||||
loc_in_sec.x = old.loc_in_sec.x;
|
||||
loc_in_sec.y = old.loc_in_sec.y;
|
||||
if(stuff_done[304][0]) {
|
||||
left_at = loc(stuff_done[304][1], stuff_done[304][2]);
|
||||
left_in = -1;
|
||||
}
|
||||
party_event_timers.reserve(30);
|
||||
for(i = 0; i < 30; i++){
|
||||
boats[i].append(old.boats[i]);
|
||||
@@ -283,6 +287,10 @@ void cParty::writeTo(std::ostream& file) const {
|
||||
if(kv.second > 0)
|
||||
file << "STATUS " << kv.first << ' ' << kv.second << '\n';
|
||||
}
|
||||
if(is_split()) {
|
||||
file << "SPLIT_LEFT_IN " << left_in << '\n';
|
||||
file << "SPLIT_LEFT_AT " << left_at.x << ' ' << left_at.y << '\n';
|
||||
}
|
||||
for(int i = 0; i < 256; i++)
|
||||
if(m_noted[i])
|
||||
file << "ROSTER " << i << '\n';
|
||||
@@ -477,6 +485,10 @@ void cParty::readFrom(std::istream& file){
|
||||
sin >> p_loc.x >> p_loc.y;
|
||||
else if(cur == "LOCINSECTOR")
|
||||
sin >> loc_in_sec.x >> loc_in_sec.y;
|
||||
else if(cur == "SPLIT_LEFT_IN")
|
||||
sin >> left_in;
|
||||
else if(cur == "SPLIT_LEFT_AT")
|
||||
sin >> left_at.x >> left_at.y;
|
||||
else if(cur == "IN")
|
||||
sin >> in_boat >> in_horse;
|
||||
else if(cur == "ROSTER"){
|
||||
@@ -685,72 +697,57 @@ unsigned char& cParty::cpn_flag(unsigned int x, unsigned int y, std::string id)
|
||||
return campaign_flags[id].idx[x][y];
|
||||
}
|
||||
|
||||
bool cParty::is_split(){
|
||||
bool cParty::is_split() const {
|
||||
bool ret = false;
|
||||
for(int i = 0; i < 6; i++)
|
||||
if(!stuff_done[304][i])
|
||||
if(!pc_present(i))
|
||||
ret = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool cParty::pc_present(short i){
|
||||
bool cParty::pc_present(short i) const {
|
||||
if(i >= 6 || i < 0) return false;
|
||||
return stuff_done[304][i];
|
||||
return !isSplit(univ.party[i].main_status);
|
||||
}
|
||||
|
||||
location cParty::left_at(){
|
||||
return loc(stuff_done[304][6],stuff_done[304][7]);
|
||||
}
|
||||
|
||||
size_t cParty::left_in(){
|
||||
return stuff_done[304][8];
|
||||
}
|
||||
extern cUniverse univ;
|
||||
std::string cParty::start_split(short a,short b,snd_num_t noise,short who) {
|
||||
bool cParty::start_split(short x,short y,snd_num_t noise,short who) {
|
||||
short i;
|
||||
|
||||
if(who >= 6 || who < 0) return "";
|
||||
if(who >= 6 || who < 0) return false;
|
||||
if(is_split())
|
||||
return "Party already split!";
|
||||
stuff_done[304][who] = 0;
|
||||
stuff_done[304][6] = univ.town.p_loc.x;
|
||||
stuff_done[304][7] = univ.town.p_loc.y;
|
||||
stuff_done[304][8] = univ.town.num;
|
||||
univ.town.p_loc.x = a;
|
||||
univ.town.p_loc.y = b;
|
||||
// TODO: This looks like it won't work.
|
||||
return false;
|
||||
// TODO: Allow splitting an arbitrary subgroup of the party
|
||||
left_at = univ.town.p_loc;
|
||||
left_in = univ.town.num;
|
||||
univ.town.p_loc.x = x;
|
||||
univ.town.p_loc.y = y;
|
||||
for(i = 0; i < 6; i++)
|
||||
if(!stuff_done[304][who])
|
||||
if(i != who)
|
||||
adven[i].main_status += eMainStatus::SPLIT;
|
||||
// TODO: Uh, why play sound 10 instead of the one passed in?
|
||||
if(noise > 0)
|
||||
play_sound(10);
|
||||
return "";
|
||||
play_sound(noise);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string cParty::end_split(snd_num_t noise) {
|
||||
bool cParty::end_split(snd_num_t noise) {
|
||||
short i;
|
||||
|
||||
if(!is_split())
|
||||
return "Party already together!";
|
||||
univ.town.p_loc = left_at();
|
||||
univ.town.num = left_in();
|
||||
return false;
|
||||
for(i = 0; i < 6; i++){
|
||||
if(isSplit(univ.party[i].main_status))
|
||||
univ.party[i].main_status -= eMainStatus::SPLIT;
|
||||
stuff_done[304][i] = true;
|
||||
}
|
||||
if(noise > 0)
|
||||
play_sound(10);
|
||||
return "You are reunited.";
|
||||
play_sound(noise);
|
||||
return true;
|
||||
}
|
||||
|
||||
short cParty::pc_present(){
|
||||
short cParty::pc_present() const {
|
||||
short ret = 7;
|
||||
for(int i = 0; i < 6; i++){
|
||||
if(stuff_done[304][i] && ret == 7)
|
||||
if(pc_present(i) && ret == 7)
|
||||
ret = i;
|
||||
else if(stuff_done[304][i] && ret < 6)
|
||||
else if(pc_present(i) && ret < 6)
|
||||
ret = 6;
|
||||
}
|
||||
if(ret == 7) ret = 6;
|
||||
|
@@ -91,6 +91,8 @@ public:
|
||||
std::vector<cEncNote> special_notes;
|
||||
std::vector<cConvers> talk_save;
|
||||
std::map<ePartyStatus,short> status;
|
||||
location left_at;
|
||||
size_t left_in;
|
||||
short direction;
|
||||
short at_which_save_slot;
|
||||
char alchemy[20];
|
||||
@@ -142,13 +144,11 @@ public:
|
||||
void writeTo(std::ostream& file) const;
|
||||
void readFrom(std::istream& file);
|
||||
|
||||
std::string start_split(short a, short b, snd_num_t noise, short who);
|
||||
std::string end_split(snd_num_t noise);
|
||||
bool is_split();
|
||||
bool pc_present(short n);
|
||||
short pc_present(); // If only one pc is present, returns the number of that pc. Otherwise returns 6.
|
||||
location left_at(); // The location that the left-behind character in a split were left at.
|
||||
size_t left_in(); // The town they were left in.
|
||||
bool start_split(short x, short y, snd_num_t noise, short who);
|
||||
bool end_split(snd_num_t noise);
|
||||
bool is_split() const;
|
||||
bool pc_present(short n) const;
|
||||
short pc_present() const; // If only one pc is present, returns the number of that pc. Otherwise returns 6.
|
||||
|
||||
typedef std::vector<cEncNote>::iterator encIter;
|
||||
typedef std::vector<cJournal>::iterator journalIter;
|
||||
|
@@ -178,6 +178,13 @@ void cSpecial::append(legacy::special_node_type& old){
|
||||
type = eSpecType::IF_EQUIP_ITEM_CLASS;
|
||||
ex2a = (old.type - 131) / 5;
|
||||
break;
|
||||
case 193: // Split party
|
||||
if(ex2a > 0) ex2a = 10;
|
||||
break;
|
||||
case 194: // Reunite party
|
||||
if(ex1a > 0) ex1a = 10;
|
||||
ex2a = 0;
|
||||
break;
|
||||
// Place fields (twelve individual node types were collapsed into one)
|
||||
case 200:
|
||||
type = eSpecType::RECT_PLACE_FIELD;
|
||||
|
@@ -43,7 +43,7 @@ class cCurTown {
|
||||
public:
|
||||
bool quickfire_present = false, belt_present = false;
|
||||
// formerly current_town_type
|
||||
short num; // 200 if outdoors (my addition)
|
||||
size_t num; // 200 if outdoors (my addition)
|
||||
short difficulty;
|
||||
bool hostile;
|
||||
cPopulation monst;
|
||||
|
Reference in New Issue
Block a user