Santa Claus screen mate update

I’ve come to realize that the batch header method I’ve been using for Powershell scripts isn’t as fool proof as I had hoped. When I sent the Santa Claus script to my mom she wasn’t able to run the batch file, it kept giving an error that a type declaration was undefined. I still haven’t quite figured that one out, but I did try compiling the script using PS2EXE and it ran on her computer without issue.

In light of that, I’m making a quick update here. I’ve changed the script a slight bit, and I’m providing a compiled exe as well.

Zip file contents:

  • Santa.ps1
  • Santa.ico
  • Santa.exe
  • Compile-Santa.ps1
Posted in Coding | Tagged , , , | Leave a comment

Merry Christmas; Santa Claus screen mate

If you’re old like me, you might remember screen mates or desktop pets. These were programs you’d run on your computer that put little interactive creatures on your screen. The first one I ever encountered was eSheep, back in the Windows 95/98 days. You can find a recreation on the Microsoft Store, and also on the author’s github page.

Well, I made a Santa Claus one for fun.

Santa.bat.txt (remove the .txt extension). Middle-click on Santa to close the script, left-click to pick him up, and right-click for a few catch phrases.


START POWERSHELL -COMMAND "Get-Content """%~f0""" | Select -Skip 1 | Out-String | Invoke-Expression" & EXIT /B

Add-Type -AssemblyName System.Windows.Forms, System.Speech
Add-Type -namespace Win32 -name UI -MemberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
[void][Win32.UI]::ShowWindowAsync((Get-Process -PID $PID).MainWindowHandle, 0) # Hide console window

$ImageStream = [System.IO.MemoryStream][System.Convert]::FromBase64String('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')

class Sprite {
    [Windows.Forms.Form]$Form
    [Windows.Forms.PictureBox]$PictureBox
    [System.Drawing.Image]$Image
    [System.Drawing.Size]$CellSize
    [System.Drawing.Size]$SheetSize
    [Hashtable]$Animations

    Sprite([System.Drawing.Image]$Image, [System.Drawing.Size]$Size) {
        $this.Form = New-Object Windows.Forms.Form -Property @{
            MinimumSize     = $Size
            ClientSize      = $Size
            TopMost         = $True
            Location        = '0,0'
            StartPosition   = 0
            FormBorderStyle = 0
            ShowInTaskbar = $False
        }
        $this.Form.TransparencyKey = $this.Form.BackColor

        $this.Image = $Image
        $this.CellSize = $Size
        $this.SheetSize = $Image.Size
        $this.PictureBox = New-Object Windows.Forms.PictureBox -Property @{
            Size = $Image.Size
            Location = '0,0'
            Image = $Image
        }
        $this.Form.Controls.Add($this.PictureBox)
    }
    Cell($Index) {
        $Width = $this.CellSize.Width
        $Height = $this.CellSize.Height

        $IndexMultiplier = $Index * $Width

        $X = $IndexMultiplier % $this.SheetSize.Width
        $YIndex = [int][Math]::Floor($IndexMultiplier / $this.SheetSize.Width)
        $Y = $YIndex * $Height
        $this.PictureBox.Location = "-$X,-$Y"
    }
}

Function ToolTip-Popup {
    param ($Text, $Control, $X, $Y, $Time, $IsBalloon = $True)
    $ToolTip = New-Object Windows.Forms.ToolTip -Property @{ IsBalloon = $IsBalloon }
    $ToolTip.SetToolTip($Control, ' ')
    $ToolTip.Show($Text, $Control, $X, $Y, $Time)
    $ToolTip.add_popup({ $this.dispose() })
}

$Speaker = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$Speaker.Rate = -6

$SpriteSize = '21,20'
$SpriteSize = '42,40'

$LoadImage = [Drawing.Image]::FromStream($ImageStream)
$Santa = New-Object Sprite($LoadImage, $SpriteSize)
$Santa.PictureBox.add_Mousedown({
    If ($_.Button -eq 'Left') {
        $global:Holding = $_.Location
        $Santa.cell(20)
    }
})
$Santa.PictureBox.add_Mousemove({
    If ($global:Holding) {
        $Mouse = [System.Windows.Forms.Cursor]::Position
        $Santa.Form.SetDesktopLocation(
            ($Mouse.X - $Santa.Form.Width / 2),
            ($Mouse.Y - $Santa.Form.Height / 2)
        )
    }
})
$Santa.PictureBox.add_Mouseup({
    $global:Holding = $null
})
$Santa.PictureBox.Add_Click({
    If ($_.Button -eq 'Middle') {
        $Santa.Form.Close()
        Stop-Process $PID
    }
    If ($_.Button -eq 'Right') {
        $ClickSequence = Get-Random -Max 3
        Switch ($ClickSequence) {
            0 {
                $global:AnimState = 'laugh'
                $global:Sequence = $Santa.Animations['laugh']
                $global:AnimChangeCountdown = 6
                $Message = 'Ho ho ho!'
            }
            1 {
                $global:AnimState = 'wave'
                $global:Sequence = $Santa.Animations['wave']
                $global:AnimChangeCountdown = 10
                $Message = 'Merry Christmas!'
            }
            2 {
                $global:AnimState = 'wave'
                $global:Sequence = $Santa.Animations['wave']
                $global:AnimChangeCountdown = 10
                $Message = 'Happy New Year!'
            }
        }
        ToolTip-Popup $Message $Santa.Form 21 15 ($global:AnimChangeCountdown * 200)
        $Speaker.SpeakAsync($Message)
    }
})

$Santa.Animations = @{
    stand_down  = 0
    stand_up    = 1
    stand_left  = 2
    stand_right = 3
    walk_down   = 0,4,0,8
    walk_up     = 1,5,1,9
    walk_left   = 2,6,2,10
    walk_right  = 3,7,3,11
    laugh       = 16,17
    wave        = 18,19
}

# 7  0  1
#  \ | /
# 6 -+- 2
#  / | \
# 5  4  3
$WalkAnimationMap = @('walk_up', 'walk_right', 'walk_right', 'walk_right', 'walk_down', 'walk_left', 'walk_left', 'walk_left')
$StandAnimationMap = @('stand_up', 'stand_right', 'stand_right', 'stand_right', 'stand_down', 'stand_left', 'stand_left', 'stand_left')
$SpriteDirection = Get-Random -Max 8

$AnimState = 'walk'
$AnimChangeCountdown = Get-Random -Min 10 -Max 20
$Sequence = $Santa.Animations[$WalkAnimationMap[$SpriteDirection]]

$AnimationTimer = New-Object Windows.Forms.Timer -Property @{
    Interval = 20
    Add_Tick = {
        If ($global:Holding) { Return }

        $global:TICKS += 20

        If ($TICKS % 200 -eq 0) {
            $global:AnimFrame++
            $global:AnimChangeCountdown--

            If ($AnimChangeCountdown -le 0) {
                Switch -regex ($AnimState) {
                    'walk' {
                        $global:AnimState = 'stand'
                        $global:Sequence = $Santa.Animations[$StandAnimationMap[$SpriteDirection]]
                        $global:AnimChangeCountdown = Get-Random -Min 5 -Max 10
                    }
                    default {
                        $global:AnimState = 'walk'
                        $global:SpriteDirection = Get-Random -Max 8
                        $global:Sequence = $Santa.Animations[$WalkAnimationMap[$SpriteDirection]]
                        $global:AnimChangeCountdown = Get-Random -Min 10 -Max 20
                    }
                }
            }
        }
        $Santa.cell(($Sequence[($global:AnimFrame) % $Sequence.count]))

        Switch ($SpriteDirection) {
            0 { $MoveY = -1 }
            1 { $MoveX = 1; $MoveY = -1 }
            2 { $MoveX = 1 }
            3 { $MoveX = 1; $MoveY = 1 }
            4 { $MoveY = 1 }
            5 { $MoveX = -1; $MoveY = 1 }
            6 { $MoveX = -1 }
            7 { $MoveX = -1; $MoveY = -1 }
            default { $MoveX = 0; $MoveY = 0 }
        }

        $SpriteX = $Santa.Form.Location.X
        $SpriteY = $Santa.Form.Location.Y

        If ($AnimState -eq 'walk') {
            $SpriteX += $MoveX * 2
            $SpriteY += $MoveY * 2
        }
        $Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen

        $Edge = @{
            left = $Screen.Left - $Santa.Form.Size.Width
            right = $Screen.Right
            top = $Screen.Top - $Santa.Form.Size.Height
            bottom = $Screen.Bottom
        }

        If ($SpriteX -gt $Edge.right)  { $SpriteX = $Edge.left }
        If ($SpriteX -lt $Edge.left)   { $SpriteX = $Edge.right }
        If ($SpriteY -gt $Edge.bottom) { $SpriteY = $Edge.top }
        If ($SpriteY -lt $Edge.top)    { $SpriteY = $Edge.bottom }

        $Santa.Form.Location = @{
            X = $SpriteX
            Y = $SpriteY
        }
    }
}

$Santa.Form.add_Load({ $AnimationTimer.Start() })
$Santa.Form.ShowDialog()

Over the years I’ve made a few little similar applications/scripts. I made some with Javascript that made little wandering video game characters on a webpage. I made one in AutoIt that had a baby Metroid that would follow your cursor. I never got as interactive as the original eSheep though, which could detect window edges and interact with them.

Anyway, over the past several days I’ve been tinkering with Powershell, and I made a little Santa Claus. I created a sprite sheet from a Bomberman sprite that I obtained from The Spriters Resource. I then converted the image into a base64 string to include directly in the script (that’s the extremely long string in the $ImageStream variable). I added on the Batch Powershell launcher snippet to the top of the script and saved it as .bat.

As usual, this started as experimenting with different Powershell functions and commands. I learned how to create a custom class with methods, how to create a window/form with transparency, and how to load an image via base64 string.

Posted in Coding | Tagged , , , , , | Leave a comment

Batch script admin check

Have a batch script that requires administrator elevation? Put this line at the top of your script.


@FLTMC >NUL 2>&1 || (POWERSHELL -WINDOWSTYLE HIDDEN START-PROCESS """%~f0""" -VERB RUNAS & EXIT /B)
Posted in Coding | Tagged , | Leave a comment

Batch Powershell launcher

Windows comes out of the box with Powershell scripts disabled, and asking every user to change their execution policy to allow running them is a hassle. To get around that, I wrote this little batch script snippet that I just prefix to all my Powershell scripts.


START POWERSHELL -COMMAND "(Get-Content """%~f0""").Where({$_ -eq '#POWERSHELL#'},'SkipUntil') | Out-String | Invoke-Expression" & EXIT /B
#POWERSHELL#

#Example PS script...
Get-Command | Out-GridView

Pause

Then I save my file as a .bat. Now I can double click the batch file, which launches in CMD, then starts Powershell, loads the contents of the calling script file, skips to the line that says #POWERSHELL# and passes the rest of the content through to Powershell, and exits the batch file.

Posted in Coding | Tagged , , | Leave a comment

Device Wake Config tool

Have you ever had to peruse your Device Manager trying to figure out which device is waking your computer from sleep? Isn’t it annoying how you have to open each device one by one, checking the Power Management tab and look for that checkbox?

Well, I found it annoying. So I wrote a little Powershell script that gives me a GUI with a list of all the wakeable devices so I can easily toggle off/on whatever I want.


Add-Type -namespace Win32 -name UI -MemberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
[void][Win32.UI]::ShowWindowAsync((Get-Process -PID $PID).MainWindowHandle, 0) # Hide console window

Add-Type -AssemblyName PresentationFramework, System.Drawing, System.Windows.Forms
[Windows.Forms.Application]::EnableVisualStyles()

$ItemCheck_Handler = {
    $Form_Main.Cursor = "WaitCursor"
    $SelItem = $Lv_DeviceList.Items[$_.Index]
    If ($_.NewValue -eq 'Checked') {
        Start-Process powercfg -ArgumentList "/deviceenablewake ""$($SelItem.Text)""" -Wait -WindowStyle Hidden
    } Else {
        Start-Process powercfg -ArgumentList "/devicedisablewake ""$($SelItem.Text)""" -Wait -WindowStyle Hidden
    }
    UpdateWakeArms
    $Form_Main.Cursor = "Default"
}

$WakeableDevices = @(powercfg /devicequery wake_programmable) | Sort-Object

$Form_Main = New-Object Windows.Forms.Form -Property @{
    Text = 'Device Wake Config'
    ClientSize = '300,400'
    MaximizeBox = $False
    MinimizeBox = $False
    SizeGripStyle = 'Show'
}

$Form_Main.Controls.Add(($Lv_DeviceList = New-Object Windows.Forms.ListView -Property @{
    Bounds = "0,0,300,400"
    Anchor = 'Top,Left,Bottom,Right'
    View = 'Details'
    FullRowSelect = $True
    Multiselect = $False
    HideSelection = $False
    HeaderStyle = 'Nonclickable'
    CheckBoxes = $True
   
    add_ItemCheck = $ItemCheck_Handler
}))
[void]$Lv_DeviceList.Columns.Add('Device Name', -1)

Foreach ($Device in $WakeableDevices) {
    If ($Device.trim() -ne "") {
        $Item = $Lv_DeviceList.Items.Add($Device)
    }
}
$Lv_DeviceList.AutoResizeColumns(2)

Function UpdateWakeArms() {
    $WakeArmed = @(powercfg /devicequery wake_armed)
    $Lv_DeviceList.remove_ItemCheck($ItemCheck_Handler)
    Foreach ($Item in $Lv_DeviceList.Items) {
        $Checked = $WakeArmed.Contains($Item.Text)
        If ($Item.Checked -ne $Checked) {
            $Item.Checked = $Checked
        }
    }
    $Lv_DeviceList.add_ItemCheck($ItemCheck_Handler)
}
UpdateWakeArms

[void]$Form_Main.ShowDialog()
Posted in Coding | Tagged , | Leave a comment

TUNIC Glyph Translator

TUNIC is a great little game I’ve been waiting a long time for. Throughout the game and manual there is a seemingly incomprehensible language used. It’s not a simple cypher and instead works on a vowel/consonant combination. I did not figure this out at all, and all credit goes to Steam user oposdeo who provided his translation guide in this thread.

To explain a bit, a cypher is a simple 1-to-1 change, so like a = 1, b = 2. Or for example “hello world” could be “!@##$ %$^#&” (where ! = h, @ = e, etc), each unique letter is represented by one unique character. When most games have a translatable language, they use this system (think the Al Bhed language in FF10). They’re relatively easy to figure out once you have enough samples to work on and can figure out a few key words (like “the” or “and”).

In this game’s language the individual glyphs are a combination vowel/consonant sound. Instead of just 5 vowels covering all the different vowel sounds (think how “O” works in owe, too, now, boy, nor), each vowel sound gets it’s own symbol, and instead of the other 21 letters representing a mixed bag of consonants (note how J and G, C and K, are sometimes the same, etc) you have explicit symbols for each sound. For example with consonants, “ch” and “sh” are their own symbols, whereas “ph” and “f”, or a hard “c” and “k” are the same.

Anyway, I’m sure I’m doing a terrible job of explaining it, for better details refer to oposdeo‘s guide. Long story short, I used his guide to create a little web tool to do the translations for you: TUNIC Glyph Translator. Works pretty well in mobile if I do say so myself.

Posted in Coding | Tagged , | Leave a comment

Something broke the site

Something broke the site for a bit. Not that I’d ever know if I hadn’t received an email about it. Obviously I’m not active here a lot. Kinda wonder why I even keep paying for this thing.

Anyway, for some reason the activated theme wasn’t loading and it was causing the whole site to have a “critical error”. I had to go edit the database directly and change the WordPress theme to something that worked. Annoying. Fixed now though.

I changed the background on the page a bit, figured out some neat CSS trick while I was messing around and thought I’d give it a try.

That’s all.

Posted in General | Leave a comment

HTML+JS Wallpaper Animations

So forever ago I made this image I called “Timeish” because it kind of reminded me of a clock face. A few months back I was playing around with the Photoshop file and found out I could create simple animations, and so I created this video. Before uploading to YouTube it actually looked half decent, but it was admittedly fairly large for 10 seconds of a spinning blue picture. Anyway, I started toying around with Javascript and HTML and eventually cooked up this thing instead.

I also have animations for two other images. One is from the image “Tunnelling“, and the animation can be found here. The other one I didn’t actually put up on deviantArt but I just called it “Spinner“.

There are a bunch of different things you can do to affect the animation:

  • Scroll the mouse wheel up and down to increase/decrease all layers’
    rotation speed.
  • Space bar, or middle click, to randomize rotation speed.
  • Backspace, or left click, to set rotation speeds to default.
  • Escape to slowdown and stop the rotations.
  • Q to immediately stop and reset all layers to a 0 degree rotation.
  • Number keys (0-9, each number affects a different layer):
    • #: Increase rotation speed by 0.1.
    • Ctrl+#: Increase rotation speed by 0.01.
    • Shift+#: Decrease rotation speed by 0.1.
    • Shift+Ctrl+#: (You guessed it) Decrease by 0.01.

Posted in Coding | Tagged , , | Leave a comment

FireKey2 (2.1.0.7)

 Last version posted was 2.1.0.4.

Download | View Source | Download Source

There have been a few minor updates:

  • 2.1.0.7
    • Rearranged Options menu
  • 2.1.0.6
    • AutoIt line now has a full edit box (merged to single line on execution).
    • Window size/pos is now remembered
    • Listview is focused after key add/edit
    • Default sort keys in order of creation/update
  • 2.1.0.5
    • Changes to _FileGetIcon, added new icons for “AutoIt commands”

 

Posted in Coding | Tagged , , , , | Leave a comment

#include _FileGetIcon.au3

A function that figures out what icon should be associated with a given file/path.
Works on customized folders, shortcuts, internet shortcuts (.url), and protocols (http, ftp, etc).

Download | View Source

Posted in Coding | Tagged , , | Leave a comment