Commit b7bba2cd2fff780e906527a85579adeb3a6efc8a

Authored by DarkGod
2 parents 43909d9a a81627f2

Merge branch 'master' into microtxn

... ... @@ -178,7 +178,8 @@ function _M:display(nb_keyframes)
178 178 self.flyers:display(nb_keyframes)
179 179 end
180 180
181   - if not self.suppressDialogs and #self.dialogs then
  181 + -- Suppress the display of dialogs when drawing for a savefile screenshot.
  182 + if not core.display.redrawingForSavefileScreenshot() and #self.dialogs then
182 183 local last = self.dialogs[#self.dialogs]
183 184 for i = last and last.__show_only and #self.dialogs or 1, #self.dialogs do
184 185 local d = self.dialogs[i]
... ... @@ -679,6 +680,20 @@ function _M:setGamma(gamma)
679 680 end
680 681 end
681 682
  683 +--- Sets the gamma of the window only if using a fullscreen shader
  684 +-- @param gamma
  685 +function _M:setFullscreenShaderGamma(gamma)
  686 + if self.support_shader_gamma and core.shader.active() then
  687 + if self.full_fbo_shader then
  688 + -- Tell the shader which gamma to use
  689 + self.full_fbo_shader:setUniform("gamma", gamma)
  690 + print("[GAMMA] Setting gamma correction using fullscreen shader", gamma)
  691 + else
  692 + print("[GAMMA] Not setting gamma correction yet, no fullscreen shader found", gamma)
  693 + end
  694 + end
  695 +end
  696 +
682 697 --- Requests the game to save
683 698 function _M:saveGame()
684 699 end
... ... @@ -724,13 +739,9 @@ end
724 739 -- @param[type=boolean] for_savefile The screenshot will be used for savefile display
725 740 -- @return screenshot
726 741 function _M:takeScreenshot(for_savefile)
  742 + core.display.forceRedrawForScreenshot(for_savefile)
727 743 if for_savefile then
728   - self.suppressDialogs = true
729   - core.display.forceRedraw()
730   - local sc = core.display.getScreenshot(self.w / 4, self.h / 4, self.w / 2, self.h / 2)
731   - self.suppressDialogs = nil
732   - core.display.forceRedraw()
733   - return sc
  744 + return core.display.getScreenshot(self.w / 4, self.h / 4, self.w / 2, self.h / 2)
734 745 else
735 746 return core.display.getScreenshot(0, 0, self.w, self.h)
736 747 end
... ...
... ... @@ -141,16 +141,33 @@ newAI("move_astar", function(self, add_check)
141 141 if config.settings.log_detail_ai > 0 then print("[move_astar] no Astar path, using move_simple") end
142 142 return self:runAI("move_simple")
143 143 else
144   - local moved = self:move(path[1].x, path[1].y)
  144 + local moved = self:moveDirection(path[1].x, path[1].y)
145 145 if moved then return moved
146 146 else
147 147 if config.settings.log_detail_ai > 0 then print("[move_astar] invalid Astar node, using move_simple", path[1].x, path[1].y, "using move_simple") end
148   - return self:runAI("move_simple")
  148 + return self:runAI("move_simple")
149 149 end
150 150 end
151 151 end
152 152 end)
153 153
  154 +-- Always use Astar pathing and exclude grids that are blocked by actors *if* you would be unable to shove/swap with the actor
  155 +-- This is autoassigned to most rares/randbosses
  156 +newAI("move_astar_advanced", function(self)
  157 + if self.ai_target.actor then
  158 + local check_all_block_move = function(nx, ny)
  159 + local actor = game.level.map(nx, ny, engine.Map.ACTOR)
  160 + if actor and actor == self.ai_target.actor then
  161 + return true
  162 + else
  163 + local check = game.level.map:checkAllEntities(nx, ny, "aiPathingBlockCheck", self)
  164 + return not check
  165 + end
  166 + end
  167 + return self:runAI("move_astar", check_all_block_move)
  168 + end
  169 +end)
  170 +
154 171 -- Use A* pathing if we were blocked for several turns, to avoid stacking up in simple chokepoints
155 172 newAI("move_blocked_astar", function(self)
156 173 if self.ai_target.actor then
... ...
... ... @@ -71,7 +71,7 @@ end
71 71
72 72 function _M:aiCanPass(x, y)
73 73 -- Nothing blocks, just go on
74   - if not game.level.map:checkAllEntities(x, y, "block_move", self, true) then return true end
  74 + if not game.level.map:checkAllEntities(x, y, "block_move", self, nil, true) then return true end
75 75
76 76 -- If there is an other actor, check hostility, if hostile, we move to attack
77 77 local target = game.level.map(x, y, Map.ACTOR)
... ... @@ -83,6 +83,10 @@ function _M:aiCanPass(x, y)
83 83 return false
84 84 end
85 85
  86 +function _M:aiPathingBlockCheck(x, y, target)
  87 +
  88 +end
  89 +
86 90 --- Move one step to the given target if possible
87 91 -- This tries the most direct route, if not available it checks sides and always tries to get closer
88 92 function _M:moveDirection(x, y, force)
... ... @@ -240,28 +244,26 @@ function _M:aiSeeTargetPos(target)
240 244 if target == self.ai_target.actor and (LSeen.GCache_turn or 0) + 10 <= game.turn and LSeen.x then
241 245 spread = spread + math.min(10, math.floor((game.turn - (LSeen.GCknown_turn or game.turn)) / (game.energy_to_act / game.energy_per_tick))) -- Limit spread to 10 tiles
242 246 tx, ty = util.bound(tx + rng.range(-spread, spread), 0, game.level.map.w - 1), util.bound(ty + rng.range(-spread, spread), 0, game.level.map.h - 1)
  247 +
243 248 -- Inertial average with last guess: can specify another method here to make the targeting position less random
244 249 if LSeen.GCache_x then -- update guess with new random position
245 250 tx = math.floor(LSeen.GCache_x + (tx-LSeen.GCache_x)/2)
246 251 ty = math.floor(LSeen.GCache_y + (ty-LSeen.GCache_y)/2)
247   -
248   ---[[ simplified sanity check
249   - if (target.canMove and not target:canMove(tx, ty, true)) or (tx == self.x and ty == self.y) then -- find a reasonable spot if target can't be at that position
250   - local nx, ny = util.findFreeGrid(tx, ty, math.max(1, spread), false)
251   - if nx then tx, ty = nx, ny end
  252 + end
  253 +
  254 + -- try to find a reasonable spot if target can't be at estimated position
  255 + local act = game.level.map(tx, ty, Map.ACTOR)
  256 + if (act and act ~= target and self:canSee(act)) or (target.canMove and not target:canMove(tx, ty, true)) then
  257 + local nx, ny, grids = util.findFreeGrid(tx, ty, math.max(1, spread), false)
  258 + if not grids then -- sometimes there is no free grid at low spreads, so try again a bit wider on failure
  259 + nx, ny, grids = util.findFreeGrid(tx, ty, 3, false)
252 260 end
253   ---]]
254   - -- try to find a reasonable spot if target can't be at estimated position
255   - local act = game.level.map(tx, ty, Map.ACTOR)
256   - if act and act ~= target and self:canSee(act) or (target.canMove and not target:canMove(tx, ty, true)) then
257   - local nx, ny, grids = util.findFreeGrid(tx, ty, math.max(1, spread), false)
258   - if grids then
259   - for i, grid in ipairs(grids) do
260   - act = game.level.map(grid[1], grid[2], Map.ACTOR)
261   - if not act or (act == target or act ~= self and not self:canSee(act)) then
262   - tx, ty = grid[1], grid[2]
263   - break
264   - end
  261 + if grids then
  262 + for i, grid in ipairs(grids) do
  263 + act = game.level.map(grid[1], grid[2], Map.ACTOR)
  264 + if not act or (act == target or act ~= self and not self:canSee(act)) then
  265 + tx, ty = grid[1], grid[2]
  266 + break
265 267 end
266 268 end
267 269 end
... ...
... ... @@ -2996,6 +2996,7 @@ function _M:die(src, death_note)
2996 2996 self.died = (self.died or 0) + 1
2997 2997 self:move(self.x, self.y, true)
2998 2998 self:check("on_resurrect", "basic_resurrect")
  2999 + self:triggerHook{"Actor:resurrect", reason="basic_resurrect"}
2999 3000
3000 3001 if self:attr("self_resurrect_chat") then
3001 3002 local chat = Chat.new(self.self_resurrect_chat, self, game.player)
... ...
... ... @@ -1869,9 +1869,14 @@ function _M:display(nb_keyframes)
1869 1869 -- If switching resolution, blank everything but the dialog
1870 1870 if self.change_res_dialog then engine.GameTurnBased.display(self, nb_keyframes) return end
1871 1871
1872   - -- Reset gamma setting, something somewhere is disrupting it, this is a stop gap solution
1873   - if self.support_shader_gamma and self.full_fbo_shader and self.full_fbo_shader.shad then self.full_fbo_shader.shad:uniGamma(config.settings.gamma_correction / 100) end
  1872 + if not core.display.redrawingForSavefileScreenshot() then
  1873 + -- Don't change gamma here during redrawing for savefile screenshot.
  1874 + -- I suspect that the following code is actually unnecessary, but I'm not changing it.
1874 1875
  1876 + -- Reset gamma setting, something somewhere is disrupting it, this is a stop gap solution
  1877 + if self.support_shader_gamma and self.full_fbo_shader and self.full_fbo_shader.shad then self.full_fbo_shader.shad:uniGamma(config.settings.gamma_correction / 100) end
  1878 + end
  1879 +
1875 1880 if self.full_fbo then self.full_fbo:use(true) end
1876 1881
1877 1882 -- Now the ui
... ... @@ -2702,22 +2707,15 @@ end
2702 2707 --- Take a screenshot of the game
2703 2708 -- @param for_savefile The screenshot will be used for savefile display
2704 2709 function _M:takeScreenshot(for_savefile)
  2710 + core.display.forceRedrawForScreenshot(for_savefile)
2705 2711 if for_savefile then
2706   - self.suppressDialogs = true
2707   - core.display.forceRedraw()
2708   -
2709 2712 local x, y = self.w / 4, self.h / 4
2710 2713 if self.level then
2711   - x, y = self.level.map:getTileToScreen(self.player.x, self.player.y)
  2714 + x, y = self.level.map:getTileToScreen(self.player.x, self.player.y, true)
2712 2715 x, y = x - self.w / 4, y - self.h / 4
2713 2716 x, y = util.bound(x, 0, self.w / 2), util.bound(y, 0, self.h / 2)
2714 2717 end
2715   - local sc = core.display.getScreenshot(x, y, self.w / 2, self.h / 2)
2716   -
2717   - self.suppressDialogs = nil
2718   - core.display.forceRedraw()
2719   -
2720   - return sc
  2718 + return core.display.getScreenshot(x, y, self.w / 2, self.h / 2)
2721 2719 else
2722 2720 return core.display.getScreenshot(0, 0, self.w, self.h)
2723 2721 end
... ...
... ... @@ -2324,6 +2324,9 @@ function _M:createRandomBoss(base, data)
2324 2324 -- Randbosses resemble players so they should use the same resist cap rules
2325 2325 -- This is particularly important because at high levels boss ranks get a lot of free resist all
2326 2326 b.resists_cap = { all = 70 }
  2327 +
  2328 + b.move_others = true
  2329 + b.open_door = true
2327 2330
2328 2331 -- Update default equipment, if any, to "boss" levels
2329 2332 for k, resolver in ipairs(b) do
... ... @@ -2404,7 +2407,11 @@ function _M:createRandomBoss(base, data)
2404 2407 if data.ai then b.ai = data.ai
2405 2408 else b.ai = (b.rank > 3) and "tactical" or b.ai
2406 2409 end
2407   - b.ai_state = { talent_in=1, ai_move=data.ai_move or "move_astar" }
  2410 + b.ai_state = { talent_in=1 }
  2411 + if not b.no_overwrite_ai_move then
  2412 + b.ai_state.ai_move = "move_astar_advanced"
  2413 + end
  2414 +
2408 2415 if data.ai_tactic then
2409 2416 b.ai_tactic = data.ai_tactic
2410 2417 else
... ... @@ -2640,6 +2647,8 @@ function _M:createRandomBossNew(base, data)
2640 2647 b.rank = data.rank or (rng.percent(30) and 4 or 3.5)
2641 2648 b.level_range[1] = data.level
2642 2649 b.fixed_rating = true
  2650 + b.move_others = true
  2651 + b.open_door = true
2643 2652 if data.life_rating then
2644 2653 b.life_rating = data.life_rating(b.life_rating)
2645 2654 else
... ... @@ -2753,7 +2762,10 @@ function _M:createRandomBossNew(base, data)
2753 2762 if data.ai then b.ai = data.ai
2754 2763 else b.ai = (b.rank > 3) and "tactical" or b.ai
2755 2764 end
2756   - b.ai_state = { talent_in=1, ai_move=data.ai_move or "move_astar" }
  2765 + b.ai_state = { talent_in=1}
  2766 + if not b.no_overwrite_ai_move then
  2767 + b.ai_state.ai_move = "move_astar_advanced"
  2768 + end
2757 2769 if data.ai_tactic then
2758 2770 b.ai_tactic = data.ai_tactic
2759 2771 else
... ...
... ... @@ -311,9 +311,18 @@ _M.aiSubstDamtypes = {
311 311 end
312 312 }
313 313
314   --- compute the "shove weight" for an actor, determining who has priority when fighting for space
315   -local shove_algorithm = function(self)
316   - return 3 * self.rank + self.size_category * self.size_category
  314 +-- Still count grids we can potentially shove or swap our way into
  315 +function _M:aiPathingBlockCheck(x, y, actor_checking)
  316 + return not self:block_move(x, y, actor_checking) or not actor_checking:canBumpDisplace(self)
  317 +end
  318 +
  319 +-- Can an NPC shove or swap positions with a space occupied by another NPC?
  320 +function _M:canBumpDisplace(target)
  321 + if target.rank >= self.rank then return false end
  322 + if not target.x then return end
  323 + if self.never_move or target.never_move or target.cant_be_moved then return false end
  324 + if not self.move_others then return false end
  325 + return true
317 326 end
318 327
319 328 --- Move one step towards the given coordinates if possible
... ... @@ -333,10 +342,10 @@ function _M:moveDirection(x, y, force)
333 342
334 343 -- if blocked, evaluate other possible directions
335 344 local l = {}
336   - local shove_wt = shove_algorithm(self)
  345 +
337 346 -- Find all possible directions to move, including towards friendly targets
338 347 local target = game.level.map(lx, ly, engine.Map.ACTOR)
339   - if target and target ~= game.player then l[#l+1] = {lx,ly, core.fov.distance(x,y,lx,ly)/2+rng.float(0, .1), target} end -- straight ahead
  348 + if target and self:reactionToward(target) > 0 and self:canBumpDisplace(target) then l[#l+1] = {lx,ly, core.fov.distance(x,y,lx,ly)/2+rng.float(0, .1), target} end -- Add straight ahead if shoveable
340 349 local dir = util.getDir(lx, ly, self.x, self.y)
341 350 local sides = util.dirSides(dir, self.x, self.y)
342 351 for _, dir in pairs(sides) do -- sides
... ... @@ -346,57 +355,51 @@ function _M:moveDirection(x, y, force)
346 355 l[#l+1] = {dx,dy, core.fov.distance(x,y,dx,dy)}
347 356 else
348 357 target = game.level.map(dx, dy, engine.Map.ACTOR)
349   - if target and target ~= game.player and target.x and self:reactionToward(target) > 0 and not target:attr("never_move") and self:canMove(dx, dy, true) then
  358 + if target and self:reactionToward(target) > 0 and self:canBumpDisplace(target) then
350 359 l[#l+1] = {dx,dy, core.fov.distance(x,y,dx,dy)/2+rng.float(0, .1), target}
351 360 end
352 361 end
353 362 end
  363 +
354 364 -- Find the best (most direct) direction
355 365 if #l > 0 then
356 366 table.sort(l, function(a,b) return a[3]<b[3] end)
357 367 local target = l[1][4]
358   - if target then -- apply shove pressure to the friendly target and move it (maybe)
359   - target.shove_pressure = (target.shove_pressure or 0) + shove_wt + (self.shove_pressure or 0)
360   - if log_detail > 3 then print("[moveDirection]", self.uid, self.name, "applying", target.shove_pressure, "shove pressure to", target.name, l[1][1], l[1][2]) end
361   - if force or target.shove_pressure > shove_algorithm(target) * 1.7 then
362   - local dir = util.getDir(target.x, target.y, self.x, self.y)
363   - local sides = util.dirSides(dir, target.x, target.y)
364   - local check_order = {}
365   - if rng.percent(50) then
366   - table.insert(check_order, "left")
367   - table.insert(check_order, "right")
368   - else
369   - table.insert(check_order, "right")
370   - table.insert(check_order, "left")
371   - end
372   - if rng.percent(50) then
373   - table.insert(check_order, "hard_left")
374   - table.insert(check_order, "hard_right")
375   - else
376   - table.insert(check_order, "hard_right")
377   - table.insert(check_order, "hard_left")
378   - end
379   - for _, side in ipairs(check_order) do
380   - local check_dir = sides[side]
381   - local sx, sy = util.coordAddDir(target.x, target.y, check_dir)
  368 + if target then -- Try to shove the blocker aside before trying to swap, this way we favor the NPCs "spreading out"
  369 + if log_detail > 3 then print("[moveDirection]", self.uid, self.name, "attempting to shove", target.name, l[1][1], l[1][2]) end
  370 + local dir = util.getDir(target.x, target.y, self.x, self.y)
  371 + local sides = util.dirSides(dir, target.x, target.y)
  372 + local check_order = {}
  373 + if rng.percent(50) then
  374 + table.insert(check_order, "left")
  375 + table.insert(check_order, "right")
  376 + else
  377 + table.insert(check_order, "right")
  378 + table.insert(check_order, "left")
  379 + end
  380 + if rng.percent(50) then
  381 + table.insert(check_order, "hard_left")
  382 + table.insert(check_order, "hard_right")
  383 + else
  384 + table.insert(check_order, "hard_right")
  385 + table.insert(check_order, "hard_left")
  386 + end
  387 + for _, side in ipairs(check_order) do
  388 + local check_dir = sides[side]
  389 + local sx, sy = util.coordAddDir(target.x, target.y, check_dir)
382 390 -- print("[moveDirection] checking shove target pos", check_dir, sx, sy)
383   - -- move the friendly target if possible and it has energy
384   - if target.energy.value > 0 and target:canMove(sx, sy) and target:move(sx, sy, true) then
385   - local energy = game.energy_to_act * target:combatMovementSpeed(sx, sy)
386   --- print("move energy required:", energy)
387   - print("[moveDirection]", self.uid, self.name, "moved (shove_pressure)", target.uid, target.name, "to", sx, sy)
388   - self:logCombat(target, "#Source# shoves #Target# aside.")
389   - target.shove_pressure = nil
390   - target._last_shove_pressure = nil
391   - -- use energy from the target (first) then the shover (if needed)
392   - if not force then self:useEnergy(util.bound(energy - target.energy.value, 0, energy)) end
393   - target:useEnergy(math.min(energy, target.energy.value))
  391 + -- move the friendly target if possible
  392 + if target:canMove(sx, sy) and target:move(sx, sy, true) then
  393 + print("[moveDirection]", self.uid, self.name, "moved (shove)", target.uid, target.name, "to", sx, sy)
  394 + self:logCombat(target, "#Source# shoves #Target# aside.")
  395 + return self:move(l[1][1], l[1][2], force)
394 396 -- print("attempting to move", self.name, "to", l[1][1], l[1][2])
395   - return self:move(l[1][1], l[1][2], force)
396   - end
397 397 end
398   - return false -- can't move target
399 398 end
  399 +
  400 + -- We failed to shove the blocker, so swap positions with them instead via the default bumpInto behavior
  401 + -- Since swapping only happens with a rank advantage we don't need to worry about swapping back and forth
  402 + return self:move(l[1][1], l[1][2], force)
400 403 else
401 404 return self:move(l[1][1], l[1][2], force)
402 405 end
... ...
... ... @@ -47,9 +47,7 @@ function _M:bumpInto(target, x, y)
47 47 local chat = Chat.new(self.can_talk, self, target, {npc=self, player=target})
48 48 chat:invoke()
49 49 if target.can_talk_only_once then target.can_talk = nil end
50   - elseif self.move_others and not target.cant_be_moved then
51   - if target.move_others and self ~= game.player then return end
52   -
  50 + elseif self.player or (self ~= game.player and self.canBumpDisplace and self:canBumpDisplace(target)) then -- canBumpDisplace is only on NPCs
53 51 -- Check we can both walk in the tile we will end up in
54 52 local blocks = game.level.map:checkAllEntitiesLayersNoStop(target.x, target.y, "block_move", self)
55 53 for kind, v in pairs(blocks) do if kind[1] ~= Map.ACTOR and v then return end end
... ...
... ... @@ -82,6 +82,7 @@ newBirthDescriptor
82 82 resolvers.inscription("INFUSION:_REGENERATION", {cooldown=10, dur=5, heal=100}, 1),
83 83 resolvers.inscription("INFUSION:_WILD", {cooldown=14, what={physical=true}, dur=4, power=14}, 2),
84 84 resolvers.inscription("INFUSION:_HEALING", {cooldown=12, heal=50}, 3),
  85 + resolvers.birth_extra_tier1_zone{name="tier1", condition=function(e) return e.starting_zone == "reknor-escape" end, "reknor-escape", "deep-bellow"},
85 86 },
86 87 default_cosmetics = { {"hairs", "Dark Hair 1"}, {"facial_features", "Dark Beard 2", {sex="Male"}} },
87 88 cosmetic_options = {
... ...
... ... @@ -65,6 +65,7 @@ newBirthDescriptor{
65 65 resolvers.inscription("RUNE:_SHIELDING", {cooldown=14, dur=5, power=130}, 1),
66 66 resolvers.inscription("RUNE:_SHATTER_AFFLICTIONS", {cooldown=18, shield=50}, 2),
67 67 resolvers.inscription("RUNE:_BLINK", {cooldown=18, power=10, range=4,}, 3),
  68 + resolvers.birth_extra_tier1_zone{name="tier1", condition=function(e) return e.starting_zone == "blighted-ruins" end, "blighted-ruins"},
68 69 },
69 70
70 71 cosmetic_options = {
... ...
... ... @@ -52,6 +52,7 @@ newBirthDescriptor{
52 52 resolvers.inscription("INFUSION:_REGENERATION", {cooldown=10, dur=5, heal=100}, 1),
53 53 resolvers.inscription("INFUSION:_WILD", {cooldown=14, what={physical=true}, dur=4, power=14}, 2),
54 54 resolvers.inscription("INFUSION:_HEALING", {cooldown=12, heal=50}, 3),
  55 + resolvers.birth_extra_tier1_zone{name="tier1", condition=function(e) return e.starting_zone == "town-irkkk" end, "murgol-lair", "ritch-tunnels"},
55 56 },
56 57 game_state = {
57 58 start_tier1_skip = 4,
... ...
... ... @@ -89,6 +89,10 @@ newBirthDescriptor{
89 89 local x, y = mod.class.Encounter:findSpot(where)
90 90 return x, y
91 91 end,
  92 + zone_tiers = {
  93 + {name="tier1", "trollmire", "norgos-lair", "scintillating-caves", "rhaloren-camp", "heart-gloom", "ruins-kor-pul"},
  94 + {name="tier2", "sandworm-lair", "maze", "daikara", "halfling-ruins"}
  95 + }
92 96 },
93 97 }
94 98
... ...
1 1 tiles={} dolls={}
2 2
3   -tiles["npc/humanoid_shalore_elven_guard.png"] = { base=64,
4   - feet = {x=33, y=61},
5   - back = {x=32, y=15},
6   - belly = {x=32, y=28},
7   - hand1 = {x=13, y=31},
8   - head = {x=31, y=5},
9   -}
10   -tiles["npc/humanoid_human_subject_z.png"] = { base=64,
11   - feet = {x=32, y=59},
12   - hand1 = {x=8, y=11},
13   - hand2 = {x=55, y=11},
14   - belly = {x=31, y=27},
15   - back = {x=31, y=15},
16   - head = {x=32, y=3},
17   -}
18   -tiles["npc/humanoid_human_high_gladiator.png"] = { base=64,
19   - feet = {x=30, y=61},
20   - hand1 = {x=8, y=13},
21   - hand2 = {x=55, y=33},
22   - back = {x=34, y=17},
23   - belly = {x=33, y=30},
24   - head = {x=30, y=7},
  3 +dolls.race_dwarf = dolls.race_dwarf or {}
  4 +dolls.race_dwarf.female = { base=64,
  5 + back = {x=33, y=25},
  6 + belly = {x=33, y=37},
  7 + feet = {x=33, y=59},
  8 + hand1 = {x=9, y=39},
  9 + hand2 = {x=55, y=39},
  10 + head = {x=33, y=9},
  11 + shoulder1 = {x=21, y=23},
  12 + shoulder2 = {x=42, y=22},
25 13 }
26 14 dolls.race_dwarf = dolls.race_dwarf or {}
27   -dolls.race_dwarf.male = { base=128,
28   - belly = {x=68, y=68},
29   - hand2 = {x=110, y=78},
30   - head = {x=64, y=20},
31   - shoulder2 = {x=83, y=45},
32   - feet = {x=68, y=122},
33   - back = {x=64, y=50},
34   - hand1 = {x=20, y=78},
35   - shoulder1 = {x=43, y=46},
  15 +dolls.race_dwarf.male = { base=64,
  16 + back = {x=32, y=25},
  17 + belly = {x=34, y=34},
  18 + feet = {x=34, y=61},
  19 + hand1 = {x=10, y=39},
  20 + hand2 = {x=55, y=39},
  21 + head = {x=32, y=10},
  22 + shoulder1 = {x=21, y=23},
  23 + shoulder2 = {x=41, y=22},
36 24 }
37   -tiles["npc/humanoid_shalore_elvala_guard.png"] = { base=64,
38   - feet = {x=32, y=61},
39   - back = {x=31, y=15},
40   - belly = {x=31, y=27},
41   - hand1 = {x=13, y=30},
42   - head = {x=31, y=5},
  25 +dolls.race_elf = dolls.race_elf or {}
  26 +dolls.race_elf.female = { base=64,
  27 + back = {x=33, y=14},
  28 + belly = {x=34, y=27},
  29 + feet = {x=34, y=61},
  30 + hand1 = {x=19, y=33},
  31 + hand2 = {x=46, y=33},
  32 + head = {x=31, y=3},
  33 + shoulder1 = {x=26, y=13},
  34 + shoulder2 = {x=38, y=12},
43 35 }
44   -tiles["npc/humanoid_naga_slasul.png"] = { base=64,
  36 +dolls.race_elf = dolls.race_elf or {}
  37 +dolls.race_elf.male = { base=64,
  38 + back = {x=32, y=15},
  39 + belly = {x=33, y=27},
45 40 feet = {x=32, y=61},
46   - hand1 = {x=11, y=30},
47   - hand2 = {x=46, y=-2},
48   - belly = {x=23, y=14},
49   - back = {x=23, y=3},
50   - head = {x=24, y=-12},
51   -}
52   -tiles["npc/humanoid_human_human_citizen.png"] = { base=64,
53   - feet = {x=35, y=59},
54   - hand1 = {x=11, y=13},
55   - hand2 = {x=47, y=30},
56   - back = {x=36, y=16},
57   - belly = {x=36, y=28},
58   - head = {x=36, y=5},
  41 + hand1 = {x=19, y=32},
  42 + hand2 = {x=44, y=34},
  43 + head = {x=30, y=4},
  44 + shoulder1 = {x=26, y=12},
  45 + shoulder2 = {x=36, y=11},
59 46 }
60   -tiles["npc/humanoid_yeek_yeek_psionic.png"] = { base=64,
  47 +dolls.race_ghoul = dolls.race_ghoul or {}
  48 +dolls.race_ghoul.all = { base=64,
  49 + back = {x=34, y=20},
  50 + belly = {x=33, y=38},
61 51 feet = {x=33, y=61},
62   - hand1 = {x=31, y=38},
63   - hand2 = {x=33, y=38},
64   - belly = {x=32, y=34},
65   - back = {x=32, y=23},
  52 + hand1 = {x=20, y=37},
  53 + hand2 = {x=48, y=38},
  54 + head = {x=33, y=8},
  55 + shoulder1 = {x=26, y=20},
  56 + shoulder2 = {x=39, y=19},
  57 +}
  58 +dolls.race_halfling = dolls.race_halfling or {}
  59 +dolls.race_halfling.female = { base=64,
  60 + back = {x=32, y=24},
  61 + belly = {x=34, y=36},
  62 + feet = {x=34, y=62},
  63 + hand1 = {x=12, y=38},
  64 + hand2 = {x=50, y=40},
66 65 head = {x=32, y=12},
  66 + shoulder1 = {x=24, y=22},
  67 + shoulder2 = {x=38, y=21},
67 68 }
68   -tiles["npc/humanoid_orc_vor__grand_geomancer_of_the_pride.png"] = { base=64,
69   - feet = {x=32, y=60},
70   - hand1 = {x=4, y=34},
71   - hand2 = {x=58, y=39},
72   - belly = {x=32, y=35},
73   - back = {x=33, y=20},
74   - head = {x=34, y=9},
  69 +dolls.race_halfling = dolls.race_halfling or {}
  70 +dolls.race_halfling.male = { base=64,
  71 + back = {x=32, y=25},
  72 + belly = {x=33, y=36},
  73 + feet = {x=34, y=61},
  74 + hand1 = {x=14, y=39},
  75 + hand2 = {x=50, y=39},
  76 + head = {x=32, y=14},
  77 + shoulder1 = {x=25, y=23},
  78 + shoulder2 = {x=40, y=22},
75 79 }
76   -tiles["npc/humanoid_shalore_mean_looking_elven_guard.png"] = { base=64,
  80 +dolls.race_human = dolls.race_human or {}
  81 +dolls.race_human.female = { base=64,
  82 + back = {x=33, y=16},
  83 + belly = {x=34, y=28},
77 84 feet = {x=33, y=60},
78   - back = {x=31, y=14},
79   - belly = {x=32, y=27},
80   - hand1 = {x=14, y=31},
81   - head = {x=31, y=6},
  85 + hand1 = {x=20, y=33},
  86 + hand2 = {x=46, y=33},
  87 + head = {x=32, y=3},
  88 + shoulder1 = {x=26, y=14},
  89 + shoulder2 = {x=38, y=12},
82 90 }
83   -tiles["npc/humanoid_shalore_elven_cultist.png"] = { base=64,
84   - feet = {x=29, y=60},
85   - hand1 = {x=8, y=9},
86   - hand2 = {x=52, y=9},
87   - belly = {x=31, y=28},
88   - back = {x=30, y=16},
89   - head = {x=31, y=6},
  91 +dolls.race_human = dolls.race_human or {}
  92 +dolls.race_human.male = { base=64,
  93 + back = {x=32, y=15},
  94 + belly = {x=32, y=28},
  95 + feet = {x=32, y=60},
  96 + hand1 = {x=15, y=32},
  97 + hand2 = {x=48, y=34},
  98 + head = {x=30, y=3},
  99 + shoulder1 = {x=24, y=12},
  100 + shoulder2 = {x=37, y=11},
90 101 }
91   -tiles["npc/humanoid_shalore_elandar.png"] = { base=64,
92   - feet = {x=34, y=59},
93   - hand1 = {x=13, y=26},
94   - hand2 = {x=50, y=-12},
95   - belly = {x=33, y=22},
96   - back = {x=30, y=8},
97   - head = {x=29, y=-2},
  102 +dolls.race_ogre = dolls.race_ogre or {}
  103 +dolls.race_ogre.female = { base=64,
  104 + back = {x=31, y=7},
  105 + belly = {x=32, y=21},
  106 + feet = {x=32, y=62},
  107 + hand1 = {x=13, y=31},
  108 + hand2 = {x=50, y=30},
  109 + head = {x=31, y=-5},
  110 + shoulder1 = {x=23, y=2},
  111 + shoulder2 = {x=39, y=2},
98 112 }
99   -tiles["npc/humanoid_dwarf_ziguranth_warrior.png"] = { base=64,
100   - feet = {x=34, y=59},
101   - hand1 = {x=18, y=43},
102   - hand2 = {x=50, y=44},
103   - back = {x=35, y=22},
104   - belly = {x=35, y=36},
105   - head = {x=35, y=7},
  113 +dolls.race_ogre = dolls.race_ogre or {}
  114 +dolls.race_ogre.male = { base=64,
  115 + back = {x=32, y=6},
  116 + belly = {x=32, y=21},
  117 + feet = {x=33, y=61},
  118 + hand1 = {x=9, y=34},
  119 + hand2 = {x=54, y=34},
  120 + head = {x=32, y=-7},
  121 + shoulder1 = {x=19, y=2},
  122 + shoulder2 = {x=42, y=1},
  123 +}
  124 +dolls.race_orc = dolls.race_orc or {}
  125 +dolls.race_orc.male = { base=64,
  126 + back = {x=32, y=22},
  127 + belly = {x=34, y=33},
  128 + feet = {x=33, y=61},
  129 + hand1 = {x=12, y=37},
  130 + hand2 = {x=51, y=38},
  131 + head = {x=32, y=10},
  132 + shoulder1 = {x=22, y=20},
  133 + shoulder2 = {x=40, y=19},
106 134 }
107 135 dolls.race_runic_golem = dolls.race_runic_golem or {}
108   -dolls.race_runic_golem.all = { base=128,
109   - belly = {x=86, y=98},
110   - hand2 = {x=44, y=56},
111   - head = {x=78, y=58},
112   - shoulder2 = {x=82, y=41},
113   - feet = {x=108, y=86},
114   - hand1 = {x=58, y=36},
115   - back = {x=56, y=96},
116   - shoulder1 = {x=44, y=44},
  136 +dolls.race_runic_golem.all = { base=64,
  137 + back = {x=28, y=48},
  138 + belly = {x=43, y=49},
  139 + feet = {x=54, y=43},
  140 + hand1 = {x=29, y=18},
  141 + hand2 = {x=22, y=28},
  142 + head = {x=39, y=29},
  143 + shoulder1 = {x=22, y=22},
  144 + shoulder2 = {x=41, y=20},
117 145 }
118   -tiles["npc/humanoid_human_assassin_lord.png"] = { base=64,
119   - feet = {x=35, y=61},
120   - hand1 = {x=10, y=10},
121   - hand2 = {x=56, y=34},
  146 +dolls.race_skeleton = dolls.race_skeleton or {}
  147 +dolls.race_skeleton.all = { base=64,
122 148 back = {x=31, y=16},
123   - belly = {x=32, y=28},
124   - head = {x=32, y=5},
  149 + belly = {x=32, y=26},
  150 + feet = {x=32, y=62},
  151 + hand1 = {x=15, y=33},
  152 + hand2 = {x=47, y=34},
  153 + head = {x=30, y=4},
  154 + shoulder1 = {x=24, y=13},
  155 + shoulder2 = {x=37, y=11},
125 156 }
126   -tiles["npc/humanoid_human_thief.png"] = { base=64,
127   - feet = {x=27, y=60},
128   - hand1 = {x=8, y=27},
129   - hand2 = {x=43, y=30},
130   - belly = {x=27, y=30},
131   - back = {x=24, y=19},
132   - head = {x=18, y=7},
  157 +dolls.race_yeek = dolls.race_yeek or {}
  158 +dolls.race_yeek.all = { base=64,
  159 + back = {x=31, y=26},
  160 + belly = {x=32, y=36},
  161 + feet = {x=32, y=62},
  162 + hand1 = {x=16, y=39},
  163 + hand2 = {x=46, y=40},
  164 + head = {x=31, y=12},
  165 + shoulder1 = {x=24, y=22},
  166 + shoulder2 = {x=37, y=21},
133 167 }
134   -tiles["npc/humanoid_dwarf_norgan.png"] = { base=64,
135   - feet = {x=41, y=57},
136   - hand1 = {x=15, y=40},
137   - hand2 = {x=47, y=19},
138   - back = {x=32, y=23},
139   - belly = {x=35, y=37},
140   - head = {x=27, y=8},
  168 +tiles["npc/humanoid_orc_kra_tor_the_gluttonous.png"] = { base=64,
  169 + back = {x=27, y=14},
  170 + belly = {x=29, y=27},
  171 + feet = {x=38, y=57},
  172 + hand1 = {x=20, y=18},
  173 + hand2 = {x=38, y=-2},
  174 + head = {x=23, y=1},
141 175 }
142   -dolls.race_human = dolls.race_human or {}
143   -dolls.race_human.male = { base=128,
144   - belly = {x=64, y=56},
145   - hand2 = {x=96, y=68},
146   - head = {x=60, y=6},
147   - shoulder2 = {x=75, y=22},
148   - feet = {x=64, y=120},
149   - hand1 = {x=30, y=64},
150   - back = {x=64, y=30},
151   - shoulder1 = {x=48, y=25},
  176 +tiles["npc/humanoid_shalore_archmage_tarelion.png"] = { base=64,
  177 + back = {x=31, y=0},
  178 + belly = {x=33, y=18},
  179 + feet = {x=33, y=59},
  180 + hand1 = {x=17, y=26},
  181 + hand2 = {x=45, y=26},
  182 + head = {x=30, y=-11},
152 183 }
153   -tiles["npc/humanoid_yaech_murgol__the_yaech_lord.png"] = { base=64,
154   - feet = {x=56, y=58},
155   - hand1 = {x=7, y=28},
156   - hand2 = {x=20, y=32},
157   - belly = {x=38, y=39},
158   - back = {x=38, y=31},
159   - head = {x=32, y=16},
  184 +tiles["npc/humanoid_human_spectator02.png"] = { base=64,
  185 + back = {x=30, y=16},
  186 + belly = {x=31, y=30},
  187 + feet = {x=30, y=59},
  188 + hand1 = {x=18, y=37},
  189 + hand2 = {x=41, y=37},
  190 + head = {x=30, y=5},
160 191 }
161   -tiles["npc/humanoid_human_the_possessed.png"] = { base=64,
162   - feet = {x=30, y=62},
163   - hand1 = {x=9, y=17},
164   - hand2 = {x=47, y=37},
165   - belly = {x=33, y=35},
166   - back = {x=33, y=17},
167   - head = {x=33, y=4},
  192 +tiles["npc/humanoid_human_townsfolk_blubbering_idiot01_64.png"] = { base=64,
  193 + back = {x=31, y=19},
  194 + belly = {x=31, y=33},
  195 + feet = {x=33, y=59},
  196 + hand1 = {x=19, y=41},
  197 + hand2 = {x=47, y=40},
  198 + head = {x=29, y=7},
168 199 }
169   -tiles["npc/humanoid_halfling_master_slinger.png"] = { base=64,
170   - feet = {x=39, y=59},
171   - hand1 = {x=15, y=42},
172   - hand2 = {x=47, y=10},
173   - back = {x=31, y=27},
174   - belly = {x=32, y=38},
175   - head = {x=28, y=14},
  200 +tiles["npc/humanoid_human_townsfolk_village_idiot01_64.png"] = { base=64,
  201 + back = {x=33, y=24},
  202 + belly = {x=37, y=34},
  203 + feet = {x=35, y=58},
  204 + head = {x=32, y=8},
176 205 }
177   -tiles["npc/humanoid_thalore_mindworm.png"] = { base=64,
178   - feet = {x=32, y=62},
179   - hand1 = {x=21, y=36},
180   - hand2 = {x=44, y=35},
181   - belly = {x=32, y=30},
182   - back = {x=31, y=13},
183   - head = {x=31, y=6},
  206 +tiles["npc/humanoid_human_celia.png"] = { base=64,
  207 + back = {x=29, y=-16},
  208 + belly = {x=28, y=2},
  209 + feet = {x=28, y=59},
  210 + hand1 = {x=15, y=16},
  211 + hand2 = {x=50, y=-20},
  212 + head = {x=29, y=-33},
184 213 }
185   -tiles["npc/humanoid_shalore_grand_corruptor.png"] = { base=64,
186   - feet = {x=25, y=61},
187   - hand1 = {x=11, y=34},
188   - hand2 = {x=53, y=17},
189   - belly = {x=28, y=31},
190   - back = {x=28, y=19},
191   - head = {x=28, y=10},
  214 +tiles["npc/humanoid_human_enthralled_slave.png"] = { base=64,
  215 + back = {x=32, y=18},
  216 + belly = {x=32, y=29},
  217 + feet = {x=33, y=58},
  218 + hand1 = {x=16, y=35},
  219 + hand2 = {x=47, y=36},
  220 + head = {x=31, y=5},
192 221 }
193   -tiles["npc/humanoid_human_harno__herald_of_last_hope.png"] = { base=64,
194   - feet = {x=32, y=61},
195   - hand1 = {x=16, y=37},
196   - hand2 = {x=45, y=36},
197   - back = {x=30, y=15},
198   - belly = {x=31, y=31},
199   - head = {x=29, y=4},
  222 +tiles["npc/humanoid_human_bandit_lord.png"] = { base=64,
  223 + back = {x=31, y=16},
  224 + belly = {x=32, y=30},
  225 + feet = {x=34, y=59},
  226 + hand1 = {x=20, y=20},
  227 + hand2 = {x=38, y=21},
  228 + head = {x=30, y=5},
200 229 }
201   -tiles["npc/humanoid_human_slave_combatant.png"] = { base=64,
202   - feet = {x=33, y=60},
203   - hand1 = {x=18, y=37},
204   - hand2 = {x=47, y=32},
205   - belly = {x=31, y=29},
  230 +tiles["npc/humanoid_human_human_guard.png"] = { base=64,
206 231 back = {x=30, y=17},
207   - head = {x=29, y=6},
208   -}
209   -dolls.race_elf = dolls.race_elf or {}
210   -dolls.race_elf.male = { base=128,
211   - belly = {x=66, y=54},
212   - hand2 = {x=88, y=68},
213   - head = {x=60, y=8},
214   - shoulder2 = {x=72, y=23},
215   - feet = {x=64, y=122},
216   - hand1 = {x=38, y=64},
217   - back = {x=64, y=30},
218   - shoulder1 = {x=52, y=25},
219   -}
220   -tiles["npc/humanoid_male_sluttymaid.png"] = { base=64,
221   - feet = {x=30, y=60},
222   - hand1 = {x=24, y=30},
223   - hand2 = {x=41, y=21},
224   - belly = {x=35, y=24},
225   - back = {x=35, y=11},
226   - head = {x=35, y=0},
  232 + belly = {x=31, y=30},
  233 + feet = {x=33, y=60},
  234 + hand1 = {x=19, y=29},
  235 + hand2 = {x=46, y=25},
  236 + head = {x=28, y=5},
227 237 }
228   -tiles["npc/humanoid_elf_limmir_the_jeweler.png"] = { base=64,
  238 +tiles["npc/humanoid_orc_orc_master_assassin.png"] = { base=64,
  239 + back = {x=29, y=18},
  240 + belly = {x=30, y=30},
229 241 feet = {x=31, y=60},
230   - hand1 = {x=11, y=37},
231   - hand2 = {x=49, y=9},
232   - back = {x=31, y=19},
233   - belly = {x=31, y=30},
234   - head = {x=32, y=4},
  242 + hand1 = {x=4, y=39},
  243 + hand2 = {x=59, y=32},
  244 + head = {x=28, y=8},
235 245 }
236   -tiles["npc/canine_warg.png"] = { base=64,
237   - feet = {x=15, y=18},
238   - hand1 = {x=48, y=22},
239   - hand2 = {x=46, y=48},
240   - belly = {x=12, y=32},
241   - back = {x=26, y=51},
242   - head = {x=33, y=13},
  246 +tiles["npc/humanoid_human_townsfolk_pitiful_looking_beggar01_64.png"] = { base=64,
  247 + back = {x=40, y=20},
  248 + belly = {x=41, y=33},
  249 + feet = {x=41, y=60},
  250 + hand1 = {x=25, y=32},
  251 + head = {x=31, y=10},
243 252 }
244   -tiles["npc/humanoid_human_ice_wyrmic.png"] = { base=64,
245   - feet = {x=30, y=61},
246   - back = {x=32, y=19},
247   - hand2 = {x=58, y=17},
248   - hand1 = {x=9, y=36},
249   - belly = {x=32, y=33},
250   - head = {x=36, y=11},
  253 +tiles["npc/humanoid_orc_krogar.png"] = { base=64,
  254 + back = {x=29, y=25},
  255 + belly = {x=29, y=35},
  256 + feet = {x=32, y=59},
  257 + hand1 = {x=14, y=0},
  258 + hand2 = {x=53, y=13},
  259 + head = {x=30, y=11},
251 260 }
252   -tiles["npc/acid_ant.png"] = { base=64,
253   - feet = {x=36, y=57},
254   - back = {x=45, y=37},
255   - hand2 = {x=51, y=17},
256   - hand1 = {x=32, y=22},
257   - belly = {x=11, y=33},
258   - head = {x=15, y=13},
  261 +tiles["npc/humanoid_shalore_elven_mage.png"] = { base=64,
  262 + back = {x=31, y=18},
  263 + belly = {x=31, y=30},
  264 + feet = {x=31, y=61},
  265 + hand1 = {x=11, y=35},
  266 + hand2 = {x=50, y=39},
  267 + head = {x=30, y=6},
259 268 }
260   -tiles["npc/humanoid_shalore_elven_corruptor.png"] = { base=64,
261   - feet = {x=34, y=60},
262   - hand1 = {x=12, y=17},
263   - hand2 = {x=48, y=34},
264   - belly = {x=31, y=33},
265   - back = {x=31, y=20},
266   - head = {x=31, y=10},
  269 +tiles["npc/humanoid_naga_naga_tidewarden.png"] = { base=64,
  270 + back = {x=32, y=-3},
  271 + belly = {x=32, y=9},
  272 + feet = {x=32, y=61},
  273 + hand1 = {x=31, y=12},
  274 + head = {x=34, y=-15},
267 275 }
268   -tiles["npc/humanoid_human_townsfolk_village_idiot01_64.png"] = { base=64,
  276 +tiles["npc/humanoid_halfling_halfling_guard.png"] = { base=64,
269 277 back = {x=33, y=24},
270   - feet = {x=35, y=58},
271   - belly = {x=37, y=34},
272   - head = {x=32, y=8},
  278 + belly = {x=36, y=36},
  279 + feet = {x=38, y=59},
  280 + hand1 = {x=8, y=28},
  281 + hand2 = {x=54, y=43},
  282 + head = {x=30, y=10},
273 283 }
274   -tiles["npc/alchemist_golem.png"] = { base=64,
275   - belly = {x=34, y=30},
276   - hand2 = {x=56, y=48},
277   - head = {x=33, y=5},
278   - shoulder2 = {x=47, y=11},
279   - feet = {x=34, y=57},
280   - shoulder1 = {x=20, y=11},
281   - back = {x=35, y=21},
282   - hand1 = {x=10, y=50},
  284 +tiles["npc/humanoid_orc_warmaster_gnarg.png"] = { base=64,
  285 + back = {x=32, y=18},
  286 + belly = {x=43, y=29},
  287 + feet = {x=40, y=60},
  288 + hand1 = {x=60, y=27},
  289 + hand2 = {x=58, y=28},
  290 + head = {x=21, y=9},
283 291 }
284   -tiles["npc/humanoid_elf_elven_sun_mage.png"] = { base=64,
285   - feet = {x=35, y=62},
286   - hand1 = {x=13, y=28},
287   - hand2 = {x=50, y=37},
  292 +tiles["npc/humanoid_orc_orc_soldier.png"] = { base=64,
  293 + back = {x=29, y=21},
  294 + belly = {x=34, y=34},
  295 + feet = {x=36, y=62},
  296 + hand1 = {x=9, y=39},
  297 + hand2 = {x=58, y=36},
  298 + head = {x=25, y=9},
  299 +}
  300 +tiles["npc/humanoid_shalore_elven_tempest.png"] = { base=64,
288 301 back = {x=32, y=16},
289   - belly = {x=34, y=35},
290   - head = {x=31, y=4},
  302 + belly = {x=31, y=28},
  303 + feet = {x=35, y=60},
  304 + hand1 = {x=11, y=9},
  305 + hand2 = {x=49, y=36},
  306 + head = {x=33, y=7},
291 307 }
292   -dolls.race_halfling = dolls.race_halfling or {}
293   -dolls.race_halfling.female = { base=128,
294   - belly = {x=68, y=72},
295   - hand2 = {x=100, y=80},
296   - head = {x=64, y=24},
297   - shoulder2 = {x=76, y=43},
298   - feet = {x=68, y=124},
299   - hand1 = {x=24, y=76},
300   - back = {x=64, y=48},
301   - shoulder1 = {x=48, y=45},
  308 +tiles["npc/humanoid_human_cryomancer.png"] = { base=64,
  309 + back = {x=35, y=16},
  310 + belly = {x=36, y=28},
  311 + feet = {x=37, y=59},
  312 + hand1 = {x=22, y=6},
  313 + hand2 = {x=44, y=32},
  314 + head = {x=34, y=5},
302 315 }
303   -tiles["npc/humanoid_human_high_slinger.png"] = { base=64,
304   - feet = {x=29, y=59},
305   - hand1 = {x=15, y=36},
306   - hand2 = {x=57, y=18},
307   - back = {x=31, y=15},
308   - belly = {x=30, y=27},
309   - head = {x=33, y=6},
  316 +tiles["npc/humanoid_thalore_thalore_hunter.png"] = { base=64,
  317 + back = {x=33, y=18},
  318 + belly = {x=33, y=30},
  319 + feet = {x=31, y=59},
  320 + hand1 = {x=18, y=38},
  321 + hand2 = {x=52, y=31},
  322 + head = {x=32, y=8},
310 323 }
311   -dolls.race_halfling = dolls.race_halfling or {}
312   -dolls.race_halfling.male = { base=128,
313   - belly = {x=66, y=72},
314   - hand2 = {x=100, y=78},
315   - head = {x=64, y=28},
316   - shoulder2 = {x=80, y=44},
317   - feet = {x=68, y=122},
318   - hand1 = {x=28, y=78},
319   - back = {x=64, y=50},
320   - shoulder1 = {x=50, y=46},
  324 +tiles["npc/humanoid_yeek_yeek_commoner_04.png"] = { base=64,
  325 + back = {x=32, y=25},
  326 + belly = {x=32, y=36},
  327 + feet = {x=33, y=60},
  328 + hand1 = {x=17, y=40},
  329 + hand2 = {x=50, y=44},
  330 + head = {x=32, y=8},
321 331 }
322   -tiles["npc/animal_feline_snow_cat.png"] = { base=64,
323   - head = {x=17, y=18},
  332 +tiles["npc/humanoid_orc_orc_elite_fighter.png"] = { base=64,
  333 + back = {x=29, y=16},
  334 + belly = {x=31, y=33},
  335 + feet = {x=31, y=60},
  336 + hand1 = {x=11, y=37},
  337 + hand2 = {x=53, y=29},
  338 + head = {x=29, y=4},
324 339 }
325   -tiles["npc/humanoid_human_master_alchemist.png"] = { base=64,
  340 +tiles["npc/humanoid_human_fire_wyrmic.png"] = { base=64,
  341 + back = {x=28, y=19},
  342 + belly = {x=28, y=28},
  343 + feet = {x=31, y=60},
  344 + hand1 = {x=12, y=30},
  345 + hand2 = {x=49, y=36},
  346 + head = {x=24, y=9},
  347 +}
  348 +tiles["npc/humanoid_dwarf_dwarven_earthwarden.png"] = { base=64,
  349 + back = {x=36, y=22},
  350 + belly = {x=35, y=37},
  351 + feet = {x=34, y=58},
  352 + hand1 = {x=20, y=37},
  353 + hand2 = {x=51, y=36},
  354 + head = {x=35, y=7},
  355 +}
  356 +tiles["npc/humanoid_human_alchemist.png"] = { base=64,
  357 + back = {x=33, y=19},
  358 + belly = {x=34, y=32},
326 359 feet = {x=35, y=59},
327   - hand1 = {x=7, y=18},
328   - hand2 = {x=57, y=35},
329   - belly = {x=37, y=28},
330   - back = {x=34, y=18},
331   - head = {x=29, y=8},
  360 + hand1 = {x=10, y=32},
  361 + hand2 = {x=51, y=34},
  362 + head = {x=33, y=5},
332 363 }
333   -dolls.race_ghoul = dolls.race_ghoul or {}
334   -dolls.race_ghoul.all = { base=128,
335   - belly = {x=66, y=76},
336   - hand2 = {x=96, y=76},
337   - head = {x=66, y=16},
338   - shoulder2 = {x=79, y=38},
339   - feet = {x=66, y=122},
340   - hand1 = {x=40, y=74},
341   - back = {x=68, y=40},
342   - shoulder1 = {x=52, y=40},
  364 +tiles["npc/humanoid_human_meranas__herald_of_angolwen.png"] = { base=64,
  365 + back = {x=34, y=21},
  366 + belly = {x=35, y=31},
  367 + feet = {x=34, y=60},
  368 + hand1 = {x=16, y=40},
  369 + hand2 = {x=52, y=39},
  370 + head = {x=31, y=4},
343 371 }
344   -tiles["npc/humanoid_orc_brotoq_the_reaver.png"] = { base=64,
345   - feet = {x=38, y=59},
346   - hand1 = {x=14, y=31},
347   - hand2 = {x=58, y=33},
348   - belly = {x=38, y=26},
349   - back = {x=38, y=15},
350   - head = {x=35, y=3},
  372 +tiles["npc/humanoid_human_human_farmer.png"] = { base=64,
  373 + back = {x=29, y=18},
  374 + belly = {x=31, y=31},
  375 + feet = {x=32, y=60},
  376 + hand1 = {x=11, y=20},
  377 + hand2 = {x=44, y=38},
  378 + head = {x=29, y=5},
351 379 }
352   -tiles["npc/humanoid_shalore_elven_elite_warrior.png"] = { base=64,
353   - feet = {x=33, y=62},
354   - back = {x=31, y=15},
355   - belly = {x=31, y=27},
  380 +tiles["npc/humanoid_human_derth_guard.png"] = { base=64,
  381 + back = {x=34, y=17},
  382 + belly = {x=36, y=29},
  383 + feet = {x=37, y=59},
  384 + hand1 = {x=10, y=18},
  385 + hand2 = {x=48, y=33},
  386 + head = {x=34, y=5},
  387 +}
  388 +tiles["npc/humanoid_human_urkis__the_high_tempest.png"] = { base=64,
  389 + back = {x=33, y=9},
  390 + belly = {x=33, y=24},
  391 + feet = {x=35, y=60},
356 392 hand1 = {x=13, y=32},
357   - head = {x=32, y=6},
  393 + hand2 = {x=51, y=29},
  394 + head = {x=33, y=-4},
358 395 }
359   -tiles["npc/humanoid_orc_orc_assassin.png"] = { base=64,
360   - feet = {x=36, y=60},
361   - hand1 = {x=4, y=30},
362   - hand2 = {x=40, y=3},
363   - belly = {x=42, y=29},
364   - back = {x=33, y=20},
365   - head = {x=24, y=11},
  396 +tiles["npc/humanoid_human_townsfolk_filthy_street_urchin01_64.png"] = { base=64,
  397 + back = {x=31, y=21},
  398 + belly = {x=33, y=32},
  399 + feet = {x=35, y=59},
  400 + hand1 = {x=12, y=32},
  401 + hand2 = {x=49, y=40},
  402 + head = {x=27, y=7},
366 403 }
367   -tiles["npc/humanoid_yaech_slaver.png"] = { base=64,
368   - feet = {x=46, y=58},
369   - hand1 = {x=16, y=28},
370