Has anyone here ever attempted object/class programming with slices in their OHR games?
I'm in the middle of making a custom battle engine that, so far, has only needed slices for sprites, boxes, and other visual elements. Some data - like Hero/Enemy stats - I've been pulling from the numbers I enter ahead of time in CUSTOM, and other data - like sprite indices and maximum stats for enemies - I've been keeping track of with global variables and assigning with plotscripts. But, as I try to do more and more with this system, I'm starting to wonder if I'm going about this in an inefficient way. There has to be a better method.
My theory is to use persistent, invisible slices that act as pseudo-objects for all battle units, both Heroes and Enemies, with slice children containing data for some of the elements you'd see in the default Hero data - base stats, max stats, current stats, sprite info, spell lists, equipped items, etc. - as well as new things that the default Hero data doesn't keep track of - custom status ailment flags, for example, or X&Y values (not for position on the screen, but position in a custom-made grid). Who knows what else I might need in the future.
Anyway, if anyone's done anything like this before, I'd like to know, and I'd like to ask for your advice, or perhaps a peek at your source code.
Pseudo-OOP with slices?
Moderators: marionline, SDHawk
Pseudo-OOP with slices?
Last edited by Baconlabs on Thu Jul 12, 2018 10:05 pm, edited 1 time in total.
I'm working on it right now. I can get you an example script I used, but it might need some tweaking. It's brief, but uses slices to make objects with attributes using slice extra data and private methods using subscripts. Let me know if you have any questions. I can also show you my implementation of this template. I used it to make more detailed NPC definitions.
Here's the script. I can PM you the hss file as well, if you want.
Here's the script. I can PM you the hss file as well, if you want.
Code: Select all
# Template for Object Oriented Programming in Hspeak
# by kylekrack
# These constants refer to attributes within an NPC object
# They are related to extra data slots
define constant, begin
0,att:thing1
1,att:thing2
2,att:thing3
end
#EXAMPLE
# If you want to call an existing Object's method, you would call:
# obj(#, setAttribute, arg1)
# CONSTRUCTOR
# Adds a child slice to a global parent that represents the new object.
# A new object's id is determined by the order in which it was created.
# In other words, the id is the child number of the parent slice.
# Attributes:
#
# More attributes can be added by adding arguments to this Constructor script
script, newObj, field1, field2, field3, begin
variable(dad, sl, sli)
# Parent slice of all objects
# I recommend making a parent slice for all of your objects, rather than
# making them direct children of the script layer. This parent slice
# should be created elsewhere, like a newgame script
# Change lookup code to appropriate parent slice on the script layer
# NOTE: you must add the lookup code to your hsi file by defining it in
# the slice collection editor
dad := lookupSlice(sli:dad, sl:scriptLayer)
# Alternatively, you could create these object slices directly on the
# script layer and refer to them from there.
# Make the slice that represents the Object
sl := createContainer(0,0)
setParent(sl, dad)
# May create sub-slices to sl here as well to fit more attributes
# Set Base Attributes
setSliceExtra(sl, att:thing1, field1)
setSliceExtra(sl, att:thing2, field2)
setSliceExtra(sl, att:thing3, field3)
# Set Sub-Slice Attributes
# sli := createContainer(0,0)
# setParent(sli, sl)
# setSliceExtra(sli, extra0, field4)
end
# obj method constants
# This is like calling object.method(args) in Java or some other language
# : The parallel is "obj(id, methodConstant, args...)"
define constant, begin
0,getAttribute
1,setAttribute
end
# Call this to access or manipulate data for an Object
script, obj, id, func, arg1=0, arg2=0, arg3=0, begin
# Variables for slice handles (in hierarchy)
variable(dad, sl, sli)
# Parent slice handle
# Change lookup code to appropriate parent slice on the script layer
dad := lookupSlice(sli:dad, sl:scriptLayer)
# Object slice handle
sl := sliceChild(dad, id)
if(not(sl)) then(exitReturning(-1)) # Check if slice is valid
# SUBSCRIPT CALLS
switch(func) do, begin
# ACCESS METHODS
case(getAttribute) sub:getAttribute(arg1)
# MANIPULATION METHODS : 1 LINE
case(setAttribute) sub:setAttribute(arg1,arg2)
# INVALID CALL
case(else) exitReturning(-1)
end
# ACCESS METHODS
subscript, sub:getAttribute, type, begin
# Return extra data based on type constant
exitReturning(getSliceExtra(sl, type))
end
# MANIPULATION METHODS
subscript, sub:setAttribute, type, val, begin
# Return extra data based on type constant
exitReturning(setSliceExtra(sl, type, val))
end
end
My pronouns are they/them
Ps. I love my wife
Ps. I love my wife
- Bob the Hamster
- Lord of the Slimes
- Posts: 7658
- Joined: Tue Oct 16, 2007 2:34 pm
- Location: Hamster Republic (Ontario Enclave)
- Contact:
Yes! You can look at my scripts in Don't Eat Soap, Bell of Chaos, Paladin Traducer, and Vorpal Florist. I used a very similar method OO in all of them.
It works pretty well. You can even fake methods by storing script references with the @scripname feature and call them with wrappers that use "run script by id"
It works pretty well. You can even fake methods by storing script references with the @scripname feature and call them with wrappers that use "run script by id"
Ah, thanks! Quick question before I get too deep into this - you're using a lot of camel-case statements, like "lookupSlice" instead of "lookup slice". Does hspeak recognize that? Have we always been able to do that? If so, I had no idea! I'll get to messing with this over the next week and let you know how well it goes.
Also, thanks James, I've never tried anything like what you're describing; after flipping through a bit of the Bell of Chaos source, I think I get the gist of how "run script by id" is supposed to be used. I'll keep this in mind going forward.
Also, thanks James, I've never tried anything like what you're describing; after flipping through a bit of the Bell of Chaos source, I think I get the gist of how "run script by id" is supposed to be used. I'll keep this in mind going forward.
All righty, stop me if any of this sounds iffy. Using a "Unit" template, I'll be making parent slices for each unit in the game with lots of child slices attached to them storing info about this and that. All parents will be created during the new-game script, but some will have their children left blank.
Parents defined as "Heroes" will have info assigned to their children during a Joins-the-Party script; these parents will be used throughout the entire game and modified over time with various scripts handling things like equipment and skill sets. Parents defined as "Enemies" will be used as templates that are created during the New-Game script and never modified - rather, a small number of blank-slate "Enemy" parents will have info copied into them from the Enemy templates when a battle begins, and it's those parents that will be referenced and modified during battles. (There will never be more than 9 Heroes and 9 Enemies in any given battle.)
After a bit of brainstorming, I've determined that each of these "Unit" parents will be assigned about 100 child slices each. Over half of that comes from building 3 new "spell lists" with 20 slots apiece. A lot of those children are also dedicated to individual status ailment flags, since I want those to be able to stack. Did I get carried away with this? Do you guys think that'll make the game slow to a crawl? I hope not. I don't plan on having more than 18 of these units active in any given battle, if that makes any difference.
Parents defined as "Heroes" will have info assigned to their children during a Joins-the-Party script; these parents will be used throughout the entire game and modified over time with various scripts handling things like equipment and skill sets. Parents defined as "Enemies" will be used as templates that are created during the New-Game script and never modified - rather, a small number of blank-slate "Enemy" parents will have info copied into them from the Enemy templates when a battle begins, and it's those parents that will be referenced and modified during battles. (There will never be more than 9 Heroes and 9 Enemies in any given battle.)
After a bit of brainstorming, I've determined that each of these "Unit" parents will be assigned about 100 child slices each. Over half of that comes from building 3 new "spell lists" with 20 slots apiece. A lot of those children are also dedicated to individual status ailment flags, since I want those to be able to stack. Did I get carried away with this? Do you guys think that'll make the game slow to a crawl? I hope not. I don't plan on having more than 18 of these units active in any given battle, if that makes any difference.
Last edited by Baconlabs on Fri Jul 13, 2018 6:46 am, edited 1 time in total.
- Bob the Hamster
- Lord of the Slimes
- Posts: 7658
- Joined: Tue Oct 16, 2007 2:34 pm
- Location: Hamster Republic (Ontario Enclave)
- Contact:
I don't remember if you can get @ references to subscripts or not. Tmc would remember.
The lathe number of slices you describe does not sound like a problem, but if you do want to reduce the number of slices, remember that you can cram a lot of data into a single invisible slice. Three "extra" data slots, x, y, width, height, four padding values.
The lathe number of slices you describe does not sound like a problem, but if you do want to reduce the number of slices, remember that you can cram a lot of data into a single invisible slice. Three "extra" data slots, x, y, width, height, four padding values.
You can't. (Because they can't run without the parent scripts. HSpeak would have to check that you don't use any non-local variables from the parent scripts.)I don't remember if you can get @ references to subscripts or not.
An extra 1800 slices should have virtually no effect, as long as they aren't visible.
Example of stuffing data into a slice: fake arrays
Last edited by TMC on Sat Jul 14, 2018 7:12 pm, edited 1 time in total.