Jump to content

Chokboyz

Member
  • Posts

    428
  • Joined

  • Last visited

    Never

Posts posted by Chokboyz

  1. Quote:
    Has the bug where conveyor belts stop working when reloading a saved game also been fixed?


    I didn't encounter the bug, but will investigate ... (seems like a belt_present being reset when loading)


    Quote:
    Drop chances almost certainly are affected: there are documented cases of items with a 100% drop rate failing to drop.


    Ok, on to-do list wink

    Chokboyz
  2. Will be away of few days, so won't be able to work on bug fixing smile

     

    Last bug fixes (i will post the code when i return) :

     

    • Placed conveyor resulting from place/swap/transform terrain when no prior conveyor was present weren't functional. Fixed.

      Just needs to put a belt_present = true if the terrain is a conveyor when changing the terrain.

    • No Step on sound option was taken in account. Fixed

      In fact there were no code using the step_sound variable from the terrain struct. All the sound were hardcoded, so i wrote the missing code.

      Which leads to an aesthetic question : should swamps play no sound when walking on them (like Exile III and original BoE) or the squish (trash) sound (default sound on the BoE editor) ?

    • Affect Statistic Node probability check was wrong. It draws a number between 0 and 100 and if the number is strictly less than pic the stats were changed. Obviously even a 100 percent chance had 1 chance on 101 to fail. There may be others functions (dropping chances ?) affected by this glitch, will check it when i returns.

    Originally Posted By: Ishad Nha
    Quick fix may be the only thing happening any time soon

    Unless there is a common (hopefully cross-platform) build, i fear it may.

     

    Good luck, with your modifications to the editor (a "boat" icon, would indeed be useful wink )

     

    Chokboyz

  3. Quote:
    just the catalog info call that fails, and I can't figure out why.

    The function seems correct to me ... (from what i can tell from only looking at the prototype smile )
    Is there a way to look inside iter to see if it's empty ?

    Apart from that, have you tested if your check if(cur_entry == numScens) was succeding ?

    Good luck,
    Chokboyz
  4. The "town dies on day X" is also affected by the funky day_reached function (not the node).

     

    Moreover, the editor was incorrectly preventing the designer to use the 10 major event (in fact, both -1 and 0 values don't do a thing, but the error text was saying to choose value between 0 and 9, -1 being do nothing). That has been corrected.

     

    Here is the changed lines 1029-1030 in the TOWNOUT.cpp file (ormus' build scenario editor code) :

    if (cre(town.town_chop_key,-1,10,"The event which prevents the town from becoming abandoned must be from 1 to 10 (-1 or 0 for none)."

    ,"",832) == TRUE) return FALSE;

     

    Apart from that, the Hide Town node being fixed and working, i assume that no legacy scenario used this broken feature (the check was done in spec2a instead of spec1b, so maybe someone figured this out ?) ...

     

    Chokboyz

     

    Edit : and a nifty one to finish : a character without the nimble trait is actually better at disarming trap than a nimble one

     

    Click to reveal.. (proof)
    if (traits[TRAIT_NIMBLE] == FALSE) r1 -= 6; // if not nimble substract 6 to random_roll1

     

    if (r1 < trap_odds[skill]) // if random_roll1 is less than trap_odd

    //depending of the picklocking skill

    {add_string_to_buf(" Trap disarmed. "); //disarm trap

    return true;

    }

     

    Of course, here is short trap_odds[30] = {5,30,35,42,48, 55,63,69,75,77,

    78,80,82,84,86, 88,90,92,94,96,98,99,99,99,99,99,99,99,99,99};

    Corrected of course (- to +).

  5. Quote:
    Theoretically possible, but in that case wouldn't I get a "file folder not found" error when making the FSRef for the directory?

    Yup, but aren't you squishing the err value resulting from FSPathMakeRef when assigning it to the output of FSOpenIterator ?
    Let's imagine that FSPathMakeRef fails and ref is empty. Then FSOpenIterator has nothing to do thus doesn't return an error.
    Then FSGetCatalogInfoBulk is called with iter which can be absolutely everything since it hasn't been initialized ...
    FSOpenIterator should report an error if iter was not properly open ...

    Is the function working when using fullpath ?

    Besides, we're assuming that cur_entry is valid since we don't know where it is declared smile

    An hypothesis though, wink
    Chokboyz
  6. Quote:
    "Day Reached?" node, which is apparently not affected by this bug.

    Indeed, the day_reached function is bypassed for this node :

    Quote:
    case 147:
    if (calc_day() >= spec.ex1a) //get the current day and evaluate
    *next_spec = spec.ex1b; // if true, call the next special
    break;

    Chokboyz
  7. Quote:
    Did anyone actually figure out that it worked that way, though? If no-one ever realized this quirk, and no-one wrote scenarios relying on it, then I think it's safe to remove it.


    Quote:
    I don't think anyone figured it out: we just knew that it didn't seem to work properly


    Ok, the day checking function will be fixed. In a first time, there will be a switch to revert back to the old weird one. If it happens (very likely) that no scenario uses the function, it will be definitely integrated.

    I assume also that no scenario would rely on character buggily appearing/disappearing at Day X/Event Y, because that has already be fixed smile

    Quote:
    preserve backwards compatibility by having the

    wink

    Chokboyz
  8. I may be wrong, but i though FSPathMakeRef used POSIX paths :

     

    Blades of Exile Scenarios/ vs Blades of Exile Scenarios:

     

    confused

     

    Also, in the windows code, the custom scenario problem was caused by the program looking in the wrong directory (because an OpenFileName function changed the working directory.

     

    Hope it helps,

    Chokboyz

  9. The Appear/Disappear on Events cases weren't working either. That has been fixed, the problem was exactly the same.

     

    While i was at it, i changed the dialogs in the Major Event has Occured Node so that it says to choose a value between 1 and 10 (not 0 and 9). It was the same glitch as the Place Town Encounter Node.

     

    Quote:
    That's the most boneheaded thing I've ever seen Jeff do, and I don't say that lightly.

    That was indeed an head-scratching choice ... I think i may be a leftover from the Exile III to BoE porting though.

    Fixing that (or not) without breaking anything is the real challenge crazy

     

    Chokboyz

  10. The Appear/Disappear on day X feature has been fixed ...

     

    All the monsters are placed in a town the first time you enter it and won't be until the town is reinitialized (by the debug function or other). They are not placed again when you reenter the town to save time.

     

    The first problem was that the part of the code checking if there's a monster to Appear/Disappear on day X in the town, was done during the first time placement of the monsters and subsequently ignored (in TOWN.cpp, line 197 of Ormus' build). The checks needs to be put outside of the if (monsters_loaded == FALSE) loop.

     

    The second was that setting c_town.monst.dudes[ i ].active to 0 may work in the previous loop, but out of it, it must be set to 1.

     

    Finally (the funky part wink ) when you check if a day is reached, the game checks that the day + 20 is reached (a comment in the code informs us that it's "to give party bonus time"). So even if you apply the fix above, if you specify that a monster appears on day 3, it will appears on day 23.

     

    Click to reveal.. (proof)
    Boolean day_reached(unsigned char which_day, unsigned char which_event)

    // which_day is day event should happen

    // which_event is the party.key_times value to cross reference with.

    // if the key_time is reached before which_day, event won't happen

    // if it's 8, event always happens

    // which_day gets an extra 20 days to give party bonus time

    {

    short what_day = (short) (which_day) + 20;

     

    if ((which_event != 8) && (party.key_times[which_event] < what_day))

    return FALSE;

    if (calc_day() >= what_day)

    return TRUE;

    else return FALSE;

     

    }

     

    The Disappear on day X part is the same (adapted) problem.

     

    Sometimes Appears Here A/B/C should works, but I don't know if Appear/Disappear on Events does.

     

    Chokboyz

     

    P.S : Attached, my version of the loop just before the if(monsters_loaded == FALSE)

     

    Click to reveal..
    for (i = 0; i < 4; i++)

    if (town_number == party.creature_save.which_town) {

    c_town.monst = party.creature_save;

    monsters_loaded = TRUE;

     

    for (j = 0; j < T_M; j++) {

    if (loc_off_act_area(c_town.monst.dudes[j].m_loc) == TRUE)

    c_town.monst.dudes[j].active = 0;

    if (c_town.monst.dudes[j].active == 2)

    c_town.monst.dudes[j].active = 1;

    c_town.monst.dudes[j].m_loc = t_d.creatures[j].start_loc;

    c_town.monst.dudes[j].m_d.health = c_town.monst.dudes[j].m_d.m_health;

    c_town.monst.dudes[j].m_d.mp = c_town.monst.dudes[j].m_d.max_mp;

    c_town.monst.dudes[j].m_d.morale = c_town.monst.dudes[j].m_d.m_morale;

    for (k = 0; k < 15; k++)

    c_town.monst.dudes[j].m_d.status[k] = 0;

    if (c_town.monst.dudes[j].summoned > 0)

    c_town.monst.dudes[j].active = 0;

    monst_target[j] = 6;

    }

     

    // Now, travelling NPCs might have arrived. Go through and put them in.

    // These should have protected status (i.e. spec1 >= 200, spec1 <= 204)

    for (j = 0; j < T_M; j++) {

    switch (c_town.monst.dudes[j].monst_start.time_flag){

    case 4: case 5 : //case 6:

    if ((((short) (party.age / 1000) % 3) + 4) != c_town.monst.dudes[j].monst_start.time_flag)

    c_town.monst.dudes[j].active = 0;

    else {

    c_town.monst.dudes[j].active = 1;

    c_town.monst.dudes[j].monst_start.spec_enc_code = 0;

    // Now remove time flag so it doesn't get reappearing

    c_town.monst.dudes[j].monst_start.time_flag = 0;

    c_town.monst.dudes[j].m_loc = t_d.creatures[j].start_loc;

    c_town.monst.dudes[j].m_d.health = c_town.monst.dudes[j].m_d.m_health;

    }

    break ;

     

    // Now, appearing/disappearing monsters might have arrived/disappeared.

    case 1:

    if (day_reached(c_town.monst.dudes[j].monst_start.monster_time, c_town.monst.dudes[j].monst_start.time_code) == TRUE)

    {

    c_town.monst.dudes[j].active = 1;

    c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get reappearing

    }

    break;

    case 2:

    if (day_reached(c_town.monst.dudes[j].monst_start.monster_time, c_town.monst.dudes[j].monst_start.time_code) == TRUE)

    {

    c_town.monst.dudes[j].active = 0;

    c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get disappearing again

    }

    break;

    case 7:

    if (calc_day() >= party.key_times[c_town.monst.dudes[j].monst_start.time_code]){ //calc_day is used because of the "definition" of party.key_times

    c_town.monst.dudes[j].active = 1;

    c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get reappearing

    }

    break;

     

    case 8:

    if (calc_day() >= party.key_times[c_town.monst.dudes[j].monst_start.time_code]){

    c_town.monst.dudes[j].active = 0;

    c_town.monst.dudes[j].monst_start.time_flag=0; // Now remove time flag so it doesn't get disappearing again

    }

    break;

    case 0:

    break;

    default:

    break;

    }

    }

     

    for (j = 0; j < town_size[town_type]; j++)

    for (k = 0; k < town_size[town_type]; k++) { // now load in saved setup,

    // except that barrels and crates restore to orig locs

    temp = setup_save.setup[j][k] & 231;

     

    misc_i[j][k] = (misc_i[j][k] & 24) | temp;//setup_save.setup[j][k];

    }

    }

     

     

  11. Quote:
    I thought the point was to simply change the label so it said "(1-10)" instead of "(0-9)". Changing the actual behavior of the node will break every scenario that uses town encounters.

    That's what has finally been done ... Must refrain from coding wink (the compatibility was assured by a switch though)

    The flipped cure/inflicted dialog for the Affect Webs node has been corrected too.

    Chokboyz
  12. Quote:
    wxWidgets is a nightmare in itself

    Glad to see i'm not the only one to think that grin
    Code::Blocks is good IDE, and when i compiled wxWidgets last version without Unicode support (downgrading windres to do so in the process confused) everything compiled fine. But compiling and executing the simple "hello world" provided example would lead to a majestic "app couldn't initialize" error (the same with BoE sources of course).
    Switching to wxDevcpp solved the problem (it doesn't build the program against a monolothic 10 Mo dll though) but then the code problems comes ... and i gave up the wxWidget idea grin

    Quote:
    We have lots of Windows-based source forks all over the place, mine included. Most do not compile properly

    I used Ormus' build as a base and had no problem with compilation. It's a C/C++ hybrid though ...

    Quote:
    I don't really know if it would be worth working with the Windows sources, since more fixes seem to be going into the Mac OS X sources rather than the Windows ones.

    Here is the (partial) list of what has, so far, been fixed from the Ormus' build :
    Bug Fixes :

    Click to reveal..
    - Custom Scenario Loading now works (FILEIO.cpp, FILEIO.h)
    - Conceal Ability Flag now works (ITEM.cpp, ITEM.h, INFODLGS.cpp)
    - Game now uses the font that comes with it. (BLADES.cpp)
    - Strengh potions can now be made (PARTY.cpp) (Ishad Nha)
    - Add/Lose Sanctuary and Add/Lose Martyr's Shield abilities fixed (SPECIALS.cpp) (Ishad Nha)
    - Acidic weapons works as living saving charm fixed (PC.cpp) (Ishad Nha)
    - Fixed the raise_dead node so that it actually raise dead (SPECIALS.cpp) (Ishad Nha)
    - Fixed the second part of a special node dialog called from a conversation wasn't properly recorded (actually read).
    - Fixed custom items weren't properly masked (transparent background) in the inventory (GRAPHUTIL.CPP and TEXT.cpp)
    - The Defense skill was used rather than the Thrown Missiles skill when firing missiles weapons (COMBAT.cpp)
    - Fixed the Paralysing Ray trap wasn't working. (PC.cpp)
    - Fixed the petrification touch was causing disease. You now have the same chance of being petrified thaht when a basilisk gazes at you each time your are hit (subject to changes) (!) (COMBAT.cpp and PC.cpp)
    - Make the automap updates after terrain change/swap/transform.
    - Cleaned and expanded the Debug Mode. Type 'D' to begin debug mode and '/' to see commands. (Ishad Nha)
    - Corrected doubling 152 index in m_pic_index. (Ishad Nha)
    - Corrected the "Town Special Encounter" node so that it makes full use of the ten groups. Now spec1a of 0 correspond to group 1, 1 to group 2, ... Spec1a of -1 does nothing a usual.
    - Fixed the ring of Will was not checked during mind duel (the number was wrong and the check was not until 24). (Lots of people)
    - Fixed Destroy Items and Move Items nodes so that they work for rectangles as well as a single space.
    - Hide Town now does work.

    When i finished cleaning my code, i will upload it to the OpenExile Google Project so that it can (temporary or not) serve as a base for further developpement.

    Quote:
    The code needs some serious refactoring and separation into parts.

    That's for sure wink

    Chokboyz

    Edit :
    Quote:
    One thing that confuses me though, if this is a C project, why the heck does it use *.cpp for the source code extension on Windows sources?

    While the original code is indeed in C, Ormus' build is a C/C++ hybrid (Ormus was planning to make it full C++ if i'm not mistaken). For example, looks into PC.cpp and look at the pc_record_type:: functions.

    If i ever got the time to do so, i'll take a look at QT4.5.
  13. Quote:
    Huh. Odd. Reordering the includes (eg placing windows.h after math.h) doesn't solve this? Or, if they're macros, simply undefining them immediately after including windows.h...

    There is actually a precompiler define option to prevent the override but that was worth mentionning (since i've lost a long time wondering what was wrong with my code smile )

    I've registered for a google account but didn't find your email in your profile or on the google project page. Must be blind, but couln't find it blush

    Chokboyz
  14. Quote:
    What resources problem? And how are min and max redefined by windows.h?

    Seems to me that resources format are not the same depending on which platform you are (.rc in windows, .glade if using GTK on linux, ...) I may be wrong though.

    Min and Max functions are redefined to Windows-brew ones when including "windows.h", overriding the c++ library ones. I had to replace all min/max in the code to either c++ or wxWidget equivalents to get it to compile in wxWidget.

    Quote:
    Well, you'll need to get a Google account then and email me.

    Ok, i will see how all of that works and email you accordingly.

    Chokboyz
  15. Quote:
    At the moment, such changes could result in asynchronization between Mac and Windows scenario formats.

    I'm leaving the scenario code alone for the very same reason ; compatibility is the key word here wink

    Quote:
    Well, I'd think that separating the logic code from the platform-dependant code would be a better thing to work on right now than rewriting the scenario code.

    Windows dependant code is mainly located in BLADES.cpp and graphics functions (DLGUTLS.cpp and so on). The min and max are redefined by default as soon as "windows.h" is included and that may be a problem ... Not to mention the ressources format problem ...

    For what i may have seen, Nikmind is succesfully porting BoE to linux, so he may have do that already ... I think he used GTK and SDL, so it can be somewhat easily ported when he is done. Nevertheless, he should have a deeper insight of this part of the code.

    I tried to use wxWidget once to make the game cross-platform, but that turned into a nightmare (version conflicting, non-unicode version crashing, windres needing to be downgraded because of incompatibility and so on ...). I didn't try QT4.5 though, but since Nikmind is already doing an easily portable game. whistle

    Quote:
    By the way, shall I add you to the Google project? (You'd need a Google account.) If you'd like to be added, you can email me.

    I don't have a Google account and it don't think the code is in a "cleaned" state enough to be released (Ishad Nha and I would need to merge our codes of course). But thanks for the offer, as soon as the source is "clean" enough, i'll upload it wink

    Chokboyz

    Edit : i've located and changed the strings in the scenario editor so that it advises to choose a monster encounter number between 1 and 10. Also changed the affect web node string to currently specify that 0 is inflicted and 1 cure (the value are flipped for this one).
  16. The bug where town couldn't be hid is fixed (assuming that won't break any compatibility with legacy scenarios ; why would would one try to hide a critical town knowing that the function doesn't work as intended ?).

     

    The problem was that the value in 2a was checked instead of the value in 1b.

     

    In SPECIALS.cpp, in town_spec, case 17 replace the line

    else party.can_find_town[spec.ex1a] = (spec.ex2a == 0) ? 0 : 1;

    by

    else party.can_find_town[spec.ex1a] = (spec.ex1b == 0) ? 0 : 1;

     

    To CM :

     

    Quote:
    I was actually suggesting making a change to the town record type, but it's probably better not to do that sort of change at this time...

    Why not wink When everything works as intended though ...

     

    Chokboyz

  17. Quote:
    Okay, I see your point here; though there are probably better ways to do it (for example making a separate waterfall terrain with no ability; this presupposes removal of the 255-terrains limit).

    That would suppose to change all the waterfall working terrains in legacy scenarios to the new non-working one ... If someone volunteer to do that, why not wink

    Quote:
    So, why not simply revert to the legacy behaviour, but make the node accept numbers from 1-10?

    It does actually by default. Leading to ...

    Quote:
    So basically, making the node say that it accepts values 1-10 rather than 0-9. That sounds much more sensible than the other idea.

    Right, i've deleted the Town Spec Encounter compatibility switch as the function is actually working as intended and the information text is only to blame.

    Quote:
    Well, you could always make a new array, or perhaps even a struct so that you don't need to remember which index is which option.

    The game reserved the indexes 300 to 309 for game related options. I just take advantage of unused space (307 to 309 are unused) instead of creating new variables.
    You don't really new to remember which index is which option unless you're going to dwelve into the code as all is set via menus (or ini file if you feel like it).

    Quote:
    I don't understand how that relates to my question/suggestion.

    This is a matter for the scenario editor and i'm currently concentrating on the game itself. What i was saying was that a simple button in town info that would set/unset the party.stuff_done[309][2] would do the trick. So it's an idea to consider ...

    To Ishad Nha : i've implemented the "Set an SDF" debug option you commented.
    Here is the code (you need to declare a char response[256] at the beginning of key stroke event handling function) :

    Click to reveal..
    case 'S': // Set a SDF <= can't set the SDF 0 (it's the default return value if the first character of the string is not a number)
    if (in_scen_debug) { //and leave alone the 300+ SDF (game options)
    display_strings("Enter Stuff Done Flag Part A (between 1 and 299)","",0,0,0,0,"Which SDFa ?",-1,130,0);
    get_text_response(873,response,0);
    i = atoi(response);
    if(i>0 && i <300){
    display_strings("Enter Stuff Done Flag Part B (between 0 and 9)","",0,0,0,0,"Which SDFb ?",-1,130,0);
    get_text_response(873,response,0);
    j = atoi(response);
    if(j >= 0 && j < 10){
    display_strings("Enter Stuff Done Flag Part Value (outrageous values are a sure way to crash, or at least broke, the game)","",0,0,0,0,"Which value ?",-1,130,0);
    get_text_response(873,response,0);
    x = atoi(response);
    party.stuff_done[j]=x;
    }
    }
    }
    break;

    Hope it's what you had planned smile
    Chokboyz
  18. Quote:
    It seems to me that since there is HUGE trove of "legacy" scenarios, and it is, frankly, very unlikely that the number of "new" scenarios will ever approach a huge trove, compatibility with legacy scenarios ought to be priority #1 by a longshot.

    My point of view exactly wink
    I think that the "fixed" options should be here nonetheless for (potential) "modern" designers who want to use these features though ...

    Chokboyz
  19. Quote:
    I don't really see the point of this...

    How is the game supposed to know what option is activated ? confused (preferences for example is array party.stuff_done[306])

    Quote:
    Is there any benefit to the legacy behaviour in this case? I can't see any.

    Any legacy scenario that has at least one Town Place Encounter Node would be unplayable since the encounter wouldn't take place (or worst another encounter would take its place)

    Quote:
    Why not make this switch an attribute of the node itself? For example, you could arrange it so that in a Kill/Raise Dead node, the Pict field is used to specify whether to raise absent PCs – a value of 0 indicates no, and the fixed behaviour occurs, while a value of 1 indicates yes, and the original behaviour occurs.

    Can be done ... Spec2a or spec2b could be used instead of pic since they are unused in the function. Nice idea ...

    Quote:
    Why not make this an attribute of the town itself? Of course, if that would require altering the scenario format it's probably best to hold off on it for now.

    Can be done, just need to put an option that set the SDF [309][2] either to 0 or 1.

    Quote:
    Though, I don't see the benefit of disabling waterfalls in town. Why don't we just make them work all the time?

    What about legacy scenarios where there are waterfalls in town leading to nowhere ? Designers put them here knowing exactly that they won't do a thing ...

    Thanks for your comments,
    Chokboyz

    To Thuryl :

    Quote:
    It's being "fixed" by internally decrementing the number of each encounter group by 1

    Actually increasing the call to the encounter group by 1 grin

    Quote:
    It seems like it would be infinitely more sensible to fix it by simply changing the range of numbers that the editor will accept for that node, but I'm not a programmer so what do I know.

    Yup, but you would still have to reload legacy scenarios and save them back with the new format. The editor already accept values between 1 and 10 (from -32 768 to 32 767 actually if i remember correctly), since ex1a to ex2b are short types.
    I preferred to have a compatibility switch that would allow to play either legacy and new scenarios "out of the box". So maybe, only changing the information text would be better wink
    This is, of course, subject to debate and changes.
    Thus, thanks for your comments,
    Chokboyz
  20. Quote:
    I used the 'search all files' option in Bloodshed Dev-cpp, it turned up only trivial results for "309".


    Thanks for that. I did the same and didn't find anything either. So it's safe to assume that party.stuff_done[309] is unused.
    Thus, party.stuff_done[309] is now "officially"( wink ) the compatibility switches array.

    So far, i've done three (working) compatibility switches, accessible by a new menu right under Preferences :
    • Switch between legacy Town Place Encounter Node (for legacy compatibility) or fixed one (so that you can make full use of the 10 special groups in scenario editor).
      Value : party.stuff_done[309][0]
    • Switch between legacy Resurrection Node (at least for easter eggs grin ) or fixed one (so that only present pc are resurrected, not the full party).
      Value : party.stuff_done[309][1]
    • Switch between Waterfalls working in Town or not (so that the user/scenario designer decided if the waterfall works in Town ; maybe legacy compatibility ?).
      Value : party.stuff_done[309][2]

    The corresponding party.stuff_done[309] must be set to 0 to active legacy behavior or 1 for fixed/new behavior (this is done in the menu for the player).
    The value 0 has been chosen so that legacy behavior is on by default (party.stuff_done array is initialised to 0 in the initialisation).
    I've fixed the .ini file reading/writing so that it nows read/write Preferences and Compatibility Options to/from it. Manually editing the file now works (for example, putting the line legacy_resurrection=1 in the file would active the legacy behavior of the resurrection node).

    I suggest reserving the party.stuff_done[309][9] switch to be set by the scenario designer, allowing or not, the player to change compatibility switches while in the scenario. The scenario designer would have full access to these switches of course. It's a suggestion though, feel free to debate smile


    On the bug-fixing side,
    Quote:
    (Milu?)Fix Destroy Items node so that it works for rectangles as well as a single space.
    has been fixed (incidentally, the same bug for the Move Items node when fixed).

    In SPECIALS.cpp, in rect_spec(), the same index (i) is used to list the successives x positions and to list all the monsters in town, wrecking havoc in the Destroy Items (case 213) and Move Items (case 212) functions, as soon as there is more than one square to check.

    To fix this, defines a new "short k;" and replaces i by k in the check for (i=0 ; i < NUM_TOWN_ITEMS; i++) and in the arrays.
    Here are my two fixed cases if you want to copy/paste (declare short k, though)
    Click to reveal..
    case 212:
    for (k = 0; k < NUM_TOWN_ITEMS; k++)
    if ((t_i.items[k].variety > 0) && (same_point(t_i.items[k].item_loc,l) == TRUE)) {
    t_i.items[k].item_loc.x = spec.sd1;
    t_i.items[k].item_loc.y = spec.sd2;
    }
    break;
    case 213:
    for (k = 0; k < NUM_TOWN_ITEMS; k++)
    if ((t_i.items[k].variety > 0) && (same_point(t_i.items[k].item_loc,l) == TRUE)) {
    t_i.items[k].variety = 0;
    }
    break;

    Chokboyz
  21. Oops, I forget a to end the case 'K' with a break in the debug function above (incidentally making the scenario end each time you call it smirk ). Fixed

     

    I've create a new file menu entitled "compatibility options" where we would give the player the choice to use old legacy (bugged) function (to play old scenario) or new fixed ones. So far, i've only put the "Legacy Place Town Encounter ?" option, but i'll add party ressurection or working waterfalls on town.

    Can someone confirm that SDF 309 is never used in the game (i didn't see that in the code) ? I would like to make it the compatibility switch array.

     

    Concerning the Monster 0 problem, was the scenario editor Delete Monster function the only problem ? (no problem on gamecode side ?)

     

    Nice to see the editor taking good shape wink

    Chokboyz

  22. To Ishad Nha : i've been merging our codes into a "clean build" that could serve as a base for future programmation.

     

    That raises several questions :

     

    1. In GRAPHUTL.cpp, line 143 of your code, the hdcMem3 parameter should be destDC (copy/paste leftover i think smile )
    2. In GLOBVAR.cpp, line 450 of your code, you've changed the char button_def_key[150] array. Why ? Is it a bug fix ?
    3. You shouldn't substract 200 to the help message in most of the case. Indeed, having a 200 + number_of_message send to the function give_help() forces the display of the help message, even if "don't give help message" is checked. That way if someone click on the help button and this option is set, the message is given. For example, with the current code, the alchemy help message is unreachable as soon as the "don't give help message" option is set.
    4. In TOWN.cpp, line 1068, you've set the two last parameters of map_world_rect to 400. Why ? Another bug fix ?
    5. I've incorporated your nice extended debug mode. I've cleaned it a little (mainly message the player when he is trying to do something not allowed, e.g flying in town ...), tweaked the Leave Town debug function so that it doesn't put you in start town but rather ask you to choose in which direction to quit the town and finally made the End Scenario functionnal.

      The problem was that the end_scenario flag was put to false at the beginning of each action, so i make it skip the check and directly end the scenario when the debug function is called.

       

      Here is the beginning of the code (the rest is untouched) :

       

      Click to reveal..
      Boolean handle_keystroke(WPARAM wParam, LPARAM lParam)

      {

      Boolean are_done = FALSE;

      POINT pass_point;

      short i,j,k;

      POINT terrain_click[10] = {{150,185},{120,215},{150,215},{180,215},

      {120,185},{150,185},{180,185},

      {120,155},{150,155},{180,135}};

      char talk_chars[9] = {'l','n','j','b','s','r','d','g','a'};

      char chr;

       

      short x,y;

      location loc;

       

      if (in_startup_mode == TRUE)

      return FALSE;

       

      chr = (char) wParam;

       

      if (overall_mode == MODE_TALKING) {

      if (chr == ' ')

      chr = 'g';

      for (i = 0; i < 9; i++)

      if (chr == talk_chars) {

      pass_point.x = preset_words.word_rect.left + 9;

      pass_point.y = preset_words.word_rect.top + 9;

      are_done = handle_action(pass_point,wParam,-1);

      return are_done;

      }

      }

      else if (overall_mode == MODE_SHOPPING) { // shopping keystrokes

      for (i = 0; i < 8; i++)

      if (chr == 97 + i) {

      pass_point.x = shopping_rects[1].left + 9;

      pass_point.y = shopping_rects[1].top + 9;

      are_done = handle_action(pass_point,wParam,-1);

      return are_done;

      }

      }

       

      if ((overall_mode != MODE_TALKING) && (overall_mode != MODE_SHOPPING)) {

       

      for (k = 0; k < (short) LOWORD(lParam); k++)

      switch(chr)

      {

      case 'D':

      if (in_scen_debug)

      {

      in_scen_debug = FALSE;

      ASB("Debug mode OFF.");

      }

      else

      {

      in_scen_debug = TRUE;

      ASB("Debug mode ON.");

      }

      print_buf();

      break;

      case '?':

      if (is_out()) FCD(1079,0);

      if (is_town()) FCD(1080,0);

      if (is_combat()) FCD(1081,0);

      break;

       

      case '1': case '2': case '3': case '4': case '5': case '6':

      pass_point.x = pc_buttons[((short) chr) - 49][0].left + 1 + PC_WIN_UL_X;

      pass_point.y = pc_buttons[((short) chr) - 49][0].top + PC_WIN_UL_Y;

      are_done = handle_action(pass_point,wParam,-1);

      return are_done;

      break;

       

      case '9':

      pass_point.x = item_screen_button_rects[6].left + ITEM_WIN_UL_X;

      pass_point.y = item_screen_button_rects[6].top + ITEM_WIN_UL_Y;

      are_done = handle_action(pass_point,wParam,-1);

      return are_done;

      break;

       

      case ' ':

      if (overall_mode == 14) { // cast multi-target spell, set # targets to 0 so that

      // space clicked doesn't matter

      num_targets_left = 0;

      pass_point = terrain_click[5];

      are_done = handle_action(pass_point,wParam,-1);

      return are_done;

      }

      if (overall_mode == 11)

      spell_cast_hit_return();

      break;

       

       

      case 'z':

      if (((overall_mode >= 10) && (overall_mode < 20)) || (overall_mode == 37)) {

      set_stat_window(current_pc);

      put_item_screen(stat_window,0);

      }

      else {

      set_stat_window(0);

      put_item_screen(stat_window,0);

      }

      break;

       

      case '=':

      if (in_scen_debug) {

      party.gold += 100;

      party.food += 100;

      for (i = 0; i < 6; i++) {

      adven.main_status = MAIN_STATUS_ALIVE;

      adven.cur_health = 100;

      adven.cur_sp = 100;

      }

      adven.giveXP(25);

      refresh_store_items();

      for (i = 0; i < 6; i++)

      for (j = 0; j < 62; j++) {

      adven.mage_spells[j] = TRUE;

      adven.priest_spells[j] = TRUE;

      adven.skills[9] = 7;

      adven.skills[10] = 7;

      }

       

      add_string_to_buf("Debug: Add stuff and heal. ");

      print_buf();

      put_pc_screen();

      }

      break;

       

      // case 'A': Alchemy <= bad idea, there's already a case 'A' - Alchemy. And working in town only.

      case 'B': // Leave town

      if (in_scen_debug) {

      party.stuff_done[304][0] = 0;

      if(overall_mode == MODE_OUTDOORS){

      add_string_to_buf("Debug - Leave Town: You're not in town !");

      print_buf();

      break;

      }

      overall_mode = MODE_OUTDOORS;

      position_party(party.outdoor_corner.x,party.outdoor_corner.y,party.p_loc.x,party.p_loc.y);

      clear_map();

      add_string_to_buf("Debug: Leaving town...");

      add_string_to_buf("Choose which direction to go.");

      print_buf();

      put_pc_screen();

      }

      break;

       

      case 'C': // Clean up

      if (in_scen_debug) {

      for (i = 0; i < 6; i++) {

      adven.status[sTATUS_POISON] = 0;

      if (adven.status[sTATUS_BLESS] < 0)

      adven.status[sTATUS_BLESS] = 0;

      if (adven.status[sTATUS_HASTE] < 0)

      adven.status[sTATUS_HASTE] = 0;

      adven.status[sTATUS_WEBS] = 0;

      adven.status[sTATUS_DISEASE] = 0;

      adven.status[sTATUS_DUMB] = 0;

      adven.status[sTATUS_ASLEEP] = 0;

      adven.status[sTATUS_PARALYZED] = 0;

      adven.status[sTATUS_ACID] = 0;

      }

      add_string_to_buf("Debug: You get cleaned up!");

      print_buf();

      put_pc_screen();

      }

      break;

      // case 'D': toggle Debug mode <= bad idea, there's already a 'D' case.

      //Can be moved out of this function to allow the character to switch debug mode during dialogues or shopping though.

      case 'E': // Miscellaneous help

      if (in_scen_debug) {

      party.stuff_done[305][0] = 10;

      party.stuff_done[305][2] = 10;

      party.stuff_done[305][3] = 10;

      add_string_to_buf("Debug: Sanctuary, Detect, Lavawalk!");

      print_buf();

      put_pc_screen();

      }

      break;

      case 'F': // Flight

      if (in_scen_debug) {

      if (overall_mode == MODE_TOWN){

      add_string_to_buf("Debug - Flying: Not while in Town !");

      print_buf();

      break;

      }

      party.stuff_done[305][1] = 10;

      add_string_to_buf("Debug: You start flying!");

      print_buf();

      }

      break;

      case 'H': // Heal PCs and restore their SP

      if (in_scen_debug) {

      party.gold += 100;

      party.food += 100;

      for (i = 0; i < 6; i++) {

      if ((adven.main_status > MAIN_STATUS_ALIVE) && (adven.main_status < MAIN_STATUS_FLED))

      adven.main_status = MAIN_STATUS_ALIVE;

      }

      adven.heal(250);

      adven.restoreSP(100);

      add_string_to_buf("Debug: Heal.");

      print_buf();

      put_pc_screen();

      }

      break;

      case 'K':

      if (in_scen_debug) {

      for (i = 0; i < T_M; i++) {

      if ((is_combat()) && (c_town.monst.dudes.active > 0) && (c_town.monst.dudes.attitude % 2 == 1))

      c_town.monst.dudes.active = 0;

       

      if ((c_town.monst.dudes.active > 0) && (c_town.monst.dudes.attitude % 2 == 1)

      && (dist(c_town.monst.dudes.m_loc,c_town.p_loc) <= 10) )

      damage_monst(i, 7,1000,0, 4);

      }

      initiate_redraw();

      add_string_to_buf("Debug: Kill things.");

      print_buf();

      break;

      }

      // case 'L': automap <= don't know exactly what you want to do here ... Reveal all map ?

      // case 'M': repeat Mage spell <= same here

      case 'N': // End scenario

      if (in_scen_debug) {

      reload_startup();

      in_startup_mode = TRUE;

      in_scen_debug=FALSE;

      draw_startup(0);

      menu_activate(1);

      if (FCD(901,0) == 2) save_file(1);

      }

      break;

      case 'O': // Location

      if (is_town()) {

      loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc;

      sprintf ((char *) c_line, "Debug: You're at x %d y %d in town %d.",

      (short) loc.x, (short) loc.y, c_town.town_num);

      }

      if (is_out()) {

      loc = (overall_mode == MODE_OUTDOORS) ? party.p_loc : c_town.p_loc;

      x = loc.x; y = loc.y;

      x += 48 * party.outdoor_corner.x; y += 48 * party.outdoor_corner.y;

      sprintf ((char *) c_line, "Debug: You're outside at x %d y %d.",x,y);

      }

      add_string_to_buf((char *) c_line);

      print_buf();

      break;

      // case 'P': repeat Priest spell

      case 'Q': // Magic map

      if (in_scen_debug) {

      if (overall_mode == MODE_OUTDOORS) {

      for (i = 0; i < 96; i++)

      for (j = 0; j < 96; j++)

      make_explored(i,j);

      }

      else {

      for (i = 0; i < 64; i++)

      for (j = 0; j < 64; j++)

      make_explored(i,j);

      }

      clear_map();

      add_string_to_buf("Debug: Magic Map.");

      print_buf();

      }

      break;

      case 'R': // Return to Start

      if (in_scen_debug) {

      if (party.in_boat >= 0) {

      add_string_to_buf(" Not while in boat. ");

      break;

      }

      force_town_enter(scenario.which_town_start,scenario.where_start);

      start_town_mode(scenario.which_town_start,9);

      position_party(scenario.out_sec_start.x,scenario.out_sec_start.y,

      scenario.out_start.x,scenario.out_start.y);

      center = c_town.p_loc = scenario.where_start;

      redraw_screen(0);

      add_string_to_buf("Debug: You are moved... ");

      print_buf();

      }

      break;

      /* case 'S': // Set a SDF <= must wait after we've done a "ask a question to player" dialog

      if (in_scen_debug) {

      break;

      }

      case 'T': // Move to new Town <= idem

      */

      case 'W':

      if(in_scen_debug){

      refresh_store_items();

      add_string_to_buf("Debug: Refreshed jobs/shops. ");

      print_buf();

      }

      break;

      case '<': // Advance clock by one day

      if (in_scen_debug) {

      ASB("Debug: One day passes...");

      print_buf();

      party.age += 3700;

      put_pc_screen();

      }

      break;

      case '>':

      if(in_scen_debug){

      ASB("Debug: Towns have short memory.");

      ASB("Your deeds have been forgotten.");

      print_buf();

      for (i = 0; i < 4; i++)

      party.creature_save.which_town = 200;

      }

      break;

      case '/': // Help list

      if(in_scen_debug){

      ASB(" Debug hot keys");

      ASB(" B: Leave town");

      ASB(" C: Get cleaned up");

      ASB(" D: Toggle Debug mode");

      ASB(" E: Sanctuary, Detect, Lavawalk");

      ASB(" F: Flight");

      ASB(" H: Heal");

      ASB(" K: Kill things");

      ASB(" N: End Scenario");

      ASB(" O: Location");

      ASB(" Q: Magic map");

      ASB(" R: Return to Start");

      ASB(" W: Refresh jobs/shops");

      ASB(" =: Heal, increase magic skills");

      ASB(" <: Make one day pass");

      ASB(" >: Towns forgive you");

      ASB(" /: Bring up this list");

      print_buf();

      }

      break;

    Thanks for that ...

     

    To ADoS : seems like it can be that ; i will investigate the "Town Encounters" special.

     

    The problem is solved : in SPECIALS.cpp, line 1867 (case 62) replace

    c_town.activateMonsters(spec.ex1a);

    by

    c_town.activateMonsters(spec.ex1a+1);

     

    Now if you want to make the n special encounter appears, just put n-1 in spec1a for the "Town Spec Encounter". As usual , the value -1 for spec1a returns nothing.

    Now we need to make a compatibility switch with that, as older scenarios won't be playable with this change ...

    I doubt that was what was causing monster 0 problem though. Keep searching ...

     

    Chokboyz

×
×
  • Create New...