/** * @brief Creates a new music. * @param music_id id of the music (a file name) */ Music::Music(const MusicId& music_id): id(music_id) { if (!is_initialized() || music_id == none) { return; } // compute the file name file_name = (std::string) "musics/" + music_id; // get the format size_t index = music_id.find_last_of("."); Debug::check_assertion(index != std::string::npos && index != music_id.size(), StringConcat() << "Invalid music file name: " << music_id); std::string extension = music_id.substr(index + 1); if (extension == "spc" || extension == "SPC" || extension == "Spc") { format = SPC; } else if (extension == "it" || extension == "IT" || extension == "It") { format = IT; } else if (extension == "ogg" || extension == "OGG" || extension == "Ogg") { format = OGG; } else { Debug::die(StringConcat() << "Unrecognized music file format: " << music_id); } for (int i = 0; i < nb_buffers; i++) { buffers[i] = AL_NONE; } source = AL_NONE; }
/* ================= UI_CreateGame_GetMapsList ================= */ static void UI_CreateGame_GetMapsList( void ) { char *afile; if( !CHECK_MAP_LIST( FALSE ) || (afile = (char *)LOAD_FILE( "maps.lst", NULL )) == NULL ) { uiCreateGame.done.generic.flags |= QMF_GRAYED; uiCreateGame.mapsList.itemNames = (const char **)uiCreateGame.mapsDescriptionPtr; Con_Printf( "Cmd_GetMapsList: can't open maps.lst\n" ); return; } char *pfile = afile; char token[1024]; int numMaps = 0; while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { if( numMaps >= UI_MAXGAMES ) break; StringConcat( uiCreateGame.mapName[numMaps], token, sizeof( uiCreateGame.mapName[0] )); StringConcat( uiCreateGame.mapsDescription[numMaps], token, MAPNAME_LENGTH ); StringConcat( uiCreateGame.mapsDescription[numMaps], uiEmptyString, MAPNAME_LENGTH ); if(( pfile = COM_ParseFile( pfile, token )) == NULL ) break; // unexpected end of file StringConcat( uiCreateGame.mapsDescription[numMaps], token, TITLE_LENGTH ); StringConcat( uiCreateGame.mapsDescription[numMaps], uiEmptyString, TITLE_LENGTH ); uiCreateGame.mapsDescriptionPtr[numMaps] = uiCreateGame.mapsDescription[numMaps]; numMaps++; } if( !numMaps ) uiCreateGame.done.generic.flags |= QMF_GRAYED; for( ; numMaps < UI_MAXGAMES; numMaps++ ) uiCreateGame.mapsDescriptionPtr[numMaps] = NULL; uiCreateGame.mapsList.itemNames = (const char **)uiCreateGame.mapsDescriptionPtr; FREE_FILE( afile ); }
/** * \brief Loads the fonts. */ void TextSurface::load_fonts() { // Load the list of available fonts. static const std::string file_name = "text/fonts.dat"; lua_State* l = luaL_newstate(); size_t size; char* buffer; FileTools::data_file_open_buffer(file_name, &buffer, &size); int load_result = luaL_loadbuffer(l, buffer, size, file_name.c_str()); FileTools::data_file_close_buffer(buffer); if (load_result != 0) { Debug::die(StringConcat() << "Failed to load the fonts file '" << file_name << "': " << lua_tostring(l, -1)); lua_pop(l, 1); } else { lua_register(l, "font", l_font); if (lua_pcall(l, 0, 0, 0) != 0) { Debug::die(StringConcat() << "Failed to load the fonts file '" << file_name << "': " << lua_tostring(l, -1)); lua_pop(l, 1); } } lua_close(l); fonts_loaded = true; }
/** * @brief Initializes the font system. */ void TextSurface::initialize() { TTF_Init(); // first determine the available fonts IniFile ini("text/fonts.dat", IniFile::READ); for (ini.start_group_iteration(); ini.has_more_groups(); ini.next_group()) { // get the font metadata std::string font_id = ini.get_group(); std::string file_name = ini.get_string_value("file", ""); Debug::check_assertion(file_name.size() > 0, StringConcat() << "Missing font file name in file 'text/fonts.dat' for group '" << font_id << "'"); int font_size = ini.get_integer_value("size", 0); Debug::check_assertion(font_size > 0, StringConcat() << "Missing font size in file 'text/fonts.dat' for group '" << font_id << "'"); fonts[font_id].file_name = file_name; fonts[font_id].font_size = font_size; if (ini.get_boolean_value("default", false)) { default_font_id = font_id; } // load the font size_t size; FileTools::data_file_open_buffer(file_name, &fonts[font_id].buffer, &size); fonts[font_id].rw = SDL_RWFromMem(fonts[font_id].buffer, int(size)); fonts[font_id].internal_font = TTF_OpenFontRW(fonts[font_id].rw, 0, font_size); Debug::check_assertion(fonts[font_id].internal_font != NULL, StringConcat() << "Cannot load font from file '" << file_name << "': " << TTF_GetError()); } Debug::check_assertion(default_font_id.size() > 0, "No default font set in file 'text/fonts.dat'"); }
/** * @brief Calls a Lua function of the current script, possibly with arguments and return values of various types. * * This is just a convenient method to push the parameters and pop the results for you * in addition to calling the Lua function. * However, this function uses the variable number of parameters mechanism of cstdarg, which * is inherently C and not C++. * This means you have to use C-style strings instead of std::string. * * The arguments and results of the Lua function are passed thanks to the variable number of * parameters (possibly of different types) of this C++ method. * The format parameter of this C++ method specifies the type of each * argument and each result of the Lua function to call. * The types of the arguments should be described in the format string as a sequence of characters * where each character represents a type ('i': int, 'b': bool, 's': const char*). * If you expect some results to get returned by the Lua function, * the format string should then take a space character, * and the types of the results are then specified in the same way, * except that results of type string are not accepted. * The space character is optional if no result is returned. * This means an empty format string can be used when the Lua function has no argument * and no return value. * * The remaining parameters of this C++ method (of variable number) * must match the specified format, * passing values for the arguments and pointers for the results. * * Let's take an example: * assuming that the Lua function you want to call takes as arguments * a string plus two integers and returns a boolean, * the format string you should specify is: "sii b". * You should then give four parameters of types const char*, int, int and bool*. * * If the Lua function does not exists in the script, * nothing happens and this C++ function returns false. * It just means that the function corresponds to an event that * the script does not want to handle. * If the Lua function exists, the arguments are pushed onto the stack, the function is executed, * the results (if any) are popped from the stack and stored into your pointed areas, * and this C++ method returns true. * In both cases, the Lua stack is left unchanged. * * This function does not support results of type string because it would cause some * complications and we want to keep its usage simple. * If you need to call a function with a result of type string, you can still do it, * but not with this C++ method. * I explain now what the problem is with string results. * If a Lua function returns a string, the memory used by the const char* pointer is discarded * when the C++ code pops it from the stack. * And this C++ method is supposed to to the job for you, so it pops the results * from the stack before returning them to you. * As a consequence, allowing string results * would require that you pop the results yourself, after having read them. * Another solution would be to return a copy of the string, * but because the variable number of parameters mechanism cannot use std::string, * the copy would be a const char* that you would have to free yourself. * As this function wants to simplify your code by doing the job for you, * both solutions are bad ideas. * However, in Solarus, calling Lua from C++ is used only to notify a script that something * happened (recall the name of this C++ method), not to ask strings to them. * * @param function_name name of the function to call * (may be prefixed by the name of several Lua tables, typically sol.main.some_function) * @param format a string describing the types of arguments to pass to the Lua function * and the types of return values to get (see above) * @return true if the function was called successfully, false if it does not exist */ bool Script::notify_script(const std::string& function_name, const char* format, ...) { // find the function and push it onto the stack bool exists = find_lua_function(function_name); if (exists) { va_list args; va_start(args, format); // push the arguments unsigned int i; unsigned int nb_arguments = 0; bool end_arguments = false; for (i = 0; i < strlen(format) && !end_arguments; i++) { switch (format[i]) { case 'i': lua_pushinteger(l, va_arg(args, int)); break; case 'b': lua_pushboolean(l, va_arg(args, int)); break; // cstdarg refuses bool case 's': lua_pushstring(l, va_arg(args, const char*)); break; // and std::string case ' ': end_arguments = true; break; default: Debug::die(StringConcat() << "Invalid character '" << format[i] << "' in format string '" << format); } if (format[i] != ' ') { nb_arguments++; } } // call the function int nb_results = strlen(format) - i; if (lua_pcall(l, nb_arguments, nb_results, 0) != 0) { Debug::print(StringConcat() << "Error in " << function_name << "(): " << lua_tostring(l, -1)); lua_pop(l, 1); nb_results = 0; } // get the results for (int i = 0; i < nb_results; i++) { char type = format[nb_arguments + i + 1]; int stack_index = -nb_results + i; switch (type) { case 'i': *va_arg(args, int*) = lua_tointeger(l, stack_index); break; case 'b': *va_arg(args, int*) = lua_toboolean(l, stack_index); break; case 's': Debug::die("String results are not supported by Script::notify_script(), please make the call yourself"); default: Debug::die(StringConcat() << "Invalid character '" << type << "' in format string '" << format); } } lua_pop(l, nb_results); va_end(args); } return exists; }
/** * \brief Returns a boolean value saved. * \param key Name of the value to get. * \return The boolean value associated with this key or false. */ bool Savegame::get_boolean(const std::string& key) { Debug::check_assertion(LuaContext::is_valid_lua_identifier(key), StringConcat() << "Savegame variable '" << key << "' is not a valid key"); bool result = false; if (saved_values.count(key) > 0) { const SavedValue& value = saved_values[key]; Debug::check_assertion(value.type == SavedValue::VALUE_BOOLEAN, StringConcat() << "Value '" << key << "' is not a boolean"); result = value.int_data != 0; } return result; }
/** * \brief Returns a integer value saved. * \param key Name of the value to get. * \return The integer value associated with this key or 0. */ int Savegame::get_integer(const std::string& key) { Debug::check_assertion(LuaContext::is_valid_lua_identifier(key), StringConcat() << "Savegame variable '" << key << "' is not a valid key"); int result = 0; if (saved_values.count(key) > 0) { const SavedValue& value = saved_values[key]; Debug::check_assertion(value.type == SavedValue::VALUE_INTEGER, StringConcat() << "Value '" << key << "' is not an integer"); result = value.int_data; } return result; }
/* ================= UI_PlayDemo_GetDemoList ================= */ static void UI_PlayDemo_GetDemoList( void ) { char comment[256]; char **filenames; int i, numFiles; filenames = FS_SEARCH( "demos/*.dem", &numFiles, TRUE ); for( i = 0; i < numFiles; i++ ) { if( i >= UI_MAXGAMES ) break; if( !GET_DEMO_COMMENT( filenames[i], comment )) { if( strlen( comment )) { // get name string even if not found - CL_GetComment can be mark demos // as <CORRUPTED> <OLD VERSION> etc StringConcat( uiPlayDemo.demoDescription[i], uiEmptyString, TITLE_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], comment, MAPNAME_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], uiEmptyString, MAXCLIENTS_LENGTH ); uiPlayDemo.demoDescriptionPtr[i] = uiPlayDemo.demoDescription[i]; COM_FileBase( filenames[i], uiPlayDemo.delName[i] ); } else uiPlayDemo.demoDescriptionPtr[i] = NULL; continue; } // strip path, leave only filename (empty slots doesn't have savename) COM_FileBase( filenames[i], uiPlayDemo.demoName[i] ); COM_FileBase( filenames[i], uiPlayDemo.delName[i] ); // fill demo desc StringConcat( uiPlayDemo.demoDescription[i], comment + CS_SIZE, TITLE_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], uiEmptyString, TITLE_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], comment, MAPNAME_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], uiEmptyString, MAPNAME_LENGTH ); // fill remaining entries StringConcat( uiPlayDemo.demoDescription[i], comment + CS_SIZE * 2, MAXCLIENTS_LENGTH ); StringConcat( uiPlayDemo.demoDescription[i], uiEmptyString, MAXCLIENTS_LENGTH ); uiPlayDemo.demoDescriptionPtr[i] = uiPlayDemo.demoDescription[i]; } for ( ; i < UI_MAXGAMES; i++ ) uiPlayDemo.demoDescriptionPtr[i] = NULL; uiPlayDemo.demosList.itemNames = (const char **)uiPlayDemo.demoDescriptionPtr; if( strlen( uiPlayDemo.demoName[0] ) == 0 ) uiPlayDemo.play.generic.flags |= QMF_GRAYED; else uiPlayDemo.play.generic.flags &= ~QMF_GRAYED; if( strlen( uiPlayDemo.delName[0] ) == 0 || !stricmp( gpGlobals->demoname, uiPlayDemo.delName[uiPlayDemo.demosList.curItem] )) uiPlayDemo.remove.generic.flags |= QMF_GRAYED; else uiPlayDemo.remove.generic.flags &= ~QMF_GRAYED; }
/** * \brief Returns a string value saved. * \param key Name of the value to get. * \return The string value associated with this key or an empty string. */ const std::string& Savegame::get_string(const std::string& key) { Debug::check_assertion(LuaContext::is_valid_lua_identifier(key), StringConcat() << "Savegame variable '" << key << "' is not a valid key"); if (saved_values.count(key) > 0) { const SavedValue& value = saved_values[key]; Debug::check_assertion(value.type == SavedValue::VALUE_STRING, StringConcat() << "Value '" << key << "' is not a string"); return value.string_data; } static const std::string empty_string = ""; return empty_string; }
/** * @brief Returns the value of a property of this movement. * * Accepted keys: * - path * - speed * - loop * - ignore_obstacles * - snap_to_grid * * @param key key of the property to get * @return the corresponding value as a string */ const std::string PathMovement::get_property(const std::string &key) { std::ostringstream oss; if (key == "path") { oss << initial_path; } else if (key == "speed") { oss << speed; } else if (key == "loop") { oss << loop; } else if (key == "ignore_obstacles") { oss << are_obstacles_ignored(); } else if (key == "snap_to_grid") { oss << snap_to_grid; } else { Debug::die(StringConcat() << "Unknown property of PathMovement: '" << key << "'"); } return oss.str(); }
/** * \brief Returns the index of the savegame variable that stores the specified ability. * \param ability_name Name of the ability. * \return Name of the boolean savegame variable that stores this ability. */ std::string Equipment::get_ability_savegame_variable( const std::string& ability_name) const { std::string savegame_variable; if (ability_name == "tunic") { savegame_variable = Savegame::KEY_ABILITY_TUNIC; } else if (ability_name == "sword") { savegame_variable = Savegame::KEY_ABILITY_SWORD; } else if (ability_name == "sword_knowledge") { savegame_variable = Savegame::KEY_ABILITY_SWORD_KNOWLEDGE; } else if (ability_name == "shield") { savegame_variable = Savegame::KEY_ABILITY_SHIELD; } else if (ability_name == "lift") { savegame_variable = Savegame::KEY_ABILITY_LIFT; } else if (ability_name == "swim") { savegame_variable = Savegame::KEY_ABILITY_SWIM; } else if (ability_name == "run") { savegame_variable = Savegame::KEY_ABILITY_RUN; } else if (ability_name == "detect_weak_walls") { savegame_variable = Savegame::KEY_ABILITY_DETECT_WEAK_WALLS; } else { Debug::die(StringConcat() << "Unknown ability '" << ability_name << "'"); } return savegame_variable; }
/** * @brief Updates the script. */ void Script::update() { // update the timers std::map<int, Timer*>::iterator it; for (it = timers.begin(); it != timers.end(); it++) { int ref = it->first; Timer* timer = it->second; timer->update(); if (timer->is_finished()) { // delete the C++ timer timers.erase(it); delete timer; // retrieve the Lua function and call it lua_rawgeti(l, LUA_REGISTRYINDEX, ref); if (lua_pcall(l, 0, 0, 0) != 0) { Debug::print(StringConcat() << "Error in the function of the timer: " << lua_tostring(l, -1)); lua_pop(l, 1); } // delete the Lua function luaL_unref(l, LUA_REGISTRYINDEX, ref); break; } } }
/** * @brief Returns a sprite handled by this script. * @param sprite_handle handle of the sprite to get * @return the corresponding sprite */ Sprite& Script::get_sprite(int sprite_handle) { Debug::check_assertion(sprites.count(sprite_handle) > 0, StringConcat() << "No sprite with handle '" << sprite_handle << "'"); return *sprites[sprite_handle]; }
/** * @brief Initializes the Lua context and loads the script from a file. * * If the script file does not exist, the field context is NULL. * * @param script_name name of a Lua script file (without extension) */ void Script::load_if_exists(const std::string& script_name) { if (l == NULL) { initialize_lua_context(); } // determine the file name (.lua) std::ostringstream oss; oss << script_name << ".lua"; std::string file_name = oss.str(); if (FileTools::data_file_exists(file_name)) { // load the file size_t size; char* buffer; FileTools::data_file_open_buffer(file_name, &buffer, &size); luaL_loadbuffer(l, buffer, size, file_name.c_str()); FileTools::data_file_close_buffer(buffer); if (lua_pcall(l, 0, 0, 0) != 0) { Debug::die(StringConcat() << "Error: failed to load script '" << script_name << "': " << lua_tostring(l, -1)); lua_pop(l, 1); } } else { // uninitialize Lua lua_close(l); l = NULL; } }
/** * @brief Sets the number of rotations of the movement. * * When this number of rotations is reached, the movement stops. * Note that is the radius changes gradually, the movement will continue * for a while until the radius reaches zero. * * @param max_rotations number of rotations to make (0 for infinite rotations) */ void CircleMovement::set_max_rotations(int max_rotations) { Debug::check_assertion(max_rotations >= 0, StringConcat() << "Invalid maximum rotations number: " << max_rotations); this->max_rotations = max_rotations; this->nb_rotations = 0; }
/** * \brief Unsets a value saved. * \param key Name of the value to unset. */ void Savegame::unset(const std::string& key) { Debug::check_assertion(LuaContext::is_valid_lua_identifier(key), StringConcat() << "Savegame variable '" << key << "' is not a valid key"); saved_values.erase(key); }
/** * @brief Sets the map. * * Warning: as this function is called when initializing the map, * the current map of the game is still the old one. * * @param map the map */ void Teletransporter::set_map(Map &map) { MapEntity::set_map(map); if (destination_point_name == "_side") { int x = get_x(); int y = get_y(); if (get_width() == 16 && x == -16) { destination_side = 0; } else if (get_width() == 16 && x == map.get_width()) { destination_side = 2; } else if (get_height() == 16 && y == -16) { destination_side = 3; } else if (get_height() == 16 && y == map.get_height()) { destination_side = 1; } else { Debug::die(StringConcat() << "Bad position of teletransporter '" << get_name() << "'"); } } transition_direction = (destination_side + 2) % 4; }
int main(int argc, char** argv) { FLAGS_alsologtostderr = true; google::ParseCommandLineFlags(&argc, &argv, true); google::InitGoogleLogging(argv[0]); HttpServer server(FLAGS_threads_num); ChineseYangHandler handler; HttpClosure* task = NewPermanentClosure( &handler, &ChineseYangHandler::HandleGet); server.RegisterPrefixSimpleHandler("/yang", task); std::string address = StringConcat( FLAGS_server_ip, ":", FLAGS_server_port); if (!server.Start(address)) { LOG(ERROR) << "start failed. address " << address; return 1; } LOG(INFO) << "listen on " << address; int ret = server.Run(); LOG(INFO) << "server finish. ret " << ret; return ret; }
/** * @brief Blits a surface on the screen with the current video mode. * @param src_surface the source surface to display on the screen */ void VideoManager::display(Surface *src_surface) { if (disable_window) { return; } switch (video_mode) { case WINDOWED_NORMAL: blit(src_surface, screen_surface); break; case WINDOWED_STRETCHED: case FULLSCREEN_NORMAL: case FULLSCREEN_WIDE: blit_stretched(src_surface, screen_surface); break; case WINDOWED_SCALE2X: case FULLSCREEN_SCALE2X: case FULLSCREEN_SCALE2X_WIDE: blit_scale2x(src_surface, screen_surface); break; default: Debug::die(StringConcat() << "Unknown video mode " << video_mode); break; } SDL_Flip(screen_surface->get_internal_surface()); }
/** * \brief Implementation of game:get_value(). * \param l The Lua context that is calling this function. * \return Number of values to return to Lua. */ int LuaContext::game_api_get_value(lua_State* l) { Savegame& savegame = check_game(l, 1); const std::string& key = luaL_checkstring(l, 2); if (!is_valid_lua_identifier(key)) { arg_error(l, 3, StringConcat() << "Invalid savegame variable '" << key << "': the name should only contain alphanumeric characters or '_'" << " and cannot start with a digit"); } if (savegame.is_boolean(key)) { lua_pushboolean(l, savegame.get_boolean(key)); } else if (savegame.is_integer(key)) { lua_pushinteger(l, savegame.get_integer(key)); } else if (savegame.is_string(key)) { lua_pushstring(l, savegame.get_string(key).c_str()); } else { lua_pushnil(l); } return 1; }
/** * @brief Initializes the text resource by loading all strings. * * The strings are loaded from the language-specific file "text/strings.dat" * and stored into memory for future access by get_string(). */ void StringResource::initialize() { strings.clear(); std::istream &file = FileTools::data_file_open("text/strings.dat", true); std::string line; // read each line int i = 0; while (std::getline(file, line)) { i++; // ignore empty lines or lines starting with '#' if (line.size() == 0 || line[0] == '#') { continue; } // get the key std::string key = line.substr(0, line.find_first_of(" \t")); // get the value size_t index = line.find_last_of("\t"); Debug::check_assertion(index != std::string::npos && index + 1 < line.size(), StringConcat() << "strings.dat, line " << i << ": cannot read string value for key '" << key << "'"); strings[key] = line.substr(index + 1); } FileTools::data_file_close(file); }
/** * @brief Sets the volume of sound effects. * @param volume the new volume (0 to 100) */ void Sound::set_volume(int volume) { Debug::check_assertion(volume >= 0 && volume <= 100, StringConcat() << "Illegal volume for sound effects:" << volume); Configuration::set_value("sound_volume", volume); Sound::volume = volume / 100.0; }
/** * \brief Creates a surface from the specified image file name. * * An assertion error occurs if the file cannot be loaded. * * \param file_name Name of the image file to load, relative to the base directory specified. * \param base_directory The base directory to use. */ Surface::Surface(const std::string& file_name, ImageDirectory base_directory): Drawable(), internal_surface(NULL), owns_internal_surface(true), with_colorkey(false), colorkey(0) { std::string prefix = ""; bool language_specific = false; if (base_directory == DIR_SPRITES) { prefix = "sprites/"; } else if (base_directory == DIR_LANGUAGE) { language_specific = true; prefix = "images/"; } std::string prefixed_file_name = prefix + file_name; size_t size; char* buffer; FileTools::data_file_open_buffer(prefixed_file_name, &buffer, &size, language_specific); SDL_RWops* rw = SDL_RWFromMem(buffer, int(size)); this->internal_surface = IMG_Load_RW(rw, 0); FileTools::data_file_close_buffer(buffer); SDL_RWclose(rw); Debug::check_assertion(internal_surface != NULL, StringConcat() << "Cannot load image '" << prefixed_file_name << "'"); with_colorkey = SDL_GetColorKey(internal_surface, &colorkey) == 0; }
/** * @brief Returns the point located just outside the hookshot's collision box, * in its current direction. */ const Rectangle Hookshot::get_facing_point() { Rectangle facing_point = get_center_point(); switch (get_sprite().get_current_direction()) { // right case 0: facing_point.add_x(8); break; // up case 1: facing_point.add_y(-9); break; // left case 2: facing_point.add_x(-9); break; // down case 3: facing_point.add_y(8); break; default: Debug::die(StringConcat() << "Invalid direction for Hookshot::get_facing_point(): " << get_sprite().get_current_direction()); } return facing_point; }
/** * \brief Sets the maximum amount of money of the player. * \param max_money the player's maximum amount number of money */ void Equipment::set_max_money(int max_money) { Debug::check_assertion(max_money > 0, StringConcat() << "Illegal maximum amount of money: " << max_money); savegame.set_integer(Savegame::KEY_MAX_MONEY, max_money); }
/** * \brief Sets the maximum level of life of the player. * * The program exits with an error message if the specified maximum * life is not valid. * * \param max_life the player's maximum life */ void Equipment::set_max_life(int max_life) { Debug::check_assertion(max_life > 0, StringConcat() << "Illegal maximum life: " << max_life); savegame.set_integer(Savegame::KEY_MAX_LIFE, max_life); }
/** * @brief Starts a timer to run a Lua function after the delay. * * The Lua function must be on the top of the stack and will be popped. * If the duration is set to zero, the function is executed immediately. * * @param l a Lua state * @param duration the timer duration in milliseconds * @param with_sound true to play a clock sound until the timer expires */ void Script::add_timer(lua_State* l, uint32_t duration, bool with_sound) { if (duration == 0) { // directly call the function if (lua_pcall(l, 0, 0, 0) != 0) { Debug::print(StringConcat() << "Error in the function of the timer: " << lua_tostring(l, -1)); lua_pop(l, 1); } } else { // store the function into the Lua registry int ref = luaL_ref(l, LUA_REGISTRYINDEX); // retrieve the script lua_getfield(l, LUA_REGISTRYINDEX, "sol.cpp_object"); Script* script = (Script*) lua_touserdata(l, -1); lua_pop(l, 1); // create the timer Timer* timer = new Timer(duration, with_sound); if (script->is_new_timer_suspended()) { timer->set_suspended(true); } script->timers[ref] = timer; } }
/** * \brief Returns an equipment item. * \param item_name Name of the item to get. * \return The corresponding item. */ const EquipmentItem& Equipment::get_item(const std::string& item_name) const { Debug::check_assertion(item_exists(item_name), StringConcat() << "Cannot find item with name '" << item_name << "'"); return *items.find(item_name)->second; }
/** * @brief Returns a movement handled by this script. * @param movement_handle handle of the movement to get * @return the corresponding movement */ Movement& Script::get_movement(int movement_handle) { Debug::check_assertion(movements.count(movement_handle) > 0, StringConcat() << "No movement with handle '" << movement_handle << "'"); return *movements[movement_handle]; }
/** * \brief Raises an assertion error if the player cannot obtain this treasure. */ void Treasure::check_obtainable() const { Debug::check_assertion(item_name.empty() || game->get_equipment().get_item(item_name).is_obtainable(), StringConcat() << "Treasure '" << item_name << "' is not allowed, did you call ensure_obtainable()?"); }