townperson picker for town attitude range

This commit is contained in:
2025-08-27 16:02:34 -05:00
parent 456c05d4ff
commit 1f7fc8854a
5 changed files with 52 additions and 5 deletions

View File

@@ -936,6 +936,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);