Jump to content

Code Discussion Thread


Celtic Minstrel

Recommended Posts

Originally Posted By: Celtic Minstrel
...Okay, this is odd. Apparently when I initialize an istringstream, an unrelated variable from an outer scope gets set to a seemingly random value.

I'm not familiar with the whole istringstream class but that sounds like a memory overflow ... How do you initialize your stream ?

Chokboyz
Link to comment
Share on other sites

  • Replies 990
  • Created
  • Last Reply

Top Posters In This Topic

Hey, here's a big fat bug... When you buy spells in Classic Blades Beta 1, they only go to the first PC in the party. All the other PCs don't get the spells. Things should not work this way; you should at least get a PC selection dialog, and the documentation IIRC says that buying a spell should give it to all PCs.

Link to comment
Share on other sites

Buying a spell only goes to the selected PC. To buy a spell for a particular PC, you need to select them in the list in the upper-right, so their name is blue and italicized. This is how it has always worked. You may notice that it says on top of the shop dialogue, "Buying spells for (PC name)".

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
...Okay, this is odd. Apparently when I initialize an istringstream, an unrelated variable from an outer scope gets set to a seemingly random value.

I'm not familiar with the whole istringstream class but that sounds like a memory overflow ... How do you initialize your stream ?
...It's part of the standard library, and initialized with a string. It shouldn't be affecting some other variable.


Another thing that's strange is that when debugging, I sometimes see two copies of the same variable...
Link to comment
Share on other sites

I don't know if this is still being used as a suggestion list or just code discussion, but I have a few suggestions;

 

1. It'd be nice if it were possible to have a special called on an attempt to talk or look at a creature. The talk node would be useful in that it could call up a small dialogue message (similar to the no-talkers in Exile 3) or could even call up a large dialogue message, if it made more sense than a full talking screen.

 

2. The way the monsters and items lists are organized doesn't make a whole lot of sense. If it were possible to drag and drop these up and down the list would be cool. That way, if we needed to reorganize, we wouldn't have to redo the monster/item completely.

 

3. I think a way of remembering coordinates in one town while off in another (or outdoors) would be incredibly useful. For instance, imagine a dungeon where there's two almost identical versions, but you need to use a special item to switch between the two.

 

4. A pre-fab generator in-scenario would be pretty nice. What I mean is, a player could take their generic party into the scenario, and the author would have already set up the specifications of the party required to play, and a node would transform the generic party into the pre-fab.

 

5. I might be the only one, but I'd like a toggle that allows/disallows XP gain from kills in certain towns. I think that'd be swell.

 

6. Is there any way of modifying the training screen so that scenario authors can change what skills a trainer allows you to increase, and the costs? Otherwise, we have to increase skills with special nodes, and that's not fun.

 

I'll see what else I can think of later.

Link to comment
Share on other sites

For the record, this thread is primarily being used for code discussion, but you can put feature requests and bug reports here too. Another place for such things is the Google Code issues page.

 

Originally Posted By: Arachnid

1. It'd be nice if it were possible to have a special called on an attempt to talk or look at a creature. The talk node would be useful in that it could call up a small dialogue message (similar to the no-talkers in Exile 3) or could even call up a large dialogue message, if it made more sense than a full talking screen.

This feature is planned. Wait, no, that was a plan to have a special node called when talking to a terrain space. But it's a good idea anyway, so I'll try to implement it.

 

Originally Posted By: Arachnid

2. The way the monsters and items lists are organized doesn't make a whole lot of sense. If it were possible to drag and drop these up and down the list would be cool. That way, if we needed to reorganize, we wouldn't have to redo the monster/item completely.

You mean a way to easily rearrange the item and monster lists? I plan to do something there. It may be simply a swap feature, letting you swap two things in the list; drag and drop is kind of hard to do. I also intend to add something to remove the need to reorganize the items list to satisfy a shop that you want to have, but I haven't quite decided how to do this.

 

Originally Posted By: Arachnid

3. I think a way of remembering coordinates in one town while off in another (or outdoors) would be incredibly useful. For instance, imagine a dungeon where there's two almost identical versions, but you need to use a special item to switch between the two.

Hmmm... I think that could be done with the planned "location specials" feature. Basically, special nodes will be able to access the coordinates of the space they were triggered on. So, if you wanted to make such a special item, you would switch towns but use the same coordinates.

 

I also intend to make it possible to leave town while the party is split up without losing all your stuff.

 

Originally Posted By: Arachnid

4. A pre-fab generator in-scenario would be pretty nice. What I mean is, a player could take their generic party into the scenario, and the author would have already set up the specifications of the party required to play, and a node would transform the generic party into the pre-fab.

Frankly, I don't like that idea. If the player has a party that they really like, and they take it into your scenario, it will essentially be destroyed. I think it's better to just use the character editor to create the prefab party and distribute it with the scenario. You won't have to worry about Mac/Windows differences anymore – both platforms will use the same save format.

 

Still, what you suggest will be possible, I think, using a special node called when the scenario starts.

 

Originally Posted By: Arachnid

5. I might be the only one, but I'd like a toggle that allows/disallows XP gain from kills in certain towns. I think that'd be swell.

Hmm, this is an interesting idea. It could probably be implemented. I'll look into it at some point.

 

Originally Posted By: Arachnid

6. Is there any way of modifying the training screen so that scenario authors can change what skills a trainer allows you to increase, and the costs? Otherwise, we have to increase skills with special nodes, and that's not fun.

I haven't looked into the training much, but I think that'd be possible. In fact, I quite like the idea.

 

By the way, do you use Mac or Windows? I think we need some Mac testers...

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Frankly, I don't like that idea. If the player has a party that they really like, and they take it into your scenario, it will essentially be destroyed. I think it's better to just use the character editor to create the prefab party and distribute it with the scenario. You won't have to worry about Mac/Windows differences anymore – both platforms will use the same save format.

Still, what you suggest will be possible, I think, using a special node called when the scenario starts.


If you don't keep a saved game from before entering a scenario, it's kind of your own fault if the scenario turns out to ruin your party -- especially if it does it right at the start of the scenario and you save over it anyway.

There are other reasons you might not want to do this (for example, it makes it harder to bring in a god-party for testing purposes), but the risk of losing your party isn't a particularly compelling one.
Link to comment
Share on other sites

Even so, I thought there were scenarios that already do that. If the means to do it is already available, I don't consider it a high priority. The only thing I might add to facilitate it (as well as introductory cutscenes) is the ability to call a special node when the scenario starts (just after displaying the intro message, if any).

Link to comment
Share on other sites

Quote:
Another thing that's strange is that when debugging, I sometimes see two copies of the same variable...

There are a couple of ways that this could happen. One is that you're misinterpreting what the debugger reports because it is showing you two variables in different scopes which have the same name, for instance if there are two for loops in the function, each with its own counter variable, which happen to be named identically.

The other way is that you are debugging code which has been compiled with a non-zero optimization level, in which case the compiler may have used unintuitive tricks to make the code more efficient.
Link to comment
Share on other sites

Some progress log :

 

I've made various corrections to the Scenario Editor info text (switched teleport/electricity SFX value, Cleanse Rectangle sd1, etc) and changed the force place monster function to preferably flush a summoned monster in case flushing a monster is needed.

 

I'm actually on two things that i need the community opinion on :

 

Quote:
Depending on the ability strength of a missile with the exploding ability, it will do different damage types. This is very strange.

True. Trivial, but does that need fixing ? What to make the default behavior ?

Edit : Seems like the problem is that the default value for the exploding arrow is 25 in the bladbase.exs. When the ability strength is between 0 and 10, the damage is fire type. So only the bladbase would need to be fixed.

 

Quote:
To enhance a steel wave blade with the flaming weapon ability, it will cost 10000 gold, but with the steel halberd (Which is worth a lot more) itonly costs 1500 gold!

Worst then that, the val_to_place variable being signed, the game display -25xxx as a price and effectively give the player 25xxx gold for having the halberd enchanted.

The maximum money is 30000, so unsigning the variable may suffice, but a maximum price to pay (i.e if greater than X, then X is the price) is another option. (given that the item value is used in the calculation formula, having a max price is a good idea nonetheless, for magic halberg value is 4000 ...).

 

Chokboyz

Link to comment
Share on other sites

I think I've already unsigned the gold variable. I'm not sure about having a maximum price though. Would it be a major problem to simply redo the calculation of enchantment costs so that it never exceeds the maximum price?

 

We could double the maximum gold (30000 -> 60000) if it helps.

 

 

As for Exploding Missile, I think it should be fire damage. The idea of Exploding missile is, I think, that it creates a fireball at its target. (Or, we could allow the designer to specify the type of damage using an extra field.)

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I think I've already unsigned the gold variable. I'm not sure about having a maximum price though. Would it be a major problem to simply redo the calculation of enchantment costs so that it never exceeds the maximum price?


This would be a major game balance change, although admittedly enchantment costs were pretty ridiculous to begin with.
Link to comment
Share on other sites

Would it really be major? It would be a game balance change, certainly, but would it really be a major change? It would make more sense than maxing out at, say, 50000 gold or whatever. My impression is that enchantments are not really a significant factor; were they commonly used? Were enchantment costs ever taken into account when designing scenarios? Stuff like that...

Link to comment
Share on other sites

They weren't commonly used in scenarios, and scenario designers probably didn't make much of an effort to balance costs, but enchantments were certainly popular among players. The Flaming Weapon enchantment in particular adds about 10-15 points of unblockable damage to each hit (in the Mac version, at least; I think it might be fire damage in the Windows version, but I'm not sure).

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
As for Exploding Missile, I think it should be fire damage. The idea of Exploding missile is, I think, that it creates a fireball at its target. (Or, we could allow the designer to specify the type of damage using an extra field.)

Yup, so i'm fixing the bladbase file (i'd put a 5 ability strength).

Originally Posted By: Celtic Minstrel
I think I've already unsigned the gold variable.

So do I. The signed variable used in the calculation is a local one.

Originally Posted By: Celtic Minstrel
I'm not sure about having a maximum price though.[...]

We could double the maximum gold (30000 -> 60000) if it helps.

Simplyfing a little, the enchantment cost is 20 times the weapon value. So enchanting a Magic Halberd (value 4000) is already costing 80000 (which is too much for an unsigned short) and value goes from 0 to 10000 ...
So, either we have a maximum price (let's say 30000, the maximum gold the party can have) or we prevent the player from enchanting some weapons.

Originally Posted By: Celtic Minstrel
Would it be a major problem to simply redo the calculation of enchantment costs so that it never exceeds the maximum price?

Originally Posted By: Thuryl
This would be a major game balance change, although admittedly enchantment costs were pretty ridiculous to begin with.


Yeah, that would be quite a change ... That would bypass the previous maximum price problem, though.
What would the new prices be, i've no idea ...

Originally Posted By: Thuryl
The Flaming Weapon enchantment in particular adds about 10-15 points of unblockable damage to each hit (in the Mac version, at least; I think it might be fire damage in the Windows version, but I'm not sure)

I'm pretty sure it's unblockable in the Windows version too.

Chokboyz
Link to comment
Share on other sites

Increasing the maximum amount of gold the party can have sounds like 'American Economics 101'.

Alcritas used a simple method by creating a Special Item; a coin worth 'x' amount of gold. As the party acquired more gold, they 'bought' these coins in a Bank, thus being able to carry more than the maximum amount the Editor allows.

This would work with any other object, too; Gemstones, Objet d'arte, Antiques, etc.

It seems to me the ability to bypass the parameters of the Editor is a function of the Author, not re-programming.

me

Link to comment
Share on other sites

Originally Posted By: Ahbleza
It seems to me the ability to bypass the parameters of the Editor is a function of the Author, not re-programming.

True, but that doesn't solve the augment weapon problem : for the program the only gold available is the one right under the party screen.
I agree with you though, the amount of gold party can carry seems right at 30000.

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Yup, so i'm fixing the bladbase file (i'd put a 5 ability strength).
Hmm, will this have the same effect apart from damage type? In particular, would it differ from Exile 3?

Originally Posted By: Chokboyz
Simplyfing a little, the enchantment cost is 20 times the weapon value. So enchanting a Magic Halberd (value 4000) is already costing 80000 (which is too much for an unsigned short) and value goes from 0 to 10000 ...
So, either we have a maximum price (let's say 30000, the maximum gold the party can have) or we prevent the player from enchanting some weapons.
Isn't the player already prevented from enchanting magic weapons?

If we have a maximum enchantment price, I don't think it should be equal to the maximum gold the party can carry.

Originally Posted By: Chokboyz
Yeah, that would be quite a change ... That would bypass the previous maximum price problem, though.
What would the new prices be, i've no idea ...
Multiply by 10 instead of 20, maybe? That would put your Magic Halberd at 40000, more than currently possible to carry but still within the bounds of an unsigned short. Of course, a weapons with a value of 10000 would still have a problem. In fact, any weapon with a value over about 6000 would have a problem. So we could multiply by 5 instead.

Or we could come up with something different such that the enchantment cost increases non-linearly with the weapon value.

Originally Posted By: Chokboyz
Originally Posted By: Thuryl
The Flaming Weapon enchantment in particular adds about 10-15 points of unblockable damage to each hit (in the Mac version, at least; I think it might be fire damage in the Windows version, but I'm not sure)

I'm pretty sure it's unblockable in the Windows version too.
That should be changed, maybe?

Originally Posted By: Ahbleza
It seems to me the ability to bypass the parameters of the Editor is a function of the Author, not re-programming.
me
This seems perilously close to saying that there's no point in adding any features to the game...
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Hmm, will this have the same effect apart from damage type? In particular, would it differ from Exile 3?

No, it will behaves like in Exile 3, minus the two fireball shots (there's only one). The damages may be higher, though (if i remember correctly, the exploding arrows were pretty weak in Exile 3).

Originally Posted By: Celtic Minstrel
Multiply by 10 instead of 20, maybe? That would put your Magic Halberd at 40000, more than currently possible to carry but still within the bounds of an unsigned short. Of course, a weapons with a value of 10000 would still have a problem. In fact, any weapon with a value over about 6000 would have a problem. So we could multiply by 5 instead.

That would involve modifying all the other multipliers (short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};) as well. So, ...

Originally Posted By: Celtic Minstrel
Or we could come up with something different such that the enchantment cost increases non-linearly with the weapon value.

I think i'll take this approach : virtually leaving the first prices untounched and asymptotically (for value -> 10000) converge towards 30000 (or whatever).

Originally Posted By: Celtic Minstrel
That should be changed, maybe?

Listed as a bug, but is it ?
Nonetheless, that would change the balance of the game, so we need more opinions before changing anything smile

Chokboyz
Link to comment
Share on other sites

I think we should leave Flaming Weapon with unblockable damage for compatibility reasons, but weren't we going to allow the designer to choose the bonus damage type anyway?

 

Another thing I thought of: Have we increased the maximum stats designers can give monsters yet? I don't know if this is an issue, but I just think we should be sure that bugs won't occur when HP doubles due to party level or increases due to Guard and absorbing abilities. If we're sure, that's great. If not, we should become sure.

 

Speaking of the HP doubling: I don't know if this has already been done, but designers should be able to disable HP doubling if they want, or perhaps set the doubling to occur only at levels set by the designer. I don't know why you'd want to set HP doubling, since it's pretty much one of the most hated "features" of BoE by designers and players alike, but at least it should be possible to disable it.

Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
I think we should leave Flaming Weapon with unblockable damage for compatibility reasons, but weren't we going to allow the designer to choose the bonus damage type anyway?

Ok, i thing we'll leave it in state until choosing the bonus damage is implemented.

Originally Posted By: The Almighty Doer of Stuff
Another thing I thought of: Have we increased the maximum stats designers can give monsters yet? I don't know if this is an issue, but I just think we should be sure that bugs won't occur when HP doubles due to party level or increases due to Guard and absorbing abilities. If we're sure, that's great. If not, we should become sure.

That's an excellent question. As far as i know, we've not increased maximum stats a designer can give to a monster. There's can't be an overflow with the current max value (2500 max base, *2 for level adjustment, *3 for guard property = 15000) except if you spend your day casting kill or whatever hits hard on a magic absorbant monster (which will end up killing it, his health becoming negative).

Originally Posted By: The Almighty Doer of Stuff
Speaking of the HP doubling: I don't know if this has already been done, but designers should be able to disable HP doubling if they want, or perhaps set the doubling to occur only at levels set by the designer. I don't know why you'd want to set HP doubling, since it's pretty much one of the most hated "features" of BoE by designers and players alike, but at least it should be possible to disable it.

The two things affected by the Difficulty level are :
  • health * 2, as you mentioned. But the health can also be multiplied by 3 or 4, depending on the sum of alive pc level and the scenario difficulty).
  • monsters damage roll * (3/2) or * 2 (depending on the sum of alive pc level and the scenario difficulty)
It is extremely easy to remove that "feature", but how should we do it ? Do a game switch (user controlled) ? Do a designer switch ? Or simply remove it ? (legacy compatibility ?) Or we can leave it alone.

Chokboyz
Link to comment
Share on other sites

I think implementing a designer switch would probably be best. Right now the only way to do it is to set the scenario to max difficulty, which then confuses people (usually those who don't read the READ ME!!!!!11!111argh files, but I won't go into that again right now) and doesn't truly indicate the difficulty of the scenario. (While we're on that subject, though, are there plans to redo the scenario difficulty labels BoA-style?)

Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
I think implementing a designer switch would probably be best.

We can use a (now unused) flag_x variable to give the designer the option to do so. That until the new scenario format is achieved, implemented and functional (and even, that can always be used for legacy scenario, if a player gets fed up with the difficulty adjustment).

Originally Posted By: The Almighty Doer of Stuff
usually those who don't read the READ ME!!!!!11!111argh files, but I won't go into that again right now

Agreed, readme should be read. That or we'll hear about a "description rectangle bug" in the next release of Classic BoE.

Quote:
The Almighty Doer of StuffWhile we're on that subject, though, are there plans to redo the scenario difficulty labels BoA-style

Which is ? Level X-Y + Rating ? I'm not very familiar with Blades of Avernum ... crazy

Chokboyz
Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
I think we should leave Flaming Weapon with unblockable damage for compatibility reasons, but weren't we going to allow the designer to choose the bonus damage type anyway?
Good point, so we can fix it in the bladebase once that's done, but translation will map it to unblockable. (However, the name of the ability will probably change from Flaming Weapon to something appropriate for unblockable damage... but that's apurely aesthetic change.)

Originally Posted By: The Almighty Doer of Stuff
Another thing I thought of: Have we increased the maximum stats designers can give monsters yet?
No, we haven't. Should we?

Originally Posted By: The Almighty Doer of Stuff
Speaking of the HP doubling: I don't know if this has already been done, but designers should be able to disable HP doubling if they want, or perhaps set the doubling to occur only at levels set by the designer. I don't know why you'd want to set HP doubling, since it's pretty much one of the most hated "features" of BoE by designers and players alike, but at least it should be possible to disable it.
This could be complicated. Currently, HP doubling occurs when the party level is greater than the difficulty level's range of party levels, right? So, what's the reason for trying to evade HP doubling by raising the difficulty level?
Link to comment
Share on other sites

Originally Posted By: Chokboyz
That's an excellent question. As far as i know, we've not increased maximum stats a designer can give to a monster. There's can't be an overflow with the current max value (2500 max base, *2 for level adjustment, *3 for guard property = 15000) except if you spend your day casting kill or whatever hits hard on a magic absorbant monster (which will end up killing it, his health becoming negative).
We should do something about that – for example, check to be sure that the health is < 65535 before doing anything. Then, check that the health to gain is < 65535 - health, and if it isn't, just set the health to 65535.

Or you could cap it at the mas health, I suppose...

Originally Posted By: Chokboyz
It is extremely easy to remove that "feature", but how should we do it ? Do a game switch (user controlled) ? Do a designer switch ? Or simply remove it ? (legacy compatibility ?) Or we can leave it alone.
Designer switch, but how? We need to decide that first.
Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
(While we're on that subject, though, are there plans to redo the scenario difficulty labels BoA-style?)
Elaborate please?

Originally Posted By: Chokboyz

We can use a (now unused) flag_x variable to give the designer the option to do so. That until the new scenario format is achieved, implemented and functional (and even, that can always be used for legacy scenario, if a player gets fed up with the difficulty adjustment).
No no no no no. Don't just reuse an unused variable without changing its name!

Originally Posted By: Chokboyz

Agreed, readme should be read. That or we'll hear about a "description rectangle bug" in the next release of Classic BoE.
Sorry, what bug?
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
This could be complicated. Currently, HP doubling occurs when the party level is greater than the difficulty level's range of party levels, right? So, what's the reason for trying to evade HP doubling by raising the difficulty level?

It's a little more complicated : HP can be tripled or multiplied by four and the damage roll of the monster is also affected (see difficulty_adjust() in the code).

Originally Posted By: Celtic Minstrel
We should do something about that – for example, check to be sure that the health is < 65535 before doing anything. Then, check that the health to gain is < 65535 - health, and if it isn't, just set the health to 65535.

Should we bother ? The maximum health a monster can have is 15000 (2500 * 2 *3), that leave 32 767 - 15000 = 17767 hp. (health is signed because you die when your health is less than 0). Let's say your maximum damaging spell does 200 damage (good roll on kill) then you would have to cast it 17767/200 ~ 88 times to overflow the variable.
Then again, it's a simple check to implement, so why not ...

Originally Posted By: Celtic Minstrel
Designer switch, but how? We need to decide that first.

For legacy scenario, one of the now unused variable, set by a led in the Scenario Editor.
For future scenario, maybe a field in the scenario structure ? confused

Originally Posted By: Celtic Minstrel
No no no no no. Don't just reuse an unused variable without changing its name!

Who said i wasn't changing the name ? wink

Originally Posted By: Celtic Minstrel
Sorry, what bug?

None.
I've made changes in description rectangles to make the (0,0) a legit rectangle (all deleted rectangles were previously put there, giving a Rectangle X description in the game if accessed; deleted rectangles now have coordinates ((-1,-1),(-1,-1))). A side effect is that already present rectangles (i.e in legacy scenarios) are now drawn in the Scenario Editor. These changes are documented in the changelog.
ADoS was pesting against those who don't read the README file and I was agreeing with him by saying that if some people doesn't read documentation, we'll surely have some report of "Rectangles wrongly appearing in corner of the town/outdoors when loading legacy scenarios" smile

Chokboyz

Edit : Here's a (very) simple proposition of a corrected augment weapon calculation formula :

Originally Posted By: Code
if(adven[pc_num].items[item_num].value <=1400)
val_to_place = max(aug_cost[shop_identify_cost] * 100,adven[pc_num].items[item_num].value * (5 + aug_cost[shop_identify_cost]));//original behavior
else
val_to_place = 1400 * (5 + aug_cost[shop_identify_cost]) + (30000 - 1400 * (5 + aug_cost[shop_identify_cost]))* (adven[pc_num].items[item_num].value - 1400)/8600;//really smoothen the price curve

The (really simple) idea used here is to let the program calculate the price as usual for the 1400 first gold pieces then to the add a fraction of the remaining (30000 - 1400 * multiplier) gold pieces depending of how "far" the item value is from the max value (10000).
The value 1400 is used because the highest multiplier is 20 (and 1500*20 = 30000, so let's use 1400).
Weapons with prices more than 1400 are few (Steel Greatsword, Steel Great Mace, Steel Halberd, ...), but this calculation method will give them about the same price of enchantement.
Example :
Steel Halberd => flaming : 28139, +1 : 13813 Value : 2000
Steel Greatsword => flaming : 28093, +1 : 13409 Value : 1800
Steel Great Mace => flaming : 28069, +1 : 13206 Value : 1700


If the maximum value (10000) is reached, then the enchantement cost 30000.
Link to comment
Share on other sites

I think you miscalculated the potential max HP. It's actually 2500 * 4 (because if you're at Very High level in a Low Level scenario, it's multiplied by 4, right?) * 3 (for Guard) = 30000, plus Absorb Spells and Draining Touch, right?

 

It's necessary to allow a switch because it wreaks havoc with game balance in ways that designers can't account for. Many scenarios, including At The Gallows and others I believe, set the difficulty to Very High even though they're meant for beginner-level parties, just so the HP won't multiply and make the game extremely difficult to impossible.

Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
I think you miscalculated the potential max HP. It's actually 2500 * 4 (because if you're at Very High level in a Low Level scenario, it's multiplied by 4, right?) * 3 (for Guard) = 30000, plus Absorb Spells and Draining Touch, right?

Damn, and to think i was the one that mentioned the four times multiplier ... rolleyes
Ok, i'll make a safety check for Absorb Spells. By the way, the Draining Touch ability (despite saying "Drains life !") only drains XP.

Originally Posted By: The Almighty Doer of Stuff
It's necessary to allow a switch because it wreaks havoc with game balance in ways that designers can't account for. Many scenarios, including At The Gallows and others I believe, set the difficulty to Very High even though they're meant for beginner-level parties, just so the HP won't multiply and make the game extremely difficult to impossible.

No problem, we only need to agree on what variable to use.

Chokboyz

Edit : safety check for Absorb Spell done. Tested and work.
Originally Posted By: Example of code

if (((dam_type == 1) || (dam_type == 3) || (dam_type == 5))
&& (victim->m_d.spec_skill == 26)) {
if((victim->m_d.health + how_much) < 32767)
victim->m_d.health += how_much;
ASB(" Magic absorbed.");
return FALSE;
}

(note that there's two occurences of the Absorb Spells check in the code)

Edit 2 : Err, seems like the Protection from Acid check is done with the wrong ability number (hasAbilEquip(122) - Spell : Stinking Cloud), should be replaced by 36.
There's also a check for a non-existing 67 object in the handle_disease() function. I think it should read 62 (Protection from Disease).
Link to comment
Share on other sites

Two suggestions;

 

1. If it's not already on the list, a way of checking a PC's name so it can be used in dialogue; so if I wrote "<pc1name> falls down a big hole." and my leader was named John, the dialogue would read "John falls down a big hole."

 

2. The ability to split the party beyond just one PC going it alone. I'd like encounters where 2 members can be used, or where the party has to be split in half. This is why I was asking for the pre-fab generator before; I'm imagining a scenario where you can have NPCs join as full PCs. (since they'd be pre-made already)

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Should we bother ? The maximum health a monster can have is 15000 (2500 * 2 *3), that leave 32 767 - 15000 = 17767 hp. (health is signed because you die when your health is less than 0). Let's say your maximum damaging spell does 200 damage (good roll on kill) then you would have to cast it 17767/200 ~ 88 times to overflow the variable.
Then again, it's a simple check to implement, so why not ...
First, it would be quite possible to make health unsigned while still causing things to die when their health is less than 0 – instead of directly checking if the health is less than 0, you check if the damage is greater than the health.

Second, yes it may hard to reach that scenario, but it's best to be as foolproof as possible. If "Absorbs spells" is supposed to cause the monster to gain hit points when struck by a spell, thereby making them immune to spells, then a such a monster dying from a spell is incorrect behaviour – a bug. Even if it's not easily reached. SO, unless scenarios actually rely on this, we should fix it.

Originally Posted By: Chokboyz
For legacy scenario, one of the now unused variable, set by a led in the Scenario Editor.
For future scenario, maybe a field in the scenario structure ? confused
I was thinking more along the lines of how the field would be used, actually.

Originally Posted By: Chokboyz
Who said i wasn't changing the name ? wink
No-one. No-one said you were, either.

Originally Posted By: Chokboyz
Edit : Here's a (very) simple proposition of a corrected augment weapon calculation formula :

Code:
if(adven[pc_num].items[item_num].value <=1400)    val_to_place = max(aug_cost[shop_identify_cost] * 100,adven[pc_num].items[item_num].value * (5 + aug_cost[shop_identify_cost]));//original behaviorelse    val_to_place = 1400 * (5 + aug_cost[shop_identify_cost]) + (30000 - 1400 * (5 + aug_cost[shop_identify_cost]))* (adven[pc_num].items[item_num].value - 1400)/8600;//really smoothen the price curve

The (really simple) idea used here is to let the program calculate the price as usual for the 1400 first gold pieces then to the add a fraction of the remaining (30000 - 1400 * multiplier) gold pieces depending of how "far" the item value is from the max value (10000).
The value 1400 is used because the highest multiplier is 20 (and 1500*20 = 30000, so let's use 1400).
Weapons with prices more than 1400 are few (Steel Greatsword, Steel Great Mace, Steel Halberd, ...), but this calculation method will give them about the same price of enchantement.
Example :
Steel Halberd => flaming : 28139, +1 : 13813 Value : 2000
Steel Greatsword => flaming : 28093, +1 : 13409 Value : 1800
Steel Great Mace => flaming : 28069, +1 : 13206 Value : 1700


If the maximum value (10000) is reached, then the enchantement cost 30000.
((Note: I reformatted the code segment))

I was thinking something logarithmic, actually. For example:

max(aug_cost[shop_identify_cost]*100,1.0*value*(aug_cost[shop_identify_cost]*(1.0 / log(value,B)))

Assuming that log(x,y) calculates the logarithim of x to base y; b could be anywhere from 2 to 20, inclusive (if you want to not exceed 30000, the choices are 2 or 3). Now, at a value of 1400 and an aug_cost of 15, that's 25320 different from the original behaviour with a base of 2 and 19100 different with a base of 10. With a value of 10000, base 2 yields 15051 and base 10 yields 50000. (With a base of 20, it's 16421 different at a value of 1400 and yields 65051 with a value of 10000.) The differences are negative (ie it'll cost less than it used to).

But maybe your method is also good...

So... the augmentation cost times 100 is a minimum cost for the enchantment; otherwise, the cost is calculated by multiplying the item value with 5 more than the augmentation cost. (original behaviour)

Then, when you have a value greater than 1400, you start with 1400 times 5 more than the augmentation cost. You take that value (call it x) and subtract it from 30000, then multiply the result by 1400 less than the value and divide by 8600; after this, you add x. It sounds rather confusing, but perhaps it works; I'll give it some thought.
Link to comment
Share on other sites

...Looks like I'm slow here... Anyway...

 

Originally Posted By: Chokboyz
Ok, i'll make a safety check for Absorb Spells. By the way, the Draining Touch ability (despite saying "Drains life !") only drains XP.
That's right, it's supposed to do that.

 

Originally Posted By: Chokboyz
No problem, we only need to agree on what variable to use.
Actually, we don't really. We only need to agree on the name of the variable. wink I'm actually going to consider using bit fields at some point for stuff like this. Just so you know.

 

Originally Posted By: Chokboyz
safety check for Absorb Spell done. Tested and work.

Originally Posted By: Example of code

if (((dam_type == 1) || (dam_type == 3) || (dam_type == 5))

&& (victim->m_d.spec_skill == 26)) {

if((victim->m_d.health + how_much) < 32767)

victim->m_d.health += how_much;

ASB(" Magic absorbed.");

return FALSE;

}

(note that there's two occurences of the Absorb Spells check in the code)

Assuming health is a signed variable, I think that check will always be true. You need to either temporarily store it in an unsigned variable (or a larger variable such as a long), or do something slightly more complicated.

 

Of course, if health is unsigned it'll work just fine...

 

Originally Posted By: Arachnid
1. If it's not already on the list, a way of checking a PC's name so it can be used in dialogue; so if I wrote "<pc1name> falls down a big hole." and my leader was named John, the dialogue would read "John falls down a big hole."
Good one. Hard to do though. It would be pretty easy to do a Display Small Message node which uses a player's name, though; maybe that's what you meant.

 

Originally Posted By: Arachnid
2. The ability to split the party beyond just one PC going it alone. I'd like encounters where 2 members can be used, or where the party has to be split in half. This is why I was asking for the pre-fab generator before; I'm imagining a scenario where you can have NPCs join as full PCs. (since they'd be pre-made already)
Part two is planned (I intend to make a way for an NPC to join the party as a PC). Part 1 was not really considered, but it's a good idea – more complex party splitting could be useful. I'll think about how that might be done without changing too much about the party-splitting mechanism.
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I was thinking more along the lines of how the field would be used, actually.

Click to reveal.. (code)
short difficulty_adjust()
{
short i, j = 0;
short to_return = 1;

[color:#339999 if(scenario.variable == 0)
return 1;


for (i = 0; i < 6; i++)
if (adven.isAlive()) j += adven.level;

if ((scenario.difficulty <= 0) && (j >= 60)) to_return++;
if ((scenario.difficulty <= 1) && (j >= 130)) to_return++;
if ((scenario.difficulty <= 2) && (j >= 210)) to_return++;
return to_return;
} [/color]

Variable would be set in the Scenario Editor, in the Scenario Details.

Originally Posted By: Celtic Minstrel
I was thinking something logarithmic, actually.

I've been thinking using logarithmic too, but my goal was to let the low values alone and only tweak the high ones.
Both approaches are valids, only results differs. If the community find the prices really ridiculous (I think Thuryl was saying something like that) then your approach may be better ...

Originally Posted By: Celtic Minstrel
It sounds rather confusing, but perhaps it works; I'll give it some thought.

It's rather simple : do as usual until 1400 is reached, then augment the price much slower (and linearly).

Originally Posted By: Celtic Minstrel
Actually, we don't really. We only need to agree on the name of the variable.

Wow ... I don't know ... apply_difficulty_adjust ?

Originally Posted By: Celtic Minstrel
Assuming health is a signed variable, I think that check will always be true.

I don't know what type the compiler/program use to make the test but it works (i'd bet it use an int) ... Maybe i should add a unsigned short, just to be sure ?

Originally Posted By: Celtic Minstrel
Good one. Hard to do though. It would be pretty easy to do a Display Small Message node which uses a player's name, though; maybe that's what you meant.

A possible way would be to check if the character '<' is read then to copy all following characters, until '>' is reached, into an array. Then string compare the array and insert the corresponding string.
Very inelegant, but should works smirk

Originally Posted By: Celtic Minstrel
Part two is planned (I intend to make a way for an NPC to join the party as a PC). Part 1 was not really considered, but it's a good idea – more complex party splitting could be useful. I'll think about how that might be done without changing too much about the party-splitting mechanism.

Splitting would involve tweaking the PSD[304][0-3] and some rewritting (active_pc maybe ?), changing the adventurers main status may already more or less work if i'm not mistaken.
Making an NPC join the party sounds like filling a PC structure wink (that is if a slot is available)

Chokboyz
Link to comment
Share on other sites

Okay, so a quick printf reveals that despite there being two variables of the same name, the correct one is always accessed. But then I get an EXC_BAD_ACCESS in operator>> for some reason.

 

The variable in question is called p and is of type std::pair<std::string,cPict*>; the correct variable has a first set to "graphic" (actually read from the XML document) and a second set to new cPict, while the other copy (which appears to be never accessed) has first set to "pict" and second set to 0x4. The function eventually returns p (and it is inserted into the map). It's particularly odd that the mysterious p.first is equal to "pict", since that's the name of the element currently being parsed (ie we're parsing a pict element).

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Actually, we don't really. We only need to agree on the name of the variable.

Wow ... I don't know ... apply_difficulty_adjust ?
Nice and descriptive, though a little long. (I also prefer thisTypeOfName, but that's beside the point.) How about simply adjust_hp?

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Assuming health is a signed variable, I think that check will always be true.

I don't know what type the compiler/program use to make the test but it works (i'd bet it use an int) ... Maybe i should add a unsigned short, just to be sure ?
I don't think Jeff ever used ints, and for good reason: you can't depend on them being a particular size. The simplest way to guarantee that it works would be to cast the health to an unsigned short. What's the type of how_much? That should maybe be unsigned too? I dunno; if it works, you can leave it for now, anyway.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Good one. Hard to do though. It would be pretty easy to do a Display Small Message node which uses a player's name, though; maybe that's what you meant.

A possible way would be to check if the character '<' is read then to copy all following characters, until '>' is reached, into an array. Then string compare the array and insert the corresponding string.
Very inelegant, but should works smirk
...Well, I was thinking something more like BoA's "add_pc_name" or whatever it's called. Your suggestion would work, of course, but it's a C solution; I'd prefer a C++ solution. Again, I'll think on it.

Originally Posted By: Chokboyz
Splitting would involve tweaking the PSD[304][0-3] and some rewritting (active_pc maybe ?), changing the adventurers main status may already more or less work if i'm not mistaken.
It would likely involve using a lot more than just 0-3. Perhaps the following breakdown of PSD[304][???] would work:

Code:
 0 .. 5 - PC present? ( > 0 means yes) 6 .. 7 - Town x,y loc of left-behind characters      8 - Town of left-behind characters

Did I miss anything?

Originally Posted By: Chokboyz
Making an NPC join the party sounds like filling a PC structure wink (that is if a slot is available)
Filling a PC structure from a monster structure, yes. Not a simple task. I'd probably make a dedicated function for it (perhaps a cPlayer constructor).
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Nice and descriptive, though a little long. (I also prefer thisTypeOfName, but that's beside the point.) How about simply adjust_hp?

Note that hp is not the only adjusted thing, monsters' damages are too, but adjust_hp (or AdjustHp or AdjustHP)is okay for me smile

Originally Posted By: Celtic Minstrel
Well, I was thinking something more like BoA's "add_pc_name" or whatever it's called.

I'm not familiar with BoA, but i assume it's a function that insert the pc name in a string ?

Originally Posted By: Celtic Minstrel
Your suggestion would work, of course, but it's a C solution; I'd prefer a C++ solution.

Indeed, that's obviously C thinking ... smile
There's should be a way to do so in C++ (given that you're converting the code to it), but i'm not skilled in C++ enough to know more than that.

Originally Posted By: Celtic Minstrel
It would likely involve using a lot more than just 0-3. Perhaps the following breakdown of PSD[304][???] would work:
Did I miss anything?

Seems fine to me. And there're unused too.
I think there's also a variable called active_pc that may need to be checked (it's the same as when a pc is soloing).

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Originally Posted By: Chokboyz
A possible way would be to check if the character '<' is read then to copy all following characters, until '>' is reached, into an array. Then string compare the array and insert the corresponding string.
Very inelegant, but should works smirk
...Well, I was thinking something more like BoA's "add_pc_name" or whatever it's called. Your suggestion would work, of course, but it's a C solution; I'd prefer a C++ solution. Again, I'll think on it.

I would argue that Chokboyz' method is, in rough outline, perfectly good for use in C++ with a bit of tweaking. First, use std::strings instead of character arrays, naturally, and use find() to look for opening and closing angle brackets. If you find a matching pair of them, pass the contents off to a function for conversion into the desired string, which you would substitute in with replace(). This would be easier if you changed the format so be like <name n>, where n is the number of the creature whose name to substitute, so that the type of data (the name) and the creature for which to get it are neatly separated. You could conceivably support other substitutions than just names as well, if there are any that designers are likely to want.

You could also use boost::regex, but that would probably be massive overkill for something this simple.

Originally Posted By: Celtic Minstrel
I don't think Jeff ever used ints, and for good reason: you can't depend on them being a particular size. The simplest way to guarantee that it works would be to cast the health to an unsigned short. What's the type of how_much? That should maybe be unsigned too? I dunno; if it works, you can leave it for now, anyway.

You do realize that the sizes of short ints, ints, long ints, and even chars is technically platform dependent, right? The standard libraries, however, provide some typedefs that are supposed to be fixed sizes, such as int32_t uint64_t and so on.
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Nice and descriptive, though a little long. (I also prefer thisTypeOfName, but that's beside the point.) How about simply adjust_hp?

Note that hp is not the only adjusted thing, monsters' damages are too, but adjust_hp (or AdjustHp or AdjustHP)is okay for me smile
I like to begin my names with a lowercase letter. smile

I've been using underscore-separated names mainly because the game already does so, so if you want to use an underscore-separated name that's fine by me. I used "camel case" in the dialog engine, though.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Well, I was thinking something more like BoA's "add_pc_name" or whatever it's called.

I'm not familiar with BoA, but i assume it's a function that insert the pc name in a string ?
BoA maintains a single string buffer; the function in question appends the PC's name to the buffer. The buffer can later be used for anything that takes a string, including a speech, dialogs, or the transcript.

In truth, however, the <...> method is more flexible.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
It would likely involve using a lot more than just 0-3. Perhaps the following breakdown of PSD[304][???] would work:
Did I miss anything?

Seems fine to me. And there're unused too.
Well, actually, they aren't unused – they're in fact used for party splitting, but in a different way. But that's something that can be converted when loading a savegame.

Originally Posted By: Chokboyz
I think there's also a variable called active_pc that may need to be checked (it's the same as when a pc is soloing).
Isn't that just the currently selected PC?

Originally Posted By: Niemand
I would argue that Chokboyz' method is, in rough outline, perfectly good for use in C++ with a bit of tweaking. First, use std::strings instead of character arrays, naturally, and use find() to look for opening and closing angle brackets. If you find a matching pair of them, pass the contents off to a function for conversion into the desired string, which you would substitute in with replace(). This would be easier if you changed the format so be like <name n>, where n is the number of the creature whose name to substitute, so that the type of data (the name) and the creature for which to get it are neatly separated.
Sure – I was referring to more than just the outline when I said that. And then we can use a replace function from the algorithm header...

Originally Posted By: Niemand
You could conceivably support other substitutions than just names as well, if there are any that designers are likely to want.
At least one thing: the value of an SDF. Possibly other numeric things, like the value of a statistic or a status...

Originally Posted By: Niemand
You could also use boost::regex, but that would probably be massive overkill for something this simple.
I did think about regex, actually...

Originally Posted By: Niemand
You do realize that the sizes of short ints, ints, long ints, and even chars is technically platform dependent, right?
Maybe, but they're less dependent than plain int.
Link to comment
Share on other sites

*sigh*

 

Well, I'm stumped on the dialog engine crash, and I can't really work on saving and loading in the new formats until Niemand finishes what he was doing (unless I want to duplicate his work), so I think I will head back to page 12 and start incorporating various fixes and small changes that are already in the Windows code.

Link to comment
Share on other sites

Quote:
until Niemand finishes what he was doing (unless I want to duplicate his work)

Was this the work of trying to check structure sizes? I'll direct more attention toward that if it's holding up your progress in other areas.

If the crash you complain of is still the one I remember, then I too am baffled, since I see no crash. Should the recently checked in versions exhibit this behavior, or were you holding back your changes until they work?
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I like to begin my names with a lowercase letter.

I've been using underscore-separated names mainly because the game already does so, so if you want to use an underscore-separated name that's fine by me. I used "camel case" in the dialog engine, though.

Ok, so are we using adjust_difficulty ? adjust_hp (despite hp not being the only affected thing) ? Any name following that format is ok for me wink

Originally Posted By: Celtic Minstrel
I will head back to page 12 and start incorporating various fixes and small changes that are already in the Windows code.

Ok, so i will slow down those fix/changes until you catch up. smile
Maybe it's a good time to make a release ... confused

I've noticed something odd : when resting/waiting, if a timed special happens, the rest/wait is not interrupted. Does this need to be changed ? (only monsters in sight and health diminution presently interrupt the rest/wait). Maybe it would be better to make it a preference switch ?

Also, will fixing the event timer break some legacy scenarios ? (the problem is that not all the time rested (waiting is not affected) is actually checked for events ... in fact, merely the 50 first moves are checked).

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Niemand
Quote:
until Niemand finishes what he was doing (unless I want to duplicate his work)

Was this the work of trying to check structure sizes? I'll direct more attention toward that if it's holding up your progress in other areas.
The dialog engine crash is holding me up more than the structure padding stuff, really... but if you could put a little more time into it that would be nice.

Originally Posted By: Niemand
If the crash you complain of is still the one I remember, then I too am baffled, since I see no crash. Should the recently checked in versions exhibit this behavior, or were you holding back your changes until they work?
I was holding it back initially, but now it is committed. It occurs when displaying the edit terrain dialog in the scenario editor (in fact when loading it).

Originally Posted By: Chokboyz
Ok, so are we using adjust_difficulty ? adjust_hp (despite hp not being the only affected thing) ? Any name following that format is ok for me wink
What else besides hit points is affected?

Originally Posted By: Chokboyz
I've noticed something odd : when resting/waiting, if a timed special happens, the rest/wait is not interrupted. Does this need to be changed ? (only monsters in sight and health diminution presently interrupt the rest/wait). Maybe it would be better to make it a preference switch ?
...Hmm. Let me think on that.

Originally Posted By: Chokboyz
Also, will fixing the event timer break some legacy scenarios ? (the problem is that not all the time rested (waiting is not affected) is actually checked for events ... in fact, merely the 50 first moves are checked).
I think it should probably be fixed, but let's wait on that...


I've noticed several odd things too. See the next post for details.
Link to comment
Share on other sites

Okay, so I went in to incorporate the changes to the Affect PC nodes (making them affect only the active PC when the party is split), and ended up doing cleanup of the code. One odd thing I noticed is that when drinking a potion, the "swallow" sound is played only if the graphic 50, 51, or 52. I've removed this check, so the sound will be played no matter what the graphic (but only if the variety is POTION).

 

For reference, this is in the use_item() function.

 

In the switch statement in the same function, I've split the second case (the one with several case labels and a nested switch statement) into individual cases, removing the inner switch statement. The cost is four lines of code duplication, which is practically nothing.

 

Another odd thing in this function is in case 120 (ITEM_SPELL_MASS_SUMMONING), in the for-loop. The end condition for the for-loop is "i < get_ran(1,3,5)", which I think means a new random value is used each time the loop executes! It will work just fine as-is, but it seems pointless. I suggest removing the get_ran call to just before the loop and storing it in a variable. Or perhaps like this:

 

for(i = 0, j = get_ran(1,3,5); i < j; i++)

 

I haven't yet made this change though (I marked it with a "TODO:" label).

 

 

In use_space, when checking for "TER_SPEC_CALL_SPECIAL_WHEN_USED", there's no return statement. Because of this, the message "Nothing to use" is printed even though something was used. I added a "return true" to the end of the if clause to fix this.

 

In adj_town_look, when checking for blockage, the "Search: You find something!" messages were commented out. I uncommented them... though we need to check those if statements, because I think it's checking a Stuff Done Flag that it shouldn't check. Also in that function, there's a switch statement that prints "(Use this space ...)" if the terrain type is 22 or 23... that is, Mountains. I've removed the switch statement altogether, since it had only one case, and moved the default case directly into the else statement. The original case is still present, but now checking the terrain ability to see if it's one of the two usable types.

Link to comment
Share on other sites

Some additions to the list of constants (note that I'm now using enums for most of the constants, rather than #defines).

 

Code:
enum eSpecContext {    SPEC_OUT_MOVE = 0,    SPEC_TOWN_MOVE = 1,    SPEC_COMBAT_MOVE = 2,    SPEC_OUT_LOOK = 3,    SPEC_TOWN_LOOK = 4,    SPEC_ENTER_TOWN = 5,    SPEC_LEAVE_TOWN = 6,    SPEC_TALK = 7,    SPEC_USE_SPEC_ITEM = 8,    SPEC_TOWN_TIMER = 9,    SPEC_SCEN_TIMER = 10,    SPEC_PARTY_TIMER = 11,    SPEC_KILL_MONST = 12,    SPEC_OUTDOOR_ENC = 13,    SPEC_WIN_ENCOUNTER = 14,    SPEC_FLEE_ENCOUNTER = 15,    SPEC_TARGET = 16,    SPEC_USE_SPACE = 17,    SPEC_SEE_MONST = 18,};enum eSpecNodeType {    SPEC_NULL = 0,    SPEC_SET_SDF = 1,    SPEC_INC_SDF = 2,    SPEC_DISPLAY_MSG = 3,    SPEC_SECRET_PASSAGE = 4,    SPEC_DISPLAY_SM_MSG = 5,    SPEC_FLIP_SDF = 6,    SPEC_OUT_BLOCK = 7,    SPEC_TOWN_BLOCK = 8,    SPEC_FIGHT_BLOCK = 9,    SPEC_LOOK_BLOCK = 10,    SPEC_CANT_ENTER = 11,    SPEC_CHANGE_TIME = 12,    SPEC_SCEN_TIMER_START = 13,    SPEC_PLAY_SOUND = 14,    SPEC_CHANGE_HORSE_OWNER = 15,    SPEC_CHANGE_BOAT_OWNER = 16,    SPEC_SET_TOWN_VISIBILITY = 17,    SPEC_MAJOR_EVENT_OCCURRED = 18,    SPEC_FORCED_GIVE = 19,    SPEC_BUY_ITEMS_OF_TYPE = 20,    SPEC_CALL_GLOBAL = 21,    SPEC_SET_SDF_ROW = 22,    SPEC_COPY_SDF = 23,    SPEC_SANCTIFY = 24,    SPEC_REST = 25,    SPEC_WANDERING_WILL_FIGHT = 26,    SPEC_END_SCENARIO = 27,    SPEC_ONCE_GIVE_ITEM = 50,    SPEC_ONCE_GIVE_SPEC_ITEM = 51,    SPEC_ONCE_NULL = 52,    SPEC_ONCE_SET_SDF = 53,    SPEC_ONCE_DISPLAY_MSG = 54,    SPEC_ONCE_DIALOG = 55,    SPEC_ONCE_DIALOG_TERRAIN = 56,    SPEC_ONCE_DIALOG_MONSTER = 57,    SPEC_ONCE_GIVE_ITEM_DIALOG = 58,    SPEC_ONCE_GIVE_ITEM_TERRAIN = 59,    SPEC_ONCE_GIVE_ITEM_MONSTER = 60    SPEC_ONCE_OUT_ENCOUNTER = 61,    SPEC_ONCE_TOWN_ENCOUNTER = 62,    SPEC_ONCE_TRAP = 63,    SPEC_SELECT_PC = 80,    SPEC_DAMAGE = 81    SPEC_AFFECT_HP = 82,    SPEC_AFFECT_SP = 83,    SPEC_AFFECT_XP = 84,    SPEC_AFFECT_SKILL_PTS = 85,    SPEC_AFFECT_DEADNESS = 86,    SPEC_AFFECT_POISON = 87,    SPEC_AFFECT_SPEED = 88,    SPEC_AFFECT_INVULN = 89,    SPEC_AFFECT_MAGIC_RES = 90,    SPEC_AFFECT_WEBS = 91,    SPEC_AFFECT_DISEASE = 92,    SPEC_AFFECT_SANCTUARY = 93,    SPEC_AFFECT_CURSE_BLESS = 94,    SPEC_AFFECT_DUMBFOUND = 95,    SPEC_AFFECT_SLEEP = 96,    SPEC_AFFECT_PARALYSIS = 97,    SPEC_AFFECT_STAT = 98,    SPEC_AFFECT_MAGE_SPELL = 99,    SPEC_AFFECT_PRIEST_SPELL = 100,    SPEC_AFFECT_GOLD = 101,    SPEC_AFFECT_FOOD = 102,    SPEC_AFFECT_ALCHEMY = 103,    SPEC_AFFECT_STEALTH = 104,    SPEC_AFFECT_FIREWALK = 105,    SPEC_AFFECT_FLIGHT = 106,    SPEC_IF_SDF = 130,    SPEC_IF_TOWN_NUM = 131,    SPEC_IF_RANDOM = 132,    SPEC_IF_HAVE_SPECIAL_ITEM = 133,    SPEC_IF_SDF_COMPARE = 134,    SPEC_IF_TOWN_TER_TYPE = 135,    SPEC_IF_OUT_TER_TYPE = 136,    SPEC_IF_HAS_GOLD = 137,    SPEC_IF_HAS_FOOD = 138,    SPEC_IF_ITEM_CLASS_ON_SPACE = 139,    SPEC_IF_HAVE_ITEM_CLASS = 140,    SPEC_IF_EQUIP_ITEM_CLASS = 141,    SPEC_IF_HAS_GOLD_AND_TAKE = 142,    SPEC_IF_HAS_FOOD_AND_TAKE = 143,    SPEC_IF_ITEM_CLASS_ON_SPACE_AND_TAKE = 144,    SPEC_IF_HAVE_ITEM_CLASS_AND_TAKE = 145,    SPEC_IF_EQUIP_ITEM_CLASS_AND_TAKE = 146,    SPEC_IF_DAY_REACHED = 147,    SPEC_IF_BARRELS = 148,    SPEC_IF_CRATES = 149,    SPEC_IF_EVENT_OCCURRED = 150,    SPEC_IF_HAS_CAVE_LORE = 151,    SPEC_IF_HAS_WOODSMAN = 152,    SPEC_IF_ENOUGH_MAGE_LORE = 153,    SPEC_IF_TEXT_RESPONSE = 154,    SPEC_IF_SDF_EQ = 155,    SPEC_MAKE_TOWN_HOSTILE = 170,    SPEC_TOWN_CHANGE_TER = 171,    SPEC_TOWN_SWAP_TER = 172,    SPEC_TOWN_TRANS_TER = 173,    SPEC_TOWN_MOVE_PARTY = 174,    SPEC_TOWN_HIT_SPACE = 175,    SPEC_TOWN_EXPLODE_SPACE = 176    SPEC_TOWN_LOCK_SPACE = 177,    SPEC_TOWN_UNLOCK_SPACE = 178,    SPEC_TOWN_SFX_BURST = 179,    SPEC_TOWN_CREATE_WANDERING = 180,    SPEC_TOWN_PLACE_MONST = 181,    SPEC_TOWN_DESTROY_MONST = 182,    SPEC_TOWN_NUKE_MONSTS = 183,    SPEC_TOWN_GENERIC_LEVER = 184,    SPEC_TOWN_GENERIC_PORTAL = 185,    SPEC_TOWN_GENERIC_BUTTON = 186,    SPEC_TOWN_GENERIC_STAIR = 187,    SPEC_TOWN_LEVER = 188,    SPEC_TOWN_PORTAL = 189,    SPEC_TOWN_STAIR = 190,    SPEC_TOWN_RELOCATE = 191, // Relocate outdoors    SPEC_TOWN_PLACE_ITEM = 192,    SPEC_TOWN_SPLIT_PARTY = 193    SPEC_TOWN_REUNITE_PARTY = 194,    SPEC_TOWN_TIMER_START = 195,    SPEC_RECT_PLACE_FIRE = 200,    SPEC_RECT_PLACE_FORCE = 201,    SPEC_RECT_PLACE_ICE = 202,    SPEC_RECT_PLACE_BLADE = 203,    SPEC_RECT_PLACE_SCLOUD = 204,    SPEC_RECT_PLACE_SLEEP = 205,    SPEC_RECT_PLACE_QUICKFIRE = 206,    SPEC_RECT_PLACE_FIRE_BARR = 207,    SPEC_RECT_PLACE_FORCE_BARR = 208,    SPEC_RECT_CLEANSE = 209,    SPEC_RECT_PLACE_SFX = 210,    SPEC_RECT_PLACE_OBJECT = 211, // place barrels, etc    SPEC_RECT_MOVE_ITEMS = 212,    SPEC_RECT_DESTROY_ITEMS = 213    SPEC_RECT_CHANGE_TER = 214,    SPEC_RECT_SWAP_TER = 215,    SPEC_RECT_TRANS_TER = 216,    SPEC_RECT_LOCK = 217,    SPEC_RECT_UNLOCK = 218,    SPEC_OUT_MAKE_WANDER = 225,    SPEC_OUT_CHANGE_TER = 226,    SPEC_OUT_PLACE_ENCOUNTER = 227,    SPEC_OUT_MOVE_PARTY = 228,    SPEC_OUT_STORE = 229,};enum eTalkNodeType {    TALK_REGULAR = 0,    TALK_DEP_ON_SDF = 1,    TALK_SET_SDF = 2,    TALK_INN = 3,    TALK_DEP_ON_TIME = 4,    TALK_DEP_ON_TIME_AND_EVENT = 5,    TALK_DEP_ON_TOWN = 6,    TALK_BUY_ITEMS = 7,    TALK_TRAINING = 8,    TALK_BUY_MAGE = 9,    TALK_BUY_PRIEST = 10,    TALK_BUY_ALCHEMY = 11,    TALK_BUY_HEALING = 12,    TALK_SELL_WEAPONS = 13,    TALK_SELL_ARMOR = 14,    TALK_SELL_ITEMS = 15,    TALK_IDENTIFY = 16,    TALK_ENCHANT = 17,    TALK_BUY_INFO = 18,    TALK_BUY_SDF = 19,    TALK_BUY_SHIP = 20,    TALK_BUY_HORSE = 21,    TALK_BUY_SPEC_ITEM = 22,    TALK_BUY_JUNK = 23,    TALK_BUY_TOWN_LOC = 24,    TALK_END_FORCE = 25,    TALK_END_FIGHT = 26,    TALK_END_ALARM = 27, // Town hostile    TALK_END_DIE = 28,    TALK_CALL_TOWN_SPEC = 29,    TALK_CALL_SCEN_SPEC = 30,};

 

 

The special context (eSpecContext) is passed to the run_special() function to specify what triggered the special (basically).

 

 

(There's some missing commas in that code, though...)

Link to comment
Share on other sites

Okay, I've removed the 50 node limit. The code is platform dependent, but I'll post it here anyway; maybe it'll help you to duplicate it.

 

Basically, I replaced this:

Code:
if (num_nodes >= 50) {    give_error("A special encounter can be at most 50 nodes long. The 50th node was just processed. The encounter will now end.","",0);    next_spec = -1;}

with this:

Code:
if(WaitNextEvent(keyDownMask|autoKeyMask, &evt, 1, NULL)){    char c = evt.message & charCodeMask;    bool interrupt = false;    if((toupper© == 'C' && (evt.modifiers & controlKey))) interrupt = true;    if((c == '.' && (evt.modifiers & cmdKey))) interrupt = true;    if(interrupt){        give_error("The special encounter was interrupted. The scenario may be in an unexpected state; it is recommended that you reload from a saved game.","",0);        next_spec = -1;    }}

 

It's probably fairly obvious, but I'll explain anyway. I first check to see if a keyDown or autoKey event is pending; if there is one, I check to see if it's either Ctrl-C or Command-period (both standard interrupt sequences); if it is, I display a diagnostic message and terminate the encounter.

 

I tested it with a two-special infinite loop (special A jumps to special B and special B jumps to special A) and it worked... but only the command-period shortcut worked. I'm not sure why Ctrl-C did not work.

 

I'm not sure what the standard interrupt key sequence would be for Windows. Ctrl-C would work, since there's nothing to "copy", but if there's another standard one you should implement that too. (Obviously you can't implement command-period though. ;))

Link to comment
Share on other sites

I'm not sure about standard interrupts in Windows. I'm not even sure there is one, except Ctrl+Alt+Delete, and that doesn't always work either.

 

Why not use Ctrl+Period? Ctrl+C is used in BoE as Copy, as you said. What if you had a Text Response node and you hit Ctrl+C? Would it know whether to copy the highlighted text or interrupt the node chain? Ctrl+Period isn't used for anything at the moment.

Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
I'm not sure about standard interrupts in Windows. I'm not even sure there is one, except Ctrl+Alt+Delete, and that doesn't always work either.
Ctrl-Alt-Delete is different; it's not an interrupt sequence. The Mac equivalent is Command-Option-Escape. And most notably of all, it's intercepted by the system, so we can't override that.

Originally Posted By: The Almighty Doer of Stuff
Why not use Ctrl+Period? Ctrl+C is used in BoE as Copy, as you said. What if you had a Text Response node and you hit Ctrl+C? Would it know whether to copy the highlighted text or interrupt the node chain? Ctrl+Period isn't used for anything at the moment.
I think Ctrl-Period is non-standard; it could be done though. As for Ctrl-C, there's no problem there: if you're in a Text Response node, then there isn't a special encounter underway (it's paused until you close the dialog), so Ctrl-C will copy the highlighted text.

The way I've implemented it, the interrupt won't work in a dialog anyway.



Maybe Ctrl-Break? I'm not sure if all keyboards have a Break key though.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...