class Quest property current_talk_to_list = Array(Int32).new property current_kill_amount = 0 property date_accepted = 0_i64 JSON.mapping( current_talk_to_list: Array(Int32), current_kill_amount: Int32, date_accepted: Int64 ) def initialize(quest_id, current_talk_to_list2 = "", current_kill_amount2 = 0, @date_accepted = Time.local.to_unix_ms) return unless quest_obj = Quests[quest_id]? if quest_obj.quest_type == "talk_to" @current_talk_to_list = current_talk_to_list2.split(";").map &.to_i if current_talk_to_list2.size > 0 end @current_kill_amount = current_kill_amount2 # pp "Creating a quest object for the quest: #{quest_obj}" # pp self end end class GameServer def handle_quest_interact(msg, client) a = msg["message"]["a"].as_i # Accepting a Quest if a == 0 quest_id = msg["message"]["qid"].as_i return unless c_quest_obj = Quests[quest_id] return unless main_quest_obj = Quests[quest_id] raise "You already have this quest." if client.active_quests[quest_id]? raise "You already completed this quest!" if client.completed_quests.includes? quest_id raise "You don't have the required quest(s) for this quest." if (main_quest_obj.required_quests - client.completed_quests).size != 0 client.active_quests[quest_id] = Quest.new(quest_id) db.exec "insert into rpg_quest_tracker (character_id, quest_id, date_accepted) values (?, ?, ?)", client.selected_characterid, quest_id, Time.local.to_unix_ms # tell them.. client.send ({quest_id: quest_id, a: 0, data: client.active_quests[quest_id]}), "QUEST" if c_quest_obj.quest_type == "first_galactic" # spawn first galactic portal for this player pp "hez" end end # Abandoning a quest if a == 1 quest_id = msg["message"]["qid"].as_i return unless c_quest_obj = Quests[quest_id] raise "You can't abandon a quest you don't have?" if !client.completed_quests.includes? quest_id client.send ({quest_id: quest_id, a: 1}), "QUEST" end if a == 3 # clicking on quest reward item quest_id = msg["message"]["qid"].as_i raise "Invalid quest id." unless main_quest_obj = Quests[quest_id]? x = msg["message"]["x"].as_i y = msg["message"]["y"].as_i raise "You don't have this quest active." if !client.completed_quests.includes? quest_id raise "You already received the rewards for this quest." if client.completed_quests.count(quest_id) == 2 client.completed_quests << quest_id update_rpg_db_character(client) mods = QueryUpdate.new mods["pos"] = "#{x}x#{y}" new_duped_item = generate_item_by_id(main_quest_obj.quest_rewards.first, mods).to_a item_query = item_to_mysql_insert_query(new_duped_item, client) result = db.exec(item_query) new_duped_item[0] = result.last_insert_id client.stash[0].items[result.last_insert_id] = ItemTuple.from(new_duped_item) client.send ({a: 5, quest_id: quest_id, x: x, y: y, item: new_duped_item, new_itemid: 12345}), "QUEST" end # Talking to NPC if a == 2 incoming_npc_id = msg["message"]["npc_id"].as_i return unless npc_obj = NPCS[incoming_npc_id]? # Does this user have any quests where they need to talk to a specific npc? if client.active_quests.size > 0 client.active_quests.each do |quest_id, quest_obj| main_quest_obj = Quests[quest_id] # Does this player have any quest item ids that this quest object needs? if main_quest_obj.required_itemids.size > 0 client.stash[0].items.each do |k, v| i_item_id = v[1] if main_quest_obj.required_itemids.includes? i_item_id handle_quest_completion(client, main_quest_obj, quest_id) client.stash[0].items.delete k # no item anymore db.exec "delete from rpg_user_items where itemid = ? and user_id = ?", k, client.user_id client.send ({a: 6, q: 0, itemid: k}), "ITEMUPDATE" break end end end if main_quest_obj.quest_type == "talk_to" # They talked to a NPC! if !quest_obj.current_talk_to_list.includes? npc_obj.npc_id quest_obj.current_talk_to_list << npc_obj.npc_id db.exec "update rpg_quest_tracker set current_talk_to_list = ? where character_id = ?", quest_obj.current_talk_to_list.join(";"), client.selected_characterid client.send ({a: 2, quest_id: quest_id, data: quest_obj.current_talk_to_list}), "QUEST" pp "You have talked to this NPC!" # Have they completed the talk to quest? # 3 = QuestCompleted. main_talk_to_list = main_quest_obj.talk_to_list.split(";").map &.to_i if (main_talk_to_list - quest_obj.current_talk_to_list).empty? handle_quest_completion(client, main_quest_obj, quest_id) end end end end end end rescue e client.send e.message, "E" end # When a player loads into the gameserver, we need to update the active_quests hash with current quests def update_rpg_quest_tracker(client) results = db.query_all "select quest_id, current_talk_to_list, current_kill_amount, date_accepted from rpg_quest_tracker where character_id = ?", client.selected_characterid, as: {Int32, String, Int32, Int64} results.each do |obj| quest_id, current_talk_to_list, current_kill_amount, date_accepted = obj # append the active quests this user has.. client.active_quests[quest_id] = Quest.new(quest_id, current_talk_to_list, current_kill_amount, date_accepted) end end def handle_quest_item_must_be_looted(item_id, client) client.active_quests.each do |quest_id, quest_obj| next unless main_quest_obj = Quests[quest_id] case main_quest_obj.quest_type when "item_must_be_looted" if main_quest_obj.items_to_drop.includes? item_id # it's complete! handle_quest_completion(client, main_quest_obj, quest_id) end end end end # Quest Completion and rewards... # quest_rewards should be a delimited list (;) of the item ids. def handle_quest_completion(client, main_quest_obj, quest_id, item_x = nil, item_y = nil) client.completed_quests << quest_id client.active_quests.delete quest_id return unless zone = client.in_zone_obj item_x = client.x if !item_x item_y = client.y if !item_y db.exec "update rpg_characters set completed_quests = ? where character_id = ?", client.completed_quests.join(";"), client.selected_characterid db.exec "delete from rpg_quest_tracker where quest_id = ? and character_id = ?", quest_id, client.selected_characterid client.send ({a: 3, quest_id: quest_id}), "QUEST" # Special Quests.. first galactic? if (quest_id == 11) zone.galactic_device = GalacticDevice.new(zone.level_info.galactic_device_pos.x, zone.level_info.galactic_device_pos.y) if galactic_device = zone.galactic_device zone.send_to_players ({scene_name: "galactic_device", cdata: "", x: galactic_device.x, y: galactic_device.y}), "ENTITY_U" end end # Does the quest give any experience? give_exp(client, main_quest_obj.quest_exp) # Does this quest have any rewards? if quest_id == 8 # take a look around. Special case. Scroll of Wisdom and a rare/magic short axe if scroll_of_wisdom = generate_item_by_id(42) zone.drop_item(scroll_of_wisdom, item_x, item_y) end mods = QueryUpdate.new mod_rolls = Array(String).new current_mod_count = 2 mod_rolls << select_random_weapon_prefix.mod_type mod_rolls << select_random_weapon_suffix.mod_type if rand < (0.5) # roll for a rare? mod_rolls << (ModGlobalWeapons.shuffle - mod_rolls).first current_mod_count += 1 end mods["identified"] = 0 mods["rare_name"] = generate_rare_name("Weapons") if current_mod_count > 2 mod_rolls.each do |mod_key| mod_struct = GlobalItemModsMapping[mod_key].select { |v| rand < v.mod_chance }.last final_roll_value = rand(mod_struct.min_value..mod_struct.max_value) mods[mod_struct.mod_type] = final_roll_value end if short_axe = generate_item_by_id(40, mods) zone.drop_item(short_axe, item_x, item_y) end else if main_quest_obj.must_talk_to_receive_reward == 0 main_quest_obj.quest_rewards.each do |item_id| if item = generate_item_by_id(item_id) drop_generated_item(client, item, item_x, item_y) end end end end rescue e pp "Error Handling Quest Completion:" pp e end end