Courageous
Wanderer
Courageous' Random Encounter Engine
Random Encounter Engine V 0.9.7B
=======================
COPYRIGHT JOE KRASKA aka 'Courageous', November, 2005
Permission to use this script (and modify it) in a RunUO private shard is hereby granted, without restriction. However no rights to redistribute this script are granted, except for any temporary (and revokable) implied redistribution rights granted by the act of posting this to a redistribution site by the original author.
UPDATED 22 FEB 2006
Updates to 0.9.8B:
The system examines a subset of a mobile's skills, multiplying them by a weighting factor. The result is a figure approximately 1-10 that rates the mobile according to a specific "class". This "class" rating can later be used in conjunction with the level= tag to determine if a player qualifies for an encounter. Here is an example:
level="8:Necromancer"
UPDATED 20 FEB 2006
Updates to 0.9.7B:
Updates to 0.9.6B:
The old tag for water based encounters (water="true") is now deprecated. It will continue to work for a version or two, but you should use landType="Water" in the future.
As part of non decaying item solution, I have lifted (with permission) Arte Gordon's XmlAttachment system. RandomEncounters now has a subdirectory "ArteGordon". If you already have XmlSpawner or plan to get it, you'll need to delete this directory from RandomEncounters.
The landType= tag is now an option on each encounter. It is case sensitive. You can set it to Water, OnRoad, OffRoad, or AnyLand. AnyLand is the default and means either on or off road.
The time= tag is also now an option on each encounter. You can set it to Day, Night, Twilight, or AnyTime. AnyTime is the default, and it means literally any time of day.
FEATURES NOT INCLUDED:
One user requested that young players not be given encounters. This request was based on the particulars of his shard, and so is not yet implemented. There is some code in the expected place that can be commented-in if desired. I'm considering allowing shard admins to mark encounters directly to determine if they are or are not for young players.
Another user requested cleanup support for mobiles spawned by OrcBrutes. This turned out to not be feasible to do except at system start up time, because the sheer number of mobiles on a shard could cause a significant lag hiccup at the cleanup point. Also, it turned out to be impossible to know which creatures were children of creatures created by random encounters.
I'm still thinking about both of these items.
FUTURE WORK
A difficulty-based scaling and limits system is currently in progress.
UPDATED 7 JAN 2006
Updates to 0.9.5B:
UPDATED 3 JAN 2006
Updates to 0.9.4B:
Updates to 0.9.3B:
This is a D&D style "random encounter" engine for RunUO.
Note that encounters do not have to be hostile. For example,
this is a good way to make your world "come alive". You can
set it up so that wilderness creatures frequently appear near
the player when the player is in the wilderness. Since these
creatures are only spawned at or near where an active player
can see them, no CPU is wasted. It also adds an element of
unpredictability to the shard.
The system is fully configurable, by facet, by region type,
and by named regions (if desired). This allows the administrator
to control what kind of encounters appear where.
The system runs off a configuration file; the system rescans
this file periodically, if it notices that the file has been
written. So your shard does not have to be bounced for you to
make configuration changes.
INSTALLATION
============
Extract the zip file into your Scripts/Custom directory. Nothing else
is required. Note that the configuration file "RandomEncounters.xml" is
expected to reside in $RUNUO_INSTALL_DIR/Scripts/Custom/RandomEncounters.
If you want to put it somewhere else or name it something else, find the variable
"m_EncountersFile" in the RandomEncounterEngine class and fiddle with it.
HOW TO
======
The Random Encounter Engine is entirely controlled by its configuration file,
so understanding its format is essential. Before we talk aboutthat, though, a few
preliminaries:
The system is controlled on a common clock that periodically checks to see
if players (player mobiles with access level == Player, not staff members!)
qualify for a random encounter. To see if they qualify, first the system
decides which picker is in use. There are two.
The first picker is the "sqrt" (square root) picker. Its the default. When
the sqrt picker is in use, the system finds the square root of the number of
players online. The system then picks this many players to see if they further
qualify for a random encounter. No more than one encounter per player.
The second picker is the "all" picker. Using the all picker, the system
considers all players online for a random encounter.
Note switching between pickers is a dramatic event, which will GREATLY
impact the number of random encounters your player see; you should decide
early which picker you're going to use.
A player qualifies for a random encounter when:
1. The facet name, region type, and region name the player is in has
encounters described for it (example, the player is on Facet the
facet named "Felucca", in a "Dungeon" region named "Covetous").
2. Failing #1 above, the the system finds a region named "default" that
otherwise qualfies by facet name and region type (example, the
player is in a Felucca Dungeon, and is in Covetous, but the administrator
did not define a named region for Covetous. If there is a default
region for Felucca Dungeons, this will be used instead).
3. The system draws a random number 0.0-1.0, and searches for the LOWEST
probability encounter it can match.
If all of the above fail, the player has no encounter.
Now on to the details. Consider the following example:
This is a standard nested tag formatted xml file. It supports the following tags:
"RandomEncounters" tag. This supports the following attributes and defaults:
picker = the picking method, defaults to "sqrt"
language = the globalization code, defaults to "en-US".
skiphidden = tells the system to exclude hidden players from encounters, defaults to FALSE
delay = amount of secs before encounters begin after server start, defaults to "60"
interval = frequency in secs encounters are checked, defaults to "1800". This field can be separated into as many as 3 values, one each for dungeons, wilderness, and guarded regions. Separate with ":"
cleanup = how long to wait before shutting down spawned mobiles, defaults to "300"
debug ="false" (print out extra debugging information)
"Facet" tag.
name =[None] (mandatory tag naming the facet)
"Region" tag.
type =[None] (mandatory tag specifying region type; can be "Guarded", "Dungeon", and "Wilderness")
name =[None] (mandatory tag naming the region; use "default" to pick up generic)
"Encounter" tag.
p = probability of encounter, default of "1.0", which means 100%. If p is set to * (e.g., p="*"), the encounter will always be had in addition to any other encounter the player might have for the region
distance = the preferred distance from the player for the encounter, a number or a range (example "1" or "0:2" or "1:3"). Default is "7".
water = water mobiles can't spawn without this; land mobiles can't spawn with it, default is "false" DEPRECATED
landType= Water, OnRoad, OffRoad, or AnyLand. Default is "AnyLand".
time=Night, Twilight, Day, or AnyTime. Default is "AnyTime".
level=notional level of the character required to have the encounter; defaults to 1. An optional second argument can be sent to the level indicating class after a separating colon. E.g., "8:Necromancer". Valid current class names are Fighter, Ranger, Mage, Necromancer, Thief, and Overall.
scaleUp=true/false, whether or not to scale up encounters that are waker than the player; defaults to false. Never more than triples an encounter.
"Mobile" tag.
p = probability of the mobile being included in a picked encounter, default is "1.0"
pick =[None] (a list of mobiles to pick from (NO SPACES!); one is picked randomly)
n = a number or a range (example "1" or "0:2" or "1:3"), default is "1"
"Item Tag"
Same as Mobile tag.
Note how Mobiles and Items can appear embedded in one another. To know the rules, use
some common sense. An Item can be in a Mobile (e.g., "orc has a Sword"), and an Item can
be in an Item (e.g., "sword in a chest"), but a Mobile cannot be in an Item! A Mobile,
however, might belong to another Mobile's team...
Now a little word on picking. Consider the following (modified) fragment:
The above says "pick 2, each randomly from OrcCaptain and OrcishLord. Then
for each leader, attach 1-3 Orcs, and likewise for each leader, offer a
.25 chance to have an OrcishMage. This calculates to a maximum of 10
Mobiles for the whole encounter.
Sub items spawn IN their parent items. Sub mobiles spawn NEAR their parent
mobiles.
(note that if a valid spawn point can't be found, a mobile or item might not
be spawned, and if this happens, the remaining part of a whole encounter might
be skipped).
EQUAL PROBABILITIES
================
It's both possible and okay to list two encounters in the same region with the same probability. In this particular case, the system draws randomly from all matching probability levels, so you don't get the wierd case where one is always preferred over the other. This also makes it so that you don't have to do gymnastics to separate all the possibilities. One could just use ".3" ".2" and ".1" for everything, letting the system sort out the equal probability encounters...
Random Encounter Engine V 0.9.7B
=======================
COPYRIGHT JOE KRASKA aka 'Courageous', November, 2005
Permission to use this script (and modify it) in a RunUO private shard is hereby granted, without restriction. However no rights to redistribute this script are granted, except for any temporary (and revokable) implied redistribution rights granted by the act of posting this to a redistribution site by the original author.
UPDATED 22 FEB 2006
Updates to 0.9.8B:
- Added the ability to differentiate players by "class," where certain values in certain skills make the player qualify for certain kinds of encounters according to class names. The system currently supports Fighter, Ranger, Mage, Necromancer, Thief, and Overall (which is the default). Note that the Ranger class is determined by outdoors skills (tracking, animal lore and taming and the like, and not any combat skills).
The system examines a subset of a mobile's skills, multiplying them by a weighting factor. The result is a figure approximately 1-10 that rates the mobile according to a specific "class". This "class" rating can later be used in conjunction with the level= tag to determine if a player qualifies for an encounter. Here is an example:
level="8:Necromancer"
UPDATED 20 FEB 2006
Updates to 0.9.7B:
- Fixed a bug in the previous version which could cause too many spawns to occur, particularly if a very low probability draw occurred.
- Added support for tagging encounter difficulty by an inferred "level" of the character.
- Added supported for scaling up encounters based on character "level"
Updates to 0.9.6B:
- Fixed a problem where non-decayable items created by the system might (theoretically) never be cleaned up by the system in the rare event the server crashed after they were spawned but before they were cleaned up by the cleaner.
- Added the ability to mark spawns for specific times during the day/night cycle, including Night, Twilight, Day, and (the default) AnyTime.
- Added the ability to more accurately specify the player's location for certain types of spawns. Currently supporting: Water, OnRoad, OffRoad, and (the default) AnyLand.
The old tag for water based encounters (water="true") is now deprecated. It will continue to work for a version or two, but you should use landType="Water" in the future.
As part of non decaying item solution, I have lifted (with permission) Arte Gordon's XmlAttachment system. RandomEncounters now has a subdirectory "ArteGordon". If you already have XmlSpawner or plan to get it, you'll need to delete this directory from RandomEncounters.
The landType= tag is now an option on each encounter. It is case sensitive. You can set it to Water, OnRoad, OffRoad, or AnyLand. AnyLand is the default and means either on or off road.
The time= tag is also now an option on each encounter. You can set it to Day, Night, Twilight, or AnyTime. AnyTime is the default, and it means literally any time of day.
FEATURES NOT INCLUDED:
One user requested that young players not be given encounters. This request was based on the particulars of his shard, and so is not yet implemented. There is some code in the expected place that can be commented-in if desired. I'm considering allowing shard admins to mark encounters directly to determine if they are or are not for young players.
Another user requested cleanup support for mobiles spawned by OrcBrutes. This turned out to not be feasible to do except at system start up time, because the sheer number of mobiles on a shard could cause a significant lag hiccup at the cleanup point. Also, it turned out to be impossible to know which creatures were children of creatures created by random encounters.
I'm still thinking about both of these items.
FUTURE WORK
A difficulty-based scaling and limits system is currently in progress.
UPDATED 7 JAN 2006
Updates to 0.9.5B:
- Added separate intervals for the different supported region types. The system will now currently supported separate timer rates for dungeons, wildernes, and guarded regions.
UPDATED 3 JAN 2006
Updates to 0.9.4B:
- Resolved an issue where mobiles would sometimes inappropriately spawn on boats that were in coastal territories.
- Resolved an issue where very long combats would sometimes result in the encounter being deleted during combat.
- Made it so that debug mode doesn't display failed spawn attempts.
Updates to 0.9.3B:
- Added some tests in the spiral finder to determine the "right" level of Z to spawn elements at; tested this in caves and towers.
- Added a catch for an exception that could arise when a mobile was described in the encounter system, but that mobile did not have a default constructor; prints a diagnostic and ignores the mobile.
- In debug mode, the spiral finder animates its search (if this is an annoyance, let me know).
This is a D&D style "random encounter" engine for RunUO.
Note that encounters do not have to be hostile. For example,
this is a good way to make your world "come alive". You can
set it up so that wilderness creatures frequently appear near
the player when the player is in the wilderness. Since these
creatures are only spawned at or near where an active player
can see them, no CPU is wasted. It also adds an element of
unpredictability to the shard.
The system is fully configurable, by facet, by region type,
and by named regions (if desired). This allows the administrator
to control what kind of encounters appear where.
The system runs off a configuration file; the system rescans
this file periodically, if it notices that the file has been
written. So your shard does not have to be bounced for you to
make configuration changes.
INSTALLATION
============
Extract the zip file into your Scripts/Custom directory. Nothing else
is required. Note that the configuration file "RandomEncounters.xml" is
expected to reside in $RUNUO_INSTALL_DIR/Scripts/Custom/RandomEncounters.
If you want to put it somewhere else or name it something else, find the variable
"m_EncountersFile" in the RandomEncounterEngine class and fiddle with it.
HOW TO
======
The Random Encounter Engine is entirely controlled by its configuration file,
so understanding its format is essential. Before we talk aboutthat, though, a few
preliminaries:
The system is controlled on a common clock that periodically checks to see
if players (player mobiles with access level == Player, not staff members!)
qualify for a random encounter. To see if they qualify, first the system
decides which picker is in use. There are two.
The first picker is the "sqrt" (square root) picker. Its the default. When
the sqrt picker is in use, the system finds the square root of the number of
players online. The system then picks this many players to see if they further
qualify for a random encounter. No more than one encounter per player.
The second picker is the "all" picker. Using the all picker, the system
considers all players online for a random encounter.
Note switching between pickers is a dramatic event, which will GREATLY
impact the number of random encounters your player see; you should decide
early which picker you're going to use.
A player qualifies for a random encounter when:
1. The facet name, region type, and region name the player is in has
encounters described for it (example, the player is on Facet the
facet named "Felucca", in a "Dungeon" region named "Covetous").
2. Failing #1 above, the the system finds a region named "default" that
otherwise qualfies by facet name and region type (example, the
player is in a Felucca Dungeon, and is in Covetous, but the administrator
did not define a named region for Covetous. If there is a default
region for Felucca Dungeons, this will be used instead).
3. The system draws a random number 0.0-1.0, and searches for the LOWEST
probability encounter it can match.
If all of the above fail, the player has no encounter.
Now on to the details. Consider the following example:
Code:
<!--mycomment-->
<RandomEncounters picker="sqrt" delay="15.0" interval="15.0:25.0:35.0" cleanup="300.0" debug="true">
<!--mycomment-->
<Facet name="Felucca">
<Region type="Wilderness" name="default">
<Encounter p="1.0" distance="7">
<Mobile pick="OrcCaptain,OrcishLord">
<Mobile n="1:3" pick="Orc"/>
<Mobile p=".25" pick="OrcishMage"/>
</Mobile>
<Item pick="WoodenTreasureChest">
<Item pick="OrcHelm"/>
<Item pick="ChainChest,BattleAxe"/>
</Item>
</Encounter>
<Encounter p=".05" distance="7">
<Mobile pick="EvilMage"/>
<Mobile n="2:3" pick="Brigand"/>
</Encounter>
</Region>
</Facet>
</RandomEncounters>
This is a standard nested tag formatted xml file. It supports the following tags:
"RandomEncounters" tag. This supports the following attributes and defaults:
picker = the picking method, defaults to "sqrt"
language = the globalization code, defaults to "en-US".
skiphidden = tells the system to exclude hidden players from encounters, defaults to FALSE
delay = amount of secs before encounters begin after server start, defaults to "60"
interval = frequency in secs encounters are checked, defaults to "1800". This field can be separated into as many as 3 values, one each for dungeons, wilderness, and guarded regions. Separate with ":"
cleanup = how long to wait before shutting down spawned mobiles, defaults to "300"
debug ="false" (print out extra debugging information)
"Facet" tag.
name =[None] (mandatory tag naming the facet)
"Region" tag.
type =[None] (mandatory tag specifying region type; can be "Guarded", "Dungeon", and "Wilderness")
name =[None] (mandatory tag naming the region; use "default" to pick up generic)
"Encounter" tag.
p = probability of encounter, default of "1.0", which means 100%. If p is set to * (e.g., p="*"), the encounter will always be had in addition to any other encounter the player might have for the region
distance = the preferred distance from the player for the encounter, a number or a range (example "1" or "0:2" or "1:3"). Default is "7".
water = water mobiles can't spawn without this; land mobiles can't spawn with it, default is "false" DEPRECATED
landType= Water, OnRoad, OffRoad, or AnyLand. Default is "AnyLand".
time=Night, Twilight, Day, or AnyTime. Default is "AnyTime".
level=notional level of the character required to have the encounter; defaults to 1. An optional second argument can be sent to the level indicating class after a separating colon. E.g., "8:Necromancer". Valid current class names are Fighter, Ranger, Mage, Necromancer, Thief, and Overall.
scaleUp=true/false, whether or not to scale up encounters that are waker than the player; defaults to false. Never more than triples an encounter.
"Mobile" tag.
p = probability of the mobile being included in a picked encounter, default is "1.0"
pick =[None] (a list of mobiles to pick from (NO SPACES!); one is picked randomly)
n = a number or a range (example "1" or "0:2" or "1:3"), default is "1"
"Item Tag"
Same as Mobile tag.
Note how Mobiles and Items can appear embedded in one another. To know the rules, use
some common sense. An Item can be in a Mobile (e.g., "orc has a Sword"), and an Item can
be in an Item (e.g., "sword in a chest"), but a Mobile cannot be in an Item! A Mobile,
however, might belong to another Mobile's team...
Now a little word on picking. Consider the following (modified) fragment:
Code:
<Mobile n="2" pick="OrcCaptain,OrcishLord">
<Mobile n="1:3" pick="Orc"/>
<Mobile p=".25" pick="OrcishMage"/>
</Mobile>
for each leader, attach 1-3 Orcs, and likewise for each leader, offer a
.25 chance to have an OrcishMage. This calculates to a maximum of 10
Mobiles for the whole encounter.
Sub items spawn IN their parent items. Sub mobiles spawn NEAR their parent
mobiles.
(note that if a valid spawn point can't be found, a mobile or item might not
be spawned, and if this happens, the remaining part of a whole encounter might
be skipped).
EQUAL PROBABILITIES
================
It's both possible and okay to list two encounters in the same region with the same probability. In this particular case, the system draws randomly from all matching probability levels, so you don't get the wierd case where one is always preferred over the other. This also makes it so that you don't have to do gymnastics to separate all the possibilities. One could just use ".3" ".2" and ".1" for everything, letting the system sort out the equal probability encounters...