Razor Enhanced Basics
This page will add some basics to know and help when coding things in Razor Enhanced. The attempt on writing this is to make it as easy as possible to understand some things and will just give a basic example and try to not get too technical to keep learning as easy.
Important Things To Know
Here are a few important things to remember when writing scripts.
- Check if need to Indent Make sure to always check when needing an indent or not on your code. This can always be a cause for a script not working.
- Don't Forget Pauses Misc.Pause(timeint) is a very important thing to remember. A lot of times when forgetting to use a pause or the right pause you can sometimes end up with a script that does not work properly and you cannot figure out why. Sometimes having this too low or non-existent can result in crashes.
- Containers Should Always Wait for Contents Items.WaitForContents(container,timeint) should always be used when opening a container with a script before having it look through the contents to ensure that razor enhanced can go through every item.
- Connected Player.Connected is the best to use with using a while instead of true. using 'while True:" will result in the script running as long as razor enhanced is loaded. 'while Player.Connected:" will only run when the player is connected and stop if logged out.
- Int start with 0 Always remember that an int will always start in 0. So when making an array or list unless specified they will always start with 0.
Indent
An Indent is a very important part of Python. Indents can be made by hitting the Tab key or space bar to create 4 empty spaces. Using Indents are required to add actions or responses to use when a query/condition is met.
EXAMPLE:
If Player.Hits < 20:
Player.ChatSay("Health is low!")
Misc.Pause(3500)
Misc.Pause(50)
Misc.SendMessage("No Longer inside Query")
With this above example, we can see that when the query of if your player has less than 20 hitpoints, it will say 'Health is low!" and then pause for 3.5 seconds. It will then exit after as there are no more direct lines beneath that are in the same indent. This will result in a pause of 50ms and the send message "No Longer inside Query" to go if your hitpoints are 20 or over, or it will go after the above condition (If Player.Hits < 20) actions are finished.
Having actions for a query/condition met inside the first would require a new indent to be placed.
EXAMPLE:
If Player.Hits < 20:
Player.ChatSay("Health is low!")
Misc.Pause(3500)
If Player.Stam > 200:
Player.ChatSay("But our stamina is over 200!")
Misc.Pause(2500)
Misc.Pause(50)
Misc.SendMessage("No Longer inside Query")
With this code, we added a check to see when our hits are under 20 if our stamina is over 200. This query/condition when met will result in it having the player say "But our stamina is over 200!" and then pause for 2500. This query/condition can only be accessed if the first query/condition is met of the player's hit points being under 20.
Functions
A function can be a sample of code to run that is only called upon when needed and will not force razor enhanced to only call it when part of the code requires it.
EXAMPLE:
self = Mobiles.FindBySerial(Player.Serial)
def castHealOnSelf():
Spells.Cast("Greater Heal")
Target.WaitForTarget(3500,False)
Target.TargetExecute(self)
while Player.Connected:
if Player.Hits < 50:
castHealOnSelf()
Misc.Pause(650)
BREAKDOWN:
self = Mobiles.FindBySerial(Player.Serial) This code is setting the 'self' variable to be linked to the player and tells Razor Enhanced that the variable is also a mobile so we can call on it later without having to write too much code every time.
def castHealOnSelf(): is the function that can be called at any time in this script by using "castHealOnSelf()". This will run all lines that are indented under it before a line that is not indented appears, which in this case, is 3 lines.
notice the next three lines are indented to tell razor enhanced they will run with the above function
Spells.Cast("Greater Heal") tells the game to cast the spell "Greater Heal".
Target.WaitForTarget(3500,False) is telling the script to not go further until a target appears on screen or 3500ms goes past (3.5 seconds). If the target does not appear it will just continue through as well so setting the wait time can vary on latency or your ISP's (Internet Service Provider's) routing to a server.
Target.TargetExecute(self) is having the spell target yourself with the 'self' variable we set at the top stating it is for your player.
notice the indent has gone away. this means this will happen when the script runs and is not part of the function that was written above it.
while Player.Connected: means that the code will run as long as the player is connected to the game. If they are not this code will stop.
notice the next three lines are indented so they will only run if your player is connected to the game.
if Player.Hits < 50: is a condition that needs to be met to run the following lines again. This one will only run the below code if your hit points go under 50.
notice the double indent below. this means that the function calling below will only happen if this condition above is made.'
castHealOnSelf() is where the script itself is calling the function to heal yourself we set above.
notice that below only one indent here which means it will happen only when the player is connected.
Misc.Pause(650) is set to pause for 650ms either after the healing function runs to heal yourself, or your hits are above 50 and do not go to the function . It is always good to have a pause here when this script will loop of some sort to help your pc from a potential crash from running too fast and having an error occur.
We could also use this same function with parameters if we need to do some specific things when a query/condition is met on a thing.
EXAMPLE:
pausetime = 650
def DoMove(scont, tcont):
Items.UseItem(scont)
Items.WaitForContents(scont,2500)
for i in scont.Contains:
Items.Move(i,tcont,-1)
Misc.Pause(pausetime)
Misc.SendMessage('Done Moving Items', 32)
source = Target.PromptTarget('Select Source Container')
sourcecont = Items.FindBySerial(source)
target = Target.PromptTarget('Select Target Container')
targetcont = Items.FindBySerial(target)
if sourcecont and targetcont:
DoMove(sourcecont, targetcont)
Misc.SendMessage('Script End', 32)
BREAKDOWN:
pausetime = 650 is setting a variable to a pause time that we can use for all pauses in this script in case we wanted more than one to save time having to remember changing more than one pause. This would allow you to change all the timers at once with one variable change.
def DoMove(scont, tcont): is a function that has two incoming parameters 'scont' and 'tcont' which you will see later in the script will be sent as Items and since their itemid are stored in RE as Containers it will know they can be accessed as containers.
notice below we have an indent again to make sure that all the lines underneath with this indent or further will only happen when this function is called upon.
Items.UseItem(scont) simulates a double click on an item. so in this case it will open 'scont' with a double click.
Items.WaitForContents(scont,2500) will not continue past until either all the contents are loaded from the server on the 'scont' or 2500ms (2.5 seconds) have passed. This is used to make sure you don't miss an item when having the script look through them.
for i in scont.Contains: This will go through every item inside the 'scont' 1 at a time and do anything indented directly under this tells Razor to do.
notice below an indent here to show that the indent that is now 2 indents wide will all work inside the above "for" statement.
Items.Move(i,tcont,-1) this is telling razor enhanced that the item it is on (i) is to be moved to the 'tcont' container. the -1 represents any amount. (setting amount to 3 on a stackable item would result in moving only 3 of the stack).
Misc.Pause(pausetime) is telling the script to pause before any more actions for the set time at the top of the script with 'pausetime' variable being called.
notice below we went back to only one indent. This means this action will only run after the 'for' statement has finished.
Misc.SendMessage('Done Moving Items', 32) is telling the client to simulate a system message on the left that says "Done Moving Items" with a hue of 32.
notice below that the indents are gone this means these actions will run when you hit play unlike the function above which needs to be called.
source = Target.PromptTarget('Select Source Container') is sending a target to your client to have you target an item that will be your source container. This will return the serial of the container.
sourcecont = Items.FindBySerial(source) is setting the item you selected by the target as an item to Razor Enhanced so it knows it is an item.
target= Target.PromptTarget('Select Target Container') is sending a target to your client to have you target an item that will be your source container. This will return the serial of the container.
targetcont = Items.FindBySerial(target) is setting the item you selected by the target as an item to Razor Enhanced so it knows it is an item.
if sourcecont and targetcont: this is having razor enhanced to make sure both items exist.
notice below the indent here. this is saying that this next line will only happen if razor enhanced determines 'sourcecont' and 'targetcont' both exist.
DoMove(sourcecont, targetcont) this is calling the function of DoMove with two parameters that were needed for the function . It is sending first 'sourcecont' (the source container you targeted) and 'targetcont' (the target container you targeted).
notice below the indent has moved again. this is to let you know we are no longer only doing this if the 'sourcecont' and 'targetcont' exist, it will happen even if they do not.
Misc.SendMessage('Script End', 32) is telling the client to simulate a system message on the left that says "Script End" with a hue of 32. The script will end after this.
But what if we only wanted to move a few items of a specific itemid? We can do so by editing the above example below.
EXAMPLE:
pausetime = 650
def DoMove(scont, tcont):
Items.UseItem(scont)
Items.WaitForContents(scont,2500)
for i in scont.Contains:
if i.ItemID == 0x0DF0:
Items.Move(i,tcont,-1)
Misc.Pause(pausetime)
elif i.ItemID == 0x410A:
Items.Move(i,tcont,-1)
Misc.Pause(pausetime)
Misc.SendMessage('Done Moving Items', 32)
source = Target.PromptTarget('Select Source Container')
sourcecont = Items.FindBySerial(source)
target = Target.PromptTarget('Select Target Container')
targetcont = Items.FindBySerial(target)
if sourcecont and targetcont:
DoMove(sourcecont, targetcont)
Misc.SendMessage('Script End', 32)
BREAKDOWN:
This code is essentially the same with a few changes put in that we will discuss here. inside the function DoMove(scont, tcont) we can see a few lines added in extra.
if i.ItemID == 0x0DF0: will check if the itemid of each item matches this itemid.
Items.Move(i,tcont,-1) this is telling razor enhanced that the item it is on (i) is to be moved to the 'tcont' container. the -1 represents any amount. (setting amount to 3 on a stackable item would result in moving only 3 of the stack).
Misc.Pause(pausetime) is telling the script to pause before any more actions for the set time at the top of the script with 'pausetime' variable being called.
elif i.ItemID == 0x410A: will check if the itemid of each item matches this itemid. We used elif so it does not try to move an item twice if say one condition was if the itemid was a certain id and the other was checking for the hue.
These were the only lines added to check on this setting for itemids. You could do the same to check for hue with i.Hue instead of i.ItemID.
Lists
Filter Lists
Filter lists are useful for various amounts of things some of the more useful are scanning the areas for mobiles and items.
For more information after reading this on what can be added to a [| mobile filter] or an [| item filter] with these links. As you get more advanced you can do loads with filters, Razor Enhanced also has filters that can be used for pathfinding, and targets.
Let's go through using a Mobile filter list to create a generic attacking script that just attacks monsters.
EXAMPLE:
from System.Collections.Generic import List
from System import Byte
def searchArea():
atk = Mobiles.Filter()
atk.Enabled = True
atk.CheckLineOfSight = True;
atk.RangeMax = 5
atk.Notorieties = List[Byte](bytes([3,4,5,6]))
enemies = Mobiles.ApplyFilter(atk)
return enemies
def goattackenemy(enemy):
monster = Mobiles.FindBySerial(enemy.Serial)
if monster:
Player.Attack(enemy)
Misc.Pause(150)
if monster and Player.InRangeMobile(monster,2):
goattackenemy(monster)
def main():
enemies = searchArea()
Mobiles.Select(enemies,'Nearest')
for enemy in enemies:
monster = Mobiles.FindBySerial(enemy.Serial)
if monster:
goattackenemy(monster)
Misc.Pause(350)
Misc.Pause(350)
while Player.Connected:
main()
BREAKDOWN
from System.Collections.Generic import List Is importing lists to be used in the script. We need to add the ability to use the namespace at the start with "from System.Collections.Generic" and then import using the list with "import List".
from System import Byte Is importing Byte to be used in the filter list. This is the same we again need to add the namespace "from.System" and then "import Byte".
def searchArea(): Here is the function for the filter that can be called anytime use of the filter is needed.
atk = Mobiles.Filter() Is setting the variable for the filter as atk. This also lets the script know atk is a Mobiles.Filter.
atk.Enabled = True Is telling the script this filter is enabled.
atk.CheckLineOfSight = True Is Telling the filter to only add mobiles that are within the line of sight of the player.
atk.RangeMax = 5 Is setting the filters range of what mobiles to add to the filter.
atk.Notorieties = List[Byte](bytes([3,4,5,6])) This is setting notorieties in which you want added to the filter. The list is blue = 1, green = 2, gray = 3, gray crim = 4, orange = 5, red = 6, yellow = 7.
enemies = Mobiles.ApplyFilter(atk) This is applying the filter list created to the 'enemies' variable.
return enemies Returns the list to where it was called when written correctly (enemies = searchArea()).
def goattackenemy(enemy): Is a function that will attack a mobile that is sent as the parameter with this function.
monster = Mobiles.FindBySerial(enemy.Serial) Sets the variable 'monster' as mobile by the serial of 'enemy' that was sent. This while not needing to be here, can help below statement sometimes ensure the mobile does exist.
if monster: Checks if the variable 'monster' exists.
Player.Attack(enemy) Will attack variable that is provided 'enemy'.
Misc.Pause(150) A pause of 150ms that can be useful to stop a potential crash.
if monster and Player.InRangeMobile(monster,2): this is checking after you attack if the monster still exists and is in a range of 2 from the player. The range could be changed if using a ranged weapon but usually, 2 is best for using melee weapons.
goattackenemy(monster) Calls the 'goattackenemy' function again to attack again if the mobile exists.
def main(): A function that can be called. This is set as the main function for this script.
enemies = searchArea() This is using the filter list function to gather a list of mobiles set in the filter used in searcArea().
Mobiles.Select(enemies,'Nearest') This is sorting the list by range starting with the nearest mobile.
for enemy in enemies: Is a For loop to cycle through the list and let you choose what to do for each mobile in the list.
monster = Mobiles.FindBySerial(enemy.Serial) Is setting the mobile to a variable. FindBySerial will set this variable to know it is a mobile and not just an object.
if monster: This is a condition to check if the mobile exists or not.
goattackenemy(monster) Calls the 'goattackenemy' function to attack the mobile.
Misc.Pause(350) A pause of 350ms that can be useful to stop a potential crash.
Misc.Pause(350) A pause of 350ms that can be useful to stop a potential crash.
while Player.Connected: This is essentially saying that it will always run main instead of stopping as long as the player is connected. While you could also use 'while True:' it is better to use Player.Connected for any script that sends packets to the game, to prevent from being locked up trying to send actions without your player being able to (this will force you to close out the game and restart).
main() Calls the function 'main' to be run.
Arrays
Arrays can be a good way to store multiple ids to a variable to call on to use for lots of different purposes.
Say we wanted to use an array to store ItemIDs for items that we can move using code we used from the functions section. Here is an example below.
EXAMPLE:
itemids = [0x0DF0, 0x410A]
pausetime = 650
def DoMove(scont, tcont):
Items.UseItem(scont)
Items.WaitForContents(scont,2500)
for i in scont.Contains:
if i.ItemID in itemids:
Items.Move(i,tcont,-1)
Misc.Pause(pausetime)
Misc.SendMessage('Done Moving Items', 32)
source = Target.PromptTarget('Select Source Container')
sourcecont = Items.FindBySerial(source)
target = Target.PromptTarget('Select Target Container')
targetcont = Items.FindBySerial(target)
if sourcecont and targetcont:
DoMove(sourcecont, targetcont)
Misc.SendMessage('Script End', 32)
BREAKDOWN:
We will breakdown a few of the new settings that are shown here to use an array to find an item specific to the itemid.
itemids = [0x0DF0, 0x410A] is a built array holding two ItemIDs. You could add more by adding a comma and a new ItemID.
if i.ItemID in itemids: Is where checking to see if the ItemID is in the array that we set at the top.
By using this change we can add more items that we could move faster and have editing to add remove more items easier.
It is possible you want your chest to be organized nice and neat. You can use an array to help with this! Below I will give an example of using an array to move items from one container to another by ItemID to a specific location in the container (so they are stacked ontop of each other looking like the 1 item instead of cluttered all over).
EXAMPLE:
itemidswloc = [[0x0DF0, 88, 264], [0x410A, 49, 138]]
pausetime = 650
def DoMove(scont, tcont):
Items.UseItem(scont)
Items.WaitForContents(scont,2500)
for i in scont.Contains:
for id in itemidswloc:
if i.ItemID == id[0]:
Items.Move(i, tcont, -1, id[1], id[2])
Misc.Pause(pausetime)
Misc.SendMessage('Done Moving Items', 32)
source = Target.PromptTarget('Select Source Container')
sourcecont = Items.FindBySerial(source)
target = Target.PromptTarget('Select Target Container')
targetcont = Items.FindBySerial(target)
if sourcecont and targetcont:
DoMove(sourcecont, targetcont)
Misc.SendMessage('Script End', 32)
BREAKDOWN:
So let's go through the changes made to achieve this.
itemidswloc = [[0x0DF0, 88, 264], [0x410A, 49, 138]] This array has been changed. Instead of one Array this becomes essentially an array stored inside an array. The first thing stored in this array is the ItemID, and next are the X and Y location values inside a chest (when an item is in a container and you inspect it the x and y shown are the x y inside the container).
for id in itemidswloc: Here we have gone so it will cycle one by one each item in the array at the top and let us compare the item with the values inside the array.
if i.ItemID == id[0]: This is stating if the ItemID matches the ItemID in the array (id[0] would mean the first spot in the array where the ItemID always is).
Items.Move(i, tcont, -1, id[1], id[2]) Now we are moving the if it was correct to the container but telling the server what location inside the container to drop it in (id[1] represents the 2nd parameter inside the array and id[2] represents the third and final one inside the array).
Using this should explain how using arrays in different ways can be useful.
NOTE: The arrays can sit in many different fashions. The Arrays here used ItemIDs and X Y locations inside the []. So an Array of different ItemIDs would sit [itemid1, itemid2, itemid3]. The second example helps show using multiple arrays. [itemid, x, y] is each array then to add that to an array you could do [[itemid1, x1, y1], [itemid2, x2, y2], [itemid3, x3, y3] ].
EXAMPLE:
Arraylist = [["Go one", "Go One Two", "Go One Three"], ["Go Two", "Go Two Three", "Go Two Three Four"] ]
Player.ChatSay(Arraylist[0][2])
BREAKDOWN:
With the above code, your player will end up saying "Go One Three". This is due to the first [] being a 0 which calls the first location inside the array. It will call the third location in that first location array. Always remember 0 is the first location. As with ints 0 is the start not 1.
Gumps
Interaction with Gumps
Creating A Gump
Gump creating can have many uses to make scripts that can do multiple things based on hitting different buttons. Using a created gump can add a gump to your game screen that only your client knows is there for you to use.
EXAMPLE:
setX = 25
setY = 50
def sendgump():
gd = Gumps.CreateGump(movable=True)
Gumps.AddPage(gd, 0)
Gumps.AddBackground(gd, 0, 0, 450, 53, 30546)
Gumps.AddAlphaRegion(gd,0,0,450,53)
Gumps.AddButton(gd, 5, 5, 2241, 2241, 1, 1, 0)
Gumps.AddTooltip(gd, r"Create Food")
Gumps.AddButton(gd, 49, 5, 2254, 2254, 2, 1, 0)
Gumps.AddTooltip(gd, r"Protection")
Gumps.AddButton(gd, 93, 5, 2261, 2261, 3, 1, 0)
Gumps.AddTooltip(gd, r"Teleport")
Gumps.AddButton(gd, 137, 5, 2269, 2269, 4, 1, 0)
Gumps.AddTooltip(gd, r"Lightning")
Gumps.AddButton(gd, 181, 5, 2271, 2271, 5, 1, 0)
Gumps.AddTooltip(gd, r"Recall")
Gumps.AddButton(gd, 225, 5, 2281, 2281, 6, 1, 0)
Gumps.AddTooltip(gd, r"Energy Bolt")
Gumps.AddButton(gd, 269, 5, 2283, 2283, 7, 1, 0)
Gumps.AddTooltip(gd, r"Invisibility")
Gumps.AddButton(gd, 313, 5, 2284, 2284, 8, 1, 0)
Gumps.AddTooltip(gd, r"Mark")
Gumps.AddButton(gd, 357, 5, 2287, 2287, 9, 1, 0)
Gumps.AddTooltip(gd, r"Reveal")
Gumps.AddButton(gd, 401, 5, 2291, 2291, 10, 1, 0)
Gumps.AddTooltip(gd, r"Gate Travel")
Gumps.SendGump(987654, Player.Serial, setX, setY, gd.gumpDefinition, gd.gumpStrings)
buttoncheck()
def buttoncheck():
Gumps.WaitForGump(987654, 60000)
Gumps.CloseGump(987654)
gd = Gumps.GetGumpData(987654)
if gd.buttonid == 1:
Spells.CastMagery('Create Food')
elif gd.buttonid == 2:
Spells.CastMagery('Protection')
elif gd.buttonid == 3:
Spells.CastMagery('Teleport')
elif gd.buttonid == 4:
Spells.CastMagery('Lightning')
elif gd.buttonid == 5:
Spells.CastMagery('Recall')
elif gd.buttonid == 6:
Spells.CastMagery('Energy Bolt')
elif gd.buttonid == 7:
Spells.CastMagery('Invisibility')
elif gd.buttonid == 8:
Spells.CastMagery('Mark')
elif gd.buttonid == 9:
Spells.CastMagery('Reveal')
elif gd.buttonid == 10:
Spells.CastMagery('Gate Travel')
while Player.Connected:
sendgump()
Misc.Pause(750)
BREAKDOWN:
setX = 25 x Location on the screen where to set gump. 0 on x would be all the way to the left.
setY = 50 y Location on the screen where to set gump. 0 on y would be all the way at the top.
def sendgump(): Function for setting up and sending the gump to your client.
gd = Gumps.CreateGump(movable=True) setting the variable 'gd' as a new gump for creation (movable = True will mean the Gump can be moved around the screen by the player setting to False would not allow you to move it).
Gumps.AddPage(gd, 0) Add a page for the Gump to run things. This can be useful when adding a second page that has separate data.
Gumps.AddBackground(gd, 0, 0, 450, 53, 30546) Is Adding the background. These are set in as Gump (gd), x (0), y (0), Length (450), Height (53), and GUMPID(30546). At the end of this section, there will be links and guides on how to find Gump ids.
Gumps.AddAlphaRegion(gd,0,0,450,53) Is Adding the background. These are set in as Gump (gd), x (0), y (0), Length (450), and Height (53). This is not needed for adding a Gump. This adds a see-through appearance to the sections where they are set to be.
Gumps.AddButton(gd, 5, 5, 2241, 2241, 1, 1, 0) Is adding a button the settings are gump (gd), x (5), y (5), ButtonIDUnPressed (2241), ButtonIDPressed (2241), ButtonID (1), ButtonType (1), Param(0). x and y represent where the button will be placed in the gump on the screen. ButtonIDUnPressed and ButtonIDPressed represent the gump id used when not pressed and while pressing before it sends the ButtonType as pressed to Razor Enhanced. ButtonID is what number of the button so Razor Enhanced knows what button you pushed. ButtonType could be changed for different things like changing a page, 1 is standard for Reply.
Gumps.AddTooltip(gd, r"Create Food") Is Adding a tooltip for when you hover over the button/item that is directly above it (in this case the button).
Gumps.SendGump(987654, Player.Serial, setX, setY, gd.gumpDefinition, gd.gumpStrings) This is how the gump gets sent to your client. Notice the number at the start 987654. This is the Gump Serial. It is wise to use numbers quite high up so they do not interfere with normal gumps sent from the server. When making a new gump you should always make sure your gump serials are never the same.
buttoncheck() This is going to go to the function to check for buttons.
def buttoncheck(): This is the function that waits and checks for button presses.
Gumps.WaitForGump(987654, 60000) This is waiting for 60 seconds (60000ms) for a response to gump serial 987654. It is important that you use the same gump serial as you set above on the SendGump line.
Gumps.CloseGump(987654) This is closing the gump. This is good practice in case of an error so the gump does not get stuck on the screen.
gd = Gumps.GetGumpData(987654) This is setting variable 'gd' to the gump data from the Gump serial 987654. This is also another that is Important to be set to the same gump serial from the one you sent.
if gd.buttonid == 1: This is if the ButtonID from the gump that was pressed was 1.
Spells.CastMagery('Create Food') Cast Spell. This will cast the spell 'Create Food' when button 1 is pressed on the gump.
elif gd.buttonid == 2: This is if the ButtonID from the gump that was pressed was 2.
Spells.CastMagery('Protection') Cast Spell. This will cast the spell 'Protection' when button 1 is pressed on the gump.
while Player.Connected: This is a loop that will be run as long as the Player is connected to the game.
sendgump() This will call the send gump function to run which will build and send the gump.
Misc.Pause(750) This is a pause so when it is returned after sending the gump there is a 750ms pause before sending again. This can help stop a possible crash or freeze.
I only added one line for the Buttons and 2 for the Buttons in the response because it they are the same settings. You can just follow them that way and adjust the X, Y, ButtonID on the buttons, and change the ButtonID action on the button check function.
With this information you can learn a small basic into making gumps. There are other commands that can be used when making a gump.
Some of those are:
- Gumps.AddHtml(gd,x,y,width,height,text,background,scrollbar)
- Gumps.AddLabel(gd,x,y,hue,text)
- Gumps.AddImage(gd,x,y,gumpID)
- Gumps.AddImageTiled(gd,x,y,width,height,gumpID)
A resource for finding gump ids can be UOFiddler. This is more of an advanced program though. It can be found [[ https://github.com/polserver/UOFiddler | here].
Some background IDs are already referenced on ServUO's website [[ https://www.servuo.com/threads/gump-background-reference.4773/ | here]].