//-------------------------------------------------------------------------------------------- bool link_load_parent( const char * modname, const Vector3f& pos ) { if ( !VALID_CSTR( modname ) ) return false; // Push this module onto the stack so we can count the heroes. if ( !link_push_module() ) return false; // Grab the stored data link_stack_entry_t *pentry = link_stack + ( link_stack_count - 1 ); // Determine how you would have to shift the heroes so that they fall on top of the spawn point. Vector3f pos_diff = pos * Info<float>::Grid::Size() - pentry->hero[0].pos_stt; // Adjust all the hero spawn points. for (int i = 0; i < pentry->hero_count; ++i) { hero_spawn_data_t * phero = pentry->hero + i; phero->pos_stt += pos_diff; phero->pos = phero->pos_stt; } // copy the module name strncpy( pentry->modname, modname, SDL_arraysize( pentry->modname ) ); // now pop this "fake" module reference off the stack return link_pop_module(); }
//-------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------- bool link_follow_modname( const char * modname, bool push_current_module ) { //ZF> TODO: not implemented return false; #if 0 /// @author BB /// @details This causes the game to follow a link, given the module name bool retval; int old_link_stack_count = link_stack_count; if ( !VALID_CSTR( modname ) ) return false; // can this module be loaded? if ( !link_test_module( modname ) ) return false; // push the link BEFORE you change the module data // otherwise you won't save the correct data! if ( push_current_module ) { link_push_module(); } // export all the local and remote characters and // quit the old module game_finish_module(); // try to load the new module //retval = game_begin_module(modname); retval = false; //ZF> TODO: not implemented if ( !retval ) { // if the module linking fails, make sure to remove any bad info from the stack link_stack_count = old_link_stack_count; } else { pickedmodule_index = -1; pickedmodule_path[0] = CSTR_END; pickedmodule_name[0] = CSTR_END; pickedmodule_write_path[0] = CSTR_END; pickedmodule_index = mnu_get_mod_number( modname ); if ( -1 != pickedmodule_index ) { strncpy( pickedmodule_path, mnu_ModList_get_vfs_path( pickedmodule_index ), SDL_arraysize( pickedmodule_path ) ); strncpy( pickedmodule_name, mnu_ModList_get_name( pickedmodule_index ), SDL_arraysize( pickedmodule_name ) ); strncpy( pickedmodule_write_path, mnu_ModList_get_dest_path( pickedmodule_index ), SDL_arraysize( pickedmodule_write_path ) ); } } return retval; #endif }
//-------------------------------------------------------------------------------------------- void load_action_names_vfs( const char* loadname ) { /// @details ZZ@> This function loads all of the 2 letter action names vfs_FILE* fileread; int cnt; char first = CSTR_END, second = CSTR_END; STRING comment; bool_t found; fileread = vfs_openRead( loadname ); if ( !fileread ) return; for ( cnt = 0; cnt < ACTION_COUNT; cnt++ ) { comment[0] = CSTR_END; found = bfalse; if ( goto_colon( NULL, fileread, bfalse ) ) { if ( vfs_scanf( fileread, " %c%c %s", &first, &second, &comment ) >= 2 ) { found = btrue; } } if ( found ) { cActionName[cnt][0] = first; cActionName[cnt][1] = second; cActionComent[cnt][0] = CSTR_END; if ( VALID_CSTR( comment ) ) { strncpy( cActionComent[cnt], comment, SDL_arraysize( cActionComent[cnt] ) ); cActionComent[cnt][255] = CSTR_END; } } else { cActionName[cnt][0] = CSTR_END; cActionComent[cnt][0] = CSTR_END; } } vfs_close( fileread ); }
//-------------------------------------------------------------------------------------------- bool link_build_vfs( const char * fname, Link_t list[] ) { if (!VALID_CSTR(fname)) return false; ReadContext ctxt(fname); if (!ctxt.ensureOpen()) return false; size_t i = 0; while (ctxt.skipToColon(true) && i < LINK_COUNT) { vfs_read_string_lit( ctxt, list[i].modname, SDL_arraysize( list[i].modname ) ); list[i].valid = true; i++; } return i > 0; }
bool link_test_module( const char * modname ) { if ( !VALID_CSTR( modname ) ) return false; //ZF> Not supported yet, needs porting bool retval = false; LoadPlayer_list_t tmp_loadplayer = LOADPLAYER_LIST_INIT; // generate a temporary list of loadplayers LoadPlayer_list_from_players( &tmp_loadplayer ); // test the given module retval = mnu_test_module_by_name( &tmp_loadplayer, modname ); // blank out the list (not necessary since the list is local, but just in case) LoadPlayer_list_init( &tmp_loadplayer ); return retval; }
//-------------------------------------------------------------------------------------------- mad_t * mad_get_framefx( mad_t * pmad, const char * cFrameName, int frame ) { /// @details ZZ@> This function figures out the IFrame invulnerability, and Attack, Grab, and /// Drop timings /// /// BB@> made a bit more sturdy parser that is not going to confuse strings like "LCRA" /// which would not crop up if the convention of L or R going first was applied universally. /// However, there are existing (and common) models which use the opposite convention, leading /// to the possibility that an fx string "LARC" could be interpreted as ACTLEFT, CHARRIGHT, *and* /// ACTRIGHT. BIT_FIELD fx = 0; char name_action[16], name_fx[16]; int name_count; int fields; int cnt; static int token_count = -1; static const char * tokens[] = { "I", "S", "F", "P", "A", "G", "D", "C", /* the normal command tokens */ "LA", "LG", "LD", "LC", "RA", "RG", "RD", "RC", NULL }; /* the "bad" token aliases */ const char * ptmp, * ptmp_end; char *paction, *paction_end; MD2_Model_t * md2; MD2_Frame_t * pframe; if ( NULL == pmad ) return pmad; md2 = pmad->md2_ptr; if ( NULL == md2 ) return pmad; // check for a valid frame number if ( frame >= md2_get_numFrames( md2 ) ) return pmad; pframe = ( MD2_Frame_t * )md2_get_Frames( md2 ); pframe = pframe + frame; // this should only be initializwd the first time through if ( token_count < 0 ) { token_count = 0; for ( cnt = 0; NULL != tokens[token_count] && cnt < 256; cnt++ ) token_count++; } // set the default values fx = 0; pframe->framefx = fx; // check for a non-trivial frame name if ( !VALID_CSTR( cFrameName ) ) return pmad; // skip over whitespace ptmp = cFrameName; ptmp_end = cFrameName + 16; for ( /* nothing */; ptmp < ptmp_end && isspace( *ptmp ); ptmp++ ) {}; // copy non-numerical text paction = name_action; paction_end = name_action + 16; for ( /* nothing */; ptmp < ptmp_end && paction < paction_end && !isspace( *ptmp ); ptmp++, paction++ ) { if ( isdigit( *ptmp ) ) break; *paction = *ptmp; } if ( paction < paction_end ) *paction = CSTR_END; name_fx[0] = CSTR_END; fields = sscanf( ptmp, "%d %15s", &name_count, name_fx ); name_action[15] = CSTR_END; name_fx[15] = CSTR_END; // check for a non-trivial fx command if ( !VALID_CSTR( name_fx ) ) return pmad; // scan the fx string for valid commands ptmp = name_fx; ptmp_end = name_fx + 15; while ( CSTR_END != *ptmp && ptmp < ptmp_end ) { size_t len; int token_index = -1; for ( cnt = 0; cnt < token_count; cnt++ ) { len = strlen( tokens[cnt] ); if ( 0 == strncmp( tokens[cnt], ptmp, len ) ) { ptmp += len; token_index = cnt; break; } } if ( -1 == token_index ) { //log_debug( "Model %s, frame %d, frame name \"%s\" has unknown frame effects command \"%s\"\n", szModelName, frame, cFrameName, ptmp ); ptmp++; } else { bool_t bad_form = bfalse; switch ( token_index ) { case 0: // "I" == invulnerable SET_BIT( fx, MADFX_INVICTUS ); break; case 1: // "S" == stop SET_BIT( fx, MADFX_STOP ); break; case 2: // "F" == footfall SET_BIT( fx, MADFX_FOOTFALL ); break; case 3: // "P" == poof SET_BIT( fx, MADFX_POOF ); break; case 4: // "A" == action // get any modifiers while (( CSTR_END != *ptmp && ptmp < ptmp_end ) && ( 'R' == *ptmp || 'L' == *ptmp ) ) { SET_BIT( fx, ( 'L' == *ptmp ) ? MADFX_ACTLEFT : MADFX_ACTRIGHT ); ptmp++; } break; case 5: // "G" == grab // get any modifiers while (( CSTR_END != *ptmp && ptmp < ptmp_end ) && ( 'R' == *ptmp || 'L' == *ptmp ) ) { SET_BIT( fx, ( 'L' == *ptmp ) ? MADFX_GRABLEFT : MADFX_GRABRIGHT ); ptmp++; } break; case 6: // "D" == drop // get any modifiers while (( CSTR_END != *ptmp && ptmp < ptmp_end ) && ( 'R' == *ptmp || 'L' == *ptmp ) ) { fx |= ( 'L' == *ptmp ) ? MADFX_DROPLEFT : MADFX_DROPRIGHT; ptmp++; } break; case 7: // "C" == grab a character // get any modifiers while (( CSTR_END != *ptmp && ptmp < ptmp_end ) && ( 'R' == *ptmp || 'L' == *ptmp ) ) { SET_BIT( fx, ( 'L' == *ptmp ) ? MADFX_CHARLEFT : MADFX_CHARRIGHT ); ptmp++; } break; case 8: // "LA" bad_form = btrue; SET_BIT( fx, MADFX_ACTLEFT ); break; case 9: // "LG" bad_form = btrue; SET_BIT( fx, MADFX_GRABLEFT ); break; case 10: // "LD" bad_form = btrue; SET_BIT( fx, MADFX_DROPLEFT ); break; case 11: // "LC" bad_form = btrue; SET_BIT( fx, MADFX_CHARLEFT ); break; case 12: // "RA" bad_form = btrue; SET_BIT( fx, MADFX_ACTRIGHT ); break; case 13: // "RG" bad_form = btrue; SET_BIT( fx, MADFX_GRABRIGHT ); break; case 14: // "RD" bad_form = btrue; SET_BIT( fx, MADFX_DROPRIGHT ); break; case 15: // "RC" bad_form = btrue; SET_BIT( fx, MADFX_CHARRIGHT ); break; } if ( bad_form && -1 != token_index ) { log_warning( "Model %s, frame %d, frame name \"%s\" has a frame effects command in an improper configuration \"%s\"\n", szModelName, frame, cFrameName, tokens[token_index] ); } } } pframe->framefx = fx; return pmad; }
//-------------------------------------------------------------------------------------------- bool tile_dictionary_load_vfs( const char * filename, tile_dictionary_t * pdict, int max_dict_size ) { /// @author ZZ /// @details This function loads fan types for the terrain Uint32 cnt, entry, vertices, commandsize; int fantype_count, fantype_offset, fantype; int command_count, command; int definition_count; int itmp; float ftmp; if ( NULL == pdict ) return false; // "delete" the old list *pdict = tile_dictionary_t(); if ( !VALID_CSTR( filename ) ) return false; // handle default parameters if ( max_dict_size < 0 ) { max_dict_size = MAP_FAN_TYPE_MAX; } // Try to open a context. ReadContext ctxt(filename); if (!ctxt.ensureOpen()) { Log::get().error("unable to load tile definitions file `%s`\n", filename); return false; } fantype_count = vfs_get_next_int(ctxt); fantype_offset = 2 * std::pow( 2.0f, std::floor( std::log( fantype_count ) / std::log( 2.0f ) ) ); definition_count = 2 * fantype_offset; if ( definition_count > MAP_FAN_TYPE_MAX ) { Log::get().error( "%s - tile dictionary has too many tile definitions (%d/%d).\n", __FUNCTION__, definition_count, MAP_FAN_TYPE_MAX ); return false; } else if ( definition_count > max_dict_size ) { Log::get().error( "%s - the number of tile difinitions has exceeded the requested number (%d/%d).\n", __FUNCTION__, definition_count, max_dict_size ); return false; } pdict->offset = fantype_offset; pdict->def_count = definition_count; for ( fantype = 0; fantype < fantype_count; fantype++ ) { tile_definition_t& pdef_sml = pdict->def_lst[fantype]; tile_definition_t& pdef_big = pdict->def_lst[fantype + fantype_offset]; vertices = vfs_get_next_int(ctxt); pdef_sml.numvertices = vertices; pdef_big.numvertices = vertices; // Dupe for ( cnt = 0; cnt < vertices; cnt++ ) { itmp = vfs_get_next_int(ctxt); pdef_sml.ref[cnt] = itmp; pdef_sml.grid_ix[cnt] = itmp & 3; pdef_sml.grid_iy[cnt] = ( itmp >> 2 ) & 3; ftmp = vfs_get_next_float(ctxt); pdef_sml.u[cnt] = ftmp; ftmp = vfs_get_next_float(ctxt); pdef_sml.v[cnt] = ftmp; // Dupe pdef_big.ref[cnt] = pdef_sml.ref[cnt]; pdef_big.grid_ix[cnt] = pdef_sml.grid_ix[cnt]; pdef_big.grid_iy[cnt] = pdef_sml.grid_iy[cnt]; pdef_big.u[cnt] = pdef_sml.u[cnt]; pdef_big.v[cnt] = pdef_sml.v[cnt]; } command_count = vfs_get_next_int(ctxt); pdef_sml.command_count = command_count; pdef_big.command_count = command_count; // Dupe for ( entry = 0, command = 0; command < command_count; command++ ) { commandsize = vfs_get_next_int(ctxt); pdef_sml.command_entries[command] = commandsize; pdef_big.command_entries[command] = commandsize; // Dupe for ( cnt = 0; cnt < commandsize; cnt++ ) { itmp = vfs_get_next_int(ctxt); pdef_sml.command_verts[entry] = itmp; pdef_big.command_verts[entry] = itmp; // Dupe entry++; } } } pdict->loaded = true; tile_dictionary_finalize( pdict ); return true; }