Implement editing dialogs for individual monster abilities

Changes to game:
- Permanent martyr's shield is now customizable - extra1 is per-mille chance to activate each time damage is taken, and extra2 is percent of damage taken to apply to attacker
- Absort spells is now customizable - extra1 is per-mille chance to activate each time damage is taken or a magic effect is applied, and extra2 is how much hp to gain from non-damaging magic effects
- Splits ability is now customizable - extra1 is per-mille chance of splitting each time damage is taken
- Special node ability is now called before the monster tries its normal attack, and multiple monsters can use them per round (though each can only use theirs once)
- Fix issue with breath weapons and icy touch abilities conflicting (legacy import issue)
- Add two variations of the summoning ability - summon according to summoning level (like the spells), or summon a random creature of a particular species
- Fix touch abilities using the range as chance to use

Changes to dialog engine:
- Fix tab order handling to exclude fields that are currently hidden
- Add method to retrieve the parameter passed to toast(), as a quick way to distinguish between the user clicking OK or Cancel after run() has exited
- Fix hidden fields being drawn anyway
- Fix setting stack page sometimes crashing if the current page was invalid due to earlier reducing the page count to 0
This commit is contained in:
2015-01-19 12:01:28 -05:00
parent d614286fec
commit 5450ae1caf
23 changed files with 936 additions and 245 deletions

View File

@@ -1016,8 +1016,13 @@ void cDialog::run(){
dialogNotToast = true;
// Focus the first text field, if there is one
if(!tabOrder.empty()) {
tabOrder[0].second->triggerFocusHandler(*this, tabOrder[0].first, false);
currentFocus = tabOrder[0].first;
auto iter = std::find_if(tabOrder.begin(), tabOrder.end(), [](std::pair<std::string,cTextField*> ctrl){
return ctrl.second->isVisible();
});
if(iter != tabOrder.end()) {
iter->second->triggerFocusHandler(*this, tabOrder[0].first, false);
currentFocus = iter->first;
}
}
// Sometimes it seems like the Cocoa menu handling clobbers the active rendering context.
// For whatever reason, delaying 100 milliseconds appears to fix this.
@@ -1197,7 +1202,7 @@ template<typename Iter> void cDialog::handleTabOrder(string& itemHit, Iter begin
while(iter != cur){
// If tab order is explicitly specified for all fields, gaps are possible
if(iter->second == nullptr) continue;
if(iter->second->getType() == CTRL_FIELD){
if(iter->second->getType() == CTRL_FIELD && iter->second->isVisible()){
if(iter->second->triggerFocusHandler(*this,iter->first,false)){
currentFocus = iter->first;
}
@@ -1235,6 +1240,7 @@ bool cDialog::toast(bool triggerFocus){
if(!this->getControl(currentFocus).triggerFocusHandler(*this, currentFocus, true)) return false;
}
dialogNotToast = false;
didAccept = triggerFocus;
return true;
}
@@ -1242,6 +1248,10 @@ void cDialog::untoast() {
dialogNotToast = true;
}
bool cDialog::accepted() {
return didAccept;
}
bool cDialog::setFocus(cTextField* newFocus, bool force) {
// TODO: Should check that there IS a currently focused field (which might not be the case if there are no fields at all).
if(!force) {

View File

@@ -150,6 +150,9 @@ public:
/// This is meant to be called from within an event handler to reverse a previous call to toast();
/// if you're already out of the dialog's event loop, you should instead call run() to reopen it.
void untoast();
/// Determine how the dialog exited.
/// @return the argument passed to toast() when the dialog was closed
bool accepted();
/// Get a reference to a control.
/// @param id The unique key of the control.
/// @throw std::invalid_argument if the control does not exist.
@@ -190,7 +193,7 @@ private:
void draw();
std::string process_keystroke(cKey keyHit);
std::string process_click(location where);
bool dialogNotToast;
bool dialogNotToast, didAccept;
rectangle winRect;
std::string defaultButton;
boost::any result;

View File

@@ -175,6 +175,7 @@ cTextField::cTextField(cDialog* parent) :
cTextField::~cTextField(){}
void cTextField::draw(){
if(!visible) return;
static const sf::Color hiliteClr = {127,127,127}, ipClr = {92, 92, 92};
inWindow->setActive();
rectangle outline = frame;

View File

@@ -98,6 +98,7 @@ size_t cStack::getPage() {
void cStack::setPageCount(size_t n) {
if(curPage >= n && n > 0)
setPage(nPages - 1);
if(n == 0) curPage = 0;
nPages = n;
storage.resize(nPages);
}