townperson picker for town attitude range

This commit is contained in:
2025-08-27 16:02:34 -05:00
parent 4a16ab4f7b
commit bb732b7784
6 changed files with 54 additions and 7 deletions

View File

@@ -6,8 +6,8 @@ Second part of message
Unused
Unused
Unused
First monster to affect (negative counts back from last)
Last monster to affect (negative counts back from last)
First monster
Last monster
Unused
New Attitude
Unused

View File

@@ -938,6 +938,7 @@ bool cDialog::addLabelFor(std::string key, std::string label, eLabelPos where, s
key += "-label";
rectangle labelRect = ctrl.getBounds();
// TODO I think these are completely wrong? But am afraid of changing it having unintended impacts.
// offset for labels on right side is absolutely not working right.
switch(where) {
case LABEL_LEFT:
labelRect.right = labelRect.left;

View File

@@ -93,19 +93,19 @@ void cPictChoice::fillPage(){
cLedGroup& group = dynamic_cast<cLedGroup&>(dlg["group"]);
group.setSelected(""); // unselect all LEDs, since the currently selected one may be on another page
for(size_t i = 0; i < per_page; i++){
int idx = page * per_page + i;
std::ostringstream sout;
sout << "led" << i + 1;
if(page * per_page + i >= picts.size())
if(idx >= picts.size() || picts[idx].first < 0)
dlg[sout.str()].hide();
else
dlg[sout.str()].show();
if(page * per_page + i == cur)
if(idx == cur)
group.setSelected(sout.str());
clear_sstr(sout);
sout << "pic" << i + 1;
cPict& pic = dynamic_cast<cPict&>(dlg[sout.str()]);
int idx = page * per_page + i;
if(idx < picts.size()){
if(idx < picts.size() && picts[idx].first >= 0){
pic.show();
if(labels.size() > idx){
// TODO clicking on the label text will not trigger the led/pict's click handler

View File

@@ -14,6 +14,8 @@ node_category_info_t CAT_TOWN{eSpecType::MAKE_TOWN_HOSTILE, eSpecType::TOWN_PLAC
namespace {
node_properties_t S_ATTITUDE = node_builder_t(eSpecType::MAKE_TOWN_HOSTILE)
.msg()
.ex1a(eSpecPicker::TOWNPERSON)
.ex1b(eSpecPicker::TOWNPERSON)
.ex2a(STRT_ATTITUDE);
node_properties_t S_MISSILE = node_builder_t(eSpecType::TOWN_RUN_MISSILE)
.msg()

View File

@@ -187,7 +187,7 @@ enum class eSpecPicker {
STATUS, STATUS_PARTY,
SDF, LOCATION, RECTANGLE, TOGGLE,
EVENT, ITEM_CLASS, QUEST, JOB_BOARD,
POINTER, SPELL_PATTERN,
POINTER, SPELL_PATTERN, TOWNPERSON
};
enum class eLocType {

View File

@@ -794,6 +794,13 @@ static void setup_node_field(cDialog& me, std::string field, short value, const
me[toggle].show();
dynamic_cast<cLed&>(me[toggle]).setState(value > 0 ? eLedState::led_red : eLedState::led_off);
break;
case eSpecPicker::TOWNPERSON:
me[button].hide();
me[toggle].show();
dynamic_cast<cLed&>(me[toggle]).setState(value < 0 ? eLedState::led_red : eLedState::led_off);
me[toggle].setText("Relative to end");
me[button2].show();
break;
default:
me[button].show();
me[button2].hide();
@@ -1563,6 +1570,43 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
case eSpecPicker::ITEM_CLASS: store = choose_text_editable(scenario.ic_names, val, &me, "Select item class:"); break;
case eSpecPicker::JOB_BOARD: store = choose_text_editable(scenario.qb_names, val, &me, "Select a job board:"); break;
case eSpecPicker::POINTER: store = val; break; // TODO: Not implemented...
case eSpecPicker::TOWNPERSON:
if(town->creatures.empty()){
showWarning("There are no creatures in this town to change attitude!");
break;
}
if(alt_button){
std::vector<pic_num_t> pics;
std::vector<std::string> labels;
for(size_t i = 0; i < town->creatures.size(); ++i){
const cTownperson& person = town->creatures[i];
if(person.number <= 0) {
pics.push_back(-1);
labels.push_back("");
}else{
const cMonster& monst = scenario.scen_monsters[person.number];
pics.push_back(monst.picture_num);
labels.push_back(fmt::format("{} at {}", monst.m_name, boost::lexical_cast<std::string>(person.start_loc)));
}
}
size_t sel = val < 0 ? town->creatures.size() + val : val;
cPictChoice choice(pics, labels, PIC_MONST, &me);
choice.show(sel);
size_t new_sel = choice.getSelected();
if(val < 0){
store = -(town->creatures.size() - new_sel);
}else{
store = new_sel;
}
}
// The townperson picker toggle changes whether the field counts up from 0 or down from the end of the list
else{
// TODO: We should also add a focus handler so that manually changing the field value updates the toggle...
if(val < 0) store = town->creatures.size() + val;
else store = -(town->creatures.size() - val);
dynamic_cast<cLed&>(me[item_hit]).setState(store < 0 ? eLedState::led_red : eLedState::led_off);
}
break;
case eSpecPicker::NONE: return false;
}
me[field].setTextToNum(store);