Random Encounters

Discussion in 'Tech Guides and Help Threads' started by Fernando, Feb 11, 2010.

Remove all ads!
  1. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    First of all, no, I'm not saying "you guys go do this", I'd like to try this myself -or with any help-, given the great time I had with the little thing that I could help Half Knight with on KotB, back in the day.

    One thing I'd like to be mod about is the random encounters; I wish there were more variety in them. Recently I met some Ettin with a couple (brown?) bears (on low level parties), or five black bears, a brigand leader and his minions... being all of this thing that I've enjoyed very much, because it was getting away from the usual lizard/gnolls/stirges that you generally meet on lower levels. If there's one thing that I love about this game (and mods), and keeps me dragging over and over to it, it's the combat variety; I've never end forming different parties and using a whole array of different strategies to try new things and "combos" in battle. So... what if we could have more variety (I can't find a better word :( ) to it? What if we could get across more animals, a CE party that decides to attack on us, and so?

    All of this, of course, using mostly creatures and combat situations that are simple or already there, because I still don't know how to do this; at least in a beta stage, that is. Could someone point me what files should I study to see how pullable this'll be for me? (Other from the random_encounter.pyc and .py)

    I suppose there's a file that gives the % of what RE you could get at every level (or something like that), scripts for the creatures you may find (for instance), and so. Could anyone point me which are the files that are used (on 5.7.2) for this RE? I'll see if I can come up with at least a couple more new things to fight against (and fear of) while travelling the World Map, and obviously with the intention of sharing it with the community (if that's the case, on 5.8.0, or being this an optional download if it doesn't fit into the main patch-plan that you already have, given the balance/unbalance discussion that we all are into).

    Thanks for any help!
     
    Last edited: Feb 11, 2010
  2. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,613
    Likes Received:
    537
    Re: Possible mod idea - More Random Encounter variety

    Well, it's all in random_encounter.py... If you need help in understanding the scripting, just ask.

    Note that when you spawn creatures in a random encounter, you're going to want them to belong to the proper faction (faction 0 only, IIRC), otherwise they might not fight you, fight amongst themselves, etc. (The latter can be fun once in a while, though).
    This might require creating a duplicate protos.tab entry with the appropriate faction.
     
  3. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    Oh, OK, I thought that there were also another file/s... evidently I need some help :p... is there a tutorial in here? I don't remember one for this, particulary... thanks for the help and the protos.tab advise (didn't thought of that)!
     
  4. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,613
    Likes Received:
    537
    Re: Possible mod idea - More Random Encounter variety

    I don't think there's a tutorial for this one.

    So let's make one :)


    Random Encounters

    Overview
    • random_encounter.py is the heart of all random encounter scripting.
    • This includes:
      • Sleep Encounters
      • Wilderness Encounters
        • Random monsters
        • Specials, e.g. Zaxis, Adventurer group
        • Triggered encounters, e.g. the reward encounters, Skole's Goons
    Functions within the file:
    • Primary Functions:
      • encounter_exists( setup, encounter ):
        • Called by the game engine only.
        • For sleep encounters:
          • Every hour you rest in a Yellow Tent area calls this function.
          • NB: it is not called when you pass time or sleep in a green tent area!
          • For wilderness encounter:
            • Gets called up to once per trip.
      • encounter_create( encounter )
        • Placement of enemies / NPCs
        • Includes scripting for:
          • Lotus Flower
          • Encampment (Bonfire) encounter
          • Wonnilon's Hideout
      • check_random_encounter( setup, encounter )
        • Checks for Wilderness encounters.
      • check_sleep_encounter( setup, encounter )
        • Checks for Sleep encounters. (Yellow Tent area)
        • Includes:
          • Area specific Chance calculation.
          • 1d100 Roll.
          • Area specific Enemy lists.
      • check_predetermined_encounter( setup, encounter )
        • Checks for triggered special encounters.
        • Creates list of spawned NPCs accordingly.
      • check_unrepeatable_encounter( setup, encounter )
        • Special wilderness encounters scripting (e.g. Zaxis, Band of Adventurers)
      • check_repeatable_encounter( setup, encounter )
        • Random Monsters.
      • get_sleep_encounter_enemies( enemy_list, encounter )
        • Randomly selects from list of possible sleep encounter enemies.
      • get_map_from_terrain(terrain)
        • Randomly chooses map type (from out of 8)
      • get_repeatable_encounter_enemies( setup, encounter )
        • Calls one of the get_[terrain]_[daytime] functions according to the selected map.
      • get_[terrain name]_[day/night]time( encounter )
        • terrains: scrub, swamp, forest, riverside
        • Randomly selects from list of possible creatures appropriate for the terrain.
      • can_sleep()
        • Determines whether the area is:
          • Green Tent
          • Yellow Tent
          • Red Tent
          • Pass Time Only
    • Secondary / Helper functions:
      • Survival_Check(encounter)
      • PC_Modifier(), NPC_Modifier(encounter)
      • group_skill_level( pc, skill )
      • Spawn_Point(encounter), random_location(loc, range, target),
      • get_circle_point_list(center, radius,num_points)
      • Slaughtered_Caravan()
      • NPC_Self_Buff()
      • Get_Multiplier(encounter)

    Wilderness Encounters


    General

    Here's how it works.

    1. You take a hike from A to B.
    2. The game then calls for encounter_exists().
      • More accurately: when you go to a different game area, then for every 'worldmap step', this function is called.
      • If you get an encounter, it won't call for the function again for that trip.
    3. encounter_exists calls check_random_encounter.
    4. check_random_encounter() checks for:
      • A successful 1d20 roll. If it succeeds:
      • Predetermined (Triggered) encounters. If one exists, it is unavoidable. If not:
      • Unrepeatable (Special) encounters. Else:
      • Repeatable (Random monster) encounters.
      • Note that it checks for them in that order. E.g. if a predetermined encounter exists, it ignores the other two.
    5. create_encounter():
      • If one of the checks returned a 1, this function is called.
      • It accepts a list of NPCs / enemies and places them on the map.
      • The list of enemies is determined by the aforementioned check_[x]_encounter.
      • Enemy placement is determined via the helper functions random_location(...) and Spawn_Point(...).
    6. The list of NPCs, map, locations, etc are contained within the variables encounter and setup. Manipulating them in a function alters them globally.
    7. Probability:
      • encounter_exists() is called for every worldmap 'step'.
      • As mentioned, a d20 roll is made by check_random_encounter() for every step of the way.
      • Thus, the chance of getting an encounter in the first place is determined by the worldmap journey number of steps.
      • Suppose the number of steps is N, the probability is then given by:
        • 1 - (1 - 0.05) ^ N
        • e.g. the Nulb -> Emridy Meadows journey has N = 21 steps.
        • The probability for an encounter is then roughly 66%.
      • This mechanism also varies where the encounter takes place along the route.

    Triggered Encounters:

    • check_predetermined_encounter contains most of the relevant scripting.
    • game.encounter_queue
      • game.encounter_queue is a global variable containing triggered encounter IDs.
      • When you want to schedule a triggered encounter, you add one to the queue.
      • The command is:
      • Code:
        game.encounter_queue.append( [ID number] )
      • This appends an encounter to the end of the queue.
    • ID:
      • encounter.id is assigned according to the entry in game.encounter_queue, as mentioned.
      • Triggered encounter IDs are generally in the 3000-3999 range.
    • Flags:
      • There are global flags that signify whether you've had a triggered encounter or not.
      • They are used to prevent the encounter from occurring twice, and for general scripting purposes (e.g. the "confront the traders" scripting).
      • IDs are matched with global flags by the formula:
      • Code:
        flag = ID - 3000 + 277
      • e.g. ID 3000 corresponds to flag 277 (this is the assassin encounter).
      • Consult the global flags list to see which flags are available for use.
    • NPC / enemy lists:
      • Each ID is prescribed with a list of enemies.
      • The format is:
      • Code:
        encounter.enemies = ( ( [NPC1 protos.tab ID], [NPC1 count] ), ( [NPC2 protos ID], [NPC2 count] ), ... )
      • E.g.:
        • encounter.enemies = ( ( 14307, 1 ), ( 14308, 10 ) )
        • Spawns the Thrommel Reward guys (A knight and his 10 retainers)
    • Probability / DC:
      • The script assigns these encounters a DC of 1000, so you'll always fail the survival check and be forced to get the encounter.
      • There is no 'level scaling' scripting for these encounters.
      • As mentioned in the general section, an encounter is not guaranteed.
      • If you want to make sure a triggered encounter happens, you may have to tamper with the d20 roll (e.g. check the encounter queue to override the d20 roll, or something to that effect).
    • Existing Triggered encounters:
      • ID 3000 - Assassin
      • ID 3001 - Thrommel Reward
      • ID 3002 - Tillahi Reward
      • ID 3003 - Sargen Reward
      • ID 3004 - Skole's Goons
      • ID 3010 - Gwenno (from Ted's disabled Desperate Housewives Mod)
      • ID 3159 - Traders en route to Nulb (from my disabled Traders Mod)
      • ID 3579 - Moathouse Gnolls
      • ID 3605 - Slaughtered Caravan


    Special Encounters:



    • check_unrepeatable_encounter contains most of the relevant scripting.
    • ID:
      • encounter.id is assigned according to the entry in game.encounter_queue, as mentioned.
      • Triggered encounter IDs are generally in the 2000-2999 range.
    • Probability / DC:
      • The game first rolls a 1d10.
      • If it succeeds:
      • An encounter is randomly selected from the list.
      • If that encounter hasn't occurred yet, and the party's effective average level exceeds the encounter's specified DC + 2, you get the encounter.
      • If not, the game moves on to check for a Random Monster encounter.
      • The survival check that allows you to avoid the encounter is as usual.
    • Flags:
      • There are global flags that signify whether you've had a special encounter or not.
      • They are used to prevent the encounter from occurring twice, and for general scripting purposes (e.g. the "Zaxis appears in the brothel" scripting).
      • IDs are matched with global flags by the formula:
      • Code:
        flag = ID - 2000 + 227
      • e.g. ID 2000 corresponds to flag 227 (this is the ochre jelly encounter).
      • Consult the global flags list to see which flags are available for use.
    • NPC / enemy lists:
      • Each ID is prescribed with a list of enemies.
      • The format is:
      • Code:
        encounter.enemies  = ( ( [NPC1 protos.tab ID], [NPC1 count] ), ( [NPC2 protos ID], [NPC2  count] ), ... )
      • E.g.:
        • encounter.enemies = ( ( 14142, 4 ) )
        • Spawns 4 ochre jellies.
    • Existing Special encounters:
      • ID 2000 - 4 ochre jellies (if you don't kill an ochre jelly by the endgame, and marry Meleny, something special happens :) )
      • ID 2001 - Zaxis
      • ID 2002 - Band of Adventurers


    Random Monsters:


    • Probability:
      • On top of the usual probabilistic calculation, check_random_encounter() calls for Survival_Check, which, on a successful roll, allows you to avoid the encounter.

    • check_repeatable_encounter
      • Randomizes map type (swamp, forest etc.) by calling get_map_from_terrain().
      • Rolls up the encounter enemies with get_repeatable_encounter_enemies().
        • This is repeated until the encounter DC is no more than the party's effective average level + 2.
    • NPC / enemy lists:
      • get_repeatable_encounter_enemies():
        • calls one of the get_[terrain]_[day/night time]() functions, according to the encounter map and time.
      • Each get_[terrain]_[time] contains possible encounters for the region.
      • The format is usually:
        Code:
        n = game.random_range(n1, n2)  #n is the number of spawned monsters, randomly chosen in the range [n1, n2]
                encounter.dc = [estimated encounter dc]
                encounter.enemies = ( ( [proto ID], n*m ), ( [proto ID], n*m), ... )
                encounter.id =  [some ID in the 1000-1999 range]
        e.g.
        Code:
                # ettin and brown bears
                n = game.random_range(1,2)
                encounter.dc = 7
                encounter.enemies = ( ( 14238, 1*m ), ( 14053, n*m ) )
                encounter.id =  1040
        
        Is the Ettin and Brown Bears encounter.
      • m is a multiplier, determined by the Get_Multiplier() function. For higher level parties, it has a chance of multiplying the number of opponents.
      • An encounter is randomly selected from the list, and the function sets the encounter.enemies variable accordingly, as seen above.

    Sleep Encounters

    Here's how it works.

    1. You rest in a Yellow Tent area.
    2. For every hour of rest, the game calls encounter_exists().
    3. encounter_exists calls check_sleep_encounter().
    4. check_sleep_encounter():
      • Makes a 1d100 roll.
        Since Co8 5.7.0, there is a variable threshold for different areas and certain circumstances (e.g. Temple on Alert status increases the chance of sleep encounters there).
      • If the roll succeeds, the script moves on to randomly select monsters.
      • Most areas and maps have a unique list of possible enemies. It's fairly well documented inside the file.
        The format is:
        Code:
        ( ( [proto ID] , [n1] ,[n2] ,[DC] ), ...)
        Code:
        [SIZE=2]
        #[proto ID] is the monster's proto ID
        #n1, n2 - between n1 and n2 creatures will appear
        #DC - used for level scaling (max DC is party effective level + 2)
        [/SIZE]
    5. The list is fed into get_sleep_encounter_enemies().
      • The function randomly selects from the list of possible enemies, and randomizes the number of opponents according to n1 and n2.
    6. create_encounter():
      • If the checks returned a 1, this function is called.
      • It accepts a list of NPCs / enemies and places them on the map.
      • The list of enemies is determined by the aforementioned check_sleep_encounter.
      • Enemy placement is determined via the helper functions random_location(...) and Spawn_Point(...).
    7. Probability:
      • encounter_exists() is called for every hour of rest.
      • As mentioned, a d100 roll is made by check_sleep_encounter(), and is checked against a variable threshold called ran_factor.
      • Thus, the chance of getting an encounter is determined by how long you rest and ran_factor.
      • Suppose the number of hours rested is N, the probability is then given by:
        • 1 - (100 - ran_factor) ^ N
        • e.g. resting for 8 hours with a ran_factor of 10 (default).
        • The probability for an encounter is then roughly 56%.
     
    Last edited: Feb 12, 2010
  5. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,613
    Likes Received:
    537
    Re: Possible mod idea - More Random Encounter variety

    How To's

    Any requests?
     
    Last edited: Feb 12, 2010
  6. Gaear

    Gaear Bastard Maestro Administrator

    Joined:
    Apr 27, 2004
    Messages:
    11,029
    Likes Received:
    42
    Re: Possible mod idea - More Random Encounter variety

    @Fernando - have a look at Shiningted's tutorials and grab Agetian's World Builder. What Sitra has oulined here thus far may appear daunting, but when you become familiar with the basics and have some good tools, it will be less so. :yes:
     
  7. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    @Sitra/Gaear: thanks, it's more than I could ask for. Great tutorial, Sitra; I'll have to start trying things to see if I'm understanding correctly, but maybe I can come up with something. Didn't think that the World Builder would help with this, I never had the guts to download it :p, but I'll give it a shot.

    I'll keep you updated on any progress/difficulties I find. Thanks!
     
  8. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    Well, today's the day... I started messing with the random_encounter.py to see if I'm getting this correctly. I'm adding this entry in random_encounter.py, on the 922 line (using Notepad2; it's on the "def get_riverside_daytime( encounter )" section). It now says:

    Code:
    elif (r == 6):
    		# ogres
    		n = game.random_range(1,3)
    		encounter.dc = 3 + (n)
    		encounter.enemies = ( ( 14448, n*m ), )
    		encounter.id =  1050
    Let's see... am I on the right track? I tried to make a RE that could only happen on the riverside map, daytime; this RE would be with 1 to 3 ogres, and I've tried to get the nearest DC calculation that I could came up with (here it's DC4 for 1 -should be DC3-, DC5 for 2 and DC6 for 3 ogres). I gave them the 1050 ID that I believe that wasn't used on the same file (a search on it didn't show any other entry using that code).

    I'm sorry if I keep asking things, it's just that all of this is a lot of new things for me, and I know that some are dumb questions, but surely is normal to overlook their simple answers :p... where can I check for a list of the encounter IDs, so I don't get in any used numbers? And, on the same line of thought... where can I find a list that shows which protos.tab number belongs to which creature, as in "14448=ogre"? I looked on the protos.tab file, but couldn't find the npc name of every entry (perhaps I should use Map Builder for that?). The last question... am I on the right track with the DC calculations I did? Because I don't know if this encounter could happen to a lvl1 party (which would be unfair, I believe), and surely I overlooked that answer.

    Thanks!

    /Edit: I've tried searching for stuff on the World Builder, as I still have to really understand how to use it :p... anyhow, I guess I found out how to get the NPCs ID numbers: an Orc Fighter is 14745... am I right? Also, two more questions :)(!!!)... NPCs that were part of other mods, like Hickorys Branch's Orcs Fighters and Dominators (if I'm not wrong), could be used for this Random Encounters? And I should take into account where should every NPC appear, right? I mean, you tried to put stirges only on the swamps, not having zombies on daylight, and such, is that correct?

    Thanks again...
     
    Last edited: Feb 14, 2010
  9. Gaear

    Gaear Bastard Maestro Administrator

    Joined:
    Apr 27, 2004
    Messages:
    11,029
    Likes Received:
    42
    Re: Possible mod idea - More Random Encounter variety

    World Builder's proto editor has a search feature from a drop down menu. You can type in 'ogre' and it will show you a list of entries that include the word ogre.

    World Builder has lots of built-in tutorials. You can find them in the included documentation or in drop down menus from within the program.

    Most monsters should be able to be used in any condition, but again keep in mind the factions concern. Also, for some few there may be associated scripting that could cause problems. e.g., a specific proto could be scripted to be destroyed upon some condition or other. Generally the basic protos (bugbear, gnoll, hobgoblin, etc.) are safe. But you also don't want monsters like 'greater temple bugbears' to appear in the swamps near the Moathouse or that kind of thing. Just use your common sense.
     
  10. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    Thanks, Gaear. I'll mostly look out for the less used monsters (or at least that's the idea), so we'll not only get more variety in the Random Encounters, but also more tactical variety. I mean, you don't fight an Ogre the same way that you fight a group of wolves or undeads... and, this way, you won't get tired after getting five crayfish encounters and still that bloody swamp lotus doesn´t show up...

    I'll try (in some hours) add some of this encounters and I'll post it here, just in case you or someone else would like to check and see if I'm doing it right (I'll betatest, of course, but being a random fact, it just might not be so easy to test).

    See ya, and thanks again.
     
  11. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    Well... I'll double post to update: I've added some encounters, buuut (as always... a "but") it didn´t work. For any reason beyond my comprehension (sp?), the stuff I added didn't work: in game, everywhere I went the "rest" icon was red, yet the party could sleep there for weeks (really) without triggering any random encounters, and even getting back your HP. The icon was red, but it was a "green icon" world, really. The same thing happened with the wilderness ones, you could go back and forth from Nulb to Hommlet, i.e., and nothing would trigger.

    I don't know what was the problem... because adding or deleting the RE that I made was the difference: on the same file, if I added them it will get "broken", and deleting them would put the game back to normal. It's strange... I'll keep trying, though.
     
  12. Shiningted

    Shiningted I want my goat back Administrator

    Joined:
    Oct 23, 2004
    Messages:
    12,651
    Likes Received:
    350
    Re: Possible mod idea - More Random Encounter variety

    Sounds like you broke Random_Encounter.py - easy to do when you are first starting out. A quick way to check - run TFE_X and choose 'clear-map-cache' (to delete all the .pyc files) then run the game, travel between towns or rest in a yellow area (or do nothing at all, the game should still run that file) then quit and check your data/scr folder. Is there a random_encounter.pyc file there? If not, you broke it so bad it couldn't compile :p (that might only be a missing ';' or ')' or some other innocent problem). If its there - well, you still broke it so go back and check what you did. Or read my 'easy mistakes to make' tutorial. ;)
    We all want to spend more time at the riverside ;)

    My only advice would have been what Sitra said - watch the monsters all have the same faction, or they will turn on each other. And don't use monsters in protos.tab that have heartbeats or are plot-critical - make new ones if necessary.

    Another option might be, add a new map with a small Cave or Tower. Then put spawners (invisible NPCs turned OF_OFF inside with a heartbeat file) to spawn some orcs, or some ettins, or whatever inside each time parties go in. As long as it doesn't turn up too often, I think that would be a lot of fun. Also a lot of work and needs a good artist, but fun :)

    Fantastic tutorial btw Sitra, I was flying blind with that file myself. Now I can fix some of the issues in KotB.
     
  13. Fernando

    Fernando Established Member

    Joined:
    Jan 5, 2006
    Messages:
    107
    Likes Received:
    0
    Re: Possible mod idea - More Random Encounter variety

    Thanks for the answer, Ted. I'll check this to see if I can see anything, even that .pyc file being created again :p
     
  14. Shiningted

    Shiningted I want my goat back Administrator

    Joined:
    Oct 23, 2004
    Messages:
    12,651
    Likes Received:
    350
    Re: Possible mod idea - More Random Encounter variety

    Well, if it doesn't work just post the relevant bit here (use the *code* - */code* html) and maybe we can help :)
     
  15. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,613
    Likes Received:
    537
    Re: Possible mod idea - More Random Encounter variety

    As Ted mentioned, it sounds like the file won't compile, due to a syntax error most likely.

    If that's the case, you can try the following method:
    open up the console
    type:
    Code:
    from random_encounter import *
    If you get an error, you can be sure it failed to compile.

    You can try to trace the broken line(s) by:

    1. Gradually deleting your additional code,
    2. Saving the file,
    3. and then typing the console code again.
    4. When the syntax error is gone, it should compile normally.
    Finally, when messing with random_encounter.py, it's generally a good idea to keep a copy of the last working version :)

    BTW,
    are you using tabs for indentation?
     
    Last edited: Feb 18, 2010
Our Host!