Jump to content

Code Discussion Thread


Celtic Minstrel

Recommended Posts

The MAGICAL_CREATURE one was merely to make the constant shorter – long constants can get annoying.

 

The RACE / TYPE argument, however, I am open to opinions. I'll wait to see what Chokboyz thinks, and then maybe change it back.

 

 

 

In other news, I split off the dialog code, the sound code, and much of the graphics code into a place where it can be shared. The Scenario Editor compiles, links, and runs successfully, which honestly isn't terribly surprising since there is little to no actual change between this code and the version of the code the Scenario editor used.

 

The next step is to get the other two to compile with it.

Link to comment
Share on other sites

  • Replies 990
  • Created
  • Last Reply

Top Posters In This Topic

Originally Posted By: Chokboyz
Edit: Fixing is finished : now, if you change the terrain (using it, stepping on it, lock/unlocking (bash/lockpick/magic/node), crumbling, whatever) while in town and the terrain is a conveyor belt, it springs to life, eager to push you into a wall (yes, that as not yet been corrected).


It probably shouldn't be corrected -- or if it is, there should be a compatibility option. I'm not sure if there are any scenarios that rely on pushing PCs through walls with conveyor belts (although there could be), but there are definitely scenarios that rely on pushing items onto blocked terrains like tables.

By the way, I really appreciate all the work you're putting into this. You and Celtic Minstrel are both doing a great job.
Link to comment
Share on other sites

Originally Posted By: Ishad Nha
I have uploaded a new version incorporating most of Chokboy's changes, the ones that had code listed for them here.
Huh. I thought Chokboyz was making those changes...

...by the way, when are you going to merge your code with his?


...


Or... should I take that post as an indication that you have merged your code?
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I'm not convinced it will play a "first big splash". I took your code as a base and made my own version:

It will, because it's not this function that play the "big splash" (it's one_sound() if I remember correctly). Then if the last sound played with one_sound is big_splash, it will not replay the sound (same for dumbfound, ...).

Originally Posted By: Celtic Minstrel
So, if you're moving from a poison square to a poison or disease square, or from a disease square to a poison or disease square, the sound will be ignored. However, if you move onto a poison or disease square from some other type of square, the sound will be played. I'm pretty sure this code will do that. (In case you're not aware, a static local variable retains its value over multiple function calls. It's essentially a global variable that can only be accessed from one function.)

In the original code, swamps produces no sound when walking on it; what you did is to add a squish (by default) sound when first stepping on it. That seems a little weird to me though (the big splash playing once in a while is enough i think, and since this is done in another function ...).

Originally Posted By: Celtic Minstrel
Well, I did that, but there was something odd there. This is what that chunk of the code now looks like:

Why did you duplicate the check outside of the loop ? What it will do is to recheck the last rectangle to see if there is a conveyor here ... And the others field = true lines are indeed supposed to be outside the loop (the game assumes that such field are always present thus active).

Originally Posted By: Celtic Minstrel
One more thing. I notice you've commented out some of the constants I added? Not that it really matters, but may I ask why?

To remind me that i have to look for references in the code wink

Originally Posted By: Celtic Minstrel
As for the MONSTER_TYPE_ constants, I kind of like the idea of using MONSTER_RACE_ instead. Any objections?

Oh, and drop the _CREATURE from MAGICAL_CREATURE.

Like ADoS, i think we should stick with the editor calling ... In the opposite, the others changes in CONSTS.h are a good idea and i have adopted them.

Originally Posted By: Celtic Minstrel
In other news, I split off the dialog code, the sound code, and much of the graphics code into a place where it can be shared. The Scenario Editor compiles, links, and runs successfully, which honestly isn't terribly surprising since there is little to no actual change between this code and the version of the code the Scenario editor used.

Good news, keep on going ...

Originally Posted By: Thuryl
It probably shouldn't be corrected -- or if it is, there should be a compatibility option. I'm not sure if there are any scenarios that rely on pushing PCs through walls with conveyor belts (although there could be), but there are definitely scenarios that rely on pushing items onto blocked terrains like tables.

Suspecting that, i added a compatibility switch for that one.

Originally Posted By: Thuryl
By the way, I really appreciate all the work you're putting into this. You and Celtic Minstrel are both doing a great job.

Thanks wink

By the way, do you have an explanation of what the precise problem with event timers/time passing is ? For what i have found, the only problem is that Resting outside/in Inn/through a Have a Rest Node bypass the event check. I didn't found a difference between in town and outdoor day as mentionned, so maybe i'm missing the point confused

Originally Posted By: Celtic Minstrel
by the way, when are you going to merge your code with his?

I have already merged his code with mine (using the last 2009 BoE sources available at the time). I am indeed doing the changes but Ishad Nha is kind enough to compile and make available an in-progress version (kind of weekly build) for those who want it (and why not want to beta test the changes grin ). And he is the one working on the Windows Scenario Editor.

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I'm not convinced it will play a "first big splash". I took your code as a base and made my own version:

It will, because it's not this function that play the "big splash" (it's one_sound() if I remember correctly). Then if the last sound played with one_sound is big_splash, it will not replay the sound (same for dumbfound, ...).

In the original code, swamps produces no sound when walking on it; what you did is to add a squish (by default) sound when first stepping on it. That seems a little weird to me though (the big splash playing once in a while is enough i think, and since this is done in another function ...).
Hmm.... I didn't realize that "big splash" and "squish" were two different sounds.

I think a better way to do this would be to add "occasional splash" as an additional option for the step sound. I've implemented this, and can post the code if you'd like, but it should be noted that it will cause older scenarios to produce the squish sound instead.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Well, I did that, but there was something odd there. This is what that chunk of the code now looks like:

Why did you duplicate the check outside of the loop ? What it will do is to recheck the last rectangle to see if there is a conveyor here ... And the others field = true lines are indeed supposed to be outside the loop (the game assumes that such field are always present thus active).
The check was already there outside the loop. That confused me. I'll remove it.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
One more thing. I notice you've commented out some of the constants I added? Not that it really matters, but may I ask why?

To remind me that i have to look for references in the code wink
Which is one thing that I have to do yet... I'm using almost none of the constants right now.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
As for the MONSTER_TYPE_ constants, I kind of like the idea of using MONSTER_RACE_ instead. Any objections?

Oh, and drop the _CREATURE from MAGICAL_CREATURE.

Like ADoS, i think we should stick with the editor calling ... In the opposite, the others changes in CONSTS.h are a good idea and i have adopted them.
Okay. I'll change that back. Did you adopt MONSTER_TYPE_MAGICAL too?

Originally Posted By: Chokboyz
Originally Posted By: Thuryl
It probably shouldn't be corrected -- or if it is, there should be a compatibility option. I'm not sure if there are any scenarios that rely on pushing PCs through walls with conveyor belts (although there could be), but there are definitely scenarios that rely on pushing items onto blocked terrains like tables.

Suspecting that, i added a compatibility switch for that one.
What sort of compatibility switch? A stuff done flag, or checking an extra field in the terrain definition?

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
by the way, when are you going to merge your code with his?

I have already merged his code with mine (using the last 2009 BoE sources available at the time). I am indeed doing the changes but Ishad Nha is kind enough to compile and make available an in-progress version (kind of weekly build) for those who want it (and why not want to beta test the changes grin ). And he is the one working on the Windows Scenario Editor.
Oh, that's good then. When will it be added to the repository, though?
Link to comment
Share on other sites

Quote:
I think a better way to do this would be to add "occasional splash" as an additional option for the step sound. I've implemented this, and can post the code if you'd like, but it should be noted that it will cause older scenarios to produce the squish sound instead.

That's definitely an option. I will stick with the original behavior right now because i work mainly on bug fixing, but that belongs to the suggestion list.

Quote:
The check was already there outside the loop. That confused me. I'll remove it.

Odd, it wasn't there in my code ... Remove it safely.

Quote:
Okay. I'll change that back. Did you adopt MONSTER_TYPE_MAGICAL too?

No, i just adopted SDF flag and shortened ...PROTECT_FROM... and NonSpell Use constants.

Quote:
What sort of compatibility switch? A stuff done flag, or checking an extra field in the terrain definition?

Right now it's a stuff done flag ([309][3] if i remember correctly), mainly for testing purpose.

Quote:
Oh, that's good then. When will it be added to the repository, though?

When majors bug will be ironed out (that's not so far ...) and i cleaned the code a little (nobody wants to be noticed the party.age each step, huh ? wink ) ...

Chokboyz
Link to comment
Share on other sites

So, possibly soon?

 

 

EDIT: The links in the first post in the Bug Fixes section may help with the time issue...

 

EDIT 2: Small change to consts.h:

Code:
#define SDF_PARTY_SPLIT_PC      304][3#define SDF_PARTY_SPLIT_TOWN    304][4 // for future use, hopefully

instead of

Code:
#define SDF_PARTY_SPLIT_PC      304][3 // for future use, hopefully

 

...because I discovered SDF(304,3) was already used.

 

I also added a line to start_split which sets PSD[sDF_PARTY_SPLIT_PC] = c_town.town_num. The idea is to allow the party to leave town while split without losing their stuff. That line won't fix it (in fact it won't do anything), but adding it is probably a necessary first step to making this change. I'm not going to figure out the details of how to make the change right now though.

Link to comment
Share on other sites

Another bug fix :

 

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) :

Click to reveal..
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;

creature_data_type *cur_monst;

Boolean exploding = FALSE;

 

skill = (overall_mode == MODE_FIRING) ? adven[current_pc].skills[sKILL_ARCHERY] : adven[current_pc].skills[sKILL_THROWN_MISSILES];

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,(int)adven[current_pc].status[1]);

hit_bonus = (overall_mode == MODE_FIRING) ? adven[current_pc].items[missile_inv_slot].bonus : 0;

hit_bonus += adven[current_pc].statAdj(1) - can_see(pc_pos[current_pc],target,0)

+ minmax(-8,8,(int) adven[current_pc].status[1]);

if ((skill_item = adven[current_pc].hasAbilEquip(41)) < 24) { //accuracy items

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 == RACE_NEPHIL)

hit_bonus += 2;

 

if (adven[current_pc].items[ammo_inv_slot].ability == 172) //exploding arrows ?

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 == TRUE) {

take_ap((overall_mode == 12) ? 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(radius2,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();

 

if (adven[current_pc].items[ammo_inv_slot].variety != 25) {//no-ammo missile type ?

if (adven[current_pc].items[ammo_inv_slot].ability != 170)//returning missile ?

adven[current_pc].items[ammo_inv_slot].charges--;

else adven[current_pc].items[ammo_inv_slot].charges = 1;

if ((adven[current_pc].hasAbilEquip(11) < 24) && (adven[current_pc].items[ammo_inv_slot].ability != 170))//drain missile item equipped && not returning missile ?

adven[current_pc].items[ammo_inv_slot].charges--;

if (adven[current_pc].items[ammo_inv_slot].charges <= 0)// no more ammo ?

adven[current_pc].takeItem(ammo_inv_slot);

}

return;

}

 

combat_posing_monster = current_working_monster = current_pc;

draw_terrain(2);

void_sanctuary(current_pc);

//play_sound((overall_mode == 12) ? 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 13:

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 12: case 14:

m_type = (adven[current_pc].items[ammo_inv_slot].isMagic()) ? 4 : 3;

break;

}

run_a_missile(pc_pos[current_pc],target,m_type,1,(overall_mode == 12) ? 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 = &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 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 ((adven[current_pc].hasAbilEquip(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)

adven[current_pc].takeItem(ammo_inv_slot);

}

}

 

combat_posing_monster = current_working_monster = -1;

move_to_zero(adven[current_pc].status[0]);

print_buf();////

}

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.

 

 

Quote:
The links in the first post in the Bug Fixes section may help with the time issue...

I've read them. What would be wonderful is an example of the bad behavior wink

I think that event check skipping during Rest (outdoor/inn/have_a_rest node) is the cause of (what i've percieved as) the bug. I didn't find any difference between an in-town and outdoor day, as others mentionned ... So i'm wondering if i have really understood the problem grin

 

Quote:
Small change to consts.h

Adopted.

 

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

 

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

 

Edit2 : The game didn't crash when i leaved town with number more than 100. However, during one of my test, the last (dummies) towns i created to reach number 100 were completely screwed (all named ÿÿÿÿ, mixed graphics in town terrains, ...), so i suspect an array error to lurk somewhere in the code. I will continue the investigation.

 

Two more "bugs fix" :

 

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.

 

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

 

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 ?)

 

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.

Link to comment
Share on other sites

Ok enough edit, this one will get a new post ...

 

Investigating the 100 town bug, i found that the saving of the maps in town with number more than 100 was faulty (disappearing squares, ...). So i took a look in the code, to find what was happening.

 

stored_town_maps_type is the structure where maps are stored. In Mac's code, it's a [200][8][64] array (200 towns, 8 is x axis (bitwise coded when read or written), 64 is y axis) and everything seems ok.

In Windows code it was a [100][8][64] array. What about the 100 other towns ? No problem, there was a second stored_town_maps_type named town_maps2 that does the job (another leftover from when the 100 town limit was reached in Exile III ?). Unfortunately, the confusion between the two stored_town_maps_type was predictable.

First there was a check to see if town number was more than 100 (if the case, use town_maps2). The reading of 100+ towns maps was well coded, but when it came to save them, it was chaos : the original version of the code saved the value from the first town_maps at the number of the town index (i.e 100+, out of the array) in town_maps2 and the corrected one only changed the function to take value into town_maps2 (but still out of the array).

 

Simply telling the function to look at the number_of_town - 100 index would have corrected the bug, but there is no point at having two array while one can do the job (even more when the Mac's code only use one !), so i changed the stored_town_maps_type to match the correct (Mac) one and modified the code accordingly.

 

I didn't have any crash, nor corrupted maps since ... Further testing would ensure that the bug is gone for good, but that should be ok.

 

Chokboyz

Link to comment
Share on other sites

Okay, still an odd choice though confused

Maybe Jeff choose to create another array instead of having to change the structure and checks all the code ... Nevermind, it's fixed after all smile

 

Some questions to people out there :

Originally Posted By: Alcritas
Creatures in one time place town encounters don’t check their life flag. For example, if you have a creature in a one time place town encounter with a life flag of 1, 5, that creature will appear when the one time place town encounter goes off, even if the 1, 5 flag has been set to 1.

Should it be fixed ? Wouldn't it break any legacy scenarios ?

 

Originally Posted By: Alcritas ?
If two friendly NPCs occupy the same space, and they both have dialogued personalities, talking to either of them will cause the game to freeze (note : infinite dialog loop).

This is cleary asking for trouble ... Should it be fixed and how ? (i've succesfully tested a fix that would only talk with the first placed character. Choosing the character you would like to talk to would be a little harder ... )

 

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.

Should the behavior described in the help file be implemented (compatibility, etc ...) ?

 

I'm always investigating empties (never seen any during all my tests) and timer problems (still guessing what the problem is).

 

Thanks,

Chokboyz

Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Alcritas
Creatures in one time place town encounters don’t check their life flag. For example, if you have a creature in a one time place town encounter with a life flag of 1, 5, that creature will appear when the one time place town encounter goes off, even if the 1, 5 flag has been set to 1.

Should it be fixed ? Wouldn't it break any legacy scenarios ?
I think it should be fixed, but I'm not sure whether it would break compatibility with older scenarios. If it could, then we'd want to find a way to fix it without breaking compatibility... and I have no idea how we would do that.

Originally Posted By: Chokboyz
Originally Posted By: Alcritas ?
If two friendly NPCs occupy the same space, and they both have dialogued personalities, talking to either of them will cause the game to freeze (note : infinite dialog loop).

This is cleary asking for trouble ... Should it be fixed and how ? (i've succesfully tested a fix that would only talk with the first placed character. Choosing the character you would like to talk to would be a little harder ... )
Well, the code does not allow a monster to move onto the same space as another monster, right? So there are therefore exactly two ways to get two monsters on one space: a) by summoning and B) by placing them in the editor. The first isn't a problem, because summoned creatures never have dialog. The second could be fixed by both including the change you mention (always pick the first character) and also by ensuring that the editor does not allow you to place a monster on a space when there is already a monster there.

Originally Posted By: Chokboyz
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.

Should the behavior described in the help file be implemented (compatibility, etc ...) ?
I see no reason to keep compatibility here.




Okay. I have committed revision 22. It's not completely stable and has a number of major bugs, but for the most part it works. It's a start towards reducing the redudancy of code. Until now there were three almost identical versions of dlogtool.c, and three almost identical versions of global.c, and three almost identical versions of sound.c, as well as a number of functions in the three graphics.c files that were almost identical. All these have been split out and merged into a single dlgtool.cpp, mathutil.cpp, soundtool.cpp, and graphtool.cpp respectively. These files and their corresponding headers may be found in the misc directory.

I have also made changes to many parts of the code, such as reducing the number of arrays. For example, dlogtool.c had several arrays with the prefix dlg_, several with the prefix item_, several with the prefix button_, and so on. Each of these sets of arrays is now a single array of structs. One nice thing about this is that the array of buttons is a lot clearer to look at (this is also helped by the introduction of several constants).

The draw_dialog_graphic function has been split into many sub-functions, each for a different type of graphic; the draw_dialog_function simply selects which sub-function to call. Most of the functions are pretty much unchanged from the original game code. I added code for drawing tall, wide, and large custom monster graphics, and removed the code for B&W graphics since the graphics sheet it depended on does not exist (and presumably therefore it is never reached).

While these changes seem quite nice, I have unfortunately introduced a number of bugs as well. The major two are that the "edit terrain" dialog causes the scenario editor to crash, and the game and pc editor do not seem to be drawing any dialog controls at all (either that or they are drawing them off the bounds of the dialog). I will certainly attempt to fix these, but it will be difficult without the ability to debug, and any help would be appreciated. Obviously you can't actually run the program, but maybe you could look over the code a little. If you have time, of course. (My hypothesis is that win_draw_string() in graphtool.cpp may be to blame for the first problem; either that or something that executes just after it is called).
Link to comment
Share on other sites

About the Town Encounter/Life flag compatibility: Pict, 1b, 2a, and 2b are unused in the One-Time Place Town Encounter node, so it should be fairly easy to include a compatibility switch.

 

As for prohibiting the designer from placing multiple monsters on a space, I think that could potentially have legitimate uses. I think just having the game call the dialog of the first-placed monster should fix it well enough.

 

I tried replicating the Empty problem based on what happened with The Killing Cave, but unfortunately couldn't. However, a different type of Empty (with stats) is summoned by the default Bladbase Scale Necklace. The necklace before it (Lifesaver Amulet) and the one after it (I forget) have ability strengths of 0, so the Scale summons Empties and the one after is effectively useless.

Link to comment
Share on other sites

Quote:
I think it should be fixed, but I'm not sure whether it would break compatibility with older scenarios. If it could, then we'd want to find a way to fix it without breaking compatibility... and I have no idea how we would do that.

Ok, that's added on the todo list (provided i find a non-destructive way to do this) ...

Quote:
Well, the code does not allow a monster to move onto the same space as another monster, right? So there are therefore exactly two ways to get two monsters on one space: a) by summoning and B) by placing them in the editor. The first isn't a problem, because summoned creatures never have dialog. The second could be fixed by both including the change you mention (always pick the first character) and also by ensuring that the editor does not allow you to place a monster on a space when there is already a monster there.

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

Quote:
I see no reason to keep compatibility here.

Will implement it so; crossing fingers that no crazy designer fiddled with the pic value smile

I will take a look at the code to help you if i find the time (i barely find the time to do work, so i may slow down a bit wink ). I am absolutely inexperienced with Mac coding (graphically speaking) though.
Nonetheless, it's nice to see the code slowly taking shape (are we on the way to cross-platforming ?) grin

Thanks,
Chokboyz

Edit: To ADoS :

Quote:
About the Town Encounter/Life flag compatibility: Pict, 1b, 2a, and 2b are unused in the One-Time Place Town Encounter node, so it should be fairly easy to include a compatibility switch.

That's what i plan to do ...

Quote:
As for prohibiting the designer from placing multiple monsters on a space, I think that could potentially have legitimate uses. I think just having the game call the dialog of the first-placed monster should fix it well enough.

I agree with you. The fix above should be enough to prevent the infinite loop. (though,i still think someone that places two npc with two personnalities on the same block, preventing them from moving is asking for trouble grin )

Quote:
I tried replicating the Empty problem based on what happened with The Killing Cave, but unfortunately couldn't. However, a different type of Empty (with stats) is summoned by the default Bladbase Scale Necklace. The necklace before it (Lifesaver Amulet) and the one after it (I forget) have ability strengths of 0, so the Scale summons Empties and the one after is effectively useless.

Too bad for the Empties, thanks to you for having tried.
The Lifesaver Amulet doesn't need charges to work.
You're right for the two others : the Scale Necklace summons "real Empties" (i.e monsters 0 with stats, ...) because it ability strengh is 0 and the Amber Periaph is useless. That should be fixed in the corrected Bladbase.exs.
Link to comment
Share on other sites

Once I've fixed the major graphics bug, I'll add all your fixes starting from this post.

 

 

I'm thinking of using the Google Code Issues section as a personal todo list (though of course anyone may submit bug reports or feature requests there). Otherwise I may just keep forgetting about things.

 

Besides the stuff that you've done which I haven't yet incorporated, I need to make use of the constants in consts.h, add the option to skip startup splash, fix several major bugs... and I think there's a few other things too.

 

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

 

Ishad Nha, would you like repository access? If so, email me.

 

EDIT: I just noticed that SDF(304,9) is checked in one place, but never appears to be assigned to... smirk

Link to comment
Share on other sites

Quote:
Once I've fixed the major graphics bug, I'll add all your fixes starting from this post.

Ok, i'll try to refrain from doing more fixing then wink

Quote:
I'm thinking of using the Google Code Issues section as a personal todo list (though of course anyone may submit bug reports or feature requests there). Otherwise I may just keep forgetting about things.

Go ahead, that's a good idea.

Quote:
Besides the stuff that you've done which I haven't yet incorporated, I need to make use of the constants in consts.h, add the option to skip startup splash, fix several major bugs... and I think there's a few other things too.

I haven't used constants from CONSTS.h much too. What others major bugs are you looking to fix ? I should add them to my todo list if not already there wink

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.

Quote:
I just noticed that SDF(304,9) is checked in one place, but never appears to be assigned to...

It is, apparently, a flag that allow/prevent some sounds from being played (that's not clear, it seems to be doubling as a No Sound check). It is assigned to 0 during the initialization of the game (cf load_file(), etc ...) so it's utterly useless.

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Quote:
Besides the stuff that you've done which I haven't yet incorporated, I need to make use of the constants in consts.h, add the option to skip startup splash, fix several major bugs... and I think there's a few other things too.

I haven't used constants from CONSTS.h much too. What others major bugs are you looking to fix ? I should add them to my todo list if not already there wink
The bugs introduced by my refactoring of the dialog code. The first one is already fixed – it was simply the result of switching the order of two if statements, I think... though that doesn't explain why it worked fine in the scenario editor. In any case, the Windows version shouldn't have these bugs, though if you incorporated my refactorings you may have introduced the bugs or similar bugs.

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.
The Mac version came first, so I think we should use the Mac graphics. I will construct a set of BMPs at some point and email them to you.

One thing of note is the fact that Windows has less graphics sheets than Mac. Several of the Windows graphics sheets consist of two or more Mac graphics sheets attached together. I'm not sure whether it'd be better to keep that discrepancy, or to alter the Windows code to make use of the split sheets, or alter the Mac code to make use of the combined sheets, or some combination of both.

Originally Posted By: Chokboyz
Quote:
I just noticed that SDF(304,9) is checked in one place, but never appears to be assigned to...

It is, apparently, a flag that allow/prevent some sounds from being played (that's not clear, it seems to be doubling as a No Sound check). It is assigned to 0 during the initialization of the game (cf load_file(), etc ...) so it's utterly useless.
In that case... shall we remove it? Then we can use it for something else.

By the way, I was thinking we could increase the size of the stuff done array. Obviously that would be a part of the file format rewrites, but I would propose extending its width to, say, 50 instead of 10.

Originally Posted By: Chokboyz
Quote:
I'm thinking of using the Google Code Issues section as a personal todo list (though of course anyone may submit bug reports or feature requests there). Otherwise I may just keep forgetting about things.

Go ahead, that's a good idea.
I shall go do that then. For the moment, I'll mostly just add bug reports. You can do the same if you like; also you can add the OS-WINDOWS label if the bug is also present in the Windows version.
Link to comment
Share on other sites

Quote:
One thing of note is the fact that Windows has less graphics sheets than Mac. Several of the Windows graphics sheets consist of two or more Mac graphics sheets attached together. I'm not sure whether it'd be better to keep that discrepancy, or to alter the Windows code to make use of the split sheets, or alter the Mac code to make use of the combined sheets, or some combination of both.

There is 10 monsters sheets (MONST1.BMP to MONST10.BMP) and 6 terrains sheets (TER1.BMP to TER6.BMP) in the Windows version of the graphics files.
I prefer having less sheets, but that's just a matter of taste wink This isn't urgent though, we will have time to discuss it ...

Quote:
In that case... shall we remove it? Then we can use it for something else.

Feel free to remove all references to it (i did) : it is, in state, useless (the only checks that involves it are always true).

Quote:
By the way, I was thinking we could increase the size of the stuff done array. Obviously that would be a part of the file format rewrites, but I would propose extending its width to, say, 50 instead of 10.

That may be a good idea for later ... Isn't 50 a little too much though wink

Quote:
also you can add the OS-WINDOWS label if the bug is also present in the Windows version.

I will check that.

I took a look at the Mac code and felt a little lost here ... I may not be of a great help as i don't know most of the functions/variable/types used ... And i can't even test my changes crazy
But i will try, anyway smile
From what you have said, it seems you have already solved the "Editing Terrain button crashed the editor" problem ? The problem remains is "game and pc editor do not seem to be drawing any dialog controls ", right ?

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).
Link to comment
Share on other sites

Originally Posted By: Chokboyz
There is 10 monsters sheets (MONST1.BMP to MONST10.BMP) and 6 terrains sheets (TER1.BMP to TER6.BMP) in the Windows version of the graphics files.
I prefer having less sheets, but that's just a matter of taste wink This isn't urgent though, we will have time to discuss it ...
I'm thinking a combination would be best. The Mac version has twice as many monster sheets, for example – attacking versions have separate sheets. On the other hand, I think it would be simpler to deal with the buttons if they were not all on one sheet. The Mac version has two sheets for each regular button (one for normal state, one for pressed state). Arranging it so that there is one button per sheet (normal and pressed versions on the same sheet) seems like a good idea.

Originally Posted By: Chokboyz
Quote:
In that case... shall we remove it? Then we can use it for something else.

Feel free to remove all references to it (i did) : it is, in state, useless (the only checks that involves it are always true).
I only found one reference to it, though you mentioned something in the startup. I do in fact have two lines of code in the startup that set SDF(NO_FRILLS) and SDF(NO_SOUNDS) to 0 – I suppose it's possible that one of those was originally affecting SDF(304,9). In any case, I'll delete that one reference.

Originally Posted By: Chokboyz
Quote:
By the way, I was thinking we could increase the size of the stuff done array. Obviously that would be a part of the file format rewrites, but I would propose extending its width to, say, 50 instead of 10.

That may be a good idea for later ... Isn't 50 a little too much though wink
With modern computers we have plenty of memory, so I'd say better a little too much than too little. Especially if we are keeping the SDF array a fixed size. I could have suggesting making it 300 wide, though. I think somewhere between 30 and 70 is probably more reasonable.

Originally Posted By: Chokboyz
Quote:
also you can add the OS-WINDOWS label if the bug is also present in the Windows version.

I will check that.

I took a look at the Mac code and felt a little lost here ... I may not be of a great help as i don't know most of the functions/variable/types used ... And i can't even test my changes crazy
But i will try, anyway smile
From what you have said, it seems you have already solved the "Editing Terrain button crashed the editor" problem ? The problem remains is "game and pc editor do not seem to be drawing any dialog controls ", right ?
No, no, it's the other way around. I've solved the "not drawing controls" problem but still have the "editing terrain crash" problem.
Link to comment
Share on other sites

Quote:
I only found one reference to it, though you mentioned something in the startup. I do in fact have two lines of code in the startup that set SDF(NO_FRILLS) and SDF(NO_SOUNDS) to 0 – I suppose it's possible that one of those was originally affecting SDF(304,9). In any case, I'll delete that one reference.

All SDF are reinitialized to 0 at each party initialization, then some options are loading from the bladmisc.dat (if i'm not mistaken) and others initialized. I would also say it's a leftover and delete it confidently.
Click to reveal.. (proof)
void init_party_scen_data()
{
short i,j,k,l;
Boolean stored_item = FALSE;
short store_help;

party.age = 0;
store_help = PSD[306][4];
for (i = 0; i < 310; i++)
for (j = 0; j < 10; j++)
party.stuff_done[ i ][j] = 0;
PSD[306][4] = store_help;
party.light_level = 0;
party.outdoor_corner.x = scenario.out_sec_start.x;
party.outdoor_corner.y = scenario.out_sec_start.y;
party.i_w_c.x = 0;
party.i_w_c.y = 0;
[...]


Quote:
With modern computers we have plenty of memory, so I'd say better a little too much than too little. Especially if we are keeping the SDF array a fixed size. I could have suggesting making it 300 wide, though. I think somewhere between 30 and 70 is probably more reasonable.

Yup, that's definitely a possibility. Should be added to the suggestion list, if not already.

Quote:
No, no, it's the other way around. I've solved the "not drawing controls" problem but still have the "editing terrain crash" problem.

Wow, must be post confusion wink

Quote:
What is the expected output? What do you see instead?
It should display the edit terrain dialog, and it does, but then it crashes.

At what moment does it exactly crash (i.e what is displayed : only the dialog, some strings in it, are the led lit, the field filled , ... ?)

Note : i've improved the fix that was redrawing the map after each terrain changes : when there were too many changes the performances dropped significantly (i noticed this on the burning farmhouse in the Deadly Goblins scenario : rapidly there are so many quickfires that the map refreshes during 1-2 seconds rolleyes). So, I wrote a function that only redraw given rectangles on the map, saving (much) time on the process. Now one can follow the fire spreading without any slowdown. I tested this new fix with some other massive map transformations and the gain was impressive.
Unfortunately, i don't know if the code is platform-dependant (i fear so) and can surely be cleaned a little ... However it was mainly an adaptation of the classic draw_map() function, so i think a Mac equivalent can be coded pretty easily.

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Quote:
What is the expected output? What do you see instead?
It should display the edit terrain dialog, and it does, but then it crashes.

At what moment does it exactly crash (i.e what is displayed : only the dialog, some strings in it, are the led lit, the field filled , ... ?)
It crashes sometime after beginning to draw the second-last dialog item, which is the string "Enter properties for this terrain type. For a detailed description of the fields, see the documentation. Note that, for terrain types 90 and below, only changes to the picture and shortcut key will be recorded.". And it exits with status 1, which suddenly makes me wonder if there's an ExitToShell() somewhere that's being reached...

EDIT: Except that there does not appear to be an ExitToShell() in the relevant area of code.
Link to comment
Share on other sites

Yes, the point is reached. The problem occurs while drawing the dialog, not while initializing it (as far as I can figure out, anyway).

 

 

By the way, I uploaded the Mac version of the graphics here. I also proposed splitting and combining various graphics on both ends – see the info.txt file.

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Originally Posted By: Chokboyz
Quote:
I just noticed that SDF(304,9) is checked in one place, but never appears to be assigned to...

It is, apparently, a flag that allow/prevent some sounds from being played (that's not clear, it seems to be doubling as a No Sound check). It is assigned to 0 during the initialization of the game (cf load_file(), etc ...) so it's utterly useless.
In that case... shall we remove it? Then we can use it for something else.


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.
Link to comment
Share on other sites

That is a good idea, though it doesn't necessarily need to use SDF(304,9). It could use, say, SDF(305,7).

 

At the moment, SDF(304,x) is used only for party-splitting information, SDF(305,x) is used primarily for party status effects (flying, stealth, etc) but also holds a few preferences, and SDF(306,x) is filled with preferences. Also, I'm not quite sure what SDF(305,9) is, but it appears to store the number of hostile monsters that have seen you (?).

Link to comment
Share on other sites

I've been unable to locate the Mac editor error, since i don't have a way to pinpoint the source of the error smirk

Have you succeeded in locating the precise point where the program crash (i.e what function, what instruction, etc ...)?

You've changed so many things concerning terrains graphics (for example, csp(813,14,store_ter.picture - 400,PICT_TER_ANIM_TYPE); regroups the original csp(813,14,store_ter.picture - 100,PICT_TER_ANIM_TYPE); and the -300 that is later used for animated terrain graphics) that it can be pretty anything (a check that uses the old notation for example).

I would investigate how the function put_ter_info_in_dlog behaves (i.e if everything that is called, is called with the right argument) and the rest of the function edit_ter_type() if it were possible ...

 

Originally Posted By: Celtic Minstrel
The problem occurs while drawing the dialog, not while initializing it (as far as I can figure out, anyway).

The drawing of the "Enter properties for this terrain ..." string is done in cd_create_dialog_parent_num(813,0); (precisely in GetNewDialog(...); speaking of which, are you sure the GetDialogWindow() is necessary ?) and since the next instruction is reached ...

 

Did you also check if your ressources files were ok ?

 

Without a way to test my guess, i'm pretty useless concerning this problem crazy

 

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)

Quote:
Also, I'm not quite sure what SDF(305,9) is, but it appears to store the number of hostile monsters that have seen you

It seems like it is a counter of "hostile activity" : if you've succesfully hide from monsters for more than 30 turns, the town gets to its "placid" state ... I didn't look if this was used in the game though ...

 

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.

 

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 ?).

 

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

 

Chokboyz

Link to comment
Share on other sites

Originally Posted By: Chokboyz
I've been unable to locate the Mac editor error, since i don't have a way to pinpoint the source of the error smirk
Have you succeeded in locating the precise point where the program crash (i.e what function, what instruction, etc ...)?
You've changed so many things concerning terrains graphics (for example, csp(813,14,store_ter.picture - 400,PICT_TER_ANIM_TYPE); regroups the original csp(813,14,store_ter.picture - 100,PICT_TER_ANIM_TYPE); and the -300 that is later used for animated terrain graphics) that it can be pretty anything (a check that uses the old notation for example).
I would investigate how the function put_ter_info_in_dlog behaves (i.e if everything that is called, is called with the right argument) and the rest of the function edit_ter_type() if it were possible ...
I didn't change much in that function, really – just the last few lines. I can't see anything amiss there.

I think all the checks that use the old notation would have failed with a "too few arguments" error, though it's possible I missed one that wouldn't. Still, I'm convinced that the problem is not with the icon-drawing portion of the code, because my debug strings tell me that the icon is already drawn before the crash occurs.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
The problem occurs while drawing the dialog, not while initializing it (as far as I can figure out, anyway).

The drawing of the "Enter properties for this terrain ..." string is done in cd_create_dialog_parent_num(813,0); (precisely in GetNewDialog(...); speaking of which, are you sure the GetDialogWindow() is necessary ?) and since the next instruction is reached ...

Did you also check if your ressources files were ok ?

Without a way to test my guess, i'm pretty useless concerning this problem crazy
I have no idea if the GetDialogWindow is necessary, but I would assume it is, since it's there.

As for the resources... somehow the Disabled bit was set on the Animated button, but clearing it didn't fix the problem Then I noticed that it was also set for the OK button, so I cleared that as well. Then I noticed it was set for a lot of other items, so I tried both clearing it for all of them and setting it for all of them, neither of which worked. Then I thought to check the other resource, but nothing seemed amiss there either. So I think it's safe to assume it's not the resources.

I know that win_draw_string() is the function that ultimately draws the text to the screen, but it's a long complicated function and I'm not finding it easy to locate just where (if anywhere) in the function the crash occurs. The function is called (indirectly) from cd_redraw(), which is called by cd_event_filter(), which is called (indirectly) by edit_ter_type().
EDIT: Huh. It turns out that the crash doesn't occur in that function. A printf statement at the end of the function was printed before it crashed.

Unfortunately I can't debug since debugging only works for Intel binaries and file loading only works for PowerPC binaries, but I'm sure I can manage. Maybe it would be better to drop this problem and instead work on getting file loading to work with an Intel binary. Then I can use the debugger to help figure out exactly where it crashes.

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)

The first could work, but I think simply skipping the boom spaces once a single one has been placed would work. It would not apply in combat, of course. The problem is that you step on lava (for example), and it damages each party member one at a time, displaying six separate effects. If it simply displayed a single effect for the whole party, the problem would be averted.

On the other hand, maybe that's the same as the first one... I'm not sure...

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'll look into that at some point.

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 ?).
I'm not sure, but it could be a relic from Exile 3 which had a lighet background pattern.

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 ...
No need to keep compatibility in the long run, except by recognizing and reading the older format. I think the one that alters the town record could actually be better – the special node one seems like it could accidentally prevent you from accessing any map. Unless you intend it to work something like hide/show town.

I'm not sure it's a good idea to be able to hide the outdoors map, anyway. If a town map is unavailable, it's because there's some kind of spell preventing you from mapping it (or something). If an outdoors map were unavailable, that would mean the spell covers an immense area. Also, towns are generally the places of interest, so there wouldn't be much need for preventing outdoor mapping (especially when you can't cast Magic Map outdoors).
Link to comment
Share on other sites

Success!! I got the scenario editor to open a scenario when compiled as Intel code, and now can use the debugger to figure out what's going wrong in the terrain dialog.

 

EDIT: This is odd. There appears to be a null pointer access between leaving win_draw_string() and re-entering char_port_draw_string() which calls it. How on earth can I fix something like that? smirk

 

I dunno if it's relevant, but in the if statement "if (i - last_line_break > 1)", the debugger would not let me "step over" the c2pstr and DrawString calls for some reason – I had to step through assembly – and when returning the stack listing was no longer accurate. I think I'll try commenting out those calls to see if they're the culprit; however, if they are, I still don't know how I would fix it.

 

EDIT: Bypassing that if statement fixed it. I suspect it may actually have been the strncpy call or the strcpy call rather than the other two – I'll look into it.

 

Next dialog bug on the agenda: figure out why LEDs are sometimes not drawn.

Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Success!! I got the scenario editor to open a scenario when compiled as Intel code, and now can use the debugger to figure out what's going wrong in the terrain dialog.

Good job, things will be easier from now on ...

By the way, in win_draw_string() :
Click to reveal..
if (on_what_line == LINES_IN_TEXT_WIN - 1) <= this is asking for trouble
i = 10000; <= as soon as the text is 11 (?) lines long

if (i - last_line_break > 1) {
strcpy((char *)str_to_draw,(char *)null_s);
strncpy ((char *) str_to_draw,(char *) c_str + last_line_break,(size_t) (i - last_line_break)); <= copy the next 10000 - last_line_break bytes to str_to_draw starting from c_str + last_line_break
sprintf((char *)str_to_draw2," %s",str_to_draw); <= this is useless, as not used (replaced by c2pstr)
//if (strlen((char *) str_to_draw2) > 3) {
// str_to_draw2[0] = (char) strlen((char *)str_to_draw);
// DrawString(str_to_draw2);
//}
if(strlen((char*)str_to_draw) > 2){
c2pstr((char*)str_to_draw);
DrawString(str_to_draw);
}

How long is the "Enter properties for this terrain type ..." string ?

Originally Posted By: Thuryl
It seems like a Show/Hide Map node would provide more flexibility to the designer than putting it in the town options, though. That's never a bad thing. There's no reason not to let people prevent outdoor mapping if for some reason they want to.

I agree, so i will (temporary or not) implement it as a global variable (SDF[30x][y]).

Chokboyz
Link to comment
Share on other sites

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Success!! I got the scenario editor to open a scenario when compiled as Intel code, and now can use the debugger to figure out what's going wrong in the terrain dialog.

Good job, things will be easier from now on ...
Well, I still need to apply this fix to the game and the PC editor, but that shouldn't be too hard...

Originally Posted By: Chokboyz
By the way, in win_draw_string() :
[...]
How long is the "Enter properties for this terrain type ..." string ?
It's 256 characters. I just made the exact same discovery a few minutes ago – the ultimate culprit was the if (on_what_line == LINES_IN_TEXT_WIN - 1) i = 10000;", which I have now commented out.

In the meantime, I made numerous fixes to the functions that draw the dialog controls. Custom graphics are now displayed in dialogs in the editor, and if it's a larger than 1x1 custom monster graphic it will even be scaled down like the preset graphics do (though it doesn't scale very well).

I think the only bug remaining in the dialog code is the one that sometimes causes a control to randomly be replaced with whiteness. It never happens in the scenario editor, though – I've only witnessed it in the game.

Another thing I did recently was to get the various files belonging to the game to display their proper icon. Saved games display the saved game icon, Blades of Exile Graphics and the .meg files display the scroll icon, scenarios display the scenario icon, and Blades of Exile Sounds displays an icon I modelled after the Exile III sounds icon. The book icon is unused, because I have no intention of using the original preferences file format – at some point I intend to switch to a plist preferences file.





The scenario header flags are 10/20/30/40 for Mac and 20/40/60/80 for Windows, right? I propose that when we rewrite the scenario format we choose the same header for Mac and for Windows – maybe something like 100/75/50/25. For scenarios in the new format, only PowerMacs would need to use the flip and port functions.

One thing I think we need before doing this, though, is a "map" of the scenario format (and also a "map" of the save file format). The structs give a good idea of the general format, but we also need to know if there is any padding in the file. (Note that the portability code doesn't seem to account for padding, so if it's there it must be the same on both platforms.)

Once we have a map, we need to create a function (or method) which reads the old file format one field at a time rather than in one large block.




I will commit another revision soon with all my changes so far. Have you made any attempt to duplicate my dialog code refactoring?
Link to comment
Share on other sites

Quote:
One thing I think we need before doing this, though, is a "map" of the scenario format (and also a "map" of the save file format). The structs give a good idea of the general format, but we also need to know if there is any padding in the file. (Note that the portability code doesn't seem to account for padding, so if it's there it must be the same on both platforms.)


There is no padding because the structs are the file format. (There may be padding in the sturct definitions themselves, which could change and which Jeff doesn't deal with, but that's just another reason to build a new, non-compiler determined file format.) Jeff just uses low level write operations, treates each struct as a block of bytes and writes it out. All you need to know is the ordering of the blocks/structs and the struct definitions.

I've thought a lot about this because of the file format work that I'm doing with BoA, and I'm not sure that there's any point in trying to read the old format in any more complicated way. Just keep the old data structures off in a namespace of their own, and when you need to read the old format, read it into a set of the old structures in much the same way that it's now done. Then, if you're introducing new in memory data structures, provide a way to construct those given the old data structures, and vice versa. This way you can read and write the old format to and from the old structures, convert between new and old structures, and read and write the new format to and from the new structures. If, however, you're not changing the in memory data structures then the job is much easier: largely preserve the old reading and writing routines, and simply also provide a new set which handle the new format.
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
I think the only bug remaining in the dialog code is the one that sometimes causes a control to randomly be replaced with whiteness. It never happens in the scenario editor, though – I've only witnessed it in the game.

This happened when displaying custom items with transparency in the Windows version. The problem was a RECT copied with src size despite being dest size (custom graphics src/dest size are often differents).

Originally Posted By: Celtic Minstrel
The scenario header flags are 10/20/30/40 for Mac and 20/40/60/80 for Windows, right? I propose that when we rewrite the scenario format we choose the same header for Mac and for Windows – maybe something like 100/75/50/25. For scenarios in the new format, only PowerMacs would need to use the flip and port functions.

Agreed, it should use the same header (thus i don't know which one ... 100/75/50/25 seems like a good choice).

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

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.

I haven't looked for the scenario format.

Originally Posted By: Celtic Minstrel
Once we have a map, we need to create a function (or method) which reads the old file format one field at a time rather than in one large block.

Seems like Ormus already did this in his version of the source code ...

Ah, and don't forget that party and pc are encrypted in save files ...

Originally Posted By: Celtic Minstrel
Have you made any attempt to duplicate my dialog code refactoring?

Not yet, i need time for this. And i need to work too wink

Chokboyz

Originally Posted By: Niedmand
All you need to know is the ordering of the blocks/structs and the struct definitions.

Ormus version of save_file follow the struct definition order. I think it's not legacy compatible, though.
Link to comment
Share on other sites

Originally Posted By: Niemand
There is no padding because the structs are the file format. (There may be padding in the sturct definitions themselves, which could change and which Jeff doesn't deal with, but that's just another reason to build a new, non-compiler determined file format.) Jeff just uses low level write operations, treates each struct as a block of bytes and writes it out. All you need to know is the ordering of the blocks/structs and the struct definitions.
The compiler-determined padding is kind of what I was thinking of. I'm not sure if there is any though. It's possible there isn't.

Originally Posted By: Niemand
I've thought a lot about this because of the file format work that I'm doing with BoA, and I'm not sure that there's any point in trying to read the old format in any more complicated way. Just keep the old data structures off in a namespace of their own, and when you need to read the old format, read it into a set of the old structures in much the same way that it's now done. Then, if you're introducing new in memory data structures, provide a way to construct those given the old data structures, and vice versa. This way you can read and write the old format to and from the old structures, convert between new and old structures, and read and write the new format to and from the new structures. If, however, you're not changing the in memory data structures then the job is much easier: largely preserve the old reading and writing routines, and simply also provide a new set which handle the new format.
Actually, I was thinking new in-memory data structures and a new file format. The actual layout of the in-memory structures may not change a lot, but I intend to make some of their elements more variable in size.

I like the idea of keeping a copy of the old structures, though. That would be useful when converting scenarios (in-memory for the game, in a new file for the editor) and save files (which I think I'll just convert without warning). Then the new structures can have a constructor that takes the old structure as a parameter...

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
I think the only bug remaining in the dialog code is the one that sometimes causes a control to randomly be replaced with whiteness. It never happens in the scenario editor, though – I've only witnessed it in the game.

This happened when displaying custom items with transparency in the Windows version. The problem was a RECT copied with src size despite being dest size (custom graphics src/dest size are often differents).
Right, something to consider then. Though that doesn't explain why it doesn't affect the scenario editor...

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
The scenario header flags are 10/20/30/40 for Mac and 20/40/60/80 for Windows, right? I propose that when we rewrite the scenario format we choose the same header for Mac and for Windows – maybe something like 100/75/50/25. For scenarios in the new format, only PowerMacs would need to use the flip and port functions.

Agreed, it should use the same header (thus i don't know which one ... 100/75/50/25 seems like a good choice).
I've added a check for these 4 flags in the load_scenario function. Obviously it doesn't do anything yet, but it's there now.

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

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.
Ooh, thanks, I had missed the presence of those three flags at the start. On Windows, is the first flag either 5790 or 1342? For a new save format, we could set that flag to some other random value. (We should avoid 40470 or 15877, which, if I've calculated correctly, are the byte-swaps of 5790 and 1342.)

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Once we have a map, we need to create a function (or method) which reads the old file format one field at a time rather than in one large block.

Seems like Ormus already did this in his version of the source code ...

Ah, and don't forget that party and pc are encrypted in save files ...
Wait, what? The only encryption I have noticed is for storing the password in the scenario.

Originally Posted By: Chokboyz
Originally Posted By: Celtic Minstrel
Have you made any attempt to duplicate my dialog code refactoring?

Not yet, i need time for this. And i need to work too wink
Fair enough. smile I'll probably give you a chance to catch up soon, once I iron out a few more things.
Link to comment
Share on other sites

Quote:
Actually, I was thinking new in-memory data structures and a new file format. The actual layout of the in-memory structures may not change a lot, but I intend to make some of their elements more variable in size.

I like the idea of keeping a copy of the old structures, though. That would be useful when converting scenarios (in-memory for the game, in a new file for the editor) and save files (which I think I'll just convert without warning). Then the new structures can have a constructor that takes the old structure as a parameter...


I heartily approve.

Quote:
The only encryption I have noticed is for storing the password in the scenario.

The game's savefiles have a really dumb, trivial cipher applied to them; each byte is XORed with the constant 0x5C.
Link to comment
Share on other sites

Originally Posted By: Celtic Minstrel
Ooh, thanks, I had missed the presence of those three flags at the start. On Windows, is the first flag either 5790 or 1342? For a new save format, we could set that flag to some other random value. (We should avoid 40470 or 15877, which, if I've calculated correctly, are the byte-swaps of 5790 and 1342.)

Yup, straight from the sources :
slot 0 ... 5790 - out 1342 - town //in town ?
slot 1 100 in scenario, 200 not in //in scen ?
slot 2 ... 3422 - no maps 5567 - maps// save maps ?


Quote:
Right, something to consider then. Though that doesn't explain why it doesn't affect the scenario editor...

I forget to precise that the faulty function was rect_draw_some_item() .

Originally Posted By: Niemand
The game's savefiles have a really dumb, trivial cipher applied to them; each byte is XORed with the constant 0x5C.

That's true for party data. The PCs data is "encoded" using the constant 0x6B wink

Quote:
Fair enough. I'll probably give you a chance to catch up soon, once I iron out a few more things.

As new bugs arose (char editor refuses to save the stored_item array if not in town ... It's incredible how bugs are always where you expect them the least rolleyes), it won't be anytime soon, i fear smirk

Chokboyz
Link to comment
Share on other sites

So if a scenario in the new format is loaded in an old version of Blades, is it going to trigger the "This scenario was created with Version 2.0 of Blades of Exile" message? This seems like the correct behaviour, since the message is already in the game, and it's less misleading than "This is not a valid Blades scenario file".

Link to comment
Share on other sites

That's a good question, Thuryl.

 

What I was proposing was to use a different set of 4 header flags to validate the file. The reason is that this would give us the greatest flexibility in redesigning the format. However, it does have the disadvantage that an older version of BoE would not recognize it as a scenario made with a later version.

 

However, looking at the scenario structure just now, I realized that this is not necessary. If we keep the original flags, then we don't actually lose any flexibility since the version data is stored immediately after the flags.

 

Therefore, I take back my proposal of changing the flags and replace it with the following proposal: use the Windows flags only. Then on Windows and on Intel Mac, no porting will be necessary unless an old-format scenario with the Mac flags is encountered. On a PowerPC Mac, on the other hand, porting will always be necessary unless an old-format scenario with the Mac flags is encountered.

 

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

 

Originally Posted By: Chokboyz

As new bugs arose (char editor refuses to save the stored_item array if not in town ... It's incredible how bugs are always where you expect them the least rolleyes), it won't be anytime soon, i fear smirk

Hmm, well, I keep running into more bugs too. I don't think the character editor even works at all right now.
Link to comment
Share on other sites

It would appear that there is a single byte of padding in the original scenario_data_type, between prog_make_ver[3] and num_towns. I don't suppose anyone can confirm or deny this?

 

EDIT: On closer inspection it appears that the padding appears later, probably after out_height, or maybe after default_ground. I think the conclusion is that we'll have to include the num_towns as part of the version header structure, because attempting to explicitly add a byte of padding to the scenario data structure minus the version information results in a second byte of padding being added implicitly. Unless there's a way to suppress this, of course.

Link to comment
Share on other sites

I just discovered the Memory Browser feature, and it suggests that there is no padding after all, at least in the top of the structure. I can only guess that there must have been a byte inserted somewhere else which was no longer needed once I shunted num_towns into the other structure. Or vice versa – the padding wasn't needed when num_towns was still there, but once it was gotten it was put back where it was in the original structure.

 

The main thing is that loading scenario and outdoor data appears to work perfectly now. All I need to do is figure out why the town data doesn't load right...

 

 

 

I suspect that Jeff took account of padding and carefully crafted his structures so that it would not be needed. That could explain the various "reserved" fields in some of the structures.

 

EDIT: I've determined that the town data isn't loading right because it's failing to skip past the outdoor section, which implies that the problem lies in the main body of the scenario data (where the size of each outdoor section is stored).

 

EDIT 2: Heh, and it appears that that's because I simply forgot to copy the out_data_size array from the old format structure into the new scenario object. That should be an easy fix then.

 

EDIT 3: Almost there – it now loads everything except the size-specific stuff (terrain and creatures).

 

EDIT 4: Eek, the code that was supposed to copy the old-format data into the new object was in fact copying it back into the old-format structure – ie, it was doing nothing at all. rolleyes

Link to comment
Share on other sites

If I may make a suggestion about a possible future feature, perhaps items with custom graphics could store the filename of the graphics file, so that as long as you keep the graphics file in the folder, you can keep the item with its original custom graphic even after leaving the scenario you got it in. Right now I'm using the two-pronged stick to represent Death Header's claws from Amazonian Saga in my souvenir collection scenario, for example, and that's somewhat disappointing.

Link to comment
Share on other sites

Originally Posted By: The Almighty Doer of Stuff
If I may make a suggestion about a possible future feature, perhaps items with custom graphics could store the filename of the graphics file, so that as long as you keep the graphics file in the folder, you can keep the item with its original custom graphic even after leaving the scenario you got it in. Right now I'm using the two-pronged stick to represent Death Header's claws from Amazonian Saga in my souvenir collection scenario, for example, and that's somewhat disappointing.
So, you're suggesting this so that we don't have to take away items with custom graphics when entering a new scenario? Well, that's a good idea, but I'm not sure I like that way of doing it. If the party has a lot of items with custom graphics, we would need to open up a lot of separate graphics files, store their contents in memory, and leave them there. Well, okay, we could probably grab the relevant graphics and paint them onto a blank in-memory sheet, then dispose of the extra files, but that's a lot of work to do each time you load a save file. Personally, I think it would be a better idea to do exactly that, but when you leave a scenario instead of when you load a saved game. Then the collected sheet could be stored either as part of the game file or as a separate companion file.

By the way, it would probably be a good idea to submit any suggestions to the issues page where they can be kept track of easier. You can still post them here, of course. I'm just pointing out that there's now a dedicated place for them. (The issues page is for both bug reports and feature suggestions, but please do not submit any bug reports until an executable file has been released.)





Does anyone want to hazard a guess about how these structures were intended to be used? From Ishad Nha's ... study ... of the Exile III town format, I'd guess they were used in E3 to create cities which could easily evolve over time, in chunks, or something; but it's not clear how they would do this. Do they work in conjunction with an existing town, including both the main town record and the size-specific record? Or do they replace the size-specific record? (Since they appear to lack terrain, I'd guess the former.)
Code:
struct city_block_type {    short block_type;    short block_destroy_time;    char block_alignment;    char block_key_time;    location block_loc;};struct city_ter_rect_type {    Rect what_rect;    unsigned char ter_type;    unsigned char hollow;};struct template_town_type {    creature_start_type creatures[30];    city_block_type city_block[15];    city_ter_rect_type city_ter_rect[10];};


It would be nice to add this feature back at some point. It's hardly urgent, but it would be something to think about.


Also, on journal entries (Exile 3-style where significant events are automatically recorded). The code to display the journal is already there, I'm pretty sure the dialog is present, and there are a number of scenario strings reserved for journal entries. I bet it could be added back quite easily – simply add a special node type or something like that.
Link to comment
Share on other sites

Quote:
So, you're suggesting this so that we don't have to take away items with custom graphics when entering a new scenario? [...] Personally, I think it would be a better idea to do exactly that, but when you leave a scenario instead of when you load a saved game. Then the collected sheet could be stored either as part of the game file or as a separate companion file.


I think that this would be the most sensible treatment, it's what I have proposed as something I would one day like to do with BoA.
Link to comment
Share on other sites

In Exile 3, a lot of the small towns were modular, composed of modules. (This meant they were 1,698 bytes in length rather than 2,782. It starts at town 120: Delan.)

In each modular town the last 220 bytes of the town record were composed of:

15 modules from the town(s) that contained all the modules and

10 rectangles for terrain.

Hence some legacies from Exile 3 may be a bit strange in BoE terms.

Link to comment
Share on other sites

Oh, nice, someone agrees with me. The only minor problem with that is that I would need to learn how to write BMP data to a file. A library would be quite useful there, so if you happen to know of one please say so. If you don't, though, I'll Google it later when some of the more crucial stuff is patched up.

 

Ishad, could you explain what you mean by "15 modules from the town"? A quick calculation shows that the size of template_town_type minus the size of template_town_type.creatures is indeed 220 bytes, so those 15 "modules" are almost certainly described by city_block_type. Do you know what each of the five fields of that struct mean? And also, what are the terrain rectangles for? What do they do? (As far as you know, that is.)

 

Okay... small towns in E3 are 2782 bytes? BoE small towns are 5446 bytes, plus all the town strings and speech! That's 3506 bytes for the primary town_record_type, followed by 1940 bytes for the tiny_tr_type which holds the actual terrain and creatures, as well as room rectangles. Does that mean all E3 towns are smaller than a BoE town of the same size?

Link to comment
Share on other sites

If you want to read and write image files from Carbon and do drawing with Quickdraw (the way that matters currently stand) the easiest way is to use Quicktime. See the Import and Export Reference for QuickTime for a list of the functions that are available, and if you'd like to see how I used them it's in the Graphic Adjuster Source.

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