Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 7 8 [9]

Author Topic: Extended item viewscreen, custom item descriptions and ASCII art 5.1 beta  (Read 29276 times)

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist

Super-Necro.

Did anything ever happen with this? Item descriptions are kinda in dfhack now, but no fancy popups with ascii art. ^^
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

I don't see the point of ASCII art when you can just include an image tbh.

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist

I don't see the point of ASCII art when you can just include an image tbh.
In that case I would include an image.

How?
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

Haha shit. Okay. Challenge accepted.

Here's about two hours' work:

Code: [Select]
--Written by Putnam

local widgets=require('gui.widgets')

local gui=require('gui')

local dlg=require('gui.dialogs')

local GraphicalButton=defclass(GraphicalButton,widgets.Widget)

GraphicalButton.ATTRS={
    on_click = DEFAULT_NIL,
    on_rclick = DEFAULT_NIL,
    graphic = DEFAULT_NIL, --refers to the name of a tilepage
    label = DEFAULT_NIL
}

function GraphicalButton:preUpdateLayout()
    self.frame=self.frame or {}
    if not self.page then self.frame.w=0 self.frame.h=0 return end
    self.frame.w=self.page.page_dim_x
    self.frame.h=self.page.page_dim_y
end

function GraphicalButton:onRenderBody(dc)
    if not self.page then return end
    for k,v in ipairs(self.page.texpos) do
        dc:seek(k%self.frame.w,math.floor(k/self.frame.w)):tile(32,v)
    end
end

function GraphicalButton:onInput(keys)
    if keys._MOUSE_L_DOWN and self:getMousePos() and self.on_click then
        self.on_click()
    end
    if keys._MOUSE_R_DOWN and self:getMousePos() and self.on_rclick then
        self.on_rclick()
    end
end

function GraphicalButton:init(args)
    if not self.graphic then return end
    for k,v in ipairs(df.global.texture.page) do
        if v.token==self.graphic then self.page=v return end
    end
    error('No tilepage found: '..self.graphic)
end

local GraphicsBox=defclass(GraphicsBox,dlg.MessageBox)

GraphicsBox.ATTRS{
    frame_style = gui.GREY_LINE_FRAME,
    frame_inset = 1,
    -- new attrs
    on_accept = DEFAULT_NIL,
    on_cancel = DEFAULT_NIL,
    on_close = DEFAULT_NIL,
}

function GraphicsBox:onRender()
    self.super.onRender(self)
    self:renderSubviews()
end

function GraphicsBox:getWantedFrameSize()
    local button=self.subviews.image
    if not button.frame then return end
    return button.frame.w,button.frame.h
end

function GraphicsBox:init(info)
    self:addviews{
        GraphicalButton{
            view_id = 'image',
            graphic = info.graphic,
            frame = {l=0,t=0}
        }
    }
end

function showImage(title,image,on_close)
    GraphicsBox{
        frame_title=title,
        graphic=image,
        on_close=on_close
    }:show()
end

local lastFrame=df.global.enabler.frame_last

dfhack.onStateChange.itemPictures=function(code)
    if code==SC_VIEWSCREEN_CHANGED and dfhack.isWorldLoaded() then
        if dfhack.gui.getCurViewscreen()._type==df.viewscreen_textviewerst and df.global.enabler.frame_last-lastFrame>df.global.enabler.gfps*20 then
            lastFrame=df.global.enabler.frame_last
            local parent=dfhack.gui.getCurViewscreen().parent
            if parent._type==df.viewscreen_unitst or parent._type==df.viewscreen_dungeon_monsterstatusst then
                local unit=parent.unit
                local imageExists=false
                local creature=df.creature_raw.find(unit)
                for k,v in ipairs(df.global.texture.page) do
                    if v.token==creature.creature_id..'_TEXT_IMAGE' then
                        imageExists=true
                        break
                    end
                end
                if imageExists then
                    showImage("Image",creature.creature_id..'_TEXT_IMAGE')
                end
            elseif parent._type==df.viewscreen_itemst then
                local item=parent.item
                local imageExists=false
                local itemName=''
                local subtype=dfhack.items.getSubtypeDef(item:getType(),item:getSubtype())
                if subtype then
                    itemName=df.item_type[item:getType()]..'/'..subtype.id --gotta be a slash methinks
                else
                    itemName=df.item_type[item:getType()]
                end
                for k,v in ipairs(df.global.texture.page) do
                    if v.token==itemName..'_TEXT_IMAGE' then
                        imageExists=true
                        break
                    end
                end
                if imageExists then
                    showImage("Image",itemName..'_TEXT_IMAGE')
                end
            end
        end
    end
end

That will allow you to add any image to any item or unit's description. It will appear apropos of nothing because I didn't take that much time on it (and also because that was the original script's behavior, though I think that's weird) the instant you go into the text viewer and look like this:



In order to load it in, you need to do something like this (using Fortbent's as an example):

Code: [Select]
graphics_putnam_godtier

[OBJECT:GRAPHICS]

[TILE_PAGE:PUTNAM_GODTIER]
[FILE:putnam/godtier.png]
[TILE_DIM:64:64]
[PAGE_DIM:12:1]

[TILE_PAGE:CHAIR_TEXT_IMAGE]
[FILE:putnam/spender.PNG]
[TILE_DIM:16:16]
[PAGE_DIM:7:12]


[CREATURE_GRAPHICS:GRAPHICS_CREATURE_FORTBENT]
 [DEFAULT:PUTNAM_GODTIER:0:0:ADD_COLOR:DEFAULT]
 [MINER:CHAIR_TEXT_IMAGE:0:0:ADD_COLOR:DEFAULT]

GRAPHICS_CREATURE_FORTBENT is just this:

Code: [Select]
[CREATURE:GRAPHICS_CREATURE_FORTBENT]
[ARENA_RESTRICTED]
[NAME:none:none:none]
[DESCRIPTION:none:none:none]
[CASTE_NAME:none:none:none]
[DOES_NOT_EXIST]

As long as a creature--ANY creature--loads a tileset, it can be used in graphics this way.

Note the name: CHAIR_TEXT_IMAGE. For any subtypeless items (such as chairs, natch), the format is name_TEXT_IMAGE. Similarly, for creatures, the format is creature_id_TEXT_IMAGE. For subtyped items (weapons etc.), it's type/subtype_TEXT_IMAGE, eg. WEAPON/ITEM_WEAPON_WHIP_TEXT_IMAGE.

Oh, I need to go more in-depth about this:

Code: [Select]
[TILE_PAGE:CHAIR_TEXT_IMAGE]
[FILE:putnam/spender.PNG]
[TILE_DIM:16:16]
[PAGE_DIM:7:12]

Note the TILE_DIM and PAGE_DIM. PAGE_DIM determines how many tiles wide and tall the image will be in-game. TILE_DIM just determines how big the tiles will be. You always want that to be in the same ratio as your tileset. Ideally you want it to have the exact same dimensions. Less ideally you want it to have at least a fraction where the denominator or numerator is one, E.G. 32:32 instead of 16:16 or 8:8 (though you almost surely don't want that lol). Note that the minimum size of the game window is 80:25, which means you don't really want an image of larger than 78:23 (since the frame has an inset of 1). You might have to stretch the image a little to get into the dims--the above image was stretched 9 pixels wide and 14 pixels tall to get it to be integer multiples of 16.
« Last Edit: May 13, 2016, 01:52:29 am by Putnam »
Logged

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist

Ok, Putnam, I'm impressed.

So... chair, right?
Spoiler (click to show/hide)
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

I mean. I chose that image specifically to show off:

1. No restrictions on color or dimensions.
2. How small the image ought to be in order to work.

An image shouldn't be more than 368 pixels tall unless you're willing to have the game render it smaller. Which it can do. But also, very large graphics files will crash the game (I used a similar method to this for the SCP mod, and 512x512 crashed the game--Toady said "I imagine our texture atlas is already at least 256x256 (since the ascii one is 128 across), but maybe that's it", so I wouldn't go above 256x256).
« Last Edit: May 13, 2016, 02:23:21 am by Putnam »
Logged

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist

I'd make small-ish icon-like graphics, if at all. But it can certainly give a mod a lot of character if done right.
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

Oh, crap, forgot the most important part. GRAPHICS must be set to YES, even if the user is using ASCII. This could cause a real problem, now that I think of it.

Meph

  • Bay Watcher
    • View Profile
    • worldbicyclist

Oh, crap, forgot the most important part. GRAPHICS must be set to YES, even if the user is using ASCII. This could cause a real problem, now that I think of it.
I figured that after your sentece
Quote
As long as a creature--ANY creature--loads a tileset, it can be used in graphics this way.
What happens if someone turns GRAPHICS to NO? Super-crash-party, or simply nothing?
Logged
::: ☼Meph Tileset☼☼Map Tileset☼- 32x graphic sets with TWBT :::
::: ☼MASTERWORK DF☼ - A comprehensive mod pack now on Patreon - 250.000+ downloads and counting :::
::: WorldBicyclist.com - Follow my bike tours around the world - 148 countries visited :::

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile

It'll either show nothing or show the frame, but not the graphics in it. The latter happens if the graphics aren't loaded in properly.

At the very least, there should be no situation where it crashes.

EDIT:

Code: [Select]
--Written by Putnam

local widgets=require('gui.widgets')

local gui=require('gui')

local dlg=require('gui.dialogs')

local GraphicalButton=defclass(GraphicalButton,widgets.Widget)

GraphicalButton.ATTRS={
    on_click = DEFAULT_NIL,
    on_rclick = DEFAULT_NIL,
    graphic = DEFAULT_NIL, --refers to the name of a tilepage
    label = DEFAULT_NIL
}

function GraphicalButton:preUpdateLayout()
    self.frame=self.frame or {}
    if not self.page then self.frame.w=0 self.frame.h=0 return end
    self.frame.w=self.page.page_dim_x
    self.frame.h=self.page.page_dim_y
end

function GraphicalButton:onRenderBody(dc)
    if not self.page then return end
    for k,v in ipairs(self.page.texpos) do
        dc:seek(k%self.frame.w,math.floor(k/self.frame.w)):tile(32,v)
    end
end

function GraphicalButton:onInput(keys)
    if keys._MOUSE_L_DOWN and self:getMousePos() and self.on_click then
        self.on_click()
    end
    if keys._MOUSE_R_DOWN and self:getMousePos() and self.on_rclick then
        self.on_rclick()
    end
end

function GraphicalButton:init(args)
    if not self.graphic then return end
    for k,v in ipairs(df.global.texture.page) do
        if v.token==self.graphic then self.page=v return end
    end
    error('No tilepage found: '..self.graphic)
end

local GraphicsBox=defclass(GraphicsBox,dlg.MessageBox)

GraphicsBox.ATTRS{
    frame_style = gui.GREY_LINE_FRAME,
    frame_inset = 1,
    -- new attrs
    on_accept = DEFAULT_NIL,
    on_cancel = DEFAULT_NIL,
    on_close = DEFAULT_NIL,
}

function GraphicsBox:onRender()
    self.super.onRender(self)
    self:renderSubviews()
end

function GraphicsBox:getWantedFrameSize()
    local button=self.subviews.image
    if not button.frame then return end
    return button.frame.w,button.frame.h
end

function GraphicsBox:init(info)
    self:addviews{
        GraphicalButton{
            view_id = 'image',
            graphic = info.graphic,
            frame = {l=0,t=0}
        }
    }
end

function showImage(title,image,on_close)
    GraphicsBox{
        frame_title=title,
        graphic=image,
        on_close=on_close
    }:show()
end

local lastFrame=df.global.enabler.frame_last

dfhack.onStateChange.itemPictures=function(code)
    if code==SC_VIEWSCREEN_CHANGED and dfhack.isWorldLoaded() then
        if dfhack.gui.getCurViewscreen()._type==df.viewscreen_textviewerst and df.global.enabler.frame_last-lastFrame>df.global.enabler.gfps*20 then
            lastFrame=df.global.enabler.frame_last
            local parent=dfhack.gui.getCurViewscreen().parent
            if parent._type==df.viewscreen_unitst or parent._type==df.viewscreen_dungeon_monsterstatusst then
                local unit=parent.unit
                local imageExists=false
                local creature=df.creature_raw.find(unit)
                for k,v in ipairs(df.global.texture.page) do
                    if v.token==creature.creature_id..'_TEXT_IMAGE' and v.loaded then
                        imageExists=true
                        break
                    end
                end
                if imageExists then
                    showImage("Image",creature.creature_id..'_TEXT_IMAGE')
                end
            elseif parent._type==df.viewscreen_itemst then
                local item=parent.item
                local imageExists=false
                local itemName=''
                local subtype=dfhack.items.getSubtypeDef(item:getType(),item:getSubtype())
                if subtype then
                    itemName=df.item_type[item:getType()]..'/'..subtype.id --gotta be a slash methinks
                else
                    itemName=df.item_type[item:getType()]
                end
                for k,v in ipairs(df.global.texture.page) do
                    if v.token==itemName..'_TEXT_IMAGE' and v.loaded then
                        imageExists=true
                        break
                    end
                end
                if imageExists then
                    showImage("Image",itemName..'_TEXT_IMAGE')
                end
            end
        end
    end
end

This version will just ignore any non-loaded graphics.
Pages: 1 ... 7 8 [9]