Easy Way to Find the Last Defined Object

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

Post Reply
User avatar
Pepsi Ranger
Liquid Metal Slime
Posts: 1457
Joined: Thu Nov 22, 2007 6:25 am
Location: South Florida

Easy Way to Find the Last Defined Object

Post by Pepsi Ranger »

Working on Entrepreneur: The Beginning tonight, and I was searching through the plotscript dictionary for a simple way to locate the last defined item (not from inventory, but from the game file) so that I can run a for/do loop that cycles through all items for various checks without having to continuously update the destination number each time I add a new item to the game. In the past I would just end on an arbitrary number well beyond my currently defined items (ex: 600 instead of the current 302), as that would guarantee I wouldn't have to mess with it for a while. But then the inevitable script errors would appear, telling me I don't have such and such item defined, and, well, that's lame and distracting.

So, I wrote a quick function that can run through all of my defined items until it detects a nonexistent one and write the last defined item ID into a global variable for use with a for/do block (or whatever may need that information to work efficiently). This script should work with almost any series of objects defined in your HSI file (items, songs, enemies, etc.) if you want a contained loop that counts every existing ID without going over the defined limit.

Code: Select all

global variable (1,itemcapped)

#example object limit finder (specifically for items)
#best to run at the start of your game or loaded game

script,find last defined item,begin
variable (loop)
loop := true
itemcapped := 0       #this variable will be used to close any conditional range of items used in a for/do block
while (loop) do(
  clear string (1)
  clear string (2)       #second string MUST be zero
  get item name (1,itemcapped)        #writes HSI name for item ID that matches the value of "itemcapped" to string 1
  if (string compare (1,2)==false) then(       #basically checks whether string 1 has a name or returns zero
    increment (itemcapped,1)       #and increments the value of "itemcapped" if a name is found
  )
  if (string compare (1,2)) then(      #breaks loop once both strings match, meaning string 1 has no name and returns zero
    loop := false
  )
)
clear string (1)
end

#example script that uses newly defined limit

script,inventory cleaner,begin
variable (i,inv)
for (i,0,itemcapped) do(
  inv := inventory (i)       #checks if the current item ID in the loop exists in player's inventory
  delete item (i,inv)         #and deletes it if found
)
end

#If game file has 302 items defined, then "itemcapped" will return a value of 302 if these scripts are written correctly.
Note that this script is for items only. If you want to write one similar for songs, enemies, etc., you'll have to change "get item name" to whatever plotscript command writes the HSI name into a string for that type (usually "get song name," "get enemy name," etc.). But this will ensure that you don't generate script errors for attempting to use nonexistent items (or songs or whatever), yet still keep up with your growing list of objects.

Hope some of you will find this useful tonight. Odds are TMC will find a way to make it obsolete by tomorrow.
Place Obligatory Signature Here
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Hope some of you will find this useful tonight. Odds are TMC will find a way to make it obsolete by tomorrow.
Hahaha. You've shown the real need for an official command. It's very simple to implement:

Code: Select all

script, last item id, begin
  return(read general(82))  # This is what's known in the trade as a "magic constant"
end
Of course that made me realise that there are many other similar commands that can be added. I started on them and will finish them off when I have more time.

One small problem with your script: "itemcapped" gets set to one past the last item ID with a name. In other words, it gets set to the number of items, rather than the last item with a valid ID. Subtract one either in "find last defined item" or when using it.

Actually, it turns out that "get item name" returns true if the item exists, and false if the item id or the string id are invalid. So you don't even need to check the name itself, and doing it that way also works item definitions with blank names.
Also, the fact that "get item name" doesn't set the string to empty if the item is invalid should probably be fixed.
Last edited by TMC on Sat Nov 12, 2016 7:24 am, edited 1 time in total.
Post Reply