Thanks for the info everyone. I like the .fetch and default way!! I think I’m going to use that for now
I am using a Tuple because it works well for bracket notation access, its .to_json converts it into a string delimited list, and intertwines beautifully with db.query methods. Examples:
ItemQuery = "itemid, rpg_items_id, slot_position, q, equipped, sockets, identified, i_atk_speed, i_phys, i_crit_chance, crit_multiplier, i_hp, i_ms, i_cast_speed, in_item, socket_data, i_defense, to_life, quality, fire_res, cold_res, lightning_res, rare_name"
alias ItemTuple = {Int64, Int32, String, Int16, Int8, String, Int8, Int16, Int16, Int16, Int16, Int16, Int16, Int16, String, String, Int16, Int16, Int8, Int8, Int8, Int8, String}
def db_get_user_items(client, tabid = 0)
db.query_all "select #{ItemQuery} from rpg_user_items where rpg_character_id = ? and user_id = ? and in_stash = #{tabid} and hardcore = ? and ladder = ?", client.selected_characterid, client.user_id, client.hardcore, client.ladder, as: ItemTuple.types
end
I tried to use a class, but it became too convoluted. Had to maintain a DB.mapping, property macros, create custom overloads for bracket notation access (which I couldn’t figure out how to do), create a to_json overload to convert all ivars into a delimited string, etc. Just became too much. A Tuple seems to do more stuff out of the box for what I need, and seems more powerful.
I use classes a lot, I just don’t think using a class for this is a good idea with my current knowledge of Crystal.
I suspect that this could be more easily solved with a struct, though. How do you get your hash in the first place?
Depends on the type of item. I have static Hashes loaded that represent the modifications to select from based on what item is being used. In the example below, it’s ModGlobalWeapons or ModGlobalArmors. The data is stored in MYSQL and exported as csv, then converted into Hashes in Crystal.
Example:
when "transmute_orb"
raise "Item must be normal rarity." if current_item_mods.size > 0
mod_rolls = Array(String).new
query_update = QueryUpdate.new
if main_on_item["type"] == "Weapons"
mod_rolls = ModGlobalWeapons.dup
mod_rolls = mod_rolls.shuffle.first(2)
else # assume boots/armors
mod_rolls = ModGlobalArmors.dup
if main_on_item["type"] == "Gloves"
mod_rolls << "i_atk_speed"
end
mod_rolls = mod_rolls.shuffle.first(2)
end
mod_rolls.each do |mod_key|
mod_struct_main = GlobalItemModsMapping[mod_key]
mod_struct = mod_struct_main[mod_struct_main.keys.shuffle.first]
final_roll_value = rand(mod_struct.min_value..mod_struct.max_value)
query_update[mod_struct.mod_type] = final_roll_value
tuple_index = GlobalItemTuple.index(mod_struct.mod_type)
client.stash[tabid_on].items[on_itemid] = modify_item_tuple(client.stash[tabid_on].items[on_itemid], tuple_index, final_roll_value)
end
if query_update.size > 0
db.exec "update rpg_user_items set #{hash_to_delimited_query_list(query_update)} where itemid = ? and user_id = ?", on_itemid, client.user_id
client.send ({a: 4, new_data: query_update, q: new_item_quantity, on_itemid: on_itemid, itemid: incoming_itemid}), "ITEMUPDATE"
# Remove 1 quantity from the orb..
client.stash[tabid].items[incoming_itemid] = modify_item_tuple(item, 3, new_item_quantity)
else
raise "Item use failed.."
end