Post new topic    
Page 1, 2  »
Red Slime
Send private message
Layered Walkabout / Visible Equippment / Could use a hand 
 PostSat Mar 07, 2020 3:41 pm
Send private message Reply with quote
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 Zombie

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?
Liquid Metal Slime
Send private message
 
 PostSat Mar 07, 2020 5:22 pm
Send private message Reply with quote
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.
Ps. I love my wife
Slime Knight
Send private message
 
 PostMon Mar 09, 2020 2:13 pm
Send private message Reply with quote
Oh! Witch2.rpg used it beautifully. Have a look.
Metal King Slime
Send private message
 
 PostMon Mar 09, 2020 4:33 pm
Send private message Reply with quote
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:

Code:
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


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.
Red Slime
Send private message
 
 PostMon Mar 09, 2020 9:11 pm
Send private message Reply with quote
@kylekrack: Thanks, you did kickstart me here Grin
@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 V

(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).

Quote:
The three-frame walking script is going to be obsolete very soon.

Might I ask if we talk about a palatable timeframe here, say two to three months or something like that?
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 Smile

Metal King Slime
Send private message
 
 PostTue Mar 10, 2020 3:34 pm
Send private message Reply with quote
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.
Red Slime
Send private message
 
 PostSat Jun 13, 2020 12:52 pm
Send private message Reply with quote
Here is the script as I currently have it, in case anybody might find it useful, or find something to improve Smile

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 V

Code:

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
Slime Knight
Send private message
 
 PostSat Jun 13, 2020 1:57 pm
Send private message Reply with quote
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.
Red Slime
Send private message
 
 PostSat Jun 13, 2020 2:42 pm
Send private message Reply with quote
To be honest, it wouldn't have occured to me if I hadn't seen it in the three-frame walking script Angel
Metal King Slime
Send private message
 
 PostSun Jun 14, 2020 2:02 am
Send private message Reply with quote
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
Code:
lookup slice(sl:walkabout sprite component, get hero slice(me))
with "get hero sprite(me)"
Liquid Metal Slime
Send private message
 
 PostSun Jun 14, 2020 3:35 am
Send private message Reply with quote
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.
Ps. I love my wife
Slime Knight
Send private message
 
 PostSun Jun 14, 2020 8:40 am
Send private message Reply with quote
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.

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.
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.

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...
Red Slime
Send private message
 
 PostSun Jun 14, 2020 9:46 am
Send private message Reply with quote
Bird wrote:
(...)Although it only works because the OHR doesn't use floating point numbers... else there would be problems at rounding, I think.(...)

I guess in that case we'd need (and might have) a floor operator.

Bird wrote:
(...)we would be well set for the future.

But think of those video game archaeologists in the year 100000 and beyond. What will they do? Devil

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.

Sometimes ideas are just in the air. I was just dumbfounded by the line
"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.

TMC 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 replace
Code:
lookup slice(sl:walkabout sprite component, get hero slice(me))
with "get hero sprite(me)"

Far better, thanks Smile


-
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:
# 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
   ##########################################
Liquid Metal King Slime
Send private message
 
 PostSun Jun 14, 2020 11:19 am
Send private message Reply with quote
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?
Red Slime
Send private message
 
 PostSun Jun 14, 2020 6:15 pm
Send private message Reply with quote
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?

This way it can all be stored in one global variable.
Display posts from previous:
Page 1, 2  »