void Level::load(const Vector3& pos, const Quaternion& rot) { // Spawn units const UnitResource* ur = level_resource::unit_resource(_resource); const u32 num_units = ur->num_units; array::resize(_unit_lookup, num_units); for (u32 i = 0; i < num_units; ++i) _unit_lookup[i] = _unit_manager->create(); spawn_units(*_world, *ur, pos, rot, array::begin(_unit_lookup)); // Post events for (u32 i = 0; i < num_units; ++i) _world->post_unit_spawned_event(_unit_lookup[i]); // Play sounds const u32 num_sounds = level_resource::num_sounds(_resource); for (u32 i = 0; i < num_sounds; ++i) { const LevelSound* ls = level_resource::get_sound(_resource, i); _world->play_sound(ls->name , ls->loop , ls->volume , ls->position , ls->range ); } }
void GameArbiter::process_command(Message *command) { switch (command->type) { case UnitMove: { auto cmd = dynamic_cast<UnitMoveMessage *>(command); int stack_id = cmd->data1; IntSet units = cmd->data2; Path& path = cmd->data3; int target_id = cmd->data4; UnitStack::pointer stack = game->stacks.get(stack_id); if (units.empty() || !stack->has_units(units) || path.empty()) { throw DataError() << "Invalid UnitMove message"; } /* Check that the move is allowed; shorten it if necessary */ Point end_pos = path.back(); UnitStack::pointer end_stack = game->level.tiles[end_pos].stack; int end_stack_id = end_stack ? end_stack->id : 0; if (end_stack_id != target_id) { path.pop_back(); target_id = 0; } MovementModel movement(game); UnitStack::pointer selected_stack = stack->copy_subset(units); unsigned int allowed_steps = movement.check_path(*selected_stack, path); bool truncated = allowed_steps < path.size(); int attack_target_id = target_id; if (truncated) target_id = 0; path.resize(allowed_steps); if (!path.empty()) { end_pos = path.back(); /* Generate updates. */ Faction::pointer faction = stack->owner; bool move = units.size() == stack->units.size() && target_id == 0; bool split = units.size() < stack->units.size() && target_id == 0; bool merge = units.size() == stack->units.size() && target_id != 0; UnitStack::pointer target = game->stacks.find(target_id); if (move) target_id = stack_id; if (split) target_id = game->get_free_stack_id(); // Send the moves for (auto iter = path.begin(); iter != path.end(); iter++) { emit(create_message(MoveUnits, stack_id, units, *iter)); } // If the stack is splitting to a new empty position, create a stack there if (split) { emit(create_message(CreateStack, target_id, end_pos, faction->id)); } emit(create_message(TransferUnits, stack_id, units, path, target_id)); // If the whole stack merged with an existing one, destroy it if (merge) { emit(create_message(DestroyStack, stack_id)); } } else { end_pos = stack->position; } UnitStack::pointer attack_target = game->stacks.find(attack_target_id); bool attack = attack_target && (attack_target->owner != stack->owner); if (attack) { BOOST_LOG_TRIVIAL(debug) << "Attack!"; Point target_point = attack_target->position; Point attacking_point = end_pos; Battle battle(game, target_point, attacking_point); battle.run(); emit(create_message(DoBattle, end_stack_id, target_point, battle.moves)); } } break; case FactionReady: { auto cmd = dynamic_cast<FactionReadyMessage *>(command); int faction_id = cmd->data1; bool ready = cmd->data2; if (game->mark_faction_ready(faction_id, ready)) { emit(create_message(FactionReady, faction_id, ready)); } if (game->all_factions_ready()) { emit(create_message(TurnEnd)); // process turn end spawn_units(); game->turn_number++; emit(create_message(TurnBegin, game->turn_number)); } } break; case Chat: { auto chat_msg = dynamic_cast<ChatMessage *>(command); emit(create_message(Chat, chat_msg->data)); } break; case SetLevelData: case CreateStructure: case DestroyStructure: { emit(command->shared_from_this()); } break; default: break; } }