Lots of refactoring of armor, weapons, character stats, etc.

This commit is contained in:
Martin Haye 2016-06-12 13:12:14 -07:00
parent 1122108e75
commit 944935c4a2
7 changed files with 96 additions and 166 deletions

View File

@ -1688,7 +1688,7 @@ class PackPartitions
def name = row.@name
withContext(name)
{
out.println("def NE_${humanNameToSymbol(name, false)}()")
out.println("def NEn_${humanNameToSymbol(name, false)}()")
def image1 = row.@image1
if (!portraitNames.contains(humanNameToSymbol(image1, false)))
@ -1758,32 +1758,14 @@ class PackPartitions
// Pre-define all the enemy creation functions
sheet.rows.row.each { row ->
out.println("predef NE_${humanNameToSymbol(row.@name, false)}")
out.println("predef NEn_${humanNameToSymbol(row.@name, false)}")
}
// Figure out the mapping between "map code" and "enemy"
// Figure out the mapping between "map code" and "enemy", and output the table for that
def codeToFunc = [:]
sheet.rows.row.each { row ->
def name = row.@name
def mapCodes = row.@"map-code".replace("\"", "")
mapCodes.split(",").collect{it.trim()}.grep{it!=""}.each { code ->
if (!codeToFunc.containsKey(code))
codeToFunc[code] = []
codeToFunc[code] << "NE_${humanNameToSymbol(name, false)}"
}
}
// Output that.
codeToFunc.sort().each { code, funcs ->
out.print("word[] ct_${humanNameToSymbol(code, false)} = ")
funcs.eachWithIndex { func, index ->
if (index > 0)
out.print(", ")
out.print("@$func")
}
out.println()
}
out.println()
addCodeToFunc("NEn_${humanNameToSymbol(row.@name, false)}", row.@"map-code", codeToFunc) }
outCodeToFuncTbl("ct_", codeToFunc, out)
// Now output a function for each enemy
sheet.rows.row.each { row ->
@ -1791,21 +1773,8 @@ class PackPartitions
}
out.println()
// Utility func
out.println("def randFrom(arr, siz)")
out.println(" return *(((rand16() % siz) << 1) + arr)")
out.println("end\n")
// And finally, a function to select an enemy given a map code.
out.println("def _enemy_forZone(mapCode)")
codeToFunc.sort().each { code, funcs ->
out.println(" if strcmpi(mapCode, \"$code\") == 0; ")
out.println(" return randFrom(@ct_${humanNameToSymbol(code, false)}, ${funcs.size()})")
out.println(" fin")
}
out.println(" puts(mapCode)")
out.println(" fatal(\"No enemies match\")")
out.println("end\n")
outCodeToFuncMethod("_enemy_forZone", "ct_", codeToFunc, out)
out.println("return @funcTbl")
out.println("done")
@ -1835,30 +1804,55 @@ class PackPartitions
out.println " //item name=${row.@name}"
}
def addCodeToFunc(func, codesString, addTo)
def addCodeToFunc(funcName, codesString, addTo)
{
if (codesString == null)
if (codesString == null || codesString.length() == 0)
return
codesString.replace("\"", "").split(",").collect{it.trim()}.grep{it!=""}.each { code ->
if (!addTo.containsKey(code))
addTo[code] = []
addTo[code] << func
addTo[code] << funcName
}
}
def outCodeToFuncTbl(prefix, codeToFunc, out)
{
codeToFunc.sort().each { code, funcs ->
out.print("word[] $prefix${humanNameToSymbol(code, false)} = ")
funcs.eachWithIndex { func, index ->
out.print("${index>0 ? ", " : ""}@$func")
}
out.println()
}
out.println()
}
def outCodeToFuncMethod(funcName, prefix, codeToFunc, out)
{
out.println("def $funcName(code)")
codeToFunc.sort().each { code, funcs ->
out.println(" if strcmpi(code, \"$code\") == 0; ")
out.println(" return randomFromArray(@ct_${humanNameToSymbol(code, false)}, ${funcs.size()})")
out.println(" fin")
}
out.println(" puts(code)")
out.println(" fatal(\"No code match\")")
out.println("end\n")
}
def genAllItems(sheets)
{
// Grab all the raw data
def funcs = []
sheets.find { it?.@name.equalsIgnoreCase("weapons") }.rows.row.each { row ->
funcs << ["weapon", "new_weapon_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
funcs << ["weapon", "NWp_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
sheets.find { it?.@name.equalsIgnoreCase("armor") }.rows.row.each { row ->
funcs << ["armor", "new_armor_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
funcs << ["armor", "NAr_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
sheets.find { it?.@name.equalsIgnoreCase("ammo") }.rows.row.each { row ->
funcs << ["ammo", "new_ammo_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
funcs << ["ammo", "NAm_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
sheets.find { it?.@name.equalsIgnoreCase("items") }.rows.row.each { row ->
funcs << ["item", "new_item_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
funcs << ["item", "NIt_${humanNameToSymbol(row.@name, false)}", funcs.size, row] }
// Build up the mappings from loot codes and store codes to creation functions
def lootCodeToFuncs = [:]

View File

@ -89,8 +89,8 @@ def playerShoot(pPlayer, pWeapon)
// Add in skill modifier, if any
pSkill = pPlayer=>p_skills
while pSkill
if pSkill=>b_modKind == pWeapon=>b_itemKind
chance = chance + pSkill=>b_modValue
if pSkill=>s_name == pWeapon=>s_itemKind
chance = chance + pSkill=>w_modValue
fin
pSkill = pSkill=>p_nextObj
loop
@ -367,7 +367,7 @@ def determineCombatOrder()
if canFight(p)
p->b_combatOrder = rand16() % (p->b_agility * 10)
combatInsert(p)
if (!(p=>b_playerFlags & PLAYER_FLAG_NPC)) // only count real players
if (!(p->b_playerFlags & PLAYER_FLAG_NPC)) // only count real players
nPlayersFighting = nPlayersFighting + 1
fin
fin

View File

@ -110,11 +110,11 @@ const pause = gameLibVecs + 3*49
const tossStrings = gameLibVecs + 3*50
const showMapName = gameLibVecs + 3*51
const setMapWindow = gameLibVecs + 3*52
const UNUSED_FN_53 = gameLibVecs + 3*53
const UNUSED_FN_54 = gameLibVecs + 3*54
const UNUSED_FN_55 = gameLibVecs + 3*55
const UNUSED_FN_56 = gameLibVecs + 3*56
const UNUSED_FN_57 = gameLibVecs + 3*57
const makeModifier = gameLibVecs + 3*53
const makeArmor = gameLibVecs + 3*54
const makeWeapon_pt1 = gameLibVecs + 3*55
const makeWeapon_pt2 = gameLibVecs + 3*56
const randomFromArray = gameLibVecs + 3*57
const UNUSED_FN_58 = gameLibVecs + 3*58
const UNUSED_FN_59 = gameLibVecs + 3*59
const UNUSED_FN_60 = gameLibVecs + 3*60

View File

@ -110,6 +110,7 @@ predef _showParty, _mmgr, _setWindow1, _setWindow2, _setWindow3
predef _reboot, _brk, _encodeDice, _rollDice
predef _setPlural, _makeEnemy, _getStringResponse, _strcmpi, _addEncounterZone, _fatal
predef _pause, _tossStrings, _showMapName, _setMapWindow
predef _makeModifier, _makeArmor, _makeWeapon_pt1, _makeWeapon_pt2, _randomFromArray
word gameLib_addrs = @_setScriptInfo, @_scriptDisplayStr, @_scriptDisplayStrNL, @_getYN
word = @_queue_setMap, @_setSky, @_setGround, @_queue_teleport, @_setPortrait, @_clearPortrait
@ -124,6 +125,7 @@ word = @_showParty, @_mmgr, @_setWindow1, @_setWindow2, @_setWindow3
word = @_reboot, @_brk, @_encodeDice, @_rollDice
word = @_setPlural, @_makeEnemy, @_getStringResponse, @_strcmpi, @_addEncounterZone, @_fatal
word = @_pause, @_tossStrings, @_showMapName, @_setMapWindow
word = @_makeModifier, @_makeArmor, @_makeWeapon_pt1, @_makeWeapon_pt2, @_randomFromArray
word = 0 // end of library functions
@ -2139,23 +2141,23 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Return a random entry from an array, given its size in number of elements.
def randFrom(arr, siz)
def _randomFromArray(arr, siz)
return *(((rand16() % siz) << 1) + arr)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def makeModifier(kind, value)
def _makeModifier(name, value)
word p; p = mmgr(HEAP_ALLOC, TYPE_MODIFIER)
p->b_modKind = kind
p->b_modValue = value
p=>s_name = mmgr(HEAP_INTERN, name)
p=>w_modValue = value
return p
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def makeArmor(name, kind, cost, armorValue, modifier)
def _makeArmor(name, kind, cost, armorValue, modifier)
word p; p = mmgr(HEAP_ALLOC, TYPE_ARMOR)
p=>s_name = mmgr(HEAP_INTERN, name)
p->b_itemKind = kind
p=>s_itemKind = mmgr(HEAP_INTERN, kind)
p=>w_cost = cost
p->b_armorValue = armorValue
p=>p_modifiers = modifier
@ -2163,12 +2165,12 @@ def makeArmor(name, kind, cost, armorValue, modifier)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def makeWeapon_pt1(name, kind, cost, ammoKind, clipSize, meleeDmg, projectileDmg)
def _makeWeapon_pt1(name, kind, cost, ammoKind, clipSize, meleeDmg, projectileDmg)
word p; p = mmgr(HEAP_ALLOC, TYPE_WEAPON)
p=>s_name = mmgr(HEAP_INTERN, name)
p->b_itemKind = kind
p=>s_itemKind = mmgr(HEAP_INTERN, kind)
p=>w_cost = cost
p->b_ammoKind = ammoKind
p=>s_ammoKind = mmgr(HEAP_INTERN, ammoKind)
p->b_clipSize = clipSize
p->b_clipCurrent = clipSize
p=>r_meleeDmg = meleeDmg
@ -2177,7 +2179,7 @@ def makeWeapon_pt1(name, kind, cost, ammoKind, clipSize, meleeDmg, projectileDmg
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def makeWeapon_pt2(p, modifier, attack0, attack1, attack2, weaponRange, combatText)
def _makeWeapon_pt2(p, modifier, attack0, attack1, attack2, weaponRange, combatText)
p->ba_attacks[0] = attack0
p->ba_attacks[1] = attack1
p->ba_attacks[2] = attack2

View File

@ -12,11 +12,11 @@ include "gamelib.plh"
include "playtype.plh"
include "gen_images.plh"
predef new_Modifier, new_Armor_Chaps, new_Armor_ShamanHeaddress, new_Armor_TahnkuPants, new_Armor_TahnkuVest
predef new_Armor_Chaps, new_Armor_ShamanHeaddress, new_Armor_TahnkuPants, new_Armor_TahnkuVest
predef new_Weapon_Handgun, new_Weapon_SpiritBow, new_Weapon_SpiritBlade, calcPlayerArmor
predef new_Player_Hue_Hauser, new_Player_Mokahnu
word[] funcTbl = @new_Modifier, @new_Armor_Chaps, @new_Armor_ShamanHeaddress, @new_Armor_TahnkuPants, @new_Armor_TahnkuVest
word[] funcTbl = @new_Armor_Chaps, @new_Armor_ShamanHeaddress, @new_Armor_TahnkuPants, @new_Armor_TahnkuVest
word = @new_Weapon_Handgun, @new_Weapon_SpiritBow, @new_Weapon_SpiritBlade, @calcPlayerArmor
word = @new_Player_Hue_Hauser, @new_Player_Mokahnu
@ -25,7 +25,7 @@ def new_Armor_Chaps
word p
p = mmgr(HEAP_ALLOC, TYPE_ARMOR)
p=>s_name = mmgr(HEAP_INTERN, "Chaps")
p->b_itemKind = KIND_PANTS
p=>s_itemKind = mmgr(HEAP_INTERN, "pants")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_armorValue = 2
@ -37,7 +37,7 @@ def new_Armor_ShamanHeaddress()
word p
p = mmgr(HEAP_ALLOC, TYPE_ARMOR)
p=>s_name = mmgr(HEAP_INTERN, "Shaman Headdress(es)")
p->b_itemKind = KIND_HAT
p=>s_itemKind = mmgr(HEAP_INTERN, "hat(s)")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_armorValue = 2
@ -49,7 +49,7 @@ def new_Armor_TahnkuPants()
word p
p = mmgr(HEAP_ALLOC, TYPE_ARMOR)
p=>s_name = mmgr(HEAP_INTERN, "Tahnku Pants")
p->b_itemKind = KIND_PANTS
p=>s_itemKind = mmgr(HEAP_INTERN, "pants")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_armorValue = 2
@ -61,7 +61,7 @@ def new_Armor_TahnkuVest()
word p
p = mmgr(HEAP_ALLOC, TYPE_ARMOR)
p=>s_name = mmgr(HEAP_INTERN, "Tahnku Vest(s)")
p->b_itemKind = KIND_SHIRT
p=>s_itemKind = mmgr(HEAP_INTERN, "shirt(s)")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_armorValue = 2
@ -73,10 +73,10 @@ def new_Weapon_Handgun
word p
p = mmgr(HEAP_ALLOC, TYPE_WEAPON)
p=>s_name = mmgr(HEAP_INTERN, "Handgun")
p->b_itemKind = KIND_HANDGUN
p=>s_itemKind = mmgr(HEAP_INTERN, "handgun(s)")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_ammoKind = KIND_BULLET
p=>s_ammoKind = mmgr(HEAP_INTERN, "Bullet(s)")
p->b_clipSize = 6
p->b_clipCurrent = p->b_clipSize
p=>r_meleeDmg = encodeDice(1, 6, 0) // 1d6
@ -92,10 +92,10 @@ def new_Weapon_SpiritBow
word p
p = mmgr(HEAP_ALLOC, TYPE_WEAPON)
p=>s_name = mmgr(HEAP_INTERN, "Spirit Bow")
p->b_itemKind = KIND_BOW
p=>s_itemKind = mmgr(HEAP_INTERN, "bow(s)")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_ammoKind = KIND_ARROW
p=>s_ammoKind = mmgr(HEAP_INTERN, "Arrow(s)")
p->b_clipSize = 12
p->b_clipCurrent = p->b_clipSize
p=>r_meleeDmg = encodeDice(3, 6, 0) // 3d6
@ -112,10 +112,10 @@ def new_Weapon_SpiritBlade
word p
p = mmgr(HEAP_ALLOC, TYPE_WEAPON)
p=>s_name = mmgr(HEAP_INTERN, "Spirit Blade")
p->b_itemKind = KIND_BOW
p=>s_itemKind = mmgr(HEAP_INTERN, "blade(s)")
p=>w_cost = -99 // for now
// no modifiers, max uses, etc. for now
p->b_ammoKind = 0
p=>s_ammoKind = NULL
p->b_clipSize = 0
p->b_clipCurrent = p->b_clipSize
p=>r_meleeDmg = encodeDice(7, 6, 0) // 7d6
@ -158,13 +158,10 @@ def new_Player_Hue_Hauser
// Basic skills
p->b_aiming = 2
p->b_dodging = 3
p->b_wilderness = 5
// Skills
addToList(p + p_skills, new_Modifier(KIND_MINING, 0))
addToList(p + p_skills, new_Modifier(KIND_NATIVE_BOND, 0))
addToList(p + p_skills, new_Modifier(KIND_PYRE_WARE, 0))
addToList(p + p_skills, new_Modifier(KIND_HANDGUN, 1))
addToList(p + p_skills, makeModifier("wilderness", 5))
addToList(p + p_skills, makeModifier("handgun(s)", 1))
// Items
addToList(p + p_items, new_Armor_Chaps())
@ -200,16 +197,13 @@ def new_Player_Mokahnu
// Basic skills
p->b_aiming = 4
p->b_dodging = 3
p->b_wilderness = 5
// Skills
addToList(p + p_skills, new_Modifier(KIND_MINING, 0))
addToList(p + p_skills, new_Modifier(KIND_NATIVE_BOND, 10))
addToList(p + p_skills, new_Modifier(KIND_PYRE_WARE, 0))
addToList(p + p_skills, new_Modifier(KIND_BLADE, 3))
addToList(p + p_skills, new_Modifier(KIND_BOW, 3))
addToList(p + p_skills, new_Modifier(KIND_RIFLE, 3))
addToList(p + p_skills, new_Modifier(KIND_BLADE, 3))
addToList(p + p_skills, makeModifier("wilderness", 5))
addToList(p + p_skills, makeModifier("native bond", 10))
addToList(p + p_skills, makeModifier("blade(s)", 3))
addToList(p + p_skills, makeModifier("bow(s)", 3))
addToList(p + p_skills, makeModifier("rifle(s)", 3))
// Items
addToList(p + p_items, new_Armor_ShamanHeaddress())

View File

@ -8,14 +8,15 @@
// governing permissions and limitations under the License.
///////////////////////////////////////////////////////////////////////////////////////////////////
// Garbage collection pointer offsets within each type
byte typeTbl_Global[] = Global, p_players, p_enemyGroups, p_combatFirst, p_encounterZones, 0
byte typeTbl_Player[] = Player, p_nextObj, s_name, p_combatNext, p_skills, p_items, p_buffs, p_debuffs, 0
byte typeTbl_Modifier[] = Modifier, p_nextObj, 0
byte typeTbl_Effect[] = Effect, p_nextObj, s_effectDescrip, 0
byte typeTbl_Item[] = Item, p_nextObj, s_name, p_modifiers, 0
byte typeTbl_Weapon[] = Weapon, p_nextObj, s_name, p_modifiers, s_combatText, 0
byte typeTbl_Armor[] = Armor, p_nextObj, s_name, p_modifiers, 0
byte typeTbl_Stuff[] = Stuff, p_nextObj, s_name, 0
byte typeTbl_Player[] = Player, p_nextObj, s_name, p_combatNext, p_skills, p_items, p_effects, 0
byte typeTbl_Modifier[] = Modifier, p_nextObj, s_name, 0
byte typeTbl_Effect[] = Effect, p_nextObj, s_name, 0
byte typeTbl_Item[] = Item, p_nextObj, s_name, s_itemKind, p_modifiers, 0
byte typeTbl_Weapon[] = Weapon, p_nextObj, s_name, s_itemKind, p_modifiers, s_combatText, 0
byte typeTbl_Armor[] = Armor, p_nextObj, s_name, s_itemKind, p_modifiers, 0
byte typeTbl_Stuff[] = Stuff, p_nextObj, s_name, s_itemKind, 0
byte typeTbl_Enemy[] = Enemy, p_nextObj, s_name, p_combatNext, s_attackText, 0
byte typeTbl_EnemyGroup[] = EnemyGroup, p_nextObj, p_enemies, 0
byte typeTbl_EncounterZone[] = EncounterZone, p_nextObj, s_name, 0
@ -24,35 +25,3 @@ word typeTbls = @typeTbl_Global, @typeTbl_Player, @typeTbl_Modifier, @typeTbl_Ef
word = @typeTbl_Weapon, @typeTbl_Armor, @typeTbl_Stuff, @typeTbl_Enemy, @typeTbl_EnemyGroup
word = @typeTbl_EncounterZone
word = 0
byte[] kind_bow_str = "bow(s)"
byte[] kind_blade_str = "blade(s)"
byte[] kind_explosive_str = "explosive(s)"
byte[] kind_handgun_str = "handgun(s)"
byte[] kind_hand_to_hand_str = "hand to hand"
byte[] kind_rifle_str = "rifle(s)"
byte[] kind_throwing_str = "throwing"
byte[] kind_mining_str = "mining"
byte[] kind_native_bond_str = "native bond"
byte[] kind_pyre_ware_str = "pyre ware"
byte[] kind_bullet_str = "bullet(s)"
byte[] kind_arrow_str = "arrow(s)"
byte[] kind_buck_str = "buck"
byte[] kind_quarrel_str = "quarrel(s)"
byte[] kind_shoes_str = "shoes"
byte[] kind_coat_str = "coat(s)"
byte[] kind_hat_str = "hat(s)"
byte[] kind_pants_str = "pants"
byte[] kind_shirt_str = "shirt(s)"
byte[] kind_gloves_str = "gloves"
byte[] kind_shield_str = "shield(s)"
// Text table for translating a kind to a string
word[] kinds = @kind_bow_str, @kind_blade_str, @kind_explosive_str, @kind_handgun_str, @kind_hand_to_hand_str, @kind_rifle_str, @kind_throwing_str
word = @kind_mining_str, @kind_native_bond_str, @kind_pyre_ware_str
word = @kind_bullet_str, @kind_arrow_str, @kind_buck_str, @kind_quarrel_str
word = @kind_shoes_str, @kind_coat_str, @kind_hat_str, @kind_pants_str, @kind_shirt_str, @kind_gloves_str, @kind_shield_str
word = NULL

View File

@ -50,10 +50,9 @@ struc Player
// Calculated attributes
byte b_armor
// Basic skills
// Basic skills (much like attributes)
byte b_aiming
byte b_dodging
byte b_wilderness
// Status
word w_maxHealth
@ -63,8 +62,7 @@ struc Player
// Lists
word p_skills // list:Modifier
word p_items // list:Item
word p_buffs // list:Effect
word p_debuffs // list:Effect
word p_effects // list:Effect
end
// Combat skills, weapon modifiers, etc.
@ -72,8 +70,8 @@ const TYPE_MODIFIER = $82
struc Modifier
byte t_type
word p_nextObj
byte b_modKind
byte b_modValue
word s_name
word w_modValue
end
// Buffs and debuffs, that last until a specified time
@ -81,9 +79,8 @@ const TYPE_EFFECT = $83
struc Effect
byte t_type
word p_nextObj
byte b_modKind
byte b_modValue
word s_effectDescrip
byte s_name
word w_modValue
word w_endTurn
end
@ -92,7 +89,7 @@ struc Item
byte t_type
word p_nextObj
word s_name
byte b_itemKind
word s_itemKind
word w_cost
word p_modifiers // list:modifier
end
@ -106,7 +103,7 @@ struc Weapon
byte t_type
word p_nextObj
word s_name
byte b_itemKind
word s_itemKind
word w_cost
word p_modifiers // list:modifier
// Usables properties
@ -114,7 +111,7 @@ struc Weapon
byte b_curUses
// Weapon properties
byte b_weaponFlags // WEAPON_FLAG_* above
byte b_ammoKind
word s_ammoKind
byte b_clipSize
byte b_clipCurrent
word r_meleeDmg // 3 hex digits: num dice, die size, add. E.g. $361 = 3d6+1
@ -130,7 +127,7 @@ struc Armor
byte t_type
word p_nextObj
word s_name
byte b_itemKind
word s_itemKind
word w_cost
word p_modifiers // list:modifier
// Usables properties
@ -147,7 +144,7 @@ struc Stuff
byte t_type
word p_nextObj
word s_name
byte b_itemKind
word s_itemKind
word w_cost
// Stuff properties
word w_count
@ -191,29 +188,3 @@ struc EncounterZone
word w_encMaxDist
word w_encChance
end
// Weapon kinds
const KIND_BOW = 1;
const KIND_BLADE = 2;
const KIND_EXPLOSIVE = 3;
const KIND_HANDGUN = 4;
const KIND_HAND_TO_HAND = 5;
const KIND_RIFLE = 6;
const KIND_THROWING = 7;
// Skill kinds
const KIND_MINING = 8;
const KIND_NATIVE_BOND = 9;
const KIND_PYRE_WARE = 10
// Ammo kinds
const KIND_BULLET = 11
const KIND_ARROW = 12
const KIND_BUCK = 13
const KIND_QUARREL = 14
// Armor kinds
const KIND_SHOES = 15
const KIND_COAT = 16
const KIND_HAT = 17
const KIND_PANTS = 18
const KIND_SHIRT = 19
const KIND_GLOVES = 20
const KIND_SHIELD = 21