void GameInstSet::deserialize(GameState* gs, SerializeBuffer& serializer) { serializer.read_int(grid_w); serializer.read_int(grid_h); //Resize and clear unit_grid.resize(grid_w * grid_h); clear(); int amnt; serializer.read_int(amnt); serializer.read_int(next_id); for (int i = 0; i < amnt; i++) { InstType type; int id; serializer.read_int(type); serializer.read_int(id); printf("Deserializing id=%d\n", id); GameInst* inst = get_instance(id); bool has_inst = inst != NULL; if (!has_inst) { inst = from_inst_type(type); inst->deserialize(gs, serializer); inst->last_x = inst->x; inst->last_y = inst->y; inst->id = id; add_instance(inst, inst->id); } else { safe_deserialize(inst, gs, serializer); } LANARTS_ASSERT( serializer_equals_read(serializer, inst->integrity_hash())); } }
unsigned int GameInstSet::hash() const { unsigned int hash = 0xbabdabe; std::vector<GameInst*> as_vector = to_vector(); for (int i = 0; i < as_vector.size(); i++) { GameInst* inst = as_vector[i]; if (!dynamic_cast<AnimatedInst*>(inst)) { hash ^= inst->integrity_hash(); hash ^= hash * 31337; //Ad hoc hashing yay } } return hash; }
void GameInstSet::clear() { for (int i = 0; i < unit_capacity; i++) { GameInst* inst = unit_set[i].inst; if (valid_inst(inst)) { inst->free_reference(); } } next_id = 1; unit_amnt = 0; depthlist_map.clear(); memset(&unit_set[0], 0, unit_capacity * sizeof(InstanceState)); memset(&unit_grid[0], 0, grid_w * grid_h * sizeof(InstanceLinkedList)); }
GameInstSet::~GameInstSet() { for (int i = 0, j = 0; i < unit_capacity; i++) { GameInst* inst = unit_set[i].inst; if (valid_inst(inst)) { inst->free_reference(); } } for (int i = 0; i < deallocation_list.size(); i++) { deallocation_list[i]->free_reference(); } }
void GameInstSet::step(GameState* gs) { for (int i = 0; i < deallocation_list.size(); i++) { deallocation_list[i]->free_reference(); } deallocation_list.clear(); for (int i = 0; i < unit_capacity; i++) { GameInst* inst = unit_set[i].inst; if (valid_inst(inst)) { inst->destroyed = false; inst->step(gs); update_instance_for_step(&unit_set[i], inst); } } }
static void process_level_hash(GameState* gs, GameLevelState* level, SerializeBuffer& sb, bool isw) { if (level->id() == -1) return; std::vector<GameInst*> instances = level->game_inst_set().to_vector(); for (int i = 0; i < instances.size(); i++) { GameInst* inst = instances[i]; if (!dynamic_cast<AnimatedInst*>(inst)) { write_or_assert_hash(sb, inst->integrity_hash(), isw); } } //compare magic number marker write_or_assert_hash(sb, 0xABCDFFFF, isw); write_or_assert_hash(sb, level->game_inst_set().hash(), isw); }
void GameInstSet::serialize(GameState* gs, SerializeBuffer& serializer) { serializer.write_int(grid_w); serializer.write_int(grid_h); serializer.write_int(size()); serializer.write_int(next_id); DepthMap::const_iterator it = depthlist_map.end(); for (int ind = 0; it != depthlist_map.begin();) { --it; InstanceState* state = it->second.start_of_list; while (state) { GameInst* inst = state->inst; serializer.write_int(get_inst_type(inst)); serializer.write_int(inst->id); inst->serialize(gs, serializer); serializer.write_int(inst->integrity_hash()); state = state->next_same_depth; } } }
void GameInstSet::copy_to(GameInstSet& inst_set) const { DepthMap::const_iterator it = depthlist_map.end(); //Synch live objects for (int ind = 0; it != depthlist_map.begin();) { --it; InstanceState* state = it->second.start_of_list; while (state) { GameInst* inst = state->inst; obj_id id = inst->id; GameInst* oinst = inst_set.get_instance(id); if (oinst == NULL || typeid(inst) != typeid(oinst)) { inst_set.add_instance(inst->clone(), id); if (oinst) oinst->destroyed = true; } state = state->next_same_depth; } } //Remove dead objects for (int i = 0; i < inst_set.unit_capacity; i++) { InstanceState* state = &inst_set.unit_set[i]; GameInst* oinst = state->inst; if (valid_inst(oinst)) { if (!oinst->destroyed) { GameInst* inst = get_instance(oinst->id); if (inst != NULL) { inst_set.__update_collision_position(state, Pos(oinst->x, oinst->y), Pos(inst->x, inst->y)); inst->copy_to(oinst); } else inst_set.__remove_instance(state); inst->free_reference(); } } } inst_set.next_id = this->next_id; LANARTS_ASSERT(check_copy_integrity(inst_set)); }
// dx & dy indicates moving direction, useful for choosing melee attack targets bool PlayerInst::enqueue_io_spell_and_attack_actions(GameState* gs, float dx, float dy) { GameView& view = gs->view(); WeaponEntry& wentry = weapon().weapon_entry(); bool mouse_within = gs->mouse_x() < gs->view().width; int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y(); int level = gs->get_level()->id(), frame = gs->frame(); bool is_moving = (dx != 0.0f || dy != 0.0f); IOController& io = gs->io_controller(); bool attack_used = enqueue_io_spell_actions(gs); bool autotarget = io.query_event(IOEvent::AUTOTARGET_CURRENT_ACTION) || io.query_event(IOEvent::ACTIVATE_SPELL_N); bool mousetarget = io.query_event(IOEvent::MOUSETARGET_CURRENT_ACTION); bool weaponuse = spell_selected() == -1; // choose & use weapon if (io.query_event(IOEvent::USE_WEAPON)) { queued_actions.push_back( game_action(gs, this, GameAction::CHOSE_SPELL, -1)); autotarget = true; weaponuse = true; } if (spell_selected() >= 0 && spells_known().get_entry(spell_selected()).mp_cost > core_stats().mp) { weaponuse = true; } // weapon use if (!attack_used && weaponuse && (autotarget || mousetarget)) { bool is_projectile = wentry.uses_projectile || equipment().has_projectile(); MonsterController& mc = gs->monster_controller(); GameInst* curr_target = gs->get_instance(current_target); GameInst* target = NULL; Pos targ_pos; if (is_projectile) { if (mousetarget) { targ_pos = Pos(rmx, rmy); } else if (autotarget && curr_target) { targ_pos = curr_target->pos(); } } else { if (mousetarget) { dx = rmx - x, dy = rmy - y; } target = get_weapon_autotarget(gs, this, curr_target, dx, dy); if (target) { targ_pos = Pos(target->x, target->y); } if (!is_moving && !target && !mousetarget && spell_selected() == -1 && curr_target && !is_projectile) { int vx, vy; GameInst* closest = get_closest_monster(gs, this); if (closest && decide_attack_movement(pos(), closest->pos(), TILE_SIZE / 4, vx, vy)) { queued_actions.push_back( game_action(gs, this, GameAction::MOVE, spellselect, round(vx), round(vy))); } } } if (target || (is_projectile && (mousetarget || curr_target))) { queued_actions.push_back( game_action(gs, this, GameAction::USE_WEAPON, spellselect, targ_pos.x, targ_pos.y)); attack_used = true; } } return attack_used; }
/* Helper method for drawing basic stat information*/ static void draw_player_base_stats(GameState* gs, PlayerInst* player_inst, int x, int y, int width) { ClassStats& class_stats = player_inst->class_stats(); CoreStats& core = player_inst->effective_stats().core; int x_interval = width / 2; int y_interval = 15; gs->font().drawf(ldraw::DrawOptions(COL_WHITE).origin(ldraw::CENTER), Pos(x - 10 + x_interval, 15), "Level %d", class_stats.xplevel); // y += y_interval; Pos p1(x, y), p2(x + x_interval, y); gs->font().drawf(COL_WHITE, Pos(x, y), "Kills %d", player_inst->score_stats().kills); if (gs->game_settings().regen_on_death) { gs->font().drawf(COL_PALE_RED, Pos(x + x_interval, y), "Deaths %d", player_inst->score_stats().deaths); } else { gs->font().draw(COL_PALE_BLUE, Pos(x + x_interval, y), "Hardcore"); } p1.y += y_interval; p2.y += y_interval; gs->font().drawf(COL_WHITE, p1, "%s", gs->get_level()->label().c_str()); gs->font().drawf(COL_GOLD, p2, "Gold %d", player_inst->gold()); p1.y += y_interval; p2.y += y_interval; gs->font().drawf(COL_MUTED_GREEN, p1, "Strength %d", core.strength); gs->font().drawf(COL_MUTED_GREEN, p2, "Magic %d", core.magic); p1.y += y_interval; p2.y += y_interval; gs->font().drawf(COL_MUTED_GREEN, p1, "Defence %d", core.defence); gs->font().drawf(COL_MUTED_GREEN, p2, "Will %d", core.willpower); p1.y += y_interval; p2.y += y_interval; // Draw hashes if in network debug mode if (gs->game_settings().network_debug_mode) { // Draw level hash gs->font().drawf(COL_MUTED_GREEN, p1, "Hash 0x%X", gs->get_level()->game_inst_set().hash()); p1.y += y_interval; // Draw player hashes for (int i = 0; i < gs->player_data().all_players().size(); i++) { unsigned int hash = gs->player_data().all_players()[i].player()->integrity_hash(); gs->font().drawf(COL_MUTED_GREEN, p1, "P%d 0x%X", i + 1, hash); p1.y += y_interval; } // Draw monster hashes (note, takes up a lot of screen space) for (int i = 0; i < gs->monster_controller().monster_ids().size(); i++) { GameInst* inst = gs->get_instance( gs->monster_controller().monster_ids()[i]); if (inst) { gs->font().drawf(COL_MUTED_GREEN, Pos(0, i * y_interval), "M%d 0x%X", i + 1, inst->integrity_hash()); } } } }