/* * Copyright (C) 1995-1997 Christopher D. Granz * * This header may not be removed. * * Refer to the file "License" included in this package for further * information and before using any of the following. */ /* * My NPC/object/room loading system is a bit slow, as you might have * noticed, this is because I did not put a high priority on bootup * speed but rather on ease of adding fields to NPC/object/room files. */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include "sapphire.h" /* * Prototypes */ static bool load_dir_desc ( ROOM_INDEX_DATA *, FILE *, int ); static bool load_exit ( ROOM_INDEX_DATA *, FILE *, int ); static int get_obj_reset_list ( char **, OBJ_RESET_DATA ** ); /* * Functions */ bool npc_load_inherit( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iInherit = fget_number_2( pFile ); if ( pNPCIndex->iInherit <= 5 || pNPCIndex->iInherit > MAX_INDEX_NUMBER ) sap_fatal( "NPC %d: Illegal NPC number `%d' for inherit.", pNPCIndex->iNumber, pNPCIndex->iInherit ); return ( FALSE ); } bool npc_load_imagefilename( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { return ( FALSE ); } bool npc_load_names( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { int i; for ( i = 0; pNPCIndex->pNameList[i] != NULL; i++ ) free_string( &pNPCIndex->pNameList[i] ); free_mem( (void **) &pNPCIndex->pNameList ); pNPCIndex->pNameList = alloc_mem( ( sizeof( string ) * 2 ) ); pNPCIndex->pNameList[0] = save_string( fget_string( pFile ) ); pNPCIndex->pNameList[1] = NULL; return ( FALSE ); } bool npc_load_shortdesc( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sShortDesc ); pNPCIndex->sShortDesc = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_desc( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[0] ); free_string( &pNPCIndex->sDescs[1] ); free_string( &pNPCIndex->sDescs[2] ); free_string( &pNPCIndex->sDescs[3] ); free_string( &pNPCIndex->sDescs[4] ); pNPCIndex->sDescs[0] = save_string( fget_string( pFile ) ); pNPCIndex->sDescs[1] = save_string( pNPCIndex->sDescs[0] ); pNPCIndex->sDescs[2] = save_string( pNPCIndex->sDescs[0] ); pNPCIndex->sDescs[3] = save_string( pNPCIndex->sDescs[0] ); pNPCIndex->sDescs[4] = save_string( pNPCIndex->sDescs[0] ); return ( FALSE ); } bool npc_load_desc1( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[0] ); pNPCIndex->sDescs[0] = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_desc2( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[1] ); pNPCIndex->sDescs[1] = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_desc3( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[2] ); pNPCIndex->sDescs[2] = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_desc4( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[3] ); pNPCIndex->sDescs[3] = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_desc5( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { free_string( &pNPCIndex->sDescs[4] ); pNPCIndex->sDescs[4] = save_string( fget_string( pFile ) ); return ( FALSE ); } bool npc_load_longdesc( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pString; char *pBuf; bool bWarn = FALSE; pString = fget_string( pFile ); pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "FORMAT" ) == TRUE ) pString = format_string( pString ); else { sap_warning( "NPC %d: Unknown string flag `%s'.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; } } free_string( &pNPCIndex->sLongDesc ); pNPCIndex->sLongDesc = save_string( pString ); return ( bWarn ); } bool npc_load_npcflags( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); for ( i = 0; snNPCFlagsTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snNPCFlagsTable[i].pName, cBuf ) == TRUE ) { SET_FLAG( pNPCIndex->fNPCFlags, snNPCFlagsTable[i].iNumber ); break; } } if ( snNPCFlagsTable[i].pName[0] == '\0' ) { sap_warning( "NPC %d: Unknown NPC flag `%s'.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; } } return ( bWarn ); } bool npc_load_partflags( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); for ( i = 0; snPartFlagsTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snPartFlagsTable[i].pName, cBuf ) == TRUE ) { SET_FLAG( pNPCIndex->fPartFlags, snPartFlagsTable[i].iNumber ); break; } } if ( snPartFlagsTable[i].pName[0] == '\0' ) { sap_warning( "NPC %d: Unknown part flag `%s'.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; } } return ( bWarn ); } bool npc_load_actflags( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); for ( i = 0; snActFlagsTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snActFlagsTable[i].pName, cBuf ) == TRUE ) { SET_FLAG( pNPCIndex->fActFlags, snActFlagsTable[i].iNumber ); break; } } if ( snActFlagsTable[i].pName[0] == '\0' ) { sap_warning( "NPC %d: Unknown action flag `%s'.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; } } return ( bWarn ); } bool npc_load_race( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char *pRace; int i; if ( ( pNPCIndex->iRace = get_race_number( ( pRace = fget_word_2( pFile ) ) ) ) == 0 ) { sap_warning( "NPC %d: Unknown race `%s'.", pNPCIndex->iNumber, pRace ); pNPCIndex->iRace = rRaceTable[0].iNumber; return ( TRUE ); } for ( i = 0; rRaceTable[i].pName[0] != '\0'; i++ ) { if ( rRaceTable[i].iNumber == pNPCIndex->iRace ) { pNPCIndex->fActFlags |= rRaceTable[i].fActFlags; break; } } return ( FALSE ); } bool npc_load_sex( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char *pSex; if ( ( pNPCIndex->iSex = get_sex_number( ( pSex = fget_word_2( pFile ) ) ) ) == 0 ) { sap_warning( "NPC %d: Unknown sex `%s'.", pNPCIndex->iNumber, pSex ); pNPCIndex->iSex = snSexTable[0].iNumber; return ( TRUE ); } return ( FALSE ); } bool npc_load_haircolor( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char *pHairColor; if ( ( pNPCIndex->iHairColor = get_hair_color_number( ( pHairColor = fget_word_2( pFile ) ) ) ) == 0 ) { sap_warning( "NPC %d: Unknown hair color `%s'.", pNPCIndex->iNumber, pHairColor ); pNPCIndex->iHairColor = snHairColorTable[0].iNumber; return ( TRUE ); } return ( FALSE ); } bool npc_load_eyecolor( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char *pEyeColor; if ( ( pNPCIndex->iEyeColor = get_hair_color_number( ( pEyeColor = fget_word_2( pFile ) ) ) ) == 0 ) { sap_warning( "NPC %d: Unknown eye color `%s'.", pNPCIndex->iNumber, pEyeColor ); pNPCIndex->iEyeColor = snEyeColorTable[0].iNumber; return ( TRUE ); } return ( FALSE ); } bool npc_load_height( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iHeight = fget_number_2( pFile ); return ( FALSE ); } bool npc_load_weight( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iWeight = fget_number_2( pFile ); return ( FALSE ); } bool npc_load_maxcarry( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iMaxCarry = fget_number_2( pFile ); if ( pNPCIndex->iMaxCarry < 0 ) { sap_warning( "NPC %d: Max carry weight less then 0.", pNPCIndex->iNumber ); pNPCIndex->iMaxCarry = 1; return ( TRUE ); } return ( FALSE ); } bool npc_load_level( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iLevel = fget_number_2( pFile ); if ( pNPCIndex->iLevel > MAX_PLAYER_LEVEL ) { sap_warning( "NPC %d: Level greater then %d.", pNPCIndex->iNumber, MAX_PLAYER_LEVEL ); pNPCIndex->iLevel = MAX_PLAYER_LEVEL; return ( TRUE ); } if ( pNPCIndex->iLevel < 1 ) { sap_warning( "NPC %d: Level less then 1.", pNPCIndex->iNumber ); pNPCIndex->iLevel = 1; return ( TRUE ); } return ( FALSE ); } bool npc_load_experience( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { bool bWarn = FALSE; pNPCIndex->iExp[0] = fget_number_2( pFile ); if ( pNPCIndex->iExp[0] > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); pNPCIndex->iExp[0] = 100; bWarn = TRUE; } if ( pNPCIndex->iExp[0] < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); pNPCIndex->iExp[0] = 0; bWarn = TRUE; } if ( fget_letter( pFile ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } pNPCIndex->iExp[1] = fget_number_2( pFile ); if ( pNPCIndex->iExp[1] > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); pNPCIndex->iExp[1] = 100; bWarn = TRUE; } if ( pNPCIndex->iExp[1] < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); pNPCIndex->iExp[1] = 0; bWarn = TRUE; } if ( fget_letter( pFile ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } pNPCIndex->iExp[2] = fget_number_2( pFile ); if ( pNPCIndex->iExp[2] > 1000 ) { sap_warning( "NPC %d: Dice modifier greater then 1000.", pNPCIndex->iNumber ); pNPCIndex->iExp[2] = 100; bWarn = TRUE; } if ( pNPCIndex->iExp[2] < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); pNPCIndex->iExp[2] = 0; bWarn = TRUE; } end: return ( bWarn ); } bool npc_load_alignment( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iAlignment = fget_number_2( pFile ); if ( pNPCIndex->iAlignment > 1000 ) { sap_warning( "NPC %d: Level greater then 1000.", pNPCIndex->iNumber ); pNPCIndex->iAlignment = 1000; return ( TRUE ); } if ( pNPCIndex->iAlignment < -1000 ) { sap_warning( "NPC %d: Level less then -1000.", pNPCIndex->iNumber ); pNPCIndex->iAlignment = -1000; return ( TRUE ); } return ( FALSE ); } bool npc_load_position( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char *pBuf; int i; pBuf = fget_word_2( pFile ); for ( i = 0; snPositionTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snPositionTable[i].pName, pBuf ) == TRUE ) { pNPCIndex->iPosition = snPositionTable[i].iNumber; return ( FALSE ); } } sap_warning( "NPC %d: Unknown position `%s'.", pNPCIndex->iNumber, pBuf ); pNPCIndex->iPosition = NUMBER_POSITION_STANDING; return ( TRUE ); } bool npc_load_gold( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iGold = fget_number_2( pFile ); return ( FALSE ); } bool npc_load_wander( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { pNPCIndex->iWander = fget_number_2( pFile ); if ( pNPCIndex->iWander > 100 ) { sap_warning( "NPC %d: Percent chance of wander greater then 100.", pNPCIndex->iNumber ); pNPCIndex->iWander = 100; return ( TRUE ); } if ( pNPCIndex->iWander < 0 ) { sap_warning( "NPC %d: Percent chance of wander less then 0.", pNPCIndex->iNumber ); pNPCIndex->iWander = 0; return ( TRUE ); } return ( FALSE ); } bool npc_load_stats( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pBuf; char c; int iNumber; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "STR" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatStr[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatStr[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatStr[2] = iNumber; } else if ( str_compare( cBuf, "INT" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatInt[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatInt[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatInt[2] = iNumber; } else if ( str_compare( cBuf, "WIS" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatWis[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatWis[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatWis[2] = iNumber; } else if ( str_compare( cBuf, "DEX" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatDex[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatDex[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatDex[2] = iNumber; } else if ( str_compare( cBuf, "CON" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCon[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCon[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCon[2] = iNumber; } else if ( str_compare( cBuf, "CHA" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCha[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCha[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatCha[2] = iNumber; } else if ( str_compare( cBuf, "LUC" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatLuc[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatLuc[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatLuc[2] = iNumber; } else if ( str_compare( cBuf, "HP" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatHP[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatHP[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatHP[2] = iNumber; } else if ( str_compare( cBuf, "MP" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMP[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMP[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMP[2] = iNumber; } else if ( str_compare( cBuf, "MV" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "dD\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Number of dice greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Number of dice less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMV[0] = iNumber; if ( LOWER( ( c = next_char( pBuf ) ) ) != 'd' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, c, "+\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 100 ) { sap_warning( "NPC %d: Dice sides greater then 100.", pNPCIndex->iNumber ); iNumber = 100; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice sides less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMV[1] = iNumber; if ( next_char( pBuf ) != '+' ) { sap_warning( "NPC %d: Incomplete dice.", pNPCIndex->iNumber ); bWarn = TRUE; continue; } pBuf = edit_str( pBuf, cBuf, '+', "\n\r\t " ); iNumber = atoi( cBuf ); if ( iNumber > 2000 ) { sap_warning( "NPC %d: Dice modifier greater then 2000.", pNPCIndex->iNumber ); iNumber = 2000; bWarn = TRUE; } if ( iNumber < 0 ) { sap_warning( "NPC %d: Dice modifier less then 0.", pNPCIndex->iNumber ); iNumber = 0; bWarn = TRUE; } pNPCIndex->VarStats.iStatMV[2] = iNumber; } else { pBuf = edit_str( pBuf, cBuf, ' ', "\n\r\t " ); sap_warning( "NPC %d: Unknown stat `%s'.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; } } return ( bWarn ); } bool npc_load_program( NPC_INDEX_DATA *pNPCIndex, FILE *pFile ) { PROGRAM_DATA *pProgram; SCRIPT_DATA *pScript; TRIGGER_DATA *pTrigger; TRIGGER_ARG_DATA *pTriggerArg; char *pStr = fget_string_3( pFile, '{', '}' ); char *pBak = pStr; char cBuf[MAX_STRING]; char cBuf2[MAX_STRING]; char *pBuf; char c; int i; bool bWarn = FALSE; pProgram = alloc_mem( sizeof( *pProgram ) ); pNPCIndex->pProgram = pProgram; while ( next_char( pStr ) != '\0' ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "TRIGGER" ) == TRUE ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); for ( pScript = pProgram->pScripts; pScript != NULL; pScript = pScript->pNext ) { if ( str_compare( pScript->pName, cBuf ) == TRUE ) break; } if ( pScript != NULL ) { sap_error( "NPC %d: Multiple blocks with the name `%s' in script.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pScript = alloc_mem( sizeof( *pScript ) ); pScript->pName = str_dup( cBuf ); pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "enabled" ) == TRUE ) pScript->bDisabled = FALSE; else if ( str_compare( cBuf, "disabled" ) == TRUE ) pScript->bDisabled = TRUE; else { str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Unknown enabled flag in script.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } do { pStr = edit_str( pStr, cBuf, ' ', "(\n\r\t " ); if ( next_char( pStr ) != '(' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Trigger missing `(' symbol in script.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; snNPCScriptTriggerTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( cBuf, snNPCScriptTriggerTable[i].pName ) == TRUE ) break; } if ( snNPCScriptTriggerTable[i].pName[0] == '\0' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Unknown trigger type `%s' in script.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pTrigger = alloc_mem( sizeof( *pTrigger ) ); pTrigger->iTrigger = snNPCScriptTriggerTable[i].iNumber; pStr = edit_str( pStr, cBuf, '(', ")" ); pBuf = remove_spaces( cBuf ); if ( next_char( pStr ) != ')' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Trigger missing `)' symbol in script.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } switch ( pTrigger->iTrigger ) { case NUMBER_NPC_TRIGGER_CREATED: break; case NUMBER_NPC_TRIGGER_RANDOM : if ( is_number( pBuf ) != TRUE ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_warning( "NPC %d: Non-number argument for " "trigger in script.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = alloc_mem( 1 ); *( (intt *) pTriggerArg->pArg ) = (intt) atoi( pBuf ); pTrigger->pArgs = pTriggerArg; break; case NUMBER_NPC_TRIGGER_MESSAGE: case NUMBER_NPC_TRIGGER_EMOTE : case NUMBER_NPC_TRIGGER_SAY : case NUMBER_NPC_TRIGGER_TELL : case NUMBER_NPC_TRIGGER_YELL : if ( str_compare( pBuf, "all" ) == TRUE ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->iType = 1; pTriggerArg->pArg = EMPTY_STRING; pTrigger->pArgs = pTriggerArg; break; } while ( *pBuf != '\0' ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pBuf = edit_str( pBuf, cBuf2, ' ', "\n\r\t " ); if ( next_char( pBuf ) == '"' ) { if ( str_compare( cBuf2, "exact" ) == TRUE ) pTriggerArg->iType = 2; else if ( str_compare( cBuf2, "prefix" ) == TRUE ) pTriggerArg->iType = 3; else if ( str_compare( cBuf2, "infix" ) == TRUE ) pTriggerArg->iType = 4; else if ( str_compare( cBuf2, "suffix" ) == TRUE ) pTriggerArg->iType = 5; else { sap_warning( "NPC %d: Unknown comparison " "type for trigger argument in script.", pNPCIndex->iNumber ); bWarn = TRUE; pTriggerArg->iType = 2; continue; } pBuf = make_string( pBuf, cBuf2 ); pBuf = remove_char_2( pBuf ); if ( cBuf2[0] == '\0' ) { sap_warning( "NPC %d: Empty string for " "trigger argument in script.", pNPCIndex->iNumber ); bWarn = TRUE; pTriggerArg->pArg = EMPTY_STRING; continue; } pTriggerArg->pArg = str_dup( cBuf2 ); } if ( ( c = next_char( pBuf ) ) == ',' ) pBuf = remove_char_2( pBuf ); else if ( c != '\0' ) { sap_warning( "NPC %d: Missing `,' for " "trigger argument list in script.", pNPCIndex->iNumber ); bWarn = TRUE; } pTriggerArg->pNext = pTrigger->pArgs; pTrigger->pArgs = pTriggerArg; } break; default : pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = str_dup( pBuf ); pTrigger->pArgs = pTriggerArg; break; } pStr = remove_char_2( pStr ); pTrigger->pNext = pScript->pTriggers; pScript->pTriggers = pTrigger; } while ( ( c = next_char( pStr ) ) != '{' && c != '\0' ); if ( next_char( pStr ) != '{' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Trigger missing `{' symbol in script.", pNPCIndex->iNumber ); bWarn = TRUE; break; } pStr = edit_str_plus( pStr, cBuf, '{', '}' ); if ( next_char( pStr ) != '}' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "NPC %d: Trigger missing `}' symbol in script.", pNPCIndex->iNumber ); bWarn = TRUE; break; } pStr = remove_char_2( pStr ); pScript->pScript = alloc_mem( ( i = npc_script_translate( pScript, cBuf ) ) ); memcpy( pScript->pScript, cBuf, i ); pScript->iCodeSize = i; pScript->pNext = pProgram->pScripts; pProgram->pScripts = pScript; } else if ( str_compare( cBuf, "USES" ) == TRUE ) { GENERIC_DATA *pGen; QUEST_DATA *pQuestData; char *pBuf2; char c; pStr = edit_str( pStr, cBuf, ' ', ";" ); if ( *pStr != ';' ) { sap_error( "NPC %d: Syntax error in script quest data reference.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } pStr++; pBuf2 = cBuf; do { pBuf2 = edit_str( pBuf2, cBuf2, ' ', ",\n\r\t " ); if ( ( c = next_char( pBuf2 ) ) != ',' && c != '\0' ) { sap_error( "NPC %d: " "Syntax error in script quest data reference.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } else if ( c == ',' ) pBuf2 = remove_char_2( pBuf2 ); for ( pQuestData = pQuestDataList; pQuestData != NULL; pQuestData = pQuestData->pNext ) { if ( strcmp( pQuestData->sName, cBuf2 ) == 0 ) { for ( pGen = pProgram->pQuestDataList; pGen; pGen = pGen->pNext ) { if ( pGen->pData == pQuestData ) break; } if ( pGen != NULL ) { sap_warning( "NPC %d: Multiply referenced quest data.", pNPCIndex->iNumber ); bWarn = TRUE; break; } pGen = alloc_mem( sizeof( *pGen ) ); pGen->pData = pQuestData; pGen->pNext = pProgram->pQuestDataList; pProgram->pQuestDataList = pGen; break; } } } while ( next_char( pBuf2 ) != '\0' ); } else { QUEST_VAR_DATA *pVar; pVar = alloc_mem( sizeof( *pVar ) ); if ( str_compare( cBuf, "number" ) == TRUE ) pVar->iType = NUMBER_VAR_NUMBER; else if ( str_compare( cBuf, "string" ) == TRUE ) pVar->iType = NUMBER_VAR_STRING; else if ( str_compare( cBuf, "character_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_CHAR; else if ( str_compare( cBuf, "object_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_OBJ; else if ( str_compare( cBuf, "room_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_ROOM; else { free_mem( (void **) &pVar ); sap_error( "NPC %d: Unknown keyword `%s' in script.", pNPCIndex->iNumber, cBuf ); bWarn = TRUE; break; } pStr = edit_str( pStr, cBuf, ' ', ";\n\r\t " ); if ( next_char( pStr ) != ';' ) { free_mem( (void **) &pVar ); sap_error( "NPC %d: Syntax error in script variable declaration.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } pStr = remove_char_2( pStr ); if ( cBuf[0] == '\0' || ( !isalpha( cBuf[0] ) && cBuf[0] != '_' ) ) { free_mem( (void **) &pVar ); sap_error( "NPC %d: Illegal name for script variable.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; cBuf[i] != '\0'; i++ ) { if ( !isalnum( cBuf[i] ) && cBuf[i] != '_' ) { free_mem( (void **) &pVar ); sap_error( "NPC %d: Illegal name for script variable.", pNPCIndex->iNumber ); bWarn = TRUE; goto end; } } pVar->sName = save_string( cBuf ); if ( pVar->iType == NUMBER_VAR_STRING ) pVar->uData.s = EMPTY_STRING; pVar->pNext = pProgram->pQuestVars; pProgram->pQuestVars = pVar; } } end: if ( pBak != EMPTY_STRING ) free_mem( (void **) &pBak ); return ( bWarn ); } bool obj_load_inherit( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { pObjIndex->iInherit = fget_number_2( pFile ); if ( pObjIndex->iInherit <= 5 || pObjIndex->iInherit > MAX_INDEX_NUMBER ) sap_fatal( "Object %d: Illegal object number `%d' for inherit.", pObjIndex->iNumber, pObjIndex->iInherit ); return ( FALSE ); } bool obj_load_imagefilename( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { return ( FALSE ); } bool obj_load_names( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { int i; for ( i = 0; pObjIndex->pNameList[i] != NULL; i++ ) free_string( &pObjIndex->pNameList[i] ); free_mem( (void **) &pObjIndex->pNameList ); pObjIndex->pNameList = alloc_mem( ( sizeof( string ) * 2 ) ); pObjIndex->pNameList[0] = save_string( fget_string( pFile ) ); pObjIndex->pNameList[1] = NULL; return ( FALSE ); } bool obj_load_shortdesc( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { free_string( &pObjIndex->sShortDesc ); pObjIndex->sShortDesc = save_string( fget_string( pFile ) ); return ( FALSE ); } bool obj_load_desc( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { free_string( &pObjIndex->sDesc ); pObjIndex->sDesc = save_string( fget_string( pFile ) ); return ( FALSE ); } bool obj_load_longdesc( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pString; char *pBuf; bool bWarn = FALSE; pString = fget_string( pFile ); pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "FORMAT" ) == TRUE ) pString = format_string( pString ); else { sap_warning( "Object %d: Unknown string flag `%s'.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; } } free_string( &pObjIndex->sLongDesc ); pObjIndex->sLongDesc = save_string( pString ); return ( bWarn ); } bool obj_load_itemtype( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char *pBuf = fget_word_2( pFile ); int i; for ( i = 0; snItemTypeTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snItemTypeTable[i].pName, pBuf ) == TRUE ) { pObjIndex->iItemType = snItemTypeTable[i].iNumber; break; } } if ( snItemTypeTable[i].pName[0] == '\0' ) { sap_error( "Object %d: Unknown item type `%s'.", pObjIndex->iNumber, pBuf ); return ( TRUE ); } return ( FALSE ); } bool obj_load_objectflags( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); for ( i = 0; snObjectFlagsTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snObjectFlagsTable[i].pName, cBuf ) == TRUE ) { SET_FLAG( pObjIndex->fObjFlags, snObjectFlagsTable[i].iNumber ); break; } } if ( snObjectFlagsTable[i].pName[0] == '\0' ) { sap_warning( "Object %d: Unknown object flag `%s'.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; } } if ( !IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_CLOSABLE ) && IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_CLOSED ) ) { sap_warning( "Object %d: Closed flag set on non-closable object.", pObjIndex->iNumber ); REMOVE_FLAG( pObjIndex->fObjFlags, FLAG_OBJECT_CLOSED ); bWarn = TRUE; } if ( !IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_CLOSABLE ) && IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_LOCKED ) ) { sap_warning( "Object %d: Locked flag set on non-closable object.", pObjIndex->iNumber ); REMOVE_FLAG( pObjIndex->fObjFlags, FLAG_OBJECT_LOCKED ); bWarn = TRUE; } else if ( !IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_CLOSED ) && IS_SET( pObjIndex->fObjFlags, FLAG_OBJECT_LOCKED ) ) { sap_warning( "Object %d: Locked flag set on non-closed object.", pObjIndex->iNumber ); REMOVE_FLAG( pObjIndex->fObjFlags, FLAG_OBJECT_LOCKED ); bWarn = TRUE; } if ( bWarn == TRUE ) return ( TRUE ); else return ( FALSE ); } bool obj_load_level( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { pObjIndex->iLevel = fget_number_2( pFile ); if ( pObjIndex->iLevel > MAX_PLAYER_LEVEL ) { sap_error( "Object %d: Level greater then %d.", pObjIndex->iNumber, MAX_PLAYER_LEVEL ); pObjIndex->iLevel = MAX_PLAYER_LEVEL; return ( TRUE ); } if ( pObjIndex->iLevel < 1 ) { sap_error( "Object %d: Level less then 1.", pObjIndex->iNumber ); pObjIndex->iLevel = 1; return ( TRUE ); } return ( FALSE ); } bool obj_load_weight( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { pObjIndex->iWeight = fget_number_2( pFile ); if ( pObjIndex->iLevel > 999 ) { sap_error( "Object %d: Weight greater then 999.", pObjIndex->iNumber ); pObjIndex->iWeight = 999; return ( TRUE ); } if ( pObjIndex->iLevel < 0 ) { sap_error( "Object %d: Weight less then 0.", pObjIndex->iNumber ); pObjIndex->iWeight = 1; return ( TRUE ); } return ( FALSE ); } bool obj_load_size( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char *pBuf; int i; pBuf = fget_word_2( pFile ); for ( i = 0; snSizeTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snSizeTable[i].pName, pBuf ) == TRUE ) { pObjIndex->iSize = snSizeTable[i].iNumber; return ( FALSE ); } } sap_warning( "Object %d: Unknown size `%s'.", pObjIndex->iNumber, pBuf ); pObjIndex->iSize = snSizeTable[0].iNumber; return ( TRUE ); } bool obj_load_cost( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { pObjIndex->iCost = fget_number_2( pFile ); return ( FALSE ); } bool obj_load_condition( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { pObjIndex->iCondition = fget_number_2( pFile ); if ( pObjIndex->iCondition > 100 ) { sap_warning( "Object %d: Condition greater then 100.", pObjIndex->iNumber ); pObjIndex->iCondition = 100; return ( TRUE ); } if ( pObjIndex->iCondition < 1 ) { sap_warning( "Object %d: Condition less then 1.", pObjIndex->iNumber ); pObjIndex->iCondition = 1; return ( TRUE ); } return ( FALSE ); } bool obj_load_material( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char *pBuf; int i; pBuf = fget_word_2( pFile ); for ( i = 0; snMaterialTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snMaterialTable[i].pName, pBuf ) == TRUE ) { pObjIndex->iMaterial = snMaterialTable[i].iNumber; return ( FALSE ); } } sap_warning( "Object %d: Unknown material type `%s'.", pObjIndex->iNumber, pBuf ); pObjIndex->iMaterial = snMaterialTable[0].iNumber; return ( TRUE ); } bool obj_load_values( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pBuf; int i = 0; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { if ( i == 6 ) { sap_warning( "Object %d: Too many value settings.", pObjIndex->iNumber ); bWarn = TRUE; break; } pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( is_number( cBuf ) != TRUE ) { sap_warning( "Object %d: Non-number as value[%d] setting.", pObjIndex->iNumber, ++i ); bWarn = TRUE; } else pObjIndex->iValues[i++] = atol( cBuf ); } return ( bWarn ); } bool obj_load_stringvalue( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pString; char *pBuf; bool bWarn = FALSE; pString = fget_string( pFile ); pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "FORMAT" ) == TRUE ) pString = format_string( pString ); else { sap_warning( "Object %d: Unknown string flag `%s'.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; } } free_string( &pObjIndex->sValue ); pObjIndex->sValue = save_string( pString ); return ( bWarn ); } bool obj_load_program( OBJ_INDEX_DATA *pObjIndex, FILE *pFile ) { PROGRAM_DATA *pProgram; SCRIPT_DATA *pScript; TRIGGER_DATA *pTrigger; TRIGGER_ARG_DATA *pTriggerArg; char *pStr = fget_string_3( pFile, '{', '}' ); char *pBak = pStr; char cBuf[MAX_STRING]; char cBuf2[MAX_STRING]; char *pBuf; char c; int i; bool bWarn = FALSE; pProgram = alloc_mem( sizeof( *pProgram ) ); pObjIndex->pProgram = pProgram; while ( next_char( pStr ) != '\0' ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "TRIGGER" ) == TRUE ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); for ( pScript = pProgram->pScripts; pScript != NULL; pScript = pScript->pNext ) { if ( str_compare( pScript->pName, cBuf ) == TRUE ) break; } if ( pScript != NULL ) { sap_error( "Object %d: Multiple blocks with the name " "`%s' in script.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pScript = alloc_mem( sizeof( *pScript ) ); pScript->pName = str_dup( cBuf ); pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "enabled" ) == TRUE ) pScript->bDisabled = FALSE; else if ( str_compare( cBuf, "disabled" ) == TRUE ) pScript->bDisabled = TRUE; else { str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Unknown enabled flag in script.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } do { pStr = edit_str( pStr, cBuf, ' ', "(\n\r\t " ); if ( next_char( pStr ) != '(' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Trigger missing `(' symbol in script.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; snNPCScriptTriggerTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( cBuf, snNPCScriptTriggerTable[i].pName ) == TRUE ) break; } if ( snNPCScriptTriggerTable[i].pName[0] == '\0' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Unknown trigger type `%s' in script.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pTrigger = alloc_mem( sizeof( *pTrigger ) ); pTrigger->iTrigger = snNPCScriptTriggerTable[i].iNumber; pStr = edit_str( pStr, cBuf, '(', ")" ); pBuf = remove_spaces( cBuf ); if ( next_char( pStr ) != ')' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Trigger missing `)' symbol in script.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } switch ( pTrigger->iTrigger ) { case NUMBER_OBJ_TRIGGER_RANDOM: if ( is_number( pBuf ) != TRUE ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_warning( "Object %d: Non-number argument " "for trigger in script.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = alloc_mem( 1 ); *( (intt *) pTriggerArg->pArg ) = (intt) atoi( pBuf ); pTrigger->pArgs = pTriggerArg; break; case NUMBER_OBJ_TRIGGER_SAY : if ( str_compare( pBuf, "all" ) == TRUE ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->iType = 1; pTriggerArg->pArg = EMPTY_STRING; pTrigger->pArgs = pTriggerArg; break; } while ( *pBuf != '\0' ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pBuf = edit_str( pBuf, cBuf2, ' ', "\n\r\t " ); if ( next_char( pBuf ) == '"' ) { if ( str_compare( cBuf2, "exact" ) == TRUE ) pTriggerArg->iType = 2; else if ( str_compare( cBuf2, "prefix" ) == TRUE ) pTriggerArg->iType = 3; else if ( str_compare( cBuf2, "infix" ) == TRUE ) pTriggerArg->iType = 4; else if ( str_compare( cBuf2, "suffix" ) == TRUE ) pTriggerArg->iType = 5; else { sap_warning( "Object %d: Unknown comparison type " "for trigger argument in script.", pObjIndex->iNumber ); bWarn = TRUE; pTriggerArg->iType = 2; continue; } pBuf = make_string( pBuf, cBuf2 ); pBuf = remove_char_2( pBuf ); if ( cBuf2[0] == '\0' ) { sap_warning( "Object %d: Empty string " "for trigger argument in script.", pObjIndex->iNumber ); bWarn = TRUE; pTriggerArg->pArg = EMPTY_STRING; continue; } pTriggerArg->pArg = str_dup( cBuf2 ); } if ( ( c = next_char( pBuf ) ) == ',' ) pBuf = remove_char_2( pBuf ); else if ( c != '\0' ) { sap_warning( "Object %d: Missing `,' for " "trigger argument list in script.", pObjIndex->iNumber ); bWarn = TRUE; } pTriggerArg->pNext = pTrigger->pArgs; pTrigger->pArgs = pTriggerArg; } break; default : pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = str_dup( pBuf ); pTrigger->pArgs = pTriggerArg; break; } pStr = remove_char_2( pStr ); pTrigger->pNext = pScript->pTriggers; pScript->pTriggers = pTrigger; } while ( ( c = next_char( pStr ) ) != '{' && c != '\0' ); if ( next_char( pStr ) != '{' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Trigger missing `{' symbol in script.", pObjIndex->iNumber ); bWarn = TRUE; break; } pStr = edit_str_plus( pStr, cBuf, '{', '}' ); if ( next_char( pStr ) != '}' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Object %d: Trigger missing `}' symbol in script.", pObjIndex->iNumber ); bWarn = TRUE; break; } pStr = remove_char_2( pStr ); pScript->pScript = alloc_mem( ( i = obj_script_translate( pScript, cBuf ) ) ); memcpy( pScript->pScript, cBuf, i ); pScript->iCodeSize = i; pScript->pNext = pProgram->pScripts; pProgram->pScripts = pScript; } else { QUEST_VAR_DATA *pVar; pVar = alloc_mem( sizeof( *pVar ) ); if ( str_compare( cBuf, "number" ) == TRUE ) pVar->iType = NUMBER_VAR_NUMBER; else if ( str_compare( cBuf, "string" ) == TRUE ) pVar->iType = NUMBER_VAR_STRING; else if ( str_compare( cBuf, "character_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_CHAR; else if ( str_compare( cBuf, "object_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_OBJ; else if ( str_compare( cBuf, "room_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_ROOM; else { free_mem( (void **) &pVar ); sap_error( "Object %d: Unknown keyword `%s' in script.", pObjIndex->iNumber, cBuf ); bWarn = TRUE; break; } pStr = edit_str( pStr, cBuf, ' ', ";\n\r\t " ); if ( next_char( pStr ) != ';' ) { free_mem( (void **) &pVar ); sap_error( "Object %d: " "Syntax error in script variable declaration.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } pStr = remove_char_2( pStr ); if ( cBuf[0] == '\0' || ( !isalpha( cBuf[0] ) && cBuf[0] != '_' ) ) { free_mem( (void **) &pVar ); sap_error( "Object %d: Illegal name for script variable.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; cBuf[i] != '\0'; i++ ) { if ( !isalnum( cBuf[i] ) && cBuf[i] != '_' ) { free_mem( (void **) &pVar ); sap_error( "Object %d: Illegal name for script variable.", pObjIndex->iNumber ); bWarn = TRUE; goto end; } } pVar->sName = save_string( cBuf ); if ( pVar->iType == NUMBER_VAR_STRING ) pVar->uData.s = EMPTY_STRING; pVar->pNext = pProgram->pQuestVars; pProgram->pQuestVars = pVar; } } end: if ( pBak != EMPTY_STRING ) free_mem( (void **) &pBak ); return ( bWarn ); } bool room_load_imagefilename( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { char *pBuf = fget_string( pFile ); int i; if ( ( i = get_file_type( pBuf ) ) != FILE_TYPE_GIF && i != FILE_TYPE_JPEG ) { sap_warning( "Room %d: Unknown image file format.", pRoomIndex->iNumber ); return ( TRUE ); } free_string( &pRoomIndex->sImageFilename ); pRoomIndex->sImageFilename = save_string( pBuf ); return ( FALSE ); } bool room_load_title( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { free_string( &pRoomIndex->sTitle ); pRoomIndex->sTitle = save_string( fget_string( pFile ) ); return ( FALSE ); } bool room_load_desc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { char cBuf[MAX_INPUT]; char *pString; char *pBuf; bool bWarn = FALSE; pString = fget_string( pFile ); pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "FORMAT" ) == TRUE ) pString = format_string( pString ); else { sap_warning( "Room %d: Unknown string flag `%s'.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } } free_string( &pRoomIndex->sDesc ); pRoomIndex->sDesc = save_string( pString ); return ( bWarn ); } bool room_load_roomflags( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); for ( i = 0; snRoomFlagsTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snRoomFlagsTable[i].pName, cBuf ) == TRUE ) { SET_FLAG( pRoomIndex->fRoomFlags, snRoomFlagsTable[i].iNumber ); break; } } if ( snRoomFlagsTable[i].pName[0] == '\0' ) { sap_warning( "Room %d: Unknown room flag `%s'.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } } return ( bWarn ); } bool room_load_sector( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { char *pBuf; int i; pBuf = fget_word_2( pFile ); for ( i = 0; snSectorTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( snSectorTable[i].pName, pBuf ) == TRUE ) { pRoomIndex->iSectorType = snSectorTable[i].iNumber; return ( FALSE ); } } sap_warning( "Room %d: Unknown sector type `%s'.", pRoomIndex->iNumber, pBuf ); pRoomIndex->iSectorType = snSectorTable[0].iNumber; return ( TRUE ); } bool room_load_temperature( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { pRoomIndex->iTemperature = fget_number_2( pFile ); if ( pRoomIndex->iTemperature > 1000 ) { sap_warning( "Room %d: Temperature greater then 1000.", pRoomIndex->iNumber ); pRoomIndex->iTemperature = 1000; return ( TRUE ); } if ( pRoomIndex->iTemperature < -1000 ) { sap_warning( "Room %d: Temperature less then -1000.", pRoomIndex->iNumber ); pRoomIndex->iTemperature = -1000; return ( TRUE ); } return ( FALSE ); } static bool load_dir_desc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile, int iDir ) { char cBuf[MAX_INPUT]; char *pString; char *pBuf; bool bWarn = FALSE; pString = fget_string( pFile ); pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "FORMAT" ) == TRUE ) pString = format_string( pString ); else { sap_warning( "Room %d: Unknown string flag `%s'.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } } free_string( &pRoomIndex->sDirDescs[iDir] ); pRoomIndex->sDirDescs[iDir] = save_string( pString ); return ( bWarn ); } bool room_load_northdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 0 ) ); } bool room_load_southdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 1 ) ); } bool room_load_eastdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 2 ) ); } bool room_load_westdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 3 ) ); } bool room_load_updesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 4 ) ); } bool room_load_downdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 5 ) ); } bool room_load_northeastdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 6 ) ); } bool room_load_southwestdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 7 ) ); } bool room_load_northwestdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 8 ) ); } bool room_load_southeastdesc( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_dir_desc( pRoomIndex, pFile, 9 ) ); } static bool load_exit( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile, int iDoor ) { char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pRoomIndex->eExits[iDoor].uRoom.iNumber = fget_number( pFile ); if ( pRoomIndex->eExits[iDoor].uRoom.iNumber <= 5 || pRoomIndex->eExits[iDoor].uRoom.iNumber > MAX_INDEX_NUMBER ) sap_fatal( "Room %d: Illegal room number `%d' in exit.", pRoomIndex->iNumber, pRoomIndex->eExits[iDoor].uRoom.iNumber ); pBuf = fget_word_2( pFile ); if ( str_compare( pBuf, "STANDARD" ) == TRUE ) { pRoomIndex->eExits[iDoor].iExitType = NUMBER_EXIT_STANDARD; return ( FALSE ); } if ( str_compare( pBuf, "SHARED" ) == TRUE ) { pRoomIndex->eExits[iDoor].bShared = TRUE; return ( FALSE ); } else if ( str_compare( pBuf, "DOOR" ) == TRUE ) { pRoomIndex->eExits[iDoor].iExitType = NUMBER_EXIT_DOOR; for ( i = 0; pRoomIndex->eExits[iDoor].pDoorNames[i] != NULL; i++ ) free_string( &pRoomIndex->eExits[iDoor].pDoorNames[i] ); free_mem( (void **) &pRoomIndex->eExits[iDoor].pDoorNames ); pRoomIndex->eExits[iDoor].pDoorNames = alloc_mem( sizeof( string ) * 2 ); pRoomIndex->eExits[iDoor].pDoorNames[0] = save_string( fget_string( pFile ) ); pRoomIndex->eExits[iDoor].pDoorNames[1] = NULL; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( str_compare( cBuf, "CLOSED" ) == TRUE ) SET_FLAG( pRoomIndex->eExits[iDoor].fOrigFlags, FLAG_DOOR_CLOSED ); else if ( str_compare( cBuf, "LOCKED" ) == TRUE ) SET_FLAG( pRoomIndex->eExits[iDoor].fOrigFlags, FLAG_DOOR_LOCKED ); else if ( str_compare( cBuf, "HIDDEN" ) == TRUE ) SET_FLAG( pRoomIndex->eExits[iDoor].fOrigFlags, FLAG_DOOR_HIDDEN ); else if ( str_compare( cBuf, "LEVEL" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "\n\r\t " ); pRoomIndex->eExits[iDoor].iLevel = atoi( cBuf ); if ( pRoomIndex->eExits[iDoor].iLevel < 1 ) { sap_warning( "Room %d: Door level less then 1.", pRoomIndex->iNumber ); pRoomIndex->eExits[iDoor].iLevel = 1; bWarn = TRUE; } if ( pRoomIndex->eExits[iDoor].iLevel > MAX_PLAYER_LEVEL ) { sap_warning( "Room %d: Door level higher then %d.", pRoomIndex->iNumber, MAX_PLAYER_LEVEL ); pRoomIndex->eExits[iDoor].iLevel = MAX_PLAYER_LEVEL; bWarn = TRUE; } } else if ( str_compare( cBuf, "KEY" ) == TRUE ) { pBuf = edit_str( pBuf, cBuf, ' ', "\n\r\t " ); pRoomIndex->eExits[iDoor].uKey.iNumber = atoi( cBuf ); if ( pRoomIndex->eExits[iDoor].uKey.iNumber <= 5 || pRoomIndex->eExits[iDoor].uKey.iNumber > MAX_INDEX_NUMBER ) sap_fatal( "Room %d: Illegal object number `%d' for door key.", pRoomIndex->iNumber, pRoomIndex->eExits[iDoor].uKey.iNumber ); } else { sap_warning( "Room %d: Unknown door flag `%s'.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } } pRoomIndex->eExits[iDoor].iResetTime = fget_number_2( pFile ); } else { sap_warning( "Room %d: Unknown exit type `%s'.", pRoomIndex->iNumber, pBuf ); return ( TRUE ); } pRoomIndex->eExits[iDoor].fCurrFlags = pRoomIndex->eExits[iDoor].fOrigFlags; return ( bWarn ); } bool room_load_exitnorth( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 0 ) ); } bool room_load_exitsouth( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 1 ) ); } bool room_load_exiteast( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 2 ) ); } bool room_load_exitwest( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 3 ) ); } bool room_load_exitup( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 4 ) ); } bool room_load_exitdown( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 5 ) ); } bool room_load_exitnortheast( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 6 ) ); } bool room_load_exitsouthwest( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 7 ) ); } bool room_load_exitnorthwest( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 8 ) ); } bool room_load_exitsoutheast( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { return ( load_exit( pRoomIndex, pFile, 9 ) ); } static int get_obj_reset_list( char **ppSrc, OBJ_RESET_DATA **ppList ) { OBJ_RESET_DATA *pReset; char *pBuf = new_buffer( ); char *pSrc = *ppSrc; char cBuf[MAX_STRING]; int i; if ( next_char( pSrc ) != '[' ) return ( -1 ); pSrc = edit_str_plus( pSrc, pBuf, '[', ']' ); if ( next_char( pSrc ) != ']' ) return ( -2 ); *ppSrc = remove_char_2( pSrc ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', "[\n\r\t " ); if ( is_number( cBuf ) != TRUE ) return ( -3 ); i = atoi( cBuf ); if ( i <= 5 || i > MAX_INDEX_NUMBER ) return ( -4 ); pReset = alloc_mem( sizeof( *pReset ) ); pReset->u1.iNumber = i; if ( ( i = get_obj_reset_list( &pBuf, &pReset->pContentResets ) ) < 0 ) return ( i ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); pReset->pNext = *ppList; *ppList = pReset; } return ( 0 ); } bool room_load_npcs( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { /* FILE *pFile2; */ NPC_RESET_DATA *pNewReset; char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', "[\n\r\t " ); pNewReset = alloc_mem( sizeof( *pNewReset ) ); if ( is_number( cBuf ) == FALSE ) { sap_fatal( "Room %d: Non-number `%s' for NPC number.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } else pNewReset->u1.iNumber = atoi( cBuf ); if ( pNewReset->u1.iNumber <= 5 || pNewReset->u1.iNumber > MAX_INDEX_NUMBER ) { sap_fatal( "Room %d: Illegal NPC number `%d' for reset.", pRoomIndex->iNumber, pNewReset->u1.iNumber ); bWarn = TRUE; } if ( ( i = get_obj_reset_list( &pBuf, &pNewReset->pInvenResets ) ) < 0 ) { sap_error( "Room %d: Error %d.", pRoomIndex->iNumber, i ); bWarn = TRUE; } if ( ( i = get_obj_reset_list( &pBuf, &pNewReset->pEqResets ) ) < 0 ) { sap_error( "Room %d: Error %d.", pRoomIndex->iNumber, i ); bWarn = TRUE; } pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( is_number( cBuf ) == FALSE ) { sap_error( "Room %d: Non-number `%s' for NPC reset time.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } else pNewReset->iResetTime = atoi( cBuf ); pNewReset->pNext = pRoomIndex->pNPCResets; pRoomIndex->pNPCResets = pNewReset; } return ( bWarn ); } bool room_load_objects( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { /* FILE *pFile2; */ OBJ_RESET_DATA *pNewReset; char cBuf[MAX_STRING]; char *pBuf; int i; bool bWarn = FALSE; pBuf = fget_string_2( pFile, '[', ']' ); while ( next_char( pBuf ) != '\0' ) { pBuf = edit_str( pBuf, cBuf, ' ', "[\n\r\t " ); pNewReset = alloc_mem( sizeof( *pNewReset ) ); if ( is_number( cBuf ) == FALSE ) { sap_fatal( "Room %d: Non-number `%s' for object number.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } else pNewReset->u1.iNumber = atoi( cBuf ); if ( pNewReset->u1.iNumber <= 5 || pNewReset->u1.iNumber > MAX_INDEX_NUMBER ) { sap_fatal( "Room %d: Illegal object number `%d' for reset.", pRoomIndex->iNumber, pNewReset->u1.iNumber ); bWarn = TRUE; } if ( ( i = get_obj_reset_list( &pBuf, &pNewReset->pContentResets ) ) < 0 ) { sap_error( "Room %d: Error %d.", pRoomIndex->iNumber, i ); bWarn = TRUE; } pBuf = edit_str( pBuf, cBuf, ' ', ",\n\r\t " ); if ( next_char( pBuf ) == ',' ) pBuf = remove_char_2( pBuf ); if ( is_number( cBuf ) == FALSE ) { sap_error( "Room %d: Non-number `%s' for object reset time.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; } else pNewReset->iResetTime = atoi( cBuf ); pNewReset->pNext = pRoomIndex->pObjResets; pRoomIndex->pObjResets = pNewReset; } return ( bWarn ); } bool room_load_program( ROOM_INDEX_DATA *pRoomIndex, FILE *pFile ) { PROGRAM_DATA *pProgram; SCRIPT_DATA *pScript; TRIGGER_DATA *pTrigger; TRIGGER_ARG_DATA *pTriggerArg; char *pStr = fget_string_3( pFile, '{', '}' ); char *pBak = pStr; char cBuf[MAX_STRING]; char cBuf2[MAX_STRING]; char *pBuf; char c; int i; bool bWarn = FALSE; pProgram = alloc_mem( sizeof( *pProgram ) ); pRoomIndex->pProgram = pProgram; while ( next_char( pStr ) != '\0' ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "TRIGGER" ) == TRUE ) { pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); for ( pScript = pProgram->pScripts; pScript != NULL; pScript = pScript->pNext ) { if ( str_compare( pScript->pName, cBuf ) == TRUE ) break; } if ( pScript != NULL ) { sap_error( "Room %d: Multiple blocks with the name `%s' in script.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pScript = alloc_mem( sizeof( *pScript ) ); pScript->pName = str_dup( cBuf ); pStr = edit_str( pStr, cBuf, ' ', "\n\r\t " ); if ( str_compare( cBuf, "enabled" ) == TRUE ) pScript->bDisabled = FALSE; else if ( str_compare( cBuf, "disabled" ) == TRUE ) pScript->bDisabled = TRUE; else { str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Unknown enabled flag in script.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } do { pStr = edit_str( pStr, cBuf, ' ', "(\n\r\t " ); if ( next_char( pStr ) != '(' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Trigger missing `(' symbol in script.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; snRoomScriptTriggerTable[i].pName[0] != '\0'; i++ ) { if ( str_compare( cBuf, snRoomScriptTriggerTable[i].pName ) == TRUE ) break; } if ( snRoomScriptTriggerTable[i].pName[0] == '\0' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Unknown trigger type `%s' in script.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; goto end; } pTrigger = alloc_mem( sizeof( *pTrigger ) ); pTrigger->iTrigger = snRoomScriptTriggerTable[i].iNumber; pStr = edit_str( pStr, cBuf, '(', ")" ); pBuf = remove_spaces( cBuf ); if ( next_char( pStr ) != ')' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Trigger missing `)' symbol in script.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } switch ( pTrigger->iTrigger ) { case NUMBER_ROOM_TRIGGER_RANDOM : if ( is_number( pBuf ) != TRUE ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; free_mem( (void **) &pTrigger ); for ( pTrigger = pScript->pTriggers; pTrigger; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_warning( "Room %d: Non-number argument for " "trigger in script.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = alloc_mem( 1 ); *( (intt *) pTriggerArg->pArg ) = (intt) atoi( pBuf ); pTrigger->pArgs = pTriggerArg; break; case NUMBER_ROOM_TRIGGER_MESSAGE: case NUMBER_ROOM_TRIGGER_EMOTE : case NUMBER_ROOM_TRIGGER_SAY : case NUMBER_ROOM_TRIGGER_YELL : if ( str_compare( pBuf, "all" ) == TRUE ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->iType = 1; pTriggerArg->pArg = EMPTY_STRING; pTrigger->pArgs = pTriggerArg; break; } while ( *pBuf != '\0' ) { pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pBuf = edit_str( pBuf, cBuf2, ' ', "\n\r\t " ); if ( next_char( pBuf ) == '"' ) { if ( str_compare( cBuf2, "exact" ) == TRUE ) pTriggerArg->iType = 2; else if ( str_compare( cBuf2, "prefix" ) == TRUE ) pTriggerArg->iType = 3; else if ( str_compare( cBuf2, "infix" ) == TRUE ) pTriggerArg->iType = 4; else if ( str_compare( cBuf2, "suffix" ) == TRUE ) pTriggerArg->iType = 5; else { sap_warning( "Room %d: Unknown " "comparison type for trigger argument " "in script.", pRoomIndex->iNumber ); bWarn = TRUE; pTriggerArg->iType = 2; continue; } pBuf = make_string( pBuf, cBuf2 ); pBuf = remove_char_2( pBuf ); if ( cBuf2[0] == '\0' ) { sap_warning( "Room %d: Empty string for " "trigger argument in script.", pRoomIndex->iNumber ); bWarn = TRUE; pTriggerArg->pArg = EMPTY_STRING; continue; } pTriggerArg->pArg = str_dup( cBuf2 ); } if ( ( c = next_char( pBuf ) ) == ',' ) pBuf = remove_char_2( pBuf ); else if ( c != '\0' ) { sap_warning( "Room %d: Missing `,' for " "trigger argument list in script.", pRoomIndex->iNumber ); bWarn = TRUE; } pTriggerArg->pNext = pTrigger->pArgs; pTrigger->pArgs = pTriggerArg; } break; default : pTriggerArg = alloc_mem( sizeof( *pTriggerArg ) ); pTriggerArg->pArg = str_dup( pBuf ); pTrigger->pArgs = pTriggerArg; break; } pStr = remove_char_2( pStr ); pTrigger->pNext = pScript->pTriggers; pScript->pTriggers = pTrigger; } while ( ( c = next_char( pStr ) ) != '{' && c != '\0' ); if ( next_char( pStr ) != '{' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Trigger missing `{' symbol in script.", pRoomIndex->iNumber ); bWarn = TRUE; break; } pStr = edit_str_plus( pStr, cBuf, '{', '}' ); if ( next_char( pStr ) != '}' ) { TRIGGER_DATA *pTriggerNext; TRIGGER_ARG_DATA *pTriggerArgNext; for ( pTrigger = pScript->pTriggers; pTrigger != NULL; pTrigger = pTriggerNext ) { pTriggerNext = pTrigger->pNext; for ( pTriggerArg = pTrigger->pArgs; pTriggerArg; pTriggerArg = pTriggerArgNext ) { pTriggerArgNext = pTriggerArg->pNext; str_free( pTriggerArg->pArg ); free_mem( (void **) &pTriggerArg ); } free_mem( (void **) &pTrigger ); } str_free( pScript->pName ); free_mem( (void **) &pScript ); sap_error( "Room %d: Trigger missing `}' symbol in script.", pRoomIndex->iNumber ); bWarn = TRUE; break; } pStr = remove_char_2( pStr ); pScript->pScript = alloc_mem( ( i = room_script_translate( pScript, cBuf ) ) ); memcpy( pScript->pScript, cBuf, i ); pScript->iCodeSize = i; pScript->pNext = pProgram->pScripts; pProgram->pScripts = pScript; } else if ( str_compare( cBuf, "USES" ) == TRUE ) { GENERIC_DATA *pGen; QUEST_DATA *pQuestData; char *pBuf2; char c; pStr = edit_str( pStr, cBuf, ' ', ";" ); if ( *pStr != ';' ) { sap_error( "Room %d: Syntax error in script quest data reference.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } pStr++; pBuf2 = cBuf; do { pBuf2 = edit_str( pBuf2, cBuf2, ' ', ",\n\r\t " ); if ( ( c = next_char( pBuf2 ) ) != ',' && c != '\0' ) { sap_error( "Room %d: " "Syntax error in script quest data reference.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } else if ( c == ',' ) pBuf2 = remove_char_2( pBuf2 ); for ( pQuestData = pQuestDataList; pQuestData != NULL; pQuestData = pQuestData->pNext ) { if ( strcmp( pQuestData->sName, cBuf2 ) == 0 ) { for ( pGen = pProgram->pQuestDataList; pGen; pGen = pGen->pNext ) { if ( pGen->pData == pQuestData ) break; } if ( pGen != NULL ) { sap_warning( "Room %d: Multiply referenced quest data.", pRoomIndex->iNumber ); bWarn = TRUE; break; } pGen = alloc_mem( sizeof( *pGen ) ); pGen->pData = pQuestData; pGen->pNext = pProgram->pQuestDataList; pProgram->pQuestDataList = pGen; break; } } } while ( next_char( pBuf2 ) != '\0' ); } else { QUEST_VAR_DATA *pVar; pVar = alloc_mem( sizeof( *pVar ) ); if ( str_compare( cBuf, "number" ) == TRUE ) pVar->iType = NUMBER_VAR_NUMBER; else if ( str_compare( cBuf, "string" ) == TRUE ) pVar->iType = NUMBER_VAR_STRING; else if ( str_compare( cBuf, "character_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_CHAR; else if ( str_compare( cBuf, "object_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_OBJ; else if ( str_compare( cBuf, "room_pointer" ) == TRUE ) pVar->iType = NUMBER_VAR_POINTER_ROOM; else { free_mem( (void **) &pVar ); sap_error( "Room %d: Unknown keyword `%s' in script.", pRoomIndex->iNumber, cBuf ); bWarn = TRUE; break; } pStr = edit_str( pStr, cBuf, ' ', ";\n\r\t " ); if ( next_char( pStr ) != ';' ) { free_mem( (void **) &pVar ); sap_error( "Room %d: Syntax error in script variable declaration.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } pStr = remove_char_2( pStr ); if ( cBuf[0] == '\0' || ( !isalpha( cBuf[0] ) && cBuf[0] != '_' ) ) { free_mem( (void **) &pVar ); sap_error( "Room %d: Illegal name for script variable.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } for ( i = 0; cBuf[i] != '\0'; i++ ) { if ( !isalnum( cBuf[i] ) && cBuf[i] != '_' ) { free_mem( (void **) &pVar ); sap_error( "Room %d: Illegal name for script variable.", pRoomIndex->iNumber ); bWarn = TRUE; goto end; } } pVar->sName = save_string( cBuf ); if ( pVar->iType == NUMBER_VAR_STRING ) pVar->uData.s = EMPTY_STRING; pVar->pNext = pProgram->pQuestVars; pProgram->pQuestVars = pVar; } } end: if ( pBak != EMPTY_STRING ) free_mem( (void **) &pBak ); return ( bWarn ); } /* * End of load.c */