Jump to content

Code Discussion Thread


Celtic Minstrel

Recommended Posts

Exile 3 figures below do not include any names or signs, the written stuff was compiled right into the program, except for the area rectangle names.

L 6,962

M 4,590

S 2,782

 

Modules are bits of town 20 or 66, a house or whatever.

Here is the latest info on the module towns.

0 4 ?

4 24 ?

28 80 location special_locs[40];

108 40 unsigned char spec_id[40];

148 24 location sign [12]

172 2 ?

174 8 location start_locs[4];

182 8 ?

190 8 location exit_locs[4];

198 8 RECT16 in_town_rect;

206 640 preset_items [64]

846 200 preset fields [50]

1,046 12 ?

1,058 420 monster type monsters [30]

1,478 120 terrain modules[15]

1,598 100 terrain rectangles[10]

 

It will take some time to dust off and verify my notes. Certain parts I can't understand.

Link to comment
Share on other sites

  • Replies 990
  • Created
  • Last Reply

Top Posters In This Topic

Well, comparing that with the BoE town_record_type may reveal something...

 

{format is start byte..end byte (num bytes): type name;}

 

town_record_type:

0000..0003 (004): short town_chop_time, town_chop_key;

0004..0019 (016): wandering_type wandering[4]; (equivalent to unsigned char wandering[4][4]wink

0020..0027 (008): location wandering_locs[4];

0028..0127 (100): location special_locs[50];

0128..0177 (050): unsigned char spec_id[50];

0178..0207 (030): location sign_locs[15];

0208..0209 (002): short lighting;

0210..0217 (008): location start_locs[4];

0218..0225 (008): location exit_locs[4];

0226..0233 (008): short exit_specs[4];

0234..0241 (008): Rect in_town_rect; (note that the Mac Rect type is {top,left,bottom,right}, while I believe the Windows RECT type is {left,top,right,bottom})

0242..0881 (640): preset_item_type preset_items[64];

0882..0883 (002): short max_num_monst;

0884..1083 (200): preset_field_type preset_fields[50];

1084..1087 (004): short spec_on_entry,spec_on_entry_if_dead;

1088..1103 (016): short timer_spec_times[8];

1104..1119 (016): short timer_specs[8];

1120..1299 (180): unsigned char strlens[180];

1300..3499 (???): special_node_type specials[100]; (this is 2200 bytes long)

3500..3503 (004): unsigned char specials1,specials2,res1,res2;

3504..3505 (002): short difficulty;

template_town_type: (if BoE had these, that is)

3506..4159 (660): creature_start_type creatures[30];

4160..4279 (120): city_block_type city_block[15]; (these would be what you're calling modules)

4280..4379 (100): city_ter_rect_type city_ter_rect[10];

 

For reference, here's the structure of the various parts.

wandering_type:

(4 bytes): unsigned char monst[4];

preset_item_type:

(2 bytes): location item_loc;

(4 bytes): short item_code,ability;

(4 bytes): unsigned char charges,always_there,property,contained;

preset_field_type:

(2 bytes): location field_loc;

(2 bytes): short field_type;

special_node_type:

(2 bytes): short type,sd1,sd2,pic,m1,m2;

(2 bytes): short ex1a,ex1b,ex2a,ex2b,jumpto;

creature_start_type:

(1 bytes): unsigned char number;

(1 bytes): unsigned char start_attitude;

(2 bytes): location start_loc;

(1 bytes): unsigned char mobile;

(1 bytes): unsigned char time_flag;

(2 bytes): unsigned char extra1,extra2;

(4 bytes): short spec1, spec2;

(2 bytes): char spec_enc_code,time_code;

(4 bytes): short monster_time,personality;

(2 bytes): short special_on_kill,facial_pic;

city_block_type:

(2 bytes): short block_type;

(2 bytes): short block_destroy_time;

(1 bytes): char block_alignment;

(1 bytes): char block_key_time;

(2 bytes): location block_loc;

city_ter_rect_type:

(8 bytes): Rect what_rect;

(1 bytes): unsigned char ter_type;

(1 bytes): unsigned char hollow;

 

 

I can see only a few differences between the BoE town record and the E3 town record: E3 has 10 fewer special spaces per town, E3 does not appear to have the max_num_monst field, and after preset_fields it has 12 bytes of unknown data where BoE has a much larger chunk including entry specials, timers, the lengths of the town strings, the special nodes, and the town difficulty. I would guess that some of those unknown 12 bytes are timers, though clearly not 8 of them, and the rest (if any) are some combination of entry specials, difficulty, and specials1/specials2 (not sure what those do). Though it's possible they are something else entirely. Maybe you can figure it out, not that it matters for BoE.

 

My question to you, then, is: Do you know how the terrain "modules" work?

Link to comment
Share on other sites

Whoa. I just discovered something amazing. The monster_record_type had a field m_name to store the name of the monster, but it seems that it's never used at all! I can't find an instance of either writing to it or reading to it. Instead the monster names are stored in a separate array in the scenario header.

 

The terrain type names are stored in the same way, but the terrain_type_type structure doesn't have a field for the name, so no redundancy there.

Link to comment
Share on other sites

Here is the Small Town E3 Record, note that it is different to the Modular town record:

Write Up: Small Exile 3 Town.

Start Length Data Type Name

0 28

28 80 location special_locs[40];

108 40 unsigned char spec_id[40];

148 26 ?

174 8 location start_locs[4];

182 8 ?

190 8 location exit_locs[4];

198 8 RECT16 in_town_rect;

206 640 preset_items [64]

846 200 preset fields [50]

1046 12 ?

1,058 1,024 unsigned char terrain[32][32];

2,082 32 rect info rect [4]

2,114 120 unsigned char room rect names[4]

2,234 420 monster type monsters [30]

2,654 128 ?

 

No, I don't currently recall exactly how the modules work. I was working on this last year but I can't find a lot of my notes. I can research this easily enough:

Port E3 town 20 into my Exile 3 Template exs file

Create an E3 town record for a modular town

Compare the two and get some ideas.

 

Create an E3 town record, go into a modular town and save the game, then use the save game file.

Link to comment
Share on other sites

Edit:

Delan is a medium sized town, not all the modular towns are small.

I have town 20 imported into my Exile 3 Template, "exthree.exs". I have a save file of the party in Delan. I have this entered into a spreadsheet. Now I need to handle the fact that the save file record concerned must handle towns of any size.

Link to comment
Share on other sites

Quote:
At some point wouldn't it be easier to just write a new game engine from scratch, and make a converter to read in BoE scenarios?

I think that's what will eventually happens.When the remaining bugs will be ironed out, the next step will be, indeed, major rewriting (Celtic Minstrel has already began that).
After releasing a (mostly) bug free version of BoE (a sort of "Classic" Blade of Exile), focus will be on code refactoring.
I don't know when it will happen, though smile

Writing a new engine from scratch is a possibility, but i'm not a programmer enough to know about that ...

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Monied Hexes and Parselmouths
Serious question here:
At some point wouldn't it be easier to just write a new game engine from scratch, and make a converter to read in BoE scenarios?
In fact, that would not be much easier at all. I'm doing very little actual writing of code – mostly I'm just moving code around, changing names, stuff like that. There's some new code, but the majority is still Jeff's original code.

So no, writing a new engine from scratch would not be easier.

Originally Posted By: Chokboyz
Quote:
At some point wouldn't it be easier to just write a new game engine from scratch, and make a converter to read in BoE scenarios?

I think that's what will eventually happens.When the remaining bugs will be ironed out, the next step will be, indeed, major rewriting (Celtic Minstrel has already began that).
After releasing a (mostly) bug free version of BoE (a sort of "Classic" Blade of Exile), focus will be on code refactoring.
I don't know when it will happen, though smile

Writing a new engine from scratch is a possibility, but i'm not a programmer enough to know about that ...
I haven't started the major rewriting – I've only done refactoring.

I don't think I'll be releasing another version that's compatible with the original though (in the sense that the original can load files created by the new version). At this point, the code for saving a scenario simply won't work right, and in fact I've commented it all out so that I can focus on getting it to load correctly.

Once refactoring is done to the point that you can actually play the game (though probably not save changes to scenarios), I'll think about adding features and fixing any remaining bugs. (And I have several things to catch up on in this thread still.)
Link to comment
Share on other sites

Originally Posted By: Shifting Global Mod
Less serious question:
Where the heck does your PDN come from?


Ah, that one grin

It's from Warhammer 40.000. In this board game, young orcs are disciplined and serious, only getting chaotic and brutal when growing up. They tend to regroup in units, calling themselves Chokboyz.
I am not the party type, so when i was young others, often see me as someone serious. One day, some guy, a Warhammer 40.000 player i suppose, told me i was behaving like a Chokboy. That pleased others and rapidly became a nickname. And that kinda sticked since ...

Not the brightest PDN i admit, but i'm used to it smile

Even less serious question:
Why the heck does your PDN changes each time i see it (your avatar gives you though) ? wink

Chokboyz
Link to comment
Share on other sites

Now I ported town 20 (Module Town) and town 120 Delan into the Exile 3 Template. It is found at:

http://www.freewebs.com/ishadnha/exthree.zip

The ten rectangles follow the pattern for "city_ter_rect_type", except for a "10" in the last figure.

0 70 0 0 0 47 0 47 50 0

0 39 0 0 0 39 0 47 55 0

0 6 0 6 0 38 0 41 100 1

0 20 0 7 0 21 0 40 246 0

0 32 0 11 0 32 0 11 104 1

0 7 0 23 0 21 0 24 246 0

0 22 0 19 0 28 0 20 246 0

0 40 0 0 0 47 0 47 50 0

0 23 0 27 0 36 0 28 246 0

0 31 0 29 0 31 0 38 246 10

 

Now that leaves city_block_type, here are the raw figures:

0 40 0 65 3 0 6 20

0 40 255 255 1 0 34 14

0 40 255 255 0 0 17 6

0 34 255 255 0 0 20 16

0 0 255 255 6 0 8 29

0 2 255 255 6 0 16 29

0 30 255 255 0 0 24 36

0 8 255 255 3 0 8 8

0 16 0 60 0 0 35 6

0 16 255 255 3 0 26 5

0 20 0 38 0 0 33 24

0 20 0 70 2 0 34 31

0 70 0 0 0 0 50 50

0 70 0 0 0 0 50 50

0 70 0 0 0 0 50 50

 

Edit:

I figure that the modules are 8*8, so there are 64 of them in module town. They are usually paired for reasons that are not clear. (I thought that I recall them being paired into a wrecked version and a normal version. Have I altered town.dat?)

 

 

Link to comment
Share on other sites

I discovered a few lines of code that will prevent Magic Map from working in a town. The town record contains a field called "special2". If special2 % 10 is equal to 1, Magic Map will fail in that town.

 

The field is never written to, and is only checked in two places: use_item() and do_mage_spell(). So it wouldn't affect Far Sight.

 

Since it's an unused field, we could easily make specials1 and specials2 into bitfield, hence changing the check to something like "if(special2 & 1)". The special 1 field is never written to either, and never checked.

 

 

Ishad, did you put a password on that scenario?

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I discovered a few lines of code that will prevent Magic Map from working in a town. The town record contains a field called "special2". If special2 % 10 is equal to 1, Magic Map will fail in that town.

The field is never written to, and is only checked in two places: use_item() and do_mage_spell(). So it wouldn't affect Far Sight.

Indeed, like m_name[25], those variables are not used. I didn't noticed the magic map (item or spell) failing condition, but that makes sense since, if i remember correctly, you couldn't use magic map on several towns/dungeons in Exile II/III.
I think we can make them into bitfield, but shouldn't the check be removed (or adapted) ?

Originally Posted By: Celtic Minstrel
Ishad, did you put a password on that scenario?

I opened the file without a problem ... I don't think there's any password.

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Even less serious question:
Why the heck does your PDN changes each time i see it (your avatar gives you though) ? wink

Largely for kicks. I enjoy tiny bursts of poetry and esoteric references. Once upon a time, there were multiple members who varied their PDNs regularly, but now it is just Alorael and I. The static and easily recognizable avatar is intentional; I don't mean to be confusing.
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I discovered a few lines of code that will prevent Magic Map from working in a town. The town record contains a field called "special2". If special2 % 10 is equal to 1, Magic Map will fail in that town.

The field is never written to, and is only checked in two places: use_item() and do_mage_spell(). So it wouldn't affect Far Sight.

Indeed, like m_name[25], those variables are not used. I didn't noticed the magic map (item or spell) failing condition, but that makes sense since, if i remember correctly, you couldn't use magic map on several towns/dungeons in Exile II/III.
I think we can make them into bitfield, but shouldn't the check be removed (or adapted) ?
Yes, the check should be adapted to check just one bit rather than dividing by 10 and checking the remainder. As for m_name, I'm now using it (instead of data_store->monst_names).

As for the scenario... it must be that the way you disabled passwords results in an arbitrary password being stored in the file. (The way I did it will do this.) I can't currently open it with my non-password editor, because it's buggy (again), so I'll just have to wait until I've fixed that.

Or if you still have the capability to set passwords, you could set it to 0 and re-upload. That should work.
Link to comment
Share on other sites

The scenario I originally uploaded contained a dodgy version of Module Town, I had altered the original E3 town dat. A new correct version has been uploaded.

Password flags still exist in the scenario, they are just ignored by the latest versions of the editor, and ignored by those versions only. (Ormus also removed the ability to set the password, so a solution won't be that simple.) If you can run the Windows Editor download it at:

http://www.freewebs.com/ishadnha/2009BoEScenarioEditor.zip

If you are on Mac, maybe someone has removed passwords from editors, I don't know. If not, there is hex-editing the towns into a scenario created using the old editor.

 

Edit:

In my exthree.exs, Delan is town 29, it is still called "Town Name", town 30 is Module town. I will have a stab at using my old Scenario Editor to create a password 0 file.

 

Edit:

I whipped a scenario with a password of 0, it contains two towns, Delan and Module Town. It can be found at:

http://www.freewebs.com/ishadnha/ExThreeA.zip

 

Edit, my guesses are:

city_block_type:

(2 bytes): short block_type; means an 8*8 module from module town

(2 bytes): short block_destroy_time;

(1 bytes): char block_alignment; means rotation angle, 90 degrees or whatever

(1 bytes): char block_key_time;

(2 bytes): location block_loc; means the top left corner of the module in the modular town concerned.

 

Edit:

In equating "city_ter_rect_type" with the ten terrain rectangles, it must be remembered that from terrain type 79 onwards E3 terrain is different to the BoE terrain with the same number.

 

Link to comment
Share on other sites

Originally Posted By: Ishad Nha

If you are on Mac, maybe someone has removed passwords from editors, I don't know. If not, there is hex-editing the towns into a scenario created using the old editor.
I've removed passwords from the Mac version, but it's also currently unable to open files, so that doesn't help much.

I'll look at that scenario now to see what I can make of it.

Do you know which town the module town is and what its size is when in the game?
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I've removed passwords from the Mac version, but it's also currently unable to open files, so that doesn't help much.

I'll look at that scenario now to see what I can make of it.

If you really can't open the file, i can remove the password (or set it to whatever you want) on Ishad Nha's first (large) file.

Originally Posted By: Celtic Minstrel
Do you know which town the module town is and what its size is when in the game?

Originally Posted By: Ishad Nha
In my exthree.exs, Delan is town 29, it is still called "Town Name", town 30 is Module town.

Judging from the map, it's a large town.

By the way, thanks Ishad Nha : being able to roam Valorim once again is a nice feeling wink

Hope it helps,
Chokboyz

Edit: Hum, that seems an excellent occasion to complete the debug mode, so here is the last command : Enter Town.

Click to reveal.. (Enter Town case)
case 'T': // Enter a Town
if (in_scen_debug) {
short find_direction_from;
char response[256]="";
sprintf(response,"Enter Town Number (between 0 and %d)", scenario.num_towns -1 );
display_strings(response,"",0,0,0,0,"Which Town ?",-1,130,0);
get_text_response(873,response,0);
i = atoi(response);
if(i>=0 && i < scenario.num_towns ){
if (party.direction == 0) find_direction_from = 2;
else if (party.direction == 4) find_direction_from = 0;
else if (party.direction < 4) find_direction_from = 3;
else find_direction_from = 1;
start_town_mode(i, find_direction_from);
}
}
break;

The direction you enter the town is the direction you are actually turned to (i.e the direction of the last step you took. Default is entering from the down).
The party outdoor location is not updated : to find the town would require scanning (hence shifting) all the outdoors areas ...
Link to comment
Share on other sites

Don't worry, I was able to open the second version.

 

I know that the map in the scenario is in 64x64, but taking into account that there are two versions of every 8x8 rectangle, I would guess that the actual town may be smaller when playing the game – either a medium town or, more likely, a tiny town.

 

Of course, that assumes that all the modules for a single town are contained within that module town. If they aren't, it could be part of a large town.

 

Originally Posted By: Ishad Nha

Edit, my guesses are:

city_block_type:

(2 bytes): short block_type; means an 8*8 module from module town

(2 bytes): short block_destroy_time;

(1 bytes): char block_alignment; means rotation angle, 90 degrees or whatever

(1 bytes): char block_key_time;

(2 bytes): location block_loc; means the top left corner of the module in the modular town concerned.

Hmm... I'm wondering whether block_type would actually be 0 for not destroyed and 1 for destroyed (or something like that). As for your guess on block_alignment – do the modules actually get rotated in Exile 3? Or are you just making a wild guess?

 

Another question: does putting all the non-destroyed modules together edge-to-edge yield the actual town, or do the modules get inserted on top of the existing town terrain at some location in the town?

 

(Suppose this is the module town, with each character being a module; it's 8 modules across by 8 modules down:

Code:
AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz!1@2#3$4%5^6

If you construct by placing modules edge-to-edge, for example:

Code:
ABCDEFGHIJKLMNOP

is there a configuration that yields the original town?

 

OR, is it more like this? Start with a complete normal town that accompanies the module town, and based on various factors, modules are selected from the module town and copied into the normal town, replacing the already-present terrain. Example with a tiny town (dots are the original terrain, other characters are terrain from some module):

Code:
.....................................................................................................................................aaaaaaaa........................aaaaaaaa........................aaaaaaaa........................aaaaaaaa........................aaaaaaaa........................aaaaaaaa........................aaaaaaaa........................aaaaaaaa..................................................................WWWWWWWW........................WWWWWWWW........................WWWWWWWW........................WWWWWWWW........................WWWWWWWW........................WWWWWWWW..........!!!!!!!!......WWWWWWWW..........!!!!!!!!......WWWWWWWW..........!!!!!!!!........................!!!!!!!!........................!!!!!!!!........................!!!!!!!!.....33333333...........!!!!!!!!.....33333333...........!!!!!!!!.....33333333........................33333333........................33333333........................33333333........................33333333........................33333333..........

Which is it? The second seems a lot like an easy way to do complicated terrain changes with very little required effort...)

Link to comment
Share on other sites

I could not open my own scenario in the old Editor because said scenario was made purely on the new Ormus version, hence I have no idea what its password would be. So ExThreeA was created by hex-editing.

"Module Town" is my name for town 20 in Exile 3, it actually has no name. It is not really a town in the usual sense, more a collection of modules.

Modules can be placed anywhere inside a modular town. As for the rotation I am quite sure of it.

When looking at Module Town, if the x and y coordinates of a given spot are both 4 mod 8, then the module contains all squares on the screen except for the right-most column and the bottom-most row.

 

Looking at Delan and at Module town, the map is basically grass with some modules added here and there. Then you have nine valid terrain rectangles.

 

rectangles terrain rectangles

BoE # Exile 3 Name X Y X Y E3 Terrain #

50 Water 0 70 47 47 50 0

55 Water 0 39 47 39 55 0

122 Wall 6 6 41 38 100 1

83 Walkway 7 20 40 21 246 0

126 Wall w. Door 11 32 11 32 104 1

83 Walkway 23 7 24 21 246 0

83 Walkway 19 22 20 28 246 0

50 Water 0 40 47 47 50 0

83 Walkway 27 23 28 36 246 0

83 Walkway 29 31 38 31 246 10

 

Copy the above into Word or whatever and change all the white space in the ten rectangle records into tab stops.

 

50 Water 0 70 47 47 50 0 = invalid rectangle

55 Water 0 39 47 39 55 0 = the shoreline

122 Wall 6 6 41 38 100 1 = the main town wall

83 Walkway 7 20 40 21 246 0 = the west:east walkway

126 Wall w. Door 11 32 11 32 104 1 = door to the Mage's room at the inn.

83 Walkway 23 7 24 21 246 0 = the north walkway

83 Walkway 19 22 20 28 246 0 = walkway in front of inn

50 Water 0 40 47 47 50 0 = the rest of the water

83 Walkway 27 23 28 36 246 0 = walkway to the docks

83 Walkway 29 31 38 31 246 10 = walkway branching off the above

 

0 40 0 65 3 0 6 20 = guardhouse and some walkway near west gate

0 40 255 255 1 0 34 14 = guardhouse and some walkway near east gate

0 40 255 255 0 0 17 6 = guardhouse and some walkway near north gate

0 34 255 255 0 0 20 16 = walkway in center of town

0 0 255 255 6 0 8 29 = private rooms part of the inn, where the mage is

0 2 255 255 6 0 16 29 = main part of the inn, where the people are

0 30 255 255 0 0 24 36 = the docks

0 8 255 255 3 0 8 8 = food shop, Feedstore

0 16 0 60 0 0 35 6 = Delan's Clothery

0 16 255 255 3 0 26 5 = (Archery shop)

0 20 0 38 0 0 33 24 = upper private house

0 20 0 70 2 0 34 31 = lower private house

0 70 0 0 0 0 50 50 = unused module slot

0 70 0 0 0 0 50 50 = unused module slot

0 70 0 0 0 0 50 50 = unused module slot

 

Link to comment
Share on other sites

Originally Posted By: Ishad Nha
"Module Town" is my name for town 20 in Exile 3, it actually has no name. It is not really a town in the usual sense, more a collection of modules.
Sorry, what I meant is, what is the town that those modules belong to? Do they belong to Delan? They don't look like they all do, at least.

I noticed some spaces in the Module town are cave floor. Would those be treated as "transparent" spaces? Or is that a translation error?

Originally Posted By: Ishad Nha


rectangles terrain rectangles
BoE # Exile 3 Name X Y X Y E3 Terrain #

50 Water 0 70 47 47 50 0
55 Water 0 39 47 39 55 0
122 Wall 6 6 41 38 100 1
83 Walkway 7 20 40 21 246 0
126 Wall w. Door 11 32 11 32 104 1
83 Walkway 23 7 24 21 246 0
83 Walkway 19 22 20 28 246 0
50 Water 0 40 47 47 50 0
83 Walkway 27 23 28 36 246 0
83 Walkway 29 31 38 31 246 10
Um... you have 7 headers there, but each line has 8 fields. What's the other field? (I'm guessing it's the last field you omitted.)
Link to comment
Share on other sites

I suspect that the type 0 bits are "transparent", they are replaced by the default terrain. Presumably the default is grass.

My spreadsheet shows 57 named modular towns:

Delan, Delis, Pergies, Inn of Blades, Silvar, Colchis, Farport, Port Townsend, Marish, Bavner, Hectar, Kuper, Fenris Port, Softport, Arrival Platform, Kneece, Gidrik, Golddale, Porter's Retreat, Bolton, Libras, Lost Isle, Storm Port, Gorst, Gebra, Aminro, Angel's Rest, Lennus, Squiggus, Bengaro, Dellston, Poulsbo, Appleton, Malloc, Isolated Inn, Dorngas, Calloc, Wainscotting, Bremerton, Spineridge, Mernia, Greendale, Tevrono, Execa, Vila, Torria, Northern Golem Spire, Southern Golem Spire, Eastern Golem Spire, Western Golem Spire, Moon, Draigoth, Erox, Manara, Ovdipur, Dellskeep, Wyvern Pass.

I suspect that they all use modules from E3 town 20. As I recall the town 66 looked like a second Module town, but its terrain was cave not surface.

There are also 23 blank modular towns.

 

As for block_alignment, this is how I understand it:

0 -

1 90*

2 180*

3 270*

6 upside down

(An asterisk, *, means degrees.)

Edit:

For a list of the towns, download:

http://www.freewebs.com/ishadnha/E3ScenarioDataRecords.zip

 

The spreadsheet used here is:

http://www.freewebs.com/ishadnha/E3SaveTownRecordDecryptor.zip

You start E3 and go into a modular town, then you save the game. You open the save game file in Hexplorer, and follow the instructions given in the spreadsheet.

You open the exs file in another copy of Hexplorer and paste in the data generated by the spreadsheet. The pasting is done into a new, blank town. This avoids the need to alter the town data size records at the start of the exs file.

 

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Alcritas
Last missile weapon in a group that possess special abilities will fail when fired (note : upon testing only the special ability fails to happens) and last stack of an ordinary thrown item that is placed immediately prior to a stack of another missile weapon with a special ability in that PC’s inventory will gain the special ability of the adjacent missile weapon.


The problem was that the function removed a missile ammo just before doing the firing. The last missile special would then be the next stack one (arrows/missiles are stored together). If there's no missile after the stack, then the special would be nothing (since you can't give missile special to a non-missile item) for the last missile, hence the failing of the last special.

Here is my corrected fire_missile() function (i only displaced the ammo removing functions to proper location) :
[...]
There are two locations for the functions because we need to remove ammo when it's an exploding arrow (first case) and when it's not (last case). Note that i placed the remove ammo functions in a way that doesn't remove ammo if the target is out of range or not in line of sight (originally you would lose a missile in both case ... that didn't made sense for me since you don't fire anything). I always modified the position of exploding arrow code so that you can no longer fire everywhere on the map even if out of range or not in sight.
Okay, this confused me a little at first, because the exploding arrows code was in a different place than in my code, but I've now implemented this change. However, I did it a little differently to avoid duplication of code:

Click to reveal.. (My version)

void fire_missile(location target) {
short r1, r2, skill, dam, dam_bonus, hit_bonus, range, targ_monst, spec_dam = 0,poison_amt = 0;
short skill_item,m_type = 0;
cPopulation::cCreature *cur_monst;
bool exploding = false;

skill = (overall_mode == MODE_FIRING) ? ADVEN[current_pc].skills[7] : ADVEN[current_pc].skills[6];
range = (overall_mode == MODE_FIRING) ? 12 : 8;
dam = ADVEN[current_pc].items[ammo_inv_slot].item_level;
dam_bonus = ADVEN[current_pc].items[ammo_inv_slot].bonus + minmax(-8,8,ADVEN[current_pc].status[1]);
hit_bonus = (overall_mode == MODE_FIRING) ? ADVEN[current_pc].items[missile_inv_slot].bonus : 0;
hit_bonus += stat_adj(current_pc,1) - can_see(pc_pos[current_pc],target,0)
+ minmax(-8,8,ADVEN[current_pc].status[1]);
if ((skill_item = pc_has_abil_equip(current_pc,41)) < 24) {
hit_bonus += ADVEN[current_pc].items[skill_item].ability_strength / 2;
dam_bonus += ADVEN[current_pc].items[skill_item].ability_strength / 2;
}

// race adj.
if (ADVEN[current_pc].race == 1)
hit_bonus += 2;

if (ADVEN[current_pc].items[ammo_inv_slot].ability == 172)
exploding = true;

if (dist(pc_pos[current_pc],target) > range)
add_string_to_buf(" Out of range.");
else if (can_see(pc_pos[current_pc],target,0) == 5)
add_string_to_buf(" Can't see target. ");
else {
// First, some missiles do special things
if (exploding) {
take_ap((overall_mode == MODE_FIRING) ? 3 : 2);
add_string_to_buf(" The arrow explodes! ");
run_a_missile(pc_pos[current_pc],target,2,1,5,
0,0,100);
start_missile_anim();
add_missile(target,2,1, 0, 0);
do_missile_anim(100,pc_pos[current_pc], 5);
place_spell_pattern(rad2,target,
50 + ADVEN[current_pc].items[ammo_inv_slot].ability_strength * 2,TRUE,current_pc);
do_explosion_anim(5,0);
end_missile_anim();
handle_marked_damage();
} else {

combat_posing_monster = current_working_monster = current_pc;
draw_terrain(2);
void_sanctuary(current_pc);
//play_sound((overall_mode == MODE_FIRING) ? 12 : 14);
take_ap((overall_mode == MODE_FIRING) ? 3 : 2);
missile_firer = current_pc;
r1 = get_ran(1,0,100) - 5 * hit_bonus - 10;
r1 += 5 * (ADVEN[current_pc].status[6] / 3);
r2 = get_ran(1,1,dam) + dam_bonus;
sprintf ((char *) create_line, "%s fires.",(char *) ADVEN[current_pc].name); // debug
add_string_to_buf((char *) create_line);

switch (overall_mode) {
case MODE_THROWING:
switch (ADVEN[current_pc].items[ammo_inv_slot].item_level) {
case 7:m_type = 10;break;
case 4:m_type = 1;break;
case 8:m_type = 5;break;
case 9:m_type = 7;break;
default:m_type = 10;break;
}
break;
case MODE_FIRING: case MODE_FANCY_TARGET:
m_type = (ADVEN[current_pc].items[ammo_inv_slot].is_magic() == TRUE) ? 4 : 3;
break;
}
run_a_missile(pc_pos[current_pc],target,m_type,1,(overall_mode == MODE_FIRING) ? 12 : 14,
0,0,100);

if (r1 > hit_chance[skill])
add_string_to_buf(" Missed.");
else if ((targ_monst = monst_there(target)) < T_M) {
cur_monst = &univ.town.monst.dudes[targ_monst];
spec_dam = calc_spec_dam(ADVEN[current_pc].items[ammo_inv_slot].ability,
ADVEN[current_pc].items[ammo_inv_slot].ability_strength,cur_monst);
if (ADVEN[current_pc].items[ammo_inv_slot].ability == 176) {
ASB(" There is a flash of light.");
cur_monst->m_d.health += r2;
}
else damage_monst(targ_monst, current_pc, r2, spec_dam, 1300);

//if (ADVEN[current_pc].items[ammo_inv_slot].ability == 33)
// hit_space(cur_monst->m_loc,get_ran(3,1,6),1,1,1);

// poison
if ((ADVEN[current_pc].status[0] > 0) && (ADVEN[current_pc].weap_poisoned == ammo_inv_slot)) {
poison_amt = ADVEN[current_pc].status[0];
if (pc_has_abil_equip(current_pc,51) < 24)
poison_amt++;
poison_monst(cur_monst,poison_amt);
}

}
else hit_space(target,r2,0,1,0);

}

if (ADVEN[current_pc].items[ammo_inv_slot].variety != 25) {
if (ADVEN[current_pc].items[ammo_inv_slot].ability != 170)
ADVEN[current_pc].items[ammo_inv_slot].charges--;
else ADVEN[current_pc].items[ammo_inv_slot].charges = 1;
if ((pc_has_abil_equip(current_pc,11) < 24) && (ADVEN[current_pc].items[ammo_inv_slot].ability != 170))
ADVEN[current_pc].items[ammo_inv_slot].charges--;
if (ADVEN[current_pc].items[ammo_inv_slot].charges <= 0)
take_item(current_pc,ammo_inv_slot);
}

}

combat_posing_monster = current_working_monster = -1;
ADVEN[current_pc].status[0] = move_to_zero(ADVEN[current_pc].status[0]);
print_buf(); // Currently these three lines will be executed if the missiles exploded, whereas formerly they would not have. Should they be in an "if(!exploding)" block?

}
In particular, consider the red section of the code.


Originally Posted By: Chokboyz
Edit1 : Concerning the "When the party is split up, Affect PC special nodes should only affect the active PC" problem, the only affected nodes are : Affect Health, Affect SP, Affect Skill Points, Kill/Raise Dead (Raise (resp. Kill) revives (resp. obliterates) the whole party ... that obviously shouldn't be changed for compatibility reasons. The compatibility switch for legacy ressurection should be adapted too), Give Mage Spell, Give Priest Spell, Affect Statistic.
A possible approach could be to use an extra (or pic) value to specify if the node is to only affect the present pc or the whole party. I think simply "fixing" this (i.e correcting the functions) is asking for compatibility problem. I may be wrong though ...
Honestly? We're eventually rewriting the scenario format. Preserving legacy behaviour can be done in the function to convert an old-format scenario to a new-format one in memory.

In any case, it doesn't make any sense for party members to be affected when they're not even present. That's why I think this should be fixed. (We can make an exception for the Kill/Raise node, I guess, but add a parameter to cancel the exception.)

Originally Posted By: Chokboyz
The three Affect Stealth, Affect Firewalk and Affect Flight nodes correctly give the power to the whole party (i have to investigate Stealth as i don't know what it does).
This is because these are not character statuses. They are party statuses stored in an SDF.

Originally Posted By: Chokboyz

The game displays no more than 10 areas description out of the 16 proposed (Alcritas)

This is a little more complicated, depending on the size of the town you can use 4 (small), 10 (medium) or 12 (large) maximum area descriptions.

In GRAPHICS.cpp in the function draw_text_bar(), the hardcoded array num_rect[3] = {12,10,4} is the cause of this limitation.
Not seeing why one couldn't use all the 16 area descriptions, i remove the array and replace the check for (i = 0; i < num_rect[town_size]; i++) by for (i = 0; i < 16; i++). Don't hesitate to tell me if i've missed something.
No, that was probably just a relic from Exile 3 – perhaps the three town sizes in E3 did not all have the same number of room rects available. I've adopted the fix.

Originally Posted By: Chokboyz
- The Spell “Resurrection” (note : and Raise Dead) does not require a Resurrection Balm, despite advertisements to the contrary.

I wonder if we should fix this one (any broken compatibility ?), but since it may prevent the spell from being cast...
In function cast_priest_spell(), case 40 and 50, find the line if ((item = adven[pc_num].hasAbil(13)) == 16) { and replace it by if ((item = adven[pc_num].hasAbil(160)) == 24) {. The add_to_buffer(...) should be replaced by a sprintf(c_line,"Need ...") to prevent redundant Spell: Resurrection lines to be printed.
The game was (originally) checking if an item causing fear was present in slot 17 of the inventory (a leftover of Exile II, when you had only 16 slots in the inventory !!!), thus having a Cause Fear weapon in slot 17 prevent the pc from casting Resurrection.
Don't worry about compatibility here. Requiring Resurrection Balm is part of the description of the spell – if it's not required, Resurrection Balm becomes useless.

Okay... it seems that the problem is quite different in the Mac code. First of all, it was case 40 and 56, not 40 and 50 – was that a typo or is it actually different on Windows? Second, the if statement you mention is already in the correct form; however, after checking for Resurrection Balm, it goes on to cast the spell regardless of whether it was found sets spell_num to 500 so that the following check for the spell number being 40 or 56 will fail.

So it would appear that it was already correct(ed) in the Mac code. I'm not sure if the bug existed in the first place, but it certainly doesn't now.

It also didn't help that the function was called do_priest_spell rather than cast_priest_spell... rolleyes

Originally Posted By: Chokboyz
Note that such leftovers are present in the do_mindduel() function (if (adven[pc_num].hasAbilEquip(53) < 16 should read if (adven[pc_num].hasAbilEquip(53) < 24) and in statAdj() in the line if (hasAbilEquip(99) < 16) tr++; (moreover, ability 99 doesn't exists ... this object is supposed to grant a damage bonus when the skill used is intelligence (mostly magic). With what should we replace it ?)
For the first, that check does not seem exist at all in my do_mindduel() function. Perhaps it should be added? Could you show me the code for what happens if the check fails?

For the second, my version of stat_adj checks for exactly 3 abilities, and 99 is not one of them. Here's the code:
Code:
short stat_adj(short pc_num,short which){    short tr;    tr = skill_bonus[ADVEN[pc_num].skills[which]];    if (which == 2) {        if (ADVEN[pc_num].traits[1] == TRUE)            tr++;        if (pc_has_abil_equip(pc_num,40) < 24)             tr++;    }    if (which == 0) {        if (ADVEN[pc_num].traits[8] == TRUE)            tr++;        if (pc_has_abil_equip(pc_num,38) < 24)             tr++;    }    if (which == 1) {        if (pc_has_abil_equip(pc_num,39) < 24)             tr++;    }    return tr;}
Does that help at all?

Originally Posted By: Chokboyz
Edit3 : Should stop editing the same post crazy
The Random Number ? Node is affected by the "100 % means almost always" bug (and no, it doesn't happen on a negligible set wink ).
In Ifthen_spec() (SPECIALS.cpp), the third case (132), put a less or equal instead of less in the random check.
Oh my. I think I'll just search for all instances of "get_ran(1,0,100)" (in all three programs) and replace them with "get_ran(1,1,100)". It's simpler that way. If you know of some instance of "get_ran(1,0,100)" that shouldn't be so replaced, speak up. (It may help to look at revision 33 to compare my changes.)

Note that I haven't changed any get_ran() calls where the third number is not 100. There are many other places where he goes from 0 to x – I'm not really sure if it should always be 1 to x or not.


Originally Posted By: Chokboyz
The safety check (always picks the first character) is the most simple one : find the (huge) handle_action() function, find the lines // Begin : talking to someone and in the loop add a break; just after else switch (c_town.monst.dudes.monst_start.personality){
default:
start_talk_mode(i,c_town.monst.dudes.monst_start.personality,c_town.monst.dudes.number,
c_town.monst.dudes.monst_start.facial_pic);
did_something = FALSE;
need_redraw = FALSE;
break;
}

(the switch can be safely removed. I suppose it was here for a different personnalities features that didn't make it ...)
And yet even if the ability to change personalities were implemented, the switch would not be necessary. I didn't add anything here – I simply removed the line "switch (c_town.monst.dudes.monst_start.personality)" (retaining the brace) and the line "default:". Without the switch, the break that's already present will break out of the loop rather than the switch.

Originally Posted By: Chokboyz
Quote:
About graphics: From what I remember, the Windows graphics are in fact brighter than the Mac graphics to account for differing gamma settings. What would you think about using the Mac graphics for the Windows version? If necessary you could probably adjust gamma manually, though that'd probably be hard (maybe upon loading an image). But I suspect it may no longer be necessary to adjust gamma, since modern computers (at least Macs) have ways of doing this automatically or something... I think...

Indeed, Windows graphics are brighter than Mac ones (it is flagrant when using custom scenarios with custom graphics done on Mac). Either we use the Mac or Windows one, but that should be normalized smile Like you , I think that adjusting gamma is no longer necessary; using a corrected bmp should suffice.
I have uploaded the Mac graphics here. With respect to what's on which sheet, the version there is not quite the same as either the Windows or Mac version – it could be considered a proposal for rearranging the sheets a little. Alternatively, you could just copy-paste from the those sheets to replace the existing Windows sheets. For the background patterns, the Mac version stores them all separately rather than on a sheet – I combined every pattern in all three programs, including some that may not be used, into a single sheet.

Originally Posted By: Chokboyz
Edit :
Originally Posted By: Alcritas
According to the BOE Manual, the Affect Party — Do Damage special node allows the scenario designer to vary the Pict. box. Doing so will supposedly only cause damage to the PC who triggers the special, if the party is in combat node. Unfortunately, this does not work.


The node now behaves as in the help file (if pict is 1, in combat mode and no Select Pc node has been used, only damage the active character).

Simply change the case 81 in affect_spec() (SPECIALS.cpp) to

case 81:
r1 = get_ran(spec.ex1a,1,spec.ex1b) + spec.ex2a; //get random damage
if (pc < 0) { //has a PC been selected
if(spec.pic == 1 && overall_mode == MODE_COMBAT) //if not and in combat and pict value is 1
adven[current_pc].damage(r1,spec.ex2b,0); //damage the current active pc
else
adven.damage(r1,spec.ex2b);//else damage everyone
}
else adven[pc].damage(r1,spec.ex2b,0);//if a pc has been selected, just damage the pc
break;

The code needs to be adapted for the Mac version, because here it use the c++ rewriting of Ormus. (just use the original damage functions).
I'll fix this too, momentarily.




On another note, one thing I've been thinking about is string lengths. Currently, the game can't handle strings longer than 255 characters, because the str_len arrays holding the string lengths are of type unsigned char. If we changed it to unsigned short, it could handle strings of up to 65535 characters; however, I think that's a bit much. So, I though we could restrict it a little more, but make up for that by including format flags. For example, if we were fine with restricting the string length to 1023 characters, we would have 6 unused bits available for formatting.

The most significant bit, then, could indicate that the string should be drawn framed. That would be simple to implement – you'd just have to set the item flag to 1 in cd_create_custom_dialog. The next three bits could specify that the text be drawn in colour – one bit for red, one for green, one for blue. And the next 2 bits could specify that the text be indented.

Such a change would not have to wait for the format rewrite – adding it would not actually affect legacy compatibility. However, it would be impossible to use until the scenario file format supports it. I'm just putting it forth as an idea. Actually, I think I'll also add it to the Google Code issues page so that it's not forgotten.

Click to reveal.. (More notes on this)

If the change is implemented, and size represents the string length, then:
  • whether it is framed would be "size & 32768",
  • the colour would be "(size & 28672) >> 12",
  • the indent would be "(size & 3072) >> 10", and
  • the actual length would be "size & 1023",
if my calculations are correct.

Colours would be:
  • 0 – grey (because black would be invisible against the background,
  • 1 – blue,
  • 2 – green,
  • 3 – cyan,
  • 4 – red,
  • 5 – magenta,
  • 6 – yellow,
  • 7 – white.


Indents would be something like:
  • 0 – none,
  • 1 – 10 pixels,
  • 2 – 15 pixels,
  • 3 – 20 pixels.
That could vary depending on which values work well.
Link to comment
Share on other sites

Originally Posted By: Ishad Nha
If that is a Windows exs file that you are trying to load, you can always load it into the official clunky old 1997 Spiderweb Editor and save it in Mac format. Then you can open it in a more modern editor.
Actually, loading a scenario works fine. It's a savegame file I'm trying to load.
Link to comment
Share on other sites

A couple things: Requiring the Resurrection Balm for Raise Dead and Resurrect would break some old scenarios. Knowing it doesn't do anything and not wanting to rip the player off with useless recipes and items, some designers did not include the recipe or the balm itself in their scenarios.

 

Perhaps instead, an SDF could be set in each scenario that determines whether those spells require the balm in that scenario?

 

Also, perhaps instead of including only one version of the graphics, perhaps a switch could be put in the preferences for darker or lighter graphics, and perhaps override it in the new scenario format, so that older scenarios can be played with default terrain matching the custom terrain, and so that designers can choose the graphics they prefer for their scenarios.

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Thuryl
You know what would be a good use for this? An option to specifically turn off damage sounds -- or better still, force them to play asynchronously. At the moment, walking on damage floors or damaging fields takes forever because you have to wait for the *zap* *zap* *zap* *zap* *zap* *zap* as all your characters get hit every single step.

Originally Posted By: Celtic Minstrel
It could use, say, SDF(305,7).

I implemented a preference option, using SDF[305][7], that does something like that.
What effect would you (as in players) prefers ?
  • Skip all delay between sounds (speeds up boom spaces) That's the one i use.
  • Play the shortest sound (i.e the sound played when a shade hits you)
  • Play no sounds (then don't count on reading the number)
  • Skips everything (as in "No frill effects" but applied to boom spaces)
Could I see your code for this?

Oh, and speaking of preferences – I implemented the "show startup splash" option (though it's a hidden preference so far, not accessible from the dialog), but I didn't use a stuff done flag for it. Instead, I declared a global variable show_startup_splash to hold this preference.

Originally Posted By: Chokboyz
I've also corrected the damaging terrains so that they display the right damage type/play the right sound when stepped on (previously the fire damage type was always used). I think this is a Windows-only bug, but if it also occurs on Mac, i'll post the fix.
I don't think it occurs on Mac – I vaguely remember stepping on cold terrain and seeing the cold damage icon. Which function does it occur in, so I can check?

Originally Posted By: Chokboyz
The party status (Flying, Firewalk, Stealth, Detect Life) were displayed in black, making them hard to read (or even notice). I fixed that too (a Windows-only bug ?).
As far as I can tell, they aren't displayed at all, even in black. Could you show your code?

I also discovered that for some reason the game isn't loading strings correctly. I'll have to look into that... it's slightly odd since the editor doesn't have a problem, but then it could have to do with the fact that the game often loads the strings "as needed" rather than all at once.

Originally Posted By: Chokboyz
Finally, a relic from the past, the Exile I/II (maybe III) "Map unavailable." feature is now implemented. I used a SDF to test it, but it's obvious the town record type would have to be changed to use it. Something that can't be done without breaking compatibility, i fear smirk
So i thought, why not make a node that displays/hide the map ? That way, even outdoors map can be hidden. And the town record type is left untouched ...
First, could you post your code? Second, there are some unused fields in the town record. One of this could be put to use for this feature. We could add the node as well, to toggle whether the map is available.

I don't think we should add the ability to hide outdoor maps though. I think I mentioned my reasoning for that somewhere already.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
a "map" of the save file format

The save_file function is helpfull here.
First the three flags town_save;in_scen;save_map (short type in windows/flag_type on mac), then the party (size party_record_type), setup (size setup_save_type), pcs (size 6* pc_record_type), outdoor data (size out_info_type), then town if town_save (size current_town_type + big_tr_type + stored_items_list for win/town_item_list for mac), stored items (size 3*stored_items_list), maps if save_map (size stored_town_maps_type + stored_outdoor_maps_type) and finally sfx and misc (?) (size 2 * (64 * 64)).
With regards to the flags, I have added a check to see if the first flag is 0x0B0E. If it is, I will treat the file as a new-format save file. The three flags will then follow as normal; after that, it may be useful to add a version flag. Beyond that, I'm not entirely sure.

Originally Posted By: Chokboyz
Notice that stored_items_list and town_item_list are the same structure and be (as it has been done by Ormus) merged into one.
These structures no longer even exists in my version – I replaced them with an array with the same time as their sole member. (This means that the party record has a [3][100] or whatever array of items for the storage locations.)

Originally Posted By: Celtic Minstrel

Oh, and I propose making the version 2.0.0, unless that's taken. I believe that would mean doing this upon saving:
Code:
scenario.format.ver[0] = 2;scenario.format.ver[0] = 0;scenario.format.ver[0] = 0;

(Note: I split out the header into a separate structure since it's the only part that will remain common between the two formats. Here's the structure:
Code:
struct scenario_header_flags {    unsigned char flag1, flag2, flag3, flag4;    unsigned char ver[3],min_run_ver,prog_make_ver[3];};
I'm not entirely sure what the difference between ver, min_run_ver, and prog_make_ver is; I'll have to look into that sometime.)
I've now realized that ver is in fact the scenario version, so it should be scenario.format.prog_make_ver that is set to 2 to indicate new version. I also moved num_towns to the header flags structure to solve alignment problems.

Originally Posted By: Chokboyz
Edit: Hum, that seems an excellent occasion to complete the debug mode, so here is the last command : Enter Town.

Click to reveal.. (Enter Town case)
case 'T': // Enter a Town
if (in_scen_debug) {
short find_direction_from;
char response[256]="";
sprintf(response,"Enter Town Number (between 0 and %d)", scenario.num_towns -1 );
display_strings(response,"",0,0,0,0,"Which Town ?",-1,130,0);
get_text_response(873,response,0);
i = atoi(response);
if(i>=0 && i < scenario.num_towns ){
if (party.direction == 0) find_direction_from = 2;
else if (party.direction == 4) find_direction_from = 0;
else if (party.direction < 4) find_direction_from = 3;
else find_direction_from = 1;
start_town_mode(i, find_direction_from);
}
}
break;

The direction you enter the town is the direction you are actually turned to (i.e the direction of the last step you took. Default is entering from the down).
The party outdoor location is not updated : to find the town would require scanning (hence shifting) all the outdoors areas ...
I should probably implement this debug mode. Could you give me some information about it?

Originally Posted By: The Almighty Doer of Stuff
A couple things: Requiring the Resurrection Balm for Raise Dead and Resurrect would break some old scenarios. Knowing it doesn't do anything and not wanting to rip the player off with useless recipes and items, some designers did not include the recipe or the balm itself in their scenarios.

Perhaps instead, an SDF could be set in each scenario that determines whether those spells require the balm in that scenario?
I don't really think this is such a good idea. For such scenarios, they could always use the character editor to gain the necessary items. We could, I suppose, add something to the conversion code that automatically sets a reserved SDF to 1 when loading in a party who is in an old-format scenario (and sets it to 0 when they're in a new-format scenario). However, I think it would be better just to fix the scenarios themselves.

Originally Posted By: The Almighty Doer of Stuff
Also, perhaps instead of including only one version of the graphics, perhaps a switch could be put in the preferences for darker or lighter graphics, and perhaps override it in the new scenario format, so that older scenarios can be played with default terrain matching the custom terrain, and so that designers can choose the graphics they prefer for their scenarios.
This would be a lot of work for minimal gain, I think. There is almost no difference between the two sets of graphics, and the Mac version is presumably how they were intended to look. Changing to dark graphics only would not break compatibility with older scenarios either. Also, having these two separate sets of graphics has meant that custom graphics sometimes don't match across platforms, so eliminating that seems like a good idea.

If someone really prefers the lighter graphics, all they have to do is edit the graphics files so that they hold the lighter graphics rather than the darker ones.
Link to comment
Share on other sites

If your reason for that is passwords, it won't be an issue. Passwords are no longer required to edit scenarios (though I would still consider requiring them to enter debug mode).

 

As a sort of compromise, perhaps we could consider making Resurrection Balm required for Resurrection but optional for Raise Dead? Or possible casting without resurrection balm could have a higher chance of failure? I dunno, but I personally think it's best to simply fix it.

 

One possible conversion-based fix for this issue would be to add the Resurrection Balm recipe to a party if anyone has the spell Raise Dead (or Resurrection), when loading a party in an old-format scenario; though, don't much like that idea either...

 

In any case, if we do have a compatibility switch, I think it should be something that's silently handled by the game, rather than something the player can control. You're right that it would be easy to simply set an SDF, preferably a reserved one; this could be done when loading the scenario. And then the player doesn't really need to think about whether they need the switch enabled – if they're in an old-format scenario, it automatically will be.

 

 

 

Are there any scenarios that actually removed Resurrection Balm from their item list? Because if there are, that's something we would want to take into account. It wouldn't affect their ability to make it if they have the recipe, but it would prevent them from adding it in the character editor unless we make a special allowance for it.

 

 

As for city blocks, yes, Ishad, they would be one of the many Exile 3 remnants in the Blades code. I intend to re-implement them sometime (quite likely in a very different way though ;)).

Link to comment
Share on other sites

The two real reasons to have modules that I can think of:

save space in the exs file, in Exile 3 the saving per town was 4,590 - 1,698 = 2,892 Bytes

make it easier to design the less important towns.

 

They also had provision for random occurring terrain types, like the small stalagmites in the Arrival Platform.

In city_ter_rect_type,if unsigned char hollow was 2 or 3, it seems that random placement of the terrain type could occur inside the prescribed rectangle.

 

Link to comment
Share on other sites

So hollow = 0 means fill the rect, hollow = 1 means just fill the border, and hollow = 2 or 3 means randomly place? But then, what's the difference between 2 and 3?

 

The reason I can think of to have modules is quite different: it makes it easier for towns to evolve without needing to make multiple copies of the entire town.

 

 

On the topic of dialog controls randomly not being drawn: I discovered that the target GWorld and the source GWorld were the same, making me wonder why it even works at all. In fact, the source and target GWorlds are the same in many, many other cases as well.

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Okay, this confused me a little at first, because the exploding arrows code was in a different place than in my code, but I've now implemented this change. However, I did it a little differently to avoid duplication of code

I've deleted the duplicated code in fire_missile(). The third last line can be left in the exploding case (the first is reinitializing a variable used in normal missile, the second reduces the amount of poison on weapons and the third print the buffer).

Concerning the Resurrection Balm, i will not fix it for now as it breaks compatibility. However, a check in the function will make it functionnal for the new scenario format.

Originally Posted By: Celtic Minstrel
It also didn't help that the function was called do_priest_spell rather than cast_priest_spell...

Sorry about that, i was in the combat_cast_priest_spell() function when writing the post grin

Originally Posted By: Celtic Minstrel
For the second, my version of stat_adj checks for exactly 3 abilities, and 99 is not one of them.

Incredibly enough, windows version of the code didn't do any check with these three values ... The Strengh, Dexterity or Intelligence item abilities were then utterly useless.

Here is my version of do_mindduel() :

Click to reveal.. (do_mindduel)
void do_mindduel(short pc_num,creature_data_type *monst)
{
short i = 0,adjust,r1,r2,balance = 0;

adjust = (adven[pc_num].level + adven[pc_num].skills[2]) / 2 - monst->m_d.level * 2;

if (adven[pc_num].hasAbilEquip(53) < 24)
adjust += 20;
if (monst->attitude % 2 != 1)
make_town_hostile();
monst->attitude = 1;

add_string_to_buf("Mindduel!");
while ((adven[pc_num].isAlive()) && (monst->active > 0) && (i < 10)) {
play_sound(1);
r1 = get_ran(1,0,100) + adjust;
r1 += 5 * (monst->m_d.status[9] - adven[pc_num].status[9]);//dumbfound status
r1 += 5 * balance;
r2 = get_ran(1,1,6);
if (r1 < 30) {
sprintf((char *)c_line, " %s is drained %d.",adven[pc_num].name,r2);
add_string_to_buf((char *) c_line);
monst->m_d.mp += r2;
balance++;
if (adven[pc_num].cur_sp == 0) {
adven[pc_num].status[9] += 2;
sprintf((char *) c_line," %s is dumbfounded.",adven[pc_num].name);
add_string_to_buf((char *) c_line);
if (adven[pc_num].status[9] > 7) {
sprintf((char *) c_line," %s is killed!",adven[pc_num].name);
add_string_to_buf((char *) c_line);
adven[pc_num].kill(2);//dead status
}
}
else adven[pc_num].cur_sp = max(0,adven[pc_num].cur_sp - r2);
}
if (r1 > 70)
{
sprintf((char *)c_line, " %s drains %d.",adven[pc_num].name,r2);
add_string_to_buf((char *) c_line);
adven[pc_num].cur_sp += r2;
balance--;
if (monst->m_d.mp == 0)
{
monst->m_d.status[9] += 2;
monst_spell_note(monst->number,22);
if (monst->m_d.status[9] > 7) kill_monst(monst,pc_num);
}
else monst->m_d.mp = max(0,monst->m_d.mp - r2);
}
print_buf();
i++;
}
}

The item ability 53 is, of course, will.

Originally Posted By: Celtic Minstrel
Oh my. I think I'll just search for all instances of "get_ran(1,0,100)" (in all three programs) and replace them with "get_ran(1,1,100)". It's simpler that way. If you know of some instance of "get_ran(1,0,100)" that shouldn't be so replaced, speak up.

I don't know if some needs to be left alone, i assumed the dice in BoE was 101-sided ... If i ever gather the courage, i will look every instance of get_ran to see if it needs fixing. It won't happens anytime soon, though.

Originally Posted By: Celtic Minstrel
Such a change would not have to wait for the format rewrite – adding it would not actually affect legacy compatibility. However, it would be impossible to use until the scenario file format supports it. I'm just putting it forth as an idea. Actually, I think I'll also add it to the Google Code issues page so that it's not forgotten.

Seconded.

Originally Posted By: The Almighty Doer of Stuff
Also, perhaps instead of including only one version of the graphics, perhaps a switch could be put in the preferences for darker or lighter graphics

I was thinking of such a thing and will see what can be done. It's not top priority though smile

Originally Posted By: Celtic Minstrel
Could I see your code for this?

End of boom_space() function :

Click to reveal..
if ((cartoon_happening == FALSE) && (dest_rect.right - dest_rect.left >= 28)
&& (dest_rect.bottom - dest_rect.top >= 36)) {
sprintf((char *) dam_str,"%d",damage);
text_rect = dest_rect;
text_rect.top += 10;
if ((damage < 10) && (dest_rect.right - dest_rect.left > 19))
text_rect.left += 2;
OffsetRect(&text_rect,-4,-5);

if ((type == 1) || (type == 4))
WinBlackDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);
else WinDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);
}

if(party.stuff_done[305][7] > 0)
play_sound(-sound_to_play[sound]);
else{

play_sound(sound_to_play[sound]);

if ((sound == 6) && (fast_bang == 0))
Delay(12, &dummy);

Delay(10,&dummy);
if (fast_bang == 0) {
del_len = PSD[306][6] * 3 + 4;
if (play_sounds == FALSE)
Delay(del_len, &dummy);
}
}

redraw_terrain();
if ((cartoon_happening == FALSE) && (overall_mode > 9) && (overall_mode != 35) && (overall_mode != 36) && (overall_mode != 50))
draw_pcs(center,1);
}

This is temporary though, as i've not decided what solution to implement.
Originally Posted By: Celtic Minstrel
I don't think it occurs on Mac – I vaguely remember stepping on cold terrain and seeing the cold damage icon. Which function does it occur in, so I can check?

In check_special_terrain(), case 2, 3 and 4 of the ter_special switch, hit_party(r1,1) should read hit_party(1,dam_type). I think this one is Windows specify, though.

Originally Posted By: Celtic Minstrel
As far as I can tell, they aren't displayed at all, even in black. Could you show your code?

Click to reveal.. (put_text_bar code)
void put_text_bar(char *str)
{
char status_str[256];
short xpos = 205;
HDC hdc;
HBITMAP store_bmp;
RECT text_rect = {5,3,279,21};
COLORREF x = RGB(0,0,0),y = RGB(255,255,255);

rect_draw_some_item (orig_text_bar_gworld, win_from_rects[4], text_bar_gworld, win_from_rects[4], 0, 0);

hdc = CreateCompatibleDC(main_dc);
SetBkMode(hdc,TRANSPARENT);
SelectObject(hdc,small_bold_font);
store_bmp = (HBITMAP) SelectObject(hdc,text_bar_gworld);
sprintf(status_str,"%s",str);
SetTextColor(hdc,y);
win_draw_string(hdc,text_rect,status_str,2,9);
SetTextColor(hdc,x);

if (monsters_going == FALSE) {
if (PSD[305][0] > 0) {
text_rect.left = xpos;
SetTextColor(hdc,RGB(255,255,255));
sprintf((char *) status_str,"Stealth");
win_draw_string(hdc,text_rect,status_str,2,9);
xpos -= 60;
}
if (PSD[305][1] > 0) {
text_rect.left = xpos;
SetTextColor(hdc,RGB(255,255,255));
sprintf((char *) status_str,"Flying");
win_draw_string(hdc,text_rect,status_str,2,9);
xpos -= 60;
}
if (PSD[305][2] > 0) {
text_rect.left = xpos;
SetTextColor(hdc,RGB(255,255,255));
sprintf((char *) status_str,"Detect Life");
win_draw_string(hdc,text_rect,status_str,2,9);
xpos -= 60;
}
if (PSD[305][3] > 0) {
text_rect.left = xpos;
SetTextColor(hdc,RGB(145+PSD[305][3]*10,40+PSD[305][3]*10,40));//fading (as effect wear off) orange text effect test
sprintf((char *) status_str,"Firewalk");
win_draw_string(hdc,text_rect,status_str,2,9);
xpos -= 60;
}
}

SelectObject(hdc,store_bmp);
if (!DeleteDC(hdc)) DebugQuit("Cannot release DC 23");
rect_draw_some_item (text_bar_gworld, win_from_rects[4], text_bar_gworld, win_to_rects[4], 0, 1);
}


Originally Posted By: Celtic Minstrel
I also discovered that for some reason the game isn't loading strings correctly. I'll have to look into that... it's slightly odd since the editor doesn't have a problem, but then it could have to do with the fact that the game often loads the strings "as needed" rather than all at once.

I've never encountered something like this with the Windows code ... A relic of the refactoring ?
Originally Posted By: Celtic Minstrel
First, could you post your code? Second, there are some unused fields in the town record. One of this could be put to use for this feature. We could add the node as well, to toggle whether the map is available.

This heavily use platform dependant graphical code but here it is anyway.
Add this at the beginning of the draw_map() function :
Click to reveal..
if(party.stuff_done[308][0] > 0 ){//map not available
if (modeless_exists[5] == TRUE){
// RECT text_rect = {30,265,230,275}; // legacy text position (lower left corner)
RECT text_rect = {0,0,300,290};
hdc2 = GetDC(the_dialog);
paint_pattern((HBITMAP) hdc2,2,map_world_rect,0);
SetBkMode(hdc2,TRANSPARENT);
SelectObject(hdc2,bold_font);
SetTextColor(hdc2,RGB(255,255,255));
char_win_draw_string(hdc2,text_rect,"Map unavailable.",1,10);
GetClientRect(GetDlgItem(the_dialog,1),&draw_rect);
InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE);
fry_dc(the_dialog,hdc2);
}
return;
}


Originally Posted By: Celtic Minstrel
I don't think we should add the ability to hide outdoor maps though. I think I mentioned my reasoning for that somewhere already.

I agree with Thuryl : if a scenario designer wants to hide outdoors, he should be able to do it. It's up to him to justify the existence of such an effect and make sure the player is not stucked with a "Unavailable Map". A simple if(overall_mode != 0) check will prevent such a thing if you really don't like the idea ...

Originally Posted By: Celtic Minstrel
With regards to the flags, I have added a check to see if the first flag is 0x0B0E. If it is, I will treat the file as a new-format save file. The three flags will then follow as normal; after that, it may be useful to add a version flag. Beyond that, I'm not entirely sure.

Which flag ? The town save flag ? Wouldn't in_scen be more appropriate ?

Originally Posted By: Celtic Minstrel
I've now realized that ver is in fact the scenario version, so it should be scenario.format.prog_make_ver that is set to 2 to indicate new version.

In the Windows version of the scenario_data_type structure, only scenario.prog_make_ver exists ... confused

Originally Posted By: Celtic Minstrel
I should probably implement this debug mode. Could you give me some information about it?

If you want a glimpse of the code, Ishad Nha lastest version of the code should have all debug functions but enter_town implemented (see handle_keystroke()).
The choice here was to use the scenario debug mode (there was another debug variable, presumably used by Jeff as a coding debug mode. It has been merged with the scenario debug mode). When you Shift+D, you enter debug mode (no password, the code being open it's pretty useless) and you have some Shift+? functions that perform debug functions.

Originally Posted By: Celtic Minstrel
Okay, so I was wondering – can anyone tell me what mode 5 is? It appears that it may be "dropping mode" when in town (as opposed to combat), but it's not really very clear...

Indeed, 5 is dropping in town mode, 15 is dropping in combat mode (checked ingame).

Originally Posted By: The Almighty Doer of Stuff
While you're working on the automap, sometimes, when I move next to water, one edge of the water will be replaced with the tile that's next to it on the automap. It's kind of hard to describe what I mean, I guess. Maybe someone knows what I'm talking about and can explain it better.

Also, terrains that emit light are strange colored blocks on the automap, rather than small representations of themselves.

I've come across this bug and i think i found its cause.
In draw_map() function, under the // Try a little optimization (rolleyes ) comment :
Click to reveal..
if ((pic < 400) && (where.x < area_to_put_on_map_rect.right - 1)) {
if (out_mode == TRUE)
what_ter2 = out[(where.x + 1)+ 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y];
else what_ter2 = t_d.terrain[where.x + 1][where.y];
if (out_mode == TRUE)
expl2 = out_e[(where.x + 1) + 48 * party.i_w_c.x][where.y + 48 * party.i_w_c.y];
else expl2 = is_explored(where.x + 1,where.y);
pic2 = scenario.ter_types[what_ter2].picture;
if ((map_pats[pic] == map_pats[pic2]) && (expl2 != 0)) {
draw_rect.right += 6;
map_graphic_placed[(where.x + 1)/ 8][where.y] =
map_graphic_placed[(where.x + 1)/ 8][where.y] | (unsigned char)(s_pow(2,(where.x + 1)% 8));
}
}

If pic2 is an animated terrain, pic2 is >= 400. But map_pats is a 256 char array, so the check is done way out of the array. If by chance the value at pic2[4xx] matches the map_pats[pic] value, it displays oddities. (torches and camfires are 411-413 so the most likely (as further) to trigger this).
The fix is to simply replace if (pic2 < 400 && (map_pats[pic] == map_pats[pic2]) && [..]

Chokboyz

Edit : ever wondered why you could fire arrows through solid walls or even in complete darkness ? It's because, in fire_missile(), the check else if (can_see(pc_pos[current_pc],target,0) == 5) should read else if (can_see(pc_pos[current_pc],target,0) > 4).
(There's also an occurence of that glitch in the field handling functions, when the program cleans the field that are not seen)
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
If your reason for that is passwords, it won't be an issue. Passwords are no longer required to edit scenarios (though I would still consider requiring them to enter debug mode).

I'm not sure I like the idea of editing other people's scenarios without consulting them and inserting things they did not include, if that's what you're saying.

Quote:
In any case, if we do have a compatibility switch, I think it should be something that's silently handled by the game, rather than something the player can control. You're right that it would be easy to simply set an SDF, preferably a reserved one; this could be done when loading the scenario. And then the player doesn't really need to think about whether they need the switch enabled – if they're in an old-format scenario, it automatically will be.

This is what I meant.


Quote:
Are there any scenarios that actually removed Resurrection Balm from their item list? Because if there are, that's something we would want to take into account. It wouldn't affect their ability to make it if they have the recipe, but it would prevent them from adding it in the character editor unless we make a special allowance for it.

There are. Someone released various alternate Bladbase.exs scenarios, several without any items at all, so the designer could insert his own items.

Don't get me wrong, I do think we should fix that bug. I just think we (well, you guys, not me obviously, but we as a community) should be very careful each time we change a functionality, so that we keep old format scenarios functioning as they were intended to function.
Link to comment
Share on other sites

I just discovered that in monster_attack_monster, demons seem to do undead damage and undead do demonic damage... can you confirm? It's just after the comment "// Check if hit, and do effects" and the if statement "if (r1 <= hit_chance[(attacker->m_d.skill + 4) / 2])", near the top of the function. That's in the combat.cpp file.

 

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Okay, this confused me a little at first, because the exploding arrows code was in a different place than in my code, but I've now implemented this change. However, I did it a little differently to avoid duplication of code

I've deleted the duplicated code in fire_missile(). The third last line can be left in the exploding case (the first is reinitializing a variable used in normal missile, the second reduces the amount of poison on weapons and the third print the buffer).

So, if it was an exploding missile, the first two lines should be skipped? At least the reduce poison line should be skipped, right?

 

Originally Posted By: Chokboyz
Concerning the Resurrection Balm, i will not fix it for now as it breaks compatibility. However, a check in the function will make it functionnal for the new scenario format.
It was already fixed (unless it was a Windows-only bug), so I'm not going to change that now.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
For the second, my version of stat_adj checks for exactly 3 abilities, and 99 is not one of them.

Incredibly enough, windows version of the code didn't do any check with these three values ... The Strengh, Dexterity or Intelligence item abilities were then utterly useless.

Okay, so what did your version of stat_adj() check for?

 

Originally Posted By: Chokboyz
Here is my version of do_mindduel() :
Hmm, that's interesting. It is there, but I didn't notice it. Your code has this:

Code:
if (adven[pc_num].hasAbilEquip(53) < 24)adjust += 20;

But mine has this instead:

Code:
if ((i = get_prot_level(pc_num,53)) > 0)adjust += i * 5;
The difference being, I think, that the bonus given by my version of the code actually depends on the ability strength of the item rather than just its presence.

 

Originally Posted By: Chokboyz
Originally Posted By: The Almighty Doer of Stuff
Also, perhaps instead of including only one version of the graphics, perhaps a switch could be put in the preferences for darker or lighter graphics

I was thinking of such a thing and will see what can be done. It's not top priority though smile

Is there really any point to that though? We'd have to have twice as many terrain sheets, for one (a lot of the other graphics are actually unaffected). We'd need a flag in the scenario format to specify which version of the graphics to use. And we'd have to consider whether to let the designer make this choice in new scenarios; if we decide that they can, the extra graphics that I've added (on the end of the last sheet and also on the new sheet) would also need an alternate version.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Could I see your code for this?

End of boom_space() function :

 

Click to reveal..
if ((cartoon_happening == FALSE) && (dest_rect.right - dest_rect.left >= 28)

&& (dest_rect.bottom - dest_rect.top >= 36)) {

sprintf((char *) dam_str,"%d",damage);

text_rect = dest_rect;

text_rect.top += 10;

if ((damage < 10) && (dest_rect.right - dest_rect.left > 19))

text_rect.left += 2;

OffsetRect(&text_rect,-4,-5);

 

if ((type == 1) || (type == 4))

WinBlackDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);

else WinDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);

}

 

if(party.stuff_done[305][7] > 0)

play_sound(-sound_to_play[sound]);

else{

play_sound(sound_to_play[sound]);

 

if ((sound == 6) && (fast_bang == 0))

Delay(12, &dummy);

 

Delay(10,&dummy);

if (fast_bang == 0) {

del_len = PSD[306][6] * 3 + 4;

if (play_sounds == FALSE)

Delay(del_len, &dummy);

}

}

 

redraw_terrain();

if ((cartoon_happening == FALSE) && (overall_mode > 9) && (overall_mode != 35) && (overall_mode != 36) && (overall_mode != 50))

draw_pcs(center,1);

}

This is temporary though, as i've not decided what solution to implement.

Hmm... the indentation confuses me (my code is horribly indented – I should fix that sometime). As far as I can see, the only change is multiplying the sound number by -1?

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I don't think it occurs on Mac – I vaguely remember stepping on cold terrain and seeing the cold damage icon. Which function does it occur in, so I can check?

In check_special_terrain(), case 2, 3 and 4 of the ter_special switch, hit_party(r1,1) should read hit_party(1,dam_type). I think this one is Windows specify, though.

Hm, it seems the bug was there, though I don't remember encountering while actually playing. I also noticed something odd just above that: "r1 = get_ran(ter_flag2,dam_type,ter_flag1)" – so, the damage type is also the minimum amount of damage? smirk That doesn't make sense, does it?

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
As far as I can tell, they aren't displayed at all, even in black. Could you show your code?

[ spoiler:put_text_bar code ]

Ohhhhh... I was looking in the wrong place! It does display in white, then. I found that Stealth would not display, though, because the Stealth spell (case 38 in do_mage_spell) was changing the wrong SDF. That's probably a bug I introduced, but you may want to check just to make sure.

 

There is a problem when you have all three of the effects stealth, detect life, and firewalk, though. First, they take up enough of the text bar that I'm sure they'd be very likely to overlap the town name. Second, Stealth will always overlap the next one to the left, it seems. That may apply to flying, too. Personally, I think it would be better to create four little icons for these effects, but any change like that would have to wait, at a minimum, until such icons could be created. wink

 

Another thing: Detect Life is not cancelled when you leave town; Stealth is. Should that be changed? Does Detect Life even work outdoors?

 

I also randomly discovered a bug where hit points suddenly jump to negative (when resting). I think that must also be a bug introduced by my changes. I'm not sure how to fix it though... and I've discovered yet other bugs too (one is something to do with loading strings from the scenario, another seems to be a problem with the combat terrain generator, though it could be a result of whatever causes the other problem...)

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I also discovered that for some reason the game isn't loading strings correctly. I'll have to look into that... it's slightly odd since the editor doesn't have a problem, but then it could have to do with the fact that the game often loads the strings "as needed" rather than all at once.

I've never encountered something like this with the Windows code ... A relic of the refactoring ?

Probably. I moved around all the code for loading the scenario, which includes the code for loading a string on demand. Currently, garbage is being displayed in place of the proper string.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
First, could you post your code? Second, there are some unused fields in the town record. One of this could be put to use for this feature. We could add the node as well, to toggle whether the map is available.

This heavily use platform dependant graphical code but here it is anyway.

Add this at the beginning of the draw_map() function :

Click to reveal..
if(party.stuff_done[308][0] > 0 ){//map not available

if (modeless_exists[5] == TRUE){

// RECT text_rect = {30,265,230,275}; // legacy text position (lower left corner)

RECT text_rect = {0,0,300,290};

hdc2 = GetDC(the_dialog);

paint_pattern((HBITMAP) hdc2,2,map_world_rect,0);

SetBkMode(hdc2,TRANSPARENT);

SelectObject(hdc2,bold_font);

SetTextColor(hdc2,RGB(255,255,255));

char_win_draw_string(hdc2,text_rect,"Map unavailable.",1,10);

GetClientRect(GetDlgItem(the_dialog,1),&draw_rect);

InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE);

fry_dc(the_dialog,hdc2);

}

return;

}

Hm, well, I won't implement it just now, but I could probably duplicate that.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I don't think we should add the ability to hide outdoor maps though. I think I mentioned my reasoning for that somewhere already.

I agree with Thuryl : if a scenario designer wants to hide outdoors, he should be able to do it. It's up to him to justify the existence of such an effect and make sure the player is not stucked with a "Unavailable Map". A simple if(overall_mode != 0) check will prevent such a thing if you really don't like the idea ...

Okay, fine.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
With regards to the flags, I have added a check to see if the first flag is 0x0B0E. If it is, I will treat the file as a new-format save file. The three flags will then follow as normal; after that, it may be useful to add a version flag. Beyond that, I'm not entirely sure.

Which flag ? The town save flag ? Wouldn't in_scen be more appropriate ?

What I'm doing is this. I check the first flag. If it's 0x0B0E, then the next flag is in_town, followed by in_scen, followed by save_maps, followed possibly by a version flag. If the first flag is not 0x0B0E, it's interpreted as the in_town flag, and loading proceeds as normal.

 

I haven't actually written the code to do anything different if the first flag is 0x0B0E – I just have the check for that flag there so far.

 

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I've now realized that ver is in fact the scenario version, so it should be scenario.format.prog_make_ver that is set to 2 to indicate new version.

In the Windows version of the scenario_data_type structure, only scenario.prog_make_ver exists ... confused

...What? Where's the scenario version stored then?

 

Originally Posted By: Chokboyz
Edit : ever wondered why you could fire arrows through solid walls or even in complete darkness ? It's because, in fire_missile(), the check else if (can_see(pc_pos[current_pc],target,0) == 5) should read else if (can_see(pc_pos[current_pc],target,0) > 4).

(There's also an occurence of that glitch in the field handling functions, when the program cleans the field that are not seen)

EDIT: Forgot to reply to this. I chose to say >= 5 instead of > 4, but the effect is the same.

 

 

 

 

Another interesting function I found that isn't used is handle_cave_lore(), which, if it were ever called, would occasionally give the party food if anyone has the cave lore trait (or Woodsman I think it's called).

 

Originally Posted By: The Almighty Doer of Stuff
Originally Posted By: Celtic Minstrel
If your reason for that is passwords, it won't be an issue. Passwords are no longer required to edit scenarios (though I would still consider requiring them to enter debug mode).

I'm not sure I like the idea of editing other people's scenarios without consulting them and inserting things they did not include, if that's what you're saying.

Basically, yes. Obviously it'd be better to get them to fix it instead, though, if they're still around; and if they aren't... I dunno...

 

Originally Posted By: The Almighty Doer of Stuff
Quote:
In any case, if we do have a compatibility switch, I think it should be something that's silently handled by the game, rather than something the player can control. You're right that it would be easy to simply set an SDF, preferably a reserved one; this could be done when loading the scenario. And then the player doesn't really need to think about whether they need the switch enabled – if they're in an old-format scenario, it automatically will be.

This is what I meant.

Okay. Chokboyz, shall we agree on an unused SDF? What about SDF(305,4), SDF(305,7), or SDF(305,8)?

 

Originally Posted By: The Almighty Doer of Stuff
Quote:
Are there any scenarios that actually removed Resurrection Balm from their item list? Because if there are, that's something we would want to take into account. It wouldn't affect their ability to make it if they have the recipe, but it would prevent them from adding it in the character editor unless we make a special allowance for it.

There are. Someone released various alternate Bladbase.exs scenarios, several without any items at all, so the designer could insert his own items.

Okay, so we should compile a list of "essential items". I'd say all the alchemical ingredients should be on there, at least. That list can then be used by the character editor to allow the player to add these items to the party.

 

Originally Posted By: The Almighty Doer of Stuff
Don't get me wrong, I do think we should fix that bug. I just think we (well, you guys, not me obviously, but we as a community) should be very careful each time we change a functionality, so that we keep old format scenarios functioning as they were intended to function.
Yeah, this would be a good idea.
Link to comment
Share on other sites

Jeff's main motivation for including modules in Exile 3 was to allow towns to slowly fall into ruin without the need for a multi-MB Town.dat file. This is a very specific E3 plot element that might not be relevant in most BoE scenarios. However there is no harm in including it, people might find other uses for it.

 

Difference between 2 and 3 is the difference between the placement of small stalagmites and bedding in the Arrival Platform. (This is where you arrive to chase down the Orb of Thralni.) To finally pin down the difference I would need to check all 57 modular towns. One thing I did learn from the Arrival Platform, the default terrain is set by the town being on the surface or being below. When I altered Town.dat to place it on the surface, it had grass not cave floor as the default terrain.

 

If you are going to use the modules, you will need to alter the editor. Might not be too hard, just import a square of terrain from another town.

Link to comment
Share on other sites

Well, that wasn't quite the sort of error I expected. It seems that the bug with hitpoints suddenly leaping to negative was because I changed get_ran! I altered it to use the standard library rand() function rather than the QuickDraw Random() function, and it no longer returned values in the expected range.

 

...which reminds me, I'm still seeding with the Quickdraw function, so it's probably not actually randomized. I'd better go fix that.

 

 

 

Since the combat terrain generator uses get_ran, that might be fixed too now.

 

 

EDIT: In the editor, overall_mode 1 is checked but, as far as I can see, never set. Can you confirm? Is it safe to remove?

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I just discovered that in monster_attack_monster, demons seem to do undead damage and undead do demonic damage... can you confirm?

Yup, confirmed. Ishad Nha found some times ago that the same thing also happens in monster_attack_pc().

Originally Posted By: Celtic Minstrel
So, if it was an exploding missile, the first two lines should be skipped? At least the reduce poison line should be skipped, right?

The first one can safely be skipped. The second one should also, because the poison wearing off with time is done in the increase_age() function if i remember correctly, so this one represents the poison wearing off because being used ...

Originally Posted By: Celtic Minstrel
Okay, so what did your version of stat_adj() check for?

Click to reveal.. (statAdj)
short pc_record_type::statAdj(short which)
{
short tr;

tr = skill_bonus[skills[which]];

if (which == 2) {//intelligence
if (traits[1] == TRUE) tr++;//has magical apt ?
if (hasAbilEquip(99) < 16) tr++;// has item with ability 99 equipped ? smile
}

if (which == 0)//strengh
if (traits[8] == TRUE) tr++;//has Exceptionnal Strenght ?

return tr;
}


Originally Posted By: Celtic Minstrel
The difference being, I think, that the bonus given by my version of the code actually depends on the ability strength of the item rather than just its presence.

The Mac version of Will items handling seems more flexible, maybe the Windows version should adopt it ? (on the other hand, the check should use the ability strenght rather then the protection level, no ? smile )

Originally Posted By: Celtic Minstrel
Is there really any point to that though?

Some people might prefers the brightest terrains ... Don't yell yet, i'm leaving that alone for the moment wink

Originally Posted By: Celtic Minstrel
Hmm... the indentation confuses me (my code is horribly indented – I should fix that sometime). As far as I can see, the only change is multiplying the sound number by -1?

Not only (multiplying the sound number by -1 makes it asynchronous), it also skips the Delay part.

Originally Posted By: Celtic Minstrel
I also noticed something odd just above that: "r1 = get_ran(ter_flag2,dam_type,ter_flag1)" – so, the damage type is also the minimum amount of damage? That doesn't make sense, does it?

I noticed that too and left it as part of the code oddities (fire block does less damage than ice which does less damage than magic). Easily fixed, should the need arise.

Originally Posted By: Celtic Minstrel
I found that Stealth would not display

Stealth displays fine in Windows version.

Originally Posted By: Celtic Minstrel
There is a problem when you have all three of the effects stealth, detect life, and firewalk, though. First, they take up enough of the text bar that I'm sure they'd be very likely to overlap the town name. Second, Stealth will always overlap the next one to the left, it seems. That may apply to flying, too. Personally, I think it would be better to create four little icons for these effects, but any change like that would have to wait, at a minimum, until such icons could be created.

Indeed, these strings overlap with the town name (and even between them). Icons would be nice ... My drawing skills being what they are, i won't be the one that draw them, though grin
If anyone feels like doing it ...

Originally Posted By: Celtic Minstrel
Another thing: Detect Life is not cancelled when you leave town; Stealth is. Should that be changed? Does Detect Life even work outdoors?

That should be changed as Detect Life doesn't work outdoor (it doesn't even work while in combat) ...
Did i broke something or monsters appears only on explorated squares ?

Originally Posted By: Celtic Minstrel
What? Where's the scenario version stored then?

The version of the editor/game used seems to be stored in scen_headers[scen].prog_make_ver. But those values are never initialized (that's probably the source of the "version error message when clicking cancel in custom scenario menu" glitch)...
The variable scenario.prog_make_ver is used to store the scenario (inner) version.

Originally Posted By: Celtic Minstrel
Another interesting function I found that isn't used is handle_cave_lore(), which, if it were ever called, would occasionally give the party food if anyone has the cave lore trait (or Woodsman I think it's called).

I remember coming across something like that, i can't seems to find it again (handle_cave_lore() doesn't exist my version of the code) ... Should it be implemented ?

Originally Posted By: Celtic Minstrel
Okay. Chokboyz, shall we agree on an unused SDF? What about SDF(305,4), SDF(305,7), or SDF(305,8)?

I actually use SDF[305][4] (skip startup screen) and SDF[305][7] (fast boom space). SDF[305][8] is free though.

Originally Posted By: The Almighty Doer of Stuff
Don't get me wrong, I do think we should fix that bug. I just think we (well, you guys, not me obviously, but we as a community) should be very careful each time we change a functionality, so that we keep old format scenarios functioning as they were intended to function.

Seems like what we're trying to do wink

Originally Posted By: Celtic Minstrel
In the editor, overall_mode 1 is checked but, as far as I can see, never set. Can you confirm? Is it safe to remove?

A quick glance at code shows no setting of overall_mode to 1. That should be ok to remove ...

Chokboyz

Edit : i've changed the exploding arrows to show the explosion radius (once they are identified) rather than the basic square when firing.
In load_missile() :
Click to reveal..
[...]
else if ((arrow < 24) && (bow < 24)) {
missile_inv_slot = bow;
ammo_inv_slot = arrow;
overall_mode = MODE_FIRING;
add_string_to_buf("Fire: Select a target. ");
add_string_to_buf(" (Hit 's' to cancel.)");
current_spell_range = 12;
if(adven[current_pc].items[arrow].ability == 172 && adven[current_pc].items[arrow].isIdent() == TRUE)
current_pat = radius2;
else

current_pat = single;
}
[...]

Once again, the code is using Ormus C++ changes and must be adapted (especially isIdent() function).

Oh and it seems that the do_missile_anim(100,pc_pos[current_pc], 5); line in the exploding case of fire_missile() is redundant (i.e a second missile is launched) ...
Erf, i found that missile removing and poison reducing must be done before damage dealing because if a pc dies from the damage dealt by the arrow, missile and poison will be reduced for the first active pc ... Using missile_firer seems a better idea than duplicating code ...

Finally, shouldn't the health arrows works for pc too ?
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I just discovered that in monster_attack_monster, demons seem to do undead damage and undead do demonic damage... can you confirm?

Yup, confirmed. Ishad Nha found some times ago that the same thing also happens in monster_attack_pc().
Good, then I've fixed both of them now.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
So, if it was an exploding missile, the first two lines should be skipped? At least the reduce poison line should be skipped, right?

The first one can safely be skipped. The second one should also, because the poison wearing off with time is done in the increase_age() function if i remember correctly, so this one represents the poison wearing off because being used ...
Done!

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Okay, so what did your version of stat_adj() check for?

Click to reveal.. (statAdj)
short pc_record_type::statAdj(short which)
{
short tr;

tr = skill_bonus[skills[which]];

if (which == 2) {//intelligence
if (traits[1] == TRUE) tr++;//has magical apt ?
if (hasAbilEquip(99) < 16) tr++;// has item with ability 99 equipped ? smile
}

if (which == 0)//strengh
if (traits[8] == TRUE) tr++;//has Exceptionnal Strenght ?

return tr;
}
Since you say ability 99 doesn't exist, maybe you should adopt the Mac version of this function? I did post it, right?

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
The difference being, I think, that the bonus given by my version of the code actually depends on the ability strength of the item rather than just its presence.

The Mac version of Will items handling seems more flexible, maybe the Windows version should adopt it ? (on the other hand, the check should use the ability strenght rather then the protection level, no ? smile )
I could be wrong, but I was under the impression that the function called actually returned the ability strength (meaning that it's a misleading function name, but still it's at least no the wrong function).

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Hmm... the indentation confuses me (my code is horribly indented – I should fix that sometime). As far as I can see, the only change is multiplying the sound number by -1?

Not only (multiplying the sound number by -1 makes it asynchronous), it also skips the Delay part.
Right, then that shall be implemented at some point. I'll make it a hidden preference for now, like the skip startup splash one.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Another thing: Detect Life is not cancelled when you leave town; Stealth is. Should that be changed? Does Detect Life even work outdoors?

That should be changed as Detect Life doesn't work outdoor (it doesn't even work while in combat) ...
Did i broke something or monsters appears only on explorated squares ?
I think they only appear on explored squares, but I don't use it much, so I'm not sure.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
What? Where's the scenario version stored then?

The version of the editor/game used seems to be stored in scen_headers[scen].prog_make_ver. But those values are never initialized (that's probably the source of the "version error message when clicking cancel in custom scenario menu" glitch)...
The variable scenario.prog_make_ver is used to store the scenario (inner) version.
That seems like a bad idea. I bet that was an Ormus change. The scenario version should not be stored in a variable called prog_make_ver, because that's misleading. To me, at least, it implies that it's the version of the program used to make the scenario. Does he at least write it to (and read it from) the file correctly? Scenario version first, followed by some other number, followed by editor version.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Another interesting function I found that isn't used is handle_cave_lore(), which, if it were ever called, would occasionally give the party food if anyone has the cave lore trait (or Woodsman I think it's called).

I remember coming across something like that, i can't seems to find it again (handle_cave_lore() doesn't exist my version of the code) ... Should it be implemented ?
Maybe. It's possible that Ormus cleaned out unused functions, or perhaps Jeff cleaned out unused function during the porting process. There are quite a lot of unused functions, not all of which have an empty body.

Let's wait on the handle_cave_lore, though. We can implement it later, maybe. At least the trait isn't useless, since special nodes can check for it.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Okay. Chokboyz, shall we agree on an unused SDF? What about SDF(305,4), SDF(305,7), or SDF(305,8)?

I actually use SDF[305][4] (skip startup screen) and SDF[305][7] (fast boom space). SDF[305][8] is free though.
Okay, SDF(305,8) it is. I'm actually not using SDF(305,4) for skip startup splash anymore, though – I'm using a global variable instead. As for SDF(305,7)... well, I haven't implemented that yet.

So... I'll add something to the loading code for old scenarios (which currently is the only loading code) to set that SDF to 1, and a check in the do_priest_spell function so that if the SDF is 1, Resurrection Balm is not required.

When I write the loading code for new scenarios, I'll make sure to set it the SDF to 0.


...Actually, the setting of the SDF would have to be in the load party code, after the scenario is loaded – something like "if(scenario.prog_make_ver < 2) PSD[305][8] = 1; else PSD[305][8] = 0;".

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
In the editor, overall_mode 1 is checked but, as far as I can see, never set. Can you confirm? Is it safe to remove?

A quick glance at code shows no setting of overall_mode to 1. That should be ok to remove ...
Good, then I'll remove it.

Originally Posted By: Chokboyz

Edit : i've changed the exploding arrows to show the explosion radius (once they are identified) rather than the basic square when firing.
In load_missile() :
Click to reveal..
[...]
else if ((arrow < 24) && (bow < 24)) {
missile_inv_slot = bow;
ammo_inv_slot = arrow;
overall_mode = MODE_FIRING;
add_string_to_buf("Fire: Select a target. ");
add_string_to_buf(" (Hit 's' to cancel.)");
current_spell_range = 12;
if(adven[current_pc].items[arrow].ability == 172 && adven[current_pc].items[arrow].isIdent() == TRUE)
current_pat = radius2;
else

current_pat = single;
}
[...]

Once again, the code is using Ormus C++ changes and must be adapted (especially isIdent() function).
This sounds like a good idea. As for isIdent, I've actually refactored the code enough that I won't have to change that (apart from the fact that I called the method is_identified instead of isIdent).

I do still have to refactor some of the PC and party-related stuff to match up with the Windows code.

Originally Posted By: Chokboyz
Oh and it seems that the do_missile_anim(100,pc_pos[current_pc], 5); line in the exploding case of fire_missile() is redundant (i.e a second missile is launched) ...
Erf, i found that missile removing and poison reducing must be done before damage dealing because if a pc dies from the damage dealt by the arrow, missile and poison will be reduced for the first active pc ... Using missile_firer seems a better idea than duplicating code ...
Okay, I'm not quite sure what you've said here...

Originally Posted By: Chokboyz
Finally, shouldn't the health arrows works for pc too ?
Huh?
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Since you say ability 99 doesn't exist, maybe you should adopt the Mac version of this function? I did post it, right?

I did (and you did) wink That was clearly what the function was supposed to be ...

Originally Posted By: Celtic Minstrel
I could be wrong, but I was under the impression that the function called actually returned the ability strength (meaning that it's a misleading function name, but still it's at least no the wrong function).

Incredibly enough, the function does indeed return the ability strengh ... Speak about a misleading name smile

Originally Posted By: Celtic Minstrel
That seems like a bad idea. I bet that was an Ormus change.

Seems like scenario version is stored in scenario.ver and program made version is stored in scenario.prog_make_ver after all (my bad crazy )
The load_scenario_header function seems the same as the Mac one (original code) (besides, if we are able to play Mac scenario, it should be ok, no ?)

Originally Posted By: Celtic Minstrel
Maybe. It's possible that Ormus cleaned out unused functions, or perhaps Jeff cleaned out unused function during the porting process. There are quite a lot of unused functions, not all of which have an empty body.

Either it's him or me, but the function has indeed been removed (present in the original Windows code) ... Putting it back in the code wouldn't requires much effort smile

Originally Posted By: Celtic Minstrel
...Actually, the setting of the SDF would have to be in the load party code, after the scenario is loaded – something like "if(scenario.prog_make_ver < 2) PSD[305][8] = 1; else PSD[305][8] = 0;".

I will adopt that as well ...

Originally Posted By: Celtic Minstrel
Okay, I'm not quite sure what you've said here...

I can understand that wink
  • the do_missile_anim(100,pc_pos[current_pc], 5); line in the exploding case of the fire_missile() is redundant in the way that two arrows will be shoot by the firer (because do_missile_anim() is already done in run_a_missile()). I removed it (that was also the cause of two explosion sounds being played)
  • The problem with ammo and poison reducing code is that it's placed after damage dealing.
    Unfortunately, if a pc (other than the firer) is killed because of the damage dealt by the arrow then current_pc switch to the first active pc (let's say Frrrrrr shoots an explosive arrow that kills Feodoric, then Jennekee (providing he is alive) ammo will be reduced (provided he has any) and poison on his blade will be reduced. Frrrrrr would lost no ammo).
    I used the already present missile_firer variable (needs to be set in exploding case) to check the right pc ... (may be a Windows only bug, as the kill function has been modified by Ormus)
Originally Posted By: Celtic Minstrel
Originally Posted By: Chokboyz
Finally, shouldn't the health arrows works for pc too ??
Huh?

The heal target missile ability, heal the monster it hits, but if it hits a pc, it deals normal damages. Should that be fixed ?

Edit: Resurrection Balm legacy compatibility check is implemented and working. In any scenario with major version number more or equal to 2, a Resurrection Balm will be needed to cast Resurrection or Raise Dead. Legacy scenarios are left alone. (SDF[305][8] used)
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Could I see your code for this?

End of boom_space() function :

Click to reveal..
if ((cartoon_happening == FALSE) && (dest_rect.right - dest_rect.left >= 28)
&& (dest_rect.bottom - dest_rect.top >= 36)) {
sprintf((char *) dam_str,"%d",damage);
text_rect = dest_rect;
text_rect.top += 10;
if ((damage < 10) && (dest_rect.right - dest_rect.left > 19))
text_rect.left += 2;
OffsetRect(&text_rect,-4,-5);

if ((type == 1) || (type == 4))
WinBlackDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);
else WinDrawString(dam_str,text_rect.left + 12,text_rect.top + 6);
}

if(party.stuff_done[305][7] > 0)
play_sound(-sound_to_play[sound]);
else{

play_sound(sound_to_play[sound]);

if ((sound == 6) && (fast_bang == 0))
Delay(12, &dummy);

Delay(10,&dummy);
if (fast_bang == 0) {
del_len = PSD[306][6] * 3 + 4;
if (play_sounds == FALSE)
Delay(del_len, &dummy);
}
}

redraw_terrain();
if ((cartoon_happening == FALSE) && (overall_mode > 9) && (overall_mode != 35) && (overall_mode != 36) && (overall_mode != 50))
draw_pcs(center,1);
}

This is temporary though, as i've not decided what solution to implement.
I've implemented this, but am checking a global variable (skip_boom_delay) instead of an SDF.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
First, could you post your code? Second, there are some unused fields in the town record. One of this could be put to use for this feature. We could add the node as well, to toggle whether the map is available.

This heavily use platform dependant graphical code but here it is anyway.
Add this at the beginning of the draw_map() function :
Click to reveal..
if(party.stuff_done[308][0] > 0 ){//map not available
if (modeless_exists[5] == TRUE){
// RECT text_rect = {30,265,230,275}; // legacy text position (lower left corner)
RECT text_rect = {0,0,300,290};
hdc2 = GetDC(the_dialog);
paint_pattern((HBITMAP) hdc2,2,map_world_rect,0);
SetBkMode(hdc2,TRANSPARENT);
SelectObject(hdc2,bold_font);
SetTextColor(hdc2,RGB(255,255,255));
char_win_draw_string(hdc2,text_rect,"Map unavailable.",1,10);
GetClientRect(GetDlgItem(the_dialog,1),&draw_rect);
InvalidateRect(GetDlgItem(the_dialog,1),&draw_rect,FALSE);
fry_dc(the_dialog,hdc2);
}
return;
}


I did something completely different, but haven't yet tested it. I discovered some code already there to hide the map in a particular case (if you're in town number -1, which at a guess I'd say might mean outdoor combat?), and simply copied and pasted and altered it slightly.

Code:
else if ((is_town()) && ((univ.town.num == -1) || (univ.town.num == -1))){    if (modeless_exists[5] == true) {        SetPort(GetDialogPort(the_dialog));        FillCRect(&map_bar_rect,bg[4]);        char_port_draw_string( GetDialogPort(modeless_dialogs[5]),map_bar_rect,"No map here.",0,12,false);        draw_pcs = false;        SetPort( map_gworld);    } else {        SetPort(old_port);        return;    }} else if((is_town() && univ.town.town->specials2 & 1)) {    if (modeless_exists[5] == true) {        SetPort(GetDialogPort(the_dialog));        FillCRect(&map_bar_rect,bg[4]);        char_port_draw_string(GetDialogPort(modeless_dialogs[5]),map_bar_rect,"This place defies mapping.",0,12,false);        draw_pcs = false;        SetPort( map_gworld);    } else {        SetPort(old_port);        return;    }}
The first else if was already there, the second I added. I'm not sure if it works though, since I have no way to set specials2 to some other value (other than by entering the debugger and editing it in there before the check occurs). I also altered the checks in do_mage_spell and use_item that involve specials2 to match this check.

This won't doesn't affect outdoor maps, though. I think we'd need to have a completely different case for masking outdoor maps, because the game loads up to 4 outdoor sections into memory at any one time.

I can of course change the string displayed to match yours if you prefer yours.
Link to comment
Share on other sites

Okay, I've implemented the "skip boom delay" as a hidden preference, though I haven't yet tested it. I've also added the version check to the load party code to set SDF(305,8) to 1. And I added a "#define SDF_RESURRECT_NO_BALM 305][8" to support that.

 

At the end of load_party() / load_file() and at the end of put_party_in_scen():

Code:
// Compatibility flagsif(in_scen && scenario.prog_make_ver[0] < 2){    PSD[sDF_RESURRECT_NO_BALM] = 1;} else {    PSD[sDF_RESURRECT_NO_BALM] = 0;}
(Note that, obviously, the in_scen part is not required in put_party_in_scen.)

 

In do_priest_spell():

Code:
if (!PSD[sDF_RESURRECT_NO_BALM] && ((spell_num == 40) || (spell_num == 56)))    if ((item = pc_has_abil(pc_num,160)) == 24) {        add_string_to_buf("  Need resurrection balm.        ");        spell_num = 500;    }    else take_item(pc_num,item);

 

Originally Posted By: The Almighty Doer of Stuff
I might try to make some icons for those four party statuses after the semester ends, if nobody else has by then.
That would be great!
Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff

Originally Posted By: Celtic Minstrel
Okay, I'm not quite sure what you've said here...

I can understand that wink
  • the do_missile_anim(100,pc_pos[current_pc], 5); line in the exploding case of the fire_missile() is redundant in the way that two arrows will be shoot by the firer (because do_missile_anim() is already done in run_a_missile()). I removed it (that was also the cause of two explosion sounds being played)
  • The problem with ammo and poison reducing code is that it's placed after damage dealing.
    Unfortunately, if a pc (other than the firer) is killed because of the damage dealt by the arrow then current_pc switch to the first active pc (let's say Frrrrrr shoots an explosive arrow that kills Feodoric, then Jennekee (providing he is alive) ammo will be reduced (provided he has any) and poison on his blade will be reduced. Frrrrrr would lost no ammo).
    I used the already present missile_firer variable (needs to be set in exploding case) to check the right pc ... (may be a Windows only bug, as the kill function has been modified by Ormus)
I commented out not only the do_missile call but also the start_missile_anim, add_missile, and end_missile_anim calls. I'm not entirely sure whether that's right though.

I also set missile_firer at the beginning of the fire_missile function to be equal to current_pc, and replaced all instances of current_pc in fire_missile with missile_firer. I'm not sure whether it was necessary, but it seemed like a good idea.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Originally Posted By: Chokboyz
Finally, shouldn't the health arrows works for pc too ??
Huh?

The heal target missile ability, heal the monster it hits, but if it hits a pc, it deals normal damages. Should that be fixed ?
Well... technically it should probably affect players in the same way as monsters. Is it possible for such missiles to be used against the player though?

If so, then yes, fix it. wink

Originally Posted By: Chokboyz
Edit: Resurrection Balm legacy compatibility check is implemented and working. In any scenario with major version number more or equal to 2, a Resurrection Balm will be needed to cast Resurrection or Raise Dead. Legacy scenarios are left alone. (SDF[305][8] used)
Perfect! Of course, there are as yet no scenarios with a major version number >= to 2; but that'll change sometime.
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I did something completely different, but haven't yet tested it. I discovered some code already there to hide the map in a particular case (if you're in town number -1, which at a guess I'd say might mean outdoor combat?), and simply copied and pasted and altered it slightly.

Such code is absent in the Windows code (unsurprisingly), but from i can get out the code it seems it does the same thing as mine. The message can be either of the two, yours being more litterate wink

Originally Posted By: Celtic Minstrel
This won't doesn't affect outdoor maps, though. I think we'd need to have a completely different case for masking outdoor maps, because the game loads up to 4 outdoor sections into memory at any one time.

I would say the game loads up to 9 outdoor sections (array is [2][2]) in memory (i think rewriting this part so that the entire outdoor is accessible at any moment will be a good think with the new scenario format).
No specific changes needs to be done to the function though, a simple isOutdoor check would suffice (i've tested mine in town/outdoor without a problem and the code seems to behaves like mine)

Originally Posted By: Celtic Minstrel
At the end of load_party() / load_file() and at the end of put_party_in_scen():

I've put it right after SDF initialization so that no case are missed (this is where play_sound is set). Apart from that, our codes are similar (minor difference : i check if SDF[308][8] == 0).

Originally Posted By: Celtic Minstrel
Well... technically it should probably affect players in the same way as monsters. Is it possible for such missiles to be used against the player though?

Yup, they do the same damage as a normal arrow smile So, I will fix it ...

Chokboyz

Edit: And here it goes : in fire_missile()
Click to reveal..
[...]
if (r1 > hit_chance[skill])
add_string_to_buf(" Missed.");
else if ((targ_monst = monst_there(target)) < T_M) {
cur_monst = &c_town.monst.dudes[targ_monst];
spec_dam = calc_spec_dam(adven[current_pc].items[ammo_inv_slot].ability,
adven[current_pc].items[ammo_inv_slot].ability_strength,cur_monst);
if (adven[current_pc].items[ammo_inv_slot].ability == 176) {
ASB(" There is a flash of light.");
cur_monst->m_d.health += r2;
}
else damage_monst(targ_monst, current_pc, r2, spec_dam, 1300);

// poison
if ((adven[current_pc].status[0] > 0) && (adven[current_pc].weap_poisoned == ammo_inv_slot)) {
poison_amt = adven[current_pc].status[0];
if (adven[current_pc].hasAbilEquip(51) < 24)
poison_amt++;
cur_monst->poison(poison_amt);
}
}
else if((targ_monst = pc_there(target)) < 6 && adven[current_pc].items[ammo_inv_slot].ability == 176){
ASB(" There is a flash of light.");
adven[targ_monst].heal(r2);
}

else hit_space(target,r2,0,1,0);
}
[...]

(another case is used because the two first are monster specifics)
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
This won't doesn't affect outdoor maps, though. I think we'd need to have a completely different case for masking outdoor maps, because the game loads up to 4 outdoor sections into memory at any one time.

I would say the game loads up to 9 outdoor sections (array is [2][2]) in memory (i think rewriting this part so that the entire outdoor is accessible at any moment will be a good think with the new scenario format).
No specific changes needs to be done to the function though, a simple isOutdoor check would suffice (i've tested mine in town/outdoor without a problem and the code seems to behaves like mine)
Uh, what? The array is [2][2], yes, which means its valid indices are [0][0], [0][1], [1][0], and [1][1]. I'd say that's definitely 4 sections.

I don't see any reason to load the entire outdoors at once. I don't think it would really provide any significant advantage, and it would be difficult to change; and also if the outdoors is large enough it may even be a bad idea (not sure though). If we decided to do it, though it would have no effect on the scenario format. Maybe the savegame format, but not the scenario format.

With the map hiding for town, I'm making it a property of the town. So, one town may have a hidden map while another doesn't. If we also make it a property of the outdoor section, we can't use the same code, because there are 4 sections loaded at once, not all of which have hidden maps. So we'd still have to draw something to the map, that is, the terrain of the adjacent sections whose maps are not hidden.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
At the end of load_party() / load_file() and at the end of put_party_in_scen():

I've put it right after SDF initialization so that no case are missed (this is where play_sound is set). Apart from that, our codes are similar (minor difference : i check if SDF[308][8] == 0).
Yeah, that's the same thing. !x will always return the same result as x==0 for any integer variable. I'm thinking of the flag as a boolean value, which is why I used the boolean operator.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Well... technically it should probably affect players in the same way as monsters. Is it possible for such missiles to be used against the player though?

Yup, they do the same damage as a normal arrow smile So, I will fix it ...
Okay, yet another thing for me to fix...
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Uh, what? The array is [2][2], yes, which means its valid indices are [0][0], [0][1], [1][0], and [1][1]. I'd say that's definitely 4 sections.

You're, of course, right ... blush

Originally Posted By: Celtic Minstrel
I don't see any reason to load the entire outdoors at once.

What i wanted to suggest was that an array pointing to every outdoor section could be good think (to avoid navigating using universe shift up/down/left/right)

Originally Posted By: Celtic Minstrel
With the map hiding for town, I'm making it a property of the town. So, one town may have a hidden map while another doesn't. If we also make it a property of the outdoor section, we can't use the same code, because there are 4 sections loaded at once, not all of which have hidden maps. So we'd still have to draw something to the map, that is, the terrain of the adjacent sections whose maps are not hidden.

Can't we make a check to see if the party is in a section to be hid (see party.i_w_c) ?

Originally Posted By: Celtic Minstrel
Okay, yet another thing for me to fix...

I've provided a possible fix in the Edit section of the previous post

Chokboyz
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...