Layered Walkabout / Visible Equippment / Could use a hand
Moderators: marionline, SDHawk
Layered Walkabout / Visible Equippment / Could use a hand
Hello,
I know I read about this somewhere, but can't seem to find it right now, so sorry for asking again an old question
Basically, I want my player to be able to customize his hero, which would end up in having the player walkabout being comprised of 4 layers:
Basesprite (m/f)
Haircut
Clothes / Armour
Weapon
The basesprite and haircut would be chosen at start, clothes and weapon would be dependant on the equipped armour and weapon.
All layers are walkabouts sized the same (to keep things simpler).
(Btw, the character creation menu is not the problem, this works well ;) )
Right now I would change the walkabout to be my basesprite dependent on player choice, no sweat there.
Storing which walkabout has been chosen for the other layers is no problem either (e.g. global variables, for the quickest way, same for the palettes).
Additionally I use the three-frame walking script, and here my dilemma begins.
Right now, it is a tad above my level, but I feel there must be an 'easy' way to simply 'stamp' the other walkabouts atop...
Any suggestions?
I know I read about this somewhere, but can't seem to find it right now, so sorry for asking again an old question
Basically, I want my player to be able to customize his hero, which would end up in having the player walkabout being comprised of 4 layers:
Basesprite (m/f)
Haircut
Clothes / Armour
Weapon
The basesprite and haircut would be chosen at start, clothes and weapon would be dependant on the equipped armour and weapon.
All layers are walkabouts sized the same (to keep things simpler).
(Btw, the character creation menu is not the problem, this works well ;) )
Right now I would change the walkabout to be my basesprite dependent on player choice, no sweat there.
Storing which walkabout has been chosen for the other layers is no problem either (e.g. global variables, for the quickest way, same for the palettes).
Additionally I use the three-frame walking script, and here my dilemma begins.
Right now, it is a tad above my level, but I feel there must be an 'easy' way to simply 'stamp' the other walkabouts atop...
Any suggestions?
Last edited by DWRL on Sat Mar 07, 2020 3:42 pm, edited 2 times in total.
The easy part is loading the additional layers. You can use load walkabout sprite() to make the sprite appear, and then set parent(handle, getHeroSlice(me)) to make it follow the hero's position. (You will likely need to adjust the specific positioning of the sprite with the set horiz/vert align/anchor.)
Animating the sprite is another story. You might be able to simplify it by setting each sprite's frame (hair, clothes, etc.) to the base sprite's frame every tick. I'm not sure what complications that may add, especially with 3 frame walking.
Animating the sprite is another story. You might be able to simplify it by setting each sprite's frame (hair, clothes, etc.) to the base sprite's frame every tick. I'm not sure what complications that may add, especially with 3 frame walking.
My pronouns are they/them
Ps. I love my wife
Ps. I love my wife
Oh! Witch2.rpg used it beautifully. Have a look.
Actually, you should write "set parent(slice, getHeroSprite(me))" instead of "set parent(slice, getHeroSlice(me))", so that it will work if there is a foot-offset on the map or if the hero Z changes (eg riding an airship). Those change the position of the hero walkabout sprite relative to its parent, the walkabout container slice.
In order to make the overlays animate, you could write a script that every tick updates the overlaid sprites so that they have the same frame as the base sprite. You will want to make this script loop using timers instead of a while loop, so that it doesn't get paused if other scripts run:
But there's a problem. The script doesn't run until the tick after the sprite frame has changed, due to the order in which things are run each frame. Try it and see whether it annoys you. (Increasing the frame rate might make it less noticable). It is possible to work around that problem, using something derived from this script, but it's quite complex.
If you use three-frame walking then you could also make the overlay sprites use more three frames too. If you don't then they will simply use two frames, but everything I wrote above is still true. Find the line in the three-frame script: "set spriteset number(slice, current spriteset)", and add some logic to change the spritesets of the overlay slices too.
The three-frame walking script is going to be obsolete very soon.
In order to make the overlays animate, you could write a script that every tick updates the overlaid sprites so that they have the same frame as the base sprite. You will want to make this script loop using timers instead of a while loop, so that it doesn't get paused if other scripts run:
Code: Select all
define constant(1, timer: overlays)
script, update overlays, begin
set sprite frame (..., get sprite frame(get hero sprite(me)))
set timer(timer:overlays, 0, 1, @update overlays) # Run this script again next next
end
If you use three-frame walking then you could also make the overlay sprites use more three frames too. If you don't then they will simply use two frames, but everything I wrote above is still true. Find the line in the three-frame script: "set spriteset number(slice, current spriteset)", and add some logic to change the spritesets of the overlay slices too.
The three-frame walking script is going to be obsolete very soon.
@kylekrack: Thanks, you did kickstart me here
@bird: Wow. This is helpful, thank you!
Actually, my biggest problems at the moment are nomenclature and slices.
Once I replaced all variable names in the three-frame-walk script (e.g. 'current spriteset' to 'current bodySet') I had less problems.
Not knowing what words are keywords and which are functions/commands isn't exactly helpful, especially while trying to wrap my head around slices and learning the language
(On a side question, is hamsterscript related to / derived from any other language? Right now I use python syntax highlighting, which makes the scripts by far more readable, but maybe there is something other my editor might know about?)
Right now my script works and puts everything nicely together, but seems to suddenly change the overlayed walkabout from #9 to #1 for some reason...
For the tick problem I just made the hero sprite set in the editor transparent and used the script for the body too. This way, it all was nicely in sync. The miniscule delay on turning around didn't bother me too much (yet).
If yes I am perfectly happy to let this rest for now 'till I can do without it, as I don't want to use unnecessary code, and guess it might lead to a cleaner implementation for the layers as well.
Oh, and a first look at the character creation menu
@bird: Wow. This is helpful, thank you!
Actually, my biggest problems at the moment are nomenclature and slices.
Once I replaced all variable names in the three-frame-walk script (e.g. 'current spriteset' to 'current bodySet') I had less problems.
Not knowing what words are keywords and which are functions/commands isn't exactly helpful, especially while trying to wrap my head around slices and learning the language
(On a side question, is hamsterscript related to / derived from any other language? Right now I use python syntax highlighting, which makes the scripts by far more readable, but maybe there is something other my editor might know about?)
Right now my script works and puts everything nicely together, but seems to suddenly change the overlayed walkabout from #9 to #1 for some reason...
For the tick problem I just made the hero sprite set in the editor transparent and used the script for the body too. This way, it all was nicely in sync. The miniscule delay on turning around didn't bother me too much (yet).
Might I ask if we talk about a palatable timeframe here, say two to three months or something like that?The three-frame walking script is going to be obsolete very soon.
If yes I am perfectly happy to let this rest for now 'till I can do without it, as I don't want to use unnecessary code, and guess it might lead to a cleaner implementation for the layers as well.
Oh, and a first look at the character creation menu
Last edited by DWRL on Mon Mar 09, 2020 10:57 pm, edited 1 time in total.
That's a beautiful menu!
The syntax of HamsterSpeak is highly unusual; unfortunately you probably won't find any other language supported by your code editor of choice that is whitespace-insensitive. One solution is to write all names in your scripts in camelCase, like other languages. I wrote a HS mode for emacs myself. Syntax highlighting is very nice to have. There's a language definition for Notepad++ available, and I think some people in Discord also created their own for... VSCode? Sublime Text? I can't remember. Or you can use Hamster Whisper, which has a help key to show the documentation for the command under the cursor; very helpful.
Ah! Making the walkabout sprite (body sprite) invisible is a clever workaround.
I want to switch to the new sprite animation system this month, in time for the next release. That will then mean that I can expose the ability to add more frames to spritesets (it's already implemented but disabled, because the builtin animations wouldn't use the new frames, and thescript commands haven't been updated yet).
In fact, I also wanted to have builtin support for automatically changing the frames of walkabout overlay sprites, so that they match the direction/frame of the base sprite. It's a common thing to want to do. But that will take me longer; it might still be a long time away.
The syntax of HamsterSpeak is highly unusual; unfortunately you probably won't find any other language supported by your code editor of choice that is whitespace-insensitive. One solution is to write all names in your scripts in camelCase, like other languages. I wrote a HS mode for emacs myself. Syntax highlighting is very nice to have. There's a language definition for Notepad++ available, and I think some people in Discord also created their own for... VSCode? Sublime Text? I can't remember. Or you can use Hamster Whisper, which has a help key to show the documentation for the command under the cursor; very helpful.
Ah! Making the walkabout sprite (body sprite) invisible is a clever workaround.
I want to switch to the new sprite animation system this month, in time for the next release. That will then mean that I can expose the ability to add more frames to spritesets (it's already implemented but disabled, because the builtin animations wouldn't use the new frames, and thescript commands haven't been updated yet).
In fact, I also wanted to have builtin support for automatically changing the frames of walkabout overlay sprites, so that they match the direction/frame of the base sprite. It's a common thing to want to do. But that will take me longer; it might still be a long time away.
Last edited by TMC on Tue Mar 10, 2020 3:35 pm, edited 1 time in total.
Here is the script as I currently have it, in case anybody might find it useful, or find something to improve
It needs the walkabout for the hero to be set to one of the same size as wished, but completely transparent.
The actual visible walkabout is 'PlayerBase', to avoid the visual inconsistency by the 1 tick delay mentioned by TMC.
The numbers in PlayerSettings directly translate to walkabout numbers or palette numbers.
Feel free to criticize, maybe I did something incredibly stupid here and haven't realized yet
It needs the walkabout for the hero to be set to one of the same size as wished, but completely transparent.
The actual visible walkabout is 'PlayerBase', to avoid the visual inconsistency by the 1 tick delay mentioned by TMC.
The numbers in PlayerSettings directly translate to walkabout numbers or palette numbers.
Feel free to criticize, maybe I did something incredibly stupid here and haven't realized yet
Code: Select all
define constant(1, timer: redrawDoll)
global variable, begin
# Gender, 1; Hairstyle, 23, Haircolor: 4, Skintone: 5, Clothes: 67
1, PlayerSettings
# 0: Reset needed, 1: No reset needed
2, ResetPlayerDoll
# PlayerWalk, layerBase, PlayerHair, PlayerCloth
3, PlayerBase
4, PlayerHair
# Not implemented yet
#5, PlayerCloth
end
plotscript, Update Doll, begin
if(ResetPlayerDoll == 0) then, begin
# TEMP, need to tie in to Character Creation
if(PlayerSettings == 0) then, begin
PlayerSettings := 020841399
end
# pGender:number of walkabout to be used as a base
# pHairstyle: number of walkabout to be used as a hair.
# pHaircolor: number of palette used for hair
# pSkintone: number of palette used for skin
# pClothes: number of palette used for clothes
variable(pGender, pHairstyle, pHaircolor, pSkintone, pClothes, pVisCloth)
pGender := PlayerSettings / 100000000
pHairstyle := (PlayerSettings, mod, 100000000) / 10000000
pHaircolor := (PlayerSettings, mod, 10000000) / 100000
pSkintone := (PlayerSettings, mod, 100000) / 10000
pClothes := (PlayerSettings, mod, 10000) / 100
# Not implemented yet
#pVisCloth := (PlayerSettings, mod, 100)
if(PlayerBase <> 0) then (free slice(PlayerBase))
if(PlayerHair <> 0) then (free slice(PlayerHair))
# (+ 7 if female, offset to female hair graphics (i.e. walkabouts 2-8 for males, 9-15 for females)
if(pGender == 1) then (pHairstyle := pHairstyle + 7)
PlayerBase := load walkabout sprite(pGender, pSkintone)
PlayerHair := load walkabout sprite(pHairstyle, pHaircolor)
set parent(PlayerBase, getHeroSprite(me))
set parent(PlayerHair, getHeroSprite(me))
ResetPlayerDoll := 1
end
else if(ResetPlayerDoll == 1) then, begin
variable(frame)
frame := get sprite frame (lookup slice(sl:walkabout sprite component, get hero slice(me)))
set sprite frame (PlayerBase, frame)
set sprite frame (PlayerHair, frame)
end
set timer(timer:redrawDoll, 0, 1, @Update Doll) # Run this script again next next
end
Last edited by DWRL on Sat Jun 13, 2020 12:57 pm, edited 3 times in total.
The power of MATH! Beautiful! Kids, you have to pay attention in school, if you want to compress the informations in one variable instead of six.
Although it only works because the OHR doesn't use floating point numbers... else there would be problems at rounding, I think. Code 020341399 will result in hairstyle #20 as intended, but 020841399 would result in 20,8 which would be #21, if rounded.
Although it only works because the OHR doesn't use floating point numbers... else there would be problems at rounding, I think. Code 020341399 will result in hairstyle #20 as intended, but 020841399 would result in 20,8 which would be #21, if rounded.
By coincidence (I think) Prifurin posted a script a couple days ago to store a date and time like 202006041859 in a single value, but ran into the problem that HamsterSpeak values are capped at 2.147 billion. So you only get 9 decimal digits, and need to use two variables for that.
Also worth mentioning that in HS you can put spaces in numbers, like "PlayerSettings := 0 20 84 13 99 ". Most useful for writing 100 000 000 instead of 100000000.
BTW, you can replace with "get hero sprite(me)"
Also worth mentioning that in HS you can put spaces in numbers, like "PlayerSettings := 0 20 84 13 99 ". Most useful for writing 100 000 000 instead of 100000000.
BTW, you can replace
Code: Select all
lookup slice(sl:walkabout sprite component, get hero slice(me))
It would be possible to store those values in a string instead of a variable. If you had 0$="0 20 84 13 99" (which would likely be created by using "append number(0, value)" for each player settings value in most cases) it could be as long as you want. Reading it would be complicated, though, since there's no arrays or string split function.
My pronouns are they/them
Ps. I love my wife
Ps. I love my wife
If we would cut the year number to the last two digits (so "19" instead of "2019"), it is possible to calculate everything back to seconds and currently have a 9-digit-number as a result. That would work until 2067, then the variable would grow farther than the 2,147 billion limit. If we declare 2020 as year 0, the terrible end can be postponed about 20 years to 2087. However if we could abandon the tiny seconds, we would be well set for the future.TMC wrote:By coincidence (I think) Prifurin posted a script a couple days ago to store a date and time like 202006041859 in a single value, but ran into the problem that HamsterSpeak values are capped at 2.147 billion. So you only get 9 decimal digits, and need to use two variables for that.
How was it with strings, that can be stored after the game was quit? They needed to be exported to a file, right? Someone did this somewhere...kylekrack wrote:It would be possible to store those values in a string instead of a variable. If you had 0$="0 20 84 13 99" (which would likely be created by using "append number(0, value)" for each player settings value in most cases) it could be as long as you want. Reading it would be complicated, though, since there's no arrays or string split function.
I guess in that case we'd need (and might have) a floor operator.Bird wrote:(...)Although it only works because the OHR doesn't use floating point numbers... else there would be problems at rounding, I think.(...)
But think of those video game archaeologists in the year 100000 and beyond. What will they do?Bird wrote:(...)we would be well set for the future.
Sometimes ideas are just in the air. I was just dumbfounded by the lineTMC wrote:By coincidence (I think) Prifurin posted a script a couple days ago to store a date and time like 202006041859 in a single value, but ran into the problem that HamsterSpeak values are capped at 2.147 billion. So you only get 9 decimal digits, and need to use two variables for that.
"extradata := current frame + current spriteset * 10 + base spriteset * 100 000"
When I finally figured it out, it was quite clever. I am still far too used to lists and dictionaries, so it would have taken quite some time for me to realign my thinking into something like that.
Far better, thanksTMC wrote:Also worth mentioning that in HS you can put spaces in numbers, like "PlayerSettings := 0 20 84 13 99 ". Most useful for writing 100 000 000 instead of 100000000.
BTW, you can replacewith "get hero sprite(me)"Code: Select all
lookup slice(sl:walkabout sprite component, get hero slice(me))
-
Update,
I had problems with loading save states, I guess my grasp of what the OHR does and doesn't isn't as firm as it could be.
(Seems the globals stored the slice handles just fine, only the slices themselves were quite nonexistent after saving and loading the game... XD)
Now the script is two-tiered, one does put 'Setup Doll' as the autorun script for the map, and the magic happens ;)
(Not cleaned up, straight out of the editor, so just excuse the many hashes. My editor makes them red, so it is easier navigating the script file.)
Code: Select all
# SCRIPT
# Show the Command menu and change selection
##########################################
plotscript, Setup Doll, begin
# TEMP, need to tie in to Character Creation
if(PlayerSettings == 0) then, begin
PlayerSettings := 0 2 08 4 13 99
end
variable(pGender, pHairstyle, pHaircolor, pSkintone, pClothes, pVisCloth)
pGender := PlayerSettings / 100000000
pHairstyle := (PlayerSettings, mod, 100000000) / 10000000
pHaircolor := (PlayerSettings, mod, 10000000) / 100000
pSkintone := (PlayerSettings, mod, 100000) / 10000
pClothes := (PlayerSettings, mod, 10000) / 100
# Not implemented yet
#pVisCloth := (PlayerSettings, mod, 100)
pHairstyle := pHairstyle + 2
if(pGender == 1) then (pHairstyle := pHairstyle + 7)
PlayerBase := load walkabout sprite(pGender, pSkintone)
PlayerHair := load walkabout sprite(pHairstyle, pHaircolor)
set parent(PlayerBase, getHeroSprite(me))
set parent(PlayerHair, getHeroSprite(me))
ResetPlayerDoll := 1
Update Doll
end
##########################################
# SCRIPT
# Show the Command menu and change selection
##########################################
plotscript, Update Doll, begin
if(ResetPlayerDoll == 0) then, begin
Setup Doll
end
else, begin
variable(frame)
frame := get sprite frame (getHeroSprite(me))
set sprite frame (PlayerBase, frame)
set sprite frame (PlayerHair, frame)
end
set timer(timer:redrawDoll, 0, 1, @Update Doll) # Run this script again next next
end
##########################################
- Spoonweaver
- Liquid Metal King Slime
- Posts: 6466
- Joined: Mon Dec 08, 2008 7:07 am
- Contact:
Why does your script convert indvidual choices into 1 variable and then convert them back again?
why not just have the editor or equip screen set pGender pHairstyle pHaircolor pSkintone and pClothes seperately and leave them seperate in stead of smashing them into PlayerSettings?
Am I missing something?
why not just have the editor or equip screen set pGender pHairstyle pHaircolor pSkintone and pClothes seperately and leave them seperate in stead of smashing them into PlayerSettings?
Am I missing something?
This way it can all be stored in one global variable.Spoonweaver wrote:Why does your script convert indvidual choices into 1 variable and then convert them back again?
why not just have the editor or equip screen set pGender pHairstyle pHaircolor pSkintone and pClothes seperately and leave them seperate in stead of smashing them into PlayerSettings?
Am I missing something?